fix: stop offering unbookable services in the booking edit flow
This commit is contained in:
@@ -24,9 +24,72 @@ class BookingEditSubmitGuard
|
||||
{
|
||||
public function __construct(
|
||||
private readonly BookingDataProcessor $bookingDataProcessor,
|
||||
private readonly ServiceAvailabilityCalculator $serviceAvailabilityCalculator,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverts selections of services that are no longer bookable.
|
||||
*
|
||||
* The read-only state in the participant form is presentation only, so a stale session or
|
||||
* a replayed POST can still carry a service that has since sold out or moved to 'Anfrage'.
|
||||
* Sending one makes BusPro reject the entire update - every participant's changes with it -
|
||||
* so the selection is reverted to what the live booking already holds.
|
||||
*
|
||||
* Services the participant already holds are never touched: the availability rule carves
|
||||
* them out, and withdrawing one would break the Leistung/Teilnehmer counts.
|
||||
*
|
||||
* Expects $workingDto->booking to be the fresh booking, as the availability rule reads its
|
||||
* already-held carve-out from there.
|
||||
*
|
||||
* @return list<string> Labels of the services that were reverted, for user feedback
|
||||
*/
|
||||
public function revertUnbookableServiceAdditions(BookingDto $workingDto, Booking $freshBooking): array
|
||||
{
|
||||
$baselineDto = $this->bookingDataProcessor->createBookingDtoFromBooking($freshBooking, $workingDto->travel, $workingDto->isInternalAgencyBooking());
|
||||
$revertedLabels = [];
|
||||
|
||||
foreach ($workingDto->participants as $index => $participant) {
|
||||
$baseline = $baselineDto->participants[$index] ?? null;
|
||||
if (null === $baseline) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$isBlocked = fn (?Service $service): bool => null !== $service
|
||||
&& null !== $service->id
|
||||
&& $this->serviceAvailabilityCalculator->isServiceUnavailable($service->id, $workingDto, $index);
|
||||
|
||||
// Multi-selection fields: drop the blocked additions, keep everything else
|
||||
foreach (['courses', 'additionalServices', 'board', 'rentals'] as $field) {
|
||||
$kept = [];
|
||||
foreach ($participant->{$field} as $service) {
|
||||
if (true === $isBlocked($service)) {
|
||||
$revertedLabels[] = (string) $service->label;
|
||||
continue;
|
||||
}
|
||||
$kept[] = $service;
|
||||
}
|
||||
|
||||
if (count($kept) !== count($participant->{$field})) {
|
||||
$participant->{$field} = $kept;
|
||||
}
|
||||
}
|
||||
|
||||
// Single-selection fields: fall back to what the booking already holds rather than
|
||||
// clearing, so a required field does not end up empty
|
||||
foreach (['skiPass', 'veg', 'transportationOutbound', 'transportationInbound', 'parkingService'] as $field) {
|
||||
if (false === $isBlocked($participant->{$field})) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$revertedLabels[] = (string) $participant->{$field}->label;
|
||||
$participant->{$field} = $baseline->{$field};
|
||||
}
|
||||
}
|
||||
|
||||
return array_values(array_unique($revertedLabels));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverts immutable category changes to fresh booking values.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user