fix: incorrect rules around family insurances
addresses #869dr80qj
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Form\Service\Condition;
|
||||
|
||||
use App\Form\Model\BookingDto;
|
||||
use App\Form\Service\Contract\FieldConditionInterface;
|
||||
|
||||
/**
|
||||
* True for dependent participants when the applicant has a family insurance selected.
|
||||
*
|
||||
* Family insurance covers the whole family under a single policy on the applicant, so
|
||||
* dependents must not be offered their own insurance selection while it's active.
|
||||
*/
|
||||
class FamilyInsuranceActiveCondition implements FieldConditionInterface
|
||||
{
|
||||
public function evaluate(BookingDto $bookingDto, int $participantIndex, array $formData): bool
|
||||
{
|
||||
if (0 === $participantIndex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$applicant = $bookingDto->getParticipant(0);
|
||||
|
||||
return null !== $applicant
|
||||
&& null !== $applicant->insurance
|
||||
&& true === $applicant->insurance->familyInsurance;
|
||||
}
|
||||
|
||||
public function getDependentFields(): array
|
||||
{
|
||||
return ['insurance'];
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Applicant has a family insurance selected';
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ use App\Form\Service\Condition\BookingEligibilityCondition;
|
||||
use App\Form\Service\Condition\BulkInsuranceBookingCondition;
|
||||
use App\Form\Service\Condition\CompositeCondition;
|
||||
use App\Form\Service\Condition\DateOfBirthProvidedCondition;
|
||||
use App\Form\Service\Condition\FamilyInsuranceActiveCondition;
|
||||
use App\Form\Service\Condition\FieldValueCondition;
|
||||
use App\Form\Service\Condition\FinalBookingOnlyCondition;
|
||||
use App\Form\Service\Condition\FirstParticipantCondition;
|
||||
@@ -221,11 +222,13 @@ class CreateFieldStateProvider extends AbstractFieldStateProvider
|
||||
),
|
||||
];
|
||||
|
||||
// Hide insurance field until date of birth is provided OR when bulk insurance booking is active OR when participant is ineligible
|
||||
// Hide insurance field until date of birth is provided OR when bulk insurance booking is active
|
||||
// OR when the applicant has a family insurance active (it already covers dependents) OR when participant is ineligible
|
||||
$this->fieldStateConditions['insurance'] = [
|
||||
'hidden' => CompositeCondition::or(
|
||||
CompositeCondition::not($dateOfBirthProvidedCondition),
|
||||
$bulkInsuranceBookingCondition,
|
||||
new FamilyInsuranceActiveCondition(),
|
||||
$bookingEligibilityCondition
|
||||
),
|
||||
];
|
||||
|
||||
@@ -1159,15 +1159,17 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
||||
// Get selectable (non-complementary) insurances with caching
|
||||
$selectableInsurances = $this->insuranceService->getSelectableInsurances($bookingDto->travel);
|
||||
|
||||
// Calculate travel price for eligibility filtering
|
||||
$travelPrice = $this->priceCalculatorService->calculateIndividualParticipantPriceExcludingInsurance($bookingDto, $participantIndex);
|
||||
// Family insurances are priced by the total booking price rather than the individual
|
||||
// participant's price - InsuranceManager applies the correct basis per insurance type
|
||||
$individualPrice = $this->priceCalculatorService->calculateIndividualParticipantPriceExcludingInsurance($bookingDto, $participantIndex);
|
||||
$totalBookingPrice = $this->priceCalculatorService->calculateTotalBookingPriceExcludingInsurance($bookingDto);
|
||||
|
||||
// Filter based on eligibility criteria for this participant
|
||||
$eligibleInsurances = $this->insuranceService->getEligibleInsurances(
|
||||
$eligibleInsurances = $this->insuranceService->getEligibleInsurancesForParticipant(
|
||||
$selectableInsurances,
|
||||
$participant,
|
||||
$bookingDto,
|
||||
$travelPrice
|
||||
$individualPrice,
|
||||
$totalBookingPrice
|
||||
);
|
||||
|
||||
// Inject synthetic "no insurance" option at the top of the list
|
||||
|
||||
@@ -136,9 +136,6 @@ class ParticipantInsuranceFieldHandler extends AbstractParticipantFieldHandler
|
||||
// Get selectable (non-complementary) insurances with caching
|
||||
$selectableInsurances = $this->insuranceService->getSelectableInsurances($bookingDto->travel);
|
||||
|
||||
// Calculate travel price for eligibility checks
|
||||
$travelPrice = $this->priceCalculatorService->calculateIndividualParticipantPriceExcludingInsurance($bookingDto, $participantIndex);
|
||||
|
||||
// Determine if this is a new user selection or just form resubmission
|
||||
$isNewSelection = null !== $selectedInsuranceId
|
||||
&& (null === $currentInsurance || !$this->isSameInsurance($selectedInsuranceId, $currentInsurance));
|
||||
@@ -161,6 +158,8 @@ class ParticipantInsuranceFieldHandler extends AbstractParticipantFieldHandler
|
||||
$selectedInsurance = $this->findInsuranceById($selectableInsurances, $selectedInsuranceId);
|
||||
|
||||
if (null !== $selectedInsurance) {
|
||||
$travelPrice = $this->priceCalculatorService->resolveInsuranceTravelPrice($bookingDto, $participantIndex, $selectedInsurance);
|
||||
|
||||
$eligibleInsurances = $this->insuranceService->getEligibleInsurances($selectableInsurances, $participant, $bookingDto, $travelPrice);
|
||||
$isSelectedInsuranceEligible = $this->isInsuranceInList($selectedInsurance, $eligibleInsurances);
|
||||
|
||||
@@ -198,6 +197,8 @@ class ParticipantInsuranceFieldHandler extends AbstractParticipantFieldHandler
|
||||
return;
|
||||
}
|
||||
|
||||
$travelPrice = $this->priceCalculatorService->resolveInsuranceTravelPrice($bookingDto, $participantIndex, $currentInsurance);
|
||||
|
||||
// Check if current insurance is still eligible with updated participant data
|
||||
$eligibleInsurances = $this->insuranceService->getEligibleInsurances($selectableInsurances, $participant, $bookingDto, $travelPrice);
|
||||
$isCurrentInsuranceStillEligible = $this->isInsuranceInList($currentInsurance, $eligibleInsurances);
|
||||
|
||||
Reference in New Issue
Block a user