shinkan-jinkendo/.claude/docs/working/SMW_IMPORTER_GAP_ANALYSIS.md

392 lines
11 KiB
Markdown
Raw Normal View History

feat: Exercises v2.0 + Migrations 014/016/017 (Clean-Room Rebuild) BREAKING CHANGES: - exercises.py komplett neu gebaut (kein Legacy-Code) - Legacy-Felder entfernt: age_groups, focus_area, secondary_areas, training_character - Nur M:N Relations, keine JSONB-Kataloge Migrations: - Migration 014: Variant Progression + Search Vector + Legacy DROP - exercise_variants: progression_level, sequence_order, prerequisite_variant_id - exercises: search_vector (tsvector für Volltext-Suche) - DROP age_groups, focus_area, secondary_areas, training_character - Helper: update_timestamp() Funktion für Triggers - Migration 016: Saved Exercise Searches - saved_exercise_searches (profile_id, name, filters JSONB) - Migration 017: Exercise Blocks + Template Blocks - exercise_blocks (name, description, goal, is_template) - exercise_block_items (exercise_id, variant_id, sequence_order, is_placeholder, placeholder_criteria) Backend (exercises.py v2.0): - GET /exercises: Volltext-Suche via tsvector, M:N Joins - GET /exercises/{id}: enrich_exercise_detail() mit allen M:N Relations - POST /exercises: M:N Relations (focus_areas_multi, training_styles_multi, target_groups_multi, age_groups, skills) - PUT /exercises: Partial Update + M:N Relations - DELETE /exercises: Cascade-Check für exercise_block_items Architecture: - Issue #53 konform: Import = Feld-Zuordnung, keine fachliche Interpretation - Helper: enrich_exercise_detail() für vollständige Objekte - Helper: assign_exercise_relations() für M:N Management (DELETE+INSERT Pattern) Docs: - SMW_IMPORTER_GAP_ANALYSIS.md: Vollständige Gap-Analyse + Umsetzungsplan Version: 0.7.0 Module: exercises 2.0.0 Schema: 20260424002
2026-04-24 15:04:27 +02:00
# SMW-Importer Gap-Analyse & Umsetzungsplanung
**Datum:** 2026-04-24
**Status:** Requirement Analysis Complete
**Nächste Schritte:** User-Approval → Implementation
---
## 1. Executive Summary
**Ziel:** SMW-Importer fertigstellen inkl. Frontend, saubere Datenbank, Issue #53 Compliance
**Aktueller Status:**
- ✅ Backend komplett (smw_client.py, smw_mapper.py, import_wiki.py)
- ✅ Migration 018 (wiki_import_tracking) deployed
- ✅ Issue #53 konform (keine fachliche Interpretation im Import)
- ✅ Duplikats-Handling via wiki_import_references
- ❌ Migrations 014-017 fehlen (Blocker für saubere DB)
- ❌ exercises.py Router nutzt Legacy-Felder (Inkonsistenz)
- ❌ Frontend für Importer fehlt komplett
**Kritischer Pfad:**
1. Migrations 014-017 anlegen (DB-Konsistenz)
2. exercises.py auf M:N umstellen (Legacy-Cleanup)
3. Frontend für Importer (Admin-UI)
---
## 2. Issue #53 Compliance Check (Mitai → Shinkan)
### 2.1 Was ist Issue #53?
**Quelle:** `c:\Dev\mitai-jinkendo\docs\issues\issue-53-phase-0c-multi-layer-architecture.md`
**Kern-Prinzip:**
```
┌────────────────────────────────────────────────┐
│ Layer 1: DATA LAYER │
│ - Pure data retrieval + calculation logic │
│ - Returns: Structured data (dict/list/float) │
│ - No formatting, no strings │
└──────────────────┬─────────────────────────────┘
│
┌───────────┴──────────┐
│ │
▼ ▼
┌──────────────┐ ┌─────────────────────┐
│ Layer 2a: │ │ Layer 2b: │
│ KI LAYER │ │ VISUALIZATION LAYER │
└──────────────┘ └─────────────────────┘
```
**Import-Regeln (ARCHITECTURE.md §8):**
- ✅ **Erlaubt:** Typ-/Einheits-Konvertierung, Zuordnung CSV→Feld, Duplikat-Logik
- ❌ **Verboten:** Fachliche Interpretation, Aggregation von "Bedeutung", Metriken für Auswertung
### 2.2 Shinkan SMW-Importer Compliance
**✅ KONFORM:**
```python
# smw_mapper.py - Nur Feld-Zuordnung
EXERCISE_PROPERTY_MAP = {
"Übungsbezeichnung": "title_override",
"Ziel": "goal",
"Durchführung": "execution",
"Plandauer": "duration_raw", # String → Int Konvertierung
"Übungstyp": "focus_area_names", # Name → ID Lookup
}
# Typ-Konvertierung (erlaubt)
duration_min = safe_int(raw_value.get("Plandauer"))
# Keine fachliche Interpretation ✅
# Keine Metriken-Berechnung ✅
```
**✅ Duplikats-Handling:**
```python
# import_wiki.py - reimport-safe
if not reimport:
cur.execute(
"SELECT id FROM wiki_import_references WHERE wiki_page_title = %s",
(page_title, import_type)
)
if cur.fetchone():
stats["skipped"] += 1
continue
```
**✅ M:N Katalog-Zuordnung:**
```python
# _assign_exercise_catalogs() - lookup only, keine Berechnung
cur.execute("SELECT id FROM focus_areas WHERE name ILIKE %s", (name,))
if row:
cur.execute(
"INSERT INTO exercise_focus_areas (exercise_id, focus_area_id, is_primary) ..."
)
```
**Fazit:** SMW-Importer ist Issue #53 konform. KEIN Refactoring nötig.
---
## 3. Datenbank-Inkonsistenz: Legacy vs. M:N
### 3.1 Problem
**Migration 005** (deployed) definiert Legacy-Felder:
```sql
CREATE TABLE exercises (
...
age_groups JSONB, -- ["minis", "kinder", "erwachsene"]
focus_area VARCHAR(100), -- karate, selbstverteidigung, gewaltschutz
secondary_areas JSONB,
...
);
```
**Migration 008** (deployed) definiert M:N Tabellen:
```sql
CREATE TABLE exercise_focus_areas (...);
CREATE TABLE exercise_age_groups (...);
CREATE TABLE exercise_target_groups (...);
```
**exercises.py Router** (aktuell) nutzt BEIDE:
```python
# Legacy beim CREATE
data.get('age_groups'), # JSONB
data.get('focus_area'), # VARCHAR
# M:N beim GET
SELECT fa.name FROM exercise_focus_areas efa
JOIN focus_areas fa ON efa.focus_area_id = fa.id
```
**Migration 014** (geplant) würde Legacy-Felder droppen:
```sql
ALTER TABLE exercises DROP COLUMN IF EXISTS age_groups;
ALTER TABLE exercises DROP COLUMN IF EXISTS focus_area;
ALTER TABLE exercises DROP COLUMN IF EXISTS secondary_areas;
```
### 3.2 Auswirkung
**Wenn Migration 014 jetzt ausgeführt wird:**
- ✅ SMW-Importer funktioniert (nutzt nur M:N)
- ❌ exercises.py CREATE bricht (INSERT referenziert gedropte Spalten)
- ❌ exercises.py GET funktioniert (nutzt M:N)
**Lösung:** exercises.py auf M:N umstellen BEVOR Migration 014
---
## 4. Fehlende Migrations 014-017
### 4.1 Inhalt
**Migration 014: Variant Progression + Search + Legacy Cleanup**
- Variant Progression (progression_level, sequence_order, prerequisite_variant_id)
- Search Vector (tsvector für Volltext-Suche)
- Legacy DROP (age_groups, focus_area, secondary_areas)
**Migration 015: Semantic Matching (OPTIONAL - Phase 2)**
- exercise_embeddings Tabelle für Vector Search
**Migration 016: Saved Searches**
- saved_exercise_searches Tabelle
**Migration 017: Exercise Blocks**
- exercise_blocks + exercise_block_items
- Template Blocks (is_template, is_placeholder, placeholder_criteria)
### 4.2 SQL-Dateien
**Status:** Spec-Inhalt existiert in `EXERCISES_DATABASE_FINAL.md`, muss als .sql extrahiert werden
**Action Items:**
- [ ] 014_variant_progression_search_legacy.sql anlegen
- [ ] 015_semantic_matching.sql anlegen (OPTIONAL)
- [ ] 016_saved_searches.sql anlegen
- [ ] 017_exercise_blocks.sql anlegen
---
## 5. Frontend für SMW-Importer
### 5.1 Fehlende Komponenten
**Admin-Seite:**
- `frontend/src/pages/MediaWikiImportPage.jsx` (NEU)
**API-Funktionen:**
- `frontend/src/utils/api.js` - Wiki-Import Funktionen ergänzen
**Navigation:**
- Admin-Navigation erweitern (Link zu Import-Seite)
### 5.2 UI-Requirements
**3-Tab Layout:**
1. **Preview Tab**
- Kategorie-Auswahl (Übungen, Fähigkeiten, Methoden)
- Limit-Auswahl (10, 50, 100)
- Preview-Button → zeigt Tabelle mit:
- Wiki-Seitentitel
- Already Imported (Ja/Nein)
- Last Imported (Datum)
- Mapped Fields (Accordion)
- Warnings/Errors
2. **Execute Tab**
- Import-Typ (Exercise, Skill, Method)
- Kategorie-Input
- Reimport-Existing (Checkbox)
- Dry-Run (Checkbox)
- Limit (Optional)
- Execute-Button → startet Background-Task
- Status-Display (Running, Completed, Failed)
- Progress (Imported/Skipped/Failed Counts)
3. **History Tab**
- Liste aller Import-Logs (neueste zuerst)
- Spalten: Type, Category, Status, Items (Total/Imported/Skipped/Failed), Date
- Expandable Row für Error-Details
**API-Endpoints (bereits vorhanden):**
- `GET /api/import/mediawiki/preview?category=Übungen&import_type=exercise&limit=10`
- `POST /api/import/mediawiki/execute` (Body: category, import_type, reimport, dry_run, limit)
- `GET /api/import/mediawiki/status/{log_id}`
- `GET /api/import/mediawiki/logs`
- `DELETE /api/import/mediawiki/references/{ref_id}` (Force Reimport)
---
## 6. Umsetzungsplan (priorisiert)
### Phase 1: Datenbank-Konsistenz (BLOCKER)
**1.1 Migrations anlegen**
- [ ] Migration 014 als .sql (Variant + Search + **Legacy DROP**)
- [ ] Migration 015 als .sql (Semantic Matching) - OPTIONAL, kann warten
- [ ] Migration 016 als .sql (Saved Searches)
- [ ] Migration 017 als .sql (Exercise Blocks)
**Aufwand:** 2-3h (SQL aus Spec extrahieren, testen)
**1.2 exercises.py Router überarbeiten**
- [ ] CREATE: Legacy-Felder entfernen, nur M:N nutzen
- [ ] UPDATE: Legacy-Felder entfernen
- [ ] Query-Filter: focus_area String-Filter durch M:N-Join ersetzen
**Aufwand:** 1-2h
**1.3 Deployment**
- [ ] Migrations 014-017 deployen (dev → prod)
- [ ] exercises.py deployen
- [ ] Testen: SMW-Import funktioniert
**Aufwand:** 1h
**Total Phase 1:** 4-6h
---
### Phase 2: SMW-Importer Frontend
**2.1 API-Funktionen**
- [ ] `api.js` erweitern:
- `previewMediaWikiImport(category, importType, limit)`
- `executeMediaWikiImport(category, importType, reimport, dryRun, limit)`
- `getMediaWikiImportStatus(logId)`
- `listMediaWikiImportLogs()`
- `deleteMediaWikiImportReference(refId)`
**Aufwand:** 0.5h
**2.2 MediaWikiImportPage.jsx**
- [ ] 3-Tab Layout (Preview, Execute, History)
- [ ] Preview: Kategorie-Auswahl, Preview-Tabelle mit Accordions
- [ ] Execute: Form mit Status-Polling
- [ ] History: Tabelle mit Expandable Rows
**Aufwand:** 3-4h
**2.3 Navigation**
- [ ] Admin-Navigation erweitern (Link zu Import-Seite)
**Aufwand:** 0.5h
**Total Phase 2:** 4-5h
---
### Phase 3: Testing & Refinement
**3.1 Integration Testing**
- [ ] Dev-System: Import von BINGO + Speed Jab Drills
- [ ] Prüfen: Alle M:N Tabellen korrekt befüllt
- [ ] Prüfen: Reimport überschreibt korrekt
- [ ] Prüfen: Duplikats-Handling funktioniert
**Aufwand:** 1-2h
**3.2 Prod Deployment**
- [ ] SMW-Importer deployen (dev → prod)
- [ ] Erste echte Imports durchführen
**Aufwand:** 1h
**Total Phase 3:** 2-3h
---
## 7. Gesamt-Aufwand
| Phase | Tasks | Aufwand |
|-------|-------|---------|
| Phase 1: DB-Konsistenz | Migrations + Router | 4-6h |
| Phase 2: Frontend | UI + API | 4-5h |
| Phase 3: Testing | Integration + Deploy | 2-3h |
| **TOTAL** | | **10-14h** |
**Empfehlung:** Phase 1 zuerst (kritisch für DB-Konsistenz), dann Phase 2+3
---
## 8. Offene Fragen
**Q1:** Sollen wir Migration 015 (Semantic Matching) jetzt anlegen oder später?
- **Pro:** Komplett-System
- **Con:** OPTIONAL, braucht Vector-Embeddings (nicht kritisch)
- **Empfehlung:** SKIPPEN, erst bei Bedarf
**Q2:** Soll exercises.py komplett refactored werden oder nur Legacy-Felder entfernen?
- **Empfehlung:** Nur Legacy-Felder entfernen (minimal invasiv)
**Q3:** Data Layer in Shinkan anlegen (wie Mitai)?
- **Status:** Shinkan hat KEIN `data_layer/` Verzeichnis
- **Empfehlung:** SPÄTER, nicht Blocker für Importer
---
## 9. Issue #53 Learnings für Shinkan
**Aus Mitai übernehmen:**
1. ✅ Import darf nur Feld-Zuordnung + Typ-Konvertierung (bereits konform)
2. ✅ Keine fachliche Interpretation im Import (bereits konform)
3. ⏸️ Data Layer für Metriken-Berechnung (SPÄTER, separate Task)
**NICHT übernehmen:**
- ❌ Komplett-Refactoring jetzt (zu großer Scope)
- ❌ Chart-Endpoints jetzt (kein Bedarf)
**Fazit:** Shinkan Import ist bereits Issue #53 konform. Kein Action-Item.
---
## 10. Nächste Schritte (User-Approval erforderlich)
**Option A: Komplett-Durchlauf (empfohlen)**
1. Migrations 014-017 anlegen
2. exercises.py auf M:N umstellen
3. Frontend für Importer bauen
4. Testen + Deployen
**Aufwand:** 10-14h
**Option B: Minimaler Pfad (schnell, aber unvollständig)**
1. Nur Migration 014 anlegen (Legacy DROP)
2. exercises.py minimal fixen
3. Frontend SPÄTER
**Aufwand:** 4-6h, aber Frontend fehlt
**Option C: User entscheidet Priorität**
- Welche Phase zuerst?
- Migration 015 (Semantic Matching) jetzt oder später?
- exercises.py komplett refactorn oder minimal?
**Empfehlung:** Option A (Komplett-Durchlauf), weil:
- Saubere Datenbank (keine Legacy-Felder)
- Vollständiger Importer (Backend + Frontend)
- Issue #53 konform
- Basis für zukünftige Features
---
**Autor:** Claude Code
**Version:** 1.0
**Status:** Pending User-Approval