wip: improved refresh logic
This commit is contained in:
@@ -46,6 +46,10 @@ class CreateStep2Controller extends AbstractController
|
||||
// Ensure correct number of participants
|
||||
$this->ensureCorrectNumberOfParticipants($bookingCreateDto);
|
||||
$participantsCount = $this->getParticipantsCount($bookingCreateDto);
|
||||
|
||||
// Pre-select mandatory services for participants with birth dates
|
||||
$this->bookingService->preselectMandatoryServices($bookingCreateDto);
|
||||
|
||||
$this->bookingService->saveBookingCreateDto($request, $bookingCreateDto);
|
||||
|
||||
$form = $this->createForm(BookingCreateStep2Type::class, $bookingCreateDto, [
|
||||
@@ -94,6 +98,16 @@ class CreateStep2Controller extends AbstractController
|
||||
]);
|
||||
|
||||
$form->handleRequest($request);
|
||||
|
||||
// Pre-select mandatory services after form processing but before pricing calculation
|
||||
$this->bookingService->preselectMandatoryServices($bookingCreateDto);
|
||||
|
||||
// Recreate the form with the updated DTO that includes mandatory services
|
||||
$form = $this->createForm(BookingCreateStep2Type::class, $bookingCreateDto, [
|
||||
'attr' => ['novalidate' => 'novalidate'],
|
||||
'validation_groups' => false,
|
||||
]);
|
||||
|
||||
$this->bookingService->saveBookingCreateDto($request, $bookingCreateDto);
|
||||
|
||||
$summary = $this->bookingService->getRoomSummaryAndParticipantCount($bookingCreateDto);
|
||||
|
||||
@@ -134,9 +134,8 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
|
||||
$attributes = [];
|
||||
|
||||
// Pre-select and make readonly for mandatory services
|
||||
// Make readonly for mandatory services (pre-selection handled by service layer)
|
||||
if (true === $service->mandatory) {
|
||||
$attributes['checked'] = true;
|
||||
$attributes['readonly'] = true;
|
||||
$attributes['class'] = 'text-pink';
|
||||
$attributes['title'] = 'Diese Leistung ist nicht abwählbar';
|
||||
|
||||
@@ -286,6 +286,12 @@ class BookingPriceCalculatorService
|
||||
}
|
||||
|
||||
$subType = $serviceData['subType'] ?? 'other';
|
||||
|
||||
// Normalize rental subtypes to avoid duplicate sections
|
||||
if (true === in_array($subType, Constants::TOKEN_RENTALS, true)) {
|
||||
$subType = 'rentals'; // Normalize all rental subtypes to a single key
|
||||
}
|
||||
|
||||
$isDiscount = $serviceData['totalPrice'] < 0;
|
||||
|
||||
// Create separate buckets for positive costs and discounts
|
||||
@@ -332,9 +338,10 @@ class BookingPriceCalculatorService
|
||||
Constants::TOKEN_ADDITIONAL => 'Zusatzleistungen',
|
||||
Constants::TOKEN_BOARD => 'Verpflegung',
|
||||
'transportation' => 'Beförderung',
|
||||
'rentals' => 'Leihmaterial', // Normalized rental subtype
|
||||
];
|
||||
|
||||
// Handle rentals array
|
||||
// Handle rentals array (keep for backward compatibility with non-normalized subtypes)
|
||||
if (true === in_array($subType, Constants::TOKEN_RENTALS, true)) {
|
||||
return 'Leihmaterial';
|
||||
}
|
||||
|
||||
@@ -266,4 +266,58 @@ class BookingService
|
||||
|
||||
return $oldSnapshot !== $newSnapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-selects mandatory services for all participants in the booking DTO.
|
||||
*
|
||||
* This method ensures that mandatory services are selected before form rendering
|
||||
* and pricing calculations, resolving timing issues where mandatory services
|
||||
* were only selected during form rendering via choice_attr callbacks.
|
||||
*
|
||||
* @param BookingCreateDto $bookingDto The booking DTO to update with mandatory services
|
||||
*/
|
||||
public function preselectMandatoryServices(BookingCreateDto $bookingDto): void
|
||||
{
|
||||
$additionalServices = $bookingDto->travel->getAdditionalServicesBySubTypes(\App\BusProNet\Constants::TOKEN_ADDITIONAL);
|
||||
$mandatoryServices = array_filter($additionalServices, fn ($service) => true === $service->mandatory);
|
||||
|
||||
// Pre-select mandatory services for each participant
|
||||
foreach ($bookingDto->participants as $participant) {
|
||||
if (null === $participant->dateOfBirth) {
|
||||
continue; // Skip participants without age information
|
||||
}
|
||||
|
||||
// Get age-appropriate mandatory services for this participant
|
||||
$ageAppropriateServices = array_filter($mandatoryServices, function ($service) use ($bookingDto, $participant) {
|
||||
// Use the age evaluator service to check if service is appropriate for participant age
|
||||
if (null === $service->ageFrom && null === $service->ageTo) {
|
||||
return true; // No age restrictions
|
||||
}
|
||||
|
||||
$age = $participant->dateOfBirth->diff($bookingDto->travel->dateFrom)->y;
|
||||
|
||||
if (null !== $service->ageFrom && $age < $service->ageFrom) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (null !== $service->ageTo && $age > $service->ageTo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
// Add mandatory services to current selections
|
||||
$currentSelections = $participant->additionalServices ?? [];
|
||||
$currentServiceIds = array_map(fn ($service) => $service->id, $currentSelections);
|
||||
|
||||
foreach ($ageAppropriateServices as $mandatoryService) {
|
||||
if (false === in_array($mandatoryService->id, $currentServiceIds, true)) {
|
||||
$currentSelections[] = $mandatoryService;
|
||||
}
|
||||
}
|
||||
|
||||
$participant->additionalServices = $currentSelections;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,24 @@
|
||||
{{ form_row(participant.remarksRoom) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{# Services hint - shown when date of birth is missing #}
|
||||
{% set participantData = participant.vars.data %}
|
||||
{% set hasDateOfBirth = participantData and participantData.dateOfBirth %}
|
||||
|
||||
{% if not hasDateOfBirth %}
|
||||
<div class="mb-4 p-4 bg-blue-50 border border-blue-200 rounded-lg">
|
||||
<div class="flex items-center">
|
||||
<svg class="w-5 h-5 text-blue-600 mr-2" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
<p class="text-sm text-blue-800">
|
||||
Zusatzleistungen sind erst nach Angabe des Geburtsdatums buchbar
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
{% if participant.skiPass is defined %}
|
||||
{{ form_row(participant.skiPass, {
|
||||
|
||||
Reference in New Issue
Block a user