fix: Szenario-Vergleich zeigt vor heute Ist-Saldo, veraltete Szenarien werden neu gerechnet (A11-T2)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-28 19:10:51 +02:00
co-authored by Claude Opus 5.5
parent 32d78fdbe1
commit 979e1c0edc
7 changed files with 261 additions and 5 deletions
+20
View File
@@ -1,5 +1,7 @@
import logging
from datetime import date, timedelta
from decimal import Decimal
from typing import Callable
from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi.templating import Jinja2Templates
@@ -25,6 +27,7 @@ from app.routers.planning import recurring_suggestions as _recurring_suggestions
from app.routers.scenarios import list_scenarios as _list_scenarios
from app.routers.transactions import count_transactions, list_transactions
from app.services.balances import account_balance, total_balance
from app.services.projection_service import refresh_stale_projections
from app.version import get_version
PAGE_SIZE = 50
@@ -51,6 +54,21 @@ templates.env.filters["eur"] = eur
templates.env.filters["de_label"] = de_label
router = APIRouter()
log = logging.getLogger(__name__)
def _safe_refresh(session: Session, refresh: Callable[[Session, date], object],
today: date) -> None:
"""Frischt abgeleitete Daten (Projektionen, Planungs-Diagramm) vor dem
Rendern auf. Ein Fehler darf die Seite nie brechen: rollback, Warnung ins
Log, die Seite rendert mit dem vorhandenen Stand."""
try:
refresh(session, today)
except Exception:
session.rollback()
log.warning("Auffrischen fehlgeschlagen: %s",
getattr(refresh, "__name__", refresh), exc_info=True)
def gui_session(request: Request):
if not session_valid(request.cookies.get(COOKIE)):
@@ -127,6 +145,7 @@ def _month_starts_desc(session: Session, today: date) -> list[date]:
@router.get("/", dependencies=[Depends(gui_session)])
def index(request: Request, session: Session = Depends(get_session)):
_safe_refresh(session, refresh_stale_projections, date.today())
accounts = session.execute(select(Account)).scalars().all()
balances = [(a, account_balance(session, a)) for a in accounts]
return templates.TemplateResponse(request, "index.html", {
@@ -323,6 +342,7 @@ def planung_page(request: Request, session: Session = Depends(get_session)):
@router.get("/szenarien", dependencies=[Depends(gui_session)])
def szenarien_page(request: Request, session: Session = Depends(get_session)):
_safe_refresh(session, refresh_stale_projections, date.today())
categories = session.execute(select(Category)).scalars().all()
recurring = _list_recurring(session=session)
loans = _list_loans(session=session)