fix: consider parking space availability

This commit is contained in:
Björn Fromme
2026-07-23 17:44:08 +02:00
parent fafc60eba9
commit b323c120f9
7 changed files with 237 additions and 4 deletions
@@ -647,13 +647,24 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
return [];
}
return [
$fieldOptions = [
'label' => $this->serviceLabelFormatter->formatServiceLabelForServices(
Constants::SERVICE_LABELS[Constants::TOKEN_PARKING],
$parkingServices
),
'required' => false,
];
// There's only ever one parking type, so check readonly state against the single service
$parkingService = reset($parkingServices);
if ($this->shouldMakeServiceReadonly($parkingService, $bookingDto, $participantIndex, 'parking')) {
$fieldOptions['attr'] = [
'readonly' => true,
'data-tooltip' => 'ausgebucht',
];
}
return $fieldOptions;
};
// Bulk insurance booking checkbox (applicant only - controls insurance assignment for all participants)
@@ -10,6 +10,7 @@ use App\BusProNet\Utility\DirectionMapper;
use App\Form\Model\BookingDto;
use App\Form\Model\ParticipantDto;
use App\Form\Service\Abstract\AbstractParticipantFieldHandler;
use App\Service\ServiceAvailabilityCalculator;
/**
* Handles parking service selection for self-organized transportation.
@@ -20,6 +21,11 @@ use App\Form\Service\Abstract\AbstractParticipantFieldHandler;
*/
class ParticipantParkingFieldHandler extends AbstractParticipantFieldHandler
{
public function __construct(
private readonly ServiceAvailabilityCalculator $serviceAvailabilityCalculator,
) {
}
public function getFieldName(): string
{
return 'parking';
@@ -73,7 +79,22 @@ class ParticipantParkingFieldHandler extends AbstractParticipantFieldHandler
// Store parking service object for pricing calculation
if (true === $isParkingSelected) {
$participant->parkingService = $this->findParkingService($bookingDto, $participantIndex);
$parkingService = $this->findParkingService($bookingDto, $participantIndex);
// Reject the selection if the service is sold out, in case the client
// bypassed the readonly UI state (e.g. a stale form or manual submission)
if (
null !== $parkingService
&& BookingDto::MODE_EDIT !== $bookingDto->getMode()
&& $this->serviceAvailabilityCalculator->isServiceUnavailable($parkingService->id, $bookingDto, $participantIndex)
) {
$participant->parking = false;
$participant->parkingService = null;
return;
}
$participant->parkingService = $parkingService;
} else {
$participant->parkingService = null;
}
@@ -173,6 +173,11 @@ class ServiceAvailabilityCalculator
$serviceUsage[$participant->skiPass->id] = ($serviceUsage[$participant->skiPass->id] ?? 0) + 1;
}
// Parking service (single selection)
if (null !== $participant->parkingService && null !== $participant->parkingService->id) {
$serviceUsage[$participant->parkingService->id] = ($serviceUsage[$participant->parkingService->id] ?? 0) + 1;
}
// Transportation services (single selection each)
if (null !== $participant->transportationOutbound && null !== $participant->transportationOutbound->id) {
$serviceUsage[$participant->transportationOutbound->id] = ($serviceUsage[$participant->transportationOutbound->id] ?? 0) + 1;
@@ -231,6 +236,7 @@ class ServiceAvailabilityCalculator
Constants::TOKEN_RENTALS,
Constants::TOKEN_SKI_PASS,
Constants::TOKEN_BOARD,
Constants::TOKEN_PARKING,
];
foreach ($additionalServiceTokens as $token) {