shinkan-jinkendo/.claude/docs/working/SMW_IMPORTER_GAP_ANALYSIS.md
Lars 01ed5509f8
Some checks failed
Deploy Development / deploy (push) Successful in 36s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 6s
Test Suite / playwright-tests (push) Failing after 1m54s
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

11 KiB

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:

# 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:

# 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:

# _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:

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:

CREATE TABLE exercise_focus_areas (...);
CREATE TABLE exercise_age_groups (...);
CREATE TABLE exercise_target_groups (...);

exercises.py Router (aktuell) nutzt BEIDE:

# 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:

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