# 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
