wip: insurance booking phase 3

This commit is contained in:
Björn Fromme
2026-03-16 11:59:10 +01:00
parent 241785b428
commit 6c9da6537e
2 changed files with 495 additions and 0 deletions
+225
View File
@@ -0,0 +1,225 @@
<?php
declare(strict_types=1);
namespace App\Service;
use App\BusProNet\Model\Insurance;
use App\Form\Model\BookingCreateDto;
use App\Form\Model\ParticipantDto;
use Carbon\Carbon;
/**
* Service for matching insurances to participants based on eligibility criteria.
*
* Evaluates insurance constraints including age limits, travel dates, booking windows,
* travel price ranges, and duration limits to determine which insurances are available
* for specific participants and booking scenarios.
*/
class InsuranceMatchingService
{
/**
* Filters insurances based on participant and booking criteria.
*
* @param array<Insurance> $insurances Available insurances to filter
* @param ParticipantDto $participant The participant to match insurances for
* @param BookingCreateDto $booking The booking context for additional criteria
*
* @return array<Insurance> Filtered array of eligible insurances
*/
public function getEligibleInsurances(array $insurances, ParticipantDto $participant, BookingCreateDto $booking): array
{
$travelStartDate = $booking->travel->dateFrom;
$travelEndDate = $booking->travel->dateTo;
// Cannot match insurances without travel dates
if (null === $travelStartDate || null === $travelEndDate) {
return [];
}
$bookingDate = Carbon::now()->toDateTimeImmutable();
$travelPrice = $this->calculateTravelPrice($booking);
$travelDurationDays = $this->calculateTravelDurationDays($travelStartDate, $travelEndDate);
return array_filter($insurances, function (Insurance $insurance) use ($participant, $travelStartDate, $travelEndDate, $bookingDate, $travelPrice, $travelDurationDays) {
return $this->isInsuranceEligible($insurance, $participant, $travelStartDate, $travelEndDate, $bookingDate, $travelPrice, $travelDurationDays);
});
}
/**
* Checks if a specific insurance is eligible for a participant.
*
* @param Insurance $insurance The insurance to check
* @param ParticipantDto $participant The participant
* @param \DateTimeImmutable $travelStartDate Travel start date
* @param \DateTimeImmutable $travelEndDate Travel end date
* @param \DateTimeImmutable $bookingDate Booking date
* @param float $travelPrice Total travel price
* @param int $travelDurationDays Travel duration in days
*
* @return bool True if insurance is eligible
*/
private function isInsuranceEligible(
Insurance $insurance,
ParticipantDto $participant,
\DateTimeImmutable $travelStartDate,
\DateTimeImmutable $travelEndDate,
\DateTimeImmutable $bookingDate,
float $travelPrice,
int $travelDurationDays,
): bool {
// Age constraints
if (!$this->checkAgeConstraints($insurance, $participant, $travelStartDate)) {
return false;
}
// Travel date constraints
if (!$this->checkTravelDateConstraints($insurance, $travelStartDate, $travelEndDate)) {
return false;
}
// Booking date constraints
if (!$this->checkBookingDateConstraints($insurance, $bookingDate)) {
return false;
}
// Travel price constraints
if (!$this->checkTravelPriceConstraints($insurance, $travelPrice)) {
return false;
}
// Travel duration constraints
if (!$this->checkTravelDurationConstraints($insurance, $travelDurationDays)) {
return false;
}
return true;
}
/**
* Checks if participant age meets insurance age constraints.
*/
private function checkAgeConstraints(Insurance $insurance, ParticipantDto $participant, \DateTimeImmutable $travelStartDate): bool
{
$participantAge = $participant->getAge($travelStartDate);
if (null === $participantAge) {
return false; // Cannot determine age eligibility without birth date
}
// 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;
}
/**
* Checks if travel dates fall within insurance validity period.
*/
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;
}
/**
* Checks if booking date falls within insurance booking window.
*/
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;
}
/**
* Checks if travel price falls within insurance price range.
*/
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;
}
/**
* Checks if travel duration falls within insurance duration limits.
*/
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;
}
/**
* Calculates the total travel price from booking data.
*
* @param BookingCreateDto $booking The booking to calculate price for
*
* @return float The total travel price
*/
private function calculateTravelPrice(BookingCreateDto $booking): float
{
// For now, return 0.0 as placeholder - this will be enhanced
// when we integrate with the existing pricing calculation system
return 0.0;
}
/**
* Calculates travel duration in days.
*
* @param \DateTimeImmutable $startDate Travel start date
* @param \DateTimeImmutable $endDate Travel end date
*
* @return int Duration in days
*/
private function calculateTravelDurationDays(\DateTimeImmutable $startDate, \DateTimeImmutable $endDate): int
{
return $startDate->diff($endDate)->days;
}
}