Kairo-Jinkendo/docs/reference/design-principles/shinkan/DASHBOARD_KPI_DESIGN_PRINCIPLES.md

106 lines
4.0 KiB
Markdown
Raw Normal View History

# Dashboard KPIs – Designprinzipien (Extraktion)
**Status:** Analyse / Arbeitspapier
**Stand:** 2026-07-04
**Geltungsbereich:** Modul „Dashboard KPI Aggregation“ — vereinfacht vs. Mitai Widgets
**Serie:** Designprinzipien für Produktfamilie · Shinkan Dokument 14 von 15
**Mitai-Vergleich:** [DASHBOARD_WIDGETS_DESIGN_PRINCIPLES.md](file:///c:/Dev/mitai-jinkendo/.claude/docs/technical/DASHBOARD_WIDGETS_DESIGN_PRINCIPLES.md) (#7, vereinfacht)
**Kernkomponenten:**
| Bereich | Pfade |
|---------|-------|
| API | `backend/routers/dashboard.py` — `GET /api/dashboard/kpis` |
| Frontend | Dashboard/Übersicht-Page |
| Refaktor-Kontext | `docs/architecture/SCHULDEN_UND_REMEDIATION.md` A3, B1 |
---
## Modul
**Dashboard KPI Aggregation**
Ein Backend-Roundtrip liefert Übungs-KPIs, YTD-Einheiten, Trainings-Home (nächste Termine, Vermerke, offene Rückschau) — Ersatz für mehrere parallele Client-Listen-Calls.
---
## Designprinzipien
### 1. Aggregierter Endpoint statt Chatty Client
| | |
|---|---|
| **Prinzip** | `GET /dashboard/kpis` ruft intern `list_exercises_like_get` + `list_training_units` mit gleichen Filtern wie zuvor im UI. |
| **Begründung** | Weniger Latenz; eine TenantContext-Auflösung; Refaktor Phase 1 Dashboard. |
| **Quelle** | `dashboard.py`; SCHULDEN A3/B1 |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Noch keine konfigurierbaren Widgets wie Mitai. |
### 2. Gleiche Filtersemantik wie Einzel-Endpoints
| | |
|---|---|
| **Prinzip** | KPI-Zählungen nutzen dieselben Helfer wie `/exercises` und `/training-units` — keine zweite Query-Logik. |
| **Begründung** | Zahlen auf Dashboard = Zahlen in Fachmodulen. |
| **Quelle** | Import aus `exercises`, `training_planning` Routern |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Interne Funktionsaufrufe statt HTTP — Kopplung an Router-Helfer. |
### 3. TenantContext für Mandanten-KPIs
| | |
|---|---|
| **Prinzip** | `Depends(get_tenant_context)` — assigned_to_me, created_by_me respektieren Verein/Rolle. |
| **Begründung** | Keine globalen KPIs für Trainer fremder Vereine. |
| **Quelle** | `get_dashboard_kpis` |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | — |
### 4. Festes Dashboard-Layout (kein Widget-Katalog)
| | |
|---|---|
| **Prinzip** | Shinkan-Übersicht zeigt definierte Kacheln — nicht nutzerkonfigurierbares Layout-JSON. |
| **Begründung** | MVP-Fokus Trainer-Verein; weniger Komplexität als Mitai. |
| **Quelle** | Produktentscheidung vs. Mitai #7 |
| **Tragfähigkeit** | **mittel** (bewusste Vereinfachung) |
| **Einschränkung** | Erweiterung braucht Backend+Frontend-Change, nicht Admin-Config. |
### 5. Profil nicht redundant laden
| | |
|---|---|
| **Prinzip** | Dashboard soll Auth-Profil nutzen — kein zweites `/profiles/me` nach Login+Reload (E2E Test 8). |
| **Begründung** | Architekturschuld A3 explizit adressiert. |
| **Quelle** | `tests/dev-smoke-test.spec.js`; Roadmap |
| **Tragfähigkeit** | **hoch** |
| **Einschränkung** | Frontend-Umsetzung muss mitziehen. |
### 6. Slice-Logik für Trainings-Home im Backend
| | |
|---|---|
| **Prinzip** | `_slice_training_home_notes` filtert Einheiten mit Vermerken — max. N Stück serverseitig. |
| **Begründung** | Kleiner Payload; klare Semantik. |
| **Quelle** | `dashboard.py` |
| **Tragfähigkeit** | **mittel** |
| **Einschränkung** | Grenzwert hardcoded — ggf. Query-Param später. |
---
## Nicht übernehmen
1. **Drei parallele fast gleiche `listTrainingUnits`-Calls** im Client — behoben durch KPI-Endpoint.
2. **Mitai Widget-Dual-Registry vorreifen** ohne Produktbedarf — Over-Engineering für Shinkan MVP.
3. **KPI-Berechnung im Frontend** aus Volllisten — skaliert nicht.
4. **Dashboard ohne Tenant-Filter** — Mandanten-Leak.
---
## Verwandte Dokumentation
- [docs/architecture/SCHULDEN_UND_REMEDIATION.md](../../architecture/SCHULDEN_UND_REMEDIATION.md)
- Mitai: [DASHBOARD_WIDGETS_DESIGN_PRINCIPLES.md](file:///c:/Dev/mitai-jinkendo/.claude/docs/technical/DASHBOARD_WIDGETS_DESIGN_PRINCIPLES.md)
- [DESIGN_PRINCIPLES_INDEX.md](./DESIGN_PRINCIPLES_INDEX.md)