fix: stop counting held seats in edit usage

This commit is contained in:
fromme committed 2026-11-04 10:10:37 +01:00
1 parent e9766dbdce
commit d8fe9a3875
2 files changed
+51

No files matched your search

@@ -219,6 +219,10 @@ class ServiceAvailabilityCalculator
/**
* Calculate how many times each service has been selected by other participants.
*
* Only new selections count. In edit mode the form is prefilled with the live booking, whose
* seats BusPro has already deducted from frei; counting them again would report a contingent
* as exhausted while seats are still free.
*
* @param BookingDto $bookingDto The booking data with participant selections
* @param int $currentParticipantIndex The index of the participant currently filling the form
*
@@ -238,6 +242,10 @@ class ServiceAvailabilityCalculator
$participantUsage = $this->countParticipantServiceUsage($participant);
foreach ($participantUsage as $serviceId => $count) {
if (null !== $bookingDto->booking && $bookingDto->booking->hasServiceForParticipant($index, $serviceId)) {
--$count;
}
$serviceUsage[$serviceId] = ($serviceUsage[$serviceId] ?? 0) + $count;
}
}
@@ -112,6 +112,30 @@ class ServiceAvailabilityCalculatorTest extends TestCase
$this->assertFalse($this->calculator->isServiceUnavailable(1, $bookingDto, 0));
}
public function testSeatsHeldByOtherParticipantsDoNotCountTowardUsageInEditMode(): void
{
// BusPro reports frei="3" after deducting the seats this booking already holds
$parkingService = $this->createParkingService(id: 1, available: 3);
$bookingDto = $this->createEditBookingDtoWithServices([$parkingService]);
$this->holdParkingForOtherParticipants($bookingDto, $parkingService, [1, 2, 3, 4, 5, 6, 7, 8]);
$this->assertFalse($this->calculator->isServiceUnavailable(1, $bookingDto, 0));
$this->assertSame(3, $this->calculator->calculateRemainingAvailability($bookingDto, 0)[1]);
}
public function testNewSelectionByOtherParticipantStillCountsTowardUsageInEditMode(): void
{
$parkingService = $this->createParkingService(id: 1, available: 1);
$bookingDto = $this->createEditBookingDtoWithServices([$parkingService]);
$otherParticipant = new ParticipantDto();
$otherParticipant->parkingService = $parkingService;
$bookingDto->participants[1] = $otherParticipant;
// Participant 1 picks the last slot in this edit without holding it in the booking
$this->assertTrue($this->calculator->isServiceUnavailable(1, $bookingDto, 0));
}
public function testAutoBookedOnRequestServiceStaysAvailableInEditMode(): void
{
$service = $this->createSkiPass(id: 1, available: 10, status: Constants::STATUS_ON_REQUEST);
@@ -236,4 +260,23 @@ class ServiceAvailabilityCalculatorTest extends TestCase
return $bookingDto;
}
/**
* Prefills the given participants with the parking service, as the edit form does for a
* service they hold in the live booking.
*
* @param list<int> $participantIndexes
*/
private function holdParkingForOtherParticipants(BookingDto $bookingDto, Service $parkingService, array $participantIndexes): void
{
$held = clone $parkingService;
$held->mapping = $participantIndexes;
$bookingDto->booking->additionalServices[$parkingService->id] = $held;
foreach ($participantIndexes as $index) {
$participant = new ParticipantDto();
$participant->parkingService = $parkingService;
$bookingDto->participants[$index] = $participant;
}
}
}