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
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:
- Migrations 014-017 anlegen (DB-Konsistenz)
- exercises.py auf M:N umstellen (Legacy-Cleanup)
- 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:
-
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
-
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)
-
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=10POST /api/import/mediawiki/execute(Body: category, import_type, reimport, dry_run, limit)GET /api/import/mediawiki/status/{log_id}GET /api/import/mediawiki/logsDELETE /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.jserweitern: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:
- ✅ Import darf nur Feld-Zuordnung + Typ-Konvertierung (bereits konform)
- ✅ Keine fachliche Interpretation im Import (bereits konform)
- ⏸️ 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)
- Migrations 014-017 anlegen
- exercises.py auf M:N umstellen
- Frontend für Importer bauen
- Testen + Deployen
Aufwand: 10-14h
Option B: Minimaler Pfad (schnell, aber unvollständig)
- Nur Migration 014 anlegen (Legacy DROP)
- exercises.py minimal fixen
- 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