fix: neutrale Kategorien gelten für Ausgabe UND Einnahme
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>
This commit is contained in:
@@ -222,7 +222,7 @@ def _match_rule(
|
||||
purpose: str,
|
||||
amount: int | None,
|
||||
allowed_kind: CategoryKind | None,
|
||||
cat_kind: dict[int, CategoryKind],
|
||||
cat_kind: dict[int, CategoryKind | None],
|
||||
) -> CategorizationRule | None:
|
||||
"""Erste passende Regel (Muster + optionale Betragsbedingung). Kategorie-Regeln
|
||||
greifen nur, wenn die Kategorie-Art (Einnahme/Ausgabe) zur Buchung passt;
|
||||
@@ -241,7 +241,10 @@ def _match_rule(
|
||||
continue
|
||||
if not rule.category_id:
|
||||
continue
|
||||
if allowed_kind is not None and cat_kind.get(rule.category_id) != allowed_kind:
|
||||
# Neutrale Kategorien („Kontoübertrag") passen in beide Richtungen: Geld
|
||||
# geht auf dem einen Konto raus und kommt auf dem anderen rein.
|
||||
art = cat_kind.get(rule.category_id)
|
||||
if allowed_kind is not None and art is not None and art != allowed_kind:
|
||||
continue
|
||||
if _pattern_hit(rule, p, z):
|
||||
return rule
|
||||
@@ -410,9 +413,12 @@ def detect_rows(db: Session, user: User, account: Account, candidates: list[dict
|
||||
|
||||
rules = db.query(CategorizationRule).filter(CategorizationRule.owner_id == user.id).all()
|
||||
rules.sort(key=_rule_sort_key, reverse=True) # längstes/manuell zuerst
|
||||
cat_kind: dict[int, CategoryKind] = {
|
||||
cid: kind
|
||||
for cid, kind in db.query(Category.id, Category.type).filter(Category.owner_id == user.id)
|
||||
# None = neutral: zählt für Ausgabe UND Einnahme (siehe _match_rule).
|
||||
cat_kind: dict[int, CategoryKind | None] = {
|
||||
cid: (None if neutral else kind)
|
||||
for cid, kind, neutral in db.query(
|
||||
Category.id, Category.type, Category.excluded_from_stats
|
||||
).filter(Category.owner_id == user.id)
|
||||
}
|
||||
# Duplikate als Multiset zählen: eine Zeile gilt nur dann als Duplikat, wenn
|
||||
# bereits GENAU SO VIELE identische Buchungen in der DB stehen. So werden echte,
|
||||
|
||||
Reference in New Issue
Block a user