Event addons bookable

This commit is contained in:
2026-08-12 16:45:02 +02:00
parent e95de52768
commit 0ee952212b
25 changed files with 656 additions and 24 deletions
+62
View File
@@ -141,6 +141,20 @@ class EventResource extends JsonResource{
// Veranstaltungsspezifische Pflicht-Auswahlfragen (Teilnahmeoptionen); leeres Array => Schritt entfällt.
$returnArray['participationOptions'] = $this->event->participation_options ?? [];
// Buchbare Zusätze (Event-Addons); leeres Array => Schritt entfällt. Preis 0 => "Kostenfrei".
$returnArray['addons'] = collect($this->event->addons ?? [])->map(function ($addon) {
$price = (float)($addon['price'] ?? 0);
return [
'key' => $addon['key'] ?? '',
'title' => $addon['title'] ?? '',
'description' => $addon['description'] ?? '',
'price' => $price,
'priceReadable' => new Amount($price, 'Euro')->toString(),
'free' => $price <= 0,
'flat' => (bool)($addon['flat'] ?? false),
];
})->toArray();
$returnArray['participationTypes'] = [];
@@ -354,6 +368,54 @@ class EventResource extends JsonResource{
return new Amount(round($basicFee->getAmount(), 2), 'Euro');
}
/**
* Löst die gewählten Zusätze (Event-Addons) gegen die Event-Definition auf und berechnet je Position den
* Betrag: Pauschale => Preis, sonst Preis × Teilnahmetage. Bei USt-Pflicht + Netto-Preismodus (`add_on`)
* wird die USt aufgeschlagen (analog Beitrag); bei „inclusive"/keiner Pflicht bleibt der Preis unverändert.
* Kein Early-Bird-Aufschlag.
*
* @param array<int, string> $selectedKeys
* @return array{items: array<int, array{key: string, title: string, price: float, flat: bool, days: int, amount: float}>, total: Amount}
*/
public function resolveAddons(array $selectedKeys, DateTime $arrival, DateTime $departure): array
{
$days = $arrival->diff($departure)->days + 1;
$addsVat = $this->event->tax_liable && $this->event->vat_pricing_mode === VatPricingMode::AddOn->value;
$items = [];
$total = new Amount(0, 'Euro');
foreach ($this->event->addons ?? [] as $addon) {
$key = $addon['key'] ?? null;
if ($key === null || !in_array($key, $selectedKeys, true)) {
continue;
}
$price = (float)($addon['price'] ?? 0);
$flat = (bool)($addon['flat'] ?? false);
$usedDays = $flat ? 1 : $days;
$amount = $flat ? $price : $price * $days;
if ($addsVat) {
$amount *= 1 + $this->event->vat_rate / 100;
}
$amount = round($amount, 2);
$items[] = [
'key' => $key,
'title' => $addon['title'] ?? $key,
'price' => $price,
'flat' => $flat,
'days' => $usedDays,
'amount' => $amount,
];
$total->addAmount(new Amount($amount, 'Euro'));
}
return ['items' => $items, 'total' => $total];
}
}