Zahlungsparser

This commit is contained in:
2026-09-09 16:55:08 +02:00
parent ae13841699
commit 651b6147bf
38 changed files with 3308 additions and 22 deletions
@@ -69,6 +69,37 @@ abstract class AbstractEventPaymentModule implements EventPaymentModule
return $this->allRequiredFilled($this->getOptions(), $config);
}
/**
* Optionen mit `scope => 'tenant'`: Sie gelten für den ganzen Mandanten und werden **nicht** pro
* Veranstaltung eingefroren.
*
* Beispiel ist das Kontoauszug-Format: Es beschreibt die Bank, nicht die Zusage an die
* Teilnehmenden. Läge es im Event-Snapshot, ließe sich nach einem Bankwechsel für laufende
* Aktionen nichts mehr importieren, bis das Format bei jeder einzeln nachgezogen wurde.
* IBAN und Kontoinhaber bleiben dagegen weiterhin pro Aktion eingefroren.
*
* @return array<int, string>
*/
public function tenantScopedOptionKeys(): array
{
return array_values(array_map(
static fn (array $option) => $option['name'],
array_filter($this->getOptions(), static fn (array $option) => ($option['scope'] ?? null) === 'tenant')
));
}
/**
* Entfernt die tenant-weiten Optionen aus einer Konfiguration -- angewandt auf den
* Copy-on-Assign-Snapshot einer Veranstaltung.
*
* @param array<string, mixed> $config
* @return array<string, mixed>
*/
public function stripTenantScopedOptions(array $config): array
{
return array_diff_key($config, array_flip($this->tenantScopedOptionKeys()));
}
/**
* @param array<string, mixed> $input
* @return array<string, mixed>
@@ -84,6 +115,24 @@ abstract class AbstractEventPaymentModule implements EventPaymentModule
return $this->allRequiredFilled($this->getParticipantOptions(), $input);
}
/**
* Die Teilnehmer-Optionen, die im Anmeldeformular tatsächlich abgefragt werden.
*
* Optionen mit `system => true` fallen heraus: Sie liegen zwar in `payment_options`, entstehen aber
* im Programm statt durch eine Eingabe -- das Zahler-Konto etwa trägt der Import aus dem
* Kontoauszug nach. Im Schema müssen sie trotzdem stehen, sonst verwirft
* {@see sanitizeParticipantOptions()} sie als unbekannte Schlüssel.
*
* @return array<int, array{name: string, label: string, type: string, required: bool}>
*/
public function participantInputOptions(): array
{
return array_values(array_filter(
$this->getParticipantOptions(),
static fn (array $option): bool => ($option['system'] ?? false) !== true,
));
}
/**
* @param array<int, array{name: string, required?: bool}> $schema
* @return array<int, string>