createTravel([ $this->createRoom(1408, 'Doppelzimmer', available: 4, minPax: 2), $this->createRoom(1409, 'Einzelzimmer', available: 2, minPax: 1), ]); $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [ 1408 => $this->createRoomSelection(1408, quantity: 2), 1409 => $this->createRoomSelection(1409, quantity: 0), ]; $adjustments = $this->bookingService()->reconcileRoomSelections($bookingDto); $this->assertSame([], $adjustments); $this->assertSame([1408, 1409], array_keys($bookingDto->roomSelections)); $this->assertSame(2, $bookingDto->roomSelections[1408]->quantity); $this->assertSame(0, $bookingDto->roomSelections[1409]->quantity); $this->assertSame(2, $bookingDto->roomSelections[1408]->capacity); $this->assertSame(4, $bookingDto->roomSelections[1408]->maxQuantity); } public function testReportsAndRemovesASelectedRoomThatIsNoLongerBookable(): void { $travel = $this->createTravel([ $this->createRoom(1408, 'Doppelzimmer', available: 0, minPax: 2), $this->createRoom(1409, 'Einzelzimmer', available: 2, minPax: 1), ]); $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [ 1408 => $this->createRoomSelection(1408, quantity: 2), 1409 => $this->createRoomSelection(1409, quantity: 0), ]; $adjustments = $this->bookingService()->reconcileRoomSelections($bookingDto); $this->assertCount(1, $adjustments); $this->assertSame(1408, $adjustments[0]->roomId); $this->assertSame(2, $adjustments[0]->requestedQuantity); $this->assertSame(0, $adjustments[0]->bookableQuantity); $this->assertTrue($adjustments[0]->isDropped()); $this->assertSame([1409], array_keys($bookingDto->roomSelections)); } public function testCapsAQuantityThatExceedsTheRemainingContingent(): void { $travel = $this->createTravel([ $this->createRoom(1408, 'Doppelzimmer', available: 1, minPax: 2), ]); $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [ 1408 => $this->createRoomSelection(1408, quantity: 3), ]; $adjustments = $this->bookingService()->reconcileRoomSelections($bookingDto); $this->assertCount(1, $adjustments); $this->assertSame(1408, $adjustments[0]->roomId); $this->assertSame('Aus der Session', $adjustments[0]->label); $this->assertSame(3, $adjustments[0]->requestedQuantity); $this->assertSame(1, $adjustments[0]->bookableQuantity); $this->assertFalse($adjustments[0]->isDropped()); $this->assertSame(1, $bookingDto->roomSelections[1408]->quantity, 'The selection carries the capped quantity'); $this->assertSame(1, $bookingDto->roomSelections[1408]->maxQuantity); } public function testLeavesAQuantityThatStillFitsTheReducedContingent(): void { $travel = $this->createTravel([ $this->createRoom(1408, 'Doppelzimmer', available: 2, minPax: 2), ]); $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [ 1408 => $this->createRoomSelection(1408, quantity: 2), ]; $adjustments = $this->bookingService()->reconcileRoomSelections($bookingDto); $this->assertSame([], $adjustments); $this->assertSame(2, $bookingDto->roomSelections[1408]->quantity); } public function testRemovesAnUnselectedRoomThatIsNoLongerBookableWithoutReportingIt(): void { $travel = $this->createTravel([ $this->createRoom(1408, 'Doppelzimmer', available: 4, minPax: 2), $this->createRoom(1409, 'Einzelzimmer', available: 0, minPax: 1), ]); $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [ 1408 => $this->createRoomSelection(1408, quantity: 1), 1409 => $this->createRoomSelection(1409, quantity: 0), ]; $adjustments = $this->bookingService()->reconcileRoomSelections($bookingDto); $this->assertSame([], $adjustments); $this->assertSame([1408], array_keys($bookingDto->roomSelections)); } public function testAddsARoomThatBecameBookableAgain(): void { $travel = $this->createTravel([ $this->createRoom(1408, 'Doppelzimmer', available: 4, minPax: 2), $this->createRoom(1409, 'Einzelzimmer', available: 2, minPax: 1), ]); $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [ 1408 => $this->createRoomSelection(1408, quantity: 1), ]; $adjustments = $this->bookingService()->reconcileRoomSelections($bookingDto); $this->assertSame([], $adjustments); $this->assertSame([1408, 1409], array_keys($bookingDto->roomSelections)); $this->assertSame(0, $bookingDto->roomSelections[1409]->quantity); $this->assertSame('Einzelzimmer', $bookingDto->roomSelections[1409]->label); } public function testEmptiesTheSelectionsWhenTheTravelSoldOutCompletely(): void { $travel = $this->createTravel([ $this->createRoom(1408, 'Doppelzimmer', available: 0, minPax: 2), ]); $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [ 1408 => $this->createRoomSelection(1408, quantity: 2), ]; $adjustments = $this->bookingService()->reconcileRoomSelections($bookingDto); $this->assertCount(1, $adjustments); $this->assertTrue($adjustments[0]->isDropped()); $this->assertSame([], $bookingDto->roomSelections); } private function bookingService(): BookingConfigurator { return new BookingConfigurator( $this->createStub(BookingSessionManager::class), $this->createStub(TravelDataProvider::class), $this->createStub(ParticipantEligibilityChecker::class), $this->createStub(BookingStatusRuleRegistry::class), $this->createStub(AgencyLoader::class), 'F' ); } /** * @param array $rooms */ private function createTravel(array $rooms): Travel { $travel = new Travel(); $travel->id = 4711; $travel->code = 'TRV-4711'; $travel->rooms = $rooms; return $travel; } private function createRoom(int $id, string $label, int $available, int $minPax): Room { $room = new Room(); $room->id = $id; $room->label = $label; $room->available = $available; $room->minPax = $minPax; $room->status = Constants::STATUS_AVAILABLE; $room->price = 199.0; return $room; } private function createRoomSelection(int $id, int $quantity): RoomSelectionDto { $selection = new RoomSelectionDto(); $selection->id = $id; $selection->label = 'Aus der Session'; $selection->quantity = $quantity; $selection->capacity = 2; $selection->maxQuantity = 9; return $selection; } }