Finanzmanager/src/Controllers/ZahlungsverkehrController.php
fds2610-bot da8e3784fa Fix #50: Zahlungsverkehr wählt die Bank automatisch zum Auftragskonto
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>
2026-08-31 07:58:07 +02:00

252 lines
8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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'),
];
}
}