feat: finalize voucher handling and discount display in summary and overview

This commit is contained in:
Björn Fromme
2026-03-16 11:59:12 +01:00
parent 2e40cbc7c7
commit 230c53875f
15 changed files with 762 additions and 46 deletions
+60 -1
View File
@@ -77,6 +77,65 @@ class BookingDto
{
}
/**
* Builds AcceptedVouchers from validated participant voucher data.
*
* Computes voucher discounts from validated vouchers stored on participants.
* This allows displaying voucher savings as soon as vouchers are validated
* in Step 2, rather than waiting for Step 3 API confirmation.
*
* For promo vouchers with percentage discounts, we need the participant price
* to calculate the actual discount amount.
*
* @param array<int, float>|null $participantPrices Prices per participant index for percentage calculation
*/
public function getAcceptedVouchers(?array $participantPrices = null): ?AcceptedVouchersDto
{
$acceptedVouchers = new AcceptedVouchersDto();
$processedPromoCodes = [];
foreach ($this->participants as $index => $participant) {
// Process purchase voucher
if (null !== $participant->validatedPurchaseVoucher) {
$voucher = $participant->validatedPurchaseVoucher;
$acceptedVouchers->addVoucher(new AcceptedVoucherDto(
type: $voucher->isGoodwill() ? AcceptedVoucherDto::TYPE_GOODWILL : AcceptedVoucherDto::TYPE_PURCHASE,
code: $voucher->voucherNumber,
amount: $voucher->remainingBalance,
description: $voucher->isGoodwill() ? 'Kulanzgutschein' : 'Kaufgutschein',
));
}
// Process promo voucher
if (null !== $participant->validatedPromoVoucher) {
$voucher = $participant->validatedPromoVoucher;
// For per-booking vouchers, only count once
if ($voucher->isPerBooking()) {
if (isset($processedPromoCodes[$voucher->code])) {
continue;
}
$processedPromoCodes[$voucher->code] = true;
}
// Calculate discount amount
$discountAmount = $voucher->discountAmount;
if ($voucher->discountPercentage > 0 && null !== $participantPrices && isset($participantPrices[$index])) {
$discountAmount = round($participantPrices[$index] * ($voucher->discountPercentage / 100), 2);
}
$acceptedVouchers->addVoucher(new AcceptedVoucherDto(
type: AcceptedVoucherDto::TYPE_PROMOTIONAL,
code: $voucher->code,
amount: $discountAmount,
description: $voucher->description,
));
}
}
return $acceptedVouchers->hasVouchers() ? $acceptedVouchers : null;
}
public function getMode(): string
{
return null !== $this->booking ? self::MODE_EDIT : self::MODE_CREATE;
@@ -251,7 +310,7 @@ class BookingDto
public function hasGoodwillVouchers(): bool
{
foreach ($this->participants as $participant) {
if (true === $participant->hasGoodwillVoucher) {
if ($participant->hasGoodwillVoucher()) {
return true;
}
}