feat: promotional and purchase vouchers

This commit is contained in:
Björn Fromme
2026-03-16 11:59:11 +01:00
parent a8c0a1aa61
commit 7df99521c4
21 changed files with 847 additions and 6 deletions
@@ -0,0 +1,84 @@
<?php
declare(strict_types=1);
namespace App\Form\Service;
use App\Form\Model\BookingDto;
use App\Form\Service\Abstract\AbstractParticipantFieldHandler;
use App\Service\VoucherValidationService;
/**
* Handles processing and validation of purchase voucher codes for booking participants.
*
* This handler validates purchase vouchers (including goodwill vouchers) via the BPN API
* and provides immediate feedback to users about voucher validity and remaining balance.
* Purchase vouchers reduce the booking price by their remaining balance and support
* partial redemption.
*
* Validation includes:
* - Voucher existence check
* - Remaining balance verification (zero-balance vouchers are reported as invalid)
* - Real-time API validation with 15-minute caching
*
* Dependencies: None (purchase vouchers don't require price calculation)
*/
class ParticipantPurchaseVoucherFieldHandler extends AbstractParticipantFieldHandler
{
public function __construct(
private readonly VoucherValidationService $voucherValidationService,
) {
}
public function getFieldName(): string
{
return 'purchaseVoucherCode';
}
public function getDependencies(): array
{
// No dependencies - purchase vouchers don't require price calculation
return [];
}
public function shouldProcess(array $submittedData, string $mode, int $participantIndex): bool
{
$voucherCode = $this->getFieldValue($submittedData, $this->getFieldName());
return null !== $voucherCode && '' !== trim($voucherCode);
}
public function processField(array $submittedData, BookingDto $bookingDto, int $participantIndex): void
{
$participant = $this->getParticipant($bookingDto, $participantIndex);
if (null === $participant) {
return;
}
$voucherCode = $this->getFieldValue($submittedData, $this->getFieldName());
if (null === $voucherCode || '' === trim($voucherCode)) {
return;
}
// Validate voucher via API
$result = $this->voucherValidationService->validatePurchaseVoucher($voucherCode);
if (true === $result->isValid && null !== $result->voucher) {
$participant->addNotification(
'success',
sprintf(
'Gutschein gültig: %s (Restwert: %.2f €)',
$result->voucher->type,
$result->voucher->remainingBalance
)
);
} else {
$participant->addNotification(
'error',
sprintf('Gutschein ungültig: %s', $result->errorMessage ?? 'Unbekannter Fehler')
);
}
}
}