For booking that are agency initiated (groups) different rules apply concerning mutability and requirement of personal data and whether the first participant is the applicant or not. This commit adds logic to evaluate the agency id assigned to the booking data to decide.
211 lines
6.8 KiB
PHP
211 lines
6.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\XmlLoader\AgencyLoader;
|
|
use App\Exception\NoRoomsAvailableException;
|
|
use App\Service\BookingPriceCalculatorService;
|
|
use App\Service\BookingService;
|
|
use App\Service\ParticipantEligibilityService;
|
|
use App\Service\TravelDataService;
|
|
use PHPUnit\Framework\TestCase;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Session\Session;
|
|
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
|
|
|
|
class BookingServiceStatusTest extends TestCase
|
|
{
|
|
private BookingService $bookingService;
|
|
private TravelDataService $travelDataService;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->travelDataService = $this->createMock(TravelDataService::class);
|
|
$priceCalculator = $this->createMock(BookingPriceCalculatorService::class);
|
|
$participantEligibility = $this->createMock(ParticipantEligibilityService::class);
|
|
$agencyLoader = $this->createMock(AgencyLoader::class);
|
|
|
|
$this->bookingService = new BookingService(
|
|
$this->travelDataService,
|
|
$priceCalculator,
|
|
$participantEligibility,
|
|
$agencyLoader,
|
|
'F' // default booking status
|
|
);
|
|
}
|
|
|
|
public function testStartFreshBookingWithFreiRooms(): void
|
|
{
|
|
$travel = $this->createTravelWithRooms([
|
|
['status' => Constants::STATUS_AVAILABLE, 'available' => 5],
|
|
]);
|
|
|
|
$this->travelDataService
|
|
->method('getTravelData')
|
|
->willReturn($travel);
|
|
|
|
$request = $this->createRequestWithSession();
|
|
|
|
$bookingDto = $this->bookingService->startFreshBooking($request, 123, 456);
|
|
|
|
$this->assertSame('F', $bookingDto->bookingStatus);
|
|
$this->assertCount(1, $bookingDto->roomSelections);
|
|
}
|
|
|
|
public function testStartFreshBookingWithFreiRoomsAndNoAvailabilityThrowsException(): void
|
|
{
|
|
$travel = $this->createTravelWithRooms([
|
|
['status' => Constants::STATUS_AVAILABLE, 'available' => 0],
|
|
]);
|
|
|
|
$this->travelDataService
|
|
->method('getTravelData')
|
|
->willReturn($travel);
|
|
|
|
$request = $this->createRequestWithSession();
|
|
|
|
$this->expectException(NoRoomsAvailableException::class);
|
|
|
|
$this->bookingService->startFreshBooking($request, 123, 456);
|
|
}
|
|
|
|
public function testStartFreshBookingWithAnfrageRooms(): void
|
|
{
|
|
$travel = $this->createTravelWithRooms([
|
|
['status' => Constants::STATUS_ON_REQUEST, 'available' => 5],
|
|
]);
|
|
|
|
$this->travelDataService
|
|
->method('getTravelData')
|
|
->willReturn($travel);
|
|
|
|
$request = $this->createRequestWithSession();
|
|
|
|
$bookingDto = $this->bookingService->startFreshBooking($request, 123, 456);
|
|
|
|
$this->assertSame('A', $bookingDto->bookingStatus);
|
|
$this->assertCount(1, $bookingDto->roomSelections);
|
|
}
|
|
|
|
public function testStartFreshBookingWithAnfrageRoomsAndNoAvailabilityThrowsException(): void
|
|
{
|
|
$travel = $this->createTravelWithRooms([
|
|
['status' => Constants::STATUS_ON_REQUEST, 'available' => 0],
|
|
]);
|
|
|
|
$this->travelDataService
|
|
->method('getTravelData')
|
|
->willReturn($travel);
|
|
|
|
$request = $this->createRequestWithSession();
|
|
|
|
$this->expectException(NoRoomsAvailableException::class);
|
|
|
|
$this->bookingService->startFreshBooking($request, 123, 456);
|
|
}
|
|
|
|
public function testStartFreshBookingWithMixedRoomsUsesFreeStatus(): void
|
|
{
|
|
// When both Frei and Anfrage rooms with availability exist, booking status should be 'F'
|
|
$travel = $this->createTravelWithRooms([
|
|
['status' => Constants::STATUS_AVAILABLE, 'available' => 5],
|
|
['status' => Constants::STATUS_ON_REQUEST, 'available' => 3],
|
|
]);
|
|
|
|
$this->travelDataService
|
|
->method('getTravelData')
|
|
->willReturn($travel);
|
|
|
|
$request = $this->createRequestWithSession();
|
|
|
|
$bookingDto = $this->bookingService->startFreshBooking($request, 123, 456);
|
|
|
|
$this->assertSame('F', $bookingDto->bookingStatus);
|
|
$this->assertCount(2, $bookingDto->roomSelections);
|
|
}
|
|
|
|
public function testStartFreshBookingWithNoBookableRoomsThrowsException(): void
|
|
{
|
|
// Rooms exist but all have 0 availability
|
|
$travel = $this->createTravelWithRooms([
|
|
['status' => Constants::STATUS_AVAILABLE, 'available' => 0],
|
|
['status' => Constants::STATUS_ON_REQUEST, 'available' => 0],
|
|
]);
|
|
|
|
$this->travelDataService
|
|
->method('getTravelData')
|
|
->willReturn($travel);
|
|
|
|
$request = $this->createRequestWithSession();
|
|
|
|
$this->expectException(NoRoomsAvailableException::class);
|
|
|
|
$this->bookingService->startFreshBooking($request, 123, 456);
|
|
}
|
|
|
|
public function testStartFreshBookingWithApiRestrictionsForcesInquiry(): void
|
|
{
|
|
// Even with Frei rooms, if API says only 'A' allowed, booking status should be 'A'
|
|
$travel = $this->createTravelWithRooms([
|
|
['status' => Constants::STATUS_AVAILABLE, 'available' => 5],
|
|
]);
|
|
$travel->allowedBookingStatus = ['A']; // API restricts to inquiry only
|
|
|
|
$this->travelDataService
|
|
->method('getTravelData')
|
|
->willReturn($travel);
|
|
|
|
$request = $this->createRequestWithSession();
|
|
|
|
$bookingDto = $this->bookingService->startFreshBooking($request, 123, 456);
|
|
|
|
$this->assertSame('A', $bookingDto->bookingStatus);
|
|
}
|
|
|
|
/**
|
|
* @param array<array{status: string, available: int}> $roomsConfig
|
|
*/
|
|
private function createTravelWithRooms(array $roomsConfig): Travel
|
|
{
|
|
$travel = new Travel();
|
|
$travel->id = 123;
|
|
$travel->hotelId = 456;
|
|
$travel->dateFrom = new \DateTimeImmutable('2030-01-01');
|
|
$travel->dateTo = new \DateTimeImmutable('2030-01-06');
|
|
$travel->allowedBookingStatus = []; // Empty means no API restrictions
|
|
|
|
$rooms = [];
|
|
foreach ($roomsConfig as $index => $config) {
|
|
$room = new Room();
|
|
$room->id = $index + 1;
|
|
$room->label = 'Test Room '.($index + 1);
|
|
$room->price = 100.0;
|
|
$room->available = $config['available'];
|
|
$room->status = $config['status'];
|
|
$room->minPax = 2;
|
|
$room->category = 'A';
|
|
$room->boardId = 1;
|
|
|
|
$rooms[$room->id] = $room;
|
|
}
|
|
|
|
$travel->rooms = $rooms;
|
|
|
|
return $travel;
|
|
}
|
|
|
|
private function createRequestWithSession(): Request
|
|
{
|
|
$session = new Session(new MockArraySessionStorage());
|
|
$request = new Request();
|
|
$request->setSession($session);
|
|
|
|
return $request;
|
|
}
|
|
}
|