From 877cba4964cf76a2578087882722084bf7f24eec4d8e6974bbf6e9ac9564adf1 Mon Sep 17 00:00:00 2001 From: wlfb Date: Fri, 17 Jul 2026 17:27:41 +0200 Subject: [PATCH] test: Absolute-Modifier und Stichtag-Semantik der Projektion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ergänzte Tests für Lückenschluss: 1. test_absolute_modifier_reduces_outflow: Absolute Modifier reduziert Ausgaben (-200 - 50 = -150) 2. test_absolute_modifier_clamps_to_zero: Absolute Modifier klemmt auf 0 (nie Vorzeichenflip: -200 + 300 = 0) 3. test_cashflow_on_start_date_excluded: Cashflows am start_date werden ausgeschlossen (Teil des Startsaldos) Alle 18 Tests grün (15 existierend + 3 neu). Co-Authored-By: Claude Fable 5 --- finance/tests/test_projection.py | 10 ++++++++++ finance/tests/test_scenario_engine.py | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/finance/tests/test_projection.py b/finance/tests/test_projection.py index db31b35..7851260 100644 --- a/finance/tests/test_projection.py +++ b/finance/tests/test_projection.py @@ -18,3 +18,13 @@ def test_no_crossing(): p = project(Decimal("100"), date(2026, 7, 31), [], horizon_days=5) assert p.first_below_zero is None assert p.low_point[1] == Decimal("100") + + +def test_cashflow_on_start_date_excluded(): + """Cashflows dated exactly on start_date are excluded (part of starting balance)""" + p = project(Decimal("100"), date(2026, 8, 1), [(date(2026, 8, 1), Decimal("-999"))], + horizon_days=5) + # All balances remain 100 because the -999 flow on start_date is ignored + assert all(bal == Decimal("100") for _, bal in p.series) + assert p.first_below_zero is None + assert p.low_point[1] == Decimal("100") diff --git a/finance/tests/test_scenario_engine.py b/finance/tests/test_scenario_engine.py index b9e0303..8410d55 100644 --- a/finance/tests/test_scenario_engine.py +++ b/finance/tests/test_scenario_engine.py @@ -35,3 +35,25 @@ def test_remove_modifier_and_planned_and_loan(): assert date(2026, 8, 1) in days # Kredit-Auszahlung assert date(2026, 9, 15) in days # Einmalposten assert all(a != Decimal("-50") for _, a in flows) # Abo entfernt + + +def test_absolute_modifier_reduces_outflow(): + """Test absolute modifier for outflows: -200 - 50 = -150""" + rec = [PlainRecurring(id=1, name="Marketing", amount=Decimal("-200"), + rhythm="monthly", due_day=10, start_date=None, + end_date=None, category_id=3)] + mods = [PlainModifier(target_type="category", target_id=3, + kind="absolute", value=Decimal("50"))] + flows = build_cashflows(rec, [], [], [], mods, date(2026, 8, 1), date(2026, 8, 31)) + assert flows == [(date(2026, 8, 10), Decimal("-150.00"))] + + +def test_absolute_modifier_clamps_to_zero(): + """Test absolute modifier clamping: -200 + 300 = 0 (never flips sign)""" + rec = [PlainRecurring(id=1, name="Marketing", amount=Decimal("-200"), + rhythm="monthly", due_day=10, start_date=None, + end_date=None, category_id=3)] + mods = [PlainModifier(target_type="category", target_id=3, + kind="absolute", value=Decimal("300"))] + flows = build_cashflows(rec, [], [], [], mods, date(2026, 8, 1), date(2026, 8, 31)) + assert flows == [(date(2026, 8, 10), Decimal("0.00"))]