WiP
This commit is contained in:
@@ -12,6 +12,7 @@ Route::middleware(IdentifyTenant::class)->group(function () {
|
||||
Route::get('/available-events', AvailableEventsController::class);
|
||||
|
||||
|
||||
Route::get('/{eventId}', SignupController::class);
|
||||
Route::get('/{eventId}/signup', SignupController::class);
|
||||
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
|
||||
@@ -3,7 +3,8 @@ 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";
|
||||
import EventManagement from "./EventManagement.vue";
|
||||
import Modal from "../../../../Views/Components/Modal.vue";
|
||||
|
||||
const props = defineProps({
|
||||
data: Object,
|
||||
@@ -14,6 +15,8 @@ import EventManagement from "./EventManagement.vue";
|
||||
});
|
||||
|
||||
const displayData = ref('main');
|
||||
const showEventData = ref(false);
|
||||
|
||||
|
||||
async function showMain() {
|
||||
const response = await fetch("/api/v1/event/details/" + props.data.event.id + '/summary');
|
||||
@@ -34,12 +37,14 @@ import EventManagement from "./EventManagement.vue";
|
||||
displayData.value = 'eventManagement';
|
||||
}
|
||||
|
||||
async function eventData() {
|
||||
showEventData.value = true;
|
||||
}
|
||||
|
||||
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>
|
||||
@@ -53,7 +58,7 @@ import EventManagement from "./EventManagement.vue";
|
||||
|
||||
<div class="event-flexbox" v-else>
|
||||
<div class="event-flexbox-row top">
|
||||
<div class="left"><ParticipationSummary :event="dynamicProps.event" /></div>
|
||||
<div class="left"><ParticipationSummary v-if="dynamicProps.event" :event="dynamicProps.event" /></div>
|
||||
<div class="right">
|
||||
<input type="button" value="Erste-Hilfe-Liste (PDF)" /><br/>
|
||||
<input type="button" value="Teili-Liste (CSV)" /><br/>
|
||||
@@ -70,10 +75,45 @@ import EventManagement from "./EventManagement.vue";
|
||||
<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="eventData()">Details für Einladung</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>
|
||||
|
||||
<Modal title="Veranstaltungsdetails" v-if="showEventData" :show="showEventData" @close="showEventData = false">
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Beginn</th>
|
||||
<td>{{ dynamicProps.event.eventBegin }}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Ende</th>
|
||||
<td>{{ dynamicProps.event.eventEnd }}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Anmeldeschluss</th>
|
||||
<td>{{dynamicProps.event.earlyBirdEnd.formatted}}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Nachmeldeschluss</th>
|
||||
<td>{{dynamicProps.event.registrationFinalEnd.formatted}}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Anmelde-URL</th>
|
||||
<td>
|
||||
{{dynamicProps.event.url}}<br />
|
||||
<img :src="'/print-event-code/' + dynamicProps.event.identifier" alt="Event Code" style="width: 150px; height: 150px; margin-top: 20px;" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</Modal>
|
||||
|
||||
</template>
|
||||
|
||||
<style>
|
||||
@@ -96,7 +136,7 @@ import EventManagement from "./EventManagement.vue";
|
||||
}
|
||||
|
||||
.event-flexbox-row.top .right {
|
||||
flex: 0 0 250px; /* feste Breite von 20% */
|
||||
flex: 0 0 250px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
event: Object
|
||||
})
|
||||
|
||||
|
||||
console.log(props.event)
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -11,35 +14,61 @@
|
||||
<div class="participant-flexbox-row top">
|
||||
<div class="left">
|
||||
<h3>Teilnehmende</h3>
|
||||
<table class="participant-income-table" style="margin-bottom: 40px;">
|
||||
<table class="participant-income-table" style="margin-bottom: 40px; font-size: 11pt;">
|
||||
<tr>
|
||||
<th>Teili</th>
|
||||
<td>7 Personen:</td>
|
||||
<td>35,00 Euro</td>
|
||||
<td>{{props.event.participants.participant.count}} Personen:</td>
|
||||
<td>
|
||||
{{props.event.participants.participant.amount.paid.readable}} /
|
||||
</td>
|
||||
<td>
|
||||
{{props.event.participants.participant.amount.expected.readable}}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Teili</th>
|
||||
<td>7 Personen:</td>
|
||||
<td>35,00 Euro</td>
|
||||
<th>Team</th>
|
||||
<td>{{props.event.participants.team.count}} Personen:</td>
|
||||
<td>
|
||||
{{props.event.participants.team.amount.paid.readable}} /
|
||||
</td>
|
||||
<td>
|
||||
{{props.event.participants.team.amount.expected.readable}}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Teili</th>
|
||||
<td>7 Personen:</td>
|
||||
<td>35,00 Euro</td>
|
||||
<th>Unterstützende</th>
|
||||
<td>{{props.event.participants.volunteer.count}} Personen:</td>
|
||||
<td>
|
||||
{{props.event.participants.volunteer.amount.paid.readable}} /
|
||||
</td>
|
||||
<td>
|
||||
{{props.event.participants.volunteer.amount.expected.readable}}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th colspan="2">Sonstiges</th>
|
||||
<td>{{ props.event.flatSupport }}</td>
|
||||
<th>Sonstige</th>
|
||||
<td>{{props.event.participants.other.count}} Personen:</td>
|
||||
<td>
|
||||
{{props.event.participants.other.amount.paid.readable}} /
|
||||
</td>
|
||||
<td>
|
||||
{{props.event.participants.other.amount.expected.readable}}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th colspan="2">Sonstige Einnahmen</th>
|
||||
<td colspan="2">{{ 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 style="padding-bottom: 20px" colspan="2">
|
||||
{{ props.event.supportPerson.readable }}<br />
|
||||
<label style="font-size: 9pt;">({{ props.event.supportPersonIndex }} / Tag p.P.)</label>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -47,27 +76,38 @@
|
||||
|
||||
<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>
|
||||
<td style="font-weight: bold; border-width: 1px; border-bottom-style: solid">
|
||||
{{ props.event.income.real.readable }} /
|
||||
</td>
|
||||
|
||||
<td style="font-weight: bold; border-width: 1px; border-bottom-style: solid">
|
||||
{{ props.event.income.expected.readable }}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr style="color:#4caf50;" v-if="props.event.totalBalance.value >= 0">
|
||||
<tr>
|
||||
<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>
|
||||
<td v-if="props.event.totalBalance.real.value >= 0" style="color: #4caf50;font-weight: bold; padding-top: 20px; font-size: 12pt !important;">
|
||||
{{ props.event.totalBalance.real.readable }} /
|
||||
</td>
|
||||
<td v-else style="color: #f44336; font-weight: bold; padding-top: 20px; font-size: 12pt !important;">
|
||||
{{props.event.totalBalance.expected.readable}}
|
||||
</td>
|
||||
|
||||
<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>
|
||||
<td v-if="props.event.totalBalance.expected.value >= 0" style="color: #4caf50; font-weight: bold; padding-top: 20px; font-size: 12pt !important;">
|
||||
{{ props.event.totalBalance.expected.readable }}
|
||||
</td>
|
||||
<td v-else style="color: #f44336; font-weight: bold; padding-top: 20px; font-size: 12pt !important;">
|
||||
{{props.event.totalBalance.expected.readable}}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<strong>Anmelde-URL: {{props.event.url}}</strong>
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
<h3>Ausgaben</h3>
|
||||
<table class="event-payment-table">
|
||||
<table class="event-payment-table" style="font-size: 11pt;">
|
||||
<tr v-for="amount in props.event.costUnit.amounts">
|
||||
<th>{{amount.name}}</th>
|
||||
<td>{{amount.string}}</td>
|
||||
@@ -110,7 +150,7 @@
|
||||
|
||||
.participant-income-table,
|
||||
.event-payment-table {
|
||||
width: 300px;
|
||||
width: 475px;
|
||||
}
|
||||
|
||||
.participant-income-table th {
|
||||
@@ -122,4 +162,8 @@
|
||||
width: 25px !important;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
.event-payment-table {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
19
app/Http/Controllers/EventCodeGetController.php
Normal file
19
app/Http/Controllers/EventCodeGetController.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\EventParticipant;
|
||||
use App\Providers\GiroCodeProvider;
|
||||
use App\Providers\QrCodeUrlProvider;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class EventCodeGetController {
|
||||
public function __invoke(string $eventToken, Request $request)
|
||||
{
|
||||
$qrCodeProvider = new QrCodeUrlProvider($eventToken);
|
||||
|
||||
return response($qrCodeProvider->createQrCode($request), 200,
|
||||
['Content-Type' => 'image/png']
|
||||
);
|
||||
}
|
||||
}
|
||||
18
app/Providers/QrCodeUrlProvider.php
Normal file
18
app/Providers/QrCodeUrlProvider.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Repositories\EventRepository;
|
||||
use Illuminate\Http\Request;
|
||||
use SimpleSoftwareIO\QrCode\Facades\QrCode;
|
||||
|
||||
class QrCodeUrlProvider {
|
||||
function __construct(private string $url) {
|
||||
}
|
||||
|
||||
public function createQrCode(Request $request) {
|
||||
$event = new EventRepository()->getByIdentifier($this->url, false)->toResource()->toArray($request);
|
||||
return
|
||||
QrCode::format('png')->size(300)->generate($event['url']);
|
||||
}
|
||||
}
|
||||
@@ -22,9 +22,19 @@ class EventParticipantResource extends JsonResource
|
||||
$amountLeft->subtractAmount($this->resource->amount_paid);
|
||||
}
|
||||
|
||||
$presenceDays = $this->resource->arrival_date->diff($this->resource->departure_date)->days;
|
||||
$presenceDaysSupport = $presenceDays;
|
||||
|
||||
if ($presenceDaysSupport === 0) {
|
||||
$presenceDaysSupport = 1;
|
||||
} else {
|
||||
$presenceDaysSupport = $presenceDaysSupport - 1;
|
||||
}
|
||||
|
||||
return array_merge(
|
||||
$this->resource->toArray(),
|
||||
[
|
||||
'presenceDays' => ['real' => $presenceDays, 'support' => $presenceDaysSupport],
|
||||
'participationType' => ParticipationType::where(['slug' => $this->resource->participation_type])->first()->name,
|
||||
'needs_payment' => $this->resource->amount->getAmount() > 0 && $event->pay_direct,
|
||||
'nicename' => $this->resource->getNicename(),
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Resources;
|
||||
|
||||
use App\Enumerations\ParticipationFeeType;
|
||||
use App\Enumerations\ParticipationType;
|
||||
use App\Models\Event;
|
||||
use App\ValueObjects\Amount;
|
||||
use DateTime;
|
||||
@@ -24,6 +25,7 @@ class EventResource extends JsonResource{
|
||||
'id' => $this->event->id,
|
||||
'name' => $this->event->name,
|
||||
'identifier' => $this->event->identifier,
|
||||
'url' => 'https://' . app('tenant')->url . '/event/' . $this->event->identifier . '/signup',
|
||||
'location' => $this->event->location,
|
||||
'postalCode' => $this->event->postal_code,
|
||||
'email' => $this->event->email,
|
||||
@@ -56,6 +58,18 @@ class EventResource extends JsonResource{
|
||||
->toArray();
|
||||
|
||||
|
||||
foreach ([
|
||||
ParticipationType::PARTICIPATION_TYPE_PARTICIPANT,
|
||||
ParticipationType::PARTICIPATION_TYPE_TEAM,
|
||||
ParticipationType::PARTICIPATION_TYPE_VOLUNTEER,
|
||||
ParticipationType::PARTICIPATION_TYPE_OTHER,
|
||||
] as $participationType) {
|
||||
$returnArray['participants'][$participationType] = $this->getParticipants($participationType);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$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;
|
||||
@@ -65,15 +79,33 @@ class EventResource extends JsonResource{
|
||||
$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['supportPersonIndex'] = $this->event->support_per_person->toString();
|
||||
$returnArray['supportPerson'] = $this->calculateSupportPerPerson($returnArray['participants']);
|
||||
|
||||
$returnArray['income'] = $this->calculateIncomes($returnArray['participants'], $returnArray['supportPerson']['amount']);
|
||||
|
||||
|
||||
$totalBalanceReal = new Amount(0, 'Euro');
|
||||
$totalBalanceExpected = new Amount(0, 'Euro');
|
||||
|
||||
$totalBalanceReal->addAmount($returnArray['income']['real']['amount']);
|
||||
$totalBalanceExpected->addAmount($returnArray['income']['expected']['amount']);
|
||||
|
||||
$totalBalanceReal->subtractAmount($returnArray['costUnit']['overAllAmount']['value']);
|
||||
$totalBalanceExpected->subtractAmount($returnArray['costUnit']['overAllAmount']['value']);
|
||||
|
||||
$returnArray['totalBalance'] = [
|
||||
'real' => [
|
||||
'value' => $totalBalanceReal->getAmount(),
|
||||
'readable' => $totalBalanceReal->toString(),
|
||||
], 'expected' => [
|
||||
'value' => $totalBalanceExpected->getAmount(),
|
||||
'readable' => $totalBalanceExpected->toString(),
|
||||
]
|
||||
];
|
||||
|
||||
$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();
|
||||
@@ -161,12 +193,106 @@ class EventResource extends JsonResource{
|
||||
return 1 + $this->event->early_bird_end_amount_increase / 100;
|
||||
}
|
||||
|
||||
public function calculateIncomes() : Amount {
|
||||
$amount = new Amount(0, 'Euro');
|
||||
$amount->addAmount($this->event->support_flat);
|
||||
return $amount;
|
||||
public function calculateSupportPerPerson(array $participants) : array {
|
||||
if ($this->event->support_per_person === null) {
|
||||
return [
|
||||
'amount' => new Amount(0, 'Euro'),
|
||||
'readable' => '0,00'
|
||||
];
|
||||
}
|
||||
|
||||
$amount = $this->event->support_per_person;
|
||||
$multiplier = 0;
|
||||
|
||||
|
||||
|
||||
foreach ($participants as $participationType => $participantData) {
|
||||
if (isset($participantData['participants']) && count($participantData['participants']) > 0) {
|
||||
foreach ($participantData['participants'] as $participant) {
|
||||
$multiplier += $participant->toResource()->toArray(new Request())['presenceDays']['support'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$amount->multiply($multiplier);
|
||||
|
||||
return [
|
||||
'amount' => $amount,
|
||||
'readable' => $amount->toString()
|
||||
];
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function calculateIncomes(array $participants, Amount $supportPerPerson) : array {
|
||||
$expectedAmount = $supportPerPerson;
|
||||
$expectedAmount->addAmount($this->event->support_flat);
|
||||
|
||||
$realAmount = $supportPerPerson;
|
||||
$realAmount->addAmount($this->event->support_flat);
|
||||
|
||||
|
||||
foreach ($participants as $participationType => $participantData) {
|
||||
$expectedAmount->addAmount(new Amount($participantData['amount']['expected']['value'], 'Euro'));
|
||||
$realAmount->addAmount(new Amount($participantData['amount']['paid']['value'], 'Euro'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
return ['real' => [
|
||||
'amount' => $realAmount,
|
||||
'readable' => $realAmount->toString()
|
||||
],
|
||||
'expected' => [
|
||||
'amount' => $expectedAmount,
|
||||
'readable' => $expectedAmount->toString(),
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function getParticipants(string $participationType) : array {
|
||||
$returnData = [];
|
||||
$returnData['amount'] = ['expected' => new Amount(0, 'Euro'), 'paid' => new Amount(0, 'Euro')];
|
||||
$returnData['count'] = 0;
|
||||
|
||||
foreach ($this->event->participants()->where(
|
||||
[
|
||||
'participation_type' => $participationType,
|
||||
'unregistered_at' => null
|
||||
]
|
||||
|
||||
)->get() as $participant)
|
||||
{
|
||||
$returnData['count']++;
|
||||
$returnData['participants'][] = $participant;
|
||||
|
||||
if ($participant->amount !== null) {
|
||||
$returnData['amount']['expected'] = $returnData['amount']['expected']->addAmount($participant->amount);
|
||||
}
|
||||
|
||||
if ($participant->amount_paid !== null) {
|
||||
$returnData['amount']['paid'] = $returnData['amount']['paid']->addAmount($participant->amount_paid);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
$returnData['amount']['expected'] =
|
||||
[
|
||||
'value' => $returnData['amount']['expected']->getAmount(),
|
||||
'readable' => $returnData['amount']['expected']->toString()
|
||||
];
|
||||
|
||||
$returnData['amount']['paid'] =
|
||||
[
|
||||
'value' => $returnData['amount']['paid']->getAmount(),
|
||||
'readable' => $returnData['amount']['paid']->toString()
|
||||
];
|
||||
|
||||
|
||||
return $returnData;
|
||||
}
|
||||
|
||||
|
||||
public function calculateAmount(
|
||||
string $participationType,
|
||||
string $feeType,
|
||||
|
||||
@@ -37,8 +37,9 @@ class Amount {
|
||||
|> function (string $value) : string { return str_replace('.', ',', $value); };
|
||||
}
|
||||
|
||||
public function addAmount(Amount $amount) : void {
|
||||
public function addAmount(Amount $amount) : Amount {
|
||||
$this->amount += $amount->getAmount();
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function subtractAmount(Amount $amount) : void {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use App\Domains\Dashboard\Controllers\DashboardController;
|
||||
use App\Http\Controllers\EventCodeGetController;
|
||||
use App\Http\Controllers\GiroCodeGetController;
|
||||
use App\Http\Controllers\TestRenderInertiaProvider;
|
||||
use App\Middleware\IdentifyTenant;
|
||||
@@ -24,6 +25,7 @@ require_once __DIR__ . '/../app/Domains/Event/Routes/api.php';
|
||||
|
||||
Route::get('/execute-crons', [CronTaskHandleProvider::class, 'run']);
|
||||
Route::get('/print-girocode/{participantToken}', GiroCodeGetController::class);
|
||||
Route::get('/print-event-code/{eventToken}', EventCodeGetController::class);
|
||||
|
||||
Route::middleware(IdentifyTenant::class)->group(function () {
|
||||
Route::get('/', DashboardController::class);
|
||||
|
||||
Reference in New Issue
Block a user