Files
myep/tests/Service/BookingServiceStatusTest.php
T
Björn Fromme e222f448bb feat: proper determination of agency initiated bookings
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.
2026-03-16 12:02:27 +01:00

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;
}
}