diff --git a/backend/migrations/059_training_units_list_ordering_index.sql b/backend/migrations/059_training_units_list_ordering_index.sql new file mode 100644 index 0000000..2586246 --- /dev/null +++ b/backend/migrations/059_training_units_list_ordering_index.sql @@ -0,0 +1,7 @@ +-- GET /api/training-units: Liste nutzt immer tu.framework_slot_id IS NULL (keine Rahmen-Blueprints) +-- und sortiert nach planned_date, planned_time_start (ASC/DESC mit NULLS LAST). +-- Teilindex verkleinert die Menge und unterstützt die Sortierung. + +CREATE INDEX IF NOT EXISTS idx_training_units_scheduled_order +ON training_units (planned_date DESC, planned_time_start DESC NULLS LAST) +WHERE framework_slot_id IS NULL; diff --git a/backend/version.py b/backend/version.py index 413be7f..17eb7b6 100644 --- a/backend/version.py +++ b/backend/version.py @@ -1,8 +1,8 @@ # Shinkan Jinkendo Version Information -APP_VERSION = "0.8.112" +APP_VERSION = "0.8.113" BUILD_DATE = "2026-05-12" -DB_SCHEMA_VERSION = "20260514058" +DB_SCHEMA_VERSION = "20260514059" MODULE_VERSIONS = { "legal_documents": "1.4.0", # Admin: Live-Vorschau pro Abschnitt + modale Vollvorschau (Editor + Dokumentenliste) @@ -36,6 +36,13 @@ MODULE_VERSIONS = { } CHANGELOG = [ + { + "version": "0.8.113", + "date": "2026-05-14", + "changes": [ + "Migration 059: Teilindex training_units(planned_date, planned_time_start) nur für Zeilen ohne framework_slot_id — list_training_units Sortierung.", + ], + }, { "version": "0.8.112", "date": "2026-05-14", diff --git a/docs/HANDOVER.md b/docs/HANDOVER.md index 3721e85..b5bca01 100644 --- a/docs/HANDOVER.md +++ b/docs/HANDOVER.md @@ -1,7 +1,7 @@ # Shinkan Jinkendo – Entwicklungsstand & Handover -**Stand:** 2026-05-12 -**App-Version / DB-Schema:** App **0.8.110**, DB-Schema **`20260512057`** (`backend/version.py`: `APP_VERSION`, `DB_SCHEMA_VERSION`) +**Stand:** 2026-05-14 +**App-Version / DB-Schema:** App **0.8.113**, DB-Schema **`20260514059`** (`backend/version.py`: `APP_VERSION`, `DB_SCHEMA_VERSION`) Diese Datei ist die **Einstiegs-Doku für neue Chat-Sessions**: Anforderungen im Detail stehen in `.claude/docs/` (siehe unten); hier der **implementierte Stand**, **Medien-Meilenstein** und **sinnvolle nächste Schritte**. @@ -76,7 +76,7 @@ Das Schema ist gegenüber dem Code zurück: Migration **`022_skills_schema_compl - **036 / 037:** Bibliotheks-Rahmen, Slot-Inhalt als **`training_units`** mit **`framework_slot_id`**; **`POST /api/training-units/from-framework-slot`**. - **Code:** `training_framework_programs.py`, `training_planning.py`; Frontend **`TrainingFrameworkProgramEditPage.jsx`**, **`createTrainingUnitFromFrameworkSlot`** in `api.js`. -### Trainingsmodule, Kombinationsübungen und Coach (Stand **0.8.110**) +### Trainingsmodule, Kombinationsübungen und Coach (Stand **0.8.113**) - **Fachspez & Drift-Schutz:** `.claude/docs/functional/Shinkan Trainingsmodule Kombinationsuebungen Spezifikation V2.md` (**§ 10.2.1** IDs, **§ 10.4** Coaching-Stufen, **§ 10.6** Produkt-Backlog, **Anhang A** Abgleich). - **Umsetzungsplan:** `.claude/docs/working/TRAINING_MODULES_IMPLEMENTATION_PLAN.md` (Phase **2** / **4** teilweise; Pakete **4a–g** — u. a. **4e** Archetyp-Admin, **4f** Massen-Vorbelegung, **4g** Backend-Validierung). diff --git a/docs/architecture/UMSETZUNGSPLAN_ROADMAP.md b/docs/architecture/UMSETZUNGSPLAN_ROADMAP.md index c46d91e..dbd3f30 100644 --- a/docs/architecture/UMSETZUNGSPLAN_ROADMAP.md +++ b/docs/architecture/UMSETZUNGSPLAN_ROADMAP.md @@ -5,7 +5,9 @@ - **Phase 0:** abgeschlossen – siehe **[BASELINE_SNAPSHOT.md](./BASELINE_SNAPSHOT.md)** (Bundle festgehalten, API-/k6-Vorlagen + Skripte unter `scripts/load/`). **Phase 2** startet erst danach (Vergleich nach Umsetzung gegen Baseline). - **Phase 1 (Teil):** Dashboard: kein zweites `getCurrentProfile`; eine `listTrainingUnits`-Abfrage für „Nächste Termine“ + Notiz-Pool; Playwright **Test 8** in `dev-smoke-test.spec.js` sichert API-Budget ab. - **Phase 1 (Teil):** Org-Inbox: **ein** gemeinsamer Ladepfad `fetchOrgInboxSnapshot` für Mount-`useEffect` und `refreshOrgInbox` (gleiche Requests, weniger Drift-Risiko; Verhalten unverändert). -- **Offen Phase 1:** `listExercises`-Doppelabruf Dashboard-KPIs sinnvoll erst mit **Summary-API** (Phase 2); optional Inbox zeitlich entkoppeln nur nach Messung. +- **Phase 1 / 2 (Teil):** Dashboard-KPIs: **`GET /api/dashboard/kpis`** (ein Roundtrip); Playwright-Test 8 angepasst. +- **Phase 2 (Teil):** Listen-Indizes **058** (`exercises` Sortierung/`created_by`) und **059** (`training_units` Kalenderliste ohne Blueprint). +- **Offen Phase 1:** Inbox zeitlich entkoppeln nur nach Messung (optional). **Ziel:** Nach MVP eine **nachhaltige** Architektur für Wachstum, **Performance** (Server + schwache Clients) und **sichere Feature-Erweiterung**. **Leitdokumente:** [ZIELBILD_ARCHITEKTUR.md](./ZIELBILD_ARCHITEKTUR.md), [SCHULDEN_UND_REMEDIATION.md](./SCHULDEN_UND_REMEDIATION.md), [VERBINDLICHE_REGELN_SHINKAN.md](./VERBINDLICHE_REGELN_SHINKAN.md). @@ -42,7 +44,7 @@ |------|-------------------|--------| | Dashboard: Doppel-`getCurrentProfile` auflösen; kanonisches Profil klären | A3 | erledigt | | Dashboard: `listTrainingUnits`-Reduktion (ein Call statt zweier identischer) | A3 | erledigt | -| Dashboard: `listExercises`-Doppelabruf / Summary-Call | A3, B1 | Phase 2 (Backend-Summary) | +| Dashboard: `listExercises`-Doppelabruf / Summary-Call | A3, B1 | erledigt (`GET /api/dashboard/kpis`) | | Org-Inbox: Ladestrategie; Umsetzung Teil 1 (gemeinsamer Ladepfad, keine doppelte Logik) | A3 | erledigt | | Org-Inbox: TTL / verzögertes Laden (nur nach Bedarf) | A3 | optional, nach Messung | @@ -62,6 +64,8 @@ | Summary-API finalisieren/erweitern falls in P1 nur Teilbereich | B1 | | Optional: erste Keyset-Pagination für eine Liste mit bekanntem Sort-Key | B3 | +**Teil erledigt (2026-05-14):** Migration **058** (`exercises`: `updated_at` / `created_by`+`updated_at`), **059** (`training_units`: Sortierung der Kalenderliste, nur Zeilen ohne `framework_slot_id`). Rest: `EXPLAIN` unter echtem Volumen, ggf. weitere Indizes. + **Abnahme:** p95 der optimierten Routen **verbessert** ggü. Phase 0 oder dokumentierte Obergrenze eingehalten. ---