Das Überweisungsformular fragt nur noch das Auftragskonto ab; die passende Bankverbindung ermittelt Bankzugang::zugangJeKonto() aus der Kontenzuordnung. Konten ohne konfigurierte Bank stehen in der Auswahl nicht mehr zur Verfügung. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
252 lines
8 KiB
PHP
252 lines
8 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace Finanzmanager\Controllers;
|
||
|
||
use Finanzmanager\Models\Adresse;
|
||
use Finanzmanager\Models\Bankzugang;
|
||
use Finanzmanager\Models\Kategorie;
|
||
use Finanzmanager\Models\Klasse;
|
||
use Finanzmanager\Models\Konto;
|
||
use Finanzmanager\Models\Zahlungsauftrag;
|
||
use Finanzmanager\Services\FinTsUeberweisung;
|
||
use Finanzmanager\View;
|
||
|
||
/**
|
||
* Zahlungsverkehr: Überweisungen erfassen, prüfen und über FinTS absenden.
|
||
*/
|
||
class ZahlungsverkehrController extends BaseController
|
||
{
|
||
public function index(): void
|
||
{
|
||
$this->verlangeAnmeldung();
|
||
|
||
$status = $this->query('status');
|
||
|
||
$this->render('zahlungsverkehr/index.php', [
|
||
'titel' => 'Zahlungsverkehr',
|
||
'auftraege' => Zahlungsauftrag::alle($status),
|
||
'status' => $status,
|
||
'offen' => Zahlungsauftrag::anzahlOffen(),
|
||
'wartetTan' => FinTsUeberweisung::wartetAufTan(),
|
||
]);
|
||
}
|
||
|
||
public function neu(): void
|
||
{
|
||
$this->verlangeAnmeldung();
|
||
|
||
$this->render('zahlungsverkehr/formular.php', [
|
||
'titel' => 'Überweisung erfassen',
|
||
'auftrag' => null,
|
||
'konten' => $this->kontenMitBank(),
|
||
'adressen' => Adresse::alle(),
|
||
'kategorien' => Kategorie::baumFlach(null, true),
|
||
'klassen' => Klasse::alle(),
|
||
]);
|
||
}
|
||
|
||
public function anlegen(): void
|
||
{
|
||
$this->verlangeAnmeldung();
|
||
|
||
try {
|
||
$id = Zahlungsauftrag::anlegen($this->formulardaten());
|
||
} catch (\Throwable $e) {
|
||
View::redirect('/zahlungsverkehr/neu', $e->getMessage(), 'fehler');
|
||
return;
|
||
}
|
||
|
||
// Auf Wunsch eine neue Adresse aus dem Empfänger anlegen – so wächst
|
||
// das Adressbuch beim Arbeiten, nicht durch Pflege.
|
||
if (isset($_POST['adresse_merken'])) {
|
||
try {
|
||
Adresse::anlegen([
|
||
'name' => $this->post('empfaenger'),
|
||
'iban' => $this->post('iban'),
|
||
'bic' => $this->post('bic'),
|
||
]);
|
||
} catch (\Throwable) {
|
||
// Gibt es die Adresse schon, ist nichts zu tun.
|
||
}
|
||
}
|
||
|
||
View::redirect('/zahlungsverkehr/' . $id, 'Überweisung erfasst. Sie ist noch nicht abgesendet.');
|
||
}
|
||
|
||
/** @param array<string,string> $params */
|
||
public function bearbeiten(array $params): void
|
||
{
|
||
$this->verlangeAnmeldung();
|
||
|
||
$auftrag = Zahlungsauftrag::find((int)$params['id']);
|
||
if ($auftrag === null) {
|
||
View::redirect('/zahlungsverkehr', 'Den Zahlungsauftrag gibt es nicht.', 'fehler');
|
||
return;
|
||
}
|
||
|
||
$konten = $this->kontenMitBank();
|
||
|
||
// Ein Auftrag, dessen Bank nachträglich entfernt wurde, soll sein
|
||
// Auftragskonto nicht verlieren – sonst würde beim Speichern
|
||
// unbemerkt ein anderes Konto gewählt.
|
||
if (!in_array((int)$auftrag['konto_id'], array_column($konten, 'id'), true)) {
|
||
$bisheriges = Konto::find((int)$auftrag['konto_id']);
|
||
if ($bisheriges !== null) {
|
||
$konten[] = $bisheriges;
|
||
}
|
||
}
|
||
|
||
$this->render('zahlungsverkehr/formular.php', [
|
||
'titel' => 'Überweisung an ' . $auftrag['empfaenger'],
|
||
'auftrag' => $auftrag,
|
||
'konten' => $konten,
|
||
'adressen' => Adresse::alle(),
|
||
'kategorien' => Kategorie::baumFlach(null, true),
|
||
'klassen' => Klasse::alle(),
|
||
]);
|
||
}
|
||
|
||
/** @param array<string,string> $params */
|
||
public function speichern(array $params): void
|
||
{
|
||
$this->verlangeAnmeldung();
|
||
|
||
$id = (int)$params['id'];
|
||
|
||
try {
|
||
Zahlungsauftrag::speichern($id, $this->formulardaten());
|
||
} catch (\Throwable $e) {
|
||
View::redirect('/zahlungsverkehr/' . $id, $e->getMessage(), 'fehler');
|
||
return;
|
||
}
|
||
|
||
View::redirect('/zahlungsverkehr/' . $id, 'Überweisung gespeichert.');
|
||
}
|
||
|
||
/** @param array<string,string> $params */
|
||
public function loeschen(array $params): void
|
||
{
|
||
$this->verlangeAnmeldung();
|
||
|
||
try {
|
||
Zahlungsauftrag::loeschen((int)$params['id']);
|
||
} catch (\Throwable $e) {
|
||
View::redirect('/zahlungsverkehr', $e->getMessage(), 'fehler');
|
||
return;
|
||
}
|
||
|
||
View::redirect('/zahlungsverkehr', 'Überweisung gelöscht.');
|
||
}
|
||
|
||
/** @param array<string,string> $params */
|
||
public function stornieren(array $params): void
|
||
{
|
||
$this->verlangeAnmeldung();
|
||
|
||
Zahlungsauftrag::stornieren((int)$params['id']);
|
||
|
||
View::redirect('/zahlungsverkehr', 'Überweisung storniert.');
|
||
}
|
||
|
||
// ── Absenden ─────────────────────────────────────────────────────────────
|
||
|
||
/** @param array<string,string> $params */
|
||
public function senden(array $params): void
|
||
{
|
||
$this->verlangeAnmeldung();
|
||
|
||
$this->zeige(FinTsUeberweisung::senden((int)$params['id']));
|
||
}
|
||
|
||
public function tanFormular(): void
|
||
{
|
||
$this->verlangeAnmeldung();
|
||
|
||
$tan = FinTsUeberweisung::offeneTanAnfrage();
|
||
if ($tan === null) {
|
||
View::redirect('/zahlungsverkehr', 'Es wartet keine Überweisung auf eine Freigabe.');
|
||
return;
|
||
}
|
||
|
||
$this->render('zahlungsverkehr/tan.php', [
|
||
'titel' => 'Überweisung freigeben',
|
||
'tan' => $tan,
|
||
'meldung' => 'Die Bank verlangt eine Freigabe.',
|
||
]);
|
||
}
|
||
|
||
public function tanEinreichen(): void
|
||
{
|
||
$this->verlangeAnmeldung();
|
||
|
||
$this->zeige(FinTsUeberweisung::tanEinreichen($this->post('tan')));
|
||
}
|
||
|
||
public function tanAbbrechen(): void
|
||
{
|
||
$this->verlangeAnmeldung();
|
||
|
||
FinTsUeberweisung::abbrechen();
|
||
|
||
View::redirect('/zahlungsverkehr', 'Vorgang abgebrochen. Der Auftrag bleibt als Entwurf stehen.');
|
||
}
|
||
|
||
/** @param array<string,mixed> $ergebnis */
|
||
private function zeige(array $ergebnis): void
|
||
{
|
||
if ($ergebnis['status'] === 'tan') {
|
||
$this->render('zahlungsverkehr/tan.php', [
|
||
'titel' => 'Überweisung freigeben',
|
||
'tan' => $ergebnis['tan'] ?? [],
|
||
'meldung' => $ergebnis['meldung'],
|
||
]);
|
||
return;
|
||
}
|
||
|
||
View::redirect(
|
||
'/zahlungsverkehr',
|
||
$ergebnis['meldung'],
|
||
$ergebnis['status'] === 'erfolg' ? 'erfolg' : 'fehler'
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Konten, denen eine Bankverbindung zugeordnet ist – nur die kommen als
|
||
* Auftragskonto infrage, denn ohne Bank lässt sich nichts senden.
|
||
*
|
||
* @return list<array<string,mixed>>
|
||
*/
|
||
private function kontenMitBank(): array
|
||
{
|
||
$zugangJeKonto = Bankzugang::zugangJeKonto();
|
||
|
||
return array_values(array_filter(
|
||
Konto::alle(true),
|
||
static fn(array $konto): bool => isset($zugangJeKonto[(int)$konto['id']])
|
||
));
|
||
}
|
||
|
||
/** @return array<string,mixed> */
|
||
private function formulardaten(): array
|
||
{
|
||
$kontoId = (int)$this->post('konto_id');
|
||
|
||
return [
|
||
'konto_id' => $kontoId,
|
||
// Die Bank ergibt sich aus dem Auftragskonto – eine eigene Auswahl
|
||
// gibt es im Formular nicht mehr.
|
||
'zugang_id' => Bankzugang::zugangJeKonto()[$kontoId] ?? null,
|
||
'empfaenger' => $this->post('empfaenger'),
|
||
'iban' => $this->post('iban'),
|
||
'bic' => $this->post('bic'),
|
||
'betrag' => str_replace(',', '.', $this->post('betrag')),
|
||
'waehrung' => $this->post('waehrung', 'EUR'),
|
||
'verwendungszweck' => $this->post('verwendungszweck'),
|
||
'ausfuehrung_am' => $this->post('ausfuehrung_am'),
|
||
'kategorie_id' => $this->post('kategorie_id'),
|
||
'klasse_id' => $this->post('klasse_id'),
|
||
];
|
||
}
|
||
}
|