feat: Szenario-Einträge je Stichtag mit Zeitraum und Art Neuer Betrag (A14-T2)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-30 13:00:18 +02:00
co-authored by Claude Opus 5.5
parent b0a1ba80a1
commit aaf05b9209
7 changed files with 144 additions and 25 deletions
+6 -4
View File
@@ -3,7 +3,8 @@
Rein (kein DB-Zugriff). Fixposten werden auf den Monat normalisiert
(quartalsweise /3, jährlich /12), Einmalposten und Kreditraten zählen voll
im Monat ihrer Fälligkeit; die Kredit-Auszahlung zählt nie. Modifikatoren
wirken exakt wie in build_cashflows (gleiche Helfer).
wirken wie in build_cashflows (gleiche Helfer); Stichtag je Fixposten ist sein
Fälligkeitstag im Monat, je Einmalposten das Fälligkeitsdatum.
"""
import calendar
from collections import defaultdict
@@ -12,7 +13,7 @@ from datetime import date
from decimal import ROUND_HALF_UP, Decimal
from app.engine.loans import Installment
from app.engine.recurrence import STEP
from app.engine.recurrence import STEP, due_in_month
from app.engine.scenario import (CENT, PlainModifier, PlainPlanned,
PlainRecurring, effective_end, modified_amount)
@@ -77,7 +78,8 @@ def breakdown_rows(month: date, recurring: list[PlainRecurring],
end = effective_end(r, modifiers)
if end is not None and end < first:
continue
amount = modified_amount(r.amount, r.category_id, r.id, modifiers)
amount = modified_amount(r.amount, r.category_id, r.id, modifiers,
on=due_in_month(first, r.due_day))
if amount is None:
continue
monthly = (amount / STEP[r.rhythm]).quantize(CENT, ROUND_HALF_UP)
@@ -87,7 +89,7 @@ def breakdown_rows(month: date, recurring: list[PlainRecurring],
for p in planned:
if not first <= p.due <= last:
continue
amount = modified_amount(p.amount, p.category_id, None, modifiers)
amount = modified_amount(p.amount, p.category_id, None, modifiers, on=p.due)
if amount is None:
continue
out.append(BreakdownRow(p.name, cat(p.category_id), "planned", None,