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
|
```mermaid
|
||||||
flowchart TD
|
flowchart TD
|
||||||
subgraph TPL["templates (Jinja2, app/templates/)"]
|
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
|
end
|
||||||
|
|
||||||
subgraph ROUTERS["routers/"]
|
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_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_transactions["transactions.py<br/>list_transactions, create_transaction,<br/>patch_transaction, count_transactions"]
|
||||||
R_categories["categories.py<br/>list_categories, create_category_rule"]
|
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_balances["balances.py<br/>account_balance(at), total_balance"]
|
||||||
S_categorize["categorize.py<br/>apply_rules"]
|
S_categorize["categorize.py<br/>apply_rules"]
|
||||||
S_suggestions["suggestions.py<br/>suggest_recurring"]
|
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_planning_chart["planning_chart.py<br/>refresh_planning_chart"]
|
||||||
S_admin["admin.py<br/>change_password, apply_rules_retroactively"]
|
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"]
|
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_recurrence["recurrence.py<br/>occurrences"]
|
||||||
E_projection["projection.py<br/>project"]
|
E_projection["projection.py<br/>project"]
|
||||||
E_scenario["scenario.py<br/>build_cashflows (PlainRecurring/<br/>PlainPlanned/PlainModifier)"]
|
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
|
end
|
||||||
|
|
||||||
subgraph PARSERS["parsers/"]
|
subgraph PARSERS["parsers/"]
|
||||||
@@ -94,6 +97,9 @@ flowchart TD
|
|||||||
R_scenarios --> N_reserved
|
R_scenarios --> N_reserved
|
||||||
R_categories --> N_reserved
|
R_categories --> N_reserved
|
||||||
R_gui --> S_doublecount
|
R_gui --> S_doublecount
|
||||||
|
R_gui --> S_breakdown
|
||||||
|
R_gui --> E_breakdown
|
||||||
|
R_gui --> E_pie
|
||||||
R_admin --> S_admin
|
R_admin --> S_admin
|
||||||
|
|
||||||
ROUTERS -.-> M_tables
|
ROUTERS -.-> M_tables
|
||||||
@@ -106,6 +112,10 @@ flowchart TD
|
|||||||
S_projection --> E_projection
|
S_projection --> E_projection
|
||||||
S_projection --> E_scenario
|
S_projection --> E_scenario
|
||||||
S_projection --> S_balances
|
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_loans
|
||||||
S_planning_chart --> E_recurrence
|
S_planning_chart --> E_recurrence
|
||||||
S_planning_chart --> M_tables
|
S_planning_chart --> M_tables
|
||||||
@@ -113,6 +123,8 @@ flowchart TD
|
|||||||
|
|
||||||
E_scenario --> E_loans
|
E_scenario --> E_loans
|
||||||
E_scenario --> E_recurrence
|
E_scenario --> E_recurrence
|
||||||
|
E_breakdown --> E_scenario
|
||||||
|
E_breakdown --> E_recurrence
|
||||||
|
|
||||||
P_registry --> P_vr
|
P_registry --> P_vr
|
||||||
P_registry --> P_hvb
|
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).
|
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`,
|
**Szenario-Engine ist rein.** `app/engine/*` (`loans.py`, `recurrence.py`,
|
||||||
`projection.py`, `scenario.py`) hat **keinen** Datenbank- oder
|
`projection.py`, `scenario.py`, `breakdown.py`, `pie.py`) hat **keinen**
|
||||||
Request-Zugriff — nur `scenario.py` importiert innerhalb der Engine von
|
Datenbank- oder Request-Zugriff — `scenario.py` und `breakdown.py`
|
||||||
`loans.py`/`recurrence.py`, sonst keine Abhängigkeiten auf `app.*`. Ein-/
|
importieren innerhalb der Engine (`loans.py`/`recurrence.py`/`scenario.py`),
|
||||||
|
sonst keine Abhängigkeiten auf `app.*`. Ein-/
|
||||||
Ausgaben sind einfache Dataclasses (`Installment`, `PlainRecurring`,
|
Ausgaben sind einfache Dataclasses (`Installment`, `PlainRecurring`,
|
||||||
`PlainPlanned`, `PlainModifier`, `Projection`). `services/projection_service.py`
|
`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
|
`PlannedItem`, `Scenario`, `ScenarioModifier`), baut daraus die Plain-Objekte
|
||||||
und ruft `engine.scenario.build_cashflows` → `engine.projection.project`.
|
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`,
|
einen dauerhaften ⚠-Hinweis je betroffenem Posten/Kredit in `planning.html`,
|
||||||
solange der Konflikt fortbesteht.
|
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
|
**Abgeleitete Tabellen + Advisory-Locks (Ausbaustufe 11).** Zwei Datenstände
|
||||||
werden bei GUI-Seitenaufrufen automatisch aufgefrischt, nie beim reinen
|
werden bei GUI-Seitenaufrufen automatisch aufgefrischt, nie beim reinen
|
||||||
API-Zugriff (`routers/gui.py::_safe_refresh`, fehlerresistent — ein Fehler
|
API-Zugriff (`routers/gui.py::_safe_refresh`, fehlerresistent — ein Fehler
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
0.12.0
|
0.13.0
|
||||||
|
|||||||
@@ -91,6 +91,24 @@
|
|||||||
Passwort wie hier anmelden, dann erscheint das Dashboard auch in der
|
Passwort wie hier anmelden, dann erscheint das Dashboard auch in der
|
||||||
Übersicht.
|
Übersicht.
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Aufteilung:</strong> zeigt für einen Monat, welche monatlichen
|
||||||
|
Kosten je Kategorie anfallen und wie viel der Einkünfte frei verfügbar
|
||||||
|
bleibt. Grundlage ist immer die Planung (Fixposten, Einmalposten,
|
||||||
|
Kredite), nie die tatsächlichen Buchungen: „System-Plan" rechnet mit
|
||||||
|
allen Posten und Krediten ohne Szenario-Änderungen und ist für jeden
|
||||||
|
Monat wählbar; ein Szenario (mit seinen Änderungen und Krediten) erst ab
|
||||||
|
dem laufenden Monat. Fixposten werden auf den Monat umgerechnet
|
||||||
|
(vierteljährlich ÷ 3, jährlich ÷ 12), Einmalposten und Kreditraten zählen
|
||||||
|
voll im Monat ihrer Fälligkeit, eine Kredit-Auszahlung zählt nicht als
|
||||||
|
Einkunft. Die Häkchen „Fixposten", „Einmalposten", „Kredite" gelten für
|
||||||
|
Einnahmen und Ausgaben. Das Tortendiagramm zeigt die Einkünfte (Kosten je
|
||||||
|
Kategorie plus „Frei verfügbar"); übersteigen die Kosten die Einkünfte,
|
||||||
|
zeigt es die Gesamtkosten. Kleine Kategorien (unter 3 %, bzw. ab der
|
||||||
|
neunten) sind zu „Übrige" zusammengefasst – höchstens 8 benannte
|
||||||
|
Kategorien plus „Übrige" und „Frei verfügbar". Ein Klick auf ein Segment oder
|
||||||
|
einen Legendeneintrag zeigt darunter die Posten dieser Kategorie.
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
Reference in New Issue
Block a user