chore: Release v0.12.0 (System-Präfix, Doppelzählungs-Warnung)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+35
-1
@@ -40,8 +40,11 @@ flowchart TD
|
|||||||
S_projection["projection_service.py<br/>run_projection, refresh_stale_projections"]
|
S_projection["projection_service.py<br/>run_projection, refresh_stale_projections"]
|
||||||
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"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
N_reserved["app/reserved.py<br/>check_reserved_name"]
|
||||||
|
|
||||||
subgraph ENGINE["engine/ (rein, kein DB-Zugriff)"]
|
subgraph ENGINE["engine/ (rein, kein DB-Zugriff)"]
|
||||||
E_loans["loans.py<br/>loan_schedule, annuity_payment, add_months"]
|
E_loans["loans.py<br/>loan_schedule, annuity_payment, add_months"]
|
||||||
E_recurrence["recurrence.py<br/>occurrences"]
|
E_recurrence["recurrence.py<br/>occurrences"]
|
||||||
@@ -86,7 +89,11 @@ flowchart TD
|
|||||||
R_imports --> S_importer
|
R_imports --> S_importer
|
||||||
R_planning --> E_loans
|
R_planning --> E_loans
|
||||||
R_planning --> S_suggestions
|
R_planning --> S_suggestions
|
||||||
|
R_planning --> S_doublecount
|
||||||
R_scenarios --> S_projection
|
R_scenarios --> S_projection
|
||||||
|
R_scenarios --> N_reserved
|
||||||
|
R_categories --> N_reserved
|
||||||
|
R_gui --> S_doublecount
|
||||||
R_admin --> S_admin
|
R_admin --> S_admin
|
||||||
|
|
||||||
ROUTERS -.-> M_tables
|
ROUTERS -.-> M_tables
|
||||||
@@ -315,9 +322,36 @@ heute), je bereits durchgerechnetem Szenario einen Startpunkt exakt heute
|
|||||||
Projektionspunkte NACH heute (`projection_points`, `day > CURRENT_DATE`) —
|
Projektionspunkte NACH heute (`projection_points`, `day > CURRENT_DATE`) —
|
||||||
Punkte <= heute aus einer älteren Berechnung erscheinen so nie.
|
Punkte <= heute aus einer älteren Berechnung erscheinen so nie.
|
||||||
`RESERVED_SCENARIO_NAME` ist für Szenario-Namen gesperrt:
|
`RESERVED_SCENARIO_NAME` ist für Szenario-Namen gesperrt:
|
||||||
`routers/scenarios.py::_check_reserved_name` lehnt `POST`/`PATCH` mit diesem
|
`app/reserved.py::check_reserved_name` lehnt `POST`/`PATCH` mit diesem
|
||||||
Namen (case-insensitiv) mit 422 ab.
|
Namen (case-insensitiv) mit 422 ab.
|
||||||
|
|
||||||
|
**Präfix `System-` reserviert (Ausbaustufe 12).** `app/reserved.py`
|
||||||
|
(`SYSTEM_PREFIX = "System-"`, `is_reserved_name`, `check_reserved_name`)
|
||||||
|
sperrt diesen Präfix für Kategorie- und Szenario-Namen (`routers/categories.py`,
|
||||||
|
`routers/scenarios.py`, je `check_reserved_name` auf `POST`/`PATCH`, 422 bei
|
||||||
|
Verstoß) — er gehört den vom Tool erzeugten Serien `RESERVED_SCENARIO_NAME`
|
||||||
|
(`"System-Ist"`, `models/views.py`) und `services/planning_chart.py::KREDITRATEN`
|
||||||
|
(`"System-Kreditraten"`).
|
||||||
|
|
||||||
|
**Doppelzählungs-Erkennung Kredit ↔ Fixposten (Ausbaustufe 12).**
|
||||||
|
`app/services/double_count.py` erkennt, wenn ein monatlicher Ausgabe-Posten
|
||||||
|
(`RecurringItem`, `rhythm == "monthly"`) betraglich vermutlich einer regulären
|
||||||
|
Kreditrate (`regular_rate`, Annuität bzw. bei endfälligen Krediten die
|
||||||
|
monatlichen Zinsen) entspricht — Toleranz `max(TOLERANZ_MIN=1.00,
|
||||||
|
rate * TOLERANZ_PROZENT=3 / 100)` — und sich die Zeiträume überschneiden
|
||||||
|
(`rate_period`). `routers/planning.py` ruft `conflicts_for_recurring` bzw.
|
||||||
|
`conflicts_for_loan` bei `POST`/`PATCH` auf `/api/recurring` und
|
||||||
|
`/api/loans` auf; ohne `doppelzaehlung_bestaetigt: true` im Request-Body
|
||||||
|
antwortet es mit `409` (`detail.code == "doppelzaehlung_kredit"`, Konstante
|
||||||
|
`CODE`). `static/doppelzaehlung.js` fängt genau diesen 409 im globalen
|
||||||
|
`htmx:responseError`-Handler ab und zeigt das `<dialog id=
|
||||||
|
"doppelzaehlung-dialog">` aus `base.html`; „Trotzdem speichern“ markiert das
|
||||||
|
Formular (`data-doppelzaehlung-bestaetigt="1"`) und sendet es erneut, die
|
||||||
|
`json-form`-Erweiterung ergänzt dabei `doppelzaehlung_bestaetigt: true`.
|
||||||
|
`routers/gui.py::planung_page` ruft zusätzlich `all_conflicts` auf und zeigt
|
||||||
|
einen dauerhaften ⚠-Hinweis je betroffenem Posten/Kredit in `planning.html`,
|
||||||
|
solange der Konflikt fortbesteht.
|
||||||
|
|
||||||
**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.11.0
|
0.12.0
|
||||||
|
|||||||
@@ -87,12 +87,33 @@
|
|||||||
Kategorie, der Szenario-Vergleich als Kurven (darin die Ist-Kurve
|
Kategorie, der Szenario-Vergleich als Kurven (darin die Ist-Kurve
|
||||||
„System-Ist“ bis heute, ab heute je Szenario weiter) und das Panel
|
„System-Ist“ bis heute, ab heute je Szenario weiter) und das Panel
|
||||||
„Planung nach Kategorie“ (Monatssummen aus der reinen Planung inkl.
|
„Planung nach Kategorie“ (Monatssummen aus der reinen Planung inkl.
|
||||||
Kreditraten, ohne Szenario-Modifikatoren) – einmal mit demselben
|
„System-Kreditraten“, ohne Szenario-Modifikatoren) – einmal mit demselben
|
||||||
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>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<strong>Reservierte Namen:</strong> Kategorien und Szenarien dürfen nicht
|
||||||
|
mit „System-“ beginnen – dieses Präfix ist für vom Tool erzeugte Einträge
|
||||||
|
reserviert (z. B. die Ist-Serie „System-Ist“ und die Kreditraten-Serie
|
||||||
|
„System-Kreditraten“ in Grafana). Ein Versuch, einen eigenen Namen mit
|
||||||
|
diesem Präfix anzulegen, wird abgelehnt.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<strong>Doppelzählungs-Warnung:</strong> beim Anlegen oder Ändern eines
|
||||||
|
wiederkehrenden Postens oder eines Kredits prüft das Tool, ob ein
|
||||||
|
monatlicher Ausgabe-Posten ungefähr einer regulären Kreditrate entspricht
|
||||||
|
(Betrag innerhalb ±3 %, mindestens 1 €, mit überlappendem Zeitraum). Trifft
|
||||||
|
das zu, erscheint ein Warnfenster – erst ein Klick auf „Trotzdem
|
||||||
|
speichern“ übernimmt den Eintrag. Solange der Konflikt bestehen bleibt,
|
||||||
|
zeigt die Planungs-Seite dauerhaft einen ⚠-Hinweis bei den betroffenen
|
||||||
|
Posten und Krediten an. Am saubersten lässt sich das vermeiden, wenn
|
||||||
|
Kreditraten ausschließlich über „Kredite“ gepflegt werden statt zusätzlich
|
||||||
|
als wiederkehrender Posten.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<strong>Tabellen sortieren:</strong> ein Klick auf einen Spaltenkopf
|
<strong>Tabellen sortieren:</strong> ein Klick auf einen Spaltenkopf
|
||||||
sortiert die Tabelle danach (⇅ unsortiert, ▲ aufsteigend, ▼ absteigend);
|
sortiert die Tabelle danach (⇅ unsortiert, ▲ aufsteigend, ▼ absteigend);
|
||||||
|
|||||||
Reference in New Issue
Block a user