Handling of event addons
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Resources;
|
||||
|
||||
use App\Models\EventParticipantAddon;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class EventParticipantAddonResource extends JsonResource
|
||||
{
|
||||
function __construct(EventParticipantAddon $addon)
|
||||
{
|
||||
parent::__construct($addon);
|
||||
}
|
||||
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'addonKey' => $this->resource->addon_key,
|
||||
'title' => $this->resource->title,
|
||||
'flat' => $this->resource->flat,
|
||||
'amount' => $this->resource->amount?->getAmount() ?? 0,
|
||||
'amountReadable' => $this->resource->amount?->toString() ?? '0,00 Euro',
|
||||
'free' => ($this->resource->amount?->getAmount() ?? 0) <= 0,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Resources;
|
||||
|
||||
use App\Models\EventParticipantOption;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class EventParticipantOptionResource extends JsonResource
|
||||
{
|
||||
function __construct(EventParticipantOption $option)
|
||||
{
|
||||
parent::__construct($option);
|
||||
}
|
||||
|
||||
public function toArray($request): array
|
||||
{
|
||||
return [
|
||||
'questionKey' => $this->resource->question_key,
|
||||
'questionLabel' => $this->resource->question_label,
|
||||
'value' => $this->resource->value,
|
||||
'valueLabel' => $this->resource->value_label,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -96,6 +96,10 @@ class EventParticipantResource extends JsonResource
|
||||
'eventName' => $this->resource->event()->first()->name,
|
||||
'arrivalDateReadable' => $this->resource->arrival_date->format('d.m.Y'),
|
||||
'departureDateReadable' => $this->resource->departure_date->format('d.m.Y'),
|
||||
'participationOptions' => $this->resource->selectedOptions()->get()->map(
|
||||
fn($option) => new EventParticipantOptionResource($option)->toArray($request))->toArray(),
|
||||
'selectedAddons' => $this->resource->selectedAddons()->get()->map(
|
||||
fn($addon) => new EventParticipantAddonResource($addon)->toArray($request))->toArray(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Resources;
|
||||
|
||||
use App\Enumerations\ParticipationFeeType;
|
||||
use App\Enumerations\ParticipationType;
|
||||
use App\Enumerations\VatPricingMode;
|
||||
use App\Models\Event;
|
||||
use App\ValueObjects\Amount;
|
||||
use DateTime;
|
||||
@@ -137,6 +138,23 @@ class EventResource extends JsonResource{
|
||||
$returnArray['paymentMethods'] = $this->event->paymentMethods()->get()->map(
|
||||
fn($paymentMethod) => new AvailablePaymentMethodResource($paymentMethod)->toArray($request))->toArray();
|
||||
|
||||
// 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'] = [];
|
||||
|
||||
@@ -342,7 +360,61 @@ class EventResource extends JsonResource{
|
||||
$basicFee = $basicFee->multiply(0.5);
|
||||
}
|
||||
|
||||
return $basicFee;
|
||||
// Bei bestehender USt-Pflicht und Netto-Preismodus die USt aufschlagen; gespeichert wird immer der
|
||||
// finale Brutto-Betrag. Bei "inklusive" oder ohne Steuerpflicht bleibt der Beitrag unverändert.
|
||||
if ($this->event->tax_liable && $this->event->vat_pricing_mode === VatPricingMode::AddOn->value) {
|
||||
$basicFee = $basicFee->multiply(1 + $this->event->vat_rate / 100);
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user