319 lines
11 KiB
PHP
319 lines
11 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace App\Tests\Service;
|
||
|
||
use App\BusProNet\Model\Room;
|
||
use App\BusProNet\Model\Service;
|
||
use App\BusProNet\Model\Travel;
|
||
use App\Form\Model\BookingCreateDto;
|
||
use App\Form\Model\ParticipantDto;
|
||
use App\Form\Model\RoomSelectionDto;
|
||
use App\Service\BookingPriceCalculatorService;
|
||
use PHPUnit\Framework\TestCase;
|
||
|
||
class BookingPriceCalculatorServiceTest extends TestCase
|
||
{
|
||
private BookingPriceCalculatorService $service;
|
||
|
||
protected function setUp(): void
|
||
{
|
||
$this->service = new BookingPriceCalculatorService();
|
||
}
|
||
|
||
public function testCalculateRoomPricingWithParticipantBasedCalculation(): void
|
||
{
|
||
// Create test data: 2 double rooms at €100 each, minPax=2
|
||
$room = new Room();
|
||
$room->id = 1;
|
||
$room->price = 100.0;
|
||
$room->minPax = 2;
|
||
$room->label = 'Double Room';
|
||
|
||
$travel = new Travel();
|
||
$travel->rooms = [$room];
|
||
|
||
$roomSelection = new RoomSelectionDto();
|
||
$roomSelection->roomId = 1;
|
||
$roomSelection->quantity = 2; // 2 rooms selected
|
||
|
||
$bookingDto = new BookingCreateDto($travel, 1);
|
||
$bookingDto->roomSelections = [$roomSelection];
|
||
|
||
// Test the calculation
|
||
$result = $this->service->calculateRoomPricing($bookingDto);
|
||
|
||
// Expected: 2 rooms × 2 participants/room × €100 = €400 total
|
||
$this->assertCount(1, $result);
|
||
$this->assertEquals(1, $result[0]['roomId']);
|
||
$this->assertEquals('Double Room', $result[0]['label']);
|
||
$this->assertEquals(2, $result[0]['quantity']); // 2 rooms
|
||
$this->assertEquals(4, $result[0]['participantCount']); // 4 participants total
|
||
$this->assertEquals(100.0, $result[0]['unitPrice']); // €100 per participant
|
||
$this->assertEquals(400.0, $result[0]['totalPrice']); // €400 total
|
||
}
|
||
|
||
public function testCalculateRoomPricingWithSingleRoomSelection(): void
|
||
{
|
||
// Create test data: 1 triple room at €150, minPax=3
|
||
$room = new Room();
|
||
$room->id = 2;
|
||
$room->price = 150.0;
|
||
$room->minPax = 3;
|
||
$room->label = 'Triple Room';
|
||
|
||
$travel = new Travel();
|
||
$travel->rooms = [$room];
|
||
|
||
$roomSelection = new RoomSelectionDto();
|
||
$roomSelection->roomId = 2;
|
||
$roomSelection->quantity = 1; // 1 room selected
|
||
|
||
$bookingDto = new BookingCreateDto($travel, 1);
|
||
$bookingDto->roomSelections = [$roomSelection];
|
||
|
||
// Test the calculation
|
||
$result = $this->service->calculateRoomPricing($bookingDto);
|
||
|
||
// Expected: 1 room × 3 participants/room × €150 = €450 total
|
||
$this->assertCount(1, $result);
|
||
$this->assertEquals(2, $result[0]['roomId']);
|
||
$this->assertEquals('Triple Room', $result[0]['label']);
|
||
$this->assertEquals(1, $result[0]['quantity']); // 1 room
|
||
$this->assertEquals(3, $result[0]['participantCount']); // 3 participants total
|
||
$this->assertEquals(150.0, $result[0]['unitPrice']); // €150 per participant
|
||
$this->assertEquals(450.0, $result[0]['totalPrice']); // €450 total
|
||
}
|
||
|
||
public function testCalculateRoomPricingWithMultipleRoomTypes(): void
|
||
{
|
||
// Create test data: Multiple room types
|
||
$singleRoom = new Room();
|
||
$singleRoom->id = 1;
|
||
$singleRoom->price = 80.0;
|
||
$singleRoom->minPax = 1;
|
||
$singleRoom->label = 'Single Room';
|
||
|
||
$doubleRoom = new Room();
|
||
$doubleRoom->id = 2;
|
||
$doubleRoom->price = 120.0;
|
||
$doubleRoom->minPax = 2;
|
||
$doubleRoom->label = 'Double Room';
|
||
|
||
$travel = new Travel();
|
||
$travel->rooms = [$singleRoom, $doubleRoom];
|
||
|
||
$singleRoomSelection = new RoomSelectionDto();
|
||
$singleRoomSelection->roomId = 1;
|
||
$singleRoomSelection->quantity = 1; // 1 single room
|
||
|
||
$doubleRoomSelection = new RoomSelectionDto();
|
||
$doubleRoomSelection->roomId = 2;
|
||
$doubleRoomSelection->quantity = 2; // 2 double rooms
|
||
|
||
$bookingDto = new BookingCreateDto($travel, 1);
|
||
$bookingDto->roomSelections = [$singleRoomSelection, $doubleRoomSelection];
|
||
|
||
// Test the calculation
|
||
$result = $this->service->calculateRoomPricing($bookingDto);
|
||
|
||
// Expected:
|
||
// - Single: 1 room × 1 participant × €80 = €80
|
||
// - Double: 2 rooms × 2 participants × €120 = €480
|
||
$this->assertCount(2, $result);
|
||
|
||
// Single room result
|
||
$singleResult = $result[0];
|
||
$this->assertEquals(1, $singleResult['roomId']);
|
||
$this->assertEquals(1, $singleResult['quantity']);
|
||
$this->assertEquals(1, $singleResult['participantCount']);
|
||
$this->assertEquals(80.0, $singleResult['unitPrice']);
|
||
$this->assertEquals(80.0, $singleResult['totalPrice']);
|
||
|
||
// Double room result
|
||
$doubleResult = $result[1];
|
||
$this->assertEquals(2, $doubleResult['roomId']);
|
||
$this->assertEquals(2, $doubleResult['quantity']);
|
||
$this->assertEquals(4, $doubleResult['participantCount']);
|
||
$this->assertEquals(120.0, $doubleResult['unitPrice']);
|
||
$this->assertEquals(480.0, $doubleResult['totalPrice']);
|
||
}
|
||
|
||
public function testCalculateRoomPricingSkipsRoomsWithNullPrice(): void
|
||
{
|
||
$room = new Room();
|
||
$room->id = 1;
|
||
$room->price = null; // No price set
|
||
$room->minPax = 2;
|
||
$room->label = 'Free Room';
|
||
|
||
$travel = new Travel();
|
||
$travel->rooms = [$room];
|
||
|
||
$roomSelection = new RoomSelectionDto();
|
||
$roomSelection->roomId = 1;
|
||
$roomSelection->quantity = 1;
|
||
|
||
$bookingDto = new BookingCreateDto($travel, 1);
|
||
$bookingDto->roomSelections = [$roomSelection];
|
||
|
||
$result = $this->service->calculateRoomPricing($bookingDto);
|
||
|
||
// Should skip rooms with null price
|
||
$this->assertEmpty($result);
|
||
}
|
||
|
||
public function testCalculateRoomPricingWithZeroQuantityRooms(): void
|
||
{
|
||
$room = new Room();
|
||
$room->id = 1;
|
||
$room->price = 100.0;
|
||
$room->minPax = 2;
|
||
$room->label = 'Double Room';
|
||
|
||
$travel = new Travel();
|
||
$travel->rooms = [$room];
|
||
|
||
$roomSelection = new RoomSelectionDto();
|
||
$roomSelection->roomId = 1;
|
||
$roomSelection->quantity = 0; // Zero quantity - not selected
|
||
|
||
$bookingDto = new BookingCreateDto($travel, 1);
|
||
$bookingDto->roomSelections = [$roomSelection];
|
||
|
||
$result = $this->service->calculateRoomPricing($bookingDto);
|
||
|
||
// Should skip rooms with zero quantity
|
||
$this->assertEmpty($result);
|
||
}
|
||
|
||
public function testCalculateIndividualParticipantPriceWithRoomAndServices(): void
|
||
{
|
||
// Create test room
|
||
$room = new Room();
|
||
$room->id = 1;
|
||
$room->price = 100.0;
|
||
$room->minPax = 2;
|
||
|
||
$travel = new Travel();
|
||
$travel->rooms = [$room];
|
||
|
||
// Create test services
|
||
$skiPass = new Service();
|
||
$skiPass->price = 50.0;
|
||
|
||
$course = new Service();
|
||
$course->price = 30.0;
|
||
|
||
// Create participant with room assignment and services
|
||
$participant = new ParticipantDto();
|
||
$participant->assignedRoomId = 1;
|
||
$participant->skiPass = $skiPass;
|
||
$participant->courses = [$course];
|
||
|
||
$bookingDto = new BookingCreateDto($travel, 1);
|
||
$bookingDto->participants = [$participant];
|
||
|
||
$result = $this->service->calculateIndividualParticipantPrice($bookingDto, 0);
|
||
|
||
// Expected: €100 (room) + €50 (ski pass) + €30 (course) = €180
|
||
$this->assertEquals(180.0, $result);
|
||
}
|
||
|
||
public function testCalculateIndividualParticipantPriceWithoutRoomAssignment(): void
|
||
{
|
||
$travel = new Travel();
|
||
|
||
// Create test services
|
||
$skiPass = new Service();
|
||
$skiPass->price = 50.0;
|
||
|
||
// Create participant without room assignment
|
||
$participant = new ParticipantDto();
|
||
$participant->assignedRoomId = null; // No room assigned
|
||
$participant->skiPass = $skiPass;
|
||
|
||
$bookingDto = new BookingCreateDto($travel, 1);
|
||
$bookingDto->participants = [$participant];
|
||
|
||
$result = $this->service->calculateIndividualParticipantPrice($bookingDto, 0);
|
||
|
||
// Expected: €0 (no room) + €50 (ski pass) = €50
|
||
$this->assertEquals(50.0, $result);
|
||
}
|
||
|
||
public function testCalculateIndividualParticipantPriceForNonExistentParticipant(): void
|
||
{
|
||
$travel = new Travel();
|
||
$bookingDto = new BookingCreateDto($travel, 1);
|
||
$bookingDto->participants = [];
|
||
|
||
$result = $this->service->calculateIndividualParticipantPrice($bookingDto, 0);
|
||
|
||
// Expected: €0 for non-existent participant
|
||
$this->assertEquals(0.0, $result);
|
||
}
|
||
|
||
public function testCalculateAllParticipantIndividualPricesWithMultipleParticipants(): void
|
||
{
|
||
// Create test rooms
|
||
$singleRoom = new Room();
|
||
$singleRoom->id = 1;
|
||
$singleRoom->price = 80.0;
|
||
$singleRoom->minPax = 1;
|
||
|
||
$doubleRoom = new Room();
|
||
$doubleRoom->id = 2;
|
||
$doubleRoom->price = 120.0;
|
||
$doubleRoom->minPax = 2;
|
||
|
||
$travel = new Travel();
|
||
$travel->rooms = [$singleRoom, $doubleRoom];
|
||
|
||
// Create test services
|
||
$skiPass = new Service();
|
||
$skiPass->price = 50.0;
|
||
|
||
$course = new Service();
|
||
$course->price = 30.0;
|
||
|
||
// Create participants
|
||
$participant1 = new ParticipantDto();
|
||
$participant1->assignedRoomId = 1; // Single room
|
||
$participant1->skiPass = $skiPass;
|
||
|
||
$participant2 = new ParticipantDto();
|
||
$participant2->assignedRoomId = 2; // Double room
|
||
$participant2->courses = [$course];
|
||
|
||
$participant3 = new ParticipantDto();
|
||
$participant3->assignedRoomId = null; // No room assigned
|
||
|
||
$bookingDto = new BookingCreateDto($travel, 1);
|
||
$bookingDto->participants = [$participant1, $participant2, $participant3];
|
||
|
||
$result = $this->service->calculateAllParticipantIndividualPrices($bookingDto);
|
||
|
||
// Expected results:
|
||
// Participant 0: €80 (single room) + €50 (ski pass) = €130
|
||
// Participant 1: €120 (double room) + €30 (course) = €150
|
||
// Participant 2: €0 (no room) + €0 (no services) = €0
|
||
$this->assertCount(3, $result);
|
||
$this->assertEquals(130.0, $result[0]);
|
||
$this->assertEquals(150.0, $result[1]);
|
||
$this->assertEquals(0.0, $result[2]);
|
||
}
|
||
|
||
public function testCalculateAllParticipantIndividualPricesWithEmptyBooking(): void
|
||
{
|
||
$travel = new Travel();
|
||
$bookingDto = new BookingCreateDto($travel, 1);
|
||
$bookingDto->participants = [];
|
||
|
||
$result = $this->service->calculateAllParticipantIndividualPrices($bookingDto);
|
||
|
||
$this->assertEmpty($result);
|
||
}
|
||
}
|