fix: reconcile assigned family insurance rate on updated participant
This commit is contained in:
1 parent
8a46908856
commit
0b642dcfe4
11 files changed
+723
-8
No files matched your search
@@ -6,6 +6,7 @@ namespace App\BusProNet\DataProcessor;
|
||||
|
||||
use App\BusProNet\Constants;
|
||||
use App\BusProNet\Model\Booking;
|
||||
use App\BusProNet\Model\Insurance;
|
||||
use App\BusProNet\Model\Travel;
|
||||
use App\BusProNet\Utility\DirectionMapper;
|
||||
use App\BusProNet\XmlLoader\AgencyLoader;
|
||||
@@ -362,12 +363,97 @@ class BookingDataProcessor
|
||||
*/
|
||||
public function createBookingRequestPayload(BookingDto $bookingDto, string $bookingType): array
|
||||
{
|
||||
// Re-validate each participant's insurance against current eligibility (price tier,
|
||||
// family constraint, etc.) before submission - selections can go stale between the
|
||||
// moment they were chosen and final submission, since users can freely revisit
|
||||
// earlier steps and change composition/services without ever re-opening the
|
||||
// insurance field. Must run before the applicant-to-dependents propagation below,
|
||||
// so that propagation is based on an already-corrected applicant selection.
|
||||
$this->reconcileInsuranceEligibility($bookingDto);
|
||||
|
||||
// Apply bulk or family insurance if applicable (modifies DTO in place)
|
||||
$this->applyApplicantInsuranceToParticipants($bookingDto);
|
||||
|
||||
return $this->payloadBuilder->buildCreatePayload($bookingDto, $bookingType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-validates every participant's currently selected insurance against present-day
|
||||
* eligibility (price tier, family constraint, age, travel/booking dates, duration) and
|
||||
* corrects any selection that's gone stale.
|
||||
*
|
||||
* Insurance eligibility is normally re-checked when a participant's own card is
|
||||
* resubmitted (see ParticipantInsuranceFieldHandler::processField()), but nothing forces
|
||||
* that to happen again if the user changes composition or services on an earlier step
|
||||
* after insurance was already chosen, then jumps straight to submission. Left unchecked,
|
||||
* a stale insurance ID (e.g. a family-tariff price tier that no longer matches the
|
||||
* current total booking price) would reach the BPN API and be rejected as a mismatch.
|
||||
*
|
||||
* Mirrors the reassign-or-clear logic already established in
|
||||
* ParticipantInsuranceFieldHandler for the resubmission case, applied here across all
|
||||
* participants right before the payload is built.
|
||||
*/
|
||||
private function reconcileInsuranceEligibility(BookingDto $bookingDto): bool
|
||||
{
|
||||
$selectableInsurances = $this->insuranceService->getSelectableInsurances($bookingDto->travel);
|
||||
$changed = false;
|
||||
|
||||
foreach ($bookingDto->getParticipants() as $index => $participant) {
|
||||
$currentInsurance = $participant->insurance;
|
||||
if (null === $currentInsurance || $currentInsurance->isNoInsurance()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$travelPrice = $this->priceCalculatorService->resolveInsuranceTravelPrice($bookingDto, $index, $currentInsurance);
|
||||
$eligibleInsurances = $this->insuranceService->getEligibleInsurances($selectableInsurances, $participant, $bookingDto, $travelPrice);
|
||||
|
||||
if ($this->isInsuranceInList($currentInsurance, $eligibleInsurances)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$reassignedInsurance = $this->insuranceService->reassignInsuranceForPriceChange(
|
||||
$selectableInsurances,
|
||||
$currentInsurance,
|
||||
$participant,
|
||||
$bookingDto,
|
||||
$travelPrice
|
||||
);
|
||||
|
||||
if (null !== $reassignedInsurance) {
|
||||
$participant->addNotification(
|
||||
'warning',
|
||||
sprintf('Versicherung vor der Übermittlung automatisch angepasst: %s', $reassignedInsurance->label)
|
||||
);
|
||||
} else {
|
||||
$participant->addNotification(
|
||||
'warning',
|
||||
'Die gewählte Versicherung ist für diese Buchung nicht mehr verfügbar und wurde entfernt. Bitte erneut auswählen.'
|
||||
);
|
||||
}
|
||||
|
||||
$participant->insurance = $reassignedInsurance;
|
||||
$changed = true;
|
||||
}
|
||||
|
||||
return $changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a specific insurance exists in a list of insurances (by id).
|
||||
*
|
||||
* @param array<Insurance> $insuranceList
|
||||
*/
|
||||
private function isInsuranceInList(Insurance $targetInsurance, array $insuranceList): bool
|
||||
{
|
||||
foreach ($insuranceList as $insurance) {
|
||||
if ($insurance->id === $targetInsurance->id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the applicant's insurance to other participants if their selection requires it.
|
||||
*
|
||||
|
||||
Reference in new issue
Block a user