Finanzmanager/docs/nebenmodule.md
fds2610-bot f388d04c05 Phasen 4 bis 7: Cockpit, Online-Banking, Wertpapiere, Nebenmodule
Damit ist der geplante Funktionsumfang beisammen.

Phase 4 abgeschlossen
- Konfigurierbare Cockpit-Kacheln; abgewählte werden nicht berechnet
- Einnahmen/Ausgaben je Monat als Balkenpaare mit Saldolinie, aufgesetzt auf
  den Summenbericht statt auf eine eigene Abfrage
- Meine Ausgaben als Ring auf der obersten Kategorieebene
- Offene Vorgänge aus allen Modulen

Phase 5 – Online-Banking
- nemiah/php-fints als Fork auf Codeberg, psr/log direkt eingebaut: die
  Anwendung hängt an keinem fremden Update-Zyklus
- PIN AES-256-GCM-verschlüsselt; Schlüssel aus APP_KEY oder aus
  data/schluessel/app_key, den der Entrypoint einmalig erzeugt
- TAN-Dialog über mehrere Requests (FinTs::persist plus serialisierte Aktion
  in der Sitzung) – ein wartender Prozess wäre mit php-fpm der falsche Weg
- Abgleich statt Direktbuchung: verbinden, übernehmen oder verwerfen
- Regeln mit vier Vergleichsarten, Betragsgrenzen und Split-Schema

Phase 6 – Wertpapiere
- Depotbuchung und Geldbuchung als zwei Seiten eines Geschäfts; betrag ist
  der Bruttowert, Nebenkosten stehen daneben
- Einstand nach gleitendem Durchschnitt, realisierte Gewinne, Erträge
- Kursabruf über Leeway oder FMP, täglicher Lauf per Cron
- QIF-Import für !Type:Invst

Dabei behoben: Der Import buchte den Geldfluss jedes Wertpapiergeschäfts als
Abgang – auch bei Verkäufen und Dividenden; und er erkannte das
Verrechnungskonto nicht, wenn dem Konto im L-Feld eine Kategorie vorangeht
(bei Verkäufen also immer).

Phase 7 – Nebenmodule und Zahlungsverkehr
- Buchungsvorlagen inklusive QIF-Import, Splits werden mitskaliert
- Regelmäßige Buchungen mit Fälligkeitslauf, Finanzkalender, Erinnerungen
- Adressen mit IBAN-Prüfung, Verträge mit Kündigungsfrist, Sparziele
- Kredite mit gerechnetem Tilgungsplan
- Überweisungen über FinTS; die Buchung entsteht erst nach Annahme durch die
  Bank. Die pain.001-Nachricht erzeugt SepaXml selbst

Nebenbei: .dockerignore ergänzt (ohne sie brach der Build an data/mariadb ab),
PlatzhalterController entfernt, zwei Inline-Handler beseitigt, die die
Content-Security-Policy ohnehin blockierte.

888 PHP-Prüfungen und 45 E2E-Tests grün.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 06:59:24 +02:00

145 lines
6.6 KiB
Markdown
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.

# Nebenmodule und Zahlungsverkehr
Was in Phase 7 dazugekommen ist: Buchungsvorlagen, regelmäßige Buchungen mit
Finanzkalender, Erinnerungen, Adressen, Verträge, Sparziele, Kredite und der
Zahlungsverkehr.
## Buchungsvorlagen
Eine Vorlage ist eine fertige Buchung ohne Datum. Sie kommt aus dem QIF
(`!Type:Memorized` – im Beispielexport 579 Stück, vom FinanzManager automatisch gemerkt)
oder entsteht aus einer vorhandenen Buchung.
**Splitzeilen werden mitskaliert.** Weicht der Betrag beim Buchen von dem der Vorlage ab,
ziehen die Splitzeilen im gleichen Verhältnis mit; die letzte bekommt den Rest, damit die
Summe auf den Cent zum Buchungsbetrag passt. Ohne das ließe sich eine Vorlage mit Splits
nur zu ihrem ursprünglichen Betrag buchen.
Die Liste sortiert nach Häufigkeit: Wer eine Vorlage sucht, sucht meist eine, die er schon
oft gebraucht hat.
Beim Import entsteht der **Name** aus Empfänger und Betrag – die QIF-Sektion führt keinen.
Kommt derselbe Name mehrfach vor, zählt ein Zähler hoch, statt Vorlagen stillschweigend zu
verschlucken.
## Regelmäßige Buchungen
Jede Reihe führt ihre **nächste Fälligkeit** mit sich. Der Fälligkeitslauf holt, was
ansteht, bucht es und schreibt das Datum fort. Eine Tabelle vorausberechneter Termine gibt
es bewusst nicht: Sie wäre bei jeder Änderung neu zu erzeugen.
Zwei Betriebsarten:
* **automatisch** – wird ohne Rückfrage gebucht. Für Miete und Gehalt, wo Betrag und
Termin feststehen.
* **auf Bestätigung** – wird nur gemeldet und wartet auf Knopfdruck. Für alles, dessen
Betrag schwankt.
Der Lauf ist gutmütig gegenüber langen Pausen: Liegen mehrere Termine zurück, wird **jeder
einzeln** gebucht, nicht einer für alle – nur so stimmen die Monatssummen. Nach dem Buchen
rückt die Fälligkeit so weit vor, bis sie in der Zukunft liegt.
In einen **abgeschlossenen Monat** wird nicht hineingebucht: Die Reihe bleibt stehen und
meldet sich, statt den ganzen Lauf mit einer Ausnahme abzubrechen.
*Überspringen* rückt vor, ohne zu buchen – für den Monat, in dem die Zahlung einmal
ausgesetzt wurde.
## Finanzkalender
Zusammengetragen aus vier Quellen: fällige regelmäßige Buchungen, offene Erinnerungen,
ablaufende Kündigungsfristen und terminierte Überweisungen. Alles gerechnet, nichts
gespeichert – eine Änderung an einer Reihe wirkt sich sofort aus.
Überfälliges bleibt sichtbar und wird markiert, statt aus der Liste zu fallen.
## Adressen und IBAN-Prüfung
Das Adressbuch speist die Empfängerauswahl im Zahlungsverkehr. **IBANs werden geprüft**
(ISO 13616: Länge je Land, Prüfziffer modulo 97). Das fängt Zahlendreher ab, bevor eine
Überweisung hinausgeht – die häufigste und ärgerlichste Fehlerquelle im Zahlungsverkehr.
Gerechnet wird stückweise mit `%` statt mit `bcmod`: Die BC-Erweiterung ist keine
Standardausstattung, und ein Modulo über sieben Ziffern lange Blöcke kommt ohne sie aus.
## Verträge
Der Nutzen liegt in der **Kündigungsfrist**: Die Übersicht zeigt, bis wann gekündigt sein
muss, damit sich ein Vertrag nicht stillschweigend verlängert. Verträge, deren Frist in den
nächsten 90 Tagen abläuft, stehen oben auf der Seite und im Finanzkalender.
Der **Jahresbetrag** rechnet verschieden getaktete Verträge vergleichbar: monatlich × 12,
vierteljährlich × 4 und so fort.
Ein Vertrag kann mit einer regelmäßigen Buchung verbunden sein, die seine Zahlung erledigt.
## Sparziele
Der erreichte Stand kommt **aus dem Kontosaldo**, nicht aus einem eigenen Zähler – ein
zweiter, gepflegter Wert liefe früher oder später von den Buchungen weg. Der Startbetrag
zieht ab, was zu Beginn schon auf dem Konto lag.
Zum Zieldatum rechnet die Anwendung aus, welche Monatsrate nötig wäre, um den Termin noch
zu halten.
Der Fortschrittsbalken ist ein `<progress>`-Element: Ein eigener Balken bräuchte seine
Breite als `style`-Attribut, und das verbietet die Content-Security-Policy.
## Kredite
Gerechnet wird als **Annuitätendarlehen**: gleichbleibende Rate, sinkender Zinsanteil,
wachsende Tilgung. Zinsen fallen je Periode auf die Restschuld an.
Der Tilgungsplan wird **gerechnet, nicht gespeichert** – er ergibt sich vollständig aus
Betrag, Zins, Rate und Beginn. Eine jährliche Sondertilgung wird im Dezember verrechnet.
Deckt die Rate nicht einmal die Zinsen der ersten Periode, entsteht kein Plan, sondern ein
Hinweis: So ein Kredit würde wachsen statt zu schrumpfen, und eine Endlosschleife wäre die
schlechtere Antwort darauf.
Bei langen Laufzeiten zeigt die Tabelle die nächsten zwei Jahre und das Ende; dazwischen
steht, wie viele Raten ausgelassen wurden.
## Zahlungsverkehr
**Erst die Bank, dann die Buchung.** Ein Zahlungsauftrag ist zunächst ein Entwurf. Die
Buchung auf dem Auftragskonto entsteht erst, wenn die Bank den Auftrag angenommen hat –
vorher wäre sie eine Behauptung, die man nach einer abgelehnten TAN wieder einsammeln
müsste.
Ein gesendeter Auftrag lässt sich weder ändern noch löschen: Er bleibt als Beleg stehen.
Fehlgeschlagene tragen die Meldung der Bank daneben.
Ohne Ausführungstermin geht die Überweisung sofort hinaus, mit Termin als
Terminüberweisung; sie erscheint dann im Finanzkalender.
### SEPA-XML von Hand
php-fints erwartet die fertige **pain.001.001.03**-Nachricht und erzeugt sie nicht. Die
üblichen Erzeuger wären zwei weitere Abhängigkeiten für ein Dokument von sechzig Zeilen –
`Services\SepaXml` schreibt es deshalb selbst.
Der **SEPA-Zeichenvorrat** ist eng: `a–z A–Z 0–9 / - ? : ( ) . , ' +` und Leerzeichen.
Umlaute werden umgeschrieben (ä → ae), alles Übrige fällt weg. Ohne diese Umschrift weist
die Bank den Auftrag zurück – und zwar erst nach dem Absenden.
Der Verwendungszweck endet bei 140 Zeichen; das ist das SEPA-Maß, alles darüber würde die
Bank ohnehin abschneiden.
### TAN
Für Überweisungen verlangt jede Bank eine TAN. Der Dialog wird genauso über die Sitzung
fortgesetzt wie beim Abruf (siehe `docs/banking.md`): Zustand sichern, Maske zeigen, nach
der Eingabe weitermachen.
Beim Abbrechen bleibt der Auftrag als Entwurf stehen und lässt sich erneut senden.
## Tests
`tests/18_NebenmoduleTest.php` – Vorlagen mit skalierten Splits und aus Buchungen,
QIF-Vorlagenimport samt Idempotenz, Terminrechnung und Fortschreiben der Fälligkeit,
Fälligkeitslauf (nur automatische Reihen, wartende rücken nicht vor), Erinnerungen,
IBAN-Prüfung mit gültigen und falschen Nummern, Kündigungsfristen und Jahresbeträge,
Sparfortschritt aus dem Konto, Tilgungsplan (Annuität, letzte Rate, Sondertilgung,
zu kleine Rate), Zahlungsaufträge (Buchung erst nach Annahme, Unveränderlichkeit,
Eingabeprüfungen), SEPA-XML (Schema, Zeichensatz, Wohlgeformtheit) und der Finanzkalender.