chore: Release v0.13.0 (Seite Aufteilung)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+42
-7
@@ -18,11 +18,11 @@ direkt aus `routers/gui.py`.
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph TPL["templates (Jinja2, app/templates/)"]
|
||||
T_pages["base.html, login.html, index.html<br/>transactions.html, salden.html<br/>import.html, planning.html<br/>admin.html, hilfe.html"]
|
||||
T_pages["base.html, login.html, index.html<br/>transactions.html, salden.html<br/>import.html, planning.html<br/>admin.html, hilfe.html<br/>aufteilung.html"]
|
||||
end
|
||||
|
||||
subgraph ROUTERS["routers/"]
|
||||
R_gui["gui.py<br/>gui_session, index, buchungen,<br/>salden_page, import_page, planung_page"]
|
||||
R_gui["gui.py<br/>gui_session, index, buchungen,<br/>salden_page, import_page, planung_page,<br/>aufteilung_page, aufteilung_kategorie_fragment"]
|
||||
R_accounts["accounts.py<br/>list_accounts, create_account,<br/>patch_account"]
|
||||
R_transactions["transactions.py<br/>list_transactions, create_transaction,<br/>patch_transaction, count_transactions"]
|
||||
R_categories["categories.py<br/>list_categories, create_category_rule"]
|
||||
@@ -37,7 +37,8 @@ flowchart TD
|
||||
S_balances["balances.py<br/>account_balance(at), total_balance"]
|
||||
S_categorize["categorize.py<br/>apply_rules"]
|
||||
S_suggestions["suggestions.py<br/>suggest_recurring"]
|
||||
S_projection["projection_service.py<br/>run_projection, refresh_stale_projections"]
|
||||
S_projection["projection_service.py<br/>run_projection, load_scenario_inputs,<br/>refresh_stale_projections"]
|
||||
S_breakdown["breakdown.py<br/>compute_breakdown"]
|
||||
S_planning_chart["planning_chart.py<br/>refresh_planning_chart"]
|
||||
S_admin["admin.py<br/>change_password, apply_rules_retroactively"]
|
||||
S_doublecount["double_count.py<br/>all_conflicts, conflicts_for_recurring,<br/>conflicts_for_loan"]
|
||||
@@ -50,6 +51,8 @@ flowchart TD
|
||||
E_recurrence["recurrence.py<br/>occurrences"]
|
||||
E_projection["projection.py<br/>project"]
|
||||
E_scenario["scenario.py<br/>build_cashflows (PlainRecurring/<br/>PlainPlanned/PlainModifier)"]
|
||||
E_breakdown["breakdown.py<br/>breakdown_rows, summarize,<br/>category_rows, share"]
|
||||
E_pie["pie.py<br/>pie_slices"]
|
||||
end
|
||||
|
||||
subgraph PARSERS["parsers/"]
|
||||
@@ -94,6 +97,9 @@ flowchart TD
|
||||
R_scenarios --> N_reserved
|
||||
R_categories --> N_reserved
|
||||
R_gui --> S_doublecount
|
||||
R_gui --> S_breakdown
|
||||
R_gui --> E_breakdown
|
||||
R_gui --> E_pie
|
||||
R_admin --> S_admin
|
||||
|
||||
ROUTERS -.-> M_tables
|
||||
@@ -106,6 +112,10 @@ flowchart TD
|
||||
S_projection --> E_projection
|
||||
S_projection --> E_scenario
|
||||
S_projection --> S_balances
|
||||
S_breakdown --> S_projection
|
||||
S_breakdown --> E_breakdown
|
||||
S_breakdown --> E_loans
|
||||
S_breakdown --> S_doublecount
|
||||
S_planning_chart --> E_loans
|
||||
S_planning_chart --> E_recurrence
|
||||
S_planning_chart --> M_tables
|
||||
@@ -113,6 +123,8 @@ flowchart TD
|
||||
|
||||
E_scenario --> E_loans
|
||||
E_scenario --> E_recurrence
|
||||
E_breakdown --> E_scenario
|
||||
E_breakdown --> E_recurrence
|
||||
|
||||
P_registry --> P_vr
|
||||
P_registry --> P_hvb
|
||||
@@ -304,12 +316,15 @@ nur noch über `rollback` (löscht Statement + Transaktionen komplett) zu
|
||||
entfernen, nicht mehr über `DELETE /api/imports/{id}` (nur für Entwürfe und Fehl-Importe).
|
||||
|
||||
**Szenario-Engine ist rein.** `app/engine/*` (`loans.py`, `recurrence.py`,
|
||||
`projection.py`, `scenario.py`) hat **keinen** Datenbank- oder
|
||||
Request-Zugriff — nur `scenario.py` importiert innerhalb der Engine von
|
||||
`loans.py`/`recurrence.py`, sonst keine Abhängigkeiten auf `app.*`. Ein-/
|
||||
`projection.py`, `scenario.py`, `breakdown.py`, `pie.py`) hat **keinen**
|
||||
Datenbank- oder Request-Zugriff — `scenario.py` und `breakdown.py`
|
||||
importieren innerhalb der Engine (`loans.py`/`recurrence.py`/`scenario.py`),
|
||||
sonst keine Abhängigkeiten auf `app.*`. Ein-/
|
||||
Ausgaben sind einfache Dataclasses (`Installment`, `PlainRecurring`,
|
||||
`PlainPlanned`, `PlainModifier`, `Projection`). `services/projection_service.py`
|
||||
ist die einzige Brücke: es lädt ORM-Objekte (`Loan`, `RecurringItem`,
|
||||
ist die einzige Brücke: `load_scenario_inputs(session, scenario)` ist die
|
||||
gemeinsame Ladefunktion (`None` = System-Plan, ohne Szenario-Änderungen)
|
||||
und lädt ORM-Objekte (`Loan`, `RecurringItem`,
|
||||
`PlannedItem`, `Scenario`, `ScenarioModifier`), baut daraus die Plain-Objekte
|
||||
und ruft `engine.scenario.build_cashflows` → `engine.projection.project`.
|
||||
|
||||
@@ -352,6 +367,26 @@ Formular (`data-doppelzaehlung-bestaetigt="1"`) und sendet es erneut, die
|
||||
einen dauerhaften ⚠-Hinweis je betroffenem Posten/Kredit in `planning.html`,
|
||||
solange der Konflikt fortbesteht.
|
||||
|
||||
**Aufteilung (Ausbaustufe 13).** `/aufteilung` (`routers/gui.py::aufteilung_page`,
|
||||
GET-Formular, die Auswahl steht in der URL) zeigt für einen Monat die Kosten
|
||||
je Kategorie aus reiner Planung, nie aus Ist-Buchungen.
|
||||
`services/breakdown.py::compute_breakdown` lädt die Planung über
|
||||
`load_scenario_inputs`; `PLAN_NAME` („System-Plan") entspricht
|
||||
`load_scenario_inputs(session, None)`, ein Szenario wird mit seinen
|
||||
Änderungen und Krediten gerechnet. Die Rechenregeln stehen in
|
||||
`engine/breakdown.py` (`breakdown_rows`, `summarize`, `category_rows`,
|
||||
`share`): Fixposten werden per `recurrence.STEP` auf den Monat normalisiert
|
||||
(vierteljährlich ÷ 3, jährlich ÷ 12), Einmalposten und Kreditraten zählen
|
||||
voll im Fälligkeitsmonat, eine Kredit-Auszahlung nie als Einkunft; `FREI`
|
||||
(„Frei verfügbar") ist der Rest der Einkünfte. Das Tortendiagramm entsteht
|
||||
serverseitig in `engine/pie.py::pie_slices` (`MIN_SHARE` 3 %, `MAX_NAMED` 8,
|
||||
Sammelsegment `UEBRIGE`). Drill-down: `GET /aufteilung/kategorie`
|
||||
(`aufteilung_kategorie_fragment`) liefert die Posten der Kategorie und
|
||||
tauscht die Haupttorte per `hx-swap-oob` aus (gewähltes Segment markiert);
|
||||
`sammel=1` wählt die Sammelgruppe „Übrige". Der Doppelzählungs-Hinweis nutzt
|
||||
`services/double_count.py::all_conflicts`. Keine Tabelle, keine View,
|
||||
Grafana unberührt.
|
||||
|
||||
**Abgeleitete Tabellen + Advisory-Locks (Ausbaustufe 11).** Zwei Datenstände
|
||||
werden bei GUI-Seitenaufrufen automatisch aufgefrischt, nie beim reinen
|
||||
API-Zugriff (`routers/gui.py::_safe_refresh`, fehlerresistent — ein Fehler
|
||||
|
||||
Reference in New Issue
Block a user