Der Stichtag eines Kontos wurde gespeichert und angezeigt, von der
Saldo-Berechnung aber ignoriert: sie addierte jede Buchung des Kontos,
auch die aus der Zeit vor dem Stichtag. Damit lief jeder Saldo um die
gesamte Vorgeschichte daneben.
Der Anfangssaldo beschreibt jetzt den Stand am ENDE des Stichtags – so
steht er auf dem Auszug. Buchungen bis einschliesslich dieses Tages
zaehlen nicht mehr zum Kontostand, bleiben aber in Liste und
Auswertungen. Beim Uebertrag wird jede Seite an ihrem eigenen Stichtag
gemessen; der Vermoegensverlauf folgt derselben Regel. Ohne Stichtag
zaehlt weiterhin alles.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Stichtag eines Kontos wird von der Saldo-Berechnung ignoriert – das
Skript weist jetzt aus, wie viel aus Buchungen bis zum Stichtag stammt
und trotzdem mitzählt. Die Übertrags-Matrix nennt dazu Beispieltexte,
Erkennungstexte der Konten und Transfer-Schlagwörter, damit sich ein
falscher Übertrag seinem Auslöser zuordnen lässt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zeigt als Matrix, welches Konto an welches überträgt, dazu Überträge
ohne Zielkonto und Währungswechsel ohne Zielbetrag – Letztere schreiben
den Fremdbetrag unkonvertiert gut und verfälschen den Saldo.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zeigt je Konto Anfangssaldo, Einnahmen, Ausgaben und beide Transfer-
Richtungen einzeln, dazu mehrfach gebuchte Auszüge und doppelte
Buchungen. Damit lässt sich ein falscher Saldo auf seine Ursache
zurückführen, statt sie zu erraten.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Kategorie-Liste zeigt nur manuelle, einer bestehenden Kategorie zugeordnete
Regeln. Bleibt sie leer, obwohl Regeln in der Datenbank stehen, sagt das Skript
warum: Es schlüsselt den Bestand nach source, kind und is_transfer auf, zählt
Regeln ohne Kategorie sowie solche, deren Kategorie nicht mehr existiert, und
nennt die Zahl der tatsächlich sichtbaren.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bei 35 Sicherungen hilft eine blosse Liste wenig. Das Skript zeigt jetzt je
Sicherung Zeitpunkt, Schlagwörter, Budget-Vorlagen und wie viele Buchungen eine
Kategorie tragen – und nennt am Ende die neueste noch vollständige samt der
fertigen Befehle zum Zurückspielen. Tabellen, die es zum Sicherungszeitpunkt
noch nicht gab, erscheinen als '–' statt als Fehler.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Listet je Backup, wie viele Schlagwörter, Budget-Vorlagen und kategorisierte
Buchungen darin stecken. Nach einem Datenverlust sieht man damit auf einen Blick,
welche Sicherung noch vollständig ist – statt nach Zeitstempel zu raten.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Auf SQLite baut Alembic (render_as_batch) eine Tabelle um, indem es eine Kopie
anlegt und das Original löscht. Bei DROP TABLE führt SQLite ein implizites DELETE
aus – mit aktiven Fremdschlüsseln schlägt das per ON DELETE CASCADE auf abhängige
Tabellen durch.
Migration 0013 fügte `categories` nur ein Feld hinzu und vernichtete dabei alle
Schlagwörter und Budget-Vorlagen und setzte die Kategorie sämtlicher Buchungen
auf NULL. Reproduziert und behoben: Fremdschlüssel werden für die Dauer der
Migration abgeschaltet (vor der Transaktion, sonst ignoriert SQLite den Befehl)
und danach wieder aktiviert. Lässt sich das Abschalten nicht bestätigen, bricht
die Migration ab, statt Daten zu riskieren.
Regressionstest legt Daten auf Stand 0012 an, migriert auf head und prüft, dass
Schlagwörter, Budget-Vorlagen und Kategoriezuordnungen erhalten bleiben.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Kategorien erben ihre Art von der Gruppe, und die ist entweder Ausgabe oder
Einnahme. Für einen Kontoübertrag passt beides nicht: Auf dem einen Konto geht
Geld raus, auf dem anderen kommt es rein – man musste also zwei Kategorien in
zwei Gruppen anlegen.
Als „nicht in Auswertungen einrechnen" markierte Kategorien werden jetzt in
beiden Richtungen angeboten (Buchungsformular und Import-Prüfansicht), und ihre
Schlagwörter greifen unabhängig vom Vorzeichen. Eine Kategorie „Kontoübertrag"
in einer Ausgabe-Gruppe genügt damit für beide Seiten.
Test für beide Richtungen; 94 grün.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die Testdatenbank lebt über den ganzen Lauf; im laufenden Monat liegen also
schon Buchungen anderer Tests. Absolute Erwartungswerte gingen allein durch,
im Gesamtlauf nicht. Jetzt zählt die Differenz vorher/nachher. 93 grün.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Umbuchungen zwischen eigenen Konten sind keine Ausgabe – das Geld ist nicht weg,
es liegt woanders. Bisher blieb nur die Wahl zwischen einer echten Transfer-
Buchung (bildet die Wirklichkeit ab, braucht aber auf beiden Seiten passende
Regeln und schätzt bei Fremdwährung den Gegenwert) oder einer gewöhnlichen
Ausgabe, die Budget und Statistik verfälscht.
Kategorien haben jetzt den Schalter „Nicht in Auswertungen einrechnen": Die
Buchung wirkt weiter auf den Kontostand, bleibt aber aus Budget, Dashboard und
Auswertungen heraus. Gefiltert wird zentral in actual_expense_by_category und
income_by_category – damit greift es zugleich für Budget-Donut, Budget-
Fortschritt, Einnahmen/Ausgaben, Ausgaben-Anteile und die Budget-Seite.
Das ersetzt die Transfer-Paarung nicht, es ist der einfachere Weg: kein
Gegenkonto, keine Kursschätzung, dafür ohne Verbindung zwischen den beiden Seiten.
Migration 0013, Schalter im Kategorie-Dialog, Kennzeichnung in der Liste, Test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die Achse richtete sich rein nach den Daten: Beschriftungen wie „-3'065.06" sind
nicht ablesbar, und ohne feste Null sah man die Bewegung, aber nicht, ob man im
Plus oder Minus steht.
- Die Skala schließt die Null immer ein und ist optisch hervorgehoben
- Runde Schritte (1, 2, 2.5, 5 x Zehnerpotenz): 0 / 2'000 / 4'000 … statt
krummer Werte; nie feiner als ein Rappen, sonst entstünden bei leerem Konto
Zwischenwerte wie 0,0025
- Vermögensverlauf: Zeitraum als Karten-Option (30 T / 90 T / 6 M / 1 J)
Gilt für jedes Liniendiagramm, nicht nur den Vermögensverlauf.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Liegen mehrere Währungstausche im selben Zeitfenster, schnappte der zuerst
geprüfte Transfer der eigentlich gemeinten Zeile das Gegenstück weg – diese blieb
dann ohne Gegenkonto stehen. Jetzt gewinnt der Kandidat mit der geringsten
Datums- und Betragsabweichung.
Toleranz von 10 % auf 20 % erhöht: Wir schätzen die Gegenseite mit dem EZB-Kurs,
die Bank rechnet mit ihrem eigenen – und fehlt uns der Kurs, schätzen wir 1:1.
Ein echter Tausch lag damit schnell über 10 % daneben (CHF 150.00 -> EUR 165.60
sind 10,4 %), eine fremde Buchung trifft das Zeitfenster praktisch nie.
An den echten Auszügen: offene Zeilen im Revolut-EUR-Import von 3 auf 1 gesunken.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neue Karten-Option „Darstellung": Liste (Standard) oder Kreis. Dieselben Zahlen,
zwei Lesarten – die Liste nennt jeden Anteil genau, der Kreis zeigt die
Verteilung auf einen Blick. Nutzt den vorhandenen Donut, dessen Legende Betrag
und Anteil ohnehin schon ausweist.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Zeigt für den laufenden Budget-Monat, wie sich die tatsächlichen Ausgaben
prozentual auf die Kategorien verteilen – absteigend sortiert, mit Balken in der
Kategoriefarbe, Prozentwert und Betrag.
Anders als der Budget-Donut hängt sie nicht am geplanten Budget: Sie zeigt reine
Ist-Ausgaben, auch wenn für den Monat nichts geplant wurde. Umschaltbar zwischen
Kategorien (Standard) und Gruppen.
Die Anteile rechnet die Oberfläche aus Betrag und Summe – gerundete Prozente vom
Server addierten sich sonst nicht auf 100 %. Wird die Karte schmal, gibt zuerst
der Betrag nach; ohne Kategorienamen sagt die Zeile nichts mehr aus.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Bei mehreren hundert Zeilen ist der Knopf oben längst aus dem Bild gescrollt;
unter der Liste steht jetzt derselbe.
- Rückgängig gemachte Importe lassen sich aus dem Verlauf entfernen. Nur diese:
solange ein Import steht, ist sein Eintrag die einzige Möglichkeit, seine
Buchungen wieder loszuwerden – der Server lehnt das sonst ab.
Test für beide Fälle des neuen Endpunkts; 92 grün.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Eine Zeile mit „Gegenkonto wählen" wird nicht gebucht, der Abgleich zählte ihren
Betrag aber trotzdem mit und meldete „stimmt überein" – das Geld fehlte im Konto,
ohne dass es auffiel.
Duplikate und Gegenbuchungen zählen weiterhin mit (ihr Betrag steckt bereits in
einer früher gebuchten Buchung); wartende Zeilen zählen jetzt als 0 und tauchen
als erste Abweichung mit Datum und Empfänger auf.
Nachgestellt am echten Raiffeisen-Auszug: Zeigt die Transfer-Regel „Übertrag" auf
das importierte Konto selbst, bleibt die Gutschrift über 92.00 ungebucht; der
Abgleich nennt jetzt genau diese Zeile.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Spaltenzuordnung aus einem echten Export (Betrag in Spalte „Amount (EUR)",
Partner als Empfänger, Payment Reference als Zweck, Partner-IBAN für die
Transfer-Erkennung). Eine Kontostand-Spalte liefert N26 nicht, dort bleibt der
Saldo-Abgleich also aus.
Nachgerechnet: 246 Zeilen, Summe -719.51; mit Anfangssaldo 872.95 ergibt das
exakt die tatsächlichen 153.44 EUR.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der Revolut-Auszug enthält ALLE Produkte in einer Datei – im CHF-Export stehen
533 Giro-Zeilen und 255 Zeilen des Ersparten, jedes mit eigenem Kontostand-
Verlauf. Ohne Trennung landeten beide auf demselben Konto und die Pocket-
Bewegungen zählten doppelt.
- Import-Vorlage kennt einen Zeilenfilter („nur Zeilen aus Spalte X mit Wert Y"),
Migration 0012; damit bekommt jedes Pocket sein eigenes Konto
- Gebührenzeilen (Betrag 0.00) können Belastung ODER Erstattung sein – beide
sehen identisch aus. Die Richtung kommt jetzt aus der Kontostand-Spalte;
ohne sie bleibt die Belastung der Normalfall
- Tests für beides; 90 grün
Nachgerechnet an den echten Auszügen: Raiffeisen 223.37, Revolut CHF 61.88,
Erspartes 6.71, Revolut EUR 0.68 – alle vier stimmen zeilengenau mit der
Kontostand-Spalte überein.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ein Wort war je Art nur einmal erlaubt, also ließ sich genau ein Preis
hinterlegen. Im Personalrestaurant zahlt man aber mal 5.00 und mal 7.50 – der
zweite Preis ließ sich nicht erfassen.
Der Betrag gehört jetzt in den Unique-Schlüssel: „sv gruppe = 5.00" und
„sv gruppe = 7.50" sind zwei Regeln derselben Kategorie, dasselbe Wort OHNE
Betrag bleibt der Auffang für alle übrigen Beträge (und darf in einer anderen
Kategorie liegen). Betrags-Regeln greifen vor dem Auffang.
- Migration 0011 (Unique-Schlüssel um amount_cents erweitert)
- Konflikt nur noch bei gleichem Wort UND gleichem Betrag; gilt auch beim
Umbenennen und für Transfer-Schlagwörter
- Test: zwei Preise treffen die Kategorie, ein dritter Betrag den Auffang; 88 grün
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die Suche prüfte nur Betrag und Zeitfenster. Ein erwarteter Transfer-EINGANG
passte damit auch auf eine gleich hohe AUSGABE: Die echte Ausgabe galt als
Gegenbuchung, wurde nicht gebucht und der Saldo lief um ihren Betrag zu hoch.
Jetzt muss das Vorzeichen zur Seite des Transfers passen (wo Geld ankam, kann
keine Ausgabe die Gegenseite sein). Test deckt genau diesen Fall ab; 87 grün.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bisher musste die Regel auf BEIDEN Auszügen ein fremdes Gegenkonto liefern. Beim
Empfangs-Auszug zeigt sie aber auf das Konto, das gerade importiert wird – damit
blieb die Zeile ohne Gegenkonto und wurde still als Einnahme gebucht.
- Gegenbuchungen werden über die Konto-Seite bestehender Transfers gesucht, nicht
über das Konto-Paar. Der Empfangs-Auszug braucht damit keine Regel mehr; eine
Regel auf der abgehenden Seite genügt für beide Dateien.
- Trifft eine Transfer-Regel, ohne dass ein Gegenkonto feststeht, wird die Zeile
nicht mehr als Einnahme/Ausgabe gebucht, sondern in der Prüfansicht mit
„Gegenkonto wählen" markiert – sonst zählt die Bewegung je nach Import-
Reihenfolge doppelt.
- Tests für beide Reihenfolgen; 86 grün.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Revolut tauscht Geld zwischen Währungskonten; im CHF-Auszug steht -100.00 CHF,
im EUR-Auszug +106.42 EUR. Die Gegenbuchungs-Erkennung verglich exakte Beträge
und griff deshalb nie – die Bewegung wurde zweimal gezählt.
- _find_counterpart erkennt die Gegenseite bei unterschiedlichen Währungen über
Konto-Paar, Zeitfenster und einen plausiblen Betrag (10 % Toleranz, weil wir
mit dem EZB-Kurs schätzen und die Bank ihren eigenen nutzt)
- die Gegenbuchung nennt den TATSÄCHLICHEN Betrag: er ersetzt beim Buchen die
Schätzung im bereits gebuchten Transfer, damit beide Salden exakt stimmen
- Test über beide Auszüge: ein Transfer, keine Doppelzählung, EUR-Seite exakt
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der Revolut-Export führt "2026-01-06 23:11:14" in der Datumsspalte. Wählte man
im Dropdown JJJJ-MM-TT, scheiterte das Parsen an der Uhrzeit – jede Zeile hatte
kein Datum und galt als ungültig ("137 Zeilen erkannt, 0 werden gebucht"),
obwohl die Auswahl richtig aussah.
- parse_date schneidet eine überzählige Uhrzeit ab und kommt auch damit klar,
wenn das Format eine Uhrzeit erwartet, der Wert aber keine hat (ISO-T ebenso)
- Dropdown um die Varianten mit Uhrzeit ergänzt, damit die Bank-Vorlagen ihren
echten Eintrag zeigen statt eines leeren Feldes
- Test: reines Datumsformat auf Datei mit Uhrzeit -> alle Zeilen erkannt, 84 grün
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die Money-Komponente gab den Betrag immer durch Math.abs() aus; das Vorzeichen
kam nur über das optionale sign-Prop. Kontostände (Konten-Seite und Dashboard-
Karte) übergeben keines – ein überzogenes Konto oder eine Kreditkartenschuld sah
dadurch positiv aus, während die Gesamtsumme korrekt negativ rechnete. Genau
dieser Widerspruch: alle Konten scheinbar im Plus, Gesamt im Minus.
Ohne sign steht der Wert für sich selbst und wird jetzt mit echtem Vorzeichen
(und rot) ausgegeben; mit sign bleibt es wie bisher, weil dort die Richtung aus
der Buchungsart kommt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bisher merkte man einen Importfehler erst am falschen Endsaldo, ohne Hinweis auf
die Ursache. Enthält der Auszug eine laufende Kontostand-Spalte, gleicht der
Import jetzt jede Zeile dagegen ab: Die Spalte sagt, wie sich der Saldo
tatsächlich verändert hat, unsere Erkennung muss dazu passen.
- neue Spaltenzuordnung "Kontostand (laufend)"; Presets Raiffeisen/Revolut ergänzt
- Prüfansicht zeigt: stimmt überein ODER Differenz + erste abweichende Zeile
(Datum, Empfänger, Betrag laut Bank vs. erkannt)
- meldet zusätzlich den Anfangssaldo laut Datei – häufigste Fehlerquelle
- rechnet mit dem tatsächlich gebuchten Betrag, damit auch nicht gebuchte Zeilen
auffallen (z. B. nicht zugeordnete Gebührenspalte); Fremdwährungs-Zeilen
gehören zu einem anderen Saldo-Verlauf und bleiben außen vor
- erkennt absteigend sortierte Auszüge
- Tests: stimmiger Auszug (ok) und fehlende Gebührenspalte (zeigt genau die
Zeile). 83 grün.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die neue Statusprüfung ließ nur „COMPLETED" durch. Deutsche Bank-Exporte
schreiben aber „ABGESCHLOSSEN", wodurch keine einzige Zeile mehr buchbar war.
Statt einer Positivliste jetzt eine Sperrliste (storniert/ausstehend/abgelehnt/
fehlgeschlagen, jeweils deutsch und englisch); unbekannte Status werden gebucht,
damit keine echten Buchungen still verloren gehen.
Test mit echtem deutschem Revolut-Export inkl. reiner Gebührenzeile
(Betrag 0.00, Gebühr 10.99): Endsaldo trifft die Kontostand-Spalte. 81 grün.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Das Revolut-Preset kannte die Spalten Gebühr/Währung/Status laut Kommentar,
der Parser hat sie aber nie gelesen. Folgen: Gebühren fehlten im Saldo,
stornierte (REVERTED) und schwebende Zeilen wurden mitgebucht, und Zeilen
fremder Währungs-Pockets landeten 1:1 im Konto – der Saldo lief dadurch zu hoch.
- Gebührenspalte mindert den Betrag (immer als Kosten)
- nur Zeilen mit Status COMPLETED (oder ohne Statusspalte) sind buchbar
- Zeilen in anderer Währung als das Zielkonto werden nicht gebucht
- Grund wird in der Prüfansicht als Badge angezeigt (storniert / Währung)
- Gebühr/Währung/Status in der Spaltenzuordnung wählbar; Revolut-Preset ergänzt
- Test mit echtem Revolut-Format (Gebühr, Storno, Fremdwährung), 80 grün
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die Liste lud nur die 200 neuesten Buchungen, wodurch ältere Monate fehlten
(bei 254 importierten Zeilen reichte die Ansicht nur bis Juni zurück). Da die
Tabelle im Browser filtert und sortiert, werden nun standardmäßig alle Buchungen
geladen. Verifiziert am echten Auszug: 254 von 254, ab 05.01.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bisher wurde eine zweite Buchung mit gleichem Tag/Betrag/Text (z. B. zwei
Gutschriften à 324 am selben Tag) fälschlich als Duplikat verworfen. Jetzt gilt
eine Zeile nur als Duplikat, wenn bereits GENAU SO VIELE identische Buchungen in
der DB stehen – ein erneuter Import derselben Datei bleibt weiterhin Duplikat-sicher.
- csv_import.detect_rows: existing/seen als Counter (Multiset) statt Set
- Tests angepasst + Re-Import-Test ergänzt; an echtem Raiffeisen-Auszug verifiziert
(254 Zeilen, 0 fälschliche Duplikate, Saldo == Bank-Endsaldo)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Enthält der Buchungstext den Erkennungs-Text (Art „Text") eines ANDEREN
Kontos, wird auch ein Eingang als Transfer VON diesem Konto gesetzt – nicht
nur die Ausgabe. Richtung ergibt sich aus dem Vorzeichen.
- Gegenbuchungs-Erkennung: existiert schon ein Transfer zwischen denselben
Konten mit passendem Betrag (±5 Tage), wird die Gegenseite als „Gegenbuchung"
markiert und nicht angehakt – so zählt dieselbe Bewegung beim Import beider
Auszüge nicht doppelt (überschreibbar in der Prüfansicht).
- Tests: Eingang übers Konto-Tag, Gegenbuchung übersprungen (78 grün)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
_set_identifiers glich die Liste per clear()+neu-Anlegen ab; SQLAlchemy fügte
dabei die (unveränderten) Identifikatoren vor dem Löschen ein und verletzte so
UNIQUE(account_id, kind, value_norm) -> Internal Server Error beim Speichern.
Jetzt als Diff: unveränderte behalten, nur fehlende hinzufügen / überzählige
entfernen. Betrifft alle Identifikator-Arten (IBAN/Nummer/Text).
Regressionstest: Umbenennen mit unverändertem Identifikator + Entfernen (76 grün).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Transfer-Regel kann direkt ein Zielkonto tragen (target_account_id); ohne ->
weiterhin Auto-Erkennung aus dem Buchungstext (Konto-Texte)
- Migration 0010; Endpunkt aktualisiert bestehendes Wort statt Konflikt
- Import bevorzugt das feste Zielkonto, sonst _guess_target_account
- Konten-Seite: Transfer-Erkennung mit Zielkonto-Auswahl + Anzeige am Chip
- Test: festes Zielkonto greift ohne Konto-Texte (75 grün)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Neue Seite „Mein Konto" (/konto, für alle Nutzer): eigenes Passwort ändern
(inkl. Richtlinien-Anzeige) + Zwei-Faktor verwalten; erreichbar über den
Nutzer-Chip in der Seitenleisten-Fußzeile
- Einstellungen: 2FA-Karte entfernt (liegt jetzt bei „Mein Konto"), Karten in
ein mehrspaltiges Raster gruppiert
- Menüpunkt „Einstellungen" unter die Überschrift „System" verschoben (für alle
Nutzer sichtbar; „Benutzer" bleibt Admin-only)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Bank-Vorlagen und eigene Vorlagen in EINEM Dropdown (optgroups, typ-getaggte
Werte preset:/tpl:)
- Speichern überschreibt bei gleichem Namen (Rückfrage); geladene Vorlage belegt
den Namen vor
- Spaltenvorschau wird automatisch erzeugt (kein „Datei einlesen"-Klick mehr)
- Gegen-IBAN in „Weitere Spalten (optional)" verschoben + erklärt; Grundzuordnung
zeigt nur Datum/Betrag/Empfänger/Zweck
- Beleg-Modus zeigt die hochgeladenen PDF-Seiten als Bild + extrahierten Text
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Neuer Parser erkennt mehrzeilige Auszüge (N26 & Co.): Beschreibung → Value
Date → Buchungsdatum → Betrag stehen auf eigenen Zeilen; Betrags-Zeile schließt
eine Buchung ab, Kopf-/Fußzeilen (Name/Adresse/eigene IBAN/Seitenzahl/
Spaltenköpfe) werden gefiltert, Gegen-IBAN und Zweck werden übernommen
- Alter Ein-Zeilen-Heuristik-Parser bleibt als Fallback
- /documents/preview liefert zusätzlich die Seiten als PNG-Data-URLs
(PyMuPDF get_pixmap, kein poppler nötig)
- Tests: N26-artige mehrzeilige Fixture + Seiten-Rendering (74 grün);
am echten 34-Seiten-Auszug 207 Buchungen erkannt
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Budget-Donut: Mittelbetrag passt sich der Länge an (kein Hineinlaufen in den
Ring bei 4-stelligen Beträgen)
- Vermögensverlauf: Y-Achse ohne Währungssymbol (formatAmount) + etwas mehr
linker Rand → „CHF …" wird nicht mehr abgeschnitten
- Karten-Optionen: im Anordnen-Modus je Karte einstellbar; Budget-Donut und
Budget-Fortschritt können nach Gruppen ODER Kategorien aufschlüsseln
(?group_by=), Auswahl wird im Layout (props) mitgespeichert
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- CategorizationRule bekommt `kind` (expense|income|transfer); Unique jetzt
(owner, match_field, pattern, kind) statt ohne kind
- Konfliktprüfung/Anlage (add/update Keyword, Transfer-Keyword, gelernte Regeln)
arbeiten kind-bewusst: dasselbe Wort je einmal pro Art möglich
- Migration 0009 mit Backfill (kind aus Kategorie-Art bzw. is_transfer)
- Tests angepasst: quer über Arten erlaubt, gleiche Art weiterhin Konflikt (71 grün)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Portierte DataTable-Komponente (aus Vorrania): Spalten per Drag breiter ziehen
und verschieben, Klick-Sortierung, Filterzeile je Spalte, Spalten ein-/ausblenden;
Breiten/Reihenfolge/Filter pro Tabelle im Browser gemerkt (localStorage)
- Zu langer Zellinhalt wird mit „…" abgeschnitten (Titel bleibt sichtbar, Excel-artig)
- Umgestellt: Buchungen, Import-Prüfansicht (inkl. interaktiver Zellen), Import-
Verlauf, Benutzer
- Neue Skeleton-Komponente für den Ladezustand
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Regeln:
- Schlagwörter mit optionaler Betragsbedingung (z. B. „SV = 5.00 → Restaurant");
Betrags-Regeln gewinnen vor betragslosen
- Transfer-Schlagwörter (Text → Transfer) auf der Konten-Seite
- Konto-Identifikator-Art „Text": erkennt das Zielkonto eines Transfers aus dem
Buchungstext (längster passender Text gewinnt)
- Migration 0007, Endpunkte, Tests (Betrag/Transfer/Konflikt), gesamt 30 grün
Optik:
- App-Icon: Münzhaufen (aus Nutzer-SVG) weiß auf grünem Grund, klein gehalten
- Farbschema auf pastelliges Grün (Akzent hell/dunkel + Favicon)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Gruppen erscheinen nur noch als dezente Zwischenüberschrift; die Kategorien
laufen als schlichte Zeilen mit dünnem Trenner durch (eine Karte).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Manuelle Schlagwörter je Kategorie (Popup mit Chips, Doppelklick zum Bearbeiten)
- Treffer über Empfänger ODER Verwendungszweck; längstes Schlagwort gewinnt;
Kind-Filter (Ausgabe/Einnahme); wirken nur bei künftigen Importen
- Lernende Korrektur-Erkennung: ab 5 Anwendungen und >= 1/3 Korrekturen
erscheint eine Prüf-Meldung in den Einstellungen (Behalten/Entfernen)
- Neue CategorySelect-Komponente (Baum + Suche, per Portal) ersetzt die
nativen optgroup-Selects in Buchungen und Import-Prüfansicht
- Migration 0006 (source/applied_count/overridden_count/confirmed, match_field any)
- Endpunkte, i18n DE/EN, Tests (test_keywords: 7 neu, gesamt 27 grün)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Backup & Export:
- routers/backup: /backup/db (Admin, konsistentes SQLite-Online-Backup),
/export/transactions.csv|json und /export/all.json (owner-gescoped).
- Einstellungen: Bereich „Backup & Export" mit Download-Buttons. docs/BACKUP.md
(Wiederherstellung + LXC-Sicherung). pytest für Export + Admin-Schutz.
Import-Verbesserungen (Nutzer-Feedback zum Ablauf):
- Klarer Hinweis, dass die Zuordnungstabelle nur Beispielzeilen zeigt und
„Vorschau erstellen" die vollständige Prüfliste + Buchen-Button erzeugt.
- Zusammenfassung (erkannt/gebucht) und Warnung, wenn keine gültige Zeile erkannt
wurde (Hinweis auf Format/Bank-Vorlage).
- Fix: Raiffeisen-Preset hat has_header=true (der Export hat eine Kopfzeile).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- services/csv_import: PRESETS-Liste (aus echten Beispiel-Exporten des Nutzers),
GET /imports/presets.
- Frontend: Preset-Auswahl im Import füllt Format/Spalten automatisch.
Beide Presets per TestClient gegen echte Zeilenformate verifiziert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ein 100%-breites select drängte das danebenliegende Eingabefeld auf 0.
Select auf feste Breite, .row-Kinder dürfen schrumpfen (min-width:0).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ein eigener Dienst-Benutzer kommt nicht an Code/venv unter /root (Modus 700).
install.sh setzt User/Group der Unit jetzt auf den Eigentümer des Repos – bei
Klon als root nach /root also root. Kein useradd mehr.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Deployment-Fixes (Dienst startete nicht -> 203/EXEC "uvicorn not found"):
- Unit ohne ProtectHome/ProtectSystem: Repo/venv dürfen unter /root oder /home
liegen (ProtectHome=true blendete diese Pfade für den Dienst aus).
- install.sh: Python-3.11+-Prüfung mit klarer Meldung; prüft nach der Installation,
dass uvicorn wirklich in der venv liegt.
- EZB-Kursabruf läuft beim Start jetzt im Hintergrund (blockiert den Start nie).
Phase-3-Backend (Dashboard):
- Modell + Migration 0004: dashboard_layouts (JSON-Layout je Nutzer).
- routers/dashboard: Layout speichern/laden/zurücksetzen + Kartendaten
(Budget-Donut, Budget-Fortschritt, Einnahmen/Ausgaben, Kontostände,
Vermögensverlauf, letzte Buchungen).
- Frontend-Infrastruktur: Chart-Komponenten (Donut/Line), palette, API-Methoden,
react-grid-layout. (Dashboard-Seite folgt im nächsten Commit.)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>