feat: surcharges and discounts per participant and in summary
This commit is contained in:
@@ -42,11 +42,26 @@ class BookingPriceCalculatorService
|
|||||||
$servicePricing = $this->calculateServicePricing($bookingDto);
|
$servicePricing = $this->calculateServicePricing($bookingDto);
|
||||||
$grandTotal = $this->calculateGrandTotal($bookingDto);
|
$grandTotal = $this->calculateGrandTotal($bookingDto);
|
||||||
|
|
||||||
return [
|
$result = [
|
||||||
'rooms' => $roomPricing,
|
'rooms' => $roomPricing,
|
||||||
'services' => $servicePricing,
|
'services' => $servicePricing,
|
||||||
'grandTotal' => $grandTotal,
|
'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'));
|
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.
|
* Formats a price value for display with proper German formatting.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -120,6 +120,31 @@ class ParticipantCardDataService
|
|||||||
*/
|
*/
|
||||||
private function getFormattedPrice(BookingDto $bookingDto, int $index): string
|
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);
|
$prices = $this->priceCalculator->calculateAllParticipantIndividualPrices($bookingDto);
|
||||||
|
|
||||||
$price = $prices[$index] ?? 0.0;
|
$price = $prices[$index] ?? 0.0;
|
||||||
|
|||||||
@@ -105,6 +105,25 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{# Surcharges Section (Edit mode only) #}
|
||||||
|
{% if pricingData.surcharges is defined and pricingData.surcharges is not empty %}
|
||||||
|
<div class="mb-6 pb-4 border-b border-gray-200">
|
||||||
|
<h4 class="font-semibold text-lg mb-3 text-gray-800">Zuschläge</h4>
|
||||||
|
<div class="space-y-1">
|
||||||
|
{% for surchargePricing in pricingData.surcharges %}
|
||||||
|
<div class="flex justify-between items-center text-sm">
|
||||||
|
<span class="text-gray-600">
|
||||||
|
{{ surchargePricing.participantCount }}x {{ surchargePricing.label }}
|
||||||
|
</span>
|
||||||
|
<span class="font-medium text-gray-900">
|
||||||
|
€{{ surchargePricing.totalPrice|number_format(2, ',', '.') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{# Total Section #}
|
{# Total Section #}
|
||||||
{% if pricingData.grandTotal is defined and pricingData.grandTotal > 0 %}
|
{% if pricingData.grandTotal is defined and pricingData.grandTotal > 0 %}
|
||||||
<div class="pt-4 border-t-2 border-gray-300">
|
<div class="pt-4 border-t-2 border-gray-300">
|
||||||
|
|||||||
Reference in New Issue
Block a user