$insurances Available insurances to filter * @param ParticipantDto $participant The participant to match insurances for * @param BookingDto $booking The booking context * @param float $travelPrice The participant's travel price (excluding insurance) * * @return array Filtered array of eligible insurances, sorted by price */ public function getEligibleInsurances( array $insurances, ParticipantDto $participant, BookingDto $booking, float $travelPrice, ): array { $travelStartDate = $booking->travel->dateFrom; $travelEndDate = $booking->travel->dateTo; if (null === $travelStartDate || null === $travelEndDate) { return []; // Cannot evaluate without travel dates } $bookingDate = Carbon::now()->toDateTimeImmutable(); $travelDurationDays = $travelStartDate->diff($travelEndDate)->days; $eligibleInsurances = array_filter( $insurances, fn (Insurance $insurance) => $this->isInsuranceEligible( $insurance, $participant, $booking, $travelStartDate, $travelEndDate, $bookingDate, $travelPrice, $travelDurationDays ) ); return $this->sortByPrice($eligibleInsurances); } /** * Checks if a specific insurance is eligible for given criteria. */ private function isInsuranceEligible( Insurance $insurance, ParticipantDto $participant, BookingDto $booking, \DateTimeImmutable $travelStartDate, \DateTimeImmutable $travelEndDate, \DateTimeImmutable $bookingDate, float $travelPrice, int $travelDurationDays, ): bool { // Family insurance constraints if (false === $this->checkFamilyInsuranceConstraints($insurance, $booking)) { return false; } // Age constraints if (false === $this->checkAgeConstraints($insurance, $participant, $travelStartDate)) { return false; } // Travel date constraints if (false === $this->checkTravelDateConstraints($insurance, $travelStartDate, $travelEndDate)) { return false; } // Booking date constraints if (false === $this->checkBookingDateConstraints($insurance, $bookingDate)) { return false; } // Travel price constraints if (false === $this->checkTravelPriceConstraints($insurance, $travelPrice)) { return false; } // Travel duration constraints if (false === $this->checkTravelDurationConstraints($insurance, $travelDurationDays)) { return false; } return true; } private function checkFamilyInsuranceConstraints(Insurance $insurance, BookingDto $booking): bool { // Family booking detection only available in create mode if (BookingDto::MODE_EDIT === $booking->getMode()) { return true; // Skip family constraints for edit mode } $isFamilyBooking = $booking->isFamilyBooking(); // If it's a family insurance, it should only be available for family bookings if (true === $insurance->familyInsurance && false === $isFamilyBooking) { return false; } // If it's not a family insurance, it should only be available for non-family bookings if (false === $insurance->familyInsurance && true === $isFamilyBooking) { return false; } return true; } private function checkAgeConstraints(Insurance $insurance, ParticipantDto $participant, \DateTimeImmutable $travelStartDate): bool { $participantAge = $participant->getAge($travelStartDate); // If no birth date is provided, skip age constraints (field will be hidden via field state conditions) if (null === $participantAge) { return true; } // Check minimum age if (null !== $insurance->ageFrom && $participantAge < $insurance->ageFrom) { return false; } // Check maximum age if (null !== $insurance->ageTo && $participantAge > $insurance->ageTo) { return false; } return true; } private function checkTravelDateConstraints(Insurance $insurance, \DateTimeImmutable $travelStartDate, \DateTimeImmutable $travelEndDate): bool { // Check travel start date if (null !== $insurance->travelDateFrom && $travelStartDate < $insurance->travelDateFrom) { return false; } if (null !== $insurance->travelDateTo && $travelStartDate > $insurance->travelDateTo) { return false; } // Check travel end date if (null !== $insurance->travelDateTo && $travelEndDate > $insurance->travelDateTo) { return false; } return true; } private function checkBookingDateConstraints(Insurance $insurance, \DateTimeImmutable $bookingDate): bool { // Check booking window start if (null !== $insurance->bookingDateFrom && $bookingDate < $insurance->bookingDateFrom) { return false; } // Check booking window end if (null !== $insurance->bookingDateTo && $bookingDate > $insurance->bookingDateTo) { return false; } return true; } private function checkTravelPriceConstraints(Insurance $insurance, float $travelPrice): bool { // Check minimum price if (null !== $insurance->travelPriceFrom && $travelPrice < $insurance->travelPriceFrom) { return false; } // Check maximum price if (null !== $insurance->travelPriceTo && $travelPrice > $insurance->travelPriceTo) { return false; } return true; } private function checkTravelDurationConstraints(Insurance $insurance, int $travelDurationDays): bool { // Check minimum duration if (null !== $insurance->travelDurationFrom && $travelDurationDays < $insurance->travelDurationFrom) { return false; } // Check maximum duration if (null !== $insurance->travelDurationTo && $travelDurationDays > $insurance->travelDurationTo) { return false; } return true; } }