215 lines
7.8 KiB
PHP
215 lines
7.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests\Service;
|
|
|
|
use App\BusProNet\Constants;
|
|
use App\BusProNet\Model\Room;
|
|
use App\BusProNet\Model\Travel;
|
|
use App\BusProNet\Service\BookingStatusRuleRegistry;
|
|
use App\BusProNet\XmlLoader\AgencyLoader;
|
|
use App\Form\Model\BookingDto;
|
|
use App\Form\Model\RoomSelectionDto;
|
|
use App\Service\BookingConfigurator;
|
|
use App\Service\BookingSessionManager;
|
|
use App\Service\ParticipantEligibilityChecker;
|
|
use App\Service\TravelDataProvider;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class BookingConfiguratorRoomReconciliationTest extends TestCase
|
|
{
|
|
public function testKeepsQuantitiesOfRoomsThatAreStillBookable(): 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: 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<int, Room> $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;
|
|
}
|
|
}
|