from datetime import date from decimal import Decimal from app.engine.scenario import (PlainModifier, PlainRecurring, effective_end, modified_amount) from app.models.tables import (Loan, PlannedItem, RecurringItem, Scenario, ScenarioLoan, ScenarioModifier, ScenarioPlannedItem) from app.services.projection_service import load_scenario_inputs def test_modifikator_helfer_oeffentlich(): mods = [PlainModifier("recurring", 1, "percent", Decimal("10")), PlainModifier("recurring", 1, "ende", Decimal("0"), date(2030, 6, 30))] assert modified_amount(Decimal("-100.00"), None, 1, mods) == Decimal("-90.00") assert modified_amount(Decimal("-100.00"), None, 2, mods) == Decimal("-100.00") r = PlainRecurring(1, "R", Decimal("-100.00"), "monthly", 1, None, date(2030, 12, 31), None) assert effective_end(r, mods) == date(2030, 6, 30) def _daten(db): rec = RecurringItem(name="R", amount=Decimal("-10.00"), rhythm="monthly", due_day=1) pln = PlannedItem(name="P", amount=Decimal("-20.00"), due=date(2030, 1, 1)) k1 = Loan(name="K1", principal=Decimal("100.00"), annual_rate_pct=Decimal("0"), term_months=2, payout_date=date(2030, 1, 1), repayment_type="annuity") k2 = Loan(name="K2", principal=Decimal("200.00"), annual_rate_pct=Decimal("0"), term_months=2, payout_date=date(2030, 1, 1), repayment_type="annuity") sc = Scenario(name="S", description="", include_recurring=True, include_planned=False) db.add_all([rec, pln, k1, k2, sc]) db.flush() db.add_all([ ScenarioLoan(scenario_id=sc.id, loan_id=k1.id), ScenarioModifier(scenario_id=sc.id, target_type="recurring", target_id=rec.id, kind="percent", value=Decimal("50")), ScenarioPlannedItem(scenario_id=sc.id, name="SP", amount=Decimal("-5.00"), due=date(2030, 2, 1)), ]) db.commit() return sc def test_load_scenario_inputs_szenario(db): sc = _daten(db) inp = load_scenario_inputs(db, sc) assert [r.name for r in inp.recurring] == ["R"] # include_planned=False: globale Einmalposten fehlen, Szenario-eigene zählen immer. assert [p.name for p in inp.planned] == ["SP"] assert inp.planned[0].category_id is None assert [l.name for l in inp.loans] == ["K1"] assert [(m.kind, m.value) for m in inp.modifiers] == [("percent", Decimal("50"))] def test_load_scenario_inputs_ohne_fixposten(db): sc = _daten(db) sc.include_recurring = False db.commit() assert load_scenario_inputs(db, sc).recurring == [] def test_load_scenario_inputs_system_plan(db): _daten(db) inp = load_scenario_inputs(db, None) assert [r.name for r in inp.recurring] == ["R"] assert [p.name for p in inp.planned] == ["P"] assert [l.name for l in inp.loans] == ["K1", "K2"] assert inp.modifiers == []