wip: insurance booking
This commit is contained in:
@@ -359,7 +359,7 @@ class BookingPriceCalculatorService
|
||||
if ($parkingTotal > 0) {
|
||||
$transportationItems['transportation_parking'] = [
|
||||
'serviceId' => 'transportation_parking',
|
||||
'label' => 'Parkplatz',
|
||||
'label' => Constants::SERVICE_LABELS[Constants::TOKEN_PARKING],
|
||||
'unitPrice' => null,
|
||||
'participantCount' => $parkingParticipants,
|
||||
'totalPrice' => $parkingTotal,
|
||||
@@ -444,23 +444,12 @@ class BookingPriceCalculatorService
|
||||
*/
|
||||
private function getGroupNameForSubtype(string $subType): string
|
||||
{
|
||||
$groupMapping = [
|
||||
Constants::TOKEN_COURSES => 'Kurse',
|
||||
Constants::TOKEN_SKI_PASS => 'Skipässe',
|
||||
Constants::TOKEN_ADDITIONAL => 'Zusatzleistungen',
|
||||
Constants::TOKEN_BOARD => 'Verpflegung',
|
||||
Constants::TOKEN_RENTAL_INSURANCE => 'Leihmaterial-Versicherung',
|
||||
Constants::GROUP_TRANSPORTATION => 'Beförderung',
|
||||
Constants::GROUP_RENTALS => 'Leihmaterial', // Normalized rental subtype
|
||||
Constants::GROUP_INSURANCE => 'Reiseversicherungen', // Normalized insurance subtype
|
||||
];
|
||||
|
||||
// Handle rentals array (keep for backward compatibility with non-normalized subtypes)
|
||||
if (true === in_array($subType, Constants::TOKEN_RENTALS, true)) {
|
||||
return 'Leihmaterial';
|
||||
return Constants::SERVICE_LABELS[Constants::GROUP_RENTALS];
|
||||
}
|
||||
|
||||
return $groupMapping[$subType] ?? 'Sonstige Leistungen';
|
||||
return Constants::SERVICE_LABELS[$subType] ?? 'Sonstige Leistungen';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -525,8 +514,8 @@ class BookingPriceCalculatorService
|
||||
/**
|
||||
* Calculates the total service cost for a single participant.
|
||||
*
|
||||
* @param ParticipantDto $participant The participant to calculate services for
|
||||
* @param bool $includeInsurance Whether to include insurance pricing (default: true)
|
||||
* @param ParticipantDto $participant The participant to calculate services for
|
||||
* @param bool $includeInsurance Whether to include insurance pricing (default: true)
|
||||
*
|
||||
* @return float The total service cost for this participant
|
||||
*/
|
||||
@@ -612,7 +601,7 @@ class BookingPriceCalculatorService
|
||||
*
|
||||
* @param array $serviceAggregation The service aggregation array to update
|
||||
* @param Insurance $insurance The insurance to add
|
||||
* @param int $quantity The quantity of the insurance
|
||||
* @param int $quantity The quantity of the insurance
|
||||
*/
|
||||
private function addInsuranceToServiceAggregation(array &$serviceAggregation, Insurance $insurance, int $quantity): void
|
||||
{
|
||||
|
||||
@@ -8,8 +8,6 @@ use App\BusProNet\Model\Insurance;
|
||||
use App\Form\Model\BookingCreateDto;
|
||||
use App\Form\Model\ParticipantDto;
|
||||
use App\Model\InsuranceEligibilityCriteria;
|
||||
use App\Service\BookingPriceCalculatorService;
|
||||
use App\Service\InsuranceTypeResolver;
|
||||
use Carbon\Carbon;
|
||||
|
||||
/**
|
||||
@@ -23,9 +21,9 @@ class InsuranceMatchingService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly BookingPriceCalculatorService $priceCalculatorService,
|
||||
private readonly InsuranceTypeResolver $insuranceTypeResolver
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters insurances based on participant and booking criteria.
|
||||
*
|
||||
@@ -78,6 +76,10 @@ class InsuranceMatchingService
|
||||
/**
|
||||
* Batch-assigns insurances of the same type to all participants based on individual pricing.
|
||||
*
|
||||
* FUTURE FEATURE: This method will be used when implementing the "applicant assigns
|
||||
* insurance to all participants" feature. The applicant's selection will be propagated
|
||||
* to all participants with automatic price tier adjustment based on individual prices.
|
||||
*
|
||||
* This method takes the applicant's insurance selection and assigns the same insurance type
|
||||
* (subType + familyInsurance) to all participants, but selects the appropriate price tier
|
||||
* based on each participant's individual travel price.
|
||||
@@ -87,6 +89,8 @@ class InsuranceMatchingService
|
||||
* @param BookingCreateDto $booking The booking with all participants
|
||||
*
|
||||
* @return array<int, Insurance|null> Array indexed by participant index with assigned insurances
|
||||
*
|
||||
* @internal Reserved for future feature implementation
|
||||
*/
|
||||
public function batchAssignInsuranceToParticipants(array $availableInsurances, Insurance $selectedInsurance, BookingCreateDto $booking): array
|
||||
{
|
||||
@@ -106,9 +110,13 @@ class InsuranceMatchingService
|
||||
|
||||
/**
|
||||
* Creates eligibility criteria from participant and booking data.
|
||||
*
|
||||
* This method performs early validation before creating the criteria object
|
||||
* to avoid unnecessary object instantiation when criteria cannot be satisfied.
|
||||
*/
|
||||
private function createEligibilityCriteria(ParticipantDto $participant, BookingCreateDto $booking): ?InsuranceEligibilityCriteria
|
||||
{
|
||||
// Early return if travel dates are missing - cannot evaluate any criteria
|
||||
$travelStartDate = $booking->travel->dateFrom;
|
||||
$travelEndDate = $booking->travel->dateTo;
|
||||
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\BusProNet\Model\Insurance;
|
||||
|
||||
/**
|
||||
* Resolves insurance types for both individual insurances and packages.
|
||||
*
|
||||
* This service provides consistent type resolution by mapping insurance subtypes
|
||||
* to standardized type constants. For packages, it analyzes contained insurances
|
||||
* to determine the dominant (non-deductible) type and applies family variants
|
||||
* based on the familyInsurance flag.
|
||||
*/
|
||||
class InsuranceTypeResolver
|
||||
{
|
||||
public const TRAVEL_CANCELLATION = 'TRAVEL_CANCELLATION';
|
||||
public const TRAVEL_CANCELLATION_FAMILY = 'TRAVEL_CANCELLATION_FAMILY';
|
||||
public const TRAVEL_PROTECTION = 'TRAVEL_PROTECTION';
|
||||
public const TRAVEL_PROTECTION_FAMILY = 'TRAVEL_PROTECTION_FAMILY';
|
||||
public const DEDUCTIBLE = 'DEDUCTIBLE';
|
||||
|
||||
/**
|
||||
* Resolves the standardized type for an insurance or package.
|
||||
*
|
||||
* @param Insurance $insurance The insurance to resolve the type for
|
||||
*
|
||||
* @return string|null The resolved type constant or null if unresolvable
|
||||
*/
|
||||
public function resolveType(Insurance $insurance): ?string
|
||||
{
|
||||
if (!$insurance->package) {
|
||||
return $this->mapSubtypeToType($insurance->subType, $insurance->familyInsurance);
|
||||
}
|
||||
|
||||
return $this->resolvePackageType($insurance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the type for an insurance package by analyzing contained insurances.
|
||||
*
|
||||
* @param Insurance $package The package to analyze
|
||||
*
|
||||
* @return string|null The resolved type or null if no primary type found
|
||||
*/
|
||||
private function resolvePackageType(Insurance $package): ?string
|
||||
{
|
||||
// Get primary (non-deductible) insurance type from contained insurances
|
||||
$primaryType = null;
|
||||
foreach ($package->containedInsurances as $contained) {
|
||||
$baseType = $this->mapSubtypeToBaseType($contained->subType);
|
||||
if ($baseType && self::DEDUCTIBLE !== $baseType) {
|
||||
$primaryType = $baseType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply family suffix using package's familyInsurance flag
|
||||
return $primaryType ? $primaryType.($package->familyInsurance ? '_FAMILY' : '') : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a subtype to a full type including family variant.
|
||||
*
|
||||
* @param string|null $subtype The subtype to map
|
||||
* @param bool $isFamily Whether this is a family insurance
|
||||
*
|
||||
* @return string|null The mapped type or null if unmappable
|
||||
*/
|
||||
private function mapSubtypeToType(?string $subtype, bool $isFamily): ?string
|
||||
{
|
||||
$baseType = $this->mapSubtypeToBaseType($subtype);
|
||||
|
||||
return $baseType ? $baseType.($isFamily ? '_FAMILY' : '') : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a subtype to its base type constant.
|
||||
*
|
||||
* @param string|null $subtype The subtype to map
|
||||
*
|
||||
* @return string|null The base type constant or null if unmappable
|
||||
*/
|
||||
private function mapSubtypeToBaseType(?string $subtype): ?string
|
||||
{
|
||||
return match ($subtype) {
|
||||
'RRV' => self::TRAVEL_CANCELLATION,
|
||||
'PAK' => self::TRAVEL_PROTECTION,
|
||||
'OHN' => self::DEDUCTIBLE,
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all available insurance type constants.
|
||||
*
|
||||
* @return array<string> Array of all type constants
|
||||
*/
|
||||
public function getAllTypes(): array
|
||||
{
|
||||
return [
|
||||
self::TRAVEL_CANCELLATION,
|
||||
self::TRAVEL_CANCELLATION_FAMILY,
|
||||
self::TRAVEL_PROTECTION,
|
||||
self::TRAVEL_PROTECTION_FAMILY,
|
||||
self::DEDUCTIBLE,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a type is a family variant.
|
||||
*
|
||||
* @param string $type The type to check
|
||||
*
|
||||
* @return bool True if the type is a family variant
|
||||
*/
|
||||
public function isFamilyType(string $type): bool
|
||||
{
|
||||
return str_ends_with($type, '_FAMILY');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the base type from a family type.
|
||||
*
|
||||
* @param string $type The type to get the base for
|
||||
*
|
||||
* @return string The base type (without _FAMILY suffix)
|
||||
*/
|
||||
public function getBaseType(string $type): string
|
||||
{
|
||||
return str_replace('_FAMILY', '', $type);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user