Neuer Schalter „Bewusst ohne Kategorie“ in der Buchungsmaske für
Abschreibungen und rein rechnerische Solarerträge. Solche Buchungen
erscheinen nicht unter den offenen Vorgängen im Cockpit, nicht im
Prüflauf des Monatsabschlusses, setzen das Konto in der Kontenübersicht
nicht fett und werden von der Regelanwendung sowie dem automatischen
Zusammenführen zu Umbuchungen ausgelassen. Kommt eine Kategorie, ein
Gegenkonto oder eine Splitbuchung hinzu, entfällt die Markierung.
Migration 028_bewusst_ohne_kategorie.sql, Test 59 und E2E-Test.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Status „wartet auf Freigabe“, solange die Bank auf TAN/Namensabgleich wartet
- Abbruch der Freigabe (auch durch neuen Sendeversuch) im Übermittlungsprotokoll
als „abgebrochen“ festhalten, Auftrag als fehlgeschlagen vermerken
- Aufträge mit Übermittlungsprotokoll nur stornieren, nicht löschen
- Migration 025, PHP-Test 57, E2E-Spec zahlungsfreigabe
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nennt die Bank bei der TAN-Abfrage einen Startcode für den TAN-Generator,
geht er im Fließtext leicht unter. StartcodeErkennung erkennt ihn über
einen pro Bankverbindung konfigurierbaren Beispielsatz (Ziffernfolge =
Platzhalter für den Code) und zeigt den Fund fett, zentriert und in
eigener Zeile. BankFreitext löst dafür die bisherige Klartext-Aufbereitung
aus FinTsUeberweisung::vopHinweis() heraus, damit TAN-Anfrage und
VoP-Rückmeldung dieselbe HTML-zu-Klartext-Umwandlung nutzen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Elf Listenansichten (Klassen, Buchungsvorlagen, Regelmäßige Buchungen,
Erinnerungen, Verträge, Adressen, Sparziele, Kredite, Abgleichregeln,
Budgets, Berichtsgruppen) zeigten das Formular unter der Liste. Jetzt
öffnet der Knopf „+ Neu“ es als Dialog.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Depot der Bank wird einem Depot im Finanzmanager zugeordnet (Migration 022)
- Bestand einbuchen: Ein-/Auslieferungen aus dem Bankbestand, Stichtag per Dialog
- Zuordnungsliste: Depots nur noch als Wertpapiergeschäft
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
.umsatztext hatte in der Flex-Zeile .umsatzkopf keinen flex-grow, wodurch
justify-content: space-between die Restfläche auf beide Zwischenräume
verteilte – der Text schwebte dadurch zentriert zwischen Ankreuzfeld und
Betrag statt linksbündig am Ankreuzfeld zu stehen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Die Summenzeile der Splitbuchungen (Buchungsmaske und Splitdialog im
Kontoblatt) zeigt jetzt den noch offenen Restbetrag zum Buchungswert statt
der Summe der Zeilen. „Speichern" bleibt gesperrt, solange Splitzeilen
befüllt sind und der Restbetrag nicht Null ist; ohne Splitzeilen (auch mit
direkter Kategorie/Gegenkonto) bleibt der Knopf wie bisher an.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Toggle „Regel anlegen“ in der Buchungsmaske (Fix#94); beim Speichern
entsteht daraus eine Regel (AbgleichRegel::ausBuchung()), die das
Kontoblatt danach in einem modalen Dialog zum Prüfen und Anpassen zeigt.
Abbruch (auch per Escape) verwirft die Regel wieder, Speichern übernimmt
Änderungen. Die Regelfelder sind aus regeln.php in regelfelder.php
ausgelagert, damit beide Formulare dieselbe Bauart teilen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Die Spalte heißt nur noch „Anteil“; darunter steht die Summe der Anteile,
die sich mit jeder Eingabe in derselben Tabelle neu berechnet.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
In der Buchungsmaske sperrt eine Eingabe in den Splitzeilen sofort
Kategorie / Gegenkonto und Klasse, und umgekehrt sperrt eine Kategorie
oder Klasse alle Splitzeilen. Der neue Knopf „Splitbuchungen löschen“
rechts über der Splittabelle leert alle Zeilen und gibt die direkten
Felder wieder frei.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bei einer Splitbuchung zeigt die Klassenspalte jetzt die gemeinsame Klasse
der Splitzeilen. Unterscheiden sie sich, steht dort die Marke „Splitbuchung“,
der Tooltip nennt je Splitzeile Kategorie und Klasse. Ein Klick auf die
Klassenzelle einer Splitbuchung öffnet den Splitdialog.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Jeder Legendeneintrag der Cockpit-Kacheln führt zu den Buchungen, aus denen
sich sein Wert zusammensetzt: Kategorien, „Nicht kategorisiert“ und „Übrige“
in „Meine Ausgaben“, Einnahmen/Ausgaben/Saldo in „Einnahmen und Ausgaben“,
Konten der Vermögensentwicklung ins Kontoblatt. Ziel ist der Drilldown der
Auswertungen mit dem Filter der Kachel; zeilenbuchungen() kennt dafür einen
Art-Filter, „alle Bewegungen“ und mehrere Kategorien.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Liegen zwei Buchungen, die eigentlich derselbe Vorgang sind, zu weit
auseinander oder gehörte eine ursprünglich einem anderen Ursprungskonto,
findet der automatische Abgleich sie nicht – die Umbuchung und ihre
einzeln erfasste Dublette stehen dann dauerhaft nebeneinander im
Kontoblatt.
Buchung::verknuepfen() führt eine Umbuchung (eigene Seite oder
Gegenseite auf diesem Konto) und eine einzeln erfasste Buchung mit
passendem Betrag zusammen: Die Umbuchung bleibt, die Dublette fällt
weg, ihr Bankumsatz hängt sich an die Umbuchung. Im Kontoblatt lässt
sich dafür jetzt auch die Gegenseite einer fremden Umbuchung ankreuzen;
ein neuer Knopf „Verknüpfen“ nutzt dieselbe Auswahl wie „Auswahl
löschen“.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Der Überweisungsdialog bietet das Häkchen „Echtzeitüberweisung“. SEPA
behandelt sie als eigenes Verfahren: Über FinTS geht der Auftrag als HKIPZ
(SendSEPARealtimeTransfer) statt als HKCCS hinaus, die pain.001-Nachricht
trägt die Zahlungsart LclInstrm/Cd = INST (nur im ISO-Format
pain.001.001.03). Eine Echtzeitüberweisung hat keinen Ausführungstermin;
bietet die Bank sie nicht an, scheitert der Auftrag mit klarer Meldung,
eine stille Umwandlung in eine gewöhnliche Überweisung ist abgeschaltet.
Neue Spalte zahlungsauftraege.echtzeit (Migration 019), Test 43 und ein
E2E-Test für das Sperren des Termins.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Der gesamte FinTS-Dialog (gesendete und empfangene Meldungen) wird je Durchlauf
in bank_protokolle gespeichert, im Erfolgs- wie im Fehlerfall. Im Zahlungsverkehr
öffnet der Status das Protokoll der Überweisung als modalen Dialog; unter
Online-Banking › Protokoll gibt es das Gesamtprotokoll mit Filter nach Bank,
Datum und Freitext.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Das Adressbuch bekommt in der Verwaltung eine eigene Kachel statt nur
über die Verträge erreichbar zu sein, denn es speist auch den
Zahlungsverkehr. Auf der Adressliste klappt zu jeder Adresse ein
<details>-Element ihre letzten Buchungen auf (Buchung::letzteFuerEmpfaenger,
kontenübergreifend nach dem exakten Empfängernamen – die Buchung führt
kein Fremdschlüsselfeld auf die Adresse).
Die Empfängerauswahl im Zahlungsverkehr-Formular ist jetzt ein Typeahead:
kombobox.js (bereits für die Kategorie im Kontoblatt im Einsatz) baut das
<select> in ein gefiltertes Eingabefeld um. Geprüft (PHP- und E2E-Tests),
dass "Empfänger ins Adressbuch übernehmen" beim Erfassen einer
Überweisung tatsächlich eine Adresse anlegt.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Kategorie-Filter und Schnellzuordnung tragen jetzt data-kombobox: kombobox.js
baut das <select> beim Laden in ein Eingabefeld mit gefilterter, aufklappender
Liste um, ohne Verhalten oder Markup für vorhandenen Code (kontoblatt.js) zu
ändern. Die Klassen-Auswahl bleibt bewusst ein gewöhnliches <select> – ihre
Liste ist kurz.
Das Ändern von Kategorie oder Klasse im Kontoblatt lud bisher die ganze
Seite neu, um die Zeile zu aktualisieren – dabei sprang der Bildschirm
nach ganz oben. kontoblatt.js schickt die Auswahl jetzt per fetch im
Hintergrund; Kategorie, Klasse und das Symbol der Bargeld-Abgleichspalte
aktualisieren sich an Ort und Stelle, die Bildlaufposition bleibt stehen.
Ohne JavaScript bleibt es bei der bisherigen Weiterleitung.
Beim Zuweisen einer Kategorie fragt der Finanzmanager beim Bargeld-Tool
(FSCash) nach, ob es zum Betrag dort schon eine Buchung gibt.
Eingerichtet wird das unter Verwaltung → Bargeld-Tool: Adresse,
Zugangsdaten (Passwort AES-verschlüsselt), Suchzeitraum und die Auswahl
der abzugleichenden Kategorien. Die Vormerkung steht als
`bargeld_abgleich` an der Kategorie selbst, nicht als Nummernliste in den
Einstellungen – so verschwindet sie mit der Kategorie.
Geprüft wird nur, was geprüft werden soll: Kategorie an der Buchung,
Kategorie vorgemerkt, Adresse konfiguriert. Fällt eines weg, verschwindet
der Status. Gesucht wird rückwärts ab dem Buchungsdatum, weil Bargeld
ausgegeben wird, bevor der Umsatz auf dem Konto ankommt.
Im Kontoblatt steht das Ergebnis zwischen Klasse und Betrag: grauer Kreis,
grüner Haken, rotes X, Ausrufezeichen. Das Ausrufezeichen behält die
Textfarbe des Farbschemas – der Fehler liegt beim Abruf, nicht bei der
Buchung. Ohne hinterlegte Adresse entfällt die Spalte.
Ein Fehlschlag ist ein Ergebnis, kein Abbruch: Die Kategorie wird auch
dann gespeichert, wenn das Bargeld-Tool schweigt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Klasse .rechts wurde in Listen von der spezifischeren Grundregel
"table.liste th, table.liste td { text-align: left }" überstimmt – die
Ausrichtung war also überall wirkungslos, nicht nur in den Berichten. Die
Regel steht jetzt bei den Tabellen-Grundregeln und gilt für alle Listen:
Kontenübersicht, Kontoblatt, Wertpapiere, Depotbuchungen, Kategorien und
die Berichte. Die berichtseigene Sonderregel entfällt dadurch.
Budgetplaner und Splittabellen bringen ihre eigene Ausrichtung mit und
bleiben unberührt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Linksbündig wirkte die schmale Tabelle verloren neben dem zentrierten
Berichtskopf. Sie steht jetzt mittig unter Überschrift und Zeitraumzeile;
die Zahlenspalten bleiben in sich rechtsbündig. Der E2E-Test prüft, dass
links und rechts gleich viel Luft bleibt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Berichtstabellen nehmen nur noch den Platz, den ihre Spalten brauchen, und
stehen links; erst bei mehr Inhalt wachsen sie bis zur vollen Breite. Im
Scrollrahmen .breittabelle bleibt es beim bisherigen Verhalten, damit die
zwölf Monatsspalten weiter waagerecht scrollen statt umzubrechen.
Dabei kam heraus, dass die Zahlenspalten gar nicht rechtsbündig standen:
.rechts und .betrag sind nur einfach spezifisch, das weiter oben stehende
"table.liste th, table.liste td { text-align: left }" gewann. Für Berichte
steht die Ausrichtung jetzt ausdrücklich, sodass die letzte Spalte ihre
Beträge an der eigenen Kante ausrichtet.
Nachgezogen: Der E2E-Test der eingeklappten Seitenleiste erwartete
toBeHidden() für die Beschriftungen, die aber mit Absicht nur per clip-path
aus dem Bild geschoben werden – für Playwright bleiben sie sichtbar. Geprüft
wird jetzt, dass sie keinen Platz mehr einnehmen und der Verweis seinen
zugänglichen Namen behält.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Marke oben in der Seitenleiste trägt jetzt das Coinstack-Symbol aus den
Altdaten und den zweifarbigen Schriftzug Finanz|manager – wie die
sidebar-brand im Steuerkram. Sie ist zugleich der Schalter: Ein Klick schiebt
die Leiste von 232 px auf 64 px zusammen, ein Klick auf das Symbol klappt sie
wieder auf. Die Menüpunkte behalten dabei Ziel und Symbol.
Der Zustand steht in einem Cookie und nicht im localStorage: So rendert der
Server die Leiste schon in der richtigen Breite, statt sie bei jedem
Seitenwechsel kurz breit aufblitzen zu lassen. Die Beschriftungen wandern
eingeklappt per clip-path aus dem Bild statt per display:none – sonst
verlören die Verweise ihren Namen für Vorleseprogramme.
Nebenbei: Die Marke hieß bisher .marke, wie die kleine Statusmarke weiter
unten im Stilblatt, deren Regeln sie überschrieben. Sie heißt jetzt
.seitenleisten-marke.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Neue Buchung und Buchung bearbeiten zeigen oben das Konto, in dem die
Buchung liegt. Die Maske steht zweispaltig, die Beschriftungen links
neben ihren Eingaben und die Erklärungen in deren Tooltip – damit endet
sie samt Splitzeilen und Knopfleiste oberhalb der Fensterhöhe.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Konto bearbeiten und Neues Konto zeigen ihre vierzehn Felder in zwei
Spalten, damit alles ohne vertikales Scrollen auf einen Bildschirm passt.
- Neue Formularvariante .formular.zweispaltig: Grid mit zwei Spalten, je
Feld ein .feld aus Beschriftung, Eingabe und Hinweis. Überschriften,
Knopfleiste und .feld.ganz laufen über beide Spalten, unter 720 px
fällt das Formular auf eine Spalte zurück.
- Feldreihenfolge zeilenweise; Namen, Werte und Feld-IDs unverändert.
- E2E-Test: Kontoart steht rechts neben dem Namen, das Formular endet
oberhalb der Fensterhöhe.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Aus der Kachel QIF-Import wird Import/Export mit je einem Knopf für beide
Richtungen; davor steht die Wahl des Dateiformats (QIF oder CSV), die als
Dialog und ohne Skript als eigene Seite funktioniert.
- CsvBuchungsImport/CsvTabelle: Buchungen samt Splitzeilen, Spalten über die
Kopfzeile, dieselbe Dublettenerkennung und der Trockenlauf wie beim QIF.
- BuchungsExport/ExportController: Filter nach Zeitraum, Konto, Kategorie und
Klasse; die Datei entsteht im Speicher, ein Exportverzeichnis gibt es nicht.
- Housekeeping: Hochgeladene Importdateien und data/tmp werden nach der
eingestellten Frist gelöscht (Vorgabe 14 Tage, 0 schaltet ab).
Migration 013, Test 29 sowie E2E-Spec importexport.spec.js.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Umsatzlisten haben jetzt dieselbe Mehrfachauswahl wie ein Kontoblatt:
ein Ankreuzfeld vor jedem Umsatz, eines in der Titelleiste für alle
angezeigten und darüber der Knopf „Auswahl löschen“. Er steht in jedem
Reiter – offen, übernommen und verworfen –, nennt die Anzahl der Auswahl
und bleibt ohne Auswahl gesperrt. Bisher ließ sich ein abgerufener Umsatz
nur übernehmen oder verwerfen; wegräumen ging gar nicht.
Gelöscht wird allein die abgerufene Zeile. Eine daraus entstandene
Buchung gehört ins Kontoblatt und bleibt dort stehen – wer sie loswerden
will, löscht sie dort, und dann kehrt ihr Umsatz ohnehin in die
Vorschlagsliste zurück. Mit dem Umsatz geht aber sein Fingerabdruck: Was
im nächsten Abrufzeitraum liegt, kommt danach wieder herein, bei einem
verworfenen Umsatz also erneut als offen.
- Neue Route POST /banking/umsaetze/loeschen auf
Bankumsatz::mehrereLoeschen(); der Status hängt am Formularziel, sodass
der Weg in denselben Reiter zurückführt. Ohne JavaScript weist der
Controller eine leere Auswahl ab.
- Die Liste ist keine Tabelle, sondern eine Folge von Karten. Die
Kopfzeile, die eine Tabelle von selbst hätte, gibt es deshalb neu als
.listenkopf; die Mechanik dahinter (.alle-waehlen mit data-waehlt) ist
unverändert die des Kontoblatts.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Klassenspalte ist anklickbar wie die Zuordnung daneben: Ein Klick
öffnet die Klassenliste in der Zelle, die Auswahl wird sofort über
POST /buchungen/{id}/klasse gespeichert. Buchung::klasseSetzen() lässt
Kategorie, Gegenkonto und Splitzeilen unberührt.
Die Buchungszeilen sind jetzt alle zwei Textzeilen hoch, ihr Inhalt steht
senkrecht in der Mitte. Was nicht auf zwei Zeilen passt, wird
abgeschnitten; den vollständigen Text zeigt der Tooltip – bei Empfänger
und Buchungstext nur dort, wo wirklich etwas fehlt, über dem
Kategoriefeld einer Splitbuchung deren Zeilen mit Kategorie und Betrag.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Eine Regel kann jetzt eine Splitbuchung vorgeben: mehrere Kategorien mit einem
Anteil in Prozent. Greift sie, wird der Umsatz in diesem Verhältnis aufgeteilt –
bei jedem Betrag neu gerechnet, sodass eine Abrechnung über 300 € und eine über
450 € nach demselben Schlüssel gebucht werden.
Das Schema lag bereits im Modell und in der Datenbank, war über die Oberfläche
aber nicht erreichbar; die Dokumentation beschrieb ein Feld, das es nirgends zu
sehen gab.
- Unter jeder Regel klappt „Splitbuchung“ die Zeilen auf: Kategorie, Klasse,
Notiz, Anteil. Dasselbe Formular steht bei „Neue Regel“ – beide binden
src/Views/banking/regelsplits.php ein.
- Die Anteile gelten zueinander, nicht absolut: 60 zu 30 sind zwei Drittel zu
einem Drittel. Bisher hätte die letzte Zeile als Rest 40 statt der
eingetragenen 30 Prozent bekommen, und der Fehler wäre in der fertigen
Buchung nicht mehr zu sehen gewesen.
- Im Abgleichdialog zeigt der Vorschlag die errechneten Zeilen und schickt sie
mit. Zuvor gingen sie beim Knopf „Als neue Buchung“ verloren: Das Formular
kannte nur Kategorie und Klasse, sodass von Hand übernommene Umsätze
ungeteilt im Kontoblatt landeten. Der automatische Lauf war nie betroffen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Name in Bestandsübersicht, Depotbuchungen und Stammdaten führt jetzt auf
/wertpapiere/papier/{id}: Kennzahlen über die ganze Historie, Stammdaten und
Kurs, Bestand je Depot, Wertentwicklung und die Buchungen eines Zeitraums.
Depot::bestand() und Depot::entwicklung() nehmen dafür eine Wertpapiernummer
entgegen – die Detailseite rechnet nicht selbst, sondern bekommt dieselben
Zahlen wie die Übersicht. Neu sind Wertpapier::kurseckwerte() und
Depotbuchung::datumsgrenzen().
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Bankabruf bringt die Wertpapierabrechnung als Umsatz auf dem Girokonto, und
erst dort entscheidet sich, dass es ein Kauf war. Wer die Buchung einem Depot
zuordnete, buchte bisher eine Umbuchung – ohne Stückzahl, ohne Kurs, ohne
Einstand. Die Zuordnungsliste im Kontoblatt kennt jetzt neben Kategorie und
Gegenkonto eine dritte Gruppe "Wertpapiergeschäft im Depot", die statt zu
speichern die Wertpapiermaske öffnet; ohne JavaScript führt derselbe Weg auf
/buchungen/{id}/wertpapier.
Die Maske ist auf den "Wertpapier kaufen"-Dialog des FinanzManagers
zugeschnitten: vorne Vorgangsart, Datum, Wertpapier, Stück und Kurs, dahinter
hinter dem Knopf "Kosten …" die Nebenkosten nach Arten – sechs Gebühren und
sechs Steuern. ISIN und WKN werden aus dem Verwendungszweck gelesen, ein
bekanntes Papier ist damit vorausgewählt. Ein Abfluss vom Konto kann nur ein
Kauf sein, ein Zufluss ein Verkauf oder eine Dividende.
Der Buchungsbetrag ist die feste Größe: Die Nebenkosten werden aus ihm
herausgerechnet, was übrig bleibt ist der Kurswert und damit der
Einstandspreis. Im Kontoblatt entsteht eine Splitbuchung mit je einer Zeile pro
belegter Kostenart und dem Rest als Umbuchung ins Depot; ohne Nebenkosten
bleibt es bei der schlichten Umbuchung. Die Depotbuchung hängt sich an die
vorhandene Buchung, statt eine zweite anzulegen (neue Spalte
depot_buchungen.buchung_erzeugt) – wird sie gelöscht, bleibt die Buchung der
Bank stehen und ist nur wieder unzugeordnet.
Die Kategorien der Kostenarten liegen im Einstellungsdialog unter "Wertpapiere",
einmalig je Art; für "Sonstige Kosten" ist die Einstellung nur die Vorgabe und
im Dialog überschreibbar. Arten ohne Kategorie werden zu Splitzeilen ohne
Zuordnung, nicht zu einem Fehler.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Abrufzeitraum kannte bisher nur Spannen. Der Stichtag steht jetzt an zwei
Stellen: als Vorgabe der Bankverbindung (neuer Abrufzeitraum "Ab Stichtag" mit
Datum in bank_zugaenge.abruf_stichtag) und als einmalige Angabe neben "Umsätze
abrufen", die der Vorgabe vorgeht und nichts speichert.
Der einmalige Stichtag liegt im Abrufzustand, nicht in der Datenbank: Nach einer
TAN-Runde läuft der Abruf im nächsten Request weiter und muss dort denselben
Zeitraum holen wie beim Start.
"Ab Stichtag" ohne Datum und unlesbare Datumsangaben werden abgewiesen; ein
Stichtag in der Zukunft wird auf heute gesetzt, statt den Abruf leer ausgehen zu
lassen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Seitenleiste war lang geworden. Termine und Verträge sind kein täglicher
Einstieg und stehen deshalb nicht mehr im Hauptmenü, sondern als letzte
Kacheln in der Verwaltung.
- Menüeinträge können weitere Pfade mitführen (`auch`), unter denen sie als
aktiv gelten – die Verwaltung leuchtet damit auch unter /termine und
/vertraege, wo die Seitenleiste sonst ohne Markierung bliebe.
- Neue Kacheln Termine (aktive Reihen, offene Erinnerungen) und Verträge
(laufende Verträge, Fristen der nächsten 90 Tage).
- Alle Kacheln der Verwaltung tragen jetzt dieselben kleinen Knöpfe; vorher
standen zwei Größen nebeneinander im selben Raster.
- Das Raster richtet seine Knopfleisten am Kachelfuß aus, statt sie der
jeweiligen Textlänge folgen zu lassen.
- .knopfleiste bricht um, statt über den rechten Kachelrand zu ragen.
Test: tests/24_NavigationTest.php
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Eine Umbuchung war auf dem Gegenkonto nicht mehr zuzuordnen: Die Zeile trug die
Marke „Umbuchung“, die Kategoriespalte daneben blieb leer. Die Daten waren
richtig, die Anzeige verschwieg sie. In der Kategoriespalte steht jetzt auch in
der Gegensicht das Konto in eckigen Klammern, von dem die Umbuchung kommt – die
Abfrage lieferte es längst mit.
Kategorie und Gegenkonto stehen in einem Feld (`Views/buchungen/zuordnungsliste.php`):
Unter den Kategorien stehen die eigenen Konten in eckigen Klammern, wie im
FinanzManager, dessen Kategoriefeld `[Konto]` annimmt. Eines davon macht die
Buchung zur Umbuchung; die Auswahl „Ausgabe / Einnahme“ bestimmt seither nur
noch die Richtung. Dieselbe Liste steht in den Splitzeilen – eine Splitzeile mit
Gegenkonto ließ sich bisher nur im Import anlegen und ging beim Bearbeiten der
Buchung stillschweigend verloren.
Schnellzuordnung: Ein Klick auf die Kategoriespalte öffnet die Liste in der
Zelle, die Auswahl speichert sofort (POST /buchungen/{id}/zuordnung) und kommt
in dieselbe Ansicht zurück. Die Liste gibt es einmal und wandert in die
angeklickte Zelle – eine Liste je Zeile wären bei hundert Zeilen ebenso viele
vollständige Kategoriebäume im HTML. Feld und Liste sind gleich breit und gleich
hoch, sonst rückte beim Anklicken die halbe Zeile. Ohne JavaScript führt
derselbe Klick in die Buchungsmaske: Die Zelle ist ein Link. Die Gegenseite
einer fremden Umbuchung führt zu ihrer Buchung auf dem anderen Konto.
Der Eintrag „Splitbuchung“ öffnet ein modales Fenster mit Zeilen für Kategorie
oder Gegenkonto, Klasse, Notiz und Betrag; der Restbetrag wird mitgerechnet. Ein
Klick auf eine bereits gesplittete Buchung öffnet direkt den Dialog. „Splitbuchung
löschen“ verwirft alle Zeilen samt ihren Zuordnungen – auch die Gegenseite einer
Splitzeile mit Gegenkonto –, die Buchung steht danach unzugeordnet im Kontoblatt.
Beide Wege gehen über `Buchung::zuordnen()` und `Buchung::splitsErsetzen()`,
achten den Monatsabschluss und lassen den Rest der Buchung unberührt.
`public/static/betrag.js` bündelt das Lesen deutscher Beträge und die
Restbetragsrechnung für Maske und Kontoblatt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Kontenzuordnung als dritter Einrichtungsschritt: Welches Bankkonto gehört zu
welchem eigenen Konto? Umsätze merken sich über `bank_konto_id`, woher sie
stammen, und ziehen mit, wenn die Zuordnung erst nach einem Abruf fällt.
Abgerufene Umsätze buchen sich auf Wunsch selbst (`Services\Bankabgleich`).
Im Kontoblatt lassen sich Buchungen sammelweise löschen; Statusmeldungen liegen
jetzt über der Ansicht, statt den Inhalt springen zu lassen.
Dazu drei Fehler, die zusammen dafür sorgten, dass abgerufene Umsätze spurlos
verschwanden – der Abruf meldete sie als vorhanden, das Kontoblatt zeigte
nichts, und in der Vorschlagsliste standen sie ebenfalls nicht:
- Eine gelöschte Buchung ließ ihren Umsatz auf „uebernommen“ stehen. Der
Fremdschlüssel setzte nur `buchung_id` auf NULL. `Buchung::loeschen()` gibt
den Umsatz jetzt vorher frei, `Bankumsatz::verwaisteOeffnen()` fängt die Wege
ab, die daran vorbeiführen – Kaskaden lösen in MariaDB keine Trigger aus.
- Ein Bankkonto entstand doppelt, wenn die Bank die IBAN nicht bei jedem Dialog
mitliefert. Gesucht wird jetzt über die Kontonummer; eine nachgelieferte IBAN
wird am vorhandenen Eintrag nachgetragen.
- Der Fingerabdruck hing an der IBAN und kippte mit ihr. Er nimmt jetzt die
`bank_konto_id`, die fest steht, solange es den Bankzugang gibt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Bank lässt sich erst nach ihren TAN-Verfahren fragen, wenn die
Zugangsdaten gespeichert sind. Das Anlegen führt deshalb über „Weiter“
direkt auf die Verfahrensseite, und die holt die Liste selbst – ein
Knopf davor wäre ein Schritt, dessen Ergebnis feststeht.
Scheitert die Abfrage, bleibt das Ergebnis in der Sitzung, damit nicht
jeder Seitenaufruf wieder in dieselbe Zeitüberschreitung läuft; die ist
für die Abfrage kürzer gesetzt als in der Bibliothek.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>
Fünf Berichtstypen wie im FinanzManager – Summen-, Buchungs-, Vergleichs-,
Kontostands- und Budgetbericht – mit Filterleiste, gespeicherten Berichten in
Berichtsgruppen, Drilldown in die Buchungen und CSV-Export.
Ein Bericht speichert nur seine Frage; die Zahlen entstehen bei jedem Aufruf neu
aus den Buchungen. Gezählt werden Bewegungen (gesplittete Buchungen über ihre
Splitzeilen), Umbuchungen bleiben außen vor, Unkategorisiertes bekommt eine
eigene Zeile. Im Ausgabenabschnitt steht der Betrag ohne Minus wie im Original,
die Schlusszeile rechnet mit den echten Vorzeichen.
Einzelheiten in docs/auswertungen.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>