From ab3d52621724bc0e999af85a63aaee4c5af1d9dc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20G=C3=BCnther?=
Date: Tue, 28 Jul 2026 16:09:38 +0200
Subject: [PATCH] Basic implementation of payment methods
---
.../RemovePaymentMethodUsageAction.php | 2 +-
.../Event/Actions/CreateEvent/CreateEventCommand.php | 2 +-
app/Domains/Event/Actions/SignUp/SignUpCommand.php | 3 +--
app/Domains/Event/Actions/SignUp/SignUpRequest.php | 3 ++-
app/Domains/Event/Controllers/SignupController.php | 11 +++++++++--
app/Domains/Event/Views/Partials/CommonSettings.vue | 4 ++--
.../Event/Views/Partials/SignUpForm/SignupForm.vue | 3 ++-
.../Partials/SignUpForm/composables/useSignupForm.js | 3 ++-
app/Domains/Event/Views/Signup.vue | 2 ++
app/Models/AvailablePaymentMethod.php | 4 +++-
app/Models/Event.php | 5 ++++-
app/RelationModels/EventPaymentMethods.php | 2 +-
...2026_07_28_140020_create_event_payment_methods.php | 5 ++++-
13 files changed, 34 insertions(+), 15 deletions(-)
diff --git a/app/Domains/Admin/Actions/RemovePaymentMethodUsage/RemovePaymentMethodUsageAction.php b/app/Domains/Admin/Actions/RemovePaymentMethodUsage/RemovePaymentMethodUsageAction.php
index 523dedf..27e5c63 100644
--- a/app/Domains/Admin/Actions/RemovePaymentMethodUsage/RemovePaymentMethodUsageAction.php
+++ b/app/Domains/Admin/Actions/RemovePaymentMethodUsage/RemovePaymentMethodUsageAction.php
@@ -11,7 +11,7 @@ class RemovePaymentMethodUsageAction
public function execute(AvailablePaymentMethod $availablePaymentMethod): void
{
foreach ($availablePaymentMethod->events()->get() as $event) {
- $event->paymentMethods()->detach($availablePaymentMethod->id);
+ $event->paymentMethods()->detach($availablePaymentMethod->slug);
$remainingActive = $event->paymentMethods()->where('active', true)->count();
if ($remainingActive === 0 && $event->registration_allowed) {
diff --git a/app/Domains/Event/Actions/CreateEvent/CreateEventCommand.php b/app/Domains/Event/Actions/CreateEvent/CreateEventCommand.php
index 11e1374..636f4de 100644
--- a/app/Domains/Event/Actions/CreateEvent/CreateEventCommand.php
+++ b/app/Domains/Event/Actions/CreateEvent/CreateEventCommand.php
@@ -63,7 +63,7 @@ class CreateEventCommand {
foreach (AvailablePaymentMethod::where('active', true)->get() as $availablePaymentMethod) {
EventPaymentMethods::create([
'event_id' => $event->id,
- 'available_payment_method_id' => $availablePaymentMethod->id,
+ 'slug' => $availablePaymentMethod->slug,
]);
}
diff --git a/app/Domains/Event/Actions/SignUp/SignUpCommand.php b/app/Domains/Event/Actions/SignUp/SignUpCommand.php
index 5c2b730..48667a4 100644
--- a/app/Domains/Event/Actions/SignUp/SignUpCommand.php
+++ b/app/Domains/Event/Actions/SignUp/SignUpCommand.php
@@ -21,7 +21,6 @@ class SignUpCommand {
};
$participantAge = new Age($this->request->birthday);
- $paymentMethod = $this->request->event->paymentMethods()->where('active', true)->first();
$response->participant = $this->request->event->participants()->create(
[
@@ -62,7 +61,7 @@ class SignUpCommand {
'notes' => $this->request->notes,
'amount' => $this->request->amount,
'payment_purpose' => $this->request->event->name . ' - Beitrag ' . $this->request->firstname . ' ' . $this->request->lastname,
- 'payment_method' => $paymentMethod?->slug, // available_payment_methods.slug === payment_methods.slug
+ 'payment_method' => $this->request->paymentMethod,
'efz_status' => $participantAge->isfullAged() ? EfzStatus::EFZ_STATUS_NOT_CHECKED : EfzStatus::EFZ_STATUS_NOT_REQUIRED,
]
);
diff --git a/app/Domains/Event/Actions/SignUp/SignUpRequest.php b/app/Domains/Event/Actions/SignUp/SignUpRequest.php
index 778aa15..fc6d648 100644
--- a/app/Domains/Event/Actions/SignUp/SignUpRequest.php
+++ b/app/Domains/Event/Actions/SignUp/SignUpRequest.php
@@ -44,7 +44,8 @@ class SignUpRequest {
public int $arrival_eating,
public int $departure_eating,
public ?string $notes,
- public Amount $amount
+ public Amount $amount,
+ public ?string $paymentMethod,
) {
}
}
diff --git a/app/Domains/Event/Controllers/SignupController.php b/app/Domains/Event/Controllers/SignupController.php
index 01bcd6d..01f82d1 100644
--- a/app/Domains/Event/Controllers/SignupController.php
+++ b/app/Domains/Event/Controllers/SignupController.php
@@ -24,7 +24,12 @@ class SignupController extends CommonController {
$availableEvents[] = $event->toResource()->toArray($request);
};
- $event = $this->events->getByIdentifier($eventId, false)?->toResource()->toArray($request);
+ $eventModel = $this->events->getByIdentifier($eventId, false);
+ $event = $eventModel?->toResource()->toArray($request);
+ // Aktuell ist genau eine aktive Zahlungsmethode je Event vorgesehen; wird bereits beim Start
+ // der Anmeldung ermittelt und ans Frontend durchgereicht, statt erst bei der Erstellung des
+ // Teilnehmenden (siehe SignUpCommand).
+ $paymentMethod = $eventModel?->paymentMethods()->where('active', true)->first();
$participantData = [
'firstname' => '',
@@ -62,6 +67,7 @@ class SignupController extends CommonController {
'availableEvents' => $availableEvents,
'localGroups' => $event['contributingLocalGroups'],
'participantData' => $participantData,
+ 'paymentMethod' => $paymentMethod?->slug,
]);
return $inertiaProvider->render();
}
@@ -136,7 +142,8 @@ class SignupController extends CommonController {
$registrationData['anreise_essen'],
$registrationData['abreise_essen'],
$registrationData['anmerkungen'],
- $amount
+ $amount,
+ $registrationData['paymentMethod'] ?? null,
);
$signupCommand = new SignUpCommand($signupRequest);
diff --git a/app/Domains/Event/Views/Partials/CommonSettings.vue b/app/Domains/Event/Views/Partials/CommonSettings.vue
index 22d5737..944b66d 100644
--- a/app/Domains/Event/Views/Partials/CommonSettings.vue
+++ b/app/Domains/Event/Views/Partials/CommonSettings.vue
@@ -48,7 +48,7 @@
contributingLocalGroups.value = props.event.contributingLocalGroups?.map(t => t.id) ?? []
eatingHabits.value = props.event.eatingHabits?.map(t => t.id) ?? []
- paymentMethods.value = props.event.paymentMethods?.map(t => t.id) ?? []
+ paymentMethods.value = props.event.paymentMethods?.map(t => t.slug) ?? []
});
async function save() {
@@ -218,7 +218,7 @@
|
-
+
|
diff --git a/app/Domains/Event/Views/Partials/SignUpForm/SignupForm.vue b/app/Domains/Event/Views/Partials/SignUpForm/SignupForm.vue
index 4f751a5..af4b0f3 100644
--- a/app/Domains/Event/Views/Partials/SignUpForm/SignupForm.vue
+++ b/app/Domains/Event/Views/Partials/SignUpForm/SignupForm.vue
@@ -16,6 +16,7 @@ const props = defineProps({
event: Object,
participantData: Object,
localGroups: Array,
+ paymentMethod: String,
})
const emit = defineEmits(['registrationDone'])
@@ -23,7 +24,7 @@ const emit = defineEmits(['registrationDone'])
const {
currentStep, goToStep, formData, selectedAddons,
submit, submitting, submitResult, summaryLoading, summaryAmount
-} = useSignupForm(props.event, props.participantData)
+} = useSignupForm(props.event, props.participantData, props.paymentMethod)
const steps = [
{ step: 1, label: 'Alter' },
diff --git a/app/Domains/Event/Views/Partials/SignUpForm/composables/useSignupForm.js b/app/Domains/Event/Views/Partials/SignUpForm/composables/useSignupForm.js
index a6ae1d5..3f7cd32 100644
--- a/app/Domains/Event/Views/Partials/SignUpForm/composables/useSignupForm.js
+++ b/app/Domains/Event/Views/Partials/SignUpForm/composables/useSignupForm.js
@@ -1,7 +1,7 @@
import { ref, reactive, computed } from 'vue'
import axios from 'axios'
-export function useSignupForm(event, participantData) {
+export function useSignupForm(event, participantData, paymentMethod) {
const currentStep = ref(1)
const submitting = ref(false)
const summaryLoading = ref(false)
@@ -11,6 +11,7 @@ export function useSignupForm(event, participantData) {
const formData = reactive({
eatingHabit: 'EATING_HABIT_VEGAN',
+ paymentMethod: paymentMethod ?? null,
userId: participantData.id,
eventId: event.id,
vorname: participantData.firstname ?? '',
diff --git a/app/Domains/Event/Views/Signup.vue b/app/Domains/Event/Views/Signup.vue
index a941154..d1b035b 100644
--- a/app/Domains/Event/Views/Signup.vue
+++ b/app/Domains/Event/Views/Signup.vue
@@ -12,6 +12,7 @@ const props = defineProps({
availableEvents: Array,
participantData: Object,
localGroups: Array,
+ paymentMethod: String,
})
const showSignup = ref(true)
@@ -103,6 +104,7 @@ function close() {
:event="props.event"
:participantData="props.participantData ?? {}"
:localGroups="props.localGroups ?? []"
+ :paymentMethod="props.paymentMethod ?? null"
/>
Die Anmeldung für diese Veranstaltung ist geschlossen.
diff --git a/app/Models/AvailablePaymentMethod.php b/app/Models/AvailablePaymentMethod.php
index d2d81f8..45f0e34 100644
--- a/app/Models/AvailablePaymentMethod.php
+++ b/app/Models/AvailablePaymentMethod.php
@@ -37,6 +37,8 @@ class AvailablePaymentMethod extends InstancedModel
public function events(): BelongsToMany
{
- return $this->belongsToMany(Event::class, 'event_payment_methods')->withTimestamps();
+ // Pivot verknüpft über den Slug -- Event::paymentMethods() greift daher automatisch nur
+ // auf Events des aktuell gebundenen Tenants zu (SiteScope auf Event + AvailablePaymentMethod).
+ return $this->belongsToMany(Event::class, 'event_payment_methods', 'slug', 'event_id', 'slug', 'id')->withTimestamps();
}
}
diff --git a/app/Models/Event.php b/app/Models/Event.php
index 5ce8b69..efa1dab 100644
--- a/app/Models/Event.php
+++ b/app/Models/Event.php
@@ -154,7 +154,10 @@ class Event extends InstancedModel
}
public function paymentMethods() : BelongsToMany {
- return $this->belongsToMany(AvailablePaymentMethod::class, 'event_payment_methods', 'event_id', 'available_payment_method_id')->withTimestamps();
+ // Pivot verknüpft über den Slug (payment_methods.slug), nicht über die numerische id
+ // von available_payment_methods -- die tenant-spezifische Instanz wird dadurch implizit
+ // über den globalen SiteScope von AvailablePaymentMethod (gefiltert auf app('tenant')) aufgelöst.
+ return $this->belongsToMany(AvailablePaymentMethod::class, 'event_payment_methods', 'event_id', 'slug', 'id', 'slug')->withTimestamps();
}
public function resetContributingLocalGroups() {
diff --git a/app/RelationModels/EventPaymentMethods.php b/app/RelationModels/EventPaymentMethods.php
index 0da9ef3..4e2099a 100644
--- a/app/RelationModels/EventPaymentMethods.php
+++ b/app/RelationModels/EventPaymentMethods.php
@@ -7,5 +7,5 @@ use App\Scopes\CommonModel;
class EventPaymentMethods extends CommonModel
{
protected $table = 'event_payment_methods';
- protected $fillable = ['event_id', 'available_payment_method_id'];
+ protected $fillable = ['event_id', 'slug'];
}
diff --git a/database/migrations/2026_07_28_140020_create_event_payment_methods.php b/database/migrations/2026_07_28_140020_create_event_payment_methods.php
index b327d1d..9fc81d3 100644
--- a/database/migrations/2026_07_28_140020_create_event_payment_methods.php
+++ b/database/migrations/2026_07_28_140020_create_event_payment_methods.php
@@ -12,8 +12,11 @@ return new class extends Migration {
Schema::create('event_payment_methods', function (Blueprint $table) {
$table->id();
$table->foreignId('event_id')->constrained('events', 'id')->restrictOnDelete()->cascadeOnUpdate();
- $table->foreignId('available_payment_method_id')->constrained('available_payment_methods', 'id')->restrictOnDelete()->cascadeOnUpdate();
+ $table->string('slug');
$table->timestamps();
+
+ $table->foreign('slug')->references('slug')->on('payment_methods')->restrictOnDelete()->cascadeOnUpdate();
+ $table->unique(['event_id', 'slug']);
});
}