wip: modernized edit flow

This commit is contained in:
Björn Fromme
2025-10-08 21:09:53 +02:00
parent c3008d7f7a
commit cba0f747cd
75 changed files with 1662 additions and 747 deletions
+67 -27
View File
@@ -9,7 +9,7 @@ use App\BusProNet\Model\Insurance;
use App\BusProNet\Model\Room;
use App\BusProNet\Model\Service;
use App\Form\Model\BookingCreateDto;
use App\Form\Model\BookingDtoInterface;
use App\Form\Model\BookingDto;
use App\Form\Model\ParticipantDto;
/**
@@ -22,17 +22,18 @@ use App\Form\Model\ParticipantDto;
class BookingPriceCalculatorService
{
public function __construct(
private readonly ParticipantEligibilityService $participantEligibilityService
private readonly ParticipantEligibilityService $participantEligibilityService,
) {
}
/**
* Calculates comprehensive pricing breakdown for a booking.
*
* @param BookingDtoInterface $bookingDto The booking data to calculate pricing for
* @param BookingDto $bookingDto The booking data to calculate pricing for
*
* @return array{rooms: array, services: array, grandTotal: float} Complete pricing breakdown
*/
public function getPricingBreakdown(BookingDtoInterface $bookingDto): array
public function getPricingBreakdown(BookingDto $bookingDto): array
{
$roomPricing = $this->calculateRoomPricing($bookingDto);
$servicePricing = $this->calculateServicePricing($bookingDto);
@@ -48,11 +49,11 @@ class BookingPriceCalculatorService
/**
* Calculates pricing for all selected rooms.
*
* @param BookingDtoInterface $bookingDto The booking data containing room selections
* @param BookingDto $bookingDto The booking data containing room selections
*
* @return array Array of room pricing data with labels, quantities, and totals
*/
public function calculateRoomPricing(BookingDtoInterface $bookingDto): array
public function calculateRoomPricing(BookingDto $bookingDto): array
{
$roomPricing = [];
@@ -95,11 +96,11 @@ class BookingPriceCalculatorService
*
* Only includes services from eligible participants (those with available skipasses for their age).
*
* @param BookingDtoInterface $bookingDto The booking data containing participants and their service selections
* @param BookingDto $bookingDto The booking data containing participants and their service selections
*
* @return array Array of service groups with each group containing services of the same subtype
*/
public function calculateServicePricing(BookingDtoInterface $bookingDto): array
public function calculateServicePricing(BookingDto $bookingDto): array
{
$participants = $bookingDto->getParticipants();
@@ -132,11 +133,11 @@ class BookingPriceCalculatorService
/**
* Calculates the grand total for the entire booking.
*
* @param BookingDtoInterface $bookingDto The booking data to calculate total for
* @param BookingDto $bookingDto The booking data to calculate total for
*
* @return float The grand total price
*/
public function calculateGrandTotal(BookingDtoInterface $bookingDto): float
public function calculateGrandTotal(BookingDto $bookingDto): float
{
$roomTotal = $this->calculateRoomTotal($bookingDto);
$serviceTotal = $this->calculateServiceTotal($bookingDto);
@@ -147,7 +148,7 @@ class BookingPriceCalculatorService
/**
* Calculates total price for all rooms.
*/
public function calculateRoomTotal(BookingDtoInterface $bookingDto): float
public function calculateRoomTotal(BookingDto $bookingDto): float
{
$roomPricing = $this->calculateRoomPricing($bookingDto);
@@ -157,7 +158,7 @@ class BookingPriceCalculatorService
/**
* Calculates total price for all services.
*/
public function calculateServiceTotal(BookingDtoInterface $bookingDto): float
public function calculateServiceTotal(BookingDto $bookingDto): float
{
$servicePricing = $this->calculateServicePricing($bookingDto);
@@ -194,12 +195,12 @@ class BookingPriceCalculatorService
* This method calculates the complete price breakdown for a single participant,
* including their room allocation (full room price) and all selected services.
*
* @param BookingDtoInterface $bookingDto The booking data containing all participants
* @param BookingDto $bookingDto The booking data containing all participants
* @param int $participantIndex The index of the participant to calculate for
*
* @return float The total price for the specified participant
*/
public function calculateIndividualParticipantPrice(BookingDtoInterface $bookingDto, int $participantIndex): float
public function calculateIndividualParticipantPrice(BookingDto $bookingDto, int $participantIndex): float
{
if (false === $bookingDto instanceof BookingCreateDto) {
return 0.0;
@@ -221,8 +222,8 @@ class BookingPriceCalculatorService
}
}
// Add service prices for this participant
$totalPrice += $this->calculateParticipantServiceTotal($participant);
// Add service prices for this participant (with booking context for bulk insurance)
$totalPrice += $this->calculateParticipantServiceTotal($participant, true, $bookingDto);
return $totalPrice;
}
@@ -230,11 +231,11 @@ class BookingPriceCalculatorService
/**
* Calculates individual prices for all participants in a booking.
*
* @param BookingDtoInterface $bookingDto The booking data containing all participants
* @param BookingDto $bookingDto The booking data containing all participants
*
* @return array Array indexed by participant index containing individual prices
*/
public function calculateAllParticipantIndividualPrices(BookingDtoInterface $bookingDto): array
public function calculateAllParticipantIndividualPrices(BookingDto $bookingDto): array
{
if (false === $bookingDto instanceof BookingCreateDto) {
return [];
@@ -256,12 +257,12 @@ class BookingPriceCalculatorService
* This method is used for insurance eligibility filtering to avoid circular dependency
* where insurance selection affects travel price which affects insurance eligibility.
*
* @param BookingDtoInterface $bookingDto The booking data containing all participants
* @param BookingDto $bookingDto The booking data containing all participants
* @param int $participantIndex The index of the participant to calculate for
*
* @return float The total price for the specified participant excluding insurance
*/
public function calculateIndividualParticipantPriceExcludingInsurance(BookingDtoInterface $bookingDto, int $participantIndex): float
public function calculateIndividualParticipantPriceExcludingInsurance(BookingDto $bookingDto, int $participantIndex): float
{
if (false === $bookingDto instanceof BookingCreateDto) {
return 0.0;
@@ -300,11 +301,11 @@ class BookingPriceCalculatorService
*
* Note: Transportation discounts will be handled generically by groupServicesBySubtype as "Beförderung - Rabatt"
*
* @param BookingDtoInterface $bookingDto The booking data containing participants
* @param BookingDto $bookingDto The booking data containing participants
*
* @return array Array of transportation line items (Zustieg, Parkplatz)
*/
private function aggregateTransportationServices(BookingDtoInterface $bookingDto): array
private function aggregateTransportationServices(BookingDto $bookingDto): array
{
$participants = $bookingDto->getParticipants();
@@ -527,12 +528,13 @@ 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)
* @param BookingDto|null $bookingDto Optional booking DTO for bulk insurance resolution
*
* @return float The total service cost for this participant
*/
private function calculateParticipantServiceTotal(ParticipantDto $participant, bool $includeInsurance = true): float
private function calculateParticipantServiceTotal(ParticipantDto $participant, bool $includeInsurance = true, ?BookingDto $bookingDto = null): float
{
$serviceTotal = 0.0;
@@ -545,8 +547,10 @@ class BookingPriceCalculatorService
$serviceTotal += $participant->rentalInsurance->price;
}
if ($includeInsurance && null !== $participant->insurance && null !== $participant->insurance->price) {
$serviceTotal += $participant->insurance->price;
// Get effective insurance (considering bulk insurance for dependent participants)
$effectiveInsurance = $this->getEffectiveInsurance($participant, $bookingDto);
if ($includeInsurance && null !== $effectiveInsurance && null !== $effectiveInsurance->price) {
$serviceTotal += $effectiveInsurance->price;
}
// Transportation services
@@ -630,4 +634,40 @@ class BookingPriceCalculatorService
$serviceAggregation[$serviceKey]['participantCount'] += $quantity;
$serviceAggregation[$serviceKey]['totalPrice'] += $insurance->price * $quantity;
}
/**
* Gets the effective insurance for a participant, considering bulk insurance assignment.
*
* When bulk insurance is active and the participant is a dependent (index > 0),
* returns the applicant's insurance. Otherwise returns the participant's own insurance.
*
* This method is used for pricing calculations to show correct prices when bulk
* insurance is enabled, even though the actual assignment happens in the processor.
*
* @param ParticipantDto $participant The participant to get insurance for
* @param BookingDto|null $bookingDto Optional booking DTO for bulk insurance check
*
* @return Insurance|null The effective insurance for pricing purposes
*/
private function getEffectiveInsurance(ParticipantDto $participant, ?BookingDto $bookingDto): ?Insurance
{
// If no booking context, use participant's own insurance
if (null === $bookingDto) {
return $participant->insurance;
}
// Applicant always uses their own insurance
if (0 === $participant->index) {
return $participant->insurance;
}
// Check if bulk insurance is active
$applicant = $bookingDto->getParticipant(0);
if (null === $applicant || false === $applicant->bulkInsuranceBooking) {
return $participant->insurance;
}
// Bulk insurance is active - use applicant's insurance for dependent participants
return $applicant->insurance;
}
}