Creation and editing of events
This commit is contained in:
34
app/Casts/AmountCast.php
Normal file
34
app/Casts/AmountCast.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Casts;
|
||||
|
||||
use App\ValueObjects\Amount;
|
||||
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class AmountCast implements CastsAttributes
|
||||
{
|
||||
public function get(Model $model, string $key, mixed $value, array $attributes): ?Amount
|
||||
{
|
||||
if ($value === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Amount((float) $value, 'Euro');
|
||||
}
|
||||
|
||||
public function set(Model $model, string $key, mixed $value, array $attributes): ?float
|
||||
{
|
||||
if ($value === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($value instanceof Amount) {
|
||||
return $value->getAmount();
|
||||
}
|
||||
|
||||
return (float) $value;
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,13 @@ class CreateCostUnitCommand {
|
||||
'mail_on_new' => $this->request->mailOnNew,
|
||||
'allow_new' => true,
|
||||
'archived' => false,
|
||||
|
||||
]);
|
||||
|
||||
if (null !== $costUnit) {
|
||||
$response->costUnit = $costUnit;
|
||||
$response->success = true;
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
|
||||
namespace App\Domains\CostUnit\Actions\CreateCostUnit;
|
||||
|
||||
class CreateCostUnitResponse {
|
||||
use App\Models\CostUnit;
|
||||
|
||||
class CreateCostUnitResponse {
|
||||
public bool $success;
|
||||
public ?CostUnit $costUnit;
|
||||
|
||||
public function __construct() {
|
||||
$this->success = false;
|
||||
$this->costUnit = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,11 @@ use Illuminate\Http\JsonResponse;
|
||||
|
||||
class OpenController extends CommonController {
|
||||
public function __invoke(int $costUnitId) {
|
||||
$costUnit = $this->costUnits->getById($costUnitId);
|
||||
|
||||
|
||||
$inertiaProvider = new InertiaProvider('CostUnit/Open', [
|
||||
'costUnitId' => $costUnitId
|
||||
'costUnit' => $costUnit
|
||||
]);
|
||||
return $inertiaProvider->render();
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
import ListInvoices from "./Partials/ListInvoices.vue";
|
||||
|
||||
const props = defineProps({
|
||||
costUnitId: Number
|
||||
costUnit: Object
|
||||
})
|
||||
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
const initialCostUnitId = props.cost_unit_id
|
||||
const initialCostUnitId = props.costUnit.id
|
||||
const initialInvoiceId = props.invoice_id
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
{
|
||||
title: 'Neue Abrechnungen',
|
||||
component: ListInvoices,
|
||||
endpoint: "/api/v1/cost-unit/" + props.costUnitId + "/invoice-list/new",
|
||||
endpoint: "/api/v1/cost-unit/" + props.costUnit.id + "/invoice-list/new",
|
||||
deep_jump_id: initialCostUnitId,
|
||||
deep_jump_id_sub: initialInvoiceId,
|
||||
|
||||
@@ -30,21 +30,21 @@
|
||||
{
|
||||
title: 'Nichtexportierte Abrechnungen',
|
||||
component: ListInvoices,
|
||||
endpoint: "/api/v1/cost-unit/" + props.costUnitId + "/invoice-list/approved",
|
||||
endpoint: "/api/v1/cost-unit/" + props.costUnit.id + "/invoice-list/approved",
|
||||
deep_jump_id: initialCostUnitId,
|
||||
deep_jump_id_sub: initialInvoiceId,
|
||||
},
|
||||
{
|
||||
title: 'Exportierte Abrechnungen',
|
||||
component: ListInvoices,
|
||||
endpoint: "/api/v1/cost-unit/" + props.costUnitId + "/invoice-list/exported",
|
||||
endpoint: "/api/v1/cost-unit/" + props.costUnit.id + "/invoice-list/exported",
|
||||
deep_jump_id: initialCostUnitId,
|
||||
deep_jump_id_sub: initialInvoiceId,
|
||||
},
|
||||
{
|
||||
title: 'Abgelehnte Abrechnungen',
|
||||
component: ListInvoices,
|
||||
endpoint: "/api/v1/cost-unit/" + props.costUnitId + "/invoice-list/denied",
|
||||
endpoint: "/api/v1/cost-unit/" + props.costUnit.id + "/invoice-list/denied",
|
||||
deep_jump_id: initialCostUnitId,
|
||||
deep_jump_id_sub: initialInvoiceId,
|
||||
},
|
||||
@@ -58,7 +58,7 @@
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppLayout title="Abrechnungen">
|
||||
<AppLayout :title="'Abrechnungen ' + props.costUnit.name">
|
||||
<shadowed-box style="width: 95%; margin: 20px auto; padding: 20px; overflow-x: hidden;">
|
||||
<tabbed-page :tabs="tabs" :initial-tab-id="initialCostUnitId" :initial-sub-tab-id="initialInvoiceId" />
|
||||
|
||||
|
||||
74
app/Domains/Event/Actions/CreateEvent/CreateEventCommand.php
Normal file
74
app/Domains/Event/Actions/CreateEvent/CreateEventCommand.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\CreateEvent;
|
||||
|
||||
use App\Enumerations\EatingHabit;
|
||||
use App\Models\Event;
|
||||
use App\Models\Tenant;
|
||||
use App\RelationModels\EventEatingHabits;
|
||||
use App\RelationModels\EventLocalGroups;
|
||||
|
||||
class CreateEventCommand {
|
||||
private CreateEventRequest $request;
|
||||
public function __construct(CreateEventRequest $request) {
|
||||
$this->request = $request;
|
||||
}
|
||||
public function execute(): CreateEventResponse {
|
||||
$response = new CreateEventResponse();
|
||||
|
||||
|
||||
|
||||
$prefix = $this->request->begin->format('Y-m_');
|
||||
if (!str_starts_with($this->request->name, $prefix)) {
|
||||
$this->request->name = $prefix . $this->request->name;
|
||||
}
|
||||
|
||||
|
||||
$event = Event::create([
|
||||
'tenant' => app('tenant')->slug,
|
||||
'name' => $this->request->name,
|
||||
'location' => $this->request->location,
|
||||
'postal_code' => $this->request->postalCode,
|
||||
'email' => $this->request->email,
|
||||
'start_date' => $this->request->begin,
|
||||
'end_date' => $this->request->end,
|
||||
'early_bird_end' => $this->request->earlyBirdEnd,
|
||||
'registration_final_end' => $this->request->registrationFinalEnd,
|
||||
'early_bird_end_amount_increase' => $this->request->earlyBirdEndAmountIncrease,
|
||||
'account_owner' => $this->request->accountOwner,
|
||||
'account_iban' => $this->request->accountIban,
|
||||
'participation_fee_type' => $this->request->participationFeeType->slug,
|
||||
'pay_per_day' => $this->request->payPerDay,
|
||||
'pay_direct' => $this->request->payDirect,
|
||||
'total_max_amount' => 0,
|
||||
'support_per_person' => 0,
|
||||
'support_flat' => 0,
|
||||
]);
|
||||
|
||||
if ($event !== null) {
|
||||
EventEatingHabits::create([
|
||||
'event_id' => $event->id,
|
||||
'eating_habit_id' => EatingHabit::where('slug', EatingHabit::EATING_HABIT_VEGAN)->first()->id,
|
||||
]);
|
||||
|
||||
EventEatingHabits::create([
|
||||
'event_id' => $event->id,
|
||||
'eating_habit_id' => EatingHabit::where('slug', EatingHabit::EATING_HABIT_VEGETARIAN)->first()->id,
|
||||
]);
|
||||
|
||||
if (app('tenant')->slug === 'lv') {
|
||||
foreach(Tenant::where(['is_active_local_group' => true])->get() as $tenant) {
|
||||
EventLocalGroups::create(['event_id' => $event->id, 'local_group_id' => $tenant->id]);
|
||||
}
|
||||
} else {
|
||||
EventLocalGroups::create(['event_id' => $event->id, 'local_group_id' => app('tenant')->id]);
|
||||
}
|
||||
|
||||
|
||||
$response->success = true;
|
||||
$response->event = $event;
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
40
app/Domains/Event/Actions/CreateEvent/CreateEventRequest.php
Normal file
40
app/Domains/Event/Actions/CreateEvent/CreateEventRequest.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\CreateEvent;
|
||||
|
||||
use App\Enumerations\ParticipationFeeType;
|
||||
use DateTime;
|
||||
|
||||
class CreateEventRequest {
|
||||
public string $name;
|
||||
public string $location;
|
||||
public string $postalCode;
|
||||
public string $email;
|
||||
public DateTime $begin;
|
||||
public DateTime $end;
|
||||
public DateTime $earlyBirdEnd;
|
||||
public DateTime $registrationFinalEnd;
|
||||
public int $earlyBirdEndAmountIncrease;
|
||||
public ParticipationFeeType $participationFeeType;
|
||||
public string $accountOwner;
|
||||
public string $accountIban;
|
||||
public bool $payPerDay;
|
||||
public bool $payDirect;
|
||||
|
||||
public function __construct(string $name, string $location, string $postalCode, string $email, DateTime $begin, DateTime $end, DateTime $earlyBirdEnd, DateTime $registrationFinalEnd, int $earlyBirdEndAmountIncrease, ParticipationFeeType $participationFeeType, string $accountOwner, string $accountIban, bool $payPerDay, bool $payDirect) {
|
||||
$this->name = $name;
|
||||
$this->location = $location;
|
||||
$this->postalCode = $postalCode;
|
||||
$this->email = $email;
|
||||
$this->begin = $begin;
|
||||
$this->end = $end;
|
||||
$this->earlyBirdEnd = $earlyBirdEnd;
|
||||
$this->registrationFinalEnd = $registrationFinalEnd;
|
||||
$this->earlyBirdEndAmountIncrease = $earlyBirdEndAmountIncrease;
|
||||
$this->participationFeeType = $participationFeeType;
|
||||
$this->accountOwner = $accountOwner;
|
||||
$this->accountIban = $accountIban;
|
||||
$this->payPerDay = $payPerDay;
|
||||
$this->payDirect = $payDirect;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\CreateEvent;
|
||||
|
||||
use App\Models\Event;
|
||||
|
||||
class CreateEventResponse {
|
||||
public bool $success;
|
||||
public ?Event $event;
|
||||
|
||||
public function __construct() {
|
||||
$this->success = false;
|
||||
$this->event = null;
|
||||
}
|
||||
}
|
||||
18
app/Domains/Event/Actions/SetCostUnit/SetCostUnitCommand.php
Normal file
18
app/Domains/Event/Actions/SetCostUnit/SetCostUnitCommand.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\SetCostUnit;
|
||||
|
||||
class SetCostUnitCommand {
|
||||
private SetCostUnitRequest $request;
|
||||
|
||||
public function __construct(SetCostUnitRequest $request) {
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function execute() : SetCostUnitResponse {
|
||||
$response = new SetCostUnitResponse();
|
||||
$this->request->event->cost_unit_id = $this->request->costUnit->id;
|
||||
$response->success = $this->request->event->save();
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
16
app/Domains/Event/Actions/SetCostUnit/SetCostUnitRequest.php
Normal file
16
app/Domains/Event/Actions/SetCostUnit/SetCostUnitRequest.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\SetCostUnit;
|
||||
|
||||
use App\Models\CostUnit;
|
||||
use App\Models\Event;
|
||||
|
||||
class SetCostUnitRequest {
|
||||
public Event $event;
|
||||
public CostUnit $costUnit;
|
||||
|
||||
public function __construct(Event $event, CostUnit $costUnit) {
|
||||
$this->event = $event;
|
||||
$this->costUnit = $costUnit;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\SetCostUnit;
|
||||
|
||||
class SetCostUnitResponse {
|
||||
public bool $success;
|
||||
|
||||
public function __construct() {
|
||||
$this->success = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\SetParticipationFees;
|
||||
|
||||
use App\RelationModels\EventParticipationFee;
|
||||
|
||||
class SetParticipationFeesCommand {
|
||||
private SetParticipationFeesRequest $request;
|
||||
public function __construct(SetParticipationFeesRequest $request) {
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function excetute() : SetParticipationFeesResponse {
|
||||
$response = new SetParticipationFeesResponse();
|
||||
$this->cleanBefore();
|
||||
|
||||
$this->request->event->participationFee1()->associate(EventParticipationFee::create([
|
||||
'tenant' => app('tenant')->slug,
|
||||
'type' => $this->request->participationFeeFirst['type'],
|
||||
'name' => $this->request->participationFeeFirst['name'],
|
||||
'description' => $this->request->participationFeeFirst['description'],
|
||||
'amount' => $this->request->participationFeeFirst['amount']->getAmount()
|
||||
]))->save();
|
||||
|
||||
if ($this->request->participationFeeSecond !== null) {
|
||||
$this->request->event->participationFee2()->associate(EventParticipationFee::create([
|
||||
'tenant' => app('tenant')->slug,
|
||||
'type' => $this->request->participationFeeSecond['type'],
|
||||
'name' => $this->request->participationFeeSecond['name'],
|
||||
'description' => $this->request->participationFeeSecond['description'],
|
||||
'amount' => $this->request->participationFeeSecond['amount']->getAmount()
|
||||
]))->save();
|
||||
}
|
||||
|
||||
if ($this->request->participationFeeThird !== null) {
|
||||
$this->request->event->participationFee3()->associate(EventParticipationFee::create([
|
||||
'tenant' => app('tenant')->slug,
|
||||
'type' => $this->request->participationFeeThird['type'],
|
||||
'name' => $this->request->participationFeeThird['name'],
|
||||
'description' => $this->request->participationFeeThird['description'],
|
||||
'amount' => $this->request->participationFeeThird['amount']->getAmount()
|
||||
]))->save();
|
||||
}
|
||||
|
||||
if ($this->request->participationFeeFourth !== null) {
|
||||
$this->request->event->participationFee4()->associate(EventParticipationFee::create([
|
||||
'tenant' => app('tenant')->slug,
|
||||
'type' => $this->request->participationFeeFourth['type'],
|
||||
'name' => $this->request->participationFeeFourth['name'],
|
||||
'description' => $this->request->participationFeeFourth['description'],
|
||||
'amount' => $this->request->participationFeeFourth['amount']->getAmount()
|
||||
]))->save();
|
||||
}
|
||||
|
||||
$this->request->event->save();
|
||||
$response->success = true;
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function cleanBefore() {
|
||||
if ($this->request->event->participationFee1()->first() !== null) {
|
||||
$this->request->event->participationFee1()->first()->delete();
|
||||
}
|
||||
|
||||
if ($this->request->event->participationFee2()->first() !== null) {
|
||||
$this->request->event->participationFee2()->first()->delete();
|
||||
}
|
||||
|
||||
if ($this->request->event->participationFee3()->first() !== null) {
|
||||
$this->request->event->participationFee3()->first()->delete();
|
||||
}
|
||||
|
||||
if ($this->request->event->participationFee4()->first() !== null) {
|
||||
$this->request->event->participationFee4()->first()->delete();
|
||||
}
|
||||
|
||||
$this->request->event->save();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\SetParticipationFees;
|
||||
|
||||
use App\Models\Event;
|
||||
use App\RelationModels\EventParticipationFee;
|
||||
|
||||
class SetParticipationFeesRequest {
|
||||
public Event $event;
|
||||
public array $participationFeeFirst;
|
||||
public ?array $participationFeeSecond;
|
||||
public ?array $participationFeeThird;
|
||||
public ?array $participationFeeFourth;
|
||||
|
||||
|
||||
public function __construct(Event $event, array $participationFeeFirst) {
|
||||
$this->event = $event;
|
||||
$this->participationFeeFirst = $participationFeeFirst;
|
||||
$this->participationFeeSecond = null;
|
||||
$this->participationFeeThird = null;
|
||||
$this->participationFeeFourth = null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\SetParticipationFees;
|
||||
|
||||
class SetParticipationFeesResponse {
|
||||
public bool $success;
|
||||
public function __construct() {
|
||||
$this->success = false;
|
||||
}
|
||||
|
||||
}
|
||||
41
app/Domains/Event/Actions/UpdateEvent/UpdateEventCommand.php
Normal file
41
app/Domains/Event/Actions/UpdateEvent/UpdateEventCommand.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\UpdateEvent;
|
||||
|
||||
class UpdateEventCommand {
|
||||
public UpdateEventRequest $request;
|
||||
public function __construct(UpdateEventRequest $request) {
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function execute() : UpdateEventResponse {
|
||||
$response = new UpdateEventResponse();
|
||||
|
||||
$this->request->event->name = $this->request->eventName;
|
||||
$this->request->event->location = $this->request->eventLocation;
|
||||
$this->request->event->postal_code = $this->request->postalCode;
|
||||
$this->request->event->email = $this->request->email;
|
||||
$this->request->event->early_bird_end = $this->request->earlyBirdEnd;
|
||||
$this->request->event->registration_final_end = $this->request->registrationFinalEnd;
|
||||
$this->request->event->alcoholics_age = $this->request->alcoholicsAge;
|
||||
$this->request->event->support_per_person = $this->request->supportPerPerson;
|
||||
$this->request->event->support_flat = $this->request->flatSupport;
|
||||
$this->request->event->save();
|
||||
|
||||
$this->request->event->resetAllowedEatingHabits();
|
||||
$this->request->event->resetContributingLocalGroups();
|
||||
|
||||
foreach($this->request->eatingHabits as $eatingHabit) {
|
||||
$this->request->event->eatingHabits()->attach($eatingHabit);
|
||||
}
|
||||
|
||||
foreach($this->request->contributingLocalGroups as $contributingLocalGroup) {
|
||||
$this->request->event->localGroups()->attach($contributingLocalGroup);
|
||||
}
|
||||
|
||||
$this->request->event->save();
|
||||
$response->success = true;
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
41
app/Domains/Event/Actions/UpdateEvent/UpdateEventRequest.php
Normal file
41
app/Domains/Event/Actions/UpdateEvent/UpdateEventRequest.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\UpdateEvent;
|
||||
|
||||
use App\Models\Event;
|
||||
use App\ValueObjects\Amount;
|
||||
use DateTime;
|
||||
|
||||
class UpdateEventRequest {
|
||||
public Event $event;
|
||||
public string $eventName;
|
||||
public string $eventLocation;
|
||||
public string $postalCode;
|
||||
public string $email;
|
||||
public DateTime $earlyBirdEnd;
|
||||
public DateTime $registrationFinalEnd;
|
||||
public int $alcoholicsAge;
|
||||
public bool $sendWeeklyReports;
|
||||
public bool $registrationAllowed;
|
||||
public Amount $flatSupport;
|
||||
public Amount $supportPerPerson;
|
||||
public array $contributingLocalGroups;
|
||||
public array $eatingHabits;
|
||||
|
||||
public function __construct(Event $event, string $eventName, string $eventLocation, string $postalCode, string $email, DateTime $earlyBirdEnd, DateTime $registrationFinalEnd, int $alcoholicsAge, bool $sendWeeklyReports, bool $registrationAllowed, Amount $flatSupport, Amount $supportPerPerson, array $contributingLocalGroups, array $eatingHabits) {
|
||||
$this->event = $event;
|
||||
$this->eventName = $eventName;
|
||||
$this->eventLocation = $eventLocation;
|
||||
$this->postalCode = $postalCode;
|
||||
$this->email = $email;
|
||||
$this->earlyBirdEnd = $earlyBirdEnd;
|
||||
$this->registrationFinalEnd = $registrationFinalEnd;
|
||||
$this->alcoholicsAge = $alcoholicsAge;
|
||||
$this->sendWeeklyReports = $sendWeeklyReports;
|
||||
$this->registrationAllowed = $registrationAllowed;
|
||||
$this->flatSupport = $flatSupport;
|
||||
$this->supportPerPerson = $supportPerPerson;
|
||||
$this->contributingLocalGroups = $contributingLocalGroups;
|
||||
$this->eatingHabits = $eatingHabits;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\UpdateEvent;
|
||||
|
||||
class UpdateEventResponse {
|
||||
public bool $success;
|
||||
|
||||
public function __construct() {
|
||||
$this->success = false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\UpdateManagers;
|
||||
|
||||
class UpdateManagersCommand {
|
||||
private UpdateManagersRequest $request;
|
||||
|
||||
public function __construct(UpdateManagersRequest $request) {
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function execute() : UpdateManagersResponse {
|
||||
$response = new UpdateManagersResponse();
|
||||
$this->request->event->resetMangers();
|
||||
|
||||
foreach ($this->request->managers as $manager) {
|
||||
$this->request->event->eventManagers()->attach($manager);
|
||||
}
|
||||
|
||||
$this->request->event->save();
|
||||
$response->success = true;
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\UpdateManagers;
|
||||
|
||||
use App\Models\Event;
|
||||
|
||||
class UpdateManagersRequest {
|
||||
public Event $event;
|
||||
public array $managers;
|
||||
|
||||
public function __construct(Event $event, array $managers) {
|
||||
$this->managers = $managers;
|
||||
$this->event = $event;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\UpdateManagers;
|
||||
|
||||
class UpdateManagersResponse {
|
||||
public bool $success;
|
||||
|
||||
public function __construct() {
|
||||
$this->success = false;
|
||||
}
|
||||
}
|
||||
100
app/Domains/Event/Controllers/CreateController.php
Normal file
100
app/Domains/Event/Controllers/CreateController.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Controllers;
|
||||
|
||||
use App\Domains\CostUnit\Actions\CreateCostUnit\CreateCostUnitCommand;
|
||||
use App\Domains\CostUnit\Actions\CreateCostUnit\CreateCostUnitRequest;
|
||||
use App\Domains\Event\Actions\CreateEvent\CreateEventCommand;
|
||||
use App\Domains\Event\Actions\CreateEvent\CreateEventRequest;
|
||||
use App\Domains\Event\Actions\SetCostUnit\SetCostUnitCommand;
|
||||
use App\Domains\Event\Actions\SetCostUnit\SetCostUnitRequest;
|
||||
use App\Enumerations\CostUnitType;
|
||||
use App\Enumerations\ParticipationFeeType;
|
||||
use App\Providers\InertiaProvider;
|
||||
use App\Resources\EventResource;
|
||||
use App\Scopes\CommonController;
|
||||
use App\ValueObjects\Amount;
|
||||
use DateTime;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class CreateController extends CommonController {
|
||||
public function __invoke() {
|
||||
return new InertiaProvider('Event/Create', [
|
||||
'emailAddress' => auth()->user()->email,
|
||||
'eventAccount' => $this->tenant->account_name,
|
||||
'eventIban' => $this->tenant->account_iban,
|
||||
'eventPayPerDay' => $this->tenant->slug === 'lv' ? true : false,
|
||||
'participationFeeType' => $this->tenant->slug === 'lv' ?
|
||||
ParticipationFeeType::PARTICIPATION_FEE_TYPE_FIXED :
|
||||
ParticipationFeeType::PARTICIPATION_FEE_TYPE_SOLIDARITY,
|
||||
])->render();
|
||||
}
|
||||
|
||||
public function doCreate(Request $request) : JsonResponse {
|
||||
|
||||
$eventBegin = DateTime::createFromFormat('Y-m-d', $request->input('eventBegin'));
|
||||
$eventEnd = DateTime::createFromFormat('Y-m-d', $request->input('eventEnd'));
|
||||
$eventEarlyBirdEnd = DateTime::createFromFormat('Y-m-d', $request->input('eventEarlyBirdEnd'));
|
||||
$registrationFinalEnd = DateTime::createFromFormat('Y-m-d', $request->input('eventRegistrationFinalEnd'));
|
||||
$participationFeeType = ParticipationFeeType::where('slug', $request->input('eventParticipationFeeType'))->first();
|
||||
$payPerDay = $request->input('eventPayPerDay');
|
||||
$payDirect = $request->input('eventPayDirectly');
|
||||
|
||||
$billingDeadline = $eventEnd->modify('+1 month');
|
||||
|
||||
$createRequest = new CreateEventRequest(
|
||||
$request->input('eventName'),
|
||||
$request->input('eventLocation'),
|
||||
$request->input('eventPostalCode'),
|
||||
$request->input('eventEmail'),
|
||||
$eventBegin,
|
||||
$eventEnd,
|
||||
$eventEarlyBirdEnd,
|
||||
$registrationFinalEnd,
|
||||
$request->input('eventEarlyBirdEndAmountIncrease'),
|
||||
$participationFeeType,
|
||||
$request->input('eventAccount'),
|
||||
$request->input('eventIban'),
|
||||
$payPerDay,
|
||||
$payDirect
|
||||
);
|
||||
|
||||
$wasSuccessful = false;
|
||||
|
||||
$createCommand = new CreateEventCommand($createRequest);
|
||||
$result = $createCommand->execute();
|
||||
if ($result->success) {
|
||||
$createCostUnitRequest = new CreateCostUnitRequest(
|
||||
$result->event->name,
|
||||
CostUnitType::COST_UNIT_TYPE_EVENT,
|
||||
Amount::fromString('0,25'),
|
||||
true,
|
||||
$billingDeadline
|
||||
);
|
||||
|
||||
$createCostUnitCommand = new CreateCostUnitCommand($createCostUnitRequest);
|
||||
$costUnitResponse = $createCostUnitCommand->execute();
|
||||
|
||||
if ($costUnitResponse->success) {
|
||||
$costUnitUpdateRequest = new SetCostUnitRequest($result->event, $costUnitResponse->costUnit);
|
||||
$costUnitUpdateCommand = new SetCostUnitCommand($costUnitUpdateRequest);
|
||||
$costUnitSetResponse = $costUnitUpdateCommand->execute();
|
||||
$wasSuccessful = $costUnitSetResponse->success;
|
||||
}
|
||||
}
|
||||
|
||||
if ($wasSuccessful) {
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'event' => new EventResource($costUnitUpdateRequest->event)->toArray()
|
||||
]);
|
||||
} else {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Die Veranstaltung konnte nicht angelegt werden.'
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
118
app/Domains/Event/Controllers/DetailsController.php
Normal file
118
app/Domains/Event/Controllers/DetailsController.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Controllers;
|
||||
|
||||
use App\Domains\Event\Actions\SetParticipationFees\SetParticipationFeesCommand;
|
||||
use App\Domains\Event\Actions\SetParticipationFees\SetParticipationFeesRequest;
|
||||
use App\Domains\Event\Actions\UpdateEvent\UpdateEventCommand;
|
||||
use App\Domains\Event\Actions\UpdateEvent\UpdateEventRequest;
|
||||
use App\Domains\Event\Actions\UpdateManagers\UpdateManagersCommand;
|
||||
use App\Domains\Event\Actions\UpdateManagers\UpdateManagersRequest;
|
||||
use App\Enumerations\ParticipationFeeType;
|
||||
use App\Enumerations\ParticipationType;
|
||||
use App\Providers\InertiaProvider;
|
||||
use App\Resources\EventResource;
|
||||
use App\Scopes\CommonController;
|
||||
use App\ValueObjects\Amount;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class DetailsController extends CommonController {
|
||||
public function __invoke(int $eventId) {
|
||||
$event = $this->events->getById($eventId);
|
||||
return new InertiaProvider('Event/Details', ['event' => $event])->render();
|
||||
}
|
||||
|
||||
public function summary(int $eventId) : JsonResponse {
|
||||
$event = $this->events->getById($eventId);
|
||||
return response()->json(['event' => new EventResource($event)->toArray()]);
|
||||
}
|
||||
|
||||
public function updateCommonSettings(int $eventId, Request $request) : JsonResponse {
|
||||
$event = $this->events->getById($eventId);
|
||||
|
||||
$earlyBirdEnd = \DateTime::createFromFormat('Y-m-d', $request->input('earlyBirdEnd'));
|
||||
$registrationFinalEnd = \DateTime::createFromFormat('Y-m-d', $request->input('registrationFinalEnd'));
|
||||
$flatSupport = Amount::fromString($request->input('flatSupport'));
|
||||
$supportPerPerson = Amount::fromString($request->input('supportPerson'));
|
||||
|
||||
$contributinLocalGroups = $request->input('contributingLocalGroups');
|
||||
$eatingHabits = $request->input('eatingHabits');
|
||||
|
||||
$eventUpdateRequest = new UpdateEventRequest(
|
||||
$event,
|
||||
$request->input('eventName'),
|
||||
$request->input('eventLocation'),
|
||||
$request->input('postalCode'),
|
||||
$request->input('email'),
|
||||
$earlyBirdEnd,
|
||||
$registrationFinalEnd,
|
||||
$request->input('alcoholicsAge'),
|
||||
$request->input('sendWeeklyReports'),
|
||||
$request->input('registrationAllowed'),
|
||||
$flatSupport,
|
||||
$supportPerPerson,
|
||||
$contributinLocalGroups,
|
||||
$eatingHabits
|
||||
);
|
||||
|
||||
$eventUpdateCommand = new UpdateEventCommand($eventUpdateRequest);
|
||||
$response = $eventUpdateCommand->execute();
|
||||
|
||||
return response()->json(['status' => $response->success ? 'success' : 'error']);
|
||||
}
|
||||
|
||||
public function updateEventManagers(int $eventId, Request $request) : JsonResponse {
|
||||
$event = $this->events->getById($eventId);
|
||||
|
||||
$updateEventManagersRequest = new UpdateManagersRequest($event, $request->input('selectedManagers'));
|
||||
$updateEventManagersCommand = new UpdateManagersCommand($updateEventManagersRequest);
|
||||
$response = $updateEventManagersCommand->execute();
|
||||
return response()->json(['status' => $response->success ? 'success' : 'error']);
|
||||
}
|
||||
|
||||
public function updateParticipationFees(int $eventId, Request $request) : JsonResponse {
|
||||
$event = $this->events->getById($eventId);
|
||||
|
||||
$participationFeeFirst = [
|
||||
'type' => ParticipationType::PARTICIPATION_TYPE_PARTICIPANT,
|
||||
'name' => 'Teilnehmer',
|
||||
'description' => $request->input('pft_1_description'),
|
||||
'amount' => Amount::fromString($request->input('pft_1_amount'))
|
||||
];
|
||||
|
||||
$participationFeeRequest = new SetParticipationFeesRequest($event, $participationFeeFirst);
|
||||
|
||||
if ($request->input('pft_2_active')) {
|
||||
$participationFeeRequest->participationFeeSecond = [
|
||||
'type' => ParticipationType::PARTICIPATION_TYPE_TEAM,
|
||||
'name' => $event->participation_fee_type === ParticipationFeeType::PARTICIPATION_FEE_TYPE_FIXED ? 'Kernteam' : 'Solidaritätsbeitrag',
|
||||
'description' => $request->input('pft_2_description'),
|
||||
'amount' => Amount::fromString($request->input('pft_2_amount'))
|
||||
];
|
||||
}
|
||||
|
||||
if ($request->input('pft_3_active')) {
|
||||
$participationFeeRequest->participationFeeThird = [
|
||||
'type' => ParticipationType::PARTICIPATION_TYPE_VOLUNTEER,
|
||||
'name' => $event->participation_fee_type === ParticipationFeeType::PARTICIPATION_FEE_TYPE_FIXED ? 'Unterstützende' : 'Reduzierter Beitrag',
|
||||
'description' => $event->participation_fee_type !== ParticipationFeeType::PARTICIPATION_FEE_TYPE_SOLIDARITY ? $request->input('pft_3_description') : 'Nach Verfügbarkeit',
|
||||
'amount' => Amount::fromString($request->input('pft_3_amount'))
|
||||
];
|
||||
}
|
||||
|
||||
if ($request->input('pft_4_active') && $event->participation_fee_type === ParticipationFeeType::PARTICIPATION_FEE_TYPE_FIXED) {
|
||||
$participationFeeRequest->participationFeeFourth = [
|
||||
'type' => ParticipationType::PARTICIPATION_TYPE_OTHER,
|
||||
'name' => 'Sonstige',
|
||||
'description' => $request->input('pft_4_description'),
|
||||
'amount' => Amount::fromString($request->input('pft_4_amount'))
|
||||
];
|
||||
}
|
||||
|
||||
$participationFeeCommand = new SetParticipationFeesCommand($participationFeeRequest);
|
||||
$response = $participationFeeCommand->excetute();
|
||||
|
||||
return response()->json(['status' => $response->success ? 'success' : 'error']);
|
||||
}
|
||||
}
|
||||
31
app/Domains/Event/Routes/api.php
Normal file
31
app/Domains/Event/Routes/api.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use App\Domains\Event\Controllers\CreateController;
|
||||
use App\Domains\Event\Controllers\DetailsController;
|
||||
use App\Middleware\IdentifyTenant;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::prefix('api/v1')
|
||||
->group(function () {
|
||||
Route::middleware(IdentifyTenant::class)->group(function () {
|
||||
Route::prefix('event')->group(function () {
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
Route::post('/create', [CreateController::class, 'doCreate']);
|
||||
|
||||
Route::prefix('/details/{eventId}') ->group(function () {
|
||||
Route::get('/summary', [DetailsController::class, 'summary']);
|
||||
|
||||
|
||||
|
||||
|
||||
Route::post('/event-managers', [DetailsController::class, 'updateEventManagers']);
|
||||
Route::post('/participation-fees', [DetailsController::class, 'updateParticipationFees']);
|
||||
Route::post('/common-settings', [DetailsController::class, 'updateCommonSettings']);
|
||||
});
|
||||
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
15
app/Domains/Event/Routes/web.php
Normal file
15
app/Domains/Event/Routes/web.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
use App\Domains\Event\Controllers\CreateController;
|
||||
use App\Domains\Event\Controllers\DetailsController;
|
||||
use App\Middleware\IdentifyTenant;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::middleware(IdentifyTenant::class)->group(function () {
|
||||
Route::prefix('event')->group(function () {
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
Route::get('/new', CreateController::class);
|
||||
Route::get('/details/{eventId}', DetailsController::class);
|
||||
});
|
||||
});
|
||||
});
|
||||
294
app/Domains/Event/Views/Create.vue
Normal file
294
app/Domains/Event/Views/Create.vue
Normal file
@@ -0,0 +1,294 @@
|
||||
<script setup>
|
||||
import AppLayout from "../../../../resources/js/layouts/AppLayout.vue";
|
||||
import {reactive, watch, ref, computed} from 'vue'
|
||||
import { subWeeks, format, parseISO, isValid, addDays } from 'date-fns'
|
||||
import ErrorText from "../../../Views/Components/ErrorText.vue";
|
||||
import {useAjax} from "../../../../resources/js/components/ajaxHandler.js";
|
||||
import ParticipationFees from "./Partials/ParticipationFees.vue";
|
||||
|
||||
const { request } = useAjax();
|
||||
|
||||
|
||||
const props = defineProps({
|
||||
'emailAddress': String,
|
||||
'eventAccount': String,
|
||||
'eventIban': String,
|
||||
"eventPayPerDay": Boolean,
|
||||
"participationFeeType": String,
|
||||
})
|
||||
|
||||
const errors = reactive({})
|
||||
|
||||
const formData = reactive({
|
||||
eventName: '',
|
||||
eventPostalCode: '',
|
||||
eventLocation: '',
|
||||
eventEmail: props.emailAddress ? props.emailAddress : '',
|
||||
eventBegin: '',
|
||||
eventEnd: '',
|
||||
eventEarlyBirdEnd: '',
|
||||
eventEarlyBirdEndAmountIncrease: 50,
|
||||
eventRegistrationFinalEnd: '',
|
||||
eventAccount: props.eventAccount ? props.eventAccount : '',
|
||||
eventIban: props.eventIban ? props.eventIban : '',
|
||||
eventPayDirectly: true,
|
||||
eventPayPerDay: props.eventPayPerDay ? props.eventPayPerDay : false,
|
||||
eventParticipationFeeType: props.participationFeeType ? props.participationFeeType : 'fixed',
|
||||
});
|
||||
|
||||
watch(
|
||||
() => formData.eventBegin,
|
||||
(newValue) => {
|
||||
if (!newValue) return
|
||||
|
||||
const beginDate = parseISO(newValue)
|
||||
|
||||
if (!isValid(beginDate)) return
|
||||
|
||||
const fourWeeksBefore = subWeeks(beginDate, 4)
|
||||
const twoWeeksBefore = subWeeks(beginDate, 2)
|
||||
const threeDaysAfter = addDays(beginDate, 2)
|
||||
|
||||
formData.eventEarlyBirdEnd = format(
|
||||
fourWeeksBefore,
|
||||
'yyyy-MM-dd'
|
||||
)
|
||||
|
||||
formData.eventRegistrationFinalEnd = format(
|
||||
twoWeeksBefore,
|
||||
'yyyy-MM-dd'
|
||||
)
|
||||
|
||||
formData.eventEnd = format(
|
||||
threeDaysAfter,
|
||||
'yyyy-MM-dd'
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
const formIsValid = computed(() => {
|
||||
errors.eventEmail = '';
|
||||
errors.eventName = '';
|
||||
errors.eventLocation = '';
|
||||
errors.eventPostalCode = '';
|
||||
errors.eventBegin = '';
|
||||
errors.eventEnd = '';
|
||||
errors.eventEarlyBirdEnd = '';
|
||||
errors.eventRegistrationFinalEnd = '';
|
||||
errors.eventAccount = '';
|
||||
errors.eventIban = '';
|
||||
|
||||
var returnValue = true;
|
||||
|
||||
if (!formData.eventName) {
|
||||
errors.eventName = 'Bitte gib den Veranstaltungsnamen ein'
|
||||
returnValue = false
|
||||
}
|
||||
|
||||
if (!formData.eventEmail) {
|
||||
errors.eventEmail = 'Bitte gib die E-Mail-Adresse der Veranstaltungsleitung für Rückfragen der Teilnehmenden ein'
|
||||
returnValue = false
|
||||
}
|
||||
|
||||
if (!formData.eventLocation) {
|
||||
errors.eventLocation = 'Bitte gib den Veranstaltungsort ein'
|
||||
returnValue = false
|
||||
}
|
||||
|
||||
if (!formData.eventPostalCode) {
|
||||
errors.eventPostalCode = 'Bitte gib die Postleitzahl des Veranstaltungsorts ein'
|
||||
returnValue = false
|
||||
}
|
||||
|
||||
if (!formData.eventBegin) {
|
||||
errors.eventBegin = 'Bitte gib das Anfangsdatum der Veranstaltung ein'
|
||||
returnValue = false
|
||||
}
|
||||
|
||||
if (!formData.eventEnd ||formData.eventEnd < formData.eventBegin ) {
|
||||
errors.eventEnd = 'Das Enddatum darf nicht vor dem Anfangsdatum liegen'
|
||||
returnValue = false
|
||||
}
|
||||
|
||||
if (!formData.eventEarlyBirdEnd ||formData.eventEarlyBirdEnd > formData.eventBegin ) {
|
||||
errors.eventEarlyBirdEnd = 'Das Enddatum der Early-Bird-Phase muss vor dem Veranstaltungsbeginn liegen'
|
||||
returnValue = false
|
||||
}
|
||||
|
||||
if (!formData.eventRegistrationFinalEnd ||formData.eventRegistrationFinalEnd > formData.eventBegin ) {
|
||||
errors.eventRegistrationFinalEnd = 'Der Anmeldeschluss darf nicht nach dem Veranstaltungsbeginn liegen'
|
||||
returnValue = false
|
||||
}
|
||||
|
||||
if (!formData.eventAccount) {
|
||||
errors.eventAccount = 'Bitte gib an, auf wen das Veranstaltungskonto für eingehende Beiträge läuft'
|
||||
returnValue = false
|
||||
}
|
||||
|
||||
if (!formData.eventIban) {
|
||||
errors.eventIban = 'Bitte gib die IBAN des Kontos für Teilnahmebeiträge ein'
|
||||
returnValue = false
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
|
||||
})
|
||||
|
||||
const showParticipationFees = ref(false)
|
||||
const newEvent = ref(null)
|
||||
|
||||
async function createEvent() {
|
||||
if (!formIsValid.value) return false
|
||||
|
||||
const data = await request("/api/v1/event/create", {
|
||||
method: "POST",
|
||||
body: {
|
||||
eventName: formData.eventName,
|
||||
eventPostalCode: formData.eventPostalCode,
|
||||
eventLocation: formData.eventLocation,
|
||||
eventEmail: formData.eventEmail,
|
||||
eventBegin: formData.eventBegin,
|
||||
eventEnd: formData.eventEnd,
|
||||
eventEarlyBirdEnd: formData.eventEarlyBirdEnd,
|
||||
eventEarlyBirdEndAmountIncrease: formData.eventEarlyBirdEndAmountIncrease,
|
||||
eventRegistrationFinalEnd: formData.eventRegistrationFinalEnd,
|
||||
eventAccount: formData.eventAccount,
|
||||
eventIban: formData.eventIban,
|
||||
eventPayDirectly: formData.eventPayDirectly,
|
||||
eventPayPerDay: formData.eventPayPerDay,
|
||||
eventParticipationFeeType: formData.eventParticipationFeeType,
|
||||
}
|
||||
});
|
||||
|
||||
if (data.status !== 'success') {
|
||||
toas.error(data.message);
|
||||
return false;
|
||||
} else {
|
||||
console.log(data.event);
|
||||
newEvent.value = data.event;
|
||||
showParticipationFees.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
async function finishCreation() {
|
||||
window.location.href = '/event/details/' + newEvent.value.id;
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppLayout title="Neue Veranstaltung">
|
||||
<fieldset>
|
||||
<legend>
|
||||
<span style="font-weight: bolder;">Grundlegende Veranstaltungsdaten</span>
|
||||
</legend>
|
||||
<ParticipationFees v-if="showParticipationFees" :event="newEvent" @close="finishCreation" />
|
||||
|
||||
<table style="margin-top: 40px; width: 100%" v-else>
|
||||
<tr style="vertical-align: top;">
|
||||
<th class="width-medium pr-20 height-50">Veranstaltungsname</th>
|
||||
<td class="height-50"><input type="text" v-model="formData.eventName" class="width-half-full" />
|
||||
<ErrorText :message="errors.eventName" /></td>
|
||||
</tr>
|
||||
|
||||
<tr style="vertical-align: top;">
|
||||
<th class="width-medium pr-20 height-50">Veranstaltungsort</th>
|
||||
<td class="height-50"><input type="text" v-model="formData.eventLocation" class="width-half-full" />
|
||||
<ErrorText :message="errors.eventLocation" /></td>
|
||||
</tr>
|
||||
|
||||
<tr style="vertical-align: top;">
|
||||
<th class="width-medium pr-20 height-50">Postleitzahl des Veranstaltungsorts</th>
|
||||
<td class="height-50"><input type="text" v-model="formData.eventPostalCode" class="width-half-full" />
|
||||
<ErrorText :message="errors.eventPostalCode" /></td>
|
||||
</tr>
|
||||
|
||||
<tr style="vertical-align: top;">
|
||||
<th class="width-medium pr-20 height-50">E-Mail-Adresse der Veranstaltungsleitung</th>
|
||||
<td class="height-50"><input type="email" v-model="formData.eventEmail" class="width-half-full" />
|
||||
<ErrorText :message="errors.eventEmail" /></td>
|
||||
</tr>
|
||||
|
||||
<tr style="vertical-align: top;">
|
||||
<th class="width-medium pr-20 height-50">Beginn</th>
|
||||
<td class="height-50"><input type="date" v-model="formData.eventBegin" class="width-half-full" />
|
||||
<ErrorText :message="errors.eventBegin" /></td>
|
||||
</tr>
|
||||
|
||||
<tr style="vertical-align: top;">
|
||||
<th class="width-medium pr-20 height-50">Ende</th>
|
||||
<td class="height-50"><input type="date" v-model="formData.eventEnd" class="width-half-full" />
|
||||
<ErrorText :message="errors.eventEnd" /></td>
|
||||
</tr>
|
||||
|
||||
<tr style="vertical-align: top;">
|
||||
<th class="width-medium pr-20 height-50">Ende Early-Bird-Phase</th>
|
||||
<td class="height-50"><input type="date" v-model="formData.eventEarlyBirdEnd" class="width-half-full" />
|
||||
<ErrorText :message="errors.eventEarlyBirdEnd" /></td>
|
||||
</tr>
|
||||
|
||||
<tr style="vertical-align: top;">
|
||||
<th class="width-medium pr-20 height-50">Finaler Anmeldeschluss</th>
|
||||
<td class="height-50"><input type="date" v-model="formData.eventRegistrationFinalEnd" class="width-half-full" />
|
||||
<ErrorText :message="errors.eventRegistrationFinalEnd" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr style="vertical-align: top;">
|
||||
<th class="width-medium pr-20 height-50">Beitragsart</th>
|
||||
<td class="height-50">
|
||||
<select v-model="formData.eventParticipationFeeType" class="width-half-full">
|
||||
<option value="fixed">Festpreis</option>
|
||||
<option value="solidarity">Solidaritätsprinzip</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr style="vertical-align: top;">
|
||||
<th class="width-medium pr-20 height-50">Preiserhöhung nach Early-Bird-Phase</th>
|
||||
<td class="height-50"><input type="number" v-model="formData.eventEarlyBirdEndAmountIncrease" class="width-tiny" />%</td>
|
||||
</tr>
|
||||
|
||||
<tr style="vertical-align: top;">
|
||||
<th class="width-medium pr-20 height-50">Veranstsaltungs-Konto</th>
|
||||
<td class="height-50"><input type="text" v-model="formData.eventAccount" class="width-full" />
|
||||
<ErrorText :message="errors.eventAccount" /></td>
|
||||
</tr>
|
||||
|
||||
<tr style="vertical-align: top;">
|
||||
<th class="width-medium pr-20 height-50">Veranstaltungs-IBAN</th>
|
||||
<td class="height-50"><input type="text" v-model="formData.eventIban" class="width-full" />
|
||||
<ErrorText :message="errors.eventIban" /></td>
|
||||
</tr>
|
||||
|
||||
<tr style="vertical-align: top;">
|
||||
<td colspan="2" style="font-weight: bold;">
|
||||
<input type="checkbox" v-model="formData.eventPayDirectly">
|
||||
Teilnehmende zahlen direkt aufs Veranstaltungskonto
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr style="vertical-align: top;">
|
||||
<td colspan="2" style="font-weight: bold;">
|
||||
<input type="checkbox" v-model="formData.eventPayPerDay">
|
||||
Beitrag abhängig von Anwesenheitstagen
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="2" class="pt-20">
|
||||
<input type="button" value="Veranstaltung erstellen" @click="createEvent" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
</fieldset>
|
||||
</AppLayout>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
60
app/Domains/Event/Views/Details.vue
Normal file
60
app/Domains/Event/Views/Details.vue
Normal file
@@ -0,0 +1,60 @@
|
||||
<script setup>
|
||||
import {reactive, inject, onMounted} from 'vue';
|
||||
import AppLayout from "../../../../resources/js/layouts/AppLayout.vue";
|
||||
import ShadowedBox from "../../../Views/Components/ShadowedBox.vue";
|
||||
import TabbedPage from "../../../Views/Components/TabbedPage.vue";
|
||||
import ListCostUnits from "../../CostUnit/Views/Partials/ListCostUnits.vue";
|
||||
import Overview from "./Partials/Overview.vue";
|
||||
|
||||
const props = defineProps({
|
||||
event: Object,
|
||||
})
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
title: 'Übersicht',
|
||||
component: Overview,
|
||||
endpoint: "/api/v1/event/details/" + props.event.id + '/summary',
|
||||
},
|
||||
{
|
||||
title: 'Alle Teilnehmendenden',
|
||||
component: ListCostUnits,
|
||||
endpoint: "/api/v1/cost-unit/open/current-running-jobs",
|
||||
},
|
||||
{
|
||||
title: 'Teilis nach Stamm',
|
||||
component: ListCostUnits,
|
||||
endpoint: "/api/v1/cost-unit/open/closed-cost-units",
|
||||
},
|
||||
{
|
||||
title: 'Teilis nach Teili-Gruppe',
|
||||
component: ListCostUnits,
|
||||
endpoint: "/api/v1/cost-unit/open/archived-cost-units",
|
||||
},
|
||||
{
|
||||
title: 'Abgemeldete Teilis',
|
||||
component: ListCostUnits,
|
||||
endpoint: "/api/v1/cost-unit/open/archived-cost-units",
|
||||
},
|
||||
{
|
||||
title: 'Zusätze',
|
||||
component: ListCostUnits,
|
||||
endpoint: "/api/v1/cost-unit/open/archived-cost-units",
|
||||
},
|
||||
]
|
||||
|
||||
onMounted(() => {
|
||||
if (undefined !== props.message) {
|
||||
toast.success(props.message)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppLayout :title="'Veranstaltungsdetails ' + props.event.name">
|
||||
<shadowed-box style="width: 95%; margin: 20px auto; padding: 20px; overflow-x: hidden;">
|
||||
<tabbed-page :tabs="tabs" />
|
||||
|
||||
</shadowed-box>
|
||||
</AppLayout>
|
||||
</template>
|
||||
258
app/Domains/Event/Views/Partials/CommonSettings.vue
Normal file
258
app/Domains/Event/Views/Partials/CommonSettings.vue
Normal file
@@ -0,0 +1,258 @@
|
||||
<script setup>
|
||||
import {onMounted, reactive, ref} from "vue";
|
||||
import ErrorText from "../../../../Views/Components/ErrorText.vue";
|
||||
import AmountInput from "../../../../Views/Components/AmountInput.vue";
|
||||
import {request} from "../../../../../resources/js/components/HttpClient.js";
|
||||
import {toast} from "vue3-toastify";
|
||||
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
|
||||
const props = defineProps({
|
||||
event: Object,
|
||||
})
|
||||
|
||||
|
||||
const dynmicProps = reactive({
|
||||
localGroups: [],
|
||||
eatingHabits:[]
|
||||
});
|
||||
|
||||
const contributingLocalGroups = ref([])
|
||||
const eatingHabits = ref([]);
|
||||
|
||||
const errors = reactive({})
|
||||
|
||||
const formData = reactive({
|
||||
contributingLocalGroups: contributingLocalGroups.value,
|
||||
eventName: props.event.name,
|
||||
eventLocation: props.event.location,
|
||||
postalCode: props.event.postalCode,
|
||||
email: props.event.email,
|
||||
earlyBirdEnd: props.event.earlyBirdEnd.internal,
|
||||
registrationFinalEnd: props.event.registrationFinalEnd.internal,
|
||||
alcoholicsAge: props.event.alcoholicsAge,
|
||||
eatingHabits: eatingHabits.value,
|
||||
sendWeeklyReports: props.event.sendWeeklyReports,
|
||||
registrationAllowed: props.event.registrationAllowed,
|
||||
flatSupport: props.event.flatSupportEdit,
|
||||
supportPerson: props.event.supportPersonEdit,
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
const response = await fetch('/api/v1/core/retrieve-event-setting-data');
|
||||
const data = await response.json();
|
||||
Object.assign(dynmicProps, data);
|
||||
|
||||
contributingLocalGroups.value = props.event.contributingLocalGroups?.map(t => t.id) ?? []
|
||||
eatingHabits.value = props.event.eatingHabits?.map(t => t.id) ?? []
|
||||
});
|
||||
|
||||
async function save() {
|
||||
const response = await request('/api/v1/event/details/' + props.event.id + '/common-settings', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: {
|
||||
eventName: formData.eventName,
|
||||
eventLocation: formData.eventLocation,
|
||||
postalCode: formData.postalCode,
|
||||
email: formData.email,
|
||||
earlyBirdEnd: formData.earlyBirdEnd,
|
||||
registrationFinalEnd: formData.registrationFinalEnd,
|
||||
alcoholicsAge: formData.alcoholicsAge,
|
||||
sendWeeklyReports: formData.sendWeeklyReports,
|
||||
registrationAllowed: formData.registrationAllowed,
|
||||
flatSupport: formData.flatSupport,
|
||||
supportPerson: formData.supportPerson,
|
||||
contributingLocalGroups: contributingLocalGroups.value,
|
||||
eatingHabits: eatingHabits.value,
|
||||
}
|
||||
})
|
||||
|
||||
if (response.status === 'success') {
|
||||
toast.success('Einstellungen wurden erfolgreich gespeichert.')
|
||||
emit('close')
|
||||
} else {
|
||||
toast.error('Beim Speichern ist ein Fehler aufgetreten.')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h2>Einstellungen</h2>
|
||||
<div class="container">
|
||||
<div class="row top">
|
||||
<div class="left">
|
||||
<table class="event-settings-table" style="width: 80%;">
|
||||
<tr>
|
||||
<th>Veranstaltungsname</th>
|
||||
<td>
|
||||
<input type="text" v-model="formData.eventName" class="width-full" /><br />
|
||||
<ErrorText :message="errors.eventName" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Veranstaltungsort</th>
|
||||
<td>
|
||||
<input type="text" v-model="formData.eventLocation" class="width-full" /><br />
|
||||
<ErrorText :message="errors.eventLocation" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Postleitzahl des Veranstaltungsorts</th>
|
||||
<td>
|
||||
<input type="text" v-model="formData.postalCode" class="width-full" /><br />
|
||||
<ErrorText :message="errors.eventPostalCode" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>E-Mail-Adresse der Veranstaltungsleitung</th>
|
||||
<td>
|
||||
<input type="text" v-model="formData.email" class="width-full" /><br />
|
||||
<ErrorText :message="errors.eventEmail" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Ende der EarlyBird-Phase</th>
|
||||
<td>
|
||||
<input type="date" v-model="formData.earlyBirdEnd" class="width-full" /><br />
|
||||
<ErrorText :message="errors.earlyBirdEnd" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Finaler Anmeldeschluss</th>
|
||||
<td>
|
||||
<input type="date" v-model="formData.registrationFinalEnd" class="width-full" /><br />
|
||||
<ErrorText :message="errors.registrationFinalEnd" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Fördermittel</th>
|
||||
<td>
|
||||
<amountInput v-model="formData.supportPerson" clasS="width-small" /> Euro p.P. / Tag
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Zuschüsse</th>
|
||||
<td>
|
||||
<amountInput v-model="formData.flatSupport" clasS="width-small" /> Euro pauschal
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Mindestalter für Alkoholkonsum</th>
|
||||
<td>
|
||||
<input type="number" v-model="formData.alcoholicsAge" class="width-tiny" /><br />
|
||||
<ErrorText :message="errors.alcoholicsAge" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="2" style="height: 25px !important;">
|
||||
<input type="checkbox" v-model="formData.sendWeeklyReports" id="sendWeeklyReports" />
|
||||
<label for="sendWeeklyReports">Wöchentliche Zusammenfassung per E-Mail an Stämme schicken</label>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<input type="checkbox" v-model="formData.registrationAllowed" id="registrationAllowed" />
|
||||
<label for="registrationAllowed">Veranstaltung ist für Anmeldungen geöffnet</label>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="right">
|
||||
<table>
|
||||
<tr>
|
||||
<th>Teilnehmende Stämme</th>
|
||||
</tr>
|
||||
<tr v-for="localGroup in dynmicProps.localGroups">
|
||||
<td>
|
||||
<input type="checkbox" :id="'localgroup_' + localGroup.id" :value="localGroup.id" v-model="contributingLocalGroups" />
|
||||
<label style="padding-left: 5px;" :for="'localgroup_' + localGroup.id">{{localGroup.name}}</label>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th style="padding-top: 40px !important;">Angebotene Ernährung</th>
|
||||
</tr>
|
||||
|
||||
<tr v-for="eatingHabit in dynmicProps.eatingHabits">
|
||||
<td>
|
||||
<input type="checkbox" :id="'eatinghabit' + eatingHabit.id" :value="eatingHabit.id" v-model="eatingHabits" />
|
||||
<label style="padding-left: 5px;" :for="'eatinghabit' + eatingHabit.id">{{eatingHabit.name}}</label>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row bott">
|
||||
<input type="button" value="Speichern" @click="save" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px; /* Abstand zwischen den Zeilen */
|
||||
width: 95%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
gap: 10px; /* Abstand zwischen den Spalten */
|
||||
}
|
||||
|
||||
.row.top .left {
|
||||
flex: 0 0 70%; /* feste Breite von 80% */
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.row.top .right {
|
||||
flex: 0 0 30%; /* feste Breite von 20% */
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.row.bottom {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.event-settings-table {
|
||||
|
||||
}
|
||||
|
||||
.event-settings-table tr {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.event-settings-table td {
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.event-settings-table th {
|
||||
vertical-align: top;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
</style>
|
||||
63
app/Domains/Event/Views/Partials/EventManagement.vue
Normal file
63
app/Domains/Event/Views/Partials/EventManagement.vue
Normal file
@@ -0,0 +1,63 @@
|
||||
<script setup>
|
||||
|
||||
import {onMounted, reactive, ref} from "vue";
|
||||
import {toast} from "vue3-toastify";
|
||||
import {request} from "../../../../../resources/js/components/HttpClient.js";
|
||||
const selectedManagers = ref([])
|
||||
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
const props = defineProps({
|
||||
event: Object
|
||||
})
|
||||
|
||||
|
||||
const commonProps = reactive({
|
||||
activeUsers: [],
|
||||
});
|
||||
|
||||
|
||||
|
||||
onMounted(async () => {
|
||||
const response = await fetch('/api/v1/core/retrieve-global-data');
|
||||
const data = await response.json();
|
||||
Object.assign(commonProps, data);
|
||||
|
||||
selectedManagers.value = props.event.managers?.map(t => t.id) ?? []
|
||||
});
|
||||
|
||||
|
||||
async function updateManagers() {
|
||||
|
||||
const response = await request('/api/v1/event/details/' + props.event.id + '/event-managers', {
|
||||
method: "POST",
|
||||
body: {
|
||||
selectedManagers: selectedManagers.value,
|
||||
}
|
||||
});
|
||||
|
||||
if (response.status === 'success') {
|
||||
toast.success('Einstellungen wurden erfolgreich gespeichert.')
|
||||
emit('close')
|
||||
} else {
|
||||
toast.error('Beim Speichern ist ein Fehler aufgetreten.')
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h3>Aktionsleitung:</h3>
|
||||
<p v-for="user in commonProps.activeUsers">
|
||||
<input
|
||||
type="checkbox"
|
||||
:id="'user_' + user.id"
|
||||
:value="user.id"
|
||||
v-model="selectedManagers"
|
||||
/>
|
||||
<label :for="'user_' + user.id">{{user.fullname}}</label>
|
||||
</p>
|
||||
|
||||
<input type="button" value="Speichern" @click="updateManagers" />
|
||||
</template>
|
||||
|
||||
113
app/Domains/Event/Views/Partials/Overview.vue
Normal file
113
app/Domains/Event/Views/Partials/Overview.vue
Normal file
@@ -0,0 +1,113 @@
|
||||
<script setup>
|
||||
import {onMounted, reactive, ref} from "vue";
|
||||
import ParticipationFees from "./ParticipationFees.vue";
|
||||
import ParticipationSummary from "./ParticipationSummary.vue";
|
||||
import CommonSettings from "./CommonSettings.vue";
|
||||
import EventManagement from "./EventManagement.vue";
|
||||
|
||||
const props = defineProps({
|
||||
data: Object,
|
||||
})
|
||||
|
||||
const dynamicProps = reactive({
|
||||
event : null,
|
||||
});
|
||||
|
||||
const displayData = ref('main');
|
||||
|
||||
async function showMain() {
|
||||
const response = await fetch("/api/v1/event/details/" + props.data.event.id + '/summary');
|
||||
const data = await response.json();
|
||||
Object.assign(dynamicProps, data);
|
||||
displayData.value = 'main';
|
||||
}
|
||||
|
||||
async function showCommonSettings() {
|
||||
displayData.value = 'commonSettings';
|
||||
}
|
||||
|
||||
async function showParticipationFees() {
|
||||
displayData.value = 'participationFees';
|
||||
}
|
||||
|
||||
async function showEventManagement() {
|
||||
displayData.value = 'eventManagement';
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
const response = await fetch("/api/v1/event/details/" + props.data.event.id + '/summary');
|
||||
const data = await response.json();
|
||||
Object.assign(dynamicProps, data);
|
||||
|
||||
console.log(dynamicProps.event)
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ParticipationFees v-if="displayData === 'participationFees'" :event="dynamicProps.event" @close="showMain" />
|
||||
<CommonSettings v-else-if="displayData === 'commonSettings'" :event="dynamicProps.event" @close="showMain" />
|
||||
<EventManagement v-else-if="displayData === 'eventManagement'" :event="dynamicProps.event" @close="showMain" />
|
||||
|
||||
|
||||
|
||||
<div class="event-flexbox" v-else>
|
||||
<div class="event-flexbox-row top">
|
||||
<div class="left"><ParticipationSummary :event="dynamicProps.event" /></div>
|
||||
<div class="right">
|
||||
<input type="button" value="Erste-Hilfe-Liste (PDF)" /><br/>
|
||||
<input type="button" value="Teili-Liste (CSV)" /><br/>
|
||||
<input type="button" value="KSV-Daten (CSV)" /><br/>
|
||||
<input type="button" value="Küchenübersicht (PDF)" /><br/>
|
||||
<input type="button" value="Beitragsliste (PDF)" /><br/>
|
||||
<input type="button" value="Getränkeliste (PDF)" /><br/>
|
||||
<input type="button" value="Foto-Erlaubnis (PDF)" /><br/>
|
||||
<input type="button" class="fix-button" value="Zahlungserinnerung senden" /><br/>
|
||||
<input type="button" class="deny-button" value="Letzte Mahnung senden" /><br/>
|
||||
<input type="button" value="Rundmail senden" /><br/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="event-flexbox-row bottom">
|
||||
<label style="font-size: 9pt;" class="link" @click="showCommonSettings">Allgemeine Einstellungen</label>
|
||||
<label style="font-size: 9pt;" class="link" @click="showEventManagement">Veranstaltungsleitung</label>
|
||||
<label style="font-size: 9pt;" class="link" @click="showParticipationFees">Teilnahmegebühren</label>
|
||||
<a style="font-size: 9pt;" class="link" :href="'/cost-unit/' + props.data.event.costUnit.id">Ausgabenübersicht</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.event-flexbox {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
width: 95%;
|
||||
margin: 20px auto 0;
|
||||
}
|
||||
|
||||
.event-flexbox-row {
|
||||
display: flex;
|
||||
gap: 10px; /* Abstand zwischen den Spalten */
|
||||
}
|
||||
|
||||
.event-flexbox-row.top .left {
|
||||
flex: 0 0 calc(100% - 300px);
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.event-flexbox-row.top .right {
|
||||
flex: 0 0 250px; /* feste Breite von 20% */
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.event-flexbox-row.bottom {
|
||||
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.event-flexbox-row.top .right input[type="button"] {
|
||||
width: 100% !important;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
231
app/Domains/Event/Views/Partials/ParticipationFees.vue
Normal file
231
app/Domains/Event/Views/Partials/ParticipationFees.vue
Normal file
@@ -0,0 +1,231 @@
|
||||
<script setup>
|
||||
import AppLayout from "../../../../../resources/js/layouts/AppLayout.vue";
|
||||
import ShadowedBox from "../../../../Views/Components/ShadowedBox.vue";
|
||||
import {reactive, watch} from "vue";
|
||||
import AmountInput from "../../../../Views/Components/AmountInput.vue";
|
||||
import ErrorText from "../../../../Views/Components/ErrorText.vue";
|
||||
import {toast} from "vue3-toastify";
|
||||
import {request} from "../../../../../resources/js/components/HttpClient.js";
|
||||
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
const props = defineProps({
|
||||
event: Object,
|
||||
})
|
||||
|
||||
const errors = reactive({})
|
||||
const formData = reactive({
|
||||
"pft_1_active": true,
|
||||
"pft_1_amount": props.event.participationFee_1.amount,
|
||||
"pft_1_description": props.event.participationFee_1.description,
|
||||
|
||||
"pft_2_active": props.event.participationFee_2.active,
|
||||
"pft_2_amount": props.event.participationFee_2.amount,
|
||||
"pft_2_description": props.event.participationFee_2.description,
|
||||
|
||||
"pft_3_active": props.event.participationFee_3.active,
|
||||
"pft_3_amount": props.event.participationFee_3.amount,
|
||||
"pft_3_description": props.event.participationFee_3.description,
|
||||
|
||||
"pft_4_active": props.event.participationFee_4.active,
|
||||
"pft_4_amount": props.event.participationFee_4.amount,
|
||||
"pft_4_description": props.event.participationFee_4.description,
|
||||
|
||||
'maxAmount': props.event.maxAmount,
|
||||
|
||||
})
|
||||
|
||||
function validateInput() {
|
||||
var noErrors = true;
|
||||
|
||||
if (formData.pft_1_description === '' && !props.event.solidarityPayment) {
|
||||
errors.pft_1_description = 'Eine Beschreibung für diese Gruppe ist erforderlich';
|
||||
noErrors = false;
|
||||
}
|
||||
|
||||
if (formData.pft_2_description === '' && formData.pft_2_active && !props.event.solidarityPayment) {
|
||||
errors.pft_2_description = 'Eine Beschreibung für diese Gruppe ist erforderlich';
|
||||
noErrors = false;
|
||||
}
|
||||
|
||||
if (formData.pft_3_description === '' && formData.pft_3_active && !props.event.solidarityPayment) {
|
||||
errors.pft_3_description = 'Eine Beschreibung für diese Gruppe ist erforderlich';
|
||||
noErrors = false;
|
||||
}
|
||||
|
||||
if (formData.pft_4_description === '' && formData.pft_4_active) {
|
||||
errors.pft_4_description = 'Eine Beschreibung für diese Gruppe ist erforderlich';
|
||||
noErrors = false;
|
||||
}
|
||||
|
||||
return noErrors;
|
||||
|
||||
}
|
||||
|
||||
async function saveParticipationFees() {
|
||||
if (!validateInput()) {
|
||||
toast.error('Bitte prüfe alle Eingaben auf Fehler')
|
||||
return;
|
||||
}
|
||||
|
||||
const data = await request('/api/v1/event/details/' + props.event.id + '/participation-fees', {
|
||||
method: "POST",
|
||||
body: {
|
||||
event_id: props.event.id,
|
||||
pft_1_active: formData.pft_1_active,
|
||||
pft_1_amount: formData.pft_1_amount,
|
||||
pft_1_description: formData.pft_1_description,
|
||||
|
||||
pft_2_active: formData.pft_2_active,
|
||||
pft_2_amount: formData.pft_2_amount,
|
||||
pft_2_description: formData.pft_2_description,
|
||||
|
||||
pft_3_active: formData.pft_3_active,
|
||||
pft_3_amount: formData.pft_3_amount,
|
||||
pft_3_description: formData.pft_3_description,
|
||||
|
||||
pft_4_active: formData.pft_4_active,
|
||||
pft_4_amount: formData.pft_4_amount,
|
||||
pft_4_description: formData.pft_4_description,
|
||||
|
||||
maxAmount: formData.maxAmount,
|
||||
}
|
||||
})
|
||||
|
||||
emit('close')
|
||||
}
|
||||
|
||||
function recalculateMaxAmount(newValue) {
|
||||
if (formData.maxAmount === 0) return;
|
||||
|
||||
var newAmount = parseFloat(newValue.replace(',', '.'));
|
||||
if (props.event.payPerDay) {
|
||||
newAmount = newAmount * props.event.duration;
|
||||
}
|
||||
|
||||
var currentMaxAmount = formData.maxAmount.replace(',', '.');
|
||||
|
||||
if (newAmount > currentMaxAmount) {
|
||||
formData.maxAmount = newAmount.toFixed(2).replace('.', ',');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<table style="width: 100%;">
|
||||
<tr>
|
||||
<td>Aktiv</td>
|
||||
<td>Preisgruppe</td>
|
||||
<td>Betrag</td>
|
||||
<td>Beschreibung</td>
|
||||
</tr>
|
||||
<tr style="height: 65px; vertical-align: top">
|
||||
<td>
|
||||
<input type="checkbox" v-model="formData.participationFeeType_1" checked disabled/>
|
||||
</td>
|
||||
<td v-if="props.event.solidarityPayment">
|
||||
Regulärer Beitrag
|
||||
</td>
|
||||
<td v-else>
|
||||
Teilnehmende
|
||||
</td>
|
||||
<td>
|
||||
<AmountInput v-model="formData.pft_1_amount" class="width-small" @blur="recalculateMaxAmount(formData.pft_1_amount)" />
|
||||
<label v-if="props.event.payPerDay"> Euro / Tag</label>
|
||||
<label v-else> Euro Gesamt</label>
|
||||
</td>
|
||||
<td>
|
||||
<input v-if="!props.event.solidarityPayment" type="text" v-model="formData.pft_1_description" style="width: 300px;" />
|
||||
<label v-else></label>
|
||||
<ErrorText :message="errors.pft_1_description" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr style="height: 65px; vertical-align: top;">
|
||||
<td>
|
||||
<input id="use_pft_2" type="checkbox" v-model="formData.pft_2_active" :checked="formData.pft_2_active" />
|
||||
</td>
|
||||
<td v-if="props.event.solidarityPayment">
|
||||
<label for="use_pft_2" style="cursor: default">
|
||||
Solidaritätsbeitrag
|
||||
</label>
|
||||
</td>
|
||||
<td v-else>
|
||||
<label for="use_pft_2" style="cursor: default">
|
||||
Kernteam
|
||||
</label>
|
||||
</td>
|
||||
<td v-if="formData.pft_2_active">
|
||||
<AmountInput v-model="formData.pft_2_amount" class="width-small" @blur="recalculateMaxAmount(formData.pft_2_amount)" />
|
||||
<label v-if="props.event.payPerDay"> Euro / Tag</label>
|
||||
<label v-else> Euro Gesamt</label>
|
||||
</td>
|
||||
<td v-if="formData.pft_2_active">
|
||||
<input v-if="!props.event.solidarityPayment" type="text" v-model="formData.pft_2_description" style="width: 300px;" />
|
||||
<label v-else></label>
|
||||
<ErrorText :message="errors.pft_2_description" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr style="height: 65px; vertical-align: top;">
|
||||
<td>
|
||||
<input id="use_pft_3" type="checkbox" v-model="formData.pft_3_active" :checked="formData.pft_3_active" />
|
||||
</td>
|
||||
<td v-if="props.event.solidarityPayment">
|
||||
<label for="use_pft_3" style="cursor: default">
|
||||
Reduzierter Beitrag
|
||||
</label>
|
||||
</td>
|
||||
<td v-else>
|
||||
<label for="use_pft_3" style="cursor: default">
|
||||
Unterstützende
|
||||
</label>
|
||||
</td>
|
||||
<td v-if="formData.pft_3_active">
|
||||
<AmountInput v-model="formData.pft_3_amount" class="width-small" @blur="recalculateMaxAmount(formData.pft_3_amount)" />
|
||||
<label v-if="props.event.payPerDay"> Euro / Tag</label>
|
||||
<label v-else> Euro Gesamt</label>
|
||||
</td>
|
||||
<td v-if="formData.pft_3_active">
|
||||
<input v-if="!props.event.solidarityPayment" type="text" v-model="formData.pft_3_description" style="width: 300px;" />
|
||||
<label v-else>Nach Verfügbarkeit</label>
|
||||
<ErrorText :message="errors.pft_3_description" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr style="height: 65px; vertical-align: top;" v-if="!props.event.solidarityPayment">
|
||||
<td>
|
||||
<input id="use_pft_4" type="checkbox" v-model="formData.pft_4_active" :checked="formData.pft_4_active" />
|
||||
</td>
|
||||
<td>
|
||||
<label for="use_pft_4" style="cursor: default">
|
||||
Sonstige
|
||||
</label>
|
||||
</td>
|
||||
<td v-if="formData.pft_4_active">
|
||||
<AmountInput v-model="formData.pft_4_amount" class="width-small" @blur="recalculateMaxAmount(formData.pft_4_amount)" />
|
||||
<label v-if="props.event.payPerDay"> Euro / Tag</label>
|
||||
<label v-else> Euro Gesamt</label>
|
||||
</td>
|
||||
<td v-if="formData.pft_4_active">
|
||||
<input type="text" v-model="formData.pft_4_description" style="width: 300px;" />
|
||||
<ErrorText :message="errors.pft_4_description" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
Maximaler Beitrag für Veranstaltung:
|
||||
</td>
|
||||
<td colspan="2">
|
||||
<AmountInput v-model="formData.maxAmount" class="width-small" /> Euro Gesamt
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<input type="button" value="Speichern" @click="saveParticipationFees" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</template>
|
||||
125
app/Domains/Event/Views/Partials/ParticipationSummary.vue
Normal file
125
app/Domains/Event/Views/Partials/ParticipationSummary.vue
Normal file
@@ -0,0 +1,125 @@
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
event: Object
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h2>Übersicht</h2>
|
||||
<div class="participant-flexbox">
|
||||
<div class="participant-flexbox-row top">
|
||||
<div class="left">
|
||||
<h3>Teilnehmende</h3>
|
||||
<table class="participant-income-table" style="margin-bottom: 40px;">
|
||||
<tr>
|
||||
<th>Teili</th>
|
||||
<td>7 Personen:</td>
|
||||
<td>35,00 Euro</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Teili</th>
|
||||
<td>7 Personen:</td>
|
||||
<td>35,00 Euro</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Teili</th>
|
||||
<td>7 Personen:</td>
|
||||
<td>35,00 Euro</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th colspan="2">Sonstiges</th>
|
||||
<td>{{ props.event.flatSupport }}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th style="padding-bottom: 20px" colspan="2">Förderung</th>
|
||||
<td style="padding-bottom: 20px">
|
||||
{{ props.event.supportPersonCalced }}<br />
|
||||
<label style="font-size: 9pt;">({{ props.event.supportPerson }} / Tag p.P.)</label>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<th colspan="2" style="border-width: 1px; border-bottom-style: solid">Gesamt</th>
|
||||
<td style="font-weight: bold; border-width: 1px; border-bottom-style: solid">{{ props.event.totalIncome }}</td>
|
||||
</tr>
|
||||
|
||||
<tr style="color:#4caf50;" v-if="props.event.totalBalance.value >= 0">
|
||||
<th style="padding-top: 20px; font-size: 12pt !important;" colspan="2">Bilanz</th>
|
||||
<td style="font-weight: bold; padding-top: 20px; font-size: 12pt !important;">{{ props.event.totalBalance.text }}</td>
|
||||
</tr>
|
||||
|
||||
<tr style="color:#f44336;" v-else>
|
||||
<th style="padding-top: 20px; font-size: 12pt !important;" colspan="2">Bilanz</th>
|
||||
<td style="font-weight: bold; padding-top: 20px; font-size: 12pt !important;">{{ props.event.totalBalance.text }}</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<strong>Anmelde-URL: {{props.event.url}}</strong>
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
<h3>Ausgaben</h3>
|
||||
<table class="event-payment-table">
|
||||
<tr v-for="amount in props.event.costUnit.amounts">
|
||||
<th>{{amount.name}}</th>
|
||||
<td>{{amount.string}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th style="color:#f44336; border-width: 1px; border-bottom-style: solid; padding-top: 20px">Gesamt</th>
|
||||
<td style="color:#f44336; border-width: 1px; border-bottom-style: solid; padding-top: 20px; font-weight: bold">{{props.event.costUnit.overAllAmount.text}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.participant-flexbox {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
width: 95%;
|
||||
margin: 20px auto 0;
|
||||
}
|
||||
|
||||
.participant-flexbox-row {
|
||||
display: flex;
|
||||
gap: 10px; /* Abstand zwischen den Spalten */
|
||||
}
|
||||
|
||||
.participant-flexbox-row.top .left {
|
||||
flex: 0 0 50%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.participant-flexbox.top .right {
|
||||
flex: 0 0 50%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.participant-income-table,
|
||||
.event-payment-table {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.participant-income-table th {
|
||||
width: 20px;
|
||||
font-size: 11pt !important;
|
||||
}
|
||||
|
||||
.participant-income-table tr td:first-child {
|
||||
width: 25px !important;
|
||||
font-size: 11pt;
|
||||
}
|
||||
</style>
|
||||
15
app/Enumerations/ParticipationFeeType.php
Normal file
15
app/Enumerations/ParticipationFeeType.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Scopes\CommonModel;
|
||||
|
||||
class ParticipationFeeType extends CommonModel {
|
||||
public const PARTICIPATION_FEE_TYPE_FIXED = 'fixed';
|
||||
public const PARTICIPATION_FEE_TYPE_SOLIDARITY = 'solidarity';
|
||||
|
||||
protected $fillable = [
|
||||
'slug',
|
||||
'name',
|
||||
];
|
||||
}
|
||||
18
app/Enumerations/ParticipationType.php
Normal file
18
app/Enumerations/ParticipationType.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Scopes\CommonModel;
|
||||
|
||||
class ParticipationType extends CommonModel {
|
||||
public const PARTICIPATION_TYPE_PARTICIPANT = 'participant';
|
||||
public const PARTICIPATION_TYPE_TEAM = 'team';
|
||||
public const PARTICIPATION_TYPE_VOLUNTEER = 'volunteer';
|
||||
public const PARTICIPATION_TYPE_OTHER = 'other';
|
||||
|
||||
|
||||
protected $fillable = [
|
||||
'slug',
|
||||
'name',
|
||||
];
|
||||
}
|
||||
@@ -8,8 +8,8 @@ use App\Models\User;
|
||||
|
||||
class DevelopmentDataSeeder {
|
||||
public function execute() {
|
||||
$this->installTenants();
|
||||
$this->installUsers();
|
||||
//$this->installTenants();
|
||||
//$this->installUsers();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -8,22 +8,51 @@ use App\Enumerations\EatingHabit;
|
||||
use App\Enumerations\FirstAidPermission;
|
||||
use App\Enumerations\InvoiceStatus;
|
||||
use App\Enumerations\InvoiceType;
|
||||
use App\Enumerations\ParticipationFeeType;
|
||||
use App\Enumerations\ParticipationType;
|
||||
use App\Enumerations\SwimmingPermission;
|
||||
use App\Enumerations\UserRole;
|
||||
use App\Models\Tenant;
|
||||
|
||||
class ProductionDataSeeder {
|
||||
public function execute() {
|
||||
$this->installCronTypes();
|
||||
/*$this->installCronTypes();
|
||||
$this->installUserRoles();
|
||||
$this->installCostUnitTypes();
|
||||
$this->installSwimmingPermissions();
|
||||
$this->installEatingHabits();
|
||||
$this->installFirstAidPermissions();
|
||||
$this->installTenants();
|
||||
$this->installInvoiceMetaData();
|
||||
$this->installInvoiceMetaData();*/
|
||||
$this->installParticipationFeeTypes();
|
||||
$this->installParticipationTypes();
|
||||
}
|
||||
|
||||
private function installParticipationTypes() {
|
||||
ParticipationType::create([
|
||||
'slug' => ParticipationType::PARTICIPATION_TYPE_PARTICIPANT,
|
||||
'name' => 'Teilnehmende'
|
||||
]);
|
||||
|
||||
ParticipationType::create([
|
||||
'slug' => ParticipationType::PARTICIPATION_TYPE_TEAM,
|
||||
'name' => 'Kernteam'
|
||||
]);
|
||||
|
||||
ParticipationType::create([
|
||||
'slug' => ParticipationType::PARTICIPATION_TYPE_VOLUNTEER,
|
||||
'name' => 'Unterstützende'
|
||||
]);
|
||||
|
||||
ParticipationType::create([
|
||||
'slug' => ParticipationType::PARTICIPATION_TYPE_OTHER,
|
||||
'name' => 'Sonstige'
|
||||
]);
|
||||
}
|
||||
|
||||
private function installParticipationFeeTypes() {
|
||||
ParticipationFeeType::create(['slug' => ParticipationFeeType::PARTICIPATION_FEE_TYPE_SOLIDARITY, 'name' => 'Solidaritätsprinzip']);
|
||||
ParticipationFeeType::create(['slug' => ParticipationFeeType::PARTICIPATION_FEE_TYPE_FIXED, 'name' => 'Festpreis']);
|
||||
}
|
||||
|
||||
private function installUserRoles() {
|
||||
|
||||
167
app/Models/Event.php
Normal file
167
app/Models/Event.php
Normal file
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Casts\AmountCast;
|
||||
use App\Enumerations\EatingHabit;
|
||||
use App\Enumerations\ParticipationFeeType;
|
||||
use App\RelationModels\EventParticipationFee;
|
||||
use App\Scopes\CommonModel;
|
||||
use App\Scopes\InstancedModel;
|
||||
use DateTime;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
|
||||
/**
|
||||
* @property string $tenant
|
||||
* @property int $cost_unit_id
|
||||
* @property string $name
|
||||
* @property string $location
|
||||
* @property string $postal_code
|
||||
* @property string $email
|
||||
* @property DateTime $start_date
|
||||
* @property DateTime $end_date
|
||||
* @property DateTime $early_bird_end
|
||||
* @property DateTime $registration_final_end
|
||||
* @property int $early_bird_end_amount_increase
|
||||
* @property int $registration_final_end_amount_increase
|
||||
* @property string $account_owner
|
||||
* @property string $account_iban
|
||||
* @property boolean $registration_allowed
|
||||
* @property string $participation_fee_type
|
||||
* @property float $total_max_amount
|
||||
* @property string $registration_link
|
||||
* @property boolean $pay_per_day
|
||||
* @property boolean $pay_direct
|
||||
* @property boolean $send_weekly_report
|
||||
* @property int $participation_fee_1
|
||||
* @property int $participation_fee_2
|
||||
* @property int $participation_fee_3
|
||||
* @property int $participation_fee_4
|
||||
* @property float $support_per_person
|
||||
* @property float $support_flat
|
||||
* @property int $alcoholics_age
|
||||
* @property boolean $archived
|
||||
*/
|
||||
class Event extends InstancedModel
|
||||
{
|
||||
protected $table = 'events';
|
||||
|
||||
protected $fillable = [
|
||||
'tenant',
|
||||
'cost_unit_id',
|
||||
'name',
|
||||
'location',
|
||||
'postal_code',
|
||||
'email',
|
||||
'start_date',
|
||||
'end_date',
|
||||
'early_bird_end',
|
||||
'registration_final_end',
|
||||
'early_bird_end_amount_increase',
|
||||
'registration_final_end_amount_increase',
|
||||
'account_owner',
|
||||
'account_iban',
|
||||
'registration_allowed',
|
||||
'participation_fee_type',
|
||||
'total_max_amount',
|
||||
'registration_link',
|
||||
'pay_per_day',
|
||||
'pay_direct',
|
||||
'send_weekly_report',
|
||||
'participation_fee_1',
|
||||
'participation_fee_2',
|
||||
'participation_fee_3',
|
||||
'participation_fee_4',
|
||||
'support_per_person',
|
||||
'support_flat',
|
||||
'alcoholics_age',
|
||||
'archived',
|
||||
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'start_date' => 'datetime',
|
||||
'end_date' => 'datetime',
|
||||
'early_bird_end' => 'datetime',
|
||||
'registration_final_end' => 'datetime',
|
||||
|
||||
'early_bird_end_amount_increase' => 'integer',
|
||||
'registration_final_end_amount_increase' => 'integer',
|
||||
'alcoholics_age' => 'integer',
|
||||
|
||||
'registration_allowed' => 'boolean',
|
||||
'pay_per_day' => 'boolean',
|
||||
'pay_direct' => 'boolean',
|
||||
'send_weekly_report' => 'boolean',
|
||||
'archived' => 'boolean',
|
||||
|
||||
'support_per_person' => AmountCast::class,
|
||||
'support_flat' => AmountCast::class,
|
||||
'total_max_amount' => AmountCast::class,
|
||||
];
|
||||
|
||||
public function tenant(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Tenant::class, 'tenant', 'slug');
|
||||
}
|
||||
|
||||
public function costUnit(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(CostUnit::class);
|
||||
}
|
||||
|
||||
public function participationFeeType(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ParticipationFeeType::class, 'participation_fee_type', 'slug');
|
||||
}
|
||||
|
||||
public function participationFee1(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(EventParticipationFee::class, 'participation_fee_1');
|
||||
}
|
||||
|
||||
public function participationFee2(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(EventParticipationFee::class, 'participation_fee_2');
|
||||
}
|
||||
|
||||
public function participationFee3(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(EventParticipationFee::class, 'participation_fee_3');
|
||||
}
|
||||
|
||||
public function participationFee4(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(EventParticipationFee::class, 'participation_fee_4');
|
||||
}
|
||||
|
||||
public function localGroups() : BelongsToMany{
|
||||
return $this->belongsToMany(Tenant::class, 'event_local_groups', 'event_id', 'local_group_id');
|
||||
}
|
||||
|
||||
public function eatingHabits() : BelongsToMany{
|
||||
return $this->belongsToMany(EatingHabit::class, 'event_allowed_eating_habits', 'event_id', 'eating_habit_id');
|
||||
}
|
||||
|
||||
public function resetContributingLocalGroups() {
|
||||
$this->localGroups()->detach();
|
||||
$this->save();
|
||||
}
|
||||
|
||||
public function resetAllowedEatingHabits() {
|
||||
$this->eatingHabits()->detach();
|
||||
$this->save();
|
||||
}
|
||||
|
||||
public function resetMangers() {
|
||||
$this->eventManagers()->detach();
|
||||
$this->save();
|
||||
}
|
||||
|
||||
public function eventManagers() : BelongsToMany {
|
||||
return $this->belongsToMany(User::class, 'event_managers', 'event_id', 'user_id')
|
||||
->withTimestamps();
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,15 @@
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Enumerations\EatingHabit;
|
||||
use App\Enumerations\InvoiceType;
|
||||
use App\Enumerations\UserRole;
|
||||
use App\Models\Tenant;
|
||||
use App\Models\User;
|
||||
use App\Repositories\EventRepository;
|
||||
use App\Repositories\PageTextRepository;
|
||||
use App\Resources\UserResource;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
@@ -98,6 +102,9 @@ class GlobalDataProvider {
|
||||
}
|
||||
|
||||
private function generateNavbar() : array {
|
||||
$eventRepository = new EventRepository();
|
||||
|
||||
|
||||
$navigation = [
|
||||
'personal' => [],
|
||||
'common' => [],
|
||||
@@ -116,6 +123,14 @@ class GlobalDataProvider {
|
||||
) {
|
||||
$navigation['costunits'][] = ['url' => '/cost-unit/list', 'display' => 'Kostenstellen'];
|
||||
$navigation['costunits'][] = ['url' => '/cost-unit/create', 'display' => 'Neue laufende Tätigkeit'];
|
||||
|
||||
|
||||
foreach ($eventRepository->listAll() as $event) {
|
||||
$navigation['events'][] = ['url' => '/event/details/' . $event->id, 'display' => $event->name];
|
||||
}
|
||||
|
||||
$navigation['events'][] = ['url' => '/event/new', 'display' => 'Neue Veranstaltung'];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,5 +156,13 @@ class GlobalDataProvider {
|
||||
return $activeUsers;
|
||||
}
|
||||
|
||||
public function getEventSettingData() : JsonResponse {
|
||||
return response()->json(
|
||||
[
|
||||
'localGroups' => Tenant::where(['is_active_local_group' => true])->get(),
|
||||
'eatingHabits' => EatingHabit::all(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
11
app/RelationModels/EventEatingHabits.php
Normal file
11
app/RelationModels/EventEatingHabits.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\RelationModels;
|
||||
|
||||
use App\Scopes\CommonModel;
|
||||
|
||||
class EventEatingHabits extends CommonModel
|
||||
{
|
||||
protected $table = 'event_allowed_eating_habits';
|
||||
protected $fillable = ['event_id', 'eating_habit_id'];
|
||||
}
|
||||
10
app/RelationModels/EventLocalGroups.php
Normal file
10
app/RelationModels/EventLocalGroups.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace App\RelationModels;
|
||||
|
||||
use App\Scopes\CommonModel;
|
||||
|
||||
class EventLocalGroups extends CommonModel {
|
||||
protected $table = 'event_local_groups';
|
||||
protected $fillable = ['event_id', 'local_group_id'];
|
||||
}
|
||||
11
app/RelationModels/EventManagers.php
Normal file
11
app/RelationModels/EventManagers.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\RelationModels;
|
||||
|
||||
use App\Scopes\CommonModel;
|
||||
|
||||
class EventManagers extends CommonModel
|
||||
{
|
||||
protected $table = 'event_managers';
|
||||
protected $fillable = ['event_id', 'user_id'];
|
||||
}
|
||||
25
app/RelationModels/EventParticipationFee.php
Normal file
25
app/RelationModels/EventParticipationFee.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\RelationModels;
|
||||
|
||||
use App\Casts\AmountCast;
|
||||
use App\Enumerations\ParticipationFeeType;
|
||||
use App\Models\Tenant;
|
||||
use App\Scopes\CommonModel;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class EventParticipationFee extends CommonModel
|
||||
{
|
||||
protected $table = 'event_participation_fees';
|
||||
|
||||
protected $fillable = ['tenant', 'type', 'name', 'description', 'amount'];
|
||||
protected $casts = ['amount' => AmountCast::class];
|
||||
|
||||
public function tenant() : BelongsTo {
|
||||
return $this->belongsTo(Tenant::class, 'tenant', 'slug');
|
||||
}
|
||||
|
||||
public function type() : BelongsTo {
|
||||
return $this->belongsTo(ParticipationFeeType::class, 'type', 'slug');
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ namespace App\Repositories;
|
||||
|
||||
use App\Enumerations\CostUnitType;
|
||||
use App\Enumerations\InvoiceStatus;
|
||||
use App\Enumerations\InvoiceType;
|
||||
use App\Enumerations\UserRole;
|
||||
use App\Models\CostUnit;
|
||||
use App\Resources\CostUnitResource;
|
||||
@@ -154,6 +155,25 @@ class CostUnitRepository {
|
||||
return $amount;
|
||||
}
|
||||
|
||||
public function sumupByInvoiceType(CostUnit $costUnit, InvoiceType $invoiceType) : Amount {
|
||||
$amount = new Amount(0, 'Euro');
|
||||
|
||||
foreach ($costUnit->invoices()->get() as $invoice) {
|
||||
if (
|
||||
$invoice->status === InvoiceStatus::INVOICE_STATUS_DENIED ||
|
||||
$invoice->donation ||
|
||||
$invoice->type !== $invoice->slug
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$amount->addAmount(Amount::fromString($invoice->amount));
|
||||
}
|
||||
return $amount;
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function countInvoices(CostUnit $costUnit) : array {
|
||||
$returnData = [
|
||||
InvoiceStatus::INVOICE_STATUS_NEW => 0,
|
||||
|
||||
56
app/Repositories/EventRepository.php
Normal file
56
app/Repositories/EventRepository.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repositories;
|
||||
|
||||
use App\Enumerations\UserRole;
|
||||
use App\Models\CostUnit;
|
||||
use App\Models\Event;
|
||||
use App\Resources\CostUnitResource;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
class EventRepository {
|
||||
public function listAll() : array {
|
||||
return $this->getEventsByCriteria([
|
||||
'archived' => false
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
public function getById(int $id, bool $accessCheck = true) : ?Event {
|
||||
$events = self::getEventsByCriteria(['id' => $id], $accessCheck);
|
||||
return $events[0] ?? null;
|
||||
}
|
||||
|
||||
public function getEventsByCriteria(array $criteria, $accessCheck = true) : array {
|
||||
$tenant = app('tenant');
|
||||
|
||||
$canSeeAll = false;
|
||||
$user = Auth()->user();
|
||||
|
||||
if ($tenant->slug !== 'lv') {
|
||||
if (
|
||||
$user->user_role_main === UserRole::USER_ROLE_ADMIN ||
|
||||
in_array( $user->user_role_local_group, [UserRole::USER_ROLE_GROUP_LEADER, UserRole::USER_ROLE_ADMIN])
|
||||
) {
|
||||
$canSeeAll = true;
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
in_array( $user->user_role_main, [UserRole::USER_ROLE_GROUP_LEADER, UserRole::USER_ROLE_ADMIN])
|
||||
) {
|
||||
$canSeeAll = true;
|
||||
}
|
||||
}
|
||||
|
||||
$visibleEvents = [];
|
||||
/** @var Event $event */
|
||||
foreach (Event::where($criteria)->get() as $event) {
|
||||
|
||||
if ($event->eventManagers()->where('user_id', $user->id)->exists() || $canSeeAll || !$accessCheck) {
|
||||
$visibleEvents[] = $event;
|
||||
}
|
||||
}
|
||||
|
||||
return $visibleEvents;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Resources;
|
||||
|
||||
use App\Enumerations\InvoiceStatus;
|
||||
use App\Enumerations\InvoiceType;
|
||||
use App\Models\CostUnit;
|
||||
use App\Repositories\CostUnitRepository;
|
||||
use App\ValueObjects\Amount;
|
||||
@@ -28,6 +29,14 @@ class CostUnitResource {
|
||||
$countDonatedInvoices = $countInvoices[InvoiceStatus::INVOICE_META_STATUS_DONATED];
|
||||
$countDeniedInvoices = $countInvoices[InvoiceStatus::INVOICE_STATUS_DENIED];
|
||||
|
||||
$amounts = [];
|
||||
$overAllAmount = new Amount(0, 'Euro');
|
||||
foreach (InvoiceType::all() as $invoiceType) {
|
||||
$overAllAmount->addAmount($costUnitRepository->sumupByInvoiceType($this->costUnit, $invoiceType));
|
||||
$amounts[$invoiceType->slug]['string'] = $costUnitRepository->sumupByInvoiceType($this->costUnit, $invoiceType)->toString();
|
||||
$amounts[$invoiceType->slug]['name'] = $invoiceType->name;
|
||||
}
|
||||
|
||||
|
||||
$data = array_merge(
|
||||
$this->costUnit->toArray(),
|
||||
@@ -41,6 +50,8 @@ class CostUnitResource {
|
||||
'countDonatedInvoices' => $countDonatedInvoices,
|
||||
'countDeniedInvoices' => $countDeniedInvoices,
|
||||
'treasurers' => $this->costUnit->treasurers()->get()->map(fn($user) => new UserResource($user))->toArray(),
|
||||
'amounts' => $amounts,
|
||||
'overAllAmount' => ['text' => $overAllAmount->toString(), 'value' => $overAllAmount],
|
||||
]);
|
||||
|
||||
|
||||
|
||||
22
app/Resources/EatingHabitResource.php
Normal file
22
app/Resources/EatingHabitResource.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Resources;
|
||||
|
||||
use App\Enumerations\EatingHabit;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class EatingHabitResource extends JsonResource {
|
||||
private EatingHabit $eatingHabit;
|
||||
|
||||
public function __construct(EatingHabit $eatingHabit) {
|
||||
$this->eatingHabit = $eatingHabit;
|
||||
}
|
||||
|
||||
public function toArray($request) : array {
|
||||
return [
|
||||
'id' => $this->eatingHabit->id,
|
||||
'slug' => $this->eatingHabit->slug,
|
||||
'name' => $this->eatingHabit->name
|
||||
];
|
||||
}
|
||||
}
|
||||
109
app/Resources/EventResource.php
Normal file
109
app/Resources/EventResource.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace App\Resources;
|
||||
|
||||
use App\Enumerations\ParticipationFeeType;
|
||||
use App\Models\Event;
|
||||
use App\ValueObjects\Amount;
|
||||
|
||||
class EventResource {
|
||||
private Event $event;
|
||||
|
||||
public function __construct(Event $event) {
|
||||
$this->event = $event;
|
||||
}
|
||||
|
||||
public function toArray() : array {
|
||||
$duration = $this->event->end_date->diff($this->event->start_date)->d + 1;
|
||||
|
||||
|
||||
$returnArray = [
|
||||
'id' => $this->event->id,
|
||||
'name' => $this->event->name,
|
||||
'location' => $this->event->location,
|
||||
'postalCode' => $this->event->postal_code,
|
||||
'email' => $this->event->email,
|
||||
'accountOwner' => $this->event->account_owner,
|
||||
'accountIban' => $this->event->account_iban,
|
||||
'alcoholicsAge' => $this->event->alcoholics_age,
|
||||
'sendWeeklyReports' => $this->event->send_weekly_report,
|
||||
'registrationAllowed' => $this->event->registration_allowed,
|
||||
'earlyBirdEnd' => ['internal' => $this->event->early_bird_end->format('Y-m-d'), 'formatted' => $this->event->early_bird_end->format('d.m.Y')],
|
||||
'registrationFinalEnd' => ['internal' => $this->event->registration_final_end->format('Y-m-d'), 'formatted' => $this->event->registration_final_end->format('d.m.Y')],
|
||||
];
|
||||
|
||||
|
||||
|
||||
$returnArray['costUnit'] = new CostUnitResource($this->event->costUnit()->first())->toArray(true);
|
||||
$returnArray['solidarityPayment'] = $this->event->participation_fee_type === ParticipationFeeType::PARTICIPATION_FEE_TYPE_SOLIDARITY;
|
||||
$returnArray['payPerDay'] = $this->event->pay_per_day;
|
||||
$returnArray['maxAmount'] = $this->event->total_max_amount->getFormattedAmount();
|
||||
$returnArray['eventBegin'] = $this->event->start_date->format('d.m.Y');
|
||||
$returnArray['eventBeginInternal'] = $this->event->start_date;
|
||||
$returnArray['eventEnd'] = $this->event->end_date->format('d.m.Y');
|
||||
$returnArray['eventEndInternal'] = $this->event->end_date;
|
||||
$returnArray['duration'] = $duration;
|
||||
#
|
||||
$totalBalance = new Amount(0, 'Euro');
|
||||
$totalBalance->addAmount($this->calculateIncomes());
|
||||
$totalBalance->subtractAmount($returnArray['costUnit']['overAllAmount']['value']);
|
||||
|
||||
$returnArray['totalIncome'] = $this->calculateIncomes()->toString();
|
||||
$returnArray['totalBalance'] = ['text' => $totalBalance->toString(), 'value' => $totalBalance->getAmount()];
|
||||
$returnArray['flatSupport'] = $this->event->support_flat->toString();
|
||||
$returnArray['supportPerson'] = $this->event->support_per_person->toString();
|
||||
|
||||
$returnArray['flatSupportEdit'] = $this->event->support_flat->getFormattedAmount();
|
||||
$returnArray['supportPersonEdit'] = $this->event->support_per_person->getFormattedAmount();
|
||||
$returnArray['managers'] = $this->event->eventManagers()->get()->map(fn($user) => new UserResource($user))->toArray();
|
||||
|
||||
$returnArray['supportPersonCalced'] = $this->event->support_per_person->toString();
|
||||
$returnArray['contributingLocalGroups'] = $this->event->localGroups()->get()->map(fn($localGroup) => new LocalGroupResource($localGroup))->toArray();
|
||||
$returnArray['eatingHabits'] = $this->event->eatingHabits()->get()->map(
|
||||
fn($eatingHabit) => new EatingHabitResource($eatingHabit))->toArray();
|
||||
|
||||
|
||||
for ($i = 1; $i <= 4; $i++) {
|
||||
$returnArray['participationFee_' . $i] = [
|
||||
'active' => false,
|
||||
'name' => '',
|
||||
'description' => '',
|
||||
'amount' => '0,00',
|
||||
'type' => null
|
||||
];
|
||||
|
||||
if ($this->event->{'participation_fee_' . $i} === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
$returnArray['participationFee_' . $i] = [
|
||||
'active' => true,
|
||||
'amount' => $this->event->{'participationFee' . $i}()->first()->amount->getFormattedAmount(),
|
||||
'name' => $this->event->{'participationFee' . $i}->first()->name,
|
||||
'description' => $this->event->{'participationFee' . $i}()->first()->description,
|
||||
'type' => $this->event->{'participationFee' . $i}->first()->type
|
||||
];
|
||||
|
||||
|
||||
if ($this->event->participation_fee_type === ParticipationFeeType::PARTICIPATION_FEE_TYPE_SOLIDARITY) {
|
||||
$returnArray['participationFee_1' . $i]['description'] = '';
|
||||
$returnArray['participationFee_2' . $i]['description'] = '';
|
||||
$returnArray['participationFee_3' . $i]['description'] = 'Nach Verfügbarkeit';
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
return $returnArray;
|
||||
}
|
||||
|
||||
public function calculateIncomes() : Amount {
|
||||
$amount = new Amount(0, 'Euro');
|
||||
$amount->addAmount($this->event->support_flat);
|
||||
return $amount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
24
app/Resources/LocalGroupResource.php
Normal file
24
app/Resources/LocalGroupResource.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Resources;
|
||||
|
||||
use App\Models\Tenant;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class LocalGroupResource extends JsonResource {
|
||||
private Tenant $tenant;
|
||||
|
||||
public function __construct(Tenant $tenant) {
|
||||
$this->tenant = $tenant;
|
||||
}
|
||||
|
||||
public function toArray($request) : array {
|
||||
return [
|
||||
'id' => $this->tenant->id,
|
||||
'name' => $this->tenant->name,
|
||||
'email' => $this->tenant->email,
|
||||
'city' => $this->tenant->city,
|
||||
'postalcode'=> $this->tenant->postcode
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ namespace App\Scopes;
|
||||
use App\Models\Tenant;
|
||||
use App\Providers\AuthCheckProvider;
|
||||
use App\Repositories\CostUnitRepository;
|
||||
use App\Repositories\EventRepository;
|
||||
use App\Repositories\InvoiceRepository;
|
||||
use App\Repositories\PageTextRepository;
|
||||
use App\Repositories\UserRepository;
|
||||
@@ -17,6 +18,7 @@ abstract class CommonController {
|
||||
protected PageTextRepository $pageTexts;
|
||||
|
||||
protected InvoiceRepository $invoices;
|
||||
protected EventRepository $events;
|
||||
|
||||
public function __construct() {
|
||||
$this->tenant = app('tenant');
|
||||
@@ -24,6 +26,7 @@ abstract class CommonController {
|
||||
$this->costUnits = new CostUnitRepository();
|
||||
$this->pageTexts = new PageTextRepository();
|
||||
$this->invoices = new InvoiceRepository();
|
||||
$this->events = new EventRepository();
|
||||
}
|
||||
|
||||
protected function checkAuth() {
|
||||
|
||||
@@ -44,4 +44,11 @@ class Amount {
|
||||
public function subtractAmount(Amount $amount) : void {
|
||||
$this->amount -= $amount->getAmount();
|
||||
}
|
||||
|
||||
public function getFormattedAmount() : string {
|
||||
$value = number_format( round( $this->amount, 2 ), 2, ',', '.' );
|
||||
return $value
|
||||
|> trim(...)
|
||||
|> function (string $value) : string { return str_replace('.', ',', $value); };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<small class="error_text" v-if="props.message">{{ props.message }}</small>
|
||||
<small style="margin-bottom: 20px;" class="error_text" v-if="props.message">{{ props.message }}</small>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -18,7 +18,8 @@ return new class extends Migration
|
||||
});
|
||||
|
||||
Schema::create('eating_habits', function (Blueprint $table) {
|
||||
$table->string('slug')->unique()->primary();
|
||||
$table->id();
|
||||
$table->string('slug')->unique();
|
||||
$table->string('name');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
@@ -25,6 +25,7 @@ return new class extends Migration {
|
||||
$table->boolean('mail_on_new')->default(true);
|
||||
$table->boolean('allow_new')->default(true);
|
||||
$table->boolean('archived')->default(false);
|
||||
|
||||
$table->foreign('tenant')->references('slug')->on('tenants')->cascadeOnDelete()->cascadeOnUpdate();
|
||||
$table->foreign('type')->references('slug')->on('cost_unit_types')->cascadeOnDelete()->cascadeOnUpdate();
|
||||
$table->timestamps();
|
||||
|
||||
102
database/migrations/2026_02_14_140010_create_events.php
Normal file
102
database/migrations/2026_02_14_140010_create_events.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('participation_fee_types', function (Blueprint $table) {
|
||||
$table->string('slug')->primary();
|
||||
$table->string('name');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('participation_types', function (Blueprint $table) {
|
||||
$table->string('slug')->primary();
|
||||
$table->string('name');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('event_participation_fees', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('tenant');
|
||||
$table->string('type');
|
||||
$table->string('name');
|
||||
$table->string('description')->default('');
|
||||
$table->float('amount',2);
|
||||
$table->timestamps();
|
||||
|
||||
$table->foreign('type')->references('slug')->on('participation_types')->cascadeOnDelete()->cascadeOnUpdate();
|
||||
$table->foreign('tenant')->references('slug')->on('tenants')->cascadeOnDelete()->cascadeOnUpdate();
|
||||
});
|
||||
|
||||
Schema::create('events', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('tenant');
|
||||
$table->foreignId('cost_unit_id')->nullable()->constrained('cost_units', 'id')->cascadeOnDelete()->cascadeOnUpdate();
|
||||
|
||||
$table->string('name');
|
||||
$table->string('location');
|
||||
$table->string('postal_code');
|
||||
$table->string('email');
|
||||
$table->dateTime('start_date');
|
||||
$table->dateTime('end_date');
|
||||
$table->dateTime('early_bird_end');
|
||||
$table->dateTime('registration_final_end');
|
||||
$table->integer('early_bird_end_amount_increase');
|
||||
$table->string('account_owner');
|
||||
$table->string('account_iban');
|
||||
$table->boolean('registration_allowed')->default(false);
|
||||
$table->string('participation_fee_type');
|
||||
$table->float('total_max_amount', 2)->default(0);
|
||||
$table->string('registration_link')->nullable();
|
||||
$table->boolean('pay_per_day');
|
||||
$table->boolean('pay_direct');
|
||||
$table->boolean('send_weekly_report')->default(true);
|
||||
$table->foreignId('participation_fee_1')->nullable()->constrained('event_participation_fees', 'id')->nullOnDelete()->cascadeOnUpdate();
|
||||
$table->foreignId('participation_fee_2')->nullable()->constrained('event_participation_fees', 'id')->nullOnDelete()->cascadeOnUpdate();
|
||||
$table->foreignId('participation_fee_3')->nullable()->constrained('event_participation_fees', 'id')->nullOnDelete()->cascadeOnUpdate();
|
||||
$table->foreignId('participation_fee_4')->nullable()->constrained('event_participation_fees', 'id')->nullOnDelete()->cascadeOnUpdate();
|
||||
$table->float('support_per_person', 2)->default(0);
|
||||
$table->float('support_flat', 2)->default(0);
|
||||
$table->integer('alcoholics_age')->default(16);
|
||||
$table->boolean('archived')->default(false);
|
||||
$table->timestamps();
|
||||
|
||||
$table->foreign('tenant')->references('slug')->on('tenants')->cascadeOnDelete()->cascadeOnUpdate();
|
||||
$table->foreign('participation_fee_type')->references('slug')->on('participation_fee_types')->cascadeOnDelete()->cascadeOnUpdate();
|
||||
});
|
||||
|
||||
Schema::create('event_allowed_eating_habits', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('event_id')->constrained('events', 'id')->cascadeOnDelete()->cascadeOnUpdate();
|
||||
$table->foreignId('eating_habit_id')->constrained('eating_habits', 'id')->cascadeOnDelete()->cascadeOnUpdate();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('event_managers', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('event_id')->constrained('events', 'id')->cascadeOnDelete()->cascadeOnUpdate();
|
||||
$table->string('user_id')->constrained('users', 'id')->cascadeOnDelete()->cascadeOnUpdate();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('cron_tasks');
|
||||
Schema::dropIfExists('cron_task_types');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('event_local_groups', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('event_id')->constrained('events', 'id')->cascadeOnDelete()->cascadeOnUpdate();
|
||||
$table->foreignId('local_group_id')->constrained('tenants', 'id')->cascadeOnDelete()->cascadeOnUpdate();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('event_local_groups');
|
||||
}
|
||||
};
|
||||
695
package-lock.json
generated
695
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -22,10 +22,11 @@
|
||||
"@fortawesome/fontawesome-svg-core": "^7.1.0",
|
||||
"@fortawesome/free-solid-svg-icons": "^7.1.0",
|
||||
"@fortawesome/vue-fontawesome": "^3.1.3",
|
||||
"@inertiajs/progress": "^0.2.7",
|
||||
"@inertiajs/progress": "^0.1.2",
|
||||
"@inertiajs/vue3": "^2.3.12",
|
||||
"@tato30/vue-pdf": "^2.0.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"vue": "^3.5.27",
|
||||
"vue3-toastify": "^0.2.8",
|
||||
"@tato30/vue-pdf": "^2.0.0"
|
||||
"vue3-toastify": "^0.2.8"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
width: 100px !important;
|
||||
}
|
||||
|
||||
.width-tiny {
|
||||
width: 60px !important;
|
||||
}
|
||||
|
||||
.width-medium {
|
||||
width: 250px !important;
|
||||
}
|
||||
@@ -17,3 +21,15 @@
|
||||
.pr-20 {
|
||||
padding-right: 20px !important;
|
||||
}
|
||||
|
||||
.height-50 {
|
||||
height: 50px !important;
|
||||
}
|
||||
|
||||
.pt-20 {
|
||||
padding-top: 20px !important;
|
||||
}
|
||||
|
||||
.pb-20 {
|
||||
padding-bottom: 20px !important;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ input[type="text"],
|
||||
input[type="email"],
|
||||
input[type="password"],
|
||||
input[type="date"],
|
||||
input[type="number"],
|
||||
select {
|
||||
width: 100%;
|
||||
font-size: 13pt;
|
||||
@@ -32,6 +33,7 @@ input[type="text"]:focus,
|
||||
input[type="email"]:focus,
|
||||
input[type="password"]:focus,
|
||||
input[type="date"]:focus,
|
||||
input[type="number"]:focus,
|
||||
select:focus {
|
||||
outline: none;
|
||||
border-color: #1d4899;
|
||||
|
||||
41
resources/js/components/HttpClient.js
Normal file
41
resources/js/components/HttpClient.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import {ref} from "vue";
|
||||
|
||||
export async function request(url, options = {}) {
|
||||
const loading = ref(true)
|
||||
const isFormData = options.body instanceof FormData
|
||||
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
|
||||
const data = ref(null)
|
||||
const error = ref(null)
|
||||
|
||||
|
||||
error.value = null
|
||||
data.value = null
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: options.method || "GET",
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': csrfToken,
|
||||
...(isFormData ? {} : { 'Content-Type': 'application/json' }),
|
||||
...(options.headers || {}),
|
||||
},
|
||||
body: isFormData
|
||||
? options.body // ✅ FormData direkt
|
||||
: options.body
|
||||
? JSON.stringify(options.body)
|
||||
: null,
|
||||
})
|
||||
|
||||
if (!response.ok) throw new Error(`HTTP ${response.status}`)
|
||||
|
||||
const result = await response.json()
|
||||
data.value = result
|
||||
return result
|
||||
} catch (err) {
|
||||
error.value = err
|
||||
console.error("AJAX Error:", err)
|
||||
return null
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
@@ -147,7 +147,7 @@ const props = defineProps({
|
||||
<tr>
|
||||
<td>Version 4.0.0</td>
|
||||
<td>
|
||||
mareike - Mdodernes Anmeldesystem und richti einfache Kostenerfassung
|
||||
mareike - Mdodernes Anmeldesystem und richtig einfache Kostenerfassung
|
||||
</td>
|
||||
<td>
|
||||
Impressum
|
||||
|
||||
@@ -16,6 +16,8 @@ require_once __DIR__ . '/../app/Domains/CostUnit/Routes/web.php';
|
||||
require_once __DIR__ . '/../app/Domains/CostUnit/Routes/api.php';
|
||||
require_once __DIR__ . '/../app/Domains/Invoice/Routes/web.php';
|
||||
require_once __DIR__ . '/../app/Domains/Invoice/Routes/api.php';
|
||||
require_once __DIR__ . '/../app/Domains/Event/Routes/web.php';
|
||||
require_once __DIR__ . '/../app/Domains/Event/Routes/api.php';
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +31,7 @@ Route::middleware(IdentifyTenant::class)->group(function () {
|
||||
Route::get('/retrieve-messages', [GlobalDataProvider::class, 'getMessages']);
|
||||
Route::get('/retrieve-invoice-types', [GlobalDataProvider::class, 'getInvoiceTypes']);
|
||||
Route::get('/retrieve-invoice-types-all', [GlobalDataProvider::class, 'getAllInvoiceTypes']);
|
||||
Route::get('/retrieve-event-setting-data', [GlobalDataProvider::class, 'getEventSettingData']);
|
||||
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user