More improvements
This commit is contained in:
@@ -26,47 +26,10 @@ const props = defineProps({
|
|||||||
Du hast noch kein erweitertes Führungszeugnis hinterlegt. Bitte reiche es umgehend ein.
|
Du hast noch kein erweitertes Führungszeugnis hinterlegt. Bitte reiche es umgehend ein.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template v-if="props.participant.paymentSummary?.hasPaymentInformation">
|
<!-- Zahlungs-Block kommt vollständig aus dem Zahlungsmodul (registrationSummary -> html). -->
|
||||||
<!-- Frei konfigurierter Text (z.B. Barzahlung) -->
|
<div v-if="props.participant.paymentSummary?.hasPaymentInformation"
|
||||||
<div v-if="props.participant.paymentSummary.html" v-html="props.participant.paymentSummary.html"
|
v-html="props.participant.paymentSummary.html"
|
||||||
style="margin-bottom: 16px;"></div>
|
style="margin-bottom: 16px;"></div>
|
||||||
|
|
||||||
<!-- Strukturierte Zeilen (z.B. Überweisung) -->
|
|
||||||
<template v-else>
|
|
||||||
<table class="form-table" style="margin-bottom: 16px;">
|
|
||||||
<tr v-for="(line, index) in props.participant.paymentSummary.lines" :key="line.label">
|
|
||||||
<td>{{ line.label }}:</td>
|
|
||||||
<td><strong v-if="line.label === 'Betrag'">{{ line.value }}</strong>
|
|
||||||
<template v-else>{{ line.value }}</template>
|
|
||||||
</td>
|
|
||||||
<td v-if="index === 0 && props.participant.paymentSummary.showGiroCode && props.participant.identifier !== ''"
|
|
||||||
:rowspan="props.participant.paymentSummary.lines.length"
|
|
||||||
style="vertical-align: top; padding-left: 20px;">
|
|
||||||
<img :src="'/print-girocode/' + props.participant.identifier" alt="GiroCode"
|
|
||||||
style="max-width: 180px;"/>
|
|
||||||
<span
|
|
||||||
style="width: 180px; text-align: center; display: block; font-size: 0.8rem; color: #6b7280; margin-top: 4px;">Giro-Code</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td> </td>
|
|
||||||
<td>
|
|
||||||
<a class="link"
|
|
||||||
:href="`/api/v1/event/participant/${props.participant.identifier}/ical-payment`">Erinnerung
|
|
||||||
in Kalender setzen</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Bitte beachte, dass deine Anmeldung erst nach Zahlungseiongang vollständig ist.<br/>
|
|
||||||
Wenn dieser nicht bis zum {{ props.event.registrationFinalEnd.formatted }} erfolgt, kann deine
|
|
||||||
Anmeldung storniert werden.<br/><br/>
|
|
||||||
Solltest du den Beitrag bis zu diesem Datum nicht oder nur teilweise überweisen können, kontaktiere
|
|
||||||
bitte die Aktionsleitung, damit wir eine gemeinsame Lösiung finden können.
|
|
||||||
</p>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
<p v-else>
|
<p v-else>
|
||||||
Du musst keinen Beitrag überweisen. Deine Anmeldung ist bestätigt.
|
Du musst keinen Beitrag überweisen. Deine Anmeldung ist bestätigt.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -59,13 +59,23 @@ Beispiel GiroCode (nur Überweisung):
|
|||||||
## Anmelde-Zusammenfassung / Mail-Anzeige
|
## Anmelde-Zusammenfassung / Mail-Anzeige
|
||||||
|
|
||||||
- `registrationSummary(RegistrationSummaryRequest): RegistrationSummaryResponse` liefert den zahlungsspezifischen
|
- `registrationSummary(RegistrationSummaryRequest): RegistrationSummaryResponse` liefert den zahlungsspezifischen
|
||||||
Anzeige-Block render-agnostisch: entweder `lines` (label/value, z.B. Überweisung) oder `html` (Freitext, z.B.
|
Anzeige-Block **fertig als HTML** (`hasPaymentInformation` + `html`). Jedes Modul rendert seinen Block über
|
||||||
Barzahlung), plus `hasPaymentInformation` und `showGiroCode`.
|
eigene Blade-Templates unter `resources/views/payment-modules/{modul}/{web,mail}.blade.php` (Überweisung:
|
||||||
|
`account-transfer/`, Barzahlung: `undefined/` — Rahmen um den konfigurierten richtext). Die Render-Stellen geben
|
||||||
|
nur noch `v-html` / `{!! !!}` aus — **keine** zahlart-spezifische Logik im Frontend/Blade.
|
||||||
|
- **Render-Kontext:** `RegistrationSummaryRequest` trägt einen `RegistrationRenderContext` (`Web`/`Mail`). Das Modul
|
||||||
|
wählt darüber (a) ein **medien-gerechtes Template** — `resources/views/payment-modules/{modul}/{web,mail}.blade.php`
|
||||||
|
(Web: SPA-Klassen `form-table`/`link`; Mail: E-Mail-taugliche Inline-Styles) und (b) die GiroCode-Bildquelle —
|
||||||
|
Web: `/print-girocode/{token}` (sessionlos, lazy), Mail: `cid:girocode.png` (inline via `$message->embedData(...)`,
|
||||||
|
bereitgestellt im dünnen Wrapper `emails/subparts/payment.blade.php`).
|
||||||
|
Hinweis: Das Web-Template darf globale (un-scoped) SPA-Klassen nutzen, da Vue-`scoped`-Styles nicht auf `v-html`
|
||||||
|
greifen.
|
||||||
- Zugang über das Teilnehmer-Model: `EventParticipant::paymentModule()`, `paymentConfiguration()` (eager-load-fähig über
|
- Zugang über das Teilnehmer-Model: `EventParticipant::paymentModule()`, `paymentConfiguration()` (eager-load-fähig über
|
||||||
`->with('event.paymentMethods')`, kein statischer Cache), `paymentSummary()`.
|
`->with('event.paymentMethods')`, kein statischer Cache), `paymentSummary(RegistrationRenderContext)`.
|
||||||
- Konsumiert von `EventParticipantResource` (`paymentSummary`), `SubmitSuccess.vue`, `emails/subparts/payment.blade.php`
|
- Konsumiert von `EventParticipantResource` (`paymentSummary` = `{hasPaymentInformation, html}`, Web-Kontext),
|
||||||
(+ `signup_complete`, `missing_amount`). GiroCode in Mails: **inline per CID** (`$message->embedData(...)`), im Web
|
`SubmitSuccess.vue`, den Mails (`EventSignUpSuccessfullMail`/`ParticipantPaymentMissingPaymentMail` rufen
|
||||||
über `/print-girocode/{token}` (sessionlos, lazy).
|
`paymentSummary(Mail)`), sowie `signup_complete`/`missing_amount` (nur umrahmende Prosa, gegated auf
|
||||||
|
`hasPaymentInformation`).
|
||||||
|
|
||||||
## Neues Zahlungsmodul hinzufügen
|
## Neues Zahlungsmodul hinzufügen
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\EventPaymentModules\DTO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render-Kontext der Anmelde-Zusammenfassung. Steuert die kontextabhängige Einbettung des GiroCodes:
|
||||||
|
* im Web über den Endpoint, in der Mail über eine inline-CID.
|
||||||
|
*/
|
||||||
|
enum RegistrationRenderContext
|
||||||
|
{
|
||||||
|
case Web;
|
||||||
|
case Mail;
|
||||||
|
}
|
||||||
@@ -8,7 +8,8 @@ use App\Models\EventParticipant;
|
|||||||
* Eingabe für {@see \App\EventPaymentModules\EventPaymentModule::registrationSummary()}.
|
* Eingabe für {@see \App\EventPaymentModules\EventPaymentModule::registrationSummary()}.
|
||||||
*
|
*
|
||||||
* Anker ist der (bereits erstellte) Teilnehmer -- daraus leiten die Module Event, Betrag/Restbetrag
|
* Anker ist der (bereits erstellte) Teilnehmer -- daraus leiten die Module Event, Betrag/Restbetrag
|
||||||
* und Verwendungszweck ab. $configuration ist die aufgelöste pro-Event-Config des Zahlungsmoduls.
|
* und Verwendungszweck ab. $configuration ist die aufgelöste pro-Event-Config des Zahlungsmoduls,
|
||||||
|
* $context steuert die kontextabhängige Ausgabe (z.B. GiroCode-Einbettung Web vs. Mail).
|
||||||
*/
|
*/
|
||||||
final class RegistrationSummaryRequest
|
final class RegistrationSummaryRequest
|
||||||
{
|
{
|
||||||
@@ -18,6 +19,7 @@ final class RegistrationSummaryRequest
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
public readonly EventParticipant $participant,
|
public readonly EventParticipant $participant,
|
||||||
public readonly array $configuration = [],
|
public readonly array $configuration = [],
|
||||||
|
public readonly RegistrationRenderContext $context = RegistrationRenderContext::Web,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,22 +5,14 @@ namespace App\EventPaymentModules\DTO;
|
|||||||
/**
|
/**
|
||||||
* Ausgabe von {@see \App\EventPaymentModules\EventPaymentModule::registrationSummary()}.
|
* Ausgabe von {@see \App\EventPaymentModules\EventPaymentModule::registrationSummary()}.
|
||||||
*
|
*
|
||||||
* Render-agnostisch: speist den Zahlungs-Abschnitt sowohl im Anmeldeabschluss (Vue) als auch in den Mails.
|
* Das Modul erzeugt seinen Zahlungs-Block vollständig als HTML; die Render-Stellen (Anmeldeabschluss,
|
||||||
* Zwei Darstellungsformen:
|
* Mails) geben ihn nur noch per `v-html` / `{!! !!}` aus.
|
||||||
* - strukturierte $lines (label/value) -- z.B. Überweisung (Kontoinhaber, IBAN, Verwendungszweck, Betrag),
|
|
||||||
* - $html -- frei konfigurierter Text (z.B. Barzahlung).
|
|
||||||
*/
|
*/
|
||||||
final class RegistrationSummaryResponse
|
final class RegistrationSummaryResponse
|
||||||
{
|
{
|
||||||
/** Gibt es überhaupt einen Zahlungs-Info-Block darzustellen? */
|
/** Gibt es überhaupt einen Zahlungs-Block darzustellen? */
|
||||||
public bool $hasPaymentInformation = false;
|
public bool $hasPaymentInformation = false;
|
||||||
|
|
||||||
/** @var array<int, array{label: string, value: string}> */
|
/** Fertig gerenderter HTML-Block der Zahlungsinformationen. */
|
||||||
public array $lines = [];
|
public string $html = '';
|
||||||
|
|
||||||
/** Frei konfigurierter HTML-Text (alternativ zu $lines). */
|
|
||||||
public ?string $html = null;
|
|
||||||
|
|
||||||
/** Soll der GiroCode (QR) angezeigt werden? */
|
|
||||||
public bool $showGiroCode = false;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace App\EventPaymentModules\Modules;
|
|||||||
|
|
||||||
use App\EventPaymentModules\AbstractEventPaymentModule;
|
use App\EventPaymentModules\AbstractEventPaymentModule;
|
||||||
use App\EventPaymentModules\DTO\CreateInvoiceRequest;
|
use App\EventPaymentModules\DTO\CreateInvoiceRequest;
|
||||||
|
use App\EventPaymentModules\DTO\RegistrationRenderContext;
|
||||||
use App\EventPaymentModules\DTO\RegistrationSummaryRequest;
|
use App\EventPaymentModules\DTO\RegistrationSummaryRequest;
|
||||||
use App\EventPaymentModules\DTO\RegistrationSummaryResponse;
|
use App\EventPaymentModules\DTO\RegistrationSummaryResponse;
|
||||||
use App\EventPaymentModules\ProvidesGiroCode;
|
use App\EventPaymentModules\ProvidesGiroCode;
|
||||||
@@ -45,15 +46,32 @@ class AccountTransferPaymentModule extends AbstractEventPaymentModule implements
|
|||||||
$amountLeft->subtractAmount($participant->amount_paid);
|
$amountLeft->subtractAmount($participant->amount_paid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$hasPaymentInformation = $amountLeft->getAmount() > 0;
|
||||||
|
|
||||||
|
// GiroCode nur bei offenem Betrag; Bildquelle je Render-Kontext (Web-Endpoint vs. Mail-CID).
|
||||||
|
$giroCodeSrc = null;
|
||||||
|
if ($hasPaymentInformation) {
|
||||||
|
$giroCodeSrc = $request->context === RegistrationRenderContext::Mail
|
||||||
|
? 'cid:girocode.png'
|
||||||
|
: '/print-girocode/' . $participant->identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Medien-gerechtes Template je Render-Kontext (Web: SPA-Klassen, Mail: E-Mail-tauglich).
|
||||||
|
$view = $request->context === RegistrationRenderContext::Mail
|
||||||
|
? 'payment-modules.account-transfer.mail'
|
||||||
|
: 'payment-modules.account-transfer.web';
|
||||||
|
|
||||||
$response = new RegistrationSummaryResponse();
|
$response = new RegistrationSummaryResponse();
|
||||||
$response->hasPaymentInformation = $amountLeft->getAmount() > 0;
|
$response->hasPaymentInformation = $hasPaymentInformation;
|
||||||
$response->showGiroCode = $response->hasPaymentInformation;
|
$response->html = view($view, [
|
||||||
$response->lines = [
|
'accountOwner' => (string)($config['account_owner'] ?? ''),
|
||||||
['label' => 'Kontoinhaber', 'value' => (string)($config['account_owner'] ?? '')],
|
'iban' => (string)($config['iban'] ?? ''),
|
||||||
['label' => 'IBAN', 'value' => (string)($config['iban'] ?? '')],
|
'paymentPurpose' => (string)$participant->payment_purpose,
|
||||||
['label' => 'Verwendungszweck', 'value' => (string)$participant->payment_purpose],
|
'amount' => $amountLeft->toString(),
|
||||||
['label' => 'Betrag', 'value' => $amountLeft->toString()],
|
'giroCodeSrc' => $giroCodeSrc,
|
||||||
];
|
'reminderUrl' => url('/api/v1/event/participant/' . $participant->identifier . '/ical-payment'),
|
||||||
|
'paymentDeadline' => $participant->event?->registration_final_end?->format('d.m.Y'),
|
||||||
|
])->render();
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace App\EventPaymentModules\Modules;
|
|||||||
|
|
||||||
use App\EventPaymentModules\AbstractEventPaymentModule;
|
use App\EventPaymentModules\AbstractEventPaymentModule;
|
||||||
use App\EventPaymentModules\DTO\CreateInvoiceRequest;
|
use App\EventPaymentModules\DTO\CreateInvoiceRequest;
|
||||||
|
use App\EventPaymentModules\DTO\RegistrationRenderContext;
|
||||||
use App\EventPaymentModules\DTO\RegistrationSummaryRequest;
|
use App\EventPaymentModules\DTO\RegistrationSummaryRequest;
|
||||||
use App\EventPaymentModules\DTO\RegistrationSummaryResponse;
|
use App\EventPaymentModules\DTO\RegistrationSummaryResponse;
|
||||||
use App\Models\PaymentMethod;
|
use App\Models\PaymentMethod;
|
||||||
@@ -33,12 +34,19 @@ class UndefinedPaymentModule extends AbstractEventPaymentModule
|
|||||||
|
|
||||||
public function registrationSummary(RegistrationSummaryRequest $request): RegistrationSummaryResponse
|
public function registrationSummary(RegistrationSummaryRequest $request): RegistrationSummaryResponse
|
||||||
{
|
{
|
||||||
$html = (string)($request->configuration['payment_information'] ?? '');
|
$paymentInformation = (string)($request->configuration['payment_information'] ?? '');
|
||||||
|
|
||||||
$response = new RegistrationSummaryResponse();
|
$response = new RegistrationSummaryResponse();
|
||||||
$response->hasPaymentInformation = trim($html) !== '';
|
$response->hasPaymentInformation = trim($paymentInformation) !== '';
|
||||||
$response->html = $html;
|
|
||||||
$response->showGiroCode = false;
|
if ($response->hasPaymentInformation) {
|
||||||
|
// Medien-gerechtes Template je Render-Kontext (Web: SPA, Mail: E-Mail-tauglich).
|
||||||
|
$view = $request->context === RegistrationRenderContext::Mail
|
||||||
|
? 'payment-modules.undefined.mail'
|
||||||
|
: 'payment-modules.undefined.web';
|
||||||
|
|
||||||
|
$response->html = view($view, ['paymentInformation' => $paymentInformation])->render();
|
||||||
|
}
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use App\Domains\Event\Actions\GenerateIcal\GenerateIcalResponse;
|
|||||||
use App\Domains\Event\Actions\GenerateIcalForDeadline\GenerateIcalForDeadlineCommand;
|
use App\Domains\Event\Actions\GenerateIcalForDeadline\GenerateIcalForDeadlineCommand;
|
||||||
use App\Domains\Event\Actions\GenerateIcalForDeadline\GenerateIcalForDeadlineRequest;
|
use App\Domains\Event\Actions\GenerateIcalForDeadline\GenerateIcalForDeadlineRequest;
|
||||||
use App\Domains\Event\Actions\GenerateIcalForDeadline\GenerateIcalForDeadlineResponse;
|
use App\Domains\Event\Actions\GenerateIcalForDeadline\GenerateIcalForDeadlineResponse;
|
||||||
|
use App\EventPaymentModules\DTO\RegistrationRenderContext;
|
||||||
use App\EventPaymentModules\ProvidesGiroCode;
|
use App\EventPaymentModules\ProvidesGiroCode;
|
||||||
use App\Models\EventParticipant;
|
use App\Models\EventParticipant;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
@@ -68,6 +69,9 @@ class EventSignUpSuccessfullMail extends Mailable
|
|||||||
? $module->giroCode($this->participant, $this->participant->paymentConfiguration())
|
? $module->giroCode($this->participant, $this->participant->paymentConfiguration())
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
// Zahlungs-Block im Mail-Kontext erzeugen (GiroCode als cid: statt Web-Endpoint).
|
||||||
|
$paymentSummary = $this->participant->paymentSummary(RegistrationRenderContext::Mail);
|
||||||
|
|
||||||
$participationIcal = $this->getParticipationIcal();
|
$participationIcal = $this->getParticipationIcal();
|
||||||
$deadlineIcal = $this->getDeadlineIcal();
|
$deadlineIcal = $this->getDeadlineIcal();
|
||||||
|
|
||||||
@@ -83,7 +87,7 @@ class EventSignUpSuccessfullMail extends Mailable
|
|||||||
'departure' => $participant['departure'],
|
'departure' => $participant['departure'],
|
||||||
'amount' => $participant['amount_left_string'],
|
'amount' => $participant['amount_left_string'],
|
||||||
'paymentFinalDate' => $event['registrationFinalEnd']['formatted'],
|
'paymentFinalDate' => $event['registrationFinalEnd']['formatted'],
|
||||||
'paymentSummary' => $participant['paymentSummary'],
|
'paymentSummary' => ['hasPaymentInformation' => $paymentSummary->hasPaymentInformation, 'html' => $paymentSummary->html],
|
||||||
'girocodeBinary' => $girocodeBinary,
|
'girocodeBinary' => $girocodeBinary,
|
||||||
'efzStatus' => $participant['efz_status'],
|
'efzStatus' => $participant['efz_status'],
|
||||||
'participationIcalFilename' => $participationIcal->filename,
|
'participationIcalFilename' => $participationIcal->filename,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Mail\ParticipantPaymentMails;
|
namespace App\Mail\ParticipantPaymentMails;
|
||||||
|
|
||||||
|
use App\EventPaymentModules\DTO\RegistrationRenderContext;
|
||||||
use App\EventPaymentModules\ProvidesGiroCode;
|
use App\EventPaymentModules\ProvidesGiroCode;
|
||||||
use App\Models\EventParticipant;
|
use App\Models\EventParticipant;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@@ -51,6 +52,9 @@ class ParticipantPaymentMissingPaymentMail extends Mailable
|
|||||||
? $module->giroCode($this->participant, $this->participant->paymentConfiguration())
|
? $module->giroCode($this->participant, $this->participant->paymentConfiguration())
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
// Zahlungs-Block im Mail-Kontext erzeugen (GiroCode als cid: statt Web-Endpoint).
|
||||||
|
$paymentSummary = $this->participant->paymentSummary(RegistrationRenderContext::Mail);
|
||||||
|
|
||||||
return new Content(
|
return new Content(
|
||||||
view: 'emails.participantPayments.missing_amount',
|
view: 'emails.participantPayments.missing_amount',
|
||||||
with: [
|
with: [
|
||||||
@@ -62,7 +66,7 @@ class ParticipantPaymentMissingPaymentMail extends Mailable
|
|||||||
'departure' => $participant['departure'],
|
'departure' => $participant['departure'],
|
||||||
'amount' => $participant['amount_left_string'],
|
'amount' => $participant['amount_left_string'],
|
||||||
'paymentFinalDate' => $event['registrationFinalEnd']['formatted'],
|
'paymentFinalDate' => $event['registrationFinalEnd']['formatted'],
|
||||||
'paymentSummary' => $participant['paymentSummary'],
|
'paymentSummary' => ['hasPaymentInformation' => $paymentSummary->hasPaymentInformation, 'html' => $paymentSummary->html],
|
||||||
'girocodeBinary' => $girocodeBinary,
|
'girocodeBinary' => $girocodeBinary,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use App\Enumerations\EfzStatus;
|
|||||||
use App\Enumerations\FirstAidPermission;
|
use App\Enumerations\FirstAidPermission;
|
||||||
use App\Enumerations\ParticipationType;
|
use App\Enumerations\ParticipationType;
|
||||||
use App\Enumerations\SwimmingPermission;
|
use App\Enumerations\SwimmingPermission;
|
||||||
|
use App\EventPaymentModules\DTO\RegistrationRenderContext;
|
||||||
use App\EventPaymentModules\DTO\RegistrationSummaryRequest;
|
use App\EventPaymentModules\DTO\RegistrationSummaryRequest;
|
||||||
use App\EventPaymentModules\DTO\RegistrationSummaryResponse;
|
use App\EventPaymentModules\DTO\RegistrationSummaryResponse;
|
||||||
use App\EventPaymentModules\EventPaymentModule;
|
use App\EventPaymentModules\EventPaymentModule;
|
||||||
@@ -202,14 +203,14 @@ class EventParticipant extends InstancedModel
|
|||||||
return $method?->pivot->configuration ?? [];
|
return $method?->pivot->configuration ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Zahlungs-Zusammenfassung (Anmeldeabschluss/Mail), vom Zahlungsmodul erzeugt. */
|
/** Zahlungs-Zusammenfassung (Anmeldeabschluss/Mail), vom Zahlungsmodul als fertiges HTML erzeugt. */
|
||||||
public function paymentSummary(): RegistrationSummaryResponse
|
public function paymentSummary(RegistrationRenderContext $context = RegistrationRenderContext::Web): RegistrationSummaryResponse
|
||||||
{
|
{
|
||||||
$module = $this->paymentModule();
|
$module = $this->paymentModule();
|
||||||
if ($module === null) {
|
if ($module === null) {
|
||||||
return new RegistrationSummaryResponse();
|
return new RegistrationSummaryResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $module->registrationSummary(new RegistrationSummaryRequest($this, $this->paymentConfiguration()));
|
return $module->registrationSummary(new RegistrationSummaryRequest($this, $this->paymentConfiguration(), $context));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,9 +61,7 @@ class EventParticipantResource extends JsonResource
|
|||||||
&& $this->resource->amount_paid?->getAmount() < $this->resource->amount->getAmount(),
|
&& $this->resource->amount_paid?->getAmount() < $this->resource->amount->getAmount(),
|
||||||
'paymentSummary' => [
|
'paymentSummary' => [
|
||||||
'hasPaymentInformation' => $paymentSummary->hasPaymentInformation,
|
'hasPaymentInformation' => $paymentSummary->hasPaymentInformation,
|
||||||
'lines' => $paymentSummary->lines,
|
|
||||||
'html' => $paymentSummary->html,
|
'html' => $paymentSummary->html,
|
||||||
'showGiroCode' => $paymentSummary->showGiroCode,
|
|
||||||
],
|
],
|
||||||
'nicename' => $this->resource->getNicename(),
|
'nicename' => $this->resource->getNicename(),
|
||||||
'arrival' => $this->resource->arrival_date->format('d.m.Y'),
|
'arrival' => $this->resource->arrival_date->format('d.m.Y'),
|
||||||
|
|||||||
@@ -39,18 +39,9 @@
|
|||||||
</table>
|
</table>
|
||||||
|
|
||||||
@if ($paymentSummary['hasPaymentInformation'])
|
@if ($paymentSummary['hasPaymentInformation'])
|
||||||
@if ($paymentSummary['showGiroCode'])
|
|
||||||
<p>
|
<p>
|
||||||
Deine Teilnahme ist <strong>noch nicht bestätigt,</strong> da dsies erst nach vollständigem Zahlungseingang
|
Zu deiner Anmeldung liegen noch folgende Zahlungsinformationen vor:
|
||||||
der
|
|
||||||
Fall ist.
|
|
||||||
Bitte zahle den Betrag in Höhe von <strong>{{$amount}}</strong> bis zum <strong>{{$paymentFinalDate}}
|
|
||||||
,</strong>
|
|
||||||
da andernfalls die Stornierung deiner Anmeldung erfolgen kann.
|
|
||||||
|
|
||||||
Um deine Anmeldung zu vervollständigen, überweise den Betrag bitte zugunsten folgender Bankverbindung:
|
|
||||||
</p>
|
</p>
|
||||||
@endif
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@include('emails.subparts.payment')<br />
|
@include('emails.subparts.payment')<br />
|
||||||
|
|||||||
@@ -36,14 +36,11 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@if ($paymentSummary['hasPaymentInformation'] && $paymentSummary['showGiroCode'])
|
@if ($paymentSummary['hasPaymentInformation'])
|
||||||
<p>
|
<p>
|
||||||
Wahrscheinlich hast du vergessen, deinen Teilnahmebeitrag zu überweisen, sodass deine Anmeldung leider <strong>noch nicht bestätigt,</strong> werden konnte.
|
Wahrscheinlich hast du vergessen, deinen Teilnahmebeitrag zu zahlen, sodass deine Anmeldung leider
|
||||||
|
<strong>noch nicht bestätigt</strong> werden konnte. Bitte hole die Zahlung anhand der folgenden
|
||||||
Um deine Anmeldung zu bestätigen, zahle bitte den Betrag in Höhe von <strong>{{$amount}}</strong> bis zum <strong>{{$paymentFinalDate}},</strong>
|
Zahlungsinformationen nach:
|
||||||
da andernfalls die Stornierung deiner Anmeldung erfolgen kann.
|
|
||||||
|
|
||||||
Um deine Anmeldung zu vervollständigen, überweise den Betrag bitte zugunsten folgender Bankverbindung:
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
@@ -1,58 +1,7 @@
|
|||||||
{{-- Zahlungs-Info-Block aus dem Zahlungsmodul ($paymentSummary). Entweder freier HTML-Text
|
{{-- Der Zahlungs-Block kommt fertig aus dem Zahlungsmodul ($paymentSummary['html']). Hier wird lediglich
|
||||||
(z.B. Barzahlung) oder strukturierte Zeilen (z.B. Überweisung) inkl. optionalem GiroCode. --}}
|
der GiroCode-Binary (falls vorhanden) als Inline-CID bereitgestellt, damit das im Modul-HTML
|
||||||
@if (!empty($paymentSummary['html']))
|
referenzierte cid:girocode.png in der Mail auflöst. --}}
|
||||||
|
@if (!empty($girocodeBinary))
|
||||||
|
@php $message->embedData($girocodeBinary, 'girocode.png', 'image/png'); @endphp
|
||||||
|
@endif
|
||||||
{!! $paymentSummary['html'] !!}
|
{!! $paymentSummary['html'] !!}
|
||||||
@else
|
|
||||||
<table cellpadding="0" cellspacing="0" border="0"
|
|
||||||
style="width: 100%; max-width: 640px; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 14px; color: #1f2937;">
|
|
||||||
@foreach ($paymentSummary['lines'] as $line)
|
|
||||||
<tr>
|
|
||||||
<td style="padding: {{ $loop->last ? '10px' : '8px' }} 12px; width: 180px; font-weight: {{ $loop->last ? '700' : '600' }}; color: {{ $loop->last ? '#111827' : '#4b5563' }}; border-{{ $loop->last ? 'top: 2px solid #d1d5db' : 'bottom: 1px solid #e5e7eb' }};">
|
|
||||||
{{ $line['label'] }}
|
|
||||||
</td>
|
|
||||||
<td style="padding: {{ $loop->last ? '10px' : '8px' }} 12px; font-weight: {{ $loop->last ? '700' : '400' }}; color: {{ $loop->last ? '#111827' : '#1f2937' }}; border-{{ $loop->last ? 'top: 2px solid #d1d5db' : 'bottom: 1px solid #e5e7eb' }};">
|
|
||||||
{{ $line['value'] }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
</table>
|
|
||||||
|
|
||||||
@if (!empty($paymentSummary['showGiroCode']))
|
|
||||||
@php
|
|
||||||
$girocodeSrc = $message->embedData($girocodeBinary, 'girocode.png', 'image/png');
|
|
||||||
@endphp
|
|
||||||
<table style="margin: 20px;">
|
|
||||||
<tr style="vertical-align: top; background-color: #eaeaea; border-spacing: 0">
|
|
||||||
<td style="padding: 20px; text-align: center; font-weight: bold;">
|
|
||||||
<strong>
|
|
||||||
Bequem überweisen mit QR-Code
|
|
||||||
</strong><br/><br/>
|
|
||||||
|
|
||||||
<img
|
|
||||||
style="padding-left: 20px;width: 150px; height: 150px;"
|
|
||||||
src="{{ $girocodeSrc }}"
|
|
||||||
alt="Giro-Code">
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<p style="padding-left:10px; padding-right: 10px; text-align: left;">
|
|
||||||
<strong>Und so funktioniert es</strong><br/>
|
|
||||||
<ul style="text-align: left; list-style: decimal; font-weight: normal">
|
|
||||||
<li style="padding-right: 10px;">Mache einen Screenshot des QR-Codes</li>
|
|
||||||
<li style="padding-right: 10px;">Öffne deine Banking-App und wähle den Menüpunkt
|
|
||||||
„(Foto-)Überweisung“.
|
|
||||||
</li>
|
|
||||||
<li style="padding-right: 10px;">Wähle das gespeicherte Bild aus</li>
|
|
||||||
</ul>
|
|
||||||
</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Bitte zahle immer mit dem vorgegeben Betreff, damit deine Zahlung möglichst einfach zugeordnet werden
|
|
||||||
kann.<br/>
|
|
||||||
Sollte die Zahlung innerhalb dieser Frist nicht oder nur teilweise möglich sein, kontaktiere bitte die
|
|
||||||
Aktionsleitung, sodass wir eine gemeinsame Lösung finden können.
|
|
||||||
</p>
|
|
||||||
@endif
|
|
||||||
@endif
|
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
{{-- Zahlungs-Block der Überweisung -- MAIL-Kontext. E-Mail-taugliches Markup (Inline-Styles, Tabellen).
|
||||||
|
$giroCodeSrc: Bildquelle des GiroCodes (cid:) -- null, wenn kein GiroCode. --}}
|
||||||
|
<table cellpadding="0" cellspacing="0" border="0"
|
||||||
|
style="width: 100%; max-width: 640px; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 14px; color: #1f2937;">
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 8px 12px; width: 180px; font-weight: 600; color: #4b5563; border-bottom: 1px solid #e5e7eb;">
|
||||||
|
Kontoinhaber
|
||||||
|
</td>
|
||||||
|
<td style="padding: 8px 12px; border-bottom: 1px solid #e5e7eb;">{{ $accountOwner }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 8px 12px; font-weight: 600; color: #4b5563; border-bottom: 1px solid #e5e7eb;">IBAN</td>
|
||||||
|
<td style="padding: 8px 12px; border-bottom: 1px solid #e5e7eb; font-family: monospace;">{{ $iban }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 8px 12px; font-weight: 600; color: #4b5563; border-bottom: 1px solid #e5e7eb;">
|
||||||
|
Verwendungszweck
|
||||||
|
</td>
|
||||||
|
<td style="padding: 8px 12px; border-bottom: 1px solid #e5e7eb;">{{ $paymentPurpose }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 10px 12px; font-weight: 700; color: #111827; border-top: 2px solid #d1d5db;">Betrag</td>
|
||||||
|
<td style="padding: 10px 12px; font-weight: 700; color: #111827; border-top: 2px solid #d1d5db;">{{ $amount }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
@if ($giroCodeSrc)
|
||||||
|
<table style="margin: 20px 0; border-collapse: collapse;">
|
||||||
|
<tr style="vertical-align: top; background-color: #eaeaea;">
|
||||||
|
<td style="padding: 20px; text-align: center; font-weight: bold;">
|
||||||
|
<strong>Bequem überweisen mit QR-Code</strong><br/><br/>
|
||||||
|
<img src="{{ $giroCodeSrc }}" alt="Giro-Code" style="width: 150px; height: 150px;"/>
|
||||||
|
</td>
|
||||||
|
<td style="padding: 10px 16px;">
|
||||||
|
<strong>Und so funktioniert es</strong>
|
||||||
|
<ol style="text-align: left; font-weight: normal; margin: 8px 0 0 18px; padding: 0;">
|
||||||
|
<li style="margin-bottom: 4px;">Öffne deine Banking-App und wähle „(Foto-)Überweisung“.</li>
|
||||||
|
<li style="margin-bottom: 4px;">Scanne den QR-Code (oder wähle einen Screenshot davon aus).</li>
|
||||||
|
<li>Prüfe die Daten und gib die Überweisung frei.</li>
|
||||||
|
</ol>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p style="margin: 8px 0;">
|
||||||
|
<a href="{{ $reminderUrl }}">Zahlungserinnerung in den Kalender setzen</a>
|
||||||
|
</p>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<p style="margin: 12px 0 0;">
|
||||||
|
Bitte zahle immer mit dem vorgegebenen Verwendungszweck, damit deine Zahlung eindeutig zugeordnet werden kann.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
@if ($paymentDeadline)
|
||||||
|
<p style="margin: 12px 0 0;">
|
||||||
|
Bitte beachte, dass deine Anmeldung erst nach vollständigem Zahlungseingang bestätigt ist. Erfolgt dieser nicht
|
||||||
|
bis zum <strong>{{ $paymentDeadline }}</strong>, kann deine Anmeldung storniert werden. Solltest du den Betrag
|
||||||
|
bis dahin nicht oder nur teilweise zahlen können, kontaktiere bitte die Aktionsleitung, damit wir eine
|
||||||
|
gemeinsame Lösung finden können.
|
||||||
|
</p>
|
||||||
|
@endif
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
{{-- Zahlungs-Block der Überweisung -- WEB-Kontext. Nutzt globale SPA-Klassen (form-table, link) aus
|
||||||
|
SignupForm.vue; wird per v-html in SubmitSuccess.vue ausgegeben.
|
||||||
|
$giroCodeSrc: Bildquelle des GiroCodes (Web-Endpoint) -- null, wenn kein GiroCode. --}}
|
||||||
|
<table class="form-table" style="margin-bottom: 16px;">
|
||||||
|
<tr>
|
||||||
|
<td>Kontoinhaber:</td>
|
||||||
|
<td>{{ $accountOwner }}</td>
|
||||||
|
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>IBAN:</td>
|
||||||
|
<td>{{ $iban }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Verwendungszweck:</td>
|
||||||
|
<td>{{ $paymentPurpose }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Betrag:</td>
|
||||||
|
<td><strong>{{ $amount }}</strong></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
@if ($giroCodeSrc)
|
||||||
|
<div style="display: flex; gap: 20px; align-items: flex-start; flex-wrap: wrap; margin-bottom: 16px;">
|
||||||
|
<div style="text-align: center;">
|
||||||
|
<img src="{{ $giroCodeSrc }}" alt="Giro-Code" style="max-width: 180px;"/>
|
||||||
|
<span style="display: block; font-size: 0.8rem; color: #6b7280; margin-top: 4px;">Giro-Code</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<strong>Bequem überweisen mit QR-Code</strong>
|
||||||
|
<ol style="margin: 8px 0 0 18px; padding: 0;">
|
||||||
|
<li>Öffne deine Banking-App und wähle „(Foto-)Überweisung“.</li>
|
||||||
|
<li>Scanne den QR-Code (oder wähle einen Screenshot davon aus).</li>
|
||||||
|
<li>Prüfe die Daten und gib die Überweisung frei.</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p style="margin: 8px 0;">
|
||||||
|
<a class="link" href="{{ $reminderUrl }}">Zahlungserinnerung in den Kalender setzen</a>
|
||||||
|
</p>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<p style="margin: 12px 0 0;">
|
||||||
|
Bitte zahle immer mit dem vorgegebenen Verwendungszweck, damit deine Zahlung eindeutig zugeordnet werden kann.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
@if ($paymentDeadline)
|
||||||
|
<p style="margin: 12px 0 0;">
|
||||||
|
Bitte beachte, dass deine Anmeldung erst nach vollständigem Zahlungseingang bestätigt ist. Erfolgt dieser nicht
|
||||||
|
bis zum <strong>{{ $paymentDeadline }}</strong>, kann deine Anmeldung storniert werden. Solltest du den Betrag
|
||||||
|
bis dahin nicht oder nur teilweise zahlen können, kontaktiere bitte die Aktionsleitung, damit wir eine
|
||||||
|
gemeinsame Lösung finden können.
|
||||||
|
</p>
|
||||||
|
@endif
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{{-- Barzahlung/Sonstiges -- MAIL-Kontext. E-Mail-tauglicher Rahmen um den nutzerdefinierten Freitext (richtext). --}}
|
||||||
|
<div style="font-family: Arial, sans-serif; font-size: 14px; color: #1f2937; line-height: 1.5;">
|
||||||
|
{!! $paymentInformation !!}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{{-- Barzahlung/Sonstiges -- WEB-Kontext. Inhalt ist der nutzerdefinierte Freitext (richtext, HTML). --}}
|
||||||
|
<div class="payment-information">
|
||||||
|
{!! $paymentInformation !!}
|
||||||
|
</div>
|
||||||
@@ -7,6 +7,7 @@ use App\Enumerations\EfzStatus;
|
|||||||
use App\Enumerations\FirstAidPermission;
|
use App\Enumerations\FirstAidPermission;
|
||||||
use App\Enumerations\ParticipationType;
|
use App\Enumerations\ParticipationType;
|
||||||
use App\Enumerations\SwimmingPermission;
|
use App\Enumerations\SwimmingPermission;
|
||||||
|
use App\EventPaymentModules\DTO\RegistrationRenderContext;
|
||||||
use App\EventPaymentModules\ProvidesGiroCode;
|
use App\EventPaymentModules\ProvidesGiroCode;
|
||||||
use App\Models\AvailablePaymentMethod;
|
use App\Models\AvailablePaymentMethod;
|
||||||
use App\Models\Event;
|
use App\Models\Event;
|
||||||
@@ -117,21 +118,54 @@ class EventParticipantPaymentSummaryTest extends TestCase
|
|||||||
$this->assertSame('Kasse', $config['account_owner']);
|
$this->assertSame('Kasse', $config['account_owner']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_payment_summary_builds_lines_from_resolved_config(): void
|
public function test_payment_summary_renders_html_from_resolved_config(): void
|
||||||
{
|
{
|
||||||
$event = $this->createEventWithTransfer(['account_owner' => 'Kasse', 'iban' => 'DE-EVENT']);
|
$event = $this->createEventWithTransfer(['account_owner' => 'Kasse', 'iban' => 'DE-EVENT']);
|
||||||
$participant = $this->createParticipant($event, 50.0);
|
$participant = $this->createParticipant($event, 50.0);
|
||||||
|
|
||||||
$summary = $participant->paymentSummary();
|
// Web-Kontext: SPA-Markup (form-table), IBAN aus der Config + GiroCode-Bild über den Endpoint.
|
||||||
|
$web = $participant->paymentSummary(RegistrationRenderContext::Web);
|
||||||
|
$this->assertTrue($web->hasPaymentInformation);
|
||||||
|
$this->assertStringContainsString('DE-EVENT', $web->html);
|
||||||
|
$this->assertStringContainsString('/print-girocode/', $web->html);
|
||||||
|
$this->assertStringContainsString('class="form-table"', $web->html);
|
||||||
|
|
||||||
$this->assertTrue($summary->hasPaymentInformation);
|
// Mail-Kontext: E-Mail-Markup (Inline-Styles), GiroCode als inline-CID.
|
||||||
$this->assertTrue($summary->showGiroCode);
|
$mail = $participant->paymentSummary(RegistrationRenderContext::Mail);
|
||||||
|
$this->assertStringContainsString('cid:girocode.png', $mail->html);
|
||||||
$byLabel = [];
|
$this->assertStringContainsString('style="', $mail->html);
|
||||||
foreach ($summary->lines as $line) {
|
$this->assertStringNotContainsString('class="form-table"', $mail->html);
|
||||||
$byLabel[$line['label']] = $line['value'];
|
|
||||||
}
|
}
|
||||||
$this->assertSame('DE-EVENT', $byLabel['IBAN']);
|
|
||||||
|
public function test_cash_summary_renders_configured_text(): void
|
||||||
|
{
|
||||||
|
$event = $this->createEventWithTransfer(['account_owner' => 'Kasse', 'iban' => 'DE-EVENT']);
|
||||||
|
|
||||||
|
$cashConfig = ['payment_information' => '<p>Bitte bar vor Ort zahlen.</p>'];
|
||||||
|
AvailablePaymentMethod::create([
|
||||||
|
'tenant' => $this->tenant->slug, 'slug' => PaymentMethod::PAYMENT_NOT_DEFINED,
|
||||||
|
'name' => 'Barzahlung', 'active' => true, 'configuration' => $cashConfig,
|
||||||
|
]);
|
||||||
|
EventPaymentMethods::create([
|
||||||
|
'event_id' => $event->id, 'slug' => PaymentMethod::PAYMENT_NOT_DEFINED, 'configuration' => $cashConfig,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$participant = $this->createParticipant($event, 50.0, PaymentMethod::PAYMENT_NOT_DEFINED);
|
||||||
|
|
||||||
|
$summary = $participant->paymentSummary(RegistrationRenderContext::Web);
|
||||||
|
$this->assertTrue($summary->hasPaymentInformation);
|
||||||
|
$this->assertStringContainsString('Bitte bar vor Ort zahlen.', $summary->html);
|
||||||
|
$this->assertStringContainsString('class="payment-information"', $summary->html);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_paid_participant_has_no_payment_information(): void
|
||||||
|
{
|
||||||
|
$event = $this->createEventWithTransfer(['account_owner' => 'Kasse', 'iban' => 'DE-EVENT']);
|
||||||
|
$participant = $this->createParticipant($event, 50.0);
|
||||||
|
$participant->amount_paid = 50.0;
|
||||||
|
$participant->save();
|
||||||
|
|
||||||
|
$this->assertFalse($participant->paymentSummary()->hasPaymentInformation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_resource_exposes_payment_summary(): void
|
public function test_resource_exposes_payment_summary(): void
|
||||||
@@ -142,6 +176,6 @@ class EventParticipantPaymentSummaryTest extends TestCase
|
|||||||
$array = $participant->toResource()->toArray(request());
|
$array = $participant->toResource()->toArray(request());
|
||||||
|
|
||||||
$this->assertTrue($array['paymentSummary']['hasPaymentInformation']);
|
$this->assertTrue($array['paymentSummary']['hasPaymentInformation']);
|
||||||
$this->assertTrue($array['paymentSummary']['showGiroCode']);
|
$this->assertStringContainsString('DE-EVENT', $array['paymentSummary']['html']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,15 @@
|
|||||||
namespace Tests\Unit;
|
namespace Tests\Unit;
|
||||||
|
|
||||||
use App\EventPaymentModules\DTO\RegistrationSummaryRequest;
|
use App\EventPaymentModules\DTO\RegistrationSummaryRequest;
|
||||||
use App\EventPaymentModules\Modules\AccountTransferPaymentModule;
|
|
||||||
use App\EventPaymentModules\Modules\UndefinedPaymentModule;
|
use App\EventPaymentModules\Modules\UndefinedPaymentModule;
|
||||||
use App\Models\EventParticipant;
|
use App\Models\EventParticipant;
|
||||||
use App\ValueObjects\Amount;
|
use App\ValueObjects\Amount;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reine Modul-Logik ohne Framework-Kontext. Das Überweisungs-Modul rendert inzwischen Blade und wird
|
||||||
|
* daher auf Feature-Ebene getestet (siehe EventParticipantPaymentSummaryTest).
|
||||||
|
*/
|
||||||
class RegistrationSummaryTest extends TestCase
|
class RegistrationSummaryTest extends TestCase
|
||||||
{
|
{
|
||||||
private function participant(float $amount, float $amountPaid, string $purpose = 'Zweck'): EventParticipant
|
private function participant(float $amount, float $amountPaid, string $purpose = 'Zweck'): EventParticipant
|
||||||
@@ -24,56 +27,6 @@ class RegistrationSummaryTest extends TestCase
|
|||||||
return $participant;
|
return $participant;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_account_transfer_summary_builds_lines_from_config(): void
|
|
||||||
{
|
|
||||||
$module = new AccountTransferPaymentModule();
|
|
||||||
$request = new RegistrationSummaryRequest(
|
|
||||||
$this->participant(50.0, 0.0, 'Camp - Beitrag'),
|
|
||||||
['account_owner' => 'Kasse', 'iban' => 'DE123', 'bic' => 'XY'],
|
|
||||||
);
|
|
||||||
|
|
||||||
$summary = $module->registrationSummary($request);
|
|
||||||
|
|
||||||
$this->assertTrue($summary->hasPaymentInformation);
|
|
||||||
$this->assertTrue($summary->showGiroCode);
|
|
||||||
$this->assertNull($summary->html);
|
|
||||||
|
|
||||||
$byLabel = [];
|
|
||||||
foreach ($summary->lines as $line) {
|
|
||||||
$byLabel[$line['label']] = $line['value'];
|
|
||||||
}
|
|
||||||
$this->assertSame('Kasse', $byLabel['Kontoinhaber']);
|
|
||||||
$this->assertSame('DE123', $byLabel['IBAN']);
|
|
||||||
$this->assertSame('Camp - Beitrag', $byLabel['Verwendungszweck']);
|
|
||||||
$this->assertArrayHasKey('Betrag', $byLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_account_transfer_without_open_amount_has_no_payment_information(): void
|
|
||||||
{
|
|
||||||
$module = new AccountTransferPaymentModule();
|
|
||||||
$summary = $module->registrationSummary(new RegistrationSummaryRequest(
|
|
||||||
$this->participant(50.0, 50.0),
|
|
||||||
['account_owner' => 'Kasse', 'iban' => 'DE123'],
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->assertFalse($summary->hasPaymentInformation);
|
|
||||||
$this->assertFalse($summary->showGiroCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_cash_summary_returns_configured_html(): void
|
|
||||||
{
|
|
||||||
$module = new UndefinedPaymentModule();
|
|
||||||
$summary = $module->registrationSummary(new RegistrationSummaryRequest(
|
|
||||||
$this->participant(50.0, 0.0),
|
|
||||||
['payment_information' => '<p>Bitte bar vor Ort zahlen.</p>'],
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->assertTrue($summary->hasPaymentInformation);
|
|
||||||
$this->assertFalse($summary->showGiroCode);
|
|
||||||
$this->assertSame('<p>Bitte bar vor Ort zahlen.</p>', $summary->html);
|
|
||||||
$this->assertSame([], $summary->lines);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_cash_summary_empty_when_no_text_configured(): void
|
public function test_cash_summary_empty_when_no_text_configured(): void
|
||||||
{
|
{
|
||||||
$module = new UndefinedPaymentModule();
|
$module = new UndefinedPaymentModule();
|
||||||
|
|||||||
Reference in New Issue
Block a user