wip: modernized edit flow

This commit is contained in:
Björn Fromme
2025-10-08 21:09:53 +02:00
parent c3008d7f7a
commit cba0f747cd
75 changed files with 1662 additions and 747 deletions
@@ -4,30 +4,23 @@ declare(strict_types=1);
namespace App\Form\Service;
use App\Form\Model\BookingCreateDto;
use App\Form\Model\BookingDtoInterface;
use App\Form\Model\BookingDto;
use App\Form\Service\Abstract\AbstractParticipantFieldHandler;
use App\Service\InsuranceMatchingService;
/**
* Handles bulk insurance booking for the applicant (first participant).
* Handles bulk insurance booking checkbox for the applicant (first participant).
*
* When the applicant enables bulk insurance booking, their selected insurance type
* (subType + familyInsurance) is automatically assigned to all participants with
* automatic price tier adjustment based on each participant's individual travel price.
* This handler only manages the checkbox state - it does NOT assign insurance to
* dependent participants. The actual bulk insurance assignment happens in the
* BookingDataProcessor during API submission, keeping the form layer clean and
* avoiding cross-participant modifications in field handlers.
*
* This handler processes the bulkInsuranceBooking checkbox state and triggers
* insurance assignment to dependent participants when enabled.
*
* Dependencies: insurance (applicant must have insurance selected before enabling bulk)
* The checkbox state is used by:
* - Templates: To display "wie Anmelder" for dependent participants
* - Processors: To apply applicant's insurance to all participants before API submission
*/
class ParticipantBulkInsuranceFieldHandler extends AbstractParticipantFieldHandler
{
public function __construct(
private readonly InsuranceMatchingService $insuranceMatchingService,
) {
}
public function getFieldName(): string
{
return 'bulkInsuranceBooking';
@@ -35,8 +28,8 @@ class ParticipantBulkInsuranceFieldHandler extends AbstractParticipantFieldHandl
public function getDependencies(): array
{
// Depends on insurance field to ensure insurance is selected before bulk assignment
return ['insurance'];
// No dependencies - just manages checkbox state
return [];
}
/**
@@ -58,120 +51,22 @@ class ParticipantBulkInsuranceFieldHandler extends AbstractParticipantFieldHandl
/**
* Processes the bulk insurance booking checkbox for the applicant.
*
* When bulk insurance is enabled and applicant has insurance selected,
* assigns the same insurance type to all participants based on their
* individual pricing and eligibility criteria.
* This handler ONLY stores the checkbox state. The actual insurance assignment
* to dependent participants is handled by BookingDataProcessor during API submission.
*
* @param array<string, mixed> $submittedData The submitted participant form data
* @param BookingDtoInterface $bookingDto The booking DTO to update
* @param BookingDto $bookingDto The booking DTO to update
* @param int $participantIndex The index of the participant (must be 0)
*/
public function processField(array $submittedData, BookingDtoInterface $bookingDto, int $participantIndex): void
public function processField(array $submittedData, BookingDto $bookingDto, int $participantIndex): void
{
$participant = $this->getParticipant($bookingDto, $participantIndex);
if (null === $participant || !$bookingDto instanceof BookingCreateDto) {
if (null === $participant) {
return;
}
// Get checkbox value from submitted data
// Get checkbox value from submitted data and store it
$bulkInsuranceBooking = $this->getFieldValue($submittedData, $this->getFieldName());
$isBulkEnabled = (bool) $bulkInsuranceBooking;
// Store checkbox state
$participant->bulkInsuranceBooking = $isBulkEnabled;
// If bulk insurance is enabled and applicant has insurance, assign to all participants
if (true === $isBulkEnabled && null !== $participant->insurance) {
$this->applyBulkInsuranceToAllParticipants($bookingDto, $participant->insurance);
}
// If bulk insurance was CHANGED from enabled to disabled, clear dependent participants' insurances
// Don't clear if it was never enabled (to allow independent insurance selection)
if (false === $isBulkEnabled && $this->wasBulkInsurancePreviouslyEnabled($bookingDto)) {
$this->clearDependentParticipantsInsurance($bookingDto);
}
}
/**
* Applies the applicant's insurance type to all participants with automatic price tier adjustment.
*
* Uses InsuranceMatchingService to find the appropriate price tier for each participant
* based on their individual travel price and eligibility criteria.
*
* @param BookingCreateDto $bookingDto The booking DTO with all participants
* @param object $applicantInsurance The insurance selected by the applicant
*/
private function applyBulkInsuranceToAllParticipants(BookingCreateDto $bookingDto, object $applicantInsurance): void
{
$availableInsurances = $bookingDto->travel->insurances ?? [];
// Get insurance assignments for all participants
$assignments = $this->insuranceMatchingService->batchAssignInsuranceToParticipants(
$availableInsurances,
$applicantInsurance,
$bookingDto
);
// Apply assignments to participants (skip applicant index 0, they keep their selection)
foreach ($assignments as $index => $insurance) {
if (0 === $index) {
continue; // Skip applicant
}
$participant = $bookingDto->getParticipant($index);
if (null !== $participant) {
$participant->insurance = $insurance;
}
}
}
/**
* Clears insurance selections for dependent participants when bulk booking is disabled.
*
* @param BookingCreateDto $bookingDto The booking DTO with all participants
*/
private function clearDependentParticipantsInsurance(BookingCreateDto $bookingDto): void
{
foreach ($bookingDto->getParticipants() as $index => $participant) {
if (0 === $index) {
continue; // Skip applicant
}
$participant->insurance = null;
}
}
/**
* Checks if bulk insurance was previously enabled by checking if dependent participants
* have the same insurance type as the applicant.
*
* This prevents clearing independent insurance selections when the checkbox is simply unchecked
* without ever having been enabled.
*
* @param BookingCreateDto $bookingDto The booking DTO with all participants
*
* @return bool True if bulk was previously active (dependent participants have matching insurance)
*/
private function wasBulkInsurancePreviouslyEnabled(BookingCreateDto $bookingDto): bool
{
$applicant = $bookingDto->participants[0] ?? null;
if (null === $applicant || null === $applicant->insurance) {
return false;
}
// Check if any dependent participant has insurance that matches the applicant
// If so, bulk was likely previously enabled
foreach ($bookingDto->participants as $index => $participant) {
if (0 === $index) {
continue; // Skip applicant
}
if (null !== $participant->insurance) {
// If any dependent has insurance, assume bulk was previously enabled
return true;
}
}
return false;
$participant->bulkInsuranceBooking = (bool) $bulkInsuranceBooking;
}
}