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>
This commit is contained in:
Guido
2026-08-27 16:02:04 +02:00
co-authored by Claude Opus 5
parent 1b47e5abe1
commit f2c1ab7dec
8 changed files with 314 additions and 12 deletions
+17 -5
View File
@@ -10,12 +10,24 @@ import datetime
def _expense_cats(admin, n=2):
"""EIGENE Kategorien anlegen, keine vorhandenen nehmen.
Der Test stellt eine davon spaeter auf "nicht einrechnen". Nimmt er eine
Kategorie, die andere Buchungen schon benutzen, fallen die mit heraus – und
die Rechnung geht um deren Summe daneben, ohne dass es mit dem zu tun hat,
was hier geprueft wird.
"""
import secrets
gruppe = next(g for g in admin.get("/api/categories").json()
if g["kind"] == "expense")
out = []
for g in admin.get("/api/categories").json():
if g["kind"] == "expense":
out += g["categories"]
assert len(out) >= n
return out[:n]
for i in range(n):
r = admin.post("/api/categories", json={
"group_id": gruppe["id"], "name": f"Neutral-Test {i} {secrets.token_hex(3)}"})
assert r.status_code == 201, r.text
out.append(r.json())
return out
def _ausgaben(admin):