Design-Spec Finanzberatungs-Umgebung & -Tool (abgenommen)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
218
docs/superpowers/specs/2026-07-17-finanzberatung-design.md
Normal file
218
docs/superpowers/specs/2026-07-17-finanzberatung-design.md
Normal file
@@ -0,0 +1,218 @@
|
||||
# Design: Finanzberatungs-Umgebung & Finanzberatungs-Tool
|
||||
|
||||
Datum: 2026-07-17 · Status: vom Nutzer abgenommen
|
||||
|
||||
## Ziel
|
||||
|
||||
Eine finanziell schwierige Phase planbar machen: Kontobewegungen der nächsten
|
||||
Zeit vorhersagen, Kreditbedarf (Zeitpunkt und Höhe) ermitteln und sinnvolle
|
||||
Ausgabenkürzungen identifizieren. Dazu werden PDF-Kontoauszüge ausgewertet, in
|
||||
einer Datenbank abgelegt und über Szenarien in die Zukunft gerechnet.
|
||||
|
||||
Das Vorhaben besteht aus zwei Repositories:
|
||||
|
||||
- **`~/fb`** (dieses Repo): die Claude-Code-Beratungsumgebung — CLAUDE.md,
|
||||
Projekt-Skills, Memory, Spezifikation und Plan. Kein Tool-Code.
|
||||
- **`~/bin`**: das Finanzberatungs-Tool als rootless-Podman-Pod mit
|
||||
Web-GUI, API und Grafana.
|
||||
|
||||
## Rahmenbedingungen (geklärt)
|
||||
|
||||
- Kontoauszüge liegen als **PDF** vor, von **mehreren Konten bei mehreren
|
||||
Banken**: Volksbank/Raiffeisenbank, HypoVereinsbank, DKB.
|
||||
- PDF-Verarbeitung durch **feste, deterministische Parser je Bank**
|
||||
(pdfplumber), keine KI-Abhängigkeit im Import.
|
||||
- Import **immer mit Vorschau**: extrahierte Buchungen werden vor der
|
||||
Übernahme angezeigt und explizit bestätigt.
|
||||
- Zugriff: Das Tool bindet nur an lokale Ports (**ab 8096**); externe
|
||||
Erreichbarkeit regelt der bestehende Traefik-Reverse-Proxy/VPN des
|
||||
Betreibers. Zusätzlich eigener Login-Schutz im Tool (siehe Sicherheit).
|
||||
- Szenarien umfassen: wiederkehrende Posten, geplante Einmalposten,
|
||||
Kredit-Simulation, Sparpotenzial-Analyse (alle vier bestätigt).
|
||||
- Architektur-Entscheidung: **Ansatz A, schlanker Pod** (drei Container),
|
||||
bewusst gegen feingranulare Microservices (B) und gegen Firefly III (C).
|
||||
|
||||
## Architektur
|
||||
|
||||
Podman Pod `finance_pod`, erstellt durch `~/bin/create_pod_finance.sh` exakt
|
||||
nach dem Muster von `~/bin/example_create_pod_langflow.sh`:
|
||||
|
||||
- gepinnte, unveränderliche Image-Tags (kein `:latest`),
|
||||
- Bind-Verzeichnisse unter `~/.local/share/finance_pod/` mit `:Z`-Flag,
|
||||
- `podman generate systemd --new` + systemd-User-Service
|
||||
`pod-finance_pod.service` in `~/.config/systemd/user/`,
|
||||
- Host-IP/Ports als Variablen am Skriptanfang.
|
||||
|
||||
| Container | Image | Port (Host → Container) |
|
||||
|---|---|---|
|
||||
| `finance-db_ctr` | `postgres:17.x` (gepinnt) | nur pod-intern (5432) |
|
||||
| `finance-api_ctr` | eigenes Image aus `~/bin/finance/Containerfile` | `127.0.0.1:8096 → 8000` |
|
||||
| `finance-grafana_ctr` | `grafana/grafana-oss` (gepinnt) | `127.0.0.1:8097 → 3000` |
|
||||
|
||||
Das Skript baut das API-Image vor dem Pod-Start per `podman build`.
|
||||
|
||||
Bind-Verzeichnisse: `postgres-data`, `grafana-data`, `inbox` (Import-Eingang,
|
||||
auch vom Host direkt befüllbar), `uploads` (archivierte Original-PDFs).
|
||||
|
||||
### Sicherheit
|
||||
|
||||
- **Web-GUI:** Login-Seite mit Benutzername/Passwort, Session-Cookie.
|
||||
Passwort wird beim Setup gesetzt und nur als Hash gespeichert.
|
||||
- **API:** statischer API-Schlüssel (langer Zufallswert), von Claude Code als
|
||||
`Authorization: Bearer`-Header mitgeschickt; Anfragen ohne gültigen
|
||||
Schlüssel werden abgelehnt.
|
||||
- **Secrets:** `~/bin/finance/.env` (gitignored), beim ersten Skriptlauf mit
|
||||
Zufallswerten erzeugt: Postgres-Passwort, API-Schlüssel,
|
||||
Grafana-Admin-Passwort, GUI-Zugangsdaten.
|
||||
- Grafana hat zusätzlich seinen eigenen Login; TLS/externes Auth macht
|
||||
Traefik.
|
||||
|
||||
## Datenmodell (Postgres, SQLAlchemy + Alembic)
|
||||
|
||||
- `accounts` — Konten: Bank, IBAN, Name, Typ (Giro/Tagesgeld/Kredit).
|
||||
- `transactions` — Buchungen: Buchungs-/Wertstellungsdatum, Betrag
|
||||
(positiv = Eingang), Verwendungszweck, Gegenpartei, Konto, Kategorie,
|
||||
Quell-Auszug, Duplikat-Hash über (Konto, Datum, Betrag, Zweck).
|
||||
- `categories` + `category_rules` — Kategorien und Zuordnungsregeln
|
||||
(Muster im Verwendungszweck/Gegenpartei → Kategorie), automatische
|
||||
Kategorisierung beim Import.
|
||||
- `statements` — importierte PDFs: Datei, Bank, Konto, Zeitraum,
|
||||
Anfangs-/Endsaldo laut PDF, Status (Entwurf/übernommen/fehlerhaft).
|
||||
- `recurring_items` — wiederkehrende Posten: Betrag, Rhythmus
|
||||
(monatlich/quartalsweise/jährlich), Stichtag, optionales Enddatum.
|
||||
- `planned_items` — geplante Einmalposten: Datum, Betrag, Beschreibung.
|
||||
- `loans` — Kredite: Auszahlungsdatum, Betrag, Zinssatz, Laufzeit,
|
||||
Tilgungsart (Annuität/endfällig).
|
||||
- `scenarios` (+ Zuordnungs-/Modifikator-Tabellen) — benannte
|
||||
Was-wäre-wenn-Pakete; Kürzungs-Modifikatoren auf Kategorien oder einzelne
|
||||
wiederkehrende Posten (prozentual oder absolut, Streichung).
|
||||
|
||||
## Import-Pipeline
|
||||
|
||||
1. PDF landet in der Inbox (Drag-and-Drop in der GUI oder Datei-Kopie auf dem
|
||||
Host).
|
||||
2. **Bank-Erkennung** anhand von Textmerkmalen wählt den Parser; drei
|
||||
Parser-Module (`vr.py`, `hvb.py`, `dkb.py`) mit gemeinsamem Interface
|
||||
`parse(pdf) → (Auszugsdaten, Buchungsliste)`.
|
||||
3. **Prüfungen:**
|
||||
- Saldo-Plausibilisierung: Anfangssaldo + Summe der Buchungen muss den
|
||||
Endsaldo ergeben; Abweichung ⇒ Auszug wird als fehlerhaft markiert und
|
||||
nicht übernommen.
|
||||
- Duplikat-Prüfung über den Duplikat-Hash; bereits vorhandene Buchungen
|
||||
werden markiert und nicht doppelt übernommen.
|
||||
4. **Vorschau (immer):** Buchungen werden als Entwurf gespeichert und in der
|
||||
GUI (bzw. per API) als Tabelle mit Saldo-Status, automatischen Kategorien
|
||||
und Duplikat-Markierungen angezeigt.
|
||||
5. **Bestätigung** übernimmt die Buchungen endgültig; danach greifen sie in
|
||||
allen Auswertungen. Fehlgeschlagene Parses bleiben mit Fehlergrund auf der
|
||||
Import-Seite sichtbar, die Original-PDF bleibt in der Inbox.
|
||||
|
||||
## Szenario-Engine
|
||||
|
||||
Reines Python-Modul (`app/engine/`), ohne DB-/Web-Abhängigkeiten testbar.
|
||||
|
||||
- Eingabe: Startsaldo (echter aktueller Gesamtsaldo bzw. je Konto),
|
||||
Szenario-Definition, Horizont (konfigurierbar, Standard 18 Monate).
|
||||
- Abrollen aller Posten zu einem **tagesgenauen Zahlungsstrom**:
|
||||
wiederkehrende Posten nach Rhythmus, Einmalposten am Datum, Kredite als
|
||||
Auszahlung + berechnete Raten (Annuitätenformel bzw. endfällig, inkl.
|
||||
Zins-/Tilgungsaufteilung und Restschuldverlauf), Kürzungs-Modifikatoren
|
||||
auf die betroffenen Posten/Kategorien.
|
||||
- Ausgabe je Szenario: Saldo-Verlauf (Tagesreihe), **Tiefpunkt** (Datum +
|
||||
Betrag), erstes Datum der Unterschreitung von Null bzw. einer
|
||||
konfigurierbaren **Warnschwelle**.
|
||||
- Ergebnisse werden in Projektions-Tabellen persistiert, damit Grafana sie
|
||||
direkt visualisieren kann; Neuberechnung per Knopf/API-Aufruf.
|
||||
- Unterstützung beim Anlegen: Muster-Erkennung über importierte Buchungen
|
||||
schlägt wiederkehrende Posten vor (Bestätigen/Verwerfen durch den Nutzer).
|
||||
- Echte Buchungen werden von Szenarien **nie verändert**.
|
||||
|
||||
## Web-GUI
|
||||
|
||||
FastAPI + Jinja2 + HTMX, deutschsprachig, vier Seiten:
|
||||
|
||||
1. **Übersicht:** Gesamtsaldo und Saldo je Konto, nächste anstehende
|
||||
Zahlungen, Warnhinweis bei drohender Schwellen-Unterschreitung,
|
||||
eingebettete Grafana-Panels.
|
||||
2. **Import:** Drag-and-Drop-Fläche, Importliste mit Status, Vorschau-Tabelle
|
||||
mit Bestätigen-Aktion.
|
||||
3. **Buchungen:** filterbare Tabelle (Konto, Zeitraum, Kategorie, Volltext),
|
||||
manuelle Kategorien-Korrektur mit „Regel daraus erzeugen“, **manuelles
|
||||
Erfassen** von Zahlungen/Einkünften per Formular.
|
||||
4. **Planung:** wiederkehrende Posten (inkl. automatischer Vorschläge),
|
||||
Einmalposten, Kredite, Szenarien mit „Durchrechnen“-Aktion und
|
||||
Ergebnisanzeige.
|
||||
|
||||
## Grafana
|
||||
|
||||
Vollständig provisioniert (Datenquelle Postgres mit lesendem DB-User,
|
||||
Dashboards als Dateien im Repo `~/bin/finance/grafana/`):
|
||||
|
||||
- Kontostand-Verlauf (je Konto und gesamt),
|
||||
- Einnahmen/Ausgaben pro Monat, gestapelt nach Kategorie,
|
||||
- Top-Ausgabenkategorien,
|
||||
- Szenario-Vergleich (Vorschau-Kurven übereinander, Nulllinie, Warnschwelle).
|
||||
|
||||
## API für Claude Code
|
||||
|
||||
REST/JSON unter `http://127.0.0.1:8096/api/…`, OpenAPI-dokumentiert.
|
||||
Abgedeckte Funktionen: Konten/Buchungen lesen und anlegen, Kategorien und
|
||||
Regeln verwalten, Import-Status abfragen und Entwürfe bestätigen,
|
||||
wiederkehrende/geplante Posten, Kredite und Szenarien anlegen/ändern,
|
||||
Szenarien durchrechnen und Ergebnisse (Verlauf, Tiefpunkt, Unterschreitung)
|
||||
abrufen.
|
||||
|
||||
## Claude-Code-Umgebung in `~/fb`
|
||||
|
||||
- **`CLAUDE.md`:** Umgebungsbeschreibung (API-URL, Ablageort des
|
||||
API-Schlüssels, Sprache Deutsch), Grundregeln („echte Buchungen nie
|
||||
ändern, Planung nur über Szenarien“).
|
||||
- **Skills** (`.claude/skills/`):
|
||||
- `finanz-api` — Endpunkt-Referenz mit curl-Beispielen,
|
||||
- `finanzberatung` — Beratungs-Workflow: Lage abrufen → Basis-Szenario →
|
||||
Varianten (Kredit/Kürzung) anlegen und rechnen → vergleichen →
|
||||
Empfehlung mit Zahlen begründen,
|
||||
- `auszug-import` — Import-Betreuung: wartende/fehlgeschlagene Importe
|
||||
prüfen, Parser-Fehler im `~/bin`-Repo beheben.
|
||||
- **Memory:** Kategorien-Konventionen, Entscheidungen (z. B. Warnschwelle),
|
||||
Eigenheiten einzelner Banken/Auszüge.
|
||||
|
||||
## Projektstruktur `~/bin`
|
||||
|
||||
```
|
||||
~/bin/
|
||||
├── create_pod_finance.sh # Pod-Skript nach dem Beispiel-Muster
|
||||
└── finance/
|
||||
├── Containerfile # Image für finance-api_ctr
|
||||
├── .env # Secrets (gitignored, vom Skript erzeugt)
|
||||
├── app/ # FastAPI: API-Routen, GUI-Routen, Auth
|
||||
│ ├── models/ # SQLAlchemy-Tabellen + Alembic-Migrationen
|
||||
│ ├── parsers/ # vr.py, hvb.py, dkb.py + Bank-Erkennung
|
||||
│ ├── engine/ # Szenario-/Kredit-Rechnung (reines Python)
|
||||
│ └── templates/ # Jinja2 + HTMX
|
||||
├── grafana/ # provisionierte Datenquelle + Dashboards
|
||||
└── tests/ # pytest
|
||||
└── fixtures/ # Beispiel-PDFs je Bank (gitignored)
|
||||
```
|
||||
|
||||
## Tests
|
||||
|
||||
Testgetriebene Entwicklung (pytest):
|
||||
|
||||
- **Engine:** Annuitäten-/Zins-Mathematik und Projektionslogik als
|
||||
Unit-Tests (zuerst geschrieben).
|
||||
- **Parser:** Tests gegen echte Beispiel-PDFs in `tests/fixtures/`
|
||||
(gitignored). Der Nutzer stellt pro Bank mindestens einen echten Auszug
|
||||
bereit (Beträge dürfen verfremdet sein, Layout muss echt sein) —
|
||||
zugesagt.
|
||||
- **API/GUI:** FastAPI-TestClient gegen eine Test-Datenbank.
|
||||
- **Deployment:** Smoke-Test am Skriptende (analog Beispiel-Skript:
|
||||
curl-Readiness-Check auf GUI und Grafana).
|
||||
|
||||
## Bewusst weggelassen (YAGNI)
|
||||
|
||||
- Kein automatischer Bank-Abruf (FinTS/PSD2) — Import nur über PDFs.
|
||||
- Keine Mehrbenutzer-/Rollenverwaltung — ein GUI-Login genügt.
|
||||
- Kein KI-Aufruf im Server — KI-Nutzung ausschließlich über Claude Code
|
||||
gegen die API.
|
||||
- Keine Sofort-Übernahme beim Import — Vorschau ist verpflichtend.
|
||||
Reference in New Issue
Block a user