roomPricingCalculator->calculateRoomPricing($bookingDto); $servicePricing = $this->servicePricingCalculator->calculateServicePricing($bookingDto); $grandTotal = $this->calculateGrandTotal($bookingDto); $result = [ 'rooms' => $roomPricing, 'services' => $servicePricing, 'grandTotal' => $grandTotal, ]; // Add surcharges if in edit mode with booking data if (null !== $bookingDto->booking && [] !== $bookingDto->booking->surcharges) { $surchargePricing = $this->calculateSurchargePricing($bookingDto->booking); if ([] !== $surchargePricing) { $result['surcharges'] = $surchargePricing; // Add surcharge total to grand total $surchargeTotal = array_sum(array_column($surchargePricing, 'totalPrice')); $result['grandTotal'] += $surchargeTotal; } } return $result; } /** * Calculates pricing for all selected rooms. * * @param BookingDto $bookingDto The booking data containing room selections * * @return array Array of room pricing data with labels, quantities, and totals */ public function calculateRoomPricing(BookingDto $bookingDto): array { return $this->roomPricingCalculator->calculateRoomPricing($bookingDto); } /** * Calculates pricing for all selected services across all participants, grouped by subtype. * * Only includes services from eligible participants (those with available skipasses for their age). * * @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(BookingDto $bookingDto): array { return $this->servicePricingCalculator->calculateServicePricing($bookingDto); } /** * Calculates the grand total for the entire booking. * * @param BookingDto $bookingDto The booking data to calculate total for * * @return float The grand total price */ public function calculateGrandTotal(BookingDto $bookingDto): float { $roomTotal = $this->roomPricingCalculator->calculateRoomTotal($bookingDto); $serviceTotal = $this->servicePricingCalculator->calculateServiceTotal($bookingDto); return $roomTotal + $serviceTotal; } /** * Calculates total price for all rooms. */ public function calculateRoomTotal(BookingDto $bookingDto): float { return $this->roomPricingCalculator->calculateRoomTotal($bookingDto); } /** * Calculates total price for all services. */ public function calculateServiceTotal(BookingDto $bookingDto): float { return $this->servicePricingCalculator->calculateServiceTotal($bookingDto); } /** * Calculates surcharge pricing grouped by label (edit mode only). * * Returns surcharges in a format similar to services for display in summary. * Groups surcharges by label and counts participant assignments. * * @param \App\BusProNet\Model\Booking $bookingData The booking entity with surcharge information * * @return array Array of surcharge data with labels, counts, and totals */ public function calculateSurchargePricing(\App\BusProNet\Model\Booking $bookingData): array { $surchargePricing = []; foreach ($bookingData->surcharges as $surcharge) { $surchargePricing[] = [ 'label' => $surcharge->label ?? 'unbekannt', 'participantCount' => count($surcharge->mapping), 'totalPrice' => $surcharge->totalPrice ?? 0.0, ]; } return $surchargePricing; } /** * Formats a price value for display with proper German formatting. * * @param float $price The price to format * * @return string Formatted price string (e.g., "123,45") */ public function formatPrice(float $price): string { return number_format($price, 2, ',', '.'); } /** * Formats a price with Euro symbol for display. * * @param float $price The price to format * * @return string Formatted price string with Euro symbol (e.g., "€123,45") */ public function formatPriceWithSymbol(float $price): string { return '€'.$this->formatPrice($price); } /** * Calculates the total price for an individual participant. * * This method calculates the complete price breakdown for a single participant, * including their room allocation (full room price) and all selected services. * * @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(BookingDto $bookingDto, int $participantIndex): float { return $this->participantPricingCalculator->calculateIndividualParticipantPrice($bookingDto, $participantIndex); } /** * Calculates individual prices for all participants in a booking. * * @param BookingDto $bookingDto The booking data containing all participants * * @return array Array indexed by participant index containing individual prices */ public function calculateAllParticipantIndividualPrices(BookingDto $bookingDto): array { return $this->participantPricingCalculator->calculateAllParticipantIndividualPrices($bookingDto); } /** * Calculates the total price for an individual participant excluding insurance. * * This method is used for insurance eligibility filtering to avoid circular dependency * where insurance selection affects travel price which affects insurance eligibility. * * Only includes services where versicherungsberechnung='J' in the XML. Services with * versicherungsberechnung='N' (like CO2 compensation) are excluded from the calculation * as per BPN API requirements for insurance tier determination. * * @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 and non-calculated services */ public function calculateIndividualParticipantPriceExcludingInsurance( BookingDto $bookingDto, int $participantIndex, ): float { return $this->participantPricingCalculator->calculateIndividualParticipantPriceExcludingInsurance( $bookingDto, $participantIndex ); } }