wip: insurance booking

This commit is contained in:
Björn Fromme
2025-09-30 14:37:49 +02:00
parent 90ae78262a
commit a5dce776de
11 changed files with 131 additions and 475 deletions
@@ -35,7 +35,7 @@ use App\Service\InsuranceMatchingService;
class ParticipantInsuranceFieldHandler extends AbstractParticipantFieldHandler
{
public function __construct(
private readonly InsuranceMatchingService $insuranceMatchingService
private readonly InsuranceMatchingService $insuranceMatchingService,
) {
}
@@ -52,13 +52,27 @@ class ParticipantInsuranceFieldHandler extends AbstractParticipantFieldHandler
/**
* Returns the field dependencies for proper processing order.
*
* This handler depends on dateOfBirth for age evaluation and insurance eligibility.
* This handler must run AFTER all fields that affect travel price, since insurance
* reassignment logic depends on accurate price calculations. It also depends on
* dateOfBirth for age evaluation and insurance eligibility.
*
* @return string[] Array containing 'dateOfBirth' dependency
* @return string[] Array of field dependencies
*/
public function getDependencies(): array
{
return ['dateOfBirth'];
return [
'dateOfBirth', // Required for age-based eligibility
'skiPass', // Affects travel price
'rentals', // Affects travel price
'courses', // Affects travel price
'additionalServices', // Affects travel price
'board', // Affects travel price
'transportationOutbound', // Affects travel price
'transportationInbound', // Affects travel price
'pickupOutbound', // Affects travel price
'pickupInbound', // Affects travel price
'parking', // Affects travel price
];
}
/**
@@ -82,8 +96,12 @@ class ParticipantInsuranceFieldHandler extends AbstractParticipantFieldHandler
* Processes the insurance field for a specific participant.
*
* This method handles both explicit insurance selection from form data and automatic
* reassignment when the participant's travel price changes. It maintains the same
* insurance type but adjusts to the appropriate price tier when needed.
* reassignment when the participant's travel price changes. It distinguishes between:
* 1. New selection: User explicitly changed their insurance choice
* 2. Resubmission: Form resubmitted with existing insurance (e.g., after adding rentals)
*
* For resubmissions, it checks if the current insurance is still eligible with updated
* participant data and automatically reassigns to the correct price tier if needed.
*
* @param array<string, mixed> $submittedData The submitted participant form data
* @param BookingDtoInterface $bookingDto The booking DTO to update (create or edit)
@@ -100,59 +118,63 @@ class ParticipantInsuranceFieldHandler extends AbstractParticipantFieldHandler
$currentInsurance = $participant->insurance;
$availableInsurances = $bookingDto->travel->insurances ?? [];
// Handle explicit insurance selection from form
if (null !== $selectedInsuranceId) {
// Determine if this is a new user selection or just form resubmission
$isNewSelection = null !== $selectedInsuranceId
&& (null === $currentInsurance || !$this->isSameInsurance($selectedInsuranceId, $currentInsurance));
// Handle explicit new insurance selection from user
if ($isNewSelection) {
$selectedInsurance = $this->findInsuranceById($availableInsurances, $selectedInsuranceId);
// Check if the selected insurance is still eligible for this participant
if (null !== $selectedInsurance) {
$eligibleInsurances = $this->insuranceMatchingService->getEligibleInsurances($availableInsurances, $participant, $bookingDto);
$isSelectedInsuranceEligible = $this->isInsuranceInList($selectedInsurance, $eligibleInsurances);
if ($isSelectedInsuranceEligible) {
// Insurance is still eligible - use it directly
// New selection is eligible - use it
$participant->insurance = $selectedInsurance;
return;
} else {
// Insurance is no longer eligible - try to reassign to same type with new price tier
// New selection is not eligible - try to find alternative in same type
$reassignedInsurance = $this->insuranceMatchingService->reassignInsuranceForPriceChange(
$availableInsurances,
$selectedInsurance,
$participant,
$bookingDto
);
$participant->insurance = $reassignedInsurance;
return;
}
} else {
// Insurance not found - clear selection
$participant->insurance = null;
return;
}
return;
}
// Handle automatic reassignment if participant had an insurance but it's no longer eligible
if (null !== $currentInsurance) {
// Check if current insurance is still eligible
// Handle form resubmission with existing insurance (automatic reassignment check)
if (null !== $currentInsurance && null !== $selectedInsuranceId) {
// Check if current insurance is still eligible with updated participant data
$eligibleInsurances = $this->insuranceMatchingService->getEligibleInsurances($availableInsurances, $participant, $bookingDto);
$isCurrentInsuranceStillEligible = $this->isInsuranceInList($currentInsurance, $eligibleInsurances);
if (!$isCurrentInsuranceStillEligible) {
// Try to reassign to same insurance type with appropriate price tier
// Current insurance no longer eligible - try to reassign to same type with new price tier
$reassignedInsurance = $this->insuranceMatchingService->reassignInsuranceForPriceChange(
$availableInsurances,
$currentInsurance,
$participant,
$bookingDto
);
$participant->insurance = $reassignedInsurance; // null if no suitable match found
return;
}
return;
}
// No insurance selected or reassignment needed - keep current state (may be null)
// Handle explicit deselection (user removed insurance)
if (null === $selectedInsuranceId) {
$participant->insurance = null;
}
}
/**
@@ -221,4 +243,19 @@ class ParticipantInsuranceFieldHandler extends AbstractParticipantFieldHandler
return false;
}
/**
* Checks if the submitted insurance ID matches the current insurance.
*
* This is used to distinguish between a new user selection and a form resubmission
* with the existing insurance selection (e.g., when user adds rentals that change travel price).
*
* @param string|int $selectedInsuranceId The insurance ID from form submission
* @param Insurance $currentInsurance The currently assigned insurance from DTO
*
* @return bool True if they represent the same insurance
*/
private function isSameInsurance(string|int $selectedInsuranceId, Insurance $currentInsurance): bool
{
return (string) $currentInsurance->id === (string) $selectedInsuranceId;
}
}