calculator = new RoomPricingCalculator(); } public function testCalculateRoomPricingWithParticipantBasedCalculation(): 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->id = 1; $roomSelection->quantity = 2; $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [$roomSelection]; $bookingDto->participants = [ $this->participantInRoom(1), $this->participantInRoom(1), $this->participantInRoom(1), $this->participantInRoom(1), ]; $result = $this->calculator->calculateRoomPricing($bookingDto); // 4 assigned participants × €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']); $this->assertEquals(4, $result[0]['participantCount']); $this->assertEquals(100.0, $result[0]['unitPrice']); $this->assertEquals(400.0, $result[0]['totalPrice']); } public function testCalculateRoomPricingWithSingleRoomSelection(): void { $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->id = 2; $roomSelection->quantity = 1; $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [$roomSelection]; $bookingDto->participants = [ $this->participantInRoom(2), $this->participantInRoom(2), ]; $result = $this->calculator->calculateRoomPricing($bookingDto); // 2 assigned participants × €150 = €300 total $this->assertCount(1, $result); $this->assertEquals(2, $result[0]['roomId']); $this->assertEquals('Triple Room', $result[0]['label']); $this->assertEquals(1, $result[0]['quantity']); $this->assertEquals(2, $result[0]['participantCount']); $this->assertEquals(150.0, $result[0]['unitPrice']); $this->assertEquals(300.0, $result[0]['totalPrice']); } public function testCalculateRoomPricingWithMultipleRoomTypes(): void { $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->id = 1; $singleRoomSelection->quantity = 1; $doubleRoomSelection = new RoomSelectionDto(); $doubleRoomSelection->id = 2; $doubleRoomSelection->quantity = 2; $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [$singleRoomSelection, $doubleRoomSelection]; $bookingDto->participants = [ $this->participantInRoom(1), $this->participantInRoom(2), $this->participantInRoom(2), $this->participantInRoom(2), ]; $result = $this->calculator->calculateRoomPricing($bookingDto); // Single: 1 participant × €80 = €80 // Double: 3 participants × €120 = €360 $this->assertCount(2, $result); $this->assertEquals(1, $result[0]['roomId']); $this->assertEquals(1, $result[0]['quantity']); $this->assertEquals(1, $result[0]['participantCount']); $this->assertEquals(80.0, $result[0]['unitPrice']); $this->assertEquals(80.0, $result[0]['totalPrice']); $this->assertEquals(2, $result[1]['roomId']); $this->assertEquals(2, $result[1]['quantity']); $this->assertEquals(3, $result[1]['participantCount']); $this->assertEquals(120.0, $result[1]['unitPrice']); $this->assertEquals(360.0, $result[1]['totalPrice']); } public function testCalculateRoomPricingSkipsRoomsWithNullPrice(): void { $room = new Room(); $room->id = 1; $room->price = null; $room->minPax = 2; $room->label = 'Free Room'; $travel = new Travel(); $travel->rooms = [$room]; $roomSelection = new RoomSelectionDto(); $roomSelection->id = 1; $roomSelection->quantity = 1; $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [$roomSelection]; $result = $this->calculator->calculateRoomPricing($bookingDto); $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->id = 1; $roomSelection->quantity = 0; $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [$roomSelection]; $result = $this->calculator->calculateRoomPricing($bookingDto); $this->assertEmpty($result); } public function testCalculateRoomPricingShowsSelectedRoomWithZeroAssignments(): void { $room = new Room(); $room->id = 1; $room->price = 100.0; $room->label = 'Double Room'; $travel = new Travel(); $travel->rooms = [$room]; $roomSelection = new RoomSelectionDto(); $roomSelection->id = 1; $roomSelection->quantity = 1; $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [$roomSelection]; $bookingDto->participants = []; $result = $this->calculator->calculateRoomPricing($bookingDto); $this->assertCount(1, $result); $this->assertEquals(1, $result[0]['roomId']); $this->assertEquals(1, $result[0]['quantity']); $this->assertEquals(0, $result[0]['participantCount']); $this->assertEquals(0.0, $result[0]['totalPrice']); } public function testCalculateRoomPricingUsesSelectionModeForStepOneSummary(): void { $room = new Room(); $room->id = 3; $room->price = 229.0; $room->minPax = 2; $room->label = 'Doppelzimmer Dusche/WC'; $travel = new Travel(); $travel->rooms = [$room]; $roomSelection = new RoomSelectionDto(); $roomSelection->id = 3; $roomSelection->quantity = 1; $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [$roomSelection]; $bookingDto->participants = [ $this->participantInRoom(3), $this->participantInRoom(3), ]; $result = $this->calculator->calculateRoomPricing($bookingDto, RoomPricingCalculator::PRICING_MODE_SELECTION); $this->assertCount(1, $result); $this->assertEquals(2, $result[0]['participantCount']); $this->assertEquals(458.0, $result[0]['totalPrice']); } public function testCalculateRoomPricingFallsBackToOneParticipantWhenOccupancyIsUnknown(): void { $room = new Room(); $room->id = 4; $room->price = 419.0; $room->minPax = null; $room->label = 'Bett im Mehrbettzimmer'; $travel = new Travel(); $travel->rooms = [$room]; $roomSelection = new RoomSelectionDto(); $roomSelection->id = 4; $roomSelection->quantity = 2; $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [$roomSelection]; $result = $this->calculator->calculateRoomPricing($bookingDto, RoomPricingCalculator::PRICING_MODE_SELECTION); $this->assertCount(1, $result); $this->assertEquals(2, $result[0]['participantCount']); $this->assertEquals(838.0, $result[0]['totalPrice']); } public function testCalculateRoomPricingInEditModeUsesStoredIndividualPrices(): void { $travel = new Travel(); $bookingDto = new BookingDto($travel, 2); $participantA = new ParticipantDto(); $participantA->assignedRoomId = 10; $participantB = new ParticipantDto(); $participantB->assignedRoomId = 10; $bookingDto->participants = [$participantA, $participantB]; $booking = new Booking(); $room = new Room(); $room->id = 10; $room->label = 'Stored Room'; $room->mapping = [0, 1]; $room->individualPrice = [0 => 200.0, 1 => 220.0]; $room->totalCount = 1; $booking->rooms = [$room]; $bookingDto->booking = $booking; $result = $this->calculator->calculateRoomPricing($bookingDto); $this->assertCount(1, $result); $this->assertEquals(10, $result[0]['roomId']); $this->assertEquals(2, $result[0]['participantCount']); $this->assertEquals(210.0, $result[0]['unitPrice']); $this->assertEquals(420.0, $result[0]['totalPrice']); } private function participantInRoom(int $roomId): ParticipantDto { $participant = new ParticipantDto(); $participant->assignedRoomId = $roomId; return $participant; } }