Waehlt man eine Datei (oder uebernimmt eine vom Telefon), erkennt Certain
Trennzeichen, Dezimalzeichen, Datumsformat und Spaltenzuordnung selbst und
traegt sie ein. Darueber steht, WAS erkannt wurde – "Format erkannt:
Revolut" oder die Spaltenzuordnung im Klartext –, damit man es pruefen kann,
statt ihm blind zu vertrauen.
War etwas nicht eindeutig, steht das ausdruecklich da mit dem Hinweis, die
Zuordnung unten anzusehen. Das Formular bleibt also erreichbar, muss aber im
Normalfall nicht mehr angefasst werden.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zwei Luecken geschlossen:
Mail-Vorschlaege standen als "pending" im Eingang, aber es gab keinen Knopf
zum Buchen – der Weg war hinten offen. Jetzt je Eintrag "Buchen" und ein
"Alle buchen". Unklare bleiben liegen: Bei ihnen fehlt etwas oder die
Erkennung war unsicher, die soll man ansehen statt im Stapel durchzuwinken.
Der Auszug vom Telefon bucht nicht mehr sofort, sondern wird nur abgelegt.
Am Telefon prueft man keine 500 Zeilen; die Datei wartet in der
Import-Ansicht und laeuft dort durch die normale Vorschau mit
Saldo-Abgleich, Zeilenfilter und Duplikatpruefung.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Loesch-Endpunkt war da, aber ohne Knopf in der Oberflaeche, und
Bearbeiten fehlte ganz – eine falsch eingetippte Zuordnung liess sich also
nicht mehr korrigieren.
Jede Zuordnung ist jetzt eine eigene Zeile mit Erkennungstext und Konto;
der Speichern-Knopf erscheint erst bei einer Aenderung. Dazu ein PUT auf
/mail/senders/{id} im Backend.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Server, Port, Benutzer und Passwort eintragen, Verbindung testen, Ordner
danach aus der echten Liste des Postfachs waehlen. Je Absender wird ein
Zielkonto zugeordnet – ohne Zuordnung uebernimmt Certain nichts, denn
dieselbe Adresse kann je nach Konto etwas anderes bedeuten.
Der Hinweis am Passwortfeld sagt, was passiert, wenn das Server-Geheimnis
getauscht wird, und empfiehlt ein App-Passwort statt des echten.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- "Mein Konto": Geraetemarken anlegen und widerrufen. Der Klartext ist
nur einmal zu sehen, daneben steht eine Bauanleitung fuer den
Kurzbefehl mit kopierfertiger Adresse und Kopfzeile. Ein fertiger
Download geht nicht: seit iOS 15 muessen Kurzbefehl-Dateien signiert
sein, und signieren kann nur ein Mac mit Apple-Konto.
- Neue Seite "Eingang": was unterwegs erfasst wurde, mit
Kategorie-Auswahl und Verwerfen.
- Die Import-Pruefliste unterscheidet jetzt, WARUM eine Zeile
uebersprungen wird: "schon erfasst" mit Erklaerung statt nur
"Duplikat".
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Liste stand in der Anlegereihenfolge, die selten die gewuenschte ist.
Neuer Endpunkt PUT /accounts/order nimmt die IDs in der gewuenschten Folge
und schreibt die Position; er muss vor /{account_id} stehen, sonst faengt
die ID-Route den Pfad ab. Fremde IDs werden abgewiesen.
In der Kontenliste zwei Pfeile je Zeile, optimistisch sortiert, damit die
Liste beim Klicken nicht springt.
Co-Authored-By: Claude Opus 5 <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>
- 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>
Im Downloads-Ordner lagen "certain-finance-export_....json" und
"certain-finance-backup_....json" nebeneinander, ohne dass man sah, welche
Datei sich zurueckladen laesst. Alle Downloads heissen jetzt
certain-finance_<art>_<datum>_<uhrzeit>.<endung>, wobei die Art es sagt:
vollbackup, vollbackup-system, datenuebersicht, buchungen, datenbank. Das
persoenliche Vollbackup traegt zusaetzlich den Benutzernamen.
Den Namen vergibt jetzt allein der Server im Content-Disposition-Kopf; das
Frontend liest ihn von dort. Vorher erfanden beide Seiten ihn getrennt und
kamen auf unterschiedliche Ergebnisse (Bindestrich gegen Unterstrich, UTC
gegen Ortszeit). Zeitstempel ist Ortszeit: wer abends um 20 Uhr exportiert,
soll keine Datei von 18 Uhr finden.
Passend dazu heisst der Knopf "Alle Daten (JSON)" nun "Datenuebersicht
(JSON)", und der Hinweis darueber sagt ausdruecklich, dass sich diese
Dateien nicht zurueckladen lassen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zwei-Faktor per TOTP mit zehn Einmal-Wiederherstellungscodes. Der
Zwischenzustand "Passwort stimmt, Code fehlt" haengt an der vorhandenen
Sitzungstabelle (pending_2fa, zehn Minuten Laufzeit) und gilt nirgends als
angemeldet; nach dem Code wird das Cookie getauscht statt weiterverwendet.
Der Wiederverwendungsschutz merkt sich das tatsaechlich getroffene
Zeitfenster, nicht die aktuelle Uhrzeit - sonst liesse sich ein Code aus dem
naechsten Fenster gleich darauf nochmal einloesen.
Passwortrichtlinie (Laenge, Zeichenklassen, MFA-Pflicht) in der neuen
globalen Tabelle app_settings, durchgesetzt beim Anlegen, Zuruecksetzen und
Aendern von Passwoertern. Bestehende Passwoerter lassen sich nicht gegen eine
neue Richtlinie pruefen - der Hash gibt nichts her. Beim Anmelden liegt das
Passwort aber kurz im Klartext vor: dort wird geprueft und bei Verstoss ein
Wechsel verlangt, mit passendem Grund fuer den Hinweistext.
Nebenbei geschlossen: must_change_password war bisher nur im Frontend
erzwungen, wer die API direkt ansprach kam vorbei. enforce_account_state
haengt jetzt am /api-Sammelrouter und laesst nur noch durch, was man zum
Erfuellen der Pflicht braucht.
Das JSON-Backup liess sich bisher grundsaetzlich nicht zurueckladen: keine
Version, Kategorien nur ueber mehrdeutige Namen, sieben Tabellen fehlten.
Daneben steht nun ein Format v2, das Beziehungen ueber lokale IDs abbildet,
je Benutzer oder systemweit. Zurueckgeladen wird nach einer Pruefansicht,
wahlweise ersetzend oder ergaenzend; vor dem Ersetzen legt der Server einen
Schnappschuss der Datenbank an. Der alte Ansichts-Export bleibt fuer
Tabellenkalkulationen bestehen und wird beim Hochladen ausdruecklich
abgewiesen, statt halb zu raten.
Frontend: wiederverwendbares Passwortfeld mit Augensymbol, animierte
Anforderungsliste, 2FA-Seite, Admin-Karte fuer die Richtlinie und Karte zum
Zurueckladen. Neue Bewegung ist in prefers-reduced-motion hinterlegt; Secret
und Codes sind markierbar, sonst verhinderte das globale user-select das
Kopieren.
Co-Authored-By: Claude Opus 5 <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>
- 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>
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>