GuidoandClaude Opus 5 f2c1ab7dec feat: Regeln nachtraeglich auf Buchungen ohne Kategorie anwenden
Regeln greifen beim Import. Alles, was vorher hereinkam – oder hereinkam, bevor
es die Regel gab –, bleibt liegen. Bei einer Bankanbindung passiert genau das
dauernd: Die Umsaetze kommen von selbst, die Regel entsteht spaeter. Die
Revolut-Aufrundungen aufs Sparen-Pocket sind der Fall, an dem es aufgefallen
ist.

Der Knopf steht bei der Transfer-Erkennung und zeigt erst, was passieren
wuerde. Uebertrags-Regeln laufen durch denselben Dienst wie jeder andere
Uebertrag – er lehnt ab, wo die Gegenseite schon gebucht ist, und solche
Buchungen bleiben unangetastet und werden mit Grund gemeldet.

Ohne festes Zielkonto wird es aus dem Buchungstext erraten, aber nur bei GENAU
einem Treffer und nur an Wortgrenzen: "Euro" darf nicht "PayPal Europe"
treffen. Zwei Moeglichkeiten heisst raten, und dann passiert nichts.

Angefasst werden nur Buchungen OHNE Kategorie – sonst ueberschriebe der Knopf
stillschweigend, was von Hand zugeordnet wurde. Ein Uebertrag ist kein Kandidat
mehr, ein zweiter Klick verschiebt das Geld also nicht erneut.

Zwei Dinge fielen beim Testen auf und sind mit behoben:

- Ein fehlgeschlagener Uebertrag verwarf per rollback() auch alles, was im
  selben Durchlauf schon gelungen war. Jetzt haelt ein Rettungspunkt je
  Uebertrag den Schaden bei dem einen.
- test_neutral_category nahm VORHANDENE Kategorien und stellte eine davon auf
  "nicht einrechnen". Benutzten andere Buchungen sie, fielen die mit heraus und
  die Rechnung ging um deren Summe daneben – ohne Bezug zum Gepruefften. Der
  Test legt sich seine Kategorien jetzt selbst an.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 16:02:04 +02:00

Certain Finance

Selbstgehostete Finanzverwaltung für Privathaushalte. Budgets, mehrere Konten (EUR und CHF), ein konfigurierbares Dashboard und Import von Kontoauszügen – lauffähig in einem Proxmox-LXC, erreichbar über eine Web-UI hinter dem eigenen Nginx Proxy Manager.

Der interne Codename/Anzeigename steht zentral an einer Stelle (web/src/brand.js, backend/app/branding.py); der Rest ist generisch.

Stack

  • Backend: FastAPI · SQLAlchemy · SQLite · Alembic · argon2 · Server-Sitzungen (Cookie)
  • Frontend: React 18 · Vite · reines JSX · react-i18next (DE/EN) · Inline-SVG-Icons
  • Betrieb: ein systemd-Dienst (uvicorn) liefert API und gebautes Frontend auf einem Port aus

Entwicklung (lokal)

Backend (Terminal 1):

cd backend
python3 -m venv .venv && . .venv/bin/activate   # Python 3.11+
pip install -r requirements.txt
APP_DATA_DIR=./data uvicorn app.main:app --reload --port 8000

Frontend (Terminal 2):

cd web
npm install
npm run dev        # http://localhost:5173  (leitet /api an :8000 weiter)

Beim ersten Start wird ein Admin angelegt (Standard admin / changeme, per APP_ADMIN_USERNAME / APP_ADMIN_PASSWORD änderbar).

Installation im LXC (Proxmox, Debian/Ubuntu)

git clone <repo-url> /opt/certain-finance
cd /opt/certain-finance
sudo ./deploy/install.sh

Danach im Nginx Proxy Manager einen Proxy-Host auf http://<LXC-IP>:<APP_PORT> anlegen (HTTPS via Let's Encrypt). Updates: sudo ./deploy/update.sh.

Details: docs/ARCHITECTURE.md · Fahrplan: docs/ROADMAP.md

S
Description
No description provided
Readme
8.7 MiB
Languages
Python 55.3%
JavaScript 22.8%
Swift 16.3%
CSS 5%
Shell 0.6%