feat: consolidated insurance service

This commit is contained in:
Björn Fromme
2026-03-16 11:59:11 +01:00
parent 4f951cdf8a
commit a0d5768752
12 changed files with 681 additions and 545 deletions
@@ -12,8 +12,8 @@ use App\BusProNet\Utility\DirectionMapper;
use App\Form\Model\BookingDto;
use App\Form\Service\Abstract\AbstractFieldOptionsProvider;
use App\Form\Service\Factory\ParticipantRoomChoiceLoaderFactory;
use App\Service\InsuranceMatchingService;
use App\Service\InsuranceTypeFilterService;
use App\Service\BookingPriceCalculatorService;
use App\Service\InsuranceService;
use App\Service\ServiceAvailabilityCalculator;
/**
@@ -45,13 +45,14 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
*
* @param ParticipantRoomChoiceLoaderFactory $roomChoiceLoaderFactory Factory for creating room choice loaders
* @param ServiceAvailabilityCalculator $serviceAvailabilityCalculator Service for calculating dynamic availability
* @param InsuranceMatchingService $insuranceMatchingService Service for matching insurances to participants
* @param InsuranceService $insuranceService Service for insurance operations
* @param BookingPriceCalculatorService $priceCalculatorService Service for calculating participant prices
*/
public function __construct(
private readonly ParticipantRoomChoiceLoaderFactory $roomChoiceLoaderFactory,
private readonly ServiceAvailabilityCalculator $serviceAvailabilityCalculator,
private readonly InsuranceMatchingService $insuranceMatchingService,
private readonly InsuranceTypeFilterService $insuranceTypeFilterService,
private readonly InsuranceService $insuranceService,
private readonly BookingPriceCalculatorService $priceCalculatorService,
) {
parent::__construct();
}
@@ -756,16 +757,18 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
return [];
}
$availableInsurances = $bookingDto->travel->insurances ?? [];
// Get selectable (non-complementary) insurances with caching
$selectableInsurances = $this->insuranceService->getSelectableInsurances($bookingDto->travel);
// Exclude complementary insurances (only available as part of packages)
$availableInsurances = $this->insuranceTypeFilterService->filterNonComplementary($availableInsurances);
// Calculate travel price for eligibility filtering
$travelPrice = $this->priceCalculatorService->calculateIndividualParticipantPriceExcludingInsurance($bookingDto, $participantIndex);
// Use insurance matching service to filter based on eligibility criteria
return $this->insuranceMatchingService->getEligibleInsurances(
$availableInsurances,
// Filter based on eligibility criteria for this participant
return $this->insuranceService->getEligibleInsurances(
$selectableInsurances,
$participant,
$bookingDto
$bookingDto,
$travelPrice
);
}
}
@@ -7,8 +7,8 @@ namespace App\Form\Service;
use App\BusProNet\Model\Insurance;
use App\Form\Model\BookingDto;
use App\Form\Service\Abstract\AbstractParticipantFieldHandler;
use App\Service\InsuranceMatchingService;
use App\Service\InsuranceTypeFilterService;
use App\Service\BookingPriceCalculatorService;
use App\Service\InsuranceService;
/**
* Handles processing of the insurance field for booking participants.
@@ -35,8 +35,8 @@ use App\Service\InsuranceTypeFilterService;
class ParticipantInsuranceFieldHandler extends AbstractParticipantFieldHandler
{
public function __construct(
private readonly InsuranceMatchingService $insuranceMatchingService,
private readonly InsuranceTypeFilterService $insuranceTypeFilterService,
private readonly InsuranceService $insuranceService,
private readonly BookingPriceCalculatorService $priceCalculatorService,
) {
}
@@ -132,10 +132,12 @@ class ParticipantInsuranceFieldHandler extends AbstractParticipantFieldHandler
$selectedInsuranceId = $this->getFieldValue($submittedData, $this->getFieldName());
$currentInsurance = $participant->insurance;
$availableInsurances = $bookingDto->travel->insurances ?? [];
// Exclude complementary insurances (only available as part of packages)
$availableInsurances = $this->insuranceTypeFilterService->filterNonComplementary($availableInsurances);
// 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
@@ -143,10 +145,10 @@ class ParticipantInsuranceFieldHandler extends AbstractParticipantFieldHandler
// Handle explicit new insurance selection from user
if ($isNewSelection) {
$selectedInsurance = $this->findInsuranceById($availableInsurances, $selectedInsuranceId);
$selectedInsurance = $this->findInsuranceById($selectableInsurances, $selectedInsuranceId);
if (null !== $selectedInsurance) {
$eligibleInsurances = $this->insuranceMatchingService->getEligibleInsurances($availableInsurances, $participant, $bookingDto);
$eligibleInsurances = $this->insuranceService->getEligibleInsurances($selectableInsurances, $participant, $bookingDto, $travelPrice);
$isSelectedInsuranceEligible = $this->isInsuranceInList($selectedInsurance, $eligibleInsurances);
if ($isSelectedInsuranceEligible) {
@@ -154,11 +156,12 @@ class ParticipantInsuranceFieldHandler extends AbstractParticipantFieldHandler
$participant->insurance = $selectedInsurance;
} else {
// New selection is not eligible - try to find alternative in same type
$reassignedInsurance = $this->insuranceMatchingService->reassignInsuranceForPriceChange(
$availableInsurances,
$reassignedInsurance = $this->insuranceService->reassignInsuranceForPriceChange(
$selectableInsurances,
$selectedInsurance,
$participant,
$bookingDto
$bookingDto,
$travelPrice
);
$participant->insurance = $reassignedInsurance;
@@ -178,16 +181,17 @@ class ParticipantInsuranceFieldHandler extends AbstractParticipantFieldHandler
// 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);
$eligibleInsurances = $this->insuranceService->getEligibleInsurances($selectableInsurances, $participant, $bookingDto, $travelPrice);
$isCurrentInsuranceStillEligible = $this->isInsuranceInList($currentInsurance, $eligibleInsurances);
if (!$isCurrentInsuranceStillEligible) {
// Current insurance no longer eligible - try to reassign to same type with new price tier
$reassignedInsurance = $this->insuranceMatchingService->reassignInsuranceForPriceChange(
$availableInsurances,
$reassignedInsurance = $this->insuranceService->reassignInsuranceForPriceChange(
$selectableInsurances,
$currentInsurance,
$participant,
$bookingDto
$bookingDto,
$travelPrice
);
if (null !== $reassignedInsurance && $reassignedInsurance->id !== $currentInsurance->id) {