- Incremented application version to 0.7.9 and updated database schema version to 20260427030. - Revised project status documentation to reflect recent milestones and changes, including detailed logs of implemented features and next steps. - Enhanced API specifications for exercises, including support for exercise variants and improved query parameters. - Updated frontend routing to streamline exercise variant management within the ExerciseFormPage. - Implemented role-based media upload limits and refined search/filter specifications for better user experience.
13 KiB
Shinkan Jinkendo - Datenbank-Schema (Technisch)
Version: 0.4.0
Stand: 2026-04-27
Aktuell deployed: Migration 023 (Skills Complete Import)
Übersicht
Dieses Dokument beschreibt die technische Datenbankstruktur von Shinkan Jinkendo.
Zuständig für fachliche Modellierung: siehe DOMAIN_MODEL.md
Migrations-Historie
| Nr. | Datum | Beschreibung | Status |
|---|---|---|---|
| 001 | 2026-04-20 | Initial Schema (Auth, Profiles) | ✅ Deployed |
| 002 | 2026-04-20 | Clubs, Divisions, Groups | ✅ Deployed |
| 003 | 2026-04-20 | Skills, Methods | ✅ Deployed |
| 004 | 2026-04-21 | Training Types | ✅ Deployed |
| 005 | 2026-04-21 | Exercises (Basis) | ✅ Deployed |
| 006 | 2026-04-21 | Training Planning | ✅ Deployed |
| 007 | 2026-04-22 | Exercise Catalogs (idempotent) | ✅ Deployed |
| 008 | 2026-04-23 | M:N Exercise Relations + Hierarchical Catalogs | ✅ Deployed |
| 009 | 2026-04-23 | Target Groups M:N Refactoring (BREAKING) | ✅ Deployed |
| 010 | 2026-04-23 | Rename training_styles to style_directions | ✅ Deployed |
| 011 | 2026-04-23 | Create Training Types | ✅ Deployed |
| 012 | 2026-04-23 | Exercise Training Characters + Trainer Contexts | ✅ Deployed |
| 013 | 2026-04-23 | Training Types Focus Area | ✅ Deployed |
| 014 | 2026-04-24 | Variant Progression Search Legacy | ✅ Deployed |
| 016 | 2026-04-24 | Saved Searches | ✅ Deployed |
| 017 | 2026-04-24 | Exercise Blocks | ✅ Deployed |
| 018 | 2026-04-24 | Wiki Import Tracking | ✅ Deployed |
| 019 | 2026-04-24 | Exercises Optional Fields (goal/execution nullable) | ✅ Deployed |
| 020 | 2026-04-27 | Exercise Skills UNIQUE Constraint | ✅ Deployed |
| 021 | 2026-04-27 | ⚠️ Faulty | |
| 022 | 2026-04-27 | Skills Schema Complete (BREAKING) | ✅ Deployed |
| 023 | 2026-04-27 | Skills Complete Import (69 Skills) | ✅ Deployed |
Migration 022: Skills Schema Complete (BREAKING CHANGE)
Problem: Skills hatten keine Kategorisierung (Haupt-/Unterkategorie, Fokusbereich).
Lösung: Vollständiges hierarchisches Schema für produktionsreifen Import.
Neue Tabellen:
-- Haupt-Kategorien (KARATE / ALLGEMEINE)
skill_main_categories (
id SERIAL PRIMARY KEY,
name VARCHAR(200) UNIQUE NOT NULL, -- "KARATE Fähigkeiten" / "ALLGEMEINE sportliche Fähigkeiten"
slug VARCHAR(50) UNIQUE NOT NULL, -- "karate" / "allgemeine"
description TEXT,
sort_order INT,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
)
-- Level-Definitionen (1-5 Beschreibungen aus Fähigkeitsmatrix)
skill_level_definitions (
id SERIAL PRIMARY KEY,
skill_id INT NOT NULL REFERENCES skills(id) ON DELETE CASCADE,
level INT NOT NULL CHECK (level BETWEEN 1 AND 5),
description TEXT NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
UNIQUE (skill_id, level)
)
Erweiterte Tabellen:
-- skill_categories erweitert
ALTER TABLE skill_categories ADD COLUMN slug VARCHAR(50);
ALTER TABLE skill_categories ADD COLUMN main_category_id INT REFERENCES skill_main_categories(id);
ALTER TABLE skill_categories ADD CONSTRAINT skill_categories_slug_unique UNIQUE (slug);
-- skills erweitert
ALTER TABLE skills ADD COLUMN main_category_id INT REFERENCES skill_main_categories(id);
ALTER TABLE skills ADD COLUMN focus_areas JSONB DEFAULT '[]'::jsonb;
Indizes:
idx_skills_main_category_ididx_skills_category_ididx_skill_categories_main_category_ididx_skill_level_definitions_skill_id
Struktur:
skill_main_categories (Hauptkategorie)
└─ skill_categories (Unterkategorie)
└─ skills (Fähigkeit)
└─ skill_level_definitions (Level 1-5 Beschreibungen)
Migration 023: Skills Complete Import
Quelle: Fähigkeitsmatrix (https://karatetrainer.net/index.php?title=Fähigkeitsmatrix)
Importiert:
- 69 Skills mit vollständiger Kategorisierung
- 2 Haupt-Kategorien: KARATE Fähigkeiten, ALLGEMEINE sportliche Fähigkeiten
- 9 Unterkategorien: Kihon, Kumite, Kata, Selbstverteidigung, Koordination, Kondition, Kognition, Soziale Fähigkeiten, Psychische Fähigkeiten
Skills-Verteilung:
KARATE Fähigkeiten (32 Skills, focus_areas: ["karate"]):
├─ Kata (8): Technik Kombination, Kata Ablauf, Bunkai, Oyo, Henka, Kakushi, Kata Atmung, Kata Rhythmus
├─ Kihon (10): Dachi Waza, Uke Waza, Zuki Waza, Uchi Waza, Geri Waza, Nage Waza, Nukite Waza, Ken Waza, Hüfteinsatz, Kime
├─ Kumite (10): Beinarbeit, Distanzkontrolle, Angriff, Abwehr Konter, Präzision, Antizipation, Timing, Taktik, Fokus, Mentale Stärke
└─ Selbstverteidigung (4): Gefahrenbewustsein, Selbstbehauptung, Selbstschutz, Gefahrenabwehr
ALLGEMEINE sportliche Fähigkeiten (37 Skills, focus_areas: ["universal"]):
├─ Kognition (5): Aufmerksamkeit, Wahrnehmung, Urteilsvermögen, Merkfähigkeit, Lernfähigkeit
├─ Kondition (15): Maximalkraft, Schnellkraft, Reaktivkraft, Kraftausdauer, Muskelaufbau,
│ Reaktionsschnelligkeit, Bewegungsschnelligkeit, Handlungsschnelligkeit,
│ Schnelligkeitsausdauer, Grundlagenausdauer, Aerobe Ausdauer, Anaerobe Ausdauer,
│ Regenerationsfähigkeit, Ermüdungswiderstandsfähigkeit, Flexibilität
├─ Koordination (7): Orientierung, Differenzierung, Kopplung, Gleichgewicht, Rhythmisierung, Reaktion, Umstellung
├─ Psychische Fähigkeiten (6): Selbstvertrauen, Konzentration, Emotionale Kontrolle, Motivation, Stressresistenz, Stressregulation
└─ Soziale Fähigkeiten (4): Deeskalation, Selbstdisziplin, Toleranz, Fairness
Duplikat-Handling: Einige Skills kommen in der Matrix doppelt vor (Kumite + Kondition/Koordination):
- Behalten in Kondition: Anaerobe Ausdauer, Bewegungsschnelligkeit, Flexibilität, Reaktionsschnelligkeit, Schnelligkeitsausdauer (konditionelle Primärfähigkeiten)
- Behalten in Kumite: Antizipation, Timing (kampfspezifisch)
Cleanup:
- DELETE FROM exercise_skills (M:N Beziehungen)
- DELETE FROM skills (alte Daten)
- DELETE FROM skill_categories
- DELETE FROM skill_main_categories
Verifikation:
-- Sollte 69 ergeben
SELECT COUNT(*) FROM skills;
-- Zeigt Verteilung
SELECT
mc.name AS hauptkategorie,
sc.name AS unterkategorie,
COUNT(s.id) AS anzahl_skills
FROM skills s
JOIN skill_categories sc ON s.category_id = sc.id
JOIN skill_main_categories mc ON s.main_category_id = mc.id
GROUP BY mc.name, sc.name, mc.sort_order, sc.sort_order
ORDER BY mc.sort_order, sc.sort_order;
Kern-Entitäten
Auth & Profile
profiles (id, name, email, password_hash, role, created_at)
sessions (id, profile_id, token, created_at, expires_at)
Organisation
clubs (id, name, abbreviation, description, logo_url, ...)
divisions (id, club_id, name, description, ...)
training_groups (id, division_id, name, description, focus_area, level, ...)
Kataloge
Fokusbereiche & Stile (M:N mit Zielgruppen)
focus_areas (id, name, abbreviation, description, color, icon, ...)
style_directions (id, focus_area_id, name, abbreviation, description, parent_style_id, ...)
target_groups (id, name, description, min_age, max_age, ...) -- Global, NICHT gebunden an Stil
training_style_target_groups (style_direction_id, target_group_id, is_primary) -- M:N Junction
Fähigkeiten (Hierarchisches Schema ab Migration 022)
-- Haupt-Kategorien (2: KARATE, ALLGEMEINE)
skill_main_categories (
id, name, slug, description, sort_order, created_at, updated_at
)
-- Unterkategorien (9: Kihon, Kumite, Kata, Selbstverteidigung, Koordination, Kondition, ...)
skill_categories (
id, name, slug, description, sort_order,
main_category_id REFERENCES skill_main_categories(id),
parent_category_id, -- Optional: Hierarchie
created_at, updated_at
)
-- Fähigkeiten (69 Skills)
skills (
id, name, description,
category_id REFERENCES skill_categories(id),
main_category_id REFERENCES skill_main_categories(id),
focus_areas JSONB, -- ["karate"] oder ["universal"]
created_at, updated_at
)
-- Level-Definitionen (optional, noch nicht gefüllt)
skill_level_definitions (
id, skill_id, level, description,
created_at, updated_at,
UNIQUE (skill_id, level)
)
Focus Areas Bedeutung:
["karate"]- Skill ist spezifisch für Karate (z.B. Kata Ablauf, Kihon)["universal"]- Skill ist universell einsetzbar (z.B. Maximalkraft, Konzentration, Deeskalation)- Später möglich:
["karate", "selbstverteidigung"]- Mehrfachzuordnung
Trainingscharakter
training_characters (id, name, description, ...)
trainer_contexts (id, name, description, ...) -- Neue Dimension (Migration 012)
Übungen (M:N Beziehungen ab Migration 008)
exercises (
id, title, summary, goal, execution, preparation, trainer_notes,
duration_min, duration_max,
group_size_min, group_size_max,
equipment JSONB,
visibility, status, created_by, club_id,
import_source, import_id, wiki_page_id, -- MediaWiki Import (Migration 018)
created_at, updated_at
)
-- M:N Beziehungen
exercise_focus_areas (exercise_id, focus_area_id, is_primary)
exercise_style_directions (exercise_id, style_direction_id, is_primary)
exercise_target_groups (exercise_id, target_group_id, is_primary)
exercise_age_groups (exercise_id, age_group) -- Enum: Minis, Kinder, Schüler, Teenager, Erwachsene
-- Fähigkeiten-Zuordnung (mit Level)
exercise_skills (
exercise_id, skill_id,
is_primary, intensity,
required_level INT, -- Voraussetzung (1-5)
target_level INT, -- Ziel (1-5)
UNIQUE (exercise_id, skill_id) -- Migration 020
)
-- Varianten & Medien
exercise_variants (id, exercise_id, name, description, ...)
exercise_media (id, exercise_id, type, url, title, description, ...)
Training Planning
training_units (id, group_id, date, title, description, ...)
training_unit_exercises (
training_unit_id, exercise_id, sort_order,
exercise_variant_id -- FK exercise_variants(id) ON DELETE SET NULL (Migration 030)
)
exercise_blocks (id, name, description, created_by, club_id, ...) -- Migration 017
MediaWiki Import (Migration 018)
wiki_import_log (
id, category, import_type, import_status,
items_total, items_imported, items_skipped, items_failed,
error_log JSONB,
started_at, finished_at,
imported_by
)
wiki_import_references (
id, wiki_page_id, entity_type, local_id,
created_at, updated_at
)
Import-Typen:
exercise- Übungen ausKategorie:Übungenskill- Fähigkeiten ausKategorie:Fähigkeitsbeschreibung(veraltet, nutze Migration 023)method- Trainingsmethoden ausKategorie:Methodenbeschreibung
Indizes
Performance-Indizes
-- Hierarchie-Lookups
CREATE INDEX idx_style_directions_focus_area ON style_directions(focus_area_id);
CREATE INDEX idx_skill_categories_main_category ON skill_categories(main_category_id);
CREATE INDEX idx_skills_category ON skills(category_id);
CREATE INDEX idx_skills_main_category ON skills(main_category_id);
-- M:N Joins
CREATE INDEX idx_exercise_focus_areas_exercise ON exercise_focus_areas(exercise_id);
CREATE INDEX idx_exercise_focus_areas_focus ON exercise_focus_areas(focus_area_id);
CREATE INDEX idx_exercise_style_directions_exercise ON exercise_style_directions(exercise_id);
CREATE INDEX idx_exercise_style_directions_style ON exercise_style_directions(style_direction_id);
CREATE INDEX idx_exercise_target_groups_exercise ON exercise_target_groups(exercise_id);
CREATE INDEX idx_exercise_target_groups_target ON exercise_target_groups(target_group_id);
CREATE INDEX idx_exercise_skills_exercise ON exercise_skills(exercise_id);
CREATE INDEX idx_exercise_skills_skill ON exercise_skills(skill_id);
-- Import-Tracking
CREATE INDEX idx_wiki_import_references_wiki_page ON wiki_import_references(wiki_page_id);
CREATE INDEX idx_wiki_import_references_entity ON wiki_import_references(entity_type, local_id);
Kaskadier-Regeln
Fokusbereich löschen
Verhalten: RESTRICT (Löschen verweigern wenn verwendet)
Prüfung:
SELECT COUNT(*) FROM style_directions WHERE focus_area_id = :id
SELECT COUNT(*) FROM exercise_focus_areas WHERE focus_area_id = :id
Alternativen:
- Umrouten: Alle abhängigen Stile auf neuen Fokusbereich setzen
- Archivieren: Status auf 'archived' setzen statt löschen
Stil löschen
Verhalten: RESTRICT wenn Zielgruppen oder Übungen zugeordnet
Umrouten-Workflow:
- Admin wählt Ziel-Stil
- System aktualisiert:
training_style_target_groups.style_direction_idexercise_style_directions.style_direction_id
- Löschen erlaubt
Zielgruppe löschen
Verhalten: SET NULL oder CASCADE in exercise_target_groups
Prüfung:
SELECT COUNT(*) FROM training_style_target_groups WHERE target_group_id = :id
SELECT COUNT(*) FROM exercise_target_groups WHERE target_group_id = :id
Skill löschen
Verhalten: CASCADE zu skill_level_definitions, RESTRICT wenn in exercise_skills
Prüfung:
SELECT COUNT(*) FROM exercise_skills WHERE skill_id = :id
Nächste Schritte
- Level-Definitionen aus Fähigkeitsmatrix extrahieren (optional)
- Skills-Import testen mit Übungs-Import
- Migration 024: Skills-Beschreibungen aus Wiki importieren
- Admin-UI für Skill-Kategorien (CRUD)
- Skill-Filter in Übungssuche integrieren
Letzte Aktualisierung: 2026-04-27
Verantwortlich: Claude Code
Review: Pending