fix: Bestandsabgleich per Token-Match und Volatilitaets-Hinweis fuer Vorschlaege
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -253,6 +253,13 @@ def test_suggest_zwei_vertraege_getrennt(db):
|
||||
out = suggest_recurring(db, today=TODAY)
|
||||
assert len(out) == 2
|
||||
assert {s["amount"] for s in out} == {Decimal("-346.23"), Decimal("-145.21")}
|
||||
# Nachtrag 3b: beide Vertraege sind fuer sich genommen stabile,
|
||||
# qualifizierte Serien - die jeweils neuere Buchung des ANDEREN Vertrags
|
||||
# gehoert selbst zu einer qualifizierten Serie und darf deshalb NICHT als
|
||||
# "abgetrennte neueste Buchung" gewertet werden (sonst waere einer der
|
||||
# beiden faelschlich als "volatil" markiert, nur weil der andere Vertrag
|
||||
# einen Tag spaeter faellig ist).
|
||||
assert all(s["hinweis"] == "" for s in out)
|
||||
|
||||
|
||||
def test_try_merge_kombiniert_serien_ueber_gruppengrenzen():
|
||||
@@ -320,3 +327,43 @@ def test_suggest_umfirmierung_merge_verschiebt_kategorie_mehrheit(db):
|
||||
assert out[0]["name"] == "Neue Firma GmbH" and out[0]["amount"] == Decimal("-52.00")
|
||||
# Kategorie-Mehrheit kippt durch den Merge von B (3) auf A (4):
|
||||
assert out[0]["category_id"] == cat_a.id
|
||||
|
||||
|
||||
# ------------------------------------------------- Nachtrag 4 (A9-Live-Gate-Fund)
|
||||
# Echter Fall aus dem Live-Gate: Fixposten 44 "Mastercard-Abrechnung Volksbank
|
||||
# (variabel, letzter Wert)" (monthly, due_day 7, -296.07) deckte den Vorschlag
|
||||
# "Volksbank Ulm-Biberach eG" (monthly, due_day 5, -584.43) nicht ab, weil
|
||||
# weder Substring- noch Betrags-Toleranz-Regel griffen. Betraege/Namen hier
|
||||
# synthetisch nachgebildet (keine echten Kontodaten, siehe CLAUDE.md).
|
||||
|
||||
def test_suggest_alias_recurring_item_token_match(db):
|
||||
acc = _acc(db)
|
||||
db.add(RecurringItem(name="Mastercard-Abrechnung Volksbank (variabel, letzter Wert)",
|
||||
amount=Decimal("-296.07"), rhythm="monthly", due_day=7))
|
||||
for d, a in [(date(2026, 4, 5), "-560.00"), (date(2026, 5, 5), "-580.00"),
|
||||
(date(2026, 6, 5), "-590.00"), (date(2026, 7, 5), "-580.00")]:
|
||||
_tx(db, acc, d, a, "Volksbank Ulm-Biberach eG")
|
||||
db.commit()
|
||||
|
||||
# Substring-Match (a) schlaegt fehl (kein Teilstring gemeinsam), Betrags-
|
||||
# Toleranz (b) auch (-580 vs. -296.07, >10%) - erst der Token-Match (c)
|
||||
# ueber das gemeinsame Token "volksbank" (Rhythmus gleich, due_day 5 vs. 7
|
||||
# -> Differenz 2 <= 2) deckt den Vorschlag ab.
|
||||
assert suggest_recurring(db, today=TODAY) == []
|
||||
|
||||
|
||||
def test_suggest_volatilitaetshinweis_bei_abgetrennter_neuester_buchung(db):
|
||||
acc = _acc(db)
|
||||
for d in [date(2026, 1, 5), date(2026, 2, 5), date(2026, 3, 5), date(2026, 4, 5)]:
|
||||
_tx(db, acc, d, "-200.00", "Schwankender Anbieter GmbH")
|
||||
# Neueste Buchung weicht >35% vom Serien-Betrag ab -> eigener Cluster,
|
||||
# klassifiziert selbst nicht (nur 1 Buchung) -> die vorgeschlagene Serie
|
||||
# bleibt die -200.00-Serie, aber mit Volatilitaets-Warnhinweis.
|
||||
_tx(db, acc, date(2026, 5, 5), "-600.00", "Schwankender Anbieter GmbH")
|
||||
db.commit()
|
||||
|
||||
out = suggest_recurring(db, today=date(2026, 5, 20))
|
||||
|
||||
assert len(out) == 1
|
||||
assert out[0]["amount"] == Decimal("-200.00") # Betrag NICHT durch die 600er-Buchung verfaelscht
|
||||
assert "schwanken" in out[0]["hinweis"].lower()
|
||||
|
||||
Reference in New Issue
Block a user