Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f00e665a03 | |||
| 454d83de2e | |||
| 30cc0b79c5 | |||
| 775d9158a6 | |||
| c60429ad28 | |||
| 0cf9602958 | |||
| e2fb616565 | |||
| faaf12b6a4 | |||
| 1a69a20750 | |||
| 71cb09f051 | |||
| b668195e21 | |||
| 94934027fa | |||
| 120c8873ef | |||
| 188735e4aa | |||
| b291c05da7 | |||
| adffa6d6b2 | |||
| 4357fd022d | |||
| d6416d9c6b | |||
| 7c1125e213 | |||
| b91af2e889 | |||
| 4a97cf230b | |||
| 0c7e3ab365 | |||
| 222113b0d5 | |||
| 895e44c984 | |||
| ef3d03200e | |||
| 6c891ff64a | |||
| d9ba5ab4f1 | |||
| 1816ca5165 | |||
| dff7d65476 | |||
| ce57669263 | |||
| 2444aab204 |
@@ -0,0 +1,5 @@
|
||||
.ai
|
||||
.junie
|
||||
.git
|
||||
storage
|
||||
tests
|
||||
@@ -3,6 +3,7 @@
|
||||
import InvoiceDetails from "../../../Invoice/Views/Partials/invoiceDetails/InvoiceDetails.vue";
|
||||
import { useAjax } from "../../../../../resources/js/components/ajaxHandler.js";
|
||||
import {ref} from "vue";
|
||||
import {toast} from "vue3-toastify";
|
||||
|
||||
const props = defineProps({
|
||||
data: Object
|
||||
@@ -12,7 +13,7 @@
|
||||
const invoice = ref(null)
|
||||
const show_invoice = ref(false)
|
||||
const localData = ref(props.data)
|
||||
|
||||
console.log(props.data)
|
||||
async function openInvoiceDetails(invoiceId) {
|
||||
const url = '/api/v1/invoice/details/' + invoiceId
|
||||
|
||||
@@ -40,6 +41,50 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function exportPayouts() {
|
||||
toast.info('Der Export wird nun gestartet. Bitte verlasse diese Seite nicht, bis der Export abgeschlossen ist.')
|
||||
|
||||
const response = await fetch('/api/v1/core/retrieve-global-data');
|
||||
const data = await response.json();
|
||||
const exportUrl = '/api/v1/cost-unit/' + props.data.costUnit.id + '/export-payouts';
|
||||
|
||||
try {
|
||||
if (data.tenant.download_exports) {
|
||||
const response = await fetch(exportUrl, {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error('Fehler beim Export (ZIP)');
|
||||
|
||||
const blob = await response.blob();
|
||||
const downloadUrl = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement("a");
|
||||
a.style.display = "none";
|
||||
a.href = downloadUrl;
|
||||
a.download = "Abrechnungen-Sippenstunden.zip";
|
||||
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
|
||||
setTimeout(() => {
|
||||
window.URL.revokeObjectURL(downloadUrl);
|
||||
document.body.removeChild(a);
|
||||
}, 100);
|
||||
} else {
|
||||
const response = await request(exportUrl, {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
toast.success(response.message);
|
||||
}
|
||||
|
||||
reload()
|
||||
|
||||
} catch (err) {
|
||||
toast.error('Beim Export der Abrechnungen ist ein Fehler aufgetreten.');
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -56,7 +101,7 @@
|
||||
</td>
|
||||
<td style="width: 150px;">
|
||||
<Icon v-if="invoice.donation" name="hand-holding-dollar" style="color: #ffffff; background-color: green" />
|
||||
<Icon v-if="invoice.alreadyPaid" name="comments-dollar" style="color: #ffffff; background-color: green" />
|
||||
<Icon v-if="invoice.externalPayment" name="comments-dollar" style="color: #ffffff; background-color: green" />
|
||||
</td>
|
||||
<td>
|
||||
{{invoice.contactName}}<br />
|
||||
@@ -68,6 +113,13 @@
|
||||
<input type="button" value="Abrechnung Anzeigen" @click="openInvoiceDetails(invoice.id)" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr v-if="props.data.endpoint === 'approved'">
|
||||
<td colspan="5"></td>
|
||||
<td>
|
||||
<a style="font-size: 10pt;" class="link" @click="exportPayouts()">Genehmigte Abrechnungen exportieren</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p v-else>Es sind keine Abrechnungen in dieser Kategorie vorhanden.</p>
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\ArchiveEvent;
|
||||
|
||||
class ArchiveEventCommand {
|
||||
public ArchiveEventRequest $request;
|
||||
|
||||
public function __construct(ArchiveEventRequest $request) {
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function execute(): ArchiveEventResponse {
|
||||
$response = new ArchiveEventResponse();
|
||||
|
||||
$this->request->event->archived = true;
|
||||
$this->request->event->save();
|
||||
|
||||
$response->success = true;
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\ArchiveEvent;
|
||||
|
||||
use App\Models\Event;
|
||||
|
||||
class ArchiveEventRequest {
|
||||
public Event $event;
|
||||
|
||||
public function __construct(Event $event) {
|
||||
$this->event = $event;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\ArchiveEvent;
|
||||
|
||||
class ArchiveEventResponse {
|
||||
public bool $success;
|
||||
|
||||
public function __construct() {
|
||||
$this->success = false;
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ class SignUpRequest {
|
||||
public Tenant $localGroup,
|
||||
public DateTime $birthday,
|
||||
public string $address_1,
|
||||
public string $address_2,
|
||||
public ?string $address_2,
|
||||
public string $postcode,
|
||||
public string $city,
|
||||
public string $email_1,
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\UnarchiveEvent;
|
||||
|
||||
class UnarchiveEventCommand {
|
||||
public UnarchiveEventRequest $request;
|
||||
|
||||
public function __construct(UnarchiveEventRequest $request) {
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function execute(): UnarchiveEventResponse {
|
||||
$response = new UnarchiveEventResponse();
|
||||
|
||||
$this->request->event->archived = false;
|
||||
$this->request->event->save();
|
||||
|
||||
$response->success = true;
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\UnarchiveEvent;
|
||||
|
||||
use App\Models\Event;
|
||||
|
||||
class UnarchiveEventRequest {
|
||||
public Event $event;
|
||||
|
||||
public function __construct(Event $event) {
|
||||
$this->event = $event;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Actions\UnarchiveEvent;
|
||||
|
||||
class UnarchiveEventResponse {
|
||||
public bool $success;
|
||||
|
||||
public function __construct() {
|
||||
$this->success = false;
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ class UpdateParticipantRequest {
|
||||
public string $birthday,
|
||||
public string $email_1,
|
||||
public string $phone_1,
|
||||
public string $contact_person,
|
||||
public ?string $contact_person,
|
||||
public ?string $email_2,
|
||||
public ?string $phone_2,
|
||||
public string $arrival,
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Controllers;
|
||||
|
||||
use App\Providers\InertiaProvider;
|
||||
use App\Scopes\CommonController;
|
||||
use Illuminate\Http\Request;
|
||||
use Inertia\Response;
|
||||
|
||||
class ArchivedEventsController extends CommonController
|
||||
{
|
||||
public function __invoke(Request $request): Response {
|
||||
$events = [];
|
||||
foreach ($this->events->getEventsByCriteria(['archived' => true]) as $event) {
|
||||
$events[] = [
|
||||
'id' => $event->id,
|
||||
'name' => $event->name,
|
||||
'location' => $event->location,
|
||||
'postalCode' => $event->postal_code,
|
||||
'eventBegin' => $event->start_date->format('d.m.Y'),
|
||||
'eventEnd' => $event->end_date->format('d.m.Y'),
|
||||
];
|
||||
}
|
||||
|
||||
return (new InertiaProvider('Event/ArchivedEvents', ['events' => $events]))->render();
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,8 @@ class CreateController extends CommonController {
|
||||
$payPerDay = $request->input('eventPayPerDay');
|
||||
$payDirect = $request->input('eventPayDirectly');
|
||||
|
||||
$billingDeadline = $eventEnd->modify('+1 month');
|
||||
$billingDeadline = clone $eventEnd;
|
||||
$billingDeadline->modify('+6 weeks');
|
||||
|
||||
$createRequest = new CreateEventRequest(
|
||||
$request->input('eventName'),
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Controllers;
|
||||
|
||||
use App\Domains\Event\Actions\ArchiveEvent\ArchiveEventCommand;
|
||||
use App\Domains\Event\Actions\ArchiveEvent\ArchiveEventRequest;
|
||||
use App\Scopes\CommonController;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class EventArchiveController extends CommonController
|
||||
{
|
||||
public function __invoke(string $eventId, Request $request): JsonResponse {
|
||||
$event = $this->events->getByIdentifier($eventId);
|
||||
|
||||
$archiveEventRequest = new ArchiveEventRequest($event);
|
||||
$archiveEventCommand = new ArchiveEventCommand($archiveEventRequest);
|
||||
$response = $archiveEventCommand->execute();
|
||||
|
||||
return response()->json([
|
||||
'status' => $response->success ? 'success' : 'error',
|
||||
'message' => $response->success ? 'Das Event wurde erfolgreich archiviert.' : 'Beim Archivieren des Events ist ein Fehler aufgetreten.'
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Event\Controllers;
|
||||
|
||||
use App\Domains\Event\Actions\UnarchiveEvent\UnarchiveEventCommand;
|
||||
use App\Domains\Event\Actions\UnarchiveEvent\UnarchiveEventRequest;
|
||||
use App\Scopes\CommonController;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class EventUnarchiveController extends CommonController
|
||||
{
|
||||
public function __invoke(int $eventId, Request $request): JsonResponse {
|
||||
$event = $this->events->getById($eventId);
|
||||
|
||||
$unarchiveRequest = new UnarchiveEventRequest($event);
|
||||
$unarchiveCommand = new UnarchiveEventCommand($unarchiveRequest);
|
||||
$response = $unarchiveCommand->execute();
|
||||
|
||||
return response()->json(['status' => $response->success ? 'success' : 'error']);
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,5 @@ class ParticipantPaymentController extends CommonController
|
||||
'class' => $amountLeft->getAmount() != 0 ? 'not-paid' : 'paid',
|
||||
]
|
||||
]);
|
||||
|
||||
dd($participant);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,8 @@ class SignupController extends CommonController {
|
||||
);
|
||||
|
||||
$signupRequest = new SignUpRequest(
|
||||
$event,$registrationData['userId'],
|
||||
$event,
|
||||
$registrationData['userId'] ?? null,
|
||||
$registrationData['vorname'],
|
||||
$registrationData['nachname'],
|
||||
$registrationData['pfadiname'],
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
use App\Domains\Event\Controllers\CreateController;
|
||||
use App\Domains\Event\Controllers\DetailsController;
|
||||
use App\Domains\Event\Controllers\EventArchiveController;
|
||||
use App\Domains\Event\Controllers\EventUnarchiveController;
|
||||
use App\Domains\Event\Controllers\MailCompose\ByGroupController;
|
||||
use App\Domains\Event\Controllers\MailCompose\SendController;
|
||||
use App\Domains\Event\Controllers\ParticipantController;
|
||||
@@ -26,6 +28,7 @@ Route::prefix('api/v1')
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
Route::post('/create', [CreateController::class, 'doCreate']);
|
||||
|
||||
|
||||
Route::prefix('{eventIdentifier}/mailing')->group(function () {
|
||||
Route::post('/compose/to-group/{groupType}', ByGroupController::class);
|
||||
Route::post('/send', SendController::class);
|
||||
@@ -37,8 +40,8 @@ Route::prefix('api/v1')
|
||||
Route::get('/summary', [DetailsController::class, 'summary']);
|
||||
|
||||
Route::get('/participants/{listType}', [DetailsController::class, 'listParticipants']);
|
||||
|
||||
|
||||
Route::post('/unarchive', EventUnarchiveController::class);
|
||||
Route::get('/archive', EventArchiveController::class);
|
||||
Route::post('/event-managers', [DetailsController::class, 'updateEventManagers']);
|
||||
Route::post('/participation-fees', [DetailsController::class, 'updateParticipationFees']);
|
||||
Route::post('/common-settings', [DetailsController::class, 'updateCommonSettings']);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
use App\Domains\Event\Controllers\ArchivedEventsController;
|
||||
use App\Domains\Event\Controllers\AvailableEventsController;
|
||||
use App\Domains\Event\Controllers\CreateController;
|
||||
use App\Domains\Event\Controllers\DetailsController;
|
||||
@@ -16,10 +17,14 @@ Route::middleware(IdentifyTenant::class)->group(function () {
|
||||
Route::get('/{eventId}/signup', SignupController::class);
|
||||
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
Route::get('/new', CreateController::class);
|
||||
Route::get('/details/{eventId}', DetailsController::class);
|
||||
Route::get('/details/{eventId}/pdf/{listType}', [DetailsController::class, 'downloadPdfList']);
|
||||
Route::get('/details/{eventId}/csv/{listType}', [DetailsController::class, 'downloadCsvList']);
|
||||
});
|
||||
});
|
||||
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
Route::get('/create-event', CreateController::class);
|
||||
Route::get('/archived-events', ArchivedEventsController::class);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import AppLayout from "../../../../resources/js/layouts/AppLayout.vue";
|
||||
import ShadowedBox from "../../../Views/Components/ShadowedBox.vue";
|
||||
import { toast } from 'vue3-toastify';
|
||||
import axios from 'axios';
|
||||
|
||||
const props = defineProps({
|
||||
events: Array,
|
||||
});
|
||||
|
||||
const events = ref([...props.events]);
|
||||
|
||||
async function unarchiveEvent(eventId) {
|
||||
try {
|
||||
const response = await axios.post(`/api/v1/event/details/${eventId}/unarchive`);
|
||||
if (response.data.status === 'success') {
|
||||
events.value = events.value.filter(e => e.id !== eventId);
|
||||
toast.success('Veranstaltung wurde aus dem Archiv geholt.');
|
||||
} else {
|
||||
toast.error('Fehler beim Wiederherstellen der Veranstaltung.');
|
||||
}
|
||||
} catch {
|
||||
toast.error('Ein unerwarteter Fehler ist aufgetreten.');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppLayout title="Archivierte Veranstaltungen">
|
||||
<div style="width: 95%; margin: 20px auto;">
|
||||
<h1 style="font-size: 1.5rem; font-weight: 700; margin-bottom: 20px;">Archivierte Veranstaltungen</h1>
|
||||
|
||||
<div
|
||||
v-if="events.length === 0"
|
||||
style="text-align: center; color: #6b7280; padding: 40px 0;"
|
||||
>
|
||||
Es sind keine archivierten Veranstaltungen vorhanden.
|
||||
</div>
|
||||
|
||||
<ShadowedBox
|
||||
v-for="event in events"
|
||||
:key="event.id"
|
||||
style="padding: 20px; margin-bottom: 16px;"
|
||||
>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px;">
|
||||
<div>
|
||||
<h2 style="margin: 0 0 4px 0; font-size: 1.1rem; font-weight: 600;">{{ event.name }}</h2>
|
||||
<span style="color: #6b7280; font-size: 0.875rem;">
|
||||
{{ event.postalCode }} {{ event.location }}
|
||||
·
|
||||
{{ event.eventBegin }} – {{ event.eventEnd }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<button
|
||||
@click="unarchiveEvent(event.id)"
|
||||
style="
|
||||
padding: 8px 20px;
|
||||
background-color: #f59e0b;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
font-size: 0.9rem;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
"
|
||||
>
|
||||
Aus dem Archiv holen
|
||||
</button>
|
||||
</div>
|
||||
</ShadowedBox>
|
||||
</div>
|
||||
</AppLayout>
|
||||
</template>
|
||||
@@ -56,6 +56,16 @@
|
||||
mailCompose.value = true
|
||||
}
|
||||
|
||||
async function archiveEvent() {
|
||||
const response = await fetch("/api/v1/event/details/" + props.data.event.identifier + "/archive" );
|
||||
const data = await response.json();
|
||||
if (data.status === 'success') {
|
||||
toast.success(data.message)
|
||||
} else {
|
||||
toast.error(data.message)
|
||||
}
|
||||
}
|
||||
|
||||
async function sendPaymentReminder() {
|
||||
toast.info("Die Nachrichten werden gesendet. Bitte verlasse diese Seite nicht.");
|
||||
const response = await fetch("/api/v1/event/" + props.data.event.identifier + "/send-payment-reminder/" );
|
||||
@@ -137,7 +147,7 @@
|
||||
<tr>
|
||||
<th>Anmelde-URL</th>
|
||||
<td>
|
||||
{{dynamicProps.event.url}}<br />
|
||||
{{dynamicProps.event.urlShort}}<br />
|
||||
<img :src="'/print-event-code/' + dynamicProps.event.identifier" alt="Event Code" style="width: 150px; height: 150px; margin-top: 20px;" />
|
||||
</td>
|
||||
</tr>
|
||||
@@ -150,6 +160,7 @@
|
||||
<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>
|
||||
<a v-if="!dynamicProps.event.registrationAllowed && !dynamicProps.event.archived" style="color: #ff0000; font-size: 9pt;" class="link" @click="archiveEvent">Archivieren</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ watch(
|
||||
form.medications = participant?.medications ?? '';
|
||||
form.extendedFirstAid = participant?.first_aid_permission ?? '';
|
||||
form.swimmingPermission = participant?.swimming_permission ?? '';
|
||||
form.tetanusVaccination = participant?.tetanus_vaccination ?? '';
|
||||
form.tetanusVaccination = participant?.tetanusVaccinationEdit ?? '';
|
||||
form.notes = participant?.notes ?? '';
|
||||
form.amountPaid = participant?.amountPaid.short ?? '';
|
||||
form.amountExpected = participant?.amountExpected.short ?? '';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script setup>
|
||||
import {reactive} from "vue";
|
||||
import ErrorText from "../../../../../../Views/Components/ErrorText.vue";
|
||||
|
||||
const props = defineProps({ formData: Object, localGroups: Array })
|
||||
const emit = defineEmits(['next', 'back'])
|
||||
@@ -64,6 +65,11 @@ const next = () => {
|
||||
hasError = true
|
||||
}
|
||||
|
||||
if (!props.formData.telefon_1) {
|
||||
errors.telefon_1 = 'Bitte eine Telefonnummer angeben.'
|
||||
hasError = true
|
||||
}
|
||||
|
||||
if (!props.formData.email_1) {
|
||||
errors.email_1 = 'Bitte eine E-Mail-Adresse angeben.'
|
||||
hasError = true
|
||||
@@ -80,8 +86,8 @@ const next = () => {
|
||||
<div>
|
||||
<h3>Persönliche Daten</h3>
|
||||
<table class="form-table">
|
||||
<tr><td>Vorname:</td><td><input type="text" v-model="props.formData.vorname" /></td></tr>
|
||||
<tr><td>Nachname:</td><td><input type="text" v-model="props.formData.nachname" /></td></tr>
|
||||
<tr><td>Vorname:</td><td><input type="text" v-model="props.formData.vorname" /><ErrorText :message="errors.vorname"/></td></tr>
|
||||
<tr><td>Nachname:</td><td><input type="text" v-model="props.formData.nachname" /><ErrorText :message="errors.nachname"/></td></tr>
|
||||
<tr><td>Pfadiname:</td><td><input type="text" v-model="props.formData.pfadiname" /></td></tr>
|
||||
<tr>
|
||||
<td>Stamm:</td>
|
||||
@@ -90,9 +96,10 @@ const next = () => {
|
||||
<option value="-1">Bitte wählen</option>
|
||||
<option v-for="lg in localGroups" :key="lg.id" :value="lg.id">{{ lg.name }}</option>
|
||||
</select>
|
||||
<ErrorText :message="errors.localGroup" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td>Geburtsdatum:</td><td><input type="date" v-model="props.formData.geburtsdatum" /></td></tr>
|
||||
<tr><td>Geburtsdatum:</td><td><input type="date" v-model="props.formData.geburtsdatum" /><ErrorText :message="errors.geburtsdatum" /></td></tr>
|
||||
<tr>
|
||||
<td>Adresse:</td>
|
||||
<td>
|
||||
@@ -103,6 +110,7 @@ const next = () => {
|
||||
<td></td>
|
||||
<td>
|
||||
<input type="text" v-model="props.formData.address2" />
|
||||
<ErrorText :message="errors.address1" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -110,10 +118,12 @@ const next = () => {
|
||||
<td>
|
||||
<input maxlength="5" type="text" v-model="props.formData.plz" style="width: 100px; margin-right: 8px;" />
|
||||
<input type="text" v-model="props.formData.ort" style="width: calc(100% - 110px);" />
|
||||
<ErrorText :message="errors.plz" />
|
||||
<ErrorText :message="errors.ort" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td>Telefon:</td><td><input type="text" v-model="props.formData.telefon_1" /></td></tr>
|
||||
<tr><td>E-Mail:</td><td><input type="text" v-model="props.formData.email_1" /></td></tr>
|
||||
<tr><td>Telefon:</td><td><input type="text" v-model="props.formData.telefon_1" /><ErrorText :message="errors.telefon_1" /></td></tr>
|
||||
<tr><td>E-Mail:</td><td><input type="text" v-model="props.formData.email_1" /><ErrorText :message="errors.email_1" /></td></tr>
|
||||
<tr>
|
||||
<td colspan="2" class="btn-row">
|
||||
<button type="button" class="btn-primary" @click="next">Weiter →</button>
|
||||
|
||||
@@ -42,6 +42,8 @@ class CreateInvoiceCommand {
|
||||
'travel_reason' => $this->request->travelReason,
|
||||
'passengers' => $this->request->passengers,
|
||||
'transportation' => $this->request->transportations,
|
||||
'payment_purpose' => $this->request->paymentPurpose,
|
||||
'comment' => $this->request->notices,
|
||||
'document_filename' => $this->request->receiptFile !== null ? $this->request->receiptFile->fullPath : null,
|
||||
]);
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ class CreateInvoiceRequest {
|
||||
public bool $isDonation;
|
||||
public ?int $userId;
|
||||
public ?string $travelReason;
|
||||
public ?string $paymentPurpose;
|
||||
public ?string $notices;
|
||||
|
||||
|
||||
public function __construct(
|
||||
@@ -43,6 +45,8 @@ class CreateInvoiceRequest {
|
||||
?int $passengers = null,
|
||||
?int $transportations,
|
||||
?string $travelReason = null,
|
||||
?string $paymentPurpose = null,
|
||||
?string $notices = null,
|
||||
|
||||
) {
|
||||
$this->costUnit = $costUnit;
|
||||
@@ -62,6 +66,8 @@ class CreateInvoiceRequest {
|
||||
$this->isDonation = $isDonation;
|
||||
$this->userId = $userId;
|
||||
$this->travelReason = $travelReason;
|
||||
$this->paymentPurpose = $paymentPurpose;
|
||||
$this->notices = $notices;
|
||||
|
||||
if ($accountIban === 'undefined') {
|
||||
$this->accountIban = null;
|
||||
|
||||
@@ -60,7 +60,6 @@ class CreateInvoiceReceiptCommand {
|
||||
storage_path('app/private/' .$filename) . '.zip',
|
||||
ZipArchive::CREATE | ZipArchive::OVERWRITE
|
||||
);
|
||||
|
||||
$zip->addFile(storage_path('app/private/' . $tmpFileName ), 'antrag.pdf');
|
||||
$zip->addFile(storage_path('app/private/' . $receipt), 'beleg.pdf');
|
||||
|
||||
@@ -114,6 +113,9 @@ HTML;
|
||||
<tr><td>Name:</td><td>%3\$s</td></tr>
|
||||
<tr><td>E-Mail:</td><td>%4\$s</td></tr>
|
||||
<tr><td>Telefon:</td><td>%5\$s</td></tr>
|
||||
<tr><td>Anmerkungen:</td><td>%16\$s</td></tr>
|
||||
|
||||
|
||||
<tr><td>Name der Kostenstelle:</td><td>%6\$s</td></tr>
|
||||
<tr><td>Zahlungsgrund:</td><td>%7\$s</td></tr>
|
||||
<tr><td>Wird der Betrag gespendet:</td><td>%8\$s</td></tr>
|
||||
@@ -186,7 +188,8 @@ HTML;
|
||||
$invoiceReadable['createdAt'],
|
||||
$invoiceReadable['approvedAt'],
|
||||
$invoiceReadable['approvedBy'],
|
||||
$changes
|
||||
$changes,
|
||||
$invoiceReadable['comment'],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,13 +8,13 @@ use App\Models\Invoice;
|
||||
use App\ValueObjects\Amount;
|
||||
|
||||
class UpdateInvoiceRequest {
|
||||
public string $comment;
|
||||
public ?string $comment;
|
||||
public InvoiceType $invoiceType;
|
||||
public CostUnit $costUnit;
|
||||
public Invoice $invoice;
|
||||
public Amount $amount;
|
||||
|
||||
public function __construct(Invoice $invoice, string $comment, InvoiceType $invoiceType, CostUnit $costUnit, Amount $amount) {
|
||||
public function __construct(Invoice $invoice, ?string $comment, InvoiceType $invoiceType, CostUnit $costUnit, Amount $amount) {
|
||||
$this->comment = $comment;
|
||||
$this->invoiceType = $invoiceType;
|
||||
$this->costUnit = $costUnit;
|
||||
|
||||
@@ -47,7 +47,10 @@ class EditController extends CommonController{
|
||||
$invoice->travel_direction,
|
||||
$invoice->distance,
|
||||
$invoice->passengers,
|
||||
$invoice->transportation
|
||||
$invoice->transportation,
|
||||
$invoice->travel_reason,
|
||||
$invoice->payment_purpose,
|
||||
$invoice->comment,
|
||||
);
|
||||
|
||||
$invoiceCreationCommand = new CreateInvoiceCommand($createInvoiceRequest);
|
||||
@@ -86,7 +89,7 @@ class EditController extends CommonController{
|
||||
|
||||
$updateInvoiceRequest = new UpdateInvoiceRequest(
|
||||
$invoice,
|
||||
$modifyData['reason_of_correction'] ?? 'Abrechnungskorrektur',
|
||||
$modifyData['notices'],
|
||||
$invoiceType,
|
||||
$newCostUnit,
|
||||
$newAmount
|
||||
|
||||
@@ -34,102 +34,4 @@ class NewInvoiceController extends CommonController {
|
||||
]);
|
||||
return $inertiaProvider->render();
|
||||
}
|
||||
|
||||
public function saveInvoice(Request $request, int $costUnitId, string $invoiceType) : JsonResponse {
|
||||
$costUnit = $this->costUnits->getById($costUnitId, true);
|
||||
if (null === $costUnit) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Beim Speichern ist ein Fehler aufgetreten. Bitte starte den Vorgang erneut.'
|
||||
]);
|
||||
}
|
||||
|
||||
$uploadedFile = null;
|
||||
if (null !== $request->file('receipt')) {
|
||||
$validation = sprintf('%1$s|%2$s|max:%3$s',
|
||||
'required',
|
||||
'mimes:pdf',
|
||||
env('MAX_INVOICE_FILE_SIZE', 16)*10
|
||||
);
|
||||
|
||||
$request->validate([
|
||||
'receipt' => $validation
|
||||
]);
|
||||
|
||||
$uploadFileProvider = new UploadFileProvider($request->file('receipt'), $costUnit);
|
||||
$uploadedFile = $uploadFileProvider->saveUploadedFile();
|
||||
}
|
||||
|
||||
switch ($invoiceType) {
|
||||
case InvoiceType::INVOICE_TYPE_TRAVELLING:
|
||||
|
||||
if ($uploadedFile !== null) {
|
||||
$amount = Amount::fromString($request->input('amount'))->getAmount();
|
||||
$distance = null;
|
||||
} else {
|
||||
$distance = Amount::fromString($request->input('amount'))->getRoundedAmount();
|
||||
$amount = $distance * $costUnit->distance_allowance;
|
||||
|
||||
}
|
||||
|
||||
$createInvoiceRequest = new CreateInvoiceRequest(
|
||||
$costUnit,
|
||||
$request->input('name'),
|
||||
InvoiceType::INVOICE_TYPE_TRAVELLING,
|
||||
$amount,
|
||||
$uploadedFile,
|
||||
'donation' === $request->input('decision') ? true : false,
|
||||
$this->users->getCurrentUserDetails()['userId'],
|
||||
$request->input('email'),
|
||||
$request->input('telephone'),
|
||||
$request->input('accountOwner'),
|
||||
$request->input('accountIban'),
|
||||
null,
|
||||
$request->input('otherText'),
|
||||
$distance,
|
||||
$request->input('havePassengers'),
|
||||
$request->input('materialTransportation'),
|
||||
$request->input('travelReason'),
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$createInvoiceRequest = new CreateInvoiceRequest(
|
||||
$costUnit,
|
||||
$request->input('name'),
|
||||
$invoiceType,
|
||||
Amount::fromString($request->input('amount'))->getAmount(),
|
||||
$uploadedFile,
|
||||
'donation' === $request->input('decision') ? true : false,
|
||||
$this->users->getCurrentUserDetails()['userId'],
|
||||
$request->input('email'),
|
||||
$request->input('telephone'),
|
||||
$request->input('accountOwner'),
|
||||
$request->input('accountIban'),
|
||||
$request->input('otherText'),
|
||||
null,
|
||||
null,
|
||||
$request->input('havePassengers'),
|
||||
$request->input('materialTransportation'),
|
||||
null
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$command = new CreateInvoiceCommand($createInvoiceRequest);
|
||||
$response = $command->execute();
|
||||
if ($response->success) {
|
||||
new FlashMessageProvider(
|
||||
'Die Abrechnung wurde erfolgreich angelegt.' . PHP_EOL . PHP_EOL . 'Sollten wir Rückfragen haben, melden wir uns bei dir',
|
||||
'success'
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Alright'
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Invoice\Controllers;
|
||||
|
||||
use App\Domains\Invoice\Actions\CreateInvoice\CreateInvoiceCommand;
|
||||
use App\Domains\Invoice\Actions\CreateInvoice\CreateInvoiceRequest;
|
||||
use App\Enumerations\InvoiceType;
|
||||
use App\Providers\FlashMessageProvider;
|
||||
use App\Providers\UploadFileProvider;
|
||||
use App\Scopes\CommonController;
|
||||
use App\ValueObjects\Amount;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class SaveInvoiceController extends CommonController
|
||||
{
|
||||
public function __invoke(Request $request, int $costUnitId, string $invoiceType) : JsonResponse {
|
||||
$costUnit = $this->costUnits->getById($costUnitId, true);
|
||||
$paymentPurpose = $request->input('paymentPurpose') ?? null;
|
||||
$notices = $request->input('notices') ?? null;
|
||||
if (null === $costUnit) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Beim Speichern ist ein Fehler aufgetreten. Bitte starte den Vorgang erneut.'
|
||||
]);
|
||||
}
|
||||
|
||||
$uploadedFile = null;
|
||||
if (null !== $request->file('receipt')) {
|
||||
$maxFileSize = env('MAX_INVOICE_FILE_SIZE', 16);
|
||||
$validation = sprintf('%1$s|%2$s|max:%3$s',
|
||||
'required',
|
||||
'mimes:pdf',
|
||||
$maxFileSize * 1024
|
||||
);
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
'receipt' => $validation
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => sprintf(
|
||||
'Der Beleg konnte nicht hochgeladen werden. Bitte beachte die Maximale Dateigröße von %1$s MB sowie die Tatsache, dass ausschließlich PDF-Dateien akzeptiert werden.',
|
||||
$maxFileSize
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
$uploadFileProvider = new UploadFileProvider($request->file('receipt'), $costUnit);
|
||||
$uploadedFile = $uploadFileProvider->saveUploadedFile();
|
||||
}
|
||||
|
||||
switch ($invoiceType) {
|
||||
case InvoiceType::INVOICE_TYPE_TRAVELLING:
|
||||
|
||||
if ($uploadedFile !== null) {
|
||||
$amount = Amount::fromString($request->input('amount'))->getAmount();
|
||||
$distance = null;
|
||||
} else {
|
||||
$distance = Amount::fromString($request->input('amount'))->getRoundedAmount();
|
||||
$amount = $distance * $costUnit->distance_allowance;
|
||||
|
||||
}
|
||||
|
||||
$createInvoiceRequest = new CreateInvoiceRequest(
|
||||
$costUnit,
|
||||
$request->input('name'),
|
||||
InvoiceType::INVOICE_TYPE_TRAVELLING,
|
||||
$amount,
|
||||
$uploadedFile,
|
||||
'donation' === $request->input('decision') ? true : false,
|
||||
$this->users->getCurrentUserDetails()['userId'],
|
||||
$request->input('email'),
|
||||
$request->input('telephone'),
|
||||
$request->input('accountOwner'),
|
||||
$request->input('accountIban'),
|
||||
null,
|
||||
$request->input('otherText'),
|
||||
$distance,
|
||||
$request->input('havePassengers'),
|
||||
$request->input('materialTransportation'),
|
||||
$request->input('travelReason'),
|
||||
null,
|
||||
$notices
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$createInvoiceRequest = new CreateInvoiceRequest(
|
||||
$costUnit,
|
||||
$request->input('name'),
|
||||
$invoiceType,
|
||||
Amount::fromString($request->input('amount'))->getAmount(),
|
||||
$uploadedFile,
|
||||
'donation' === $request->input('decision') ? true : false,
|
||||
$this->users->getCurrentUserDetails()['userId'],
|
||||
$request->input('email'),
|
||||
$request->input('telephone'),
|
||||
$request->input('accountOwner'),
|
||||
$request->input('accountIban'),
|
||||
$request->input('otherText'),
|
||||
null,
|
||||
null,
|
||||
$request->input('havePassengers'),
|
||||
$request->input('materialTransportation'),
|
||||
null,
|
||||
$paymentPurpose,
|
||||
$notices
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$command = new CreateInvoiceCommand($createInvoiceRequest);
|
||||
$response = $command->execute();
|
||||
if ($response->success) {
|
||||
new FlashMessageProvider(
|
||||
'Die Abrechnung wurde erfolgreich angelegt.' . PHP_EOL . PHP_EOL . 'Sollten wir Rückfragen haben, melden wir uns bei dir',
|
||||
'success'
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => 'Alright'
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,13 +6,14 @@ use App\Domains\Invoice\Controllers\ChangeStateController;
|
||||
use App\Domains\Invoice\Controllers\EditController;
|
||||
use App\Domains\Invoice\Controllers\ListMyInvoicesController;
|
||||
use App\Domains\Invoice\Controllers\NewInvoiceController;
|
||||
use App\Domains\Invoice\Controllers\SaveInvoiceController;
|
||||
use App\Domains\Invoice\Controllers\ShowInvoiceController;
|
||||
use App\Middleware\IdentifyTenant;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::middleware(IdentifyTenant::class)->group(function () {
|
||||
Route::prefix('api/v1/invoice')->group(function () {
|
||||
Route::post('/new/{costUnitId}/{invoiceType}', [NewInvoiceController::class, 'saveInvoice']);
|
||||
Route::post('/new/{costUnitId}/{invoiceType}', SaveInvoiceController::class);
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
Route::get('/details/{invoiceId}', ShowInvoiceController::class);
|
||||
Route::get('/showReceipt/{invoiceId}', [ShowInvoiceController::class, 'showReceipt']);
|
||||
|
||||
@@ -5,6 +5,7 @@ import Modal from "../../../Views/Components/Modal.vue";
|
||||
import {onMounted, reactive, ref} from "vue";
|
||||
import ExpenseAccounting from "./Partials/newInvoice/expense-accounting.vue";
|
||||
import TravelExpenseAccounting from "./Partials/newInvoice/travel-expense-accounting.vue";
|
||||
import DirectPayment from "./Partials/newInvoice/direct-payment.vue";
|
||||
|
||||
const props = defineProps({
|
||||
currentEvents: Object,
|
||||
@@ -42,6 +43,24 @@ const invoiceType = ref('');
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="eventId === 0"
|
||||
class="invoice-type-layer" style="width: calc(100% - 60px); margin: auto"
|
||||
@click="isOpen = true;invoiceType='direct-payment'"
|
||||
>
|
||||
<TextResource textName="NEW_DIRECT_PAYMENT" />
|
||||
</div>
|
||||
|
||||
<DirectPayment v-if="invoiceType === 'direct-payment' && eventId !== 0"
|
||||
:eventId="eventId"
|
||||
:userName="props.userName"
|
||||
:userEmail="props.userEmail"
|
||||
:userTelephone="props.userTelephone"
|
||||
:userAccountIban="props.userAccountIban"
|
||||
:userAccountOwner="props.userAccountOwner"
|
||||
:userId="props.userId"
|
||||
/>
|
||||
|
||||
<ExpenseAccounting v-if="invoiceType === 'expense-accounting' && eventId !== 0"
|
||||
:eventId="eventId"
|
||||
:userName="props.userName"
|
||||
@@ -62,7 +81,7 @@ const invoiceType = ref('');
|
||||
:userId="props.userId"
|
||||
/>
|
||||
|
||||
<Modal :show="isOpen" title="Veranstaltung auswählen" @close="isOpen = false">
|
||||
<Modal :show="isOpen" title="Veranstaltung auswählen" @close="isOpen = false" width="450px">
|
||||
<select v-model="eventId" @change="isOpen=false" style="width: 100%">
|
||||
<option value="0" disabled>Bitte auswählen</option>
|
||||
<optgroup label="Laufende Tätigkeiten">
|
||||
|
||||
@@ -20,7 +20,7 @@ const formData = reactive({
|
||||
type_internal: props.newInvoice.internalType || '',
|
||||
cost_unit: props.newInvoice.costUnitId || '',
|
||||
amount: props.newInvoice.amountPlain || '',
|
||||
reason_of_correction: '',
|
||||
notices: props.newInvoice.comments || '',
|
||||
})
|
||||
|
||||
const submitForm = () => {
|
||||
@@ -71,9 +71,13 @@ onMounted(async () => {
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Grund der Korrektur:</td>
|
||||
<td>Anmerkungen:</td>
|
||||
<td>
|
||||
<input type="text" v-model="formData.reason_of_correction" class="width-half-full" />
|
||||
<textarea
|
||||
id="notices"
|
||||
name="notices" v-model="formData.notices"
|
||||
maxlength="128"
|
||||
style="font-size: 14pt; width: 550px;" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ const emit = defineEmits(["accept", "deny", "fix", "reopen"])
|
||||
<td>{{props.data.accountIban}}</td>
|
||||
<td>Buchungsinformationen:</td>
|
||||
<td v-if="props.data.donation">Als Spende gebucht</td>
|
||||
<td v-else-if="props.data.alreadyPaid">Beleg ohne Auszahlung</td>
|
||||
<td v-else-if="props.data.externalPayment">Rechnungszahlung</td>
|
||||
<td v-else>Klassische Auszahlung</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
@@ -81,7 +81,7 @@ const emit = defineEmits(["accept", "deny", "fix", "reopen"])
|
||||
<td>{{props.data.accountIban}}</td>
|
||||
<td>Buchungsinformationen:</td>
|
||||
<td v-if="props.data.donation">Als Spende gebucht</td>
|
||||
<td v-else-if="props.data.alreadyPaid">Beleg ohne Auszahlung</td>
|
||||
<td v-else-if="props.data.externalPayment">Rechnungszahlung</td>
|
||||
<td v-else>Klassische Auszahlung</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
</td>
|
||||
<td style="width: 150px;">
|
||||
<Icon v-if="invoice.donation" name="hand-holding-dollar" style="color: #ffffff; background-color: green" />
|
||||
<Icon v-if="invoice.alreadyPaid" name="comments-dollar" style="color: #ffffff; background-color: green" />
|
||||
<Icon v-if="invoice.externalPayment" name="comments-dollar" style="color: #ffffff; background-color: green" />
|
||||
</td>
|
||||
<td>
|
||||
{{invoice.contactName}}<br />
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
<script setup>
|
||||
|
||||
import { ref, onMounted, reactive } from 'vue'
|
||||
import {checkFilesize} from "../../../../../../resources/js/components/InvoiceUploadChecks.js";
|
||||
import RefundData from "./refund-data.vue";
|
||||
import AmountInput from "../../../../../Views/Components/AmountInput.vue";
|
||||
import {useAjax} from "../../../../../../resources/js/components/ajaxHandler.js";
|
||||
import InfoIcon from '../../../../../Views/Components/InfoIcon.vue'
|
||||
import {toast} from "vue3-toastify";
|
||||
import PaymentData from "./payment-data.vue";
|
||||
|
||||
|
||||
|
||||
const data = defineProps({
|
||||
eventId: Number,
|
||||
userName: String,
|
||||
userEmail: String,
|
||||
userTelephone: String,
|
||||
userAccountIban: String,
|
||||
userAccountOwner: String,
|
||||
})
|
||||
|
||||
|
||||
const { request } = useAjax();
|
||||
const amount = ref(0.00);
|
||||
const invoiceType = ref(null);
|
||||
const otherText = ref('');
|
||||
const receipt = ref(null)
|
||||
const finalStep = ref(false)
|
||||
|
||||
const invoiceTypeCollection = reactive({
|
||||
invoiceTypes: {}
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
const response = await fetch('/api/v1/core/retrieve-invoice-types');
|
||||
const data = await response.json();
|
||||
Object.assign(invoiceTypeCollection, data);
|
||||
});
|
||||
|
||||
|
||||
function handleFileChange(event) {
|
||||
if (checkFilesize('receipt')) {
|
||||
receipt.value = event.target.files[0]
|
||||
finalStep.value = true
|
||||
} else {
|
||||
event.target.value = null
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<fieldset>
|
||||
<legend><span style="font-weight: bolder;">Was ist der Anlass der Rechnung</span></legend>
|
||||
|
||||
<p v-for="availableInvoiceType in invoiceTypeCollection.invoiceTypes">
|
||||
<input
|
||||
name="invpice_type"
|
||||
type="radio"
|
||||
:value="availableInvoiceType.slug"
|
||||
:id="'invoice_type_' + availableInvoiceType.slug"
|
||||
v-model="invoiceType"
|
||||
>
|
||||
<label :for="'invoice_type_' + availableInvoiceType.slug">{{ availableInvoiceType.name }}</label>
|
||||
<InfoIcon :text="'INFO_INVOICE_TYPE_' + availableInvoiceType.slug" /><br />
|
||||
</p>
|
||||
|
||||
|
||||
<label for="invoice_type_other">
|
||||
<input
|
||||
type="text"
|
||||
class="width-full"
|
||||
name="kostengruppe_sonstiges"
|
||||
placeholder="Sonstige"
|
||||
for="invoice_type_other"
|
||||
v-model="otherText"
|
||||
@focus="invoiceType = 'other'"
|
||||
/>
|
||||
</label>
|
||||
|
||||
</fieldset><br /><br />
|
||||
|
||||
<fieldset>
|
||||
<legend><span style="font-weight: bolder;">Wie hoch ist der Betrag</span></legend>
|
||||
<AmountInput v-model="amount" class="width-small" id="amount" name="amount" /> Euro
|
||||
<info-icon></info-icon><br /><br />
|
||||
|
||||
<input
|
||||
v-if="amount != '' && invoiceType !== null"
|
||||
class="mareike-button"
|
||||
onclick="document.getElementById('receipt').click();"
|
||||
type="button"
|
||||
value="Beleg auswählen und fortfahren" />
|
||||
<input accept="application/pdf" type="file" id="receipt" name="receipt" @change="handleFileChange"
|
||||
style="display: none"/>
|
||||
</fieldset><br />
|
||||
|
||||
|
||||
|
||||
<PaymentData
|
||||
v-if="finalStep"
|
||||
:eventId="data.eventId"
|
||||
:invoice-type="invoiceType"
|
||||
:amount="amount"
|
||||
:other-text="otherText"
|
||||
:userName="data.userName"
|
||||
:userEmail="data.userEmail"
|
||||
:userTelephone="data.userTelephone"
|
||||
:userAccountIban="data.userAccountIban"
|
||||
:userAccountOwner="data.userAccountOwner"
|
||||
:receipt="receipt"
|
||||
travelReason=""
|
||||
@close="finalStep = false"
|
||||
/>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import Modal from "../../../../../Views/Components/Modal.vue";
|
||||
import IbanInput from "../../../../../Views/Components/IbanInput.vue";
|
||||
import {useAjax} from "../../../../../../resources/js/components/ajaxHandler.js";
|
||||
import TextResource from "../../../../../Views/Components/TextResource.vue";
|
||||
import {invoiceCheckContactName} from "../../../../../../resources/js/components/InvoiceUploadChecks.js";
|
||||
import {toast} from "vue3-toastify";
|
||||
import ErrorText from "../../../../../Views/Components/ErrorText.vue";
|
||||
|
||||
const { request } = useAjax();
|
||||
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
|
||||
const props = defineProps({
|
||||
eventId: Number,
|
||||
invoiceType: String,
|
||||
amount: [String, Number],
|
||||
otherText: String,
|
||||
receipt: File,
|
||||
userName: String,
|
||||
userEmail: String,
|
||||
userTelephone: String,
|
||||
userAccountOwner: String,
|
||||
userAccountIban: String,
|
||||
havePassengers: Number,
|
||||
materialTransportation: Boolean,
|
||||
travelReason: String,
|
||||
})
|
||||
|
||||
const finalStep = ref(true)
|
||||
const userName = ref(props.userName)
|
||||
const userEmail = ref(props.userEmail)
|
||||
const userTelephone = ref(props.userTelephone)
|
||||
const userIban = ref('')
|
||||
const userAccountOwner = ref('')
|
||||
const paymentPurpose = ref('')
|
||||
const sending = ref(false)
|
||||
const success = ref(false)
|
||||
const decision = ref('')
|
||||
const errorMsg = ref('')
|
||||
const confirmation = ref(null)
|
||||
const receiptError = ref('')
|
||||
|
||||
async function sendData() {
|
||||
if (!userName.value) return
|
||||
|
||||
sending.value = true
|
||||
errorMsg.value = ''
|
||||
success.value = false
|
||||
|
||||
const formData = new FormData()
|
||||
|
||||
formData.append('name', userName.value)
|
||||
formData.append('email', userEmail.value)
|
||||
formData.append('telephone', userTelephone.value)
|
||||
formData.append('amount', props.amount)
|
||||
formData.append('otherText', props.otherText)
|
||||
formData.append('decision', decision.value)
|
||||
formData.append('accountOwner', userAccountOwner.value)
|
||||
formData.append('accountIban', userIban.value)
|
||||
formData.append('paymentPurpose', paymentPurpose.value)
|
||||
formData.append('havePassengers', props.havePassengers ? 1 : 0)
|
||||
formData.append('materialTransportation', props.materialTransportation ? 1 : 0)
|
||||
formData.append('travelReason', props.travelReason)
|
||||
|
||||
if (props.receipt) {
|
||||
formData.append('receipt', props.receipt)
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const response = await request('/api/v1/invoice/new/' + props.eventId + '/' + props.invoiceType, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
|
||||
if (response.status === 'success') {
|
||||
window.location.href = '/';
|
||||
} else {
|
||||
receiptError.value = response.message;
|
||||
}
|
||||
} catch (err) {
|
||||
toast.error(result.message);
|
||||
} finally {
|
||||
sending.value = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal :show="finalStep" title='Bitte gib deine Daten ein' @close="emit('close')" width="600px">
|
||||
<label>
|
||||
<strong>Dein Name Name (kein Pfadiname):</strong>
|
||||
</label><br />
|
||||
<input
|
||||
type="text"
|
||||
@keyup="invoiceCheckContactName();"
|
||||
id="contact_name"
|
||||
name="contact_name" v-model="userName"
|
||||
style="font-size: 14pt; width: 550px;" /><br /><br />
|
||||
|
||||
<label v-if="userName !== ''">
|
||||
<strong>E-Mail-Adresse (Für Rückfragen):</strong>
|
||||
</label><br />
|
||||
<input
|
||||
v-if="userName !== ''"
|
||||
type="email"
|
||||
name="contact_email"
|
||||
v-model="userEmail"
|
||||
style="font-size: 14pt; width: 550px;" /><br /><br />
|
||||
|
||||
<label v-if="userName !== ''">
|
||||
<strong>Telefonnummer (für Rückfragen):</strong>
|
||||
</label><br />
|
||||
<input
|
||||
v-if="userName !== ''"
|
||||
type="text"
|
||||
id="contact_telephone"
|
||||
name="contact_telephone" v-model="userTelephone"
|
||||
style="font-size: 14pt; width: 550px;" /><br /><br />
|
||||
|
||||
<span id="confirm_payment" v-if="userEmail !== '' && userTelephone !== ''">
|
||||
<label>
|
||||
<strong>Zahlungsempfänger*in:</strong>
|
||||
</label><br />
|
||||
<input type="text" name="account_owner" id="account_owner" v-model="userAccountOwner" style="font-size: 14pt; width: 550px;" /><br /><br />
|
||||
|
||||
<label>
|
||||
<strong>IBAN:</strong>
|
||||
</label><br />
|
||||
<IbanInput id="account_iban" name="account_iban" v-model="userIban" style="font-size: 14pt; width: 550px;" /><br /><br />
|
||||
|
||||
<label>
|
||||
<strong>Überweisungstext (laut Rechnung):</strong>
|
||||
</label><br />
|
||||
<input
|
||||
type="text"
|
||||
id="payment_purpose"
|
||||
name="payment_purpose"
|
||||
v-model="paymentPurpose"
|
||||
style="font-size: 14pt; width: 550px;"
|
||||
/><br /><br />
|
||||
<ErrorText :message="receiptError" />
|
||||
|
||||
<span v-if="paymentPurpose != '' && userAccountOwner != '' && userIban && userIban.length === 27"><br />
|
||||
<input type="radio" name="confirmation_radio" value="payment" id="confirmation_radio_payment" v-model="confirmation">
|
||||
<TextResource belongsTo="confirmation_radio_payment" textName="CONFIRMATION_DIRECT_PAYMENT" /><br /><br />
|
||||
<input type="button" v-if="confirmation !== null && !sending" @click="sendData" value="Beleg einreichen" />
|
||||
</span>
|
||||
</span>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* optional styling */
|
||||
</style>
|
||||
|
||||
@@ -6,6 +6,7 @@ import {useAjax} from "../../../../../../resources/js/components/ajaxHandler.js"
|
||||
import TextResource from "../../../../../Views/Components/TextResource.vue";
|
||||
import {invoiceCheckContactName} from "../../../../../../resources/js/components/InvoiceUploadChecks.js";
|
||||
import {toast} from "vue3-toastify";
|
||||
import ErrorText from "../../../../../Views/Components/ErrorText.vue";
|
||||
|
||||
const { request } = useAjax();
|
||||
|
||||
@@ -39,7 +40,8 @@ const success = ref(false)
|
||||
const decision = ref('')
|
||||
const errorMsg = ref('')
|
||||
const confirmation = ref(null)
|
||||
|
||||
const receiptError = ref('')
|
||||
const notices = ref('')
|
||||
|
||||
async function sendData() {
|
||||
if (!userName.value) return
|
||||
@@ -61,6 +63,7 @@ async function sendData() {
|
||||
formData.append('havePassengers', props.havePassengers ? 1 : 0)
|
||||
formData.append('materialTransportation', props.materialTransportation ? 1 : 0)
|
||||
formData.append('travelReason', props.travelReason)
|
||||
formData.append('notices', notices.value)
|
||||
|
||||
if (props.receipt) {
|
||||
formData.append('receipt', props.receipt)
|
||||
@@ -75,6 +78,8 @@ async function sendData() {
|
||||
|
||||
if (response.status === 'success') {
|
||||
window.location.href = '/';
|
||||
} else {
|
||||
receiptError.value = response.message;
|
||||
}
|
||||
} catch (err) {
|
||||
toast.error(result.message);
|
||||
@@ -87,7 +92,7 @@ async function sendData() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal :show="finalStep" title='Bitte gib deine Daten ein' @close="emit('close')">
|
||||
<Modal :show="finalStep" title='Bitte gib deine Daten ein' @close="emit('close')" width="600px">
|
||||
<label>
|
||||
<strong>Dein Name Name (kein Pfadiname):</strong>
|
||||
</label><br />
|
||||
@@ -118,7 +123,16 @@ async function sendData() {
|
||||
name="contact_telephone" v-model="userTelephone"
|
||||
style="font-size: 14pt; width: 550px;" /><br /><br />
|
||||
|
||||
<span id="decision" v-if="userEmail !== '' && decision === ''">
|
||||
<label v-if="userName !== ''">
|
||||
<strong>Weitere Informationen zur Abrechnung (Max. 128 Zeichen):</strong>
|
||||
</label><br />
|
||||
<textarea
|
||||
id="notices"
|
||||
name="notices" v-model="notices"
|
||||
maxlength="128"
|
||||
style="font-size: 14pt; width: 550px;" /><br /><br />
|
||||
|
||||
<span id="decision" v-if="userEmail !== '' && userTelephone !== '' && decision === ''">
|
||||
<label><br />
|
||||
<strong>Möchtest du den Betrag spenden?</strong>
|
||||
</label><br />
|
||||
@@ -143,7 +157,7 @@ async function sendData() {
|
||||
<strong>IBAN:</strong>
|
||||
</label><br />
|
||||
<IbanInput id="account_iban" name="account_iban" v-model="userIban" style="font-size: 14pt; width: 550px;" /><br /><br />
|
||||
|
||||
<ErrorText :message="receiptError" />
|
||||
<span v-if="userAccountOwner != '' && userIban && userIban.length === 27"><br />
|
||||
<input type="radio" name="confirmation_radio" value="payment" id="confirmation_radio_payment" v-model="confirmation">
|
||||
<TextResource belongsTo="confirmation_radio_payment" textName="CONFIRMATION_PAYMENT" /><br /><br />
|
||||
|
||||
@@ -37,7 +37,7 @@ class UserRegistrationCommand {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$generateActivationCoedeRequest = new GenerateActivationTokenRequest($user);
|
||||
$generateActivationCoedeRequest = new GenerateActivationTokenRequest($user, new \DateTime()->add(new \DateInterval('P1D')));
|
||||
$generateActivationCoedeDommand = new GenerateActivationTokenCommand($generateActivationCoedeRequest);
|
||||
$result = $generateActivationCoedeDommand->execute();
|
||||
|
||||
|
||||
@@ -15,6 +15,11 @@ class InvoiceType extends CommonModel {
|
||||
|
||||
public const INVOICE_TYPE_CATERING = 'catering';
|
||||
|
||||
public const INVOICE_TYPE_LOGSTIC = 'logistic';
|
||||
|
||||
public const INVOICE_TYPE_TECHNICAL = 'technical';
|
||||
|
||||
public const INVOICE_TYPE_MANAGEMENT = 'management';
|
||||
|
||||
protected $fillable = [
|
||||
'slug',
|
||||
|
||||
@@ -24,12 +24,10 @@ class ProductionDataSeeder {
|
||||
$this->installSwimmingPermissions();
|
||||
$this->installEatingHabits();
|
||||
$this->installFirstAidPermissions();
|
||||
$this->installTenants();
|
||||
$this->installInvoiceMetaData();
|
||||
$this->installParticipationFeeTypes();
|
||||
$this->installParticipationTypes();
|
||||
$this->installEfzStatus();
|
||||
$this->installCronTasks();
|
||||
}
|
||||
|
||||
private function installEfzStatus() {
|
||||
@@ -102,21 +100,7 @@ class ProductionDataSeeder {
|
||||
|
||||
}
|
||||
|
||||
private function installTenants() {
|
||||
Tenant::create([
|
||||
'slug' => 'lv',
|
||||
'name' => 'Landesunmittelbare Mitglieder',
|
||||
'url' => 'mareike.local',
|
||||
'account_name' => 'Bund der Pfadfinder*innen Landesverband Sachsen e.V.',
|
||||
'account_iban' => 'DE12345678901234567890',
|
||||
'account_bic' => 'GENODEF1S10',
|
||||
'email' => 'test@example.com',
|
||||
'city' => 'Lommatzsch',
|
||||
'postcode' => '01623',
|
||||
'is_active_local_group' => true,
|
||||
'has_active_instance' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
private function installInvoiceMetaData() {
|
||||
InvoiceType::create([
|
||||
@@ -155,12 +139,5 @@ class ProductionDataSeeder {
|
||||
CronTaskType::create(['slug' => CronTaskType::CRON_TASK_TYPE_REALTIME]);
|
||||
CronTaskType::create(['slug' => CronTaskType::CRON_TASK_TYPE_DAILY]);
|
||||
}
|
||||
|
||||
private function installCronTasks() {
|
||||
CronTask::create(['name' => 'UploadInvoices', 'execution_type' => CronTaskType::CRON_TASK_TYPE_REALTIME]);
|
||||
CronTask::create(['name' => 'CloseCostUnit', 'execution_type' => CronTaskType::CRON_TASK_TYPE_DAILY, 'schedule_time' => '00:05']);
|
||||
CronTask::create(['name' => 'CloseEvent', 'execution_type' => CronTaskType::CRON_TASK_TYPE_DAILY, 'schedule_time' => '00:10']);
|
||||
CronTask::create(['name' => 'NotifyTeam', 'execution_type' => CronTaskType::CRON_TASK_TYPE_DAILY, 'schedule_time' => '20:00']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,271 @@
|
||||
<?php
|
||||
|
||||
namespace App\Installer\Providers;
|
||||
|
||||
use App\Enumerations\CronTaskType;
|
||||
use App\Models\CronTask;
|
||||
use App\Models\Tenant;
|
||||
use App\Models\User;
|
||||
|
||||
class BdpLvSachsenDataSeeder {
|
||||
public function execute() {
|
||||
$this->installTenants();
|
||||
$this->installUsers();
|
||||
$this->installCronTasks();
|
||||
}
|
||||
|
||||
private function installTenants()
|
||||
{
|
||||
Tenant::create([
|
||||
'slug' => 'lv',
|
||||
'name' => 'Landesunmittelbare Mitglieder',
|
||||
'url' => 'beta.mareike.sachsen.pfadfinden.de',
|
||||
'account_name' => 'Bund der Pfadfinder*innen Landesverband Sachsen e.V.',
|
||||
'account_iban' => 'DE12345678901234567890',
|
||||
'account_bic' => 'GENODEF1S10',
|
||||
'email' => 'landesvorstand@sachsen.pfadfinden.de',
|
||||
'email_finance' => 'finanzamt@sachsen.pfadfinden.de',
|
||||
'city' => 'Limbach-Oberfrohne',
|
||||
'postcode' => '09212',
|
||||
'is_active_local_group' => true,
|
||||
'has_active_instance' => true,
|
||||
]);
|
||||
|
||||
Tenant::create([
|
||||
'slug' => 'wm',
|
||||
'name' => 'Wilde Möhre',
|
||||
'url' => 'wilde-moehre.mareike.local',
|
||||
'account_name' => 'Bund der Pfadfinder*innen Landesverband Sachsen e.V. - Stamm Wilde Möhre',
|
||||
'account_iban' => 'DE12345678901234567890',
|
||||
'account_bic' => 'GENODEF1S10',
|
||||
'email' => 'info@pfadfinden-halle.de',
|
||||
'email_finance' => 'info@pfadfinden-halle.de',
|
||||
'city' => 'Halle (Saale)',
|
||||
'postcode' => '06120',
|
||||
'download_exports' => true,
|
||||
'upload_exports' => true,
|
||||
'is_active_local_group' => true,
|
||||
'has_active_instance' => true,
|
||||
]);
|
||||
|
||||
Tenant::create([
|
||||
'slug' => 'anc',
|
||||
'name' => 'Ancalagon',
|
||||
'url' => 'ancalagon.mareike.sachsen.pfadfinden.de',
|
||||
'download_exports' => true,
|
||||
'upload_exports' => true,
|
||||
'is_active_local_group' => true,
|
||||
'has_active_instance' => true,
|
||||
'account_name' => 'Bund der Pfadfinder*innen Landesverband Sachsen e.V. - Stamm Wilde Möhre',
|
||||
'account_iban' => 'DE12345678901234567890',
|
||||
'account_bic' => 'GENODEF1S10',
|
||||
'email' => 'info@stamm-ancalagon.de',
|
||||
'email_finance' => 'info@stamm-ancalagon.de',
|
||||
'city' => 'Leipzig',
|
||||
'postcode' => '04425',
|
||||
]);
|
||||
|
||||
Tenant::create([
|
||||
'slug' => 'ban',
|
||||
'name' => 'Bankiva',
|
||||
'url' => 'bankiva.mareike.sachsen.pfadfinden.de',
|
||||
'download_exports' => true,
|
||||
'upload_exports' => true,
|
||||
'is_active_local_group' => true,
|
||||
'has_active_instance' => true,
|
||||
'account_name' => 'Bund der Pfadfinder*innen Landesverband Sachsen e.V. - Stamm Wilde Möhre',
|
||||
'account_iban' => 'DE12345678901234567890',
|
||||
'account_bic' => 'GENODEF1S10',
|
||||
'email' => 'bankiva@sachsen.pfadfinden.de',
|
||||
'email_finance' => 'bankiva@sachsen.pfadfinden.de',
|
||||
'city' => 'Leipzig',
|
||||
'postcode' => '04157',
|
||||
]);
|
||||
|
||||
Tenant::create([
|
||||
'slug' => 'ere',
|
||||
'name' => 'Erebor',
|
||||
'url' => 'erebor.mareike.sachsen.pfadfinden.de',
|
||||
'download_exports' => true,
|
||||
'upload_exports' => true,
|
||||
'is_active_local_group' => true,
|
||||
'has_active_instance' => true,
|
||||
'account_name' => 'Bund der Pfadfinder*innen Landesverband Sachsen e.V. - Stamm Wilde Möhre',
|
||||
'account_iban' => 'DE12345678901234567890',
|
||||
'account_bic' => 'GENODEF1S10',
|
||||
'email' => 'freiberg@sachsen.pfadfinden.de',
|
||||
'email_finance' => 'freiberg@sachsen.pfadfinden.de',
|
||||
'city' => 'Freiberg',
|
||||
'postcode' => '09599',
|
||||
]);
|
||||
|
||||
Tenant::create([
|
||||
'slug' => 'fen',
|
||||
'name' => 'Fennek',
|
||||
'url' => 'fennek.mareike.local',
|
||||
'download_exports' => true,
|
||||
'upload_exports' => true,
|
||||
'is_active_local_group' => true,
|
||||
'has_active_instance' => true,
|
||||
'account_name' => 'Bund der Pfadfinder*innen Landesverband Sachsen e.V. - Stamm Fennek',
|
||||
'account_iban' => 'DE12345678901234567890',
|
||||
'account_bic' => 'GENODEF1S10',
|
||||
'email' => 'chemnitz@sachsen.pfadfinden.de',
|
||||
'email_finance' => 'chemnitz@sachsen.pfadfinden.de',
|
||||
'city' => 'Chemnitz',
|
||||
'postcode' => '09125',
|
||||
]);
|
||||
|
||||
Tenant::create([
|
||||
'slug' => 'feu',
|
||||
'name' => 'Feuerland',
|
||||
'url' => 'feuerland.mareike.sachsen.pfadfinden.de',
|
||||
'download_exports' => true,
|
||||
'upload_exports' => true,
|
||||
'is_active_local_group' => true,
|
||||
'has_active_instance' => true,
|
||||
'account_name' => 'Bund der Pfadfinder*innen Landesverband Sachsen e.V. - Stamm Feuerland',
|
||||
'account_iban' => 'DE12345678901234567890',
|
||||
'account_bic' => 'GENODEF1S10',
|
||||
'email' => 'info@stamm-feuerland.de',
|
||||
'email_finance' => 'info@stamm-feuerland.de',
|
||||
'city' => 'Leipzig',
|
||||
'postcode' => '04318',
|
||||
]);
|
||||
|
||||
Tenant::create([
|
||||
'slug' => 'gr',
|
||||
'name' => 'Goldener Reiter',
|
||||
'url' => 'goldener-reiter.mareike.sachsen.pfadfinden.de',
|
||||
'download_exports' => true,
|
||||
'upload_exports' => true,
|
||||
'is_active_local_group' => true,
|
||||
'has_active_instance' => true,
|
||||
'account_name' => 'Bund der Pfadfinder*innen Landesverband Sachsen e.V. - Stamm Goldener Reiter',
|
||||
'account_iban' => 'DE12345678901234567890',
|
||||
'account_bic' => 'GENODEF1S10',
|
||||
'email' => 'stafue@goldenerreiter.org',
|
||||
'email_finance' => 'stafue@goldenerreiter.org',
|
||||
'city' => 'Dresden',
|
||||
'postcode' => '01099',
|
||||
]);
|
||||
|
||||
Tenant::create([
|
||||
'slug' => 'leo',
|
||||
'name' => 'LEO',
|
||||
'url' => 'leo.mareike.sachsen.pfadfinden.de',
|
||||
'download_exports' => true,
|
||||
'upload_exports' => true,
|
||||
'is_active_local_group' => true,
|
||||
'has_active_instance' => true,
|
||||
'account_name' => 'Bund der Pfadfinder*innen Landesverband Sachsen e.V. - Stamm Leo',
|
||||
'account_iban' => 'DE12345678901234567890',
|
||||
'account_bic' => 'GENODEF1S10',
|
||||
'email' => 'stafue@leipzig-pfadfinden.de',
|
||||
'email_finance' => 'stafue@leipzig-pfadfinden.de',
|
||||
'city' => 'Leipzig',
|
||||
'postcode' => '04229',
|
||||
]);
|
||||
|
||||
Tenant::create([
|
||||
'slug' => 'rf',
|
||||
'name' => 'Roter Fuchs',
|
||||
'url' => 'roter-fuchs.mareike.sachsen.pfadfinden.de',
|
||||
'download_exports' => true,
|
||||
'upload_exports' => true,
|
||||
'is_active_local_group' => true,
|
||||
'has_active_instance' => true,
|
||||
'account_name' => 'Bund der Pfadfinder*innen Landesverband Sachsen e.V. - Stamm Roter Fuchs',
|
||||
'account_iban' => 'DE12345678901234567890',
|
||||
'account_bic' => 'GENODEF1S10',
|
||||
'email' => 'info@pfadfinden-lommatzsch.de',
|
||||
'email_finance' => 'info@pfadfinden-lommatzsch.de',
|
||||
'city' => 'Lommatzsch',
|
||||
'postcode' => '01623',
|
||||
]);
|
||||
|
||||
Tenant::create([
|
||||
'slug' => 'sapi',
|
||||
'name' => 'Saalepiraten',
|
||||
'url' => 'saalepiraten.mareike.sachsen.pfadfinden.de',
|
||||
'download_exports' => true,
|
||||
'upload_exports' => true,
|
||||
'is_active_local_group' => true,
|
||||
'has_active_instance' => true,
|
||||
'account_name' => 'Bund der Pfadfinder*innen Landesverband Sachsen e.V. - Stamm Saalepiraten',
|
||||
'account_iban' => 'DE12345678901234567890',
|
||||
'account_bic' => 'GENODEF1S10',
|
||||
'email' => 'saalepiratenbernburg@gmail.com',
|
||||
'email_finance' => 'saalepiratenbernburg@gmail.com',
|
||||
'city' => 'Bernburg',
|
||||
'postcode' => '06408',
|
||||
]);
|
||||
}
|
||||
|
||||
private function installUsers() {
|
||||
$users = [
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'ada@irmielin.org', 'local_group' => 'feu', 'firstname' => 'Ada', 'lastname' => 'Lindner', 'email' => 'ada@irmielin.org', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'adrianhuebner1@gmx.de', 'local_group' => 'lv', 'firstname' => 'Adrian', 'lastname' => 'Hübner', 'email' => 'adrianhuebner1@gmx.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'aneta2622@seznam.cz', 'local_group' => 'fen', 'firstname' => 'Josef', 'lastname' => 'Soukup', 'email' => 'aneta2622@seznam.cz', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'antje.heilmann@gmx.de', 'local_group' => 'sapi', 'firstname' => 'Antje', 'lastname' => 'Heilmann', 'email' => 'antje.heilmann@gmx.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'arne.hartmann@leipzig-pfadfinden.de', 'local_group' => 'leo', 'firstname' => 'Arne', 'lastname' => 'Hartmann', 'email' => 'arne.hartmann@leipzig-pfadfinden.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_ADMINISTRATOR', 'user_role_local_group' => 'ROLE_GROUP_LEADER', 'username' => 'thomas@pfadfinden-halle.de', 'local_group' => 'wm', 'firstname' => 'Thomas', 'lastname' => 'Günther', 'email' => 'thomas@pfadfinden-halle.de', 'activation_token_expires_at' => null, 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'corinna-veith@gmx.de', 'local_group' => 'lv', 'firstname' => 'Corinna', 'lastname' => 'Lajewski', 'email' => 'corinna-veith@gmx.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'eliseschenfeld@gmail.com', 'local_group' => 'leo', 'firstname' => 'Elise', 'lastname' => 'Schenfeld', 'email' => 'eliseschenfeld@gmail.com', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'emmi.pins@posteo.de', 'local_group' => 'feu', 'firstname' => 'Emily', 'lastname' => 'Pins', 'email' => 'emmi.pins@posteo.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'fangorn@goldenerreiter.org', 'local_group' => 'gr', 'firstname' => 'Karl', 'lastname' => 'Redemann', 'email' => 'fangorn@goldenerreiter.org', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'franziskabaer@posteo.de', 'local_group' => 'fen', 'firstname' => 'Franziska', 'lastname' => 'Baer', 'email' => 'franziskabaer@posteo.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'frederik.pitz@pfadfinden.de', 'local_group' => 'lv', 'firstname' => 'Frederik', 'lastname' => 'Pitz', 'email' => 'frederik.pitz@pfadfinden.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'fyn.thaerigen@gmail.com', 'local_group' => 'lv', 'firstname' => 'Fyn Valentin', 'lastname' => 'Thärigen', 'email' => 'fyn.thaerigen@gmail.com', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'jakob.rudolph@pfadfinden.de', 'local_group' => 'lv', 'firstname' => 'Jakob', 'lastname' => 'Rudolph', 'email' => 'jakob.rudolph@pfadfinden.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'jenny.abel@proton.me', 'local_group' => 'fen', 'firstname' => 'Jenny', 'lastname' => 'Abel', 'email' => 'jenny.abel@proton.me', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'Jerry@pfadfinden-halle.de', 'local_group' => 'wm', 'firstname' => 'Jérémie', 'lastname' => 'Duckwitz', 'email' => 'Jerry@pfadfinden-halle.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'jonathan.helm@pfadfinden.de', 'local_group' => 'lv', 'firstname' => 'Jonathan', 'lastname' => 'Helm', 'email' => 'jonathan.helm@pfadfinden.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'jul-ka@gmx.net', 'local_group' => 'sapi', 'firstname' => 'Juliane', 'lastname' => 'Kahl', 'email' => 'jul-ka@gmx.net', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'julia.meier@pfadfinden.de', 'local_group' => 'lv', 'firstname' => 'Julia', 'lastname' => 'Meier', 'email' => 'julia.meier@pfadfinden.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'julika.scheibler@leipzig-pfadfinden.de','local_group' => 'leo', 'firstname' => 'Julika', 'lastname' => 'Scheibler', 'email' => 'julika.scheibler@leipzig-pfadfinden.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'karlmarx.95@gmail.com', 'local_group' => 'sapi', 'firstname' => 'Karlmarx', 'lastname' => 'Thangamani', 'email' => 'karlmarx.95@gmail.com', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'kilian@cyberfuchs.de', 'local_group' => 'lv', 'firstname' => 'Kilian', 'lastname' => 'Fuchs', 'email' => 'kilian@cyberfuchs.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'korni@pfadfinden-lommatzsch.de', 'local_group' => 'rf', 'firstname' => 'Konstantin', 'lastname' => 'Stephan', 'email' => 'korni@pfadfinden-lommatzsch.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'laiu@gmx.net', 'local_group' => 'lv', 'firstname' => 'Roukaya', 'lastname' => 'Zakarias', 'email' => 'laiu@gmx.net', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'lars.kristen@gmx.net', 'local_group' => 'ban', 'firstname' => 'Lars', 'lastname' => 'Kristen', 'email' => 'lars.kristen@gmx.net', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'laura.kopsch@pfadfinden.de', 'local_group' => 'lv', 'firstname' => 'Laura', 'lastname' => 'Kopsch', 'email' => 'laura.kopsch@pfadfinden.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'leopardgecko333@gmx.de', 'local_group' => 'lv', 'firstname' => 'Konrad', 'lastname' => 'Birch-Hirschfeld', 'email' => 'leopardgecko333@gmx.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'lionhartmann@yahoo.de', 'local_group' => 'wm', 'firstname' => 'Lion', 'lastname' => 'Hartmann', 'email' => 'lionhartmann@yahoo.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'lisa.sy@gmx.net', 'local_group' => 'lv', 'firstname' => 'Lisa', 'lastname' => 'Synnatzschke', 'email' => 'lisa.sy@gmx.net', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'lukas.dalpke@gmx.de', 'local_group' => 'gr', 'firstname' => 'Lukas', 'lastname' => 'Dalpke', 'email' => 'lukas.dalpke@gmx.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'marc.friede@gmx.de', 'local_group' => 'lv', 'firstname' => 'Marc', 'lastname' => 'Friede', 'email' => 'marc.friede@gmx.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'marcel.pfadfinden@familiebrause.de', 'local_group' => 'fen', 'firstname' => 'Marcel', 'lastname' => 'Brause', 'email' => 'marcel.pfadfinden@familiebrause.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'maria.hahn1991@gmx.de', 'local_group' => 'wm', 'firstname' => 'Clara Sophie', 'lastname' => 'Hahn', 'email' => 'maria.hahn1991@gmx.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'marlene.koehler@pfadfinden.de', 'local_group' => 'lv', 'firstname' => 'Marlene', 'lastname' => 'Köhler', 'email' => 'marlene.koehler@pfadfinden.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'marslisdneu@aol.de', 'local_group' => 'feu', 'firstname' => 'Steffi', 'lastname' => 'Deckenbach', 'email' => 'marslisdneu@aol.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'mascha.meyenschein@pfadfinden.de', 'local_group' => 'lv', 'firstname' => 'Mascha', 'lastname' => 'Meyenschein', 'email' => 'mascha.meyenschein@pfadfinden.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'nataliehammer22@web.de', 'local_group' => 'lv', 'firstname' => 'Nathalie', 'lastname' => 'Hammermüller', 'email' => 'nataliehammer22@web.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'pdeakova@centrum.cz', 'local_group' => 'fen', 'firstname' => 'Mikulas', 'lastname' => 'Loub', 'email' => 'pdeakova@centrum.cz', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'pfadfinden@christian-schlag.org', 'local_group' => 'wm', 'firstname' => 'Christian', 'lastname' => 'Schlag', 'email' => 'pfadfinden@christian-schlag.org', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'rebekka.thielen@googlemail.com', 'local_group' => 'lv', 'firstname' => 'Almuna Elisa', 'lastname' => 'Hines', 'email' => 'rebekka.thielen@googlemail.com', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'rieke.langhans@gmail.com', 'local_group' => 'lv', 'firstname' => 'Rieke', 'lastname' => 'Langhans', 'email' => 'rieke.langhans@gmail.com', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'rolle@tocraft.dev', 'local_group' => 'anc', 'firstname' => 'Tobias', 'lastname' => 'Cuiper', 'email' => 'rolle@tocraft.dev', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'ronja.opel@icloud.com', 'local_group' => 'leo', 'firstname' => 'Ronja', 'lastname' => 'Opel', 'email' => 'ronja.opel@icloud.com', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'schubert-steffi83@web.de', 'local_group' => 'fen', 'firstname' => 'Fino Kilian', 'lastname' => 'Schubert', 'email' => 'schubert-steffi83@web.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'sebastianeckloff@gmx.de', 'local_group' => 'lv', 'firstname' => 'Sebastian', 'lastname' => 'Eckloff', 'email' => 'sebastianeckloff@gmx.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'sonne.grazek@yahoo.de', 'local_group' => 'feu', 'firstname' => 'Mandy', 'lastname' => 'Grazek', 'email' => 'sonne.grazek@yahoo.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'flieder.pfadfinden@familiebrause.de', 'local_group' => 'fen', 'firstname' => 'Sophie', 'lastname' => 'Brause', 'email' => 'flieder.pfadfinden@familiebrause.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'Theresa.grafe@posteo.de', 'local_group' => 'lv', 'firstname' => 'Theresa', 'lastname' => 'Grafe', 'email' => 'Theresa.grafe@posteo.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_ADMINISTRATOR', 'user_role_local_group' => 'ROLE_USER', 'username' => 'tux@goldenerreiter.org', 'local_group' => 'gr', 'firstname' => 'Christoph', 'lastname' => 'Wagner', 'email' => 'tux@goldenerreiter.org', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'undine.reschke@web.de', 'local_group' => 'lv', 'firstname' => 'Undine', 'lastname' => 'Reschke', 'email' => 'undine.reschke@web.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
['user_role_main' => 'ROLE_USER', 'user_role_local_group' => 'ROLE_USER', 'username' => 'yannik@suck-taucha.de', 'local_group' => 'lv', 'firstname' => 'Yannik', 'lastname' => 'Suck', 'email' => 'yannik@suck-taucha.de', 'activation_token_expires_at' => '2026-02-20 21:53:58', 'active' => true],
|
||||
];
|
||||
|
||||
foreach ($users as $userData) {
|
||||
User::create($userData);
|
||||
}
|
||||
}
|
||||
|
||||
private function installCronTasks() {
|
||||
CronTask::create(['name' => 'UploadInvoices', 'execution_type' => CronTaskType::CRON_TASK_TYPE_REALTIME]);
|
||||
CronTask::create(['name' => 'CloseCostUnit', 'execution_type' => CronTaskType::CRON_TASK_TYPE_DAILY, 'schedule_time' => '00:05']);
|
||||
CronTask::create(['name' => 'CloseEvent', 'execution_type' => CronTaskType::CRON_TASK_TYPE_DAILY, 'schedule_time' => '00:10']);
|
||||
CronTask::create(['name' => 'NotifyTeam', 'execution_type' => CronTaskType::CRON_TASK_TYPE_DAILY, 'schedule_time' => '20:00']);
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,8 @@ class activationCodeTemplate extends MessageTemplate {
|
||||
}
|
||||
|
||||
public function composeMessage(EmailAddress $emailAddress, string $activationCode): void {
|
||||
$this->message = "Dein Aktivierungscode lautet: {$activationCode}" . PHP_EOL .
|
||||
"Gib diesen zusammen mit der Mailadresse {$emailAddress->getValue()} ein.";
|
||||
$this->message = "Hallo,<br >dein angefordertet Aktivierungscode lautet: {$activationCode}<br />.
|
||||
Gib diesen zusammen mit der Mailadresse {$emailAddress->getValue()} ein.<br /><br />
|
||||
Hast du keinen Code angefordert?<br />In diesem Fall kannst du die E-Mail ignorieren.";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ class EventParticipant extends InstancedModel
|
||||
}
|
||||
|
||||
public function getFullName() : string {
|
||||
if ($this->nickname === null) {
|
||||
if ($this->nickname === null || trim($this->nickname) === '') {
|
||||
return sprintf('%1$s %2$s', $this->firstname, $this->lastname)
|
||||
|>trim(...);
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ class Invoice extends InstancedModel
|
||||
'contact_phone',
|
||||
'contact_bank_owner',
|
||||
'contact_bank_iban',
|
||||
'payment_purpose',
|
||||
'amount',
|
||||
'donation',
|
||||
'distance',
|
||||
|
||||
@@ -41,10 +41,13 @@ class CronTaskHandleProvider extends CommonController
|
||||
|
||||
// --- Daily Tasks ---
|
||||
if ($task->execution_type === CronTaskType::CRON_TASK_TYPE_DAILY) {
|
||||
$scheduledTime = $task->schedule_time;
|
||||
$scheduledTime = \DateTime::createFromFormat('Y-m-d H:i:s', date('Y-m-d ') . $task->schedule_time);
|
||||
$now = Carbon::now();
|
||||
|
||||
|
||||
$alreadyRunToday = $task->last_run?->isToday() ?? false;
|
||||
|
||||
if (!$alreadyRunToday && $now->format('H:i') === $scheduledTime) {
|
||||
if (!$alreadyRunToday && $now >= $scheduledTime) {
|
||||
$this->runTask($task);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,12 +25,13 @@ class GlobalDataProvider {
|
||||
'navbar' => $this->generateNavbar(),
|
||||
'tenant' => app('tenant'),
|
||||
'activeUsers' => $this->getActiveUsers(),
|
||||
'version' => config('app.version'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function getAllInvoiceTypes() : JsonResponse {
|
||||
$invoiceTypes = [];
|
||||
foreach (InvoiceType::all() as $invoiceType) {
|
||||
foreach (InvoiceType::orderBy('sort_order')->get() as $invoiceType) {
|
||||
if (
|
||||
$invoiceType->slug === InvoiceType::INVOICE_TYPE_OTHER
|
||||
) {
|
||||
@@ -52,10 +53,9 @@ class GlobalDataProvider {
|
||||
|
||||
public function getInvoiceTypes() : JsonResponse {
|
||||
$invoiceTypes = [];
|
||||
foreach (InvoiceType::all() as $invoiceType) {
|
||||
foreach (InvoiceType::orderBy('sort_order')->get() as $invoiceType) {
|
||||
if (
|
||||
$invoiceType->slug === InvoiceType::INVOICE_TYPE_TRAVELLING ||
|
||||
$invoiceType->slug === InvoiceType::INVOICE_TYPE_OTHER
|
||||
$invoiceType->slug === InvoiceType::INVOICE_TYPE_TRAVELLING
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
@@ -66,8 +66,6 @@ class GlobalDataProvider {
|
||||
];
|
||||
}
|
||||
|
||||
$invoiceTypes[] = ['slug' => InvoiceType::INVOICE_TYPE_OTHER, 'name' => 'Sonstige Kosten'];
|
||||
|
||||
return response()->json([
|
||||
'invoiceTypes' => $invoiceTypes
|
||||
]);
|
||||
@@ -110,6 +108,7 @@ class GlobalDataProvider {
|
||||
'common' => [],
|
||||
'costunits' => [],
|
||||
'events' => [],
|
||||
'eventControl' => [],
|
||||
];
|
||||
|
||||
$navigation['personal'][] = ['url' => '/', 'display' => 'Home'];
|
||||
@@ -129,7 +128,8 @@ class GlobalDataProvider {
|
||||
$navigation['events'][] = ['url' => '/event/details/' . $event->identifier, 'display' => $event->name];
|
||||
}
|
||||
|
||||
$navigation['events'][] = ['url' => '/event/new', 'display' => 'Neue Veranstaltung'];
|
||||
$navigation['eventControl'][] = ['url' => '/archived-events', 'display' => 'Archivierte Veranstaltungen'];
|
||||
$navigation['eventControl'][] = ['url' => '/create-event', 'display' => 'Neue Veranstaltung'];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class InvoiceCsvFileProvider {
|
||||
'"Kontoinhaber*in"',
|
||||
'"Betrag"',
|
||||
'"Spende"',
|
||||
'"Beleg ohne Auszahlung"',
|
||||
'"Buchungstext"'
|
||||
]);
|
||||
|
||||
foreach ($this->invoices as $invoice) {
|
||||
@@ -38,7 +38,7 @@ class InvoiceCsvFileProvider {
|
||||
'"' . $invoiceReadable['accountOwner'] . '"',
|
||||
'"' . $invoiceReadable['amountPlain'] . '"',
|
||||
'"' . $invoiceReadable['donation'] . '"',
|
||||
'"' . $invoiceReadable['alreadyPaid'] . '"'
|
||||
'"' . $invoiceReadable['paymentPurpose'] . '"'
|
||||
]);
|
||||
|
||||
$csvArray[] = $csvLine;
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Models\Invoice;
|
||||
use App\Resources\InvoiceResource;
|
||||
use DOMDocument;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class PainFileProvider {
|
||||
public string $senderIban;
|
||||
@@ -89,6 +91,8 @@ class PainFileProvider {
|
||||
$pmt_inf->appendChild($dbtr_agt);
|
||||
|
||||
foreach ($this->invoices as $index => $invoice) {
|
||||
$invoiceResource = new InvoiceResource($invoice)->toArray(new Request());
|
||||
|
||||
$cdt_trf_tx_inf = $doc->createElement('CdtTrfTxInf');
|
||||
|
||||
$pmt_id = $doc->createElement('PmtId');
|
||||
@@ -112,7 +116,7 @@ class PainFileProvider {
|
||||
$cdt_trf_tx_inf->appendChild($cdtr_acct);
|
||||
|
||||
$rmt_inf = $doc->createElement('RmtInf');
|
||||
$rmt_inf->appendChild($doc->createElement('Ustrd', 'Auslagenerstattung Rechnungsnummer ' . $invoice['invoice_number']));
|
||||
$rmt_inf->appendChild($doc->createElement('Ustrd', $invoiceResource['paymentPurpose']));
|
||||
$cdt_trf_tx_inf->appendChild($rmt_inf);
|
||||
|
||||
$pmt_inf->appendChild($cdt_trf_tx_inf);
|
||||
|
||||
@@ -16,12 +16,6 @@ class WebDavProvider {
|
||||
public function uploadFile(string $fileName) : bool {
|
||||
$baseDir = storage_path('app/private/');
|
||||
|
||||
return $this->webDavClient->upload_file($baseDir . $fileName, $this->workingDirectory . '/'.
|
||||
basename($fileName)
|
||||
|
||||
|
||||
|
||||
);
|
||||
return $this->webDavClient->upload_file($baseDir . $fileName, $this->workingDirectory . '/');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ class CostUnitRepository {
|
||||
$visibleCostUnits = [];
|
||||
/** @var CostUnit $costUnit */
|
||||
foreach (Costunit::where($criteria)->get() as $costUnit) {
|
||||
if ($costUnit->treasurers()->where('user_id', $user->id)->exists() || $canSeeAll || $disableAccessCheck) {
|
||||
if ($canSeeAll || $disableAccessCheck || $costUnit->treasurers()->where('user_id', $user->id)->exists() ) {
|
||||
if ($forDisplay) {
|
||||
$visibleCostUnits[] = new CostUnitResource($costUnit)->toArray(request());
|
||||
} else {
|
||||
|
||||
@@ -88,7 +88,7 @@ class EventParticipantRepository {
|
||||
|
||||
public function getParticipantsWithIntolerances(Event $event, Request $request) : array {
|
||||
$participants = [];
|
||||
foreach ($event->participants()->whereNotNull('intolerances')->whereNot('intolerances' , '=', '')->get() as $participant) {
|
||||
foreach ($event->participants()->orderBy('lastname')->orderBy('firstname')->whereNotNull('intolerances')->whereNot('intolerances' , '=', '')->get() as $participant) {
|
||||
$participants[] = $participant->toResource()->toArray($request);
|
||||
};
|
||||
|
||||
@@ -97,7 +97,7 @@ class EventParticipantRepository {
|
||||
|
||||
public function getKitchenOverview(Event $event) : array {
|
||||
$data = [];
|
||||
$participants = $event->participants()->get();
|
||||
$participants = $event->participants()->orderBy('lastname')->orderBy('firstname')->get();
|
||||
|
||||
|
||||
for ($cur_date = $event->start_date; $cur_date <= $event->end_date; $cur_date->modify('+1 day')) {
|
||||
|
||||
@@ -90,7 +90,7 @@ class EventRepository {
|
||||
|
||||
$visibleEvents = [];
|
||||
/** @var Event $event */
|
||||
foreach (Event::where($criteria)->get() as $event) {
|
||||
foreach (Event::where($criteria)->orderBy('start_date')->get() as $event) {
|
||||
|
||||
if ($canSeeAll || !$accessCheck || $event->eventManagers()->where('user_id', $user->id)->exists()) {
|
||||
$visibleEvents[] = $event;
|
||||
|
||||
@@ -93,6 +93,7 @@ class UserRepository {
|
||||
'first_aid_permission' => $request->firstAidPermission,
|
||||
'bank_account_owner' => $request->bankAccountOwner,
|
||||
'bank_account_iban' => $request->bankAccountIban,
|
||||
'birthday' => $request->birthday,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class CostUnitResource {
|
||||
|
||||
$amounts = [];
|
||||
$overAllAmount = new Amount(0, 'Euro');
|
||||
foreach (InvoiceType::all() as $invoiceType) {
|
||||
foreach (InvoiceType::orderBy('sort_order')->get() 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;
|
||||
|
||||
@@ -48,10 +48,11 @@ class EventParticipantResource extends JsonResource
|
||||
'unregisteredAt' => $this->resource->unregistered_at?->format('d.m.Y'),
|
||||
'fullname' => $this->resource->getFullName(),
|
||||
'age' => new Age($this->resource->birthday)->getAge(),
|
||||
'localgroup' => $this->resource->localGroup()->first()->name,
|
||||
'localgroup' => $this->resource->localGroup()?->first()?->name ?? 'Nicht im LV',
|
||||
'swimmingPermission' => $this->resource->swimmingPermission()->first()->short,
|
||||
'extendedFirstAid' => $this->resource->firstAidPermission()->first()->name,
|
||||
'tetanusVaccination' => $this->resource->tetanus_vaccination?->format('d.m.Y') ?? 'Unbekannt',
|
||||
'tetanusVaccinationEdit' => $this->resource->tetanus_vaccination?->format('Y-m-d') ?? null,
|
||||
'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 && $this->resource->amount_paid?->getAmount() < $this->resource->amount->getAmount(),
|
||||
@@ -64,10 +65,10 @@ class EventParticipantResource extends JsonResource
|
||||
'amountPaid' => ['value' => $this->resource->amount_paid, 'readable' => $this->resource->amount_paid?->toString() ?? '0,00 Euro', 'short' => $this->resource->amount_paid?->getFormattedAmount() ?? '0,00'],
|
||||
'amountExpected' => ['value' => $this->resource->amount, 'readable' => $this->resource->amount?->toString() ?? '0,00 Euro', 'short' => $this->resource->amount?->getFormattedAmount() ?? '0,00'],
|
||||
'alcoholicsAllowed' => new Age($this->resource->birthday)->getAge() >= $event->alcoholics_age,
|
||||
'localGroupPostcode' => $this->resource->localGroup()->first()->postcode,
|
||||
'localGroupCity' => $this->resource->localGroup()->first()->city,
|
||||
'localGroupPostcode' => $this->resource->localGroup()->first()?->postcode ?? '00000',
|
||||
'localGroupCity' => $this->resource->localGroup()->first()?->city ?? '00000',
|
||||
'state' => config('postCode.map.' . $this->resource->postcode),
|
||||
'localGroupState' => config('postCode.map.' . $this->resource->localGroup()->first()->postcode),
|
||||
'localGroupState' => null !== $this->resource->localGroup()->first()?->postcode ? config('postCode.map.' . $this->resource->postcode) : '--',
|
||||
'birthday' => $this->resource->birthday->format('d.m.Y'),
|
||||
'eatingHabit' => EatingHabit::where('slug', $this->resource->eating_habit)->first()->name,
|
||||
'cocColor' => match ($this->resource->efz_status) {
|
||||
|
||||
@@ -26,16 +26,16 @@ class EventResource extends JsonResource{
|
||||
'name' => $this->event->name,
|
||||
'identifier' => $this->event->identifier,
|
||||
'url' => 'https://' . app('tenant')->url . '/event/' . $this->event->identifier . '/signup',
|
||||
'urlShort' => 'https://' . app('tenant')->url . '/event/' . $this->event->identifier,
|
||||
'location' => $this->event->location,
|
||||
'postalCode' => $this->event->postal_code,
|
||||
'email' => $this->event->email,
|
||||
'accountOwner' => $this->event->account_owner,
|
||||
'accountIban' => $this->event->account_iban,
|
||||
'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,
|
||||
'archived' => $this->event->archived,
|
||||
'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')],
|
||||
'refundAfterEarlyBirdEnd' => 100 - $this->event->early_bird_end_amount_increase,
|
||||
|
||||
@@ -38,7 +38,8 @@ class InvoiceResource {
|
||||
$returnData['amount'] = Amount::fromString($this->invoice->amount, ' Euro')->toString();
|
||||
$returnData['id'] = $this->invoice->id;
|
||||
$returnData['donation'] = $this->invoice->donation;
|
||||
$returnData['alreadyPaid'] = !$this->invoice->donation && null === $this->invoice->contact_bank_iban;
|
||||
$returnData['externalPayment'] = null !== $this->invoice->payment_purpose;
|
||||
$returnData['paymentPurpose'] = $this->invoice->payment_purpose ?? 'Auslagenerstattung Rechnungsnummer ' . $returnData['invoiceNumber'];
|
||||
$returnData['accountOwner'] = $this->invoice->contact_bank_owner ?? '--';
|
||||
$returnData['accountIban'] = $this->invoice->contact_bank_iban ?? '--';
|
||||
$returnData['status'] = $this->invoice->status;
|
||||
@@ -67,7 +68,7 @@ class InvoiceResource {
|
||||
$returnData['approvedBy'] = $this->invoice->approvedBy()->first()->username ?? '--';
|
||||
}
|
||||
|
||||
$returnData['alreadyPaid'] = $returnData['alreadyPaid'] == '' ? 0 : 1;
|
||||
$returnData['externalPayment'] = $returnData['externalPayment'] == '' ? 0 : 1;
|
||||
|
||||
return $returnData;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace App\Tasks;
|
||||
|
||||
use App\Domains\CostUnit\Actions\ChangeCostUnitState\ChangeCostUnitStateCommand;
|
||||
use App\Domains\CostUnit\Actions\ChangeCostUnitState\ChangeCostUnitStateRequest;
|
||||
use App\Models\CostUnit;
|
||||
use App\Repositories\CostUnitRepository;
|
||||
|
||||
@@ -12,9 +14,18 @@ class CloseCostUnit implements CronTask {
|
||||
$costUnitRepository = new CostUnitRepository();
|
||||
/** @var CostUnit $costUnit */
|
||||
foreach ($costUnitRepository->getCurrentEvents() as $costUnit) {
|
||||
if (\DateTime::createFromFormat('Y-m-d', $costUnit->billing_deadline) < $now ) {
|
||||
$costUnit->allow_new = false;
|
||||
$costUnit->save();
|
||||
$billingEndTime = \DateTime::createFromFormat('Y-m-d H:i:s', $costUnit['billing_deadline']);
|
||||
$billingEndTime->setTime(0,0,0);
|
||||
$billingEndTime->add(new \DateInterval('P1D'));
|
||||
|
||||
$now = now();
|
||||
|
||||
if ($billingEndTime < $now) {
|
||||
new ChangeCostUnitStateCommand(
|
||||
new ChangeCostUnitStateRequest(
|
||||
CostUnit::where('id', $costUnit['id'])->first(),false, false
|
||||
)
|
||||
)->execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ class CloseEvent implements CronTask {
|
||||
$eventRepository = new EventRepository();
|
||||
/** @var Event $event */
|
||||
foreach ($eventRepository->getAvailable(false) as $event) {
|
||||
if ($event->registration_final_end < $now ) {
|
||||
if ($event->registration_final_end <= $now ) {
|
||||
$event->registration_allowed = false;
|
||||
$event->save();
|
||||
}
|
||||
|
||||
@@ -16,16 +16,17 @@ use Psr\Log\LoggerInterface;
|
||||
class NotifyTeam implements CronTask {
|
||||
public function handle(): void
|
||||
{
|
||||
if (date('w') !== 0) {
|
||||
// return;
|
||||
if ((int)date('w') !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$eventRepository = new EventRepository();
|
||||
/** @var Event $event */
|
||||
foreach ($eventRepository->getAvailable(false) as $event) {
|
||||
foreach (Tenant::all() as $tenant) {
|
||||
echo $tenant->slug . PHP_EOL;
|
||||
$participants = $event->participants()->where('local_group', $tenant->slug)->whereNull('unregistered_at')->get();
|
||||
}
|
||||
|
||||
|
||||
if ($participants->isEmpty()) {
|
||||
continue;
|
||||
@@ -38,4 +39,5 @@ class NotifyTeam implements CronTask {
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="modal-body" style="max-height: 600px; overflow: auto;">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -19,7 +19,7 @@ onMounted(async () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<label :for="props.belongsTo">{{contentData.content}}</label>
|
||||
<label :for="props.belongsTo" v-html="contentData.content"></label>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -123,4 +123,5 @@ return [
|
||||
'store' => env('APP_MAINTENANCE_STORE', 'database'),
|
||||
],
|
||||
|
||||
'version' => trim(file_get_contents(base_path('version'))),
|
||||
];
|
||||
|
||||
@@ -12,7 +12,7 @@ return new class extends Migration {
|
||||
Schema::create('page_texts', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('content');
|
||||
$table->longText('content');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ return new class extends Migration {
|
||||
$table->foreignId('cost_unit_id')->nullable()->constrained('cost_units', 'id')->restrictOnDelete()->cascadeOnUpdate();
|
||||
|
||||
$table->string('name');
|
||||
$table->string('identifier');
|
||||
$table->string('identifier')->unique();
|
||||
$table->string('location');
|
||||
$table->string('postal_code');
|
||||
$table->string('email');
|
||||
|
||||
@@ -22,12 +22,12 @@ return new class extends Migration {
|
||||
|
||||
$table->foreignId('event_id')->constrained('events', 'id')->cascadeOnDelete()->cascadeOnUpdate();
|
||||
$table->foreignId('user_id')->nullable()->constrained('users', 'id')->cascadeOnDelete()->cascadeOnUpdate();
|
||||
$table->string('identifier');
|
||||
$table->string('identifier')->unique();
|
||||
$table->string('firstname');
|
||||
$table->string('lastname');
|
||||
$table->string('nickname')->nullable();
|
||||
$table->string('participation_type');
|
||||
$table->string('local_group');
|
||||
$table->string('local_group')->nullable();
|
||||
$table->date('birthday');
|
||||
$table->string('address_1');
|
||||
$table->string('address_2')->nullable();
|
||||
@@ -63,7 +63,7 @@ return new class extends Migration {
|
||||
$table->dateTime('unregistered_at')->nullable();
|
||||
|
||||
$table->foreign('swimming_permission')->references('slug')->on('swimming_permissions')->restrictOnDelete()->cascadeOnUpdate();
|
||||
$table->foreign('eating_habits')->references('slug')->on('eating_habits')->restrictOnDelete()->cascadeOnUpdate();
|
||||
$table->foreign('eating_habit')->references('slug')->on('eating_habits')->restrictOnDelete()->cascadeOnUpdate();
|
||||
$table->foreign('first_aid_permission')->references('slug')->on('first_aid_permissions')->restrictOnDelete()->cascadeOnUpdate();
|
||||
$table->foreign('tenant')->references('slug')->on('tenants')->restrictOnDelete()->cascadeOnUpdate();
|
||||
$table->foreign('local_group')->references('slug')->on('tenants')->restrictOnDelete()->cascadeOnUpdate();
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<?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::table('invoice_types', function (Blueprint $table) {
|
||||
$table->integer('sort_order')->default(1)->after('name');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
<?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::table('invoices', function (Blueprint $table) {
|
||||
$table->string('payment_purpose')->nullable()->default(null)->after('contact_bank_iban');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
@@ -5,6 +5,7 @@ namespace Database\Seeders;
|
||||
use App\Installer\DevelopmentDataSeeder;
|
||||
use App\Installer\ProductionData;
|
||||
use App\Installer\ProductionDataSeeder;
|
||||
use App\Installer\Providers\BdpLvSachsenDataSeeder;
|
||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
@@ -24,5 +25,12 @@ class DatabaseSeeder extends Seeder
|
||||
$deveopmentDataSeeder = new DevelopmentDataSeeder();
|
||||
$deveopmentDataSeeder->execute();
|
||||
}
|
||||
|
||||
switch (env('PROVIDER')) {
|
||||
case 'bdp-lv-sachsen':
|
||||
$productionSeeeder = new BdpLvSachsenDataSeeder();
|
||||
$productionSeeeder->execute();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
services:
|
||||
mareike-app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/prod.Dockerfile
|
||||
|
||||
mareike-nginx:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/Dockerfile.nginx
|
||||
depends_on:
|
||||
- mareike-app
|
||||
ports:
|
||||
- 9000:80
|
||||
@@ -0,0 +1,43 @@
|
||||
FROM php:8.5-fpm-alpine AS base
|
||||
|
||||
ARG UID=1000
|
||||
ARG GID=1000
|
||||
ENV USER=mareike
|
||||
ENV GROUPNAME=$USER
|
||||
|
||||
RUN addgroup -g ${GID} -S ${GROUPNAME} \
|
||||
&& adduser -u ${UID} -D -S -G ${GROUPNAME} ${USER}
|
||||
|
||||
RUN apk add --no-cache \
|
||||
mc \
|
||||
unzip \
|
||||
rsync
|
||||
|
||||
COPY --chmod=0755 /docker/php/composer.phar /usr/bin/composer
|
||||
RUN apk add --no-cache --virtual .build-deps \
|
||||
autoconf \
|
||||
build-base \
|
||||
libzip-dev \
|
||||
libpng-dev \
|
||||
libxml2-dev \
|
||||
oniguruma-dev \
|
||||
nodejs \
|
||||
imagemagick-dev \
|
||||
npm && \
|
||||
pecl install imagick && docker-php-ext-enable imagick
|
||||
|
||||
RUN docker-php-ext-install mysqli pdo pdo_mysql mbstring zip exif pcntl gd
|
||||
|
||||
COPY . /var/www/html
|
||||
WORKDIR /var/www/html
|
||||
RUN composer install --no-dev --optimize-autoloader
|
||||
RUN npm install
|
||||
RUN npm run build
|
||||
|
||||
EXPOSE 9000
|
||||
|
||||
RUN mv /var/www/html /src
|
||||
COPY docker/run-mareike.sh /usr/local/bin/
|
||||
|
||||
USER mareike
|
||||
CMD ["run-mareike.sh"]
|
||||
@@ -0,0 +1,36 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
rsync -rlDog --chown $USER:$GROUPNAME --delete --exclude=/storage /src/ /var/www/html
|
||||
install -d -m 0755 -o $USER -g $GROUPNAME \
|
||||
storage \
|
||||
storage/framework \
|
||||
storage/framework/cache \
|
||||
storage/framework/sessions \
|
||||
storage/framework/views \
|
||||
storage/app \
|
||||
storage/app/private \
|
||||
storage/logs
|
||||
|
||||
php artisan migrate --force
|
||||
|
||||
rm .dockerignore
|
||||
rm .editorconfig
|
||||
rm .env.example
|
||||
rm .gitattributes
|
||||
rm .gitignore
|
||||
rm Makefile
|
||||
rm README.md
|
||||
rm docker-compose.dev
|
||||
rm docker-compose.prod
|
||||
rm justfile
|
||||
rm phpunit.xml
|
||||
rm -rf node_modules
|
||||
rm composer.lock
|
||||
rm package-lock.json
|
||||
rm package.json
|
||||
rm -rf docker
|
||||
rm -rf database
|
||||
rm -rf app/Installer
|
||||
|
||||
exec "php-fpm"
|
||||
@@ -4,7 +4,7 @@
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.invoice-main-flexbox div {
|
||||
.invoice-type-layer {
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
border: 1px solid #ccc;
|
||||
@@ -15,7 +15,7 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.invoice-main-flexbox div:hover {
|
||||
.invoice-type-layer:hover {
|
||||
background-color: #FAE39C;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,8 @@ const props = defineProps({
|
||||
title: { type: String, default: 'App' },
|
||||
flash: { type: Object, default: () => ({}) }
|
||||
});
|
||||
|
||||
console.log(globalProps)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -101,6 +103,16 @@ const props = defineProps({
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav-links" v-if="globalProps.navbar.eventControl.length > 0">
|
||||
<li v-for="navlink in globalProps.navbar.eventControl">
|
||||
<a
|
||||
:class="{ navlink_active: navlink.url.endsWith(currentPath) }"
|
||||
:href="navlink.url"
|
||||
>{{navlink.display}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
@@ -145,7 +157,7 @@ const props = defineProps({
|
||||
<footer class="footer">
|
||||
<table>
|
||||
<tr>
|
||||
<td>Version 4.0.0</td>
|
||||
<td>Version {{ globalProps.version }}</td>
|
||||
<td>
|
||||
mareike - Mdodernes Anmeldesystem und richtig einfache Kostenerfassung
|
||||
</td>
|
||||
|
||||
@@ -23,6 +23,13 @@ require_once __DIR__ . '/../app/Domains/Event/Routes/web.php';
|
||||
require_once __DIR__ . '/../app/Domains/Event/Routes/api.php';
|
||||
|
||||
|
||||
Route::get('/LKvDUqWl', function () {
|
||||
return redirect('/event/LKvDUqWl');
|
||||
});
|
||||
|
||||
Route::get('/LKvDUqWl/', function () {
|
||||
return redirect('/event/LKvDUqWl');
|
||||
});
|
||||
|
||||
Route::get('/execute-crons', [CronTaskHandleProvider::class, 'run']);
|
||||
Route::get('/print-girocode/{participantToken}', GiroCodeGetController::class);
|
||||
|
||||
Reference in New Issue
Block a user