From 353ff6056cd0ac5b1fc4f4710ab192f5dba0dacb39887c9449aa334e80d6d83b Mon Sep 17 00:00:00 2001 From: wlfb Date: Mon, 20 Jul 2026 14:21:11 +0200 Subject: [PATCH] docs: Plan-Haekchen Ausbaustufe 7 Co-Authored-By: Claude Fable 5 --- .../plans/2026-07-20-ausbaustufe-7.md | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/docs/superpowers/plans/2026-07-20-ausbaustufe-7.md b/docs/superpowers/plans/2026-07-20-ausbaustufe-7.md index 0b0fba4..409d05f 100644 --- a/docs/superpowers/plans/2026-07-20-ausbaustufe-7.md +++ b/docs/superpowers/plans/2026-07-20-ausbaustufe-7.md @@ -1,6 +1,6 @@ # Ausbaustufe 7 Implementation Plan — Szenarien-Seite, Formular-UX, Kategorien (v0.8.0) -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [x]`) syntax for tracking. **Goal:** Szenarien auf eigene Seite `/szenarien`, verständliches Eintrags-Formular (Paar-Layout, Gesperrt-Kennzeichnung, dynamisches Wert-Label, abgesetzter Durchrechnen-Button), Kategorien-Verwaltung auf der Admin-Seite; Release v0.8.0. @@ -32,7 +32,7 @@ - Consumes: bestehenden Szenario-Kontext (`_scenario_rows`, `modifier_kinds`), `gui_session`, alle bestehenden Templates/JS-Helfer. - Produces: `GET /szenarien` (login-geschützt) mit Kontext `scenario_rows`, `loans`, `categories`, `category_names`, `recurring`, `recurring_names`, `modifier_kinds`; `toggleEdit` global in `base.html`. Task 2 baut auf `szenarien.html` auf. -- [ ] **Step 1: Failing GUI-Tests** — in `tests/test_gui.py`: +- [x] **Step 1: Failing GUI-Tests** — in `tests/test_gui.py`: ```python def test_szenarien_seite_und_nav(client, db): @@ -56,7 +56,7 @@ def test_szenarien_seite_braucht_login(client): Run: `.venv/bin/python -m pytest tests/test_gui.py -q` → neue Tests FAIL (404) -- [ ] **Step 2: Route** — `app/routers/gui.py`: in `planung_page` die Zeilen `scenarios = _list_scenarios(...)`, `"scenario_rows": ...` und `"modifier_kinds": ...` entfernen (die übrigen Kontexteinträge bleiben). Neue Route direkt darunter: +- [x] **Step 2: Route** — `app/routers/gui.py`: in `planung_page` die Zeilen `scenarios = _list_scenarios(...)`, `"scenario_rows": ...` und `"modifier_kinds": ...` entfernen (die übrigen Kontexteinträge bleiben). Neue Route direkt darunter: ```python @router.get("/szenarien", dependencies=[Depends(gui_session)]) @@ -76,7 +76,7 @@ def szenarien_page(request: Request, session: Session = Depends(get_session)): }) ``` -- [ ] **Step 3: Template-Umzug** — Neues `app/templates/szenarien.html`: +- [x] **Step 3: Template-Umzug** — Neues `app/templates/szenarien.html`: ```html {% extends "base.html" %} @@ -102,17 +102,17 @@ def szenarien_page(request: Request, session: Session = Depends(get_session)): Der `

Szenarien

` entfällt (die Seite hat die `

`-Überschrift). In `planning.html`: die gesamte Szenarien-`
` löschen; aus dem Script-Block `onModTargetTypeChange`, `onEntryArtChange`, `toggleScenarioLoan` und `toggleEdit` entfernen — `toggleEdit` zieht in den zentralen Script-Block von `base.html` (dort nach der json-form-Extension einfügen, unverändert inkl. Kommentar); `loadLoanSchedule`/`fmtEur`/`formatIsoDate` und `loadedSchedules` bleiben in `planning.html`. -- [ ] **Step 4: Nav + Hilfe** — `base.html`: `Szenarien` zwischen Planung- und Admin-Link. `hilfe.html`: Formulierungen, die die Szenarien auf der Planung-Seite verorten, auf „Szenarien-Seite" anpassen (grep nach „Szenari" in `hilfe.html` und Ortsangaben prüfen). +- [x] **Step 4: Nav + Hilfe** — `base.html`: `Szenarien` zwischen Planung- und Admin-Link. `hilfe.html`: Formulierungen, die die Szenarien auf der Planung-Seite verorten, auf „Szenarien-Seite" anpassen (grep nach „Szenari" in `hilfe.html` und Ortsangaben prüfen). -- [ ] **Step 5: Bestehende Tests umziehen** — `tests/test_gui.py`: die Szenario-GUI-Tests (`test_szenario_gui_ende_und_einmalzahlungen`, `test_szenario_eintraege_tabelle`, Szenario-Anteile von `test_planung_hat_bearbeiten_formulare`) von `client.get("/planung")` auf `client.get("/szenarien")` umstellen. In `test_planung_hat_bearbeiten_formulare` den Scenario-Teil (Scenario-Seed + `hx-patch="/api/scenarios/`-Assertion) in einen neuen Test `test_szenarien_hat_bearbeiten_formular` auslagern, der `/szenarien` lädt; der Planung-Test behält rec/pln/loan mit `>= 3` Bearbeiten-Buttons. `test_pages_require_login`/`test_pages_render_after_login`: Pfad `/szenarien` in die jeweilige Pfadliste aufnehmen. +- [x] **Step 5: Bestehende Tests umziehen** — `tests/test_gui.py`: die Szenario-GUI-Tests (`test_szenario_gui_ende_und_einmalzahlungen`, `test_szenario_eintraege_tabelle`, Szenario-Anteile von `test_planung_hat_bearbeiten_formulare`) von `client.get("/planung")` auf `client.get("/szenarien")` umstellen. In `test_planung_hat_bearbeiten_formulare` den Scenario-Teil (Scenario-Seed + `hx-patch="/api/scenarios/`-Assertion) in einen neuen Test `test_szenarien_hat_bearbeiten_formular` auslagern, der `/szenarien` lädt; der Planung-Test behält rec/pln/loan mit `>= 3` Bearbeiten-Buttons. `test_pages_require_login`/`test_pages_render_after_login`: Pfad `/szenarien` in die jeweilige Pfadliste aufnehmen. -- [ ] **Step 6: Suite grün** +- [x] **Step 6: Suite grün** Run: `.venv/bin/python -m pytest -q` → PASS -- [ ] **Step 7: Fable-Testagent-Abnahme** (Live-Approximation: beide Seiten rendern; keine Szenario-Reste auf /planung; `toggleEdit` genau EINMAL definiert [base.html], auf beiden Seiten funktionale Edit-Formulare; keine JS-Referenzen auf entfernte Funktionen in planning.html; Nav auf allen Seiten). Erst nach VERIFIED weiter. +- [x] **Step 7: Fable-Testagent-Abnahme** (Live-Approximation: beide Seiten rendern; keine Szenario-Reste auf /planung; `toggleEdit` genau EINMAL definiert [base.html], auf beiden Seiten funktionale Edit-Formulare; keine JS-Referenzen auf entfernte Funktionen in planning.html; Nav auf allen Seiten). Erst nach VERIFIED weiter. -- [ ] **Step 8: Commit** +- [x] **Step 8: Commit** ```bash cd /home/wlfb/bin && git add finance/app/ finance/tests/test_gui.py @@ -130,7 +130,7 @@ git commit -m "feat: eigene Szenarien-Seite /szenarien" - Consumes: `szenarien.html` aus Task 1 (Neuer-Eintrag-Formular mit Feldern kind/target_type/target_id/value/end_date/name/amount/due; `onEntryArtChange`). - Produces: CSS-Klassen `.entry-form`, `.entry-art`, `.value-label`; dynamisches Wert-Label in `onEntryArtChange`; abgesetzter Durchrechnen-Block. -- [ ] **Step 1: Failing GUI-Test** +- [x] **Step 1: Failing GUI-Test** ```python def test_neuer_eintrag_formular_struktur(client, db): @@ -147,7 +147,7 @@ def test_neuer_eintrag_formular_struktur(client, db): Run: → FAIL -- [ ] **Step 2: CSS** — `app/static/style.css` ergänzen: +- [x] **Step 2: CSS** — `app/static/style.css` ergänzen: ```css /* Ausbaustufe 7: Formular-Paare als Einheit, gesperrte Felder erkennbar. */ @@ -180,7 +180,7 @@ label:has(input:disabled), label:has(select:disabled) { (Falls `style.css` bereits eine kollidierende `label`-Regel für `.planning-section` hat: die neue Regel dahinter einsortieren, Spezifität prüfen.) -- [ ] **Step 3: Formular-Markup** — in `szenarien.html` das Neuer-Eintrag-Formular umbauen: +- [x] **Step 3: Formular-Markup** — in `szenarien.html` das Neuer-Eintrag-Formular umbauen: - `
` (Attribute inkl. `data-modifiers-url`/`data-planned-url` unverändert). - Statt `Neuer Eintrag:`: erste Zeile @@ -211,7 +211,7 @@ label:has(input:disabled), label:has(select:disabled) { ``` -- [ ] **Step 4: Dynamisches Wert-Label** — in `onEntryArtChange` (szenarien.html) nach der `setDisabled('value', …)`-Zeile ergänzen: +- [x] **Step 4: Dynamisches Wert-Label** — in `onEntryArtChange` (szenarien.html) nach der `setDisabled('value', …)`-Zeile ergänzen: ```javascript var valueLabel = form.querySelector('.value-label'); @@ -221,11 +221,11 @@ label:has(input:disabled), label:has(select:disabled) { } ``` -- [ ] **Step 5: Suite grün** — `.venv/bin/python -m pytest -q` → PASS +- [x] **Step 5: Suite grün** — `.venv/bin/python -m pytest -q` → PASS -- [ ] **Step 6: Fable-Testagent-Abnahme** — Live-Approximation + Handtrace: gerenderte Struktur (entry-art zuerst, Paare als `inline-flex`-Einheiten via CSS-Regeln vorhanden, Tooltips an allen Umschaltfeldern, `
`+project-block), Wert-Label-Wechsel für alle 5 Arten, Startzustand konsistent (percent: Wert aktiv mit Label „Prozentsatz (%)"). Erst nach VERIFIED weiter. +- [x] **Step 6: Fable-Testagent-Abnahme** — Live-Approximation + Handtrace: gerenderte Struktur (entry-art zuerst, Paare als `inline-flex`-Einheiten via CSS-Regeln vorhanden, Tooltips an allen Umschaltfeldern, `
`+project-block), Wert-Label-Wechsel für alle 5 Arten, Startzustand konsistent (percent: Wert aktiv mit Label „Prozentsatz (%)"). Erst nach VERIFIED weiter. -- [ ] **Step 7: Commit** +- [x] **Step 7: Commit** ```bash cd /home/wlfb/bin && git add finance/app/static/style.css finance/app/templates/szenarien.html finance/tests/test_gui.py @@ -244,7 +244,7 @@ git commit -m "feat: Eintrags-Formular mit Paar-Layout und Gesperrt-Kennzeichnun - Consumes: `CategoryIn`/`CategoryOut`, `POST /api/categories` (vorhanden); `toggleEdit` (seit Task 1 global in base.html); json-form. - Produces: `PATCH /api/categories/{category_id}` (404 „Kategorie nicht gefunden", 409 „Kategorie existiert bereits"); Admin-Abschnitt „Kategorien" mit IDs `cat-row-{id}`/`cat-edit-{id}`. -- [ ] **Step 1: Failing API-Test** — `tests/test_crud_api.py`: +- [x] **Step 1: Failing API-Test** — `tests/test_crud_api.py`: ```python def test_category_patch(client): @@ -266,7 +266,7 @@ def test_category_patch(client): Run: `.venv/bin/python -m pytest tests/test_crud_api.py -q` → FAIL (405) -- [ ] **Step 2: PATCH-Endpunkt** — `app/routers/categories.py`, nach `create_category`: +- [x] **Step 2: PATCH-Endpunkt** — `app/routers/categories.py`, nach `create_category`: ```python @router.patch("/categories/{category_id}", response_model=CategoryOut) @@ -285,7 +285,7 @@ def patch_category(category_id: int, data: CategoryIn, return CategoryOut.model_validate(cat) ``` -- [ ] **Step 3: Failing GUI-Test** — `tests/test_admin.py` (Muster für Login dort übernehmen; falls die Datei GUI-Zugriffe anders aufbaut, an bestehende Fixtures anlehnen): +- [x] **Step 3: Failing GUI-Test** — `tests/test_admin.py` (Muster für Login dort übernehmen; falls die Datei GUI-Zugriffe anders aufbaut, an bestehende Fixtures anlehnen): ```python def test_admin_zeigt_kategorien_verwaltung(client, db): @@ -302,7 +302,7 @@ def test_admin_zeigt_kategorien_verwaltung(client, db): Run: → FAIL -- [ ] **Step 4: Admin-Kontext + Template** — `app/routers/admin.py`: in `admin_page` (und im Fehler-/Erfolgs-Re-Render von `admin_change_password`, damit der Abschnitt nie verschwindet — UX-Regel) `"categories": session.execute(select(Category)).scalars().all()` in den Template-Kontext aufnehmen (Imports `select`, `Category` ergänzen; `session`-Dependency, falls die Route noch keine hat). `admin.html`, neuer Abschnitt vor dem `