Automatischer Zahlungsparser

This commit is contained in:
2026-09-10 09:50:14 +02:00
parent 025035190d
commit 6301c342e4
24 changed files with 1692 additions and 83 deletions
@@ -86,6 +86,16 @@ const retainedAmount = computed(() => {
const hasRetention = computed(() => retainedAmount.value > 0);
/**
* Das Konto, das die Zahlungsart kennt -- bei der Überweisung das des Zahlungseingangs.
*
* Ist es da, wird es weder erfragt noch bearbeitet: Erstattet wird auf das Konto, von dem der Beitrag
* kam, und genau das steht hier. `null`, solange nichts bekannt ist (Barzahlung, Altbestand).
*/
const knownRefundAccount = computed(
() => showParticipant.value?.refundData?.available ? showParticipant.value.refundData : null
);
const retainedAmountReadable = computed(
() => retainedAmount.value.toFixed(2).replace('.', ',') + ' Euro'
);
@@ -121,7 +131,8 @@ const refundFormComplete = computed(() => {
}
}
if (refundForm.captureMode === 'management') {
// Beim bekannten Konto gibt es nichts einzugeben -- es steht fest.
if (refundForm.captureMode === 'management' && !knownRefundAccount.value) {
return refundForm.accountOwner.trim() !== '' && refundForm.accountIban.trim() !== '';
}
@@ -429,7 +440,7 @@ function validateRefund() {
// Beim Direktweg wird sofort eingereicht -- danach gibt es keine Gelegenheit mehr zu berichtigen.
// Ob die IBAN wirklich stimmt, prüft der Server mit Prüfziffer und länderabhängiger Länge.
if (refundForm.captureMode === 'management') {
if (refundForm.captureMode === 'management' && !knownRefundAccount.value) {
if (!refundForm.accountOwner.trim()) {
refundErrors.accountOwner = 'Bitte gib an, wem das Konto gehört.';
}
@@ -456,9 +467,14 @@ async function execRefund() {
amount: refundForm.amount,
reason: refundForm.reason,
reasonNote: refundForm.reasonNote,
// Leer beim Weg über den Teili -- dann verschickt der Server nur den Link.
accountOwner: refundForm.captureMode === 'management' ? refundForm.accountOwner : '',
accountIban: refundForm.captureMode === 'management' ? refundForm.accountIban : '',
// Leer beim Weg über den Teili -- dann verschickt der Server nur den Link. Beim
// Sofort-Einreichen mit bekanntem Konto geht dieses mit; eingegeben wurde nichts.
accountOwner: refundForm.captureMode === 'management'
? (knownRefundAccount.value?.accountOwner ?? refundForm.accountOwner)
: '',
accountIban: refundForm.captureMode === 'management'
? (knownRefundAccount.value?.accountIban ?? refundForm.accountIban)
: '',
// Spende: kein Konto, trotzdem sofort eingereicht.
donation: refundForm.captureMode === 'donation',
// Leer bei voller Erstattung -- dann gibt es nichts zu begründen.
@@ -805,14 +821,36 @@ function mailToGroup(groupKey) {
Liegt die Bankverbindung schon vor oder will der Teili spenden, entfällt der Umweg über ihn:
die Erstattung wird sofort eingereicht. Er bekommt den Beleg trotzdem.
-->
<!--
Ist das Konto aus dem Zahlungseingang bekannt, wird es weder erfragt noch bearbeitet: Es
steht fest, dass auf genau dieses Konto zu erstatten ist. Der Teili entscheidet dann nur
noch, ob er es haben oder spenden möchte.
-->
<div v-if="knownRefundAccount" class="refund-known-account">
<strong>Konto aus dem Zahlungseingang</strong>
<span>{{ knownRefundAccount.accountOwner }}</span>
<span class="refund-known-account__iban">{{ knownRefundAccount.accountIban }}</span>
<span class="refund-known-account__source">{{ knownRefundAccount.source }}</span>
</div>
<div class="refund-field">
<label class="refund-choice">
<input type="radio" value="participant" v-model="refundForm.captureMode" />
Teilnehmer*in trägt die Bankverbindung selbst ein
<template v-if="knownRefundAccount">
Teilnehmer*in bestätigt die Erstattung oder spendet
</template>
<template v-else>
Teilnehmer*in trägt die Bankverbindung selbst ein
</template>
</label>
<label class="refund-choice">
<input type="radio" value="management" v-model="refundForm.captureMode" />
Bankverbindung liegt mir vor
<template v-if="knownRefundAccount">
Sofort einreichen, ohne auf die Rückmeldung zu warten
</template>
<template v-else>
Bankverbindung liegt mir vor
</template>
</label>
<label class="refund-choice">
<input type="radio" value="donation" v-model="refundForm.captureMode" />
@@ -825,7 +863,13 @@ function mailToGroup(groupKey) {
eingereicht; der Teili erhält den Beleg per E-Mail.
</p>
<template v-if="refundForm.captureMode === 'management'">
<!-- Bekanntes Konto: nichts einzugeben, es wird ohnehin dieses genommen. -->
<p v-if="refundForm.captureMode === 'management' && knownRefundAccount" class="refund-hint">
Die Erstattung wird sofort auf das oben genannte Konto eingereicht. Der Teili erhält den
Beleg per E-Mail, wird aber nicht mehr nach einer Spende gefragt.
</p>
<template v-if="refundForm.captureMode === 'management' && !knownRefundAccount">
<div class="refund-field">
<label for="refund_account_owner">Kontoinhaber*in</label>
<input
@@ -882,6 +926,31 @@ function mailToGroup(groupKey) {
color: #4b5563;
}
/* Anzeige, kein Feld: bewusst nicht wie ein Eingabeblock gesetzt, damit gar nicht erst der Eindruck
entsteht, hier ließe sich etwas ändern. */
.refund-known-account {
display: flex;
flex-direction: column;
gap: 2px;
margin-bottom: 12px;
padding: 10px 12px;
border: 1px solid #d1d5db;
border-radius: 6px;
background-color: #f9fafb;
font-size: 0.9rem;
}
.refund-known-account__iban {
font-family: monospace;
letter-spacing: 0.04em;
color: #4b5563;
}
.refund-known-account__source {
color: #6b7280;
font-size: 0.8rem;
}
.refund-field {
margin-bottom: 14px;
}