# 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