feat: indicate family insurance eligibility
This commit is contained in:
1 parent
0b642dcfe4
commit
2cfa87f44b
12 files changed
+327
-234
No files matched your search
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\BusProNet\Model\Insurance;
|
||||
use App\Form\Model\BookingDto;
|
||||
|
||||
/**
|
||||
* Single source of truth for "the applicant could still upgrade to a family insurance".
|
||||
*
|
||||
* Participants are entered one card at a time, applicant first, so at the moment the
|
||||
* applicant has to pick an insurance the family constellation is not yet known and no
|
||||
* family insurance can be offered. Only the applicant may hold a family insurance, so
|
||||
* without a standing hint the opportunity is silently lost once the dependents' dates
|
||||
* of birth make the booking eligible.
|
||||
*
|
||||
* This is deliberately a derived predicate rather than a one-time event: it stays true
|
||||
* for as long as the applicant can still act on it and disappears by itself once they
|
||||
* switch to a family insurance, deliberately pick something else while eligible, or the
|
||||
* constellation stops qualifying.
|
||||
*/
|
||||
class FamilyInsuranceAvailabilityChecker
|
||||
{
|
||||
public function __construct(
|
||||
private readonly InsuranceManager $insuranceService,
|
||||
private readonly BookingPriceCalculator $priceCalculatorService,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the applicant should be pointed at a family insurance they cannot have
|
||||
* chosen earlier.
|
||||
*
|
||||
* Requires `applicantInsuranceChosenWhileFamilyIneligible` - i.e. the standing choice
|
||||
* was actually made before family insurance was possible - so an applicant who was
|
||||
* offered a family insurance and picked something else is not nagged about it.
|
||||
*/
|
||||
public function isFamilyInsuranceUpgradeAvailable(BookingDto $bookingDto): bool
|
||||
{
|
||||
if (false === $bookingDto->applicantInsuranceChosenWhileFamilyIneligible) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$applicant = $bookingDto->getParticipant(0);
|
||||
|
||||
if (null === $applicant || null === $applicant->insurance || true === $applicant->insurance->familyInsurance) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->hasEligibleFamilyInsurance($bookingDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a family insurance is actually eligible right now - not just whether
|
||||
* the participant composition qualifies as a family booking, but whether a selectable
|
||||
* family insurance product actually matches the current total booking price.
|
||||
*/
|
||||
public function hasEligibleFamilyInsurance(BookingDto $bookingDto): bool
|
||||
{
|
||||
if (false === $bookingDto->isFamilyBooking()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$applicant = $bookingDto->getParticipant(0);
|
||||
if (null === $applicant) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$selectableInsurances = $this->insuranceService->getSelectableInsurances($bookingDto->travel);
|
||||
$familyInsurances = array_values(array_filter($selectableInsurances, static fn (Insurance $i) => true === $i->familyInsurance));
|
||||
|
||||
if ([] === $familyInsurances) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$totalPrice = $this->priceCalculatorService->calculateTotalBookingPriceExcludingInsurance($bookingDto);
|
||||
|
||||
return [] !== $this->insuranceService->getEligibleInsurances($familyInsurances, $applicant, $bookingDto, $totalPrice);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user