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:
2026-09-29 07:40:03 +02:00
co-authored by Claude Opus 5.5
parent e665180b1f
commit b78990786f
3 changed files with 58 additions and 3 deletions
+35 -1
View File
@@ -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
View File
@@ -1 +1 @@
0.11.0 0.12.0
+22 -1
View File
@@ -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);