From cb38beb32c46f8d22467e4586e50e791c20bc8fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Thu, 13 Nov 2025 09:30:49 +0100 Subject: [PATCH] feat: surcharges and discounts per participant and in summary --- src/Service/BookingPriceCalculatorService.php | 42 ++++++++++++++++++- src/Service/ParticipantCardDataService.php | 25 +++++++++++ templates/booking/_summary.html.twig | 19 +++++++++ 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/src/Service/BookingPriceCalculatorService.php b/src/Service/BookingPriceCalculatorService.php index 8337ce4..8d6ce35 100644 --- a/src/Service/BookingPriceCalculatorService.php +++ b/src/Service/BookingPriceCalculatorService.php @@ -42,11 +42,26 @@ class BookingPriceCalculatorService $servicePricing = $this->calculateServicePricing($bookingDto); $grandTotal = $this->calculateGrandTotal($bookingDto); - return [ + $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; } /** @@ -225,6 +240,31 @@ class BookingPriceCalculatorService return array_sum(array_column($servicePricing, 'groupTotal')); } + /** + * 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. * diff --git a/src/Service/ParticipantCardDataService.php b/src/Service/ParticipantCardDataService.php index 296954a..9066fc8 100644 --- a/src/Service/ParticipantCardDataService.php +++ b/src/Service/ParticipantCardDataService.php @@ -120,6 +120,31 @@ class ParticipantCardDataService */ private function getFormattedPrice(BookingDto $bookingDto, int $index): string { + // Check if canceled (only possible in edit mode when booking property is set) + $isCanceled = ($bookingDto->booking?->participantsStatus[$index] ?? null) === 'S'; + + if (true === $isCanceled) { + // Calculate surcharge total for canceled participant + if (null === $bookingDto->booking) { + return '-'; + } + + $surcharges = $bookingDto->booking->getSurchargesForParticipant($index); + $surchargeTotal = 0.0; + + foreach ($surcharges as $surcharge) { + $surchargeTotal += $surcharge->individualPrice[$index] ?? 0.0; + } + + // Show nothing if no surcharges, otherwise show "x,xx € Stornokosten" + if (0.0 === $surchargeTotal) { + return '-'; + } + + return number_format($surchargeTotal, 2, ',', '.').' € Stornokosten'; + } + + // For active participants: existing price calculation logic $prices = $this->priceCalculator->calculateAllParticipantIndividualPrices($bookingDto); $price = $prices[$index] ?? 0.0; diff --git a/templates/booking/_summary.html.twig b/templates/booking/_summary.html.twig index 710abfe..323adbf 100644 --- a/templates/booking/_summary.html.twig +++ b/templates/booking/_summary.html.twig @@ -105,6 +105,25 @@ {% endif %} + {# Surcharges Section (Edit mode only) #} + {% if pricingData.surcharges is defined and pricingData.surcharges is not empty %} +
+

Zuschläge

+
+ {% for surchargePricing in pricingData.surcharges %} +
+ + {{ surchargePricing.participantCount }}x {{ surchargePricing.label }} + + + €{{ surchargePricing.totalPrice|number_format(2, ',', '.') }} + +
+ {% endfor %} +
+
+ {% endif %} + {# Total Section #} {% if pricingData.grandTotal is defined and pricingData.grandTotal > 0 %}