From e8ea948b38e4a389d7efebdb09cc49347564f9afafb24e3ce1d4f46e2766a6a9 Mon Sep 17 00:00:00 2001 From: wlfb Date: Fri, 17 Jul 2026 18:38:52 +0200 Subject: [PATCH] test: Vorschlagslogik suggest_recurring abgedeckt Co-Authored-By: Claude Fable 5 --- finance/tests/test_planning_api.py | 56 +++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/finance/tests/test_planning_api.py b/finance/tests/test_planning_api.py index 987c534..d4308f6 100644 --- a/finance/tests/test_planning_api.py +++ b/finance/tests/test_planning_api.py @@ -1,7 +1,8 @@ from datetime import date from decimal import Decimal -from app.models.tables import Account, Statement +from app.models.tables import Account, Category, RecurringItem, Statement, Transaction +from app.services.suggestions import suggest_recurring H = {"Authorization": "Bearer test-key"} @@ -45,3 +46,56 @@ def test_loan_in_scenario_keeps_balance_positive(client, db): body = client.post(f"/api/scenarios/{sc['id']}/project", headers=H, params={"horizon_days": 92, "start_date": "2026-07-15"}).json() assert Decimal(body["low_point_balance"]) > Decimal("0") + + +def _tx(acc, d, amount, counterparty, dedup, category_id=None): + return Transaction(account_id=acc.id, booking_date=d, amount=Decimal(amount), + purpose="", counterparty=counterparty, status="confirmed", + dedup_hash=dedup, category_id=category_id) + + +def test_suggest_recurring_three_consecutive_months_with_year_wrap(db): + acc = Account(bank="dkb", iban="DE01", name="G", type="giro") + db.add(acc) + db.flush() + cat = Category(name="Miete") + db.add(cat) + db.flush() + # Dez 2025 -> Jan 2026 -> Feb 2026: 3 aufeinanderfolgende Monate ueber den + # Jahreswechsel hinweg (prueft die Monats-Linearisierung y*12+m). + db.add(_tx(acc, date(2025, 12, 1), "-600.00", "Vermieter", "h1", cat.id)) + db.add(_tx(acc, date(2026, 1, 15), "-600.00", "Vermieter", "h2", cat.id)) + db.add(_tx(acc, date(2026, 2, 28), "-600.00", "Vermieter", "h3", cat.id)) + db.commit() + + out = suggest_recurring(db) + + # Median der Tage [1, 15, 28] = 15; Betrag unveraendert uebernommen. + assert out == [{"name": "Vermieter", "amount": Decimal("-600.00"), + "rhythm": "monthly", "due_day": 15, "category_id": cat.id}] + + +def test_suggest_recurring_two_months_no_suggestion(db): + acc = Account(bank="dkb", iban="DE01", name="G", type="giro") + db.add(acc) + db.flush() + db.add(_tx(acc, date(2026, 3, 10), "-50.00", "Zweimonatig", "h1")) + db.add(_tx(acc, date(2026, 4, 10), "-50.00", "Zweimonatig", "h2")) + db.commit() + + assert suggest_recurring(db) == [] + + +def test_suggest_recurring_excludes_existing_recurring_item(db): + acc = Account(bank="dkb", iban="DE01", name="G", type="giro") + db.add(acc) + db.flush() + db.add(_tx(acc, date(2026, 1, 5), "-30.00", "Streaming", "h1")) + db.add(_tx(acc, date(2026, 2, 5), "-30.00", "Streaming", "h2")) + db.add(_tx(acc, date(2026, 3, 5), "-30.00", "Streaming", "h3")) + db.add(RecurringItem(name="Streaming", amount=Decimal("-30.00"), + rhythm="monthly", due_day=5)) + db.commit() + + # Gleicher Name + Betrag wie ein bereits vorhandenes RecurringItem -> ausgelassen. + assert suggest_recurring(db) == []