1203 lines
32 KiB
Markdown
1203 lines
32 KiB
Markdown
|
|
# Shinkan Jinkendo – Technisches Setup
|
|||
|
|
|
|||
|
|
> **Trainer- und Vereinsplattform für Kampfsport-Trainingsplanung**
|
|||
|
|
> Basis: Mitai Jinkendo Ökosystem
|
|||
|
|
> Domain: shinkan.jinkendo.de (真観 - "Wahre Beobachtung")
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. Fachliche Einordnung
|
|||
|
|
|
|||
|
|
**Shinkan ist KEINE persönliche Tracking-App.**
|
|||
|
|
|
|||
|
|
Shinkan ist eine **trainer- und vereinszentrierte Planungs- und Inhaltsplattform** mit Fokus auf:
|
|||
|
|
- Übungsverwaltung und -suche
|
|||
|
|
- Trainingsplanung für Gruppen
|
|||
|
|
- Standardisierung und Wiederverwendung
|
|||
|
|
- Freigabe und Governance von Inhalten
|
|||
|
|
- Import aus bestehendem MediaWiki
|
|||
|
|
|
|||
|
|
**Primäre Nutzer in MVP:** Trainer, Vereinsadmins, Redakteure
|
|||
|
|
**Nicht in MVP:** Individuelle Sportler-Apps, persönliches Tracking, Gürtel-Tracking
|
|||
|
|
|
|||
|
|
**Abgrenzung zu Mitai:**
|
|||
|
|
- Mitai = persönliches Körper- und Trainings-Tracking
|
|||
|
|
- Shinkan = Trainer-Arbeit, Übungen, Trainingsplanung, Vereinsstandards
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. Übernommene Infrastruktur von Mitai
|
|||
|
|
|
|||
|
|
| Komponente | Status | Verwendung |
|
|||
|
|
|-----------|---------|------------|
|
|||
|
|
| Auth-System | ✅ 1:1 übernehmen | Token + bcrypt |
|
|||
|
|
| Membership-Basis | ✅ Übernehmen | Tiers, Features (vereinfacht) |
|
|||
|
|
| User-Profiles | ✅ Übernehmen | Multi-Profile pro Account |
|
|||
|
|
| Tech-Stack | ✅ 1:1 | React 18 + FastAPI + PostgreSQL 16 |
|
|||
|
|
| Docker/Compose | ✅ 1:1 | Dev + Prod Umgebungen |
|
|||
|
|
| PWA | ✅ 1:1 | Mobile + Desktop |
|
|||
|
|
| Design-System | ✅ Basis | CSS-Variablen, mobile-first |
|
|||
|
|
| Versioning | ✅ 1:1 | version.py + Migrations |
|
|||
|
|
| Gitea CI/CD | ✅ 1:1 | Auto-Deploy dev/prod |
|
|||
|
|
|
|||
|
|
**Ports:**
|
|||
|
|
- Prod: 3003/8003 (Frontend/Backend)
|
|||
|
|
- Dev: 3098/8098 (Frontend/Backend)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. Technische Basis (identisch zu Mitai)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Frontend: React 18 + Vite + PWA (Node 20)
|
|||
|
|
Backend: FastAPI Python 3.12
|
|||
|
|
Datenbank: PostgreSQL 16 Alpine
|
|||
|
|
Container: Docker + Docker Compose
|
|||
|
|
Auth: Token-basiert + bcrypt
|
|||
|
|
KI: OpenRouter API (optional, nicht MVP-kritisch)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. Verzeichnisstruktur (angepasst)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
shinkan-jinkendo/
|
|||
|
|
├── backend/
|
|||
|
|
│ ├── main.py # App-Setup + Router-Registration
|
|||
|
|
│ ├── db.py # PostgreSQL Connection Pool
|
|||
|
|
│ ├── db_init.py # DB-Init + Migrations
|
|||
|
|
│ ├── auth.py # Hash, Verify, Sessions, Feature-Access
|
|||
|
|
│ ├── models.py # Pydantic Models
|
|||
|
|
│ ├── version.py # Versionskontrolle
|
|||
|
|
│ ├── migrations/ # SQL-Migrationen (001_*.sql)
|
|||
|
|
│ └── routers/
|
|||
|
|
│ ├── auth.py # Login, Register, Sessions
|
|||
|
|
│ ├── profiles.py # User-Profiles
|
|||
|
|
│ ├── clubs.py # Vereine / Sparten
|
|||
|
|
│ ├── groups.py # Trainingsgruppen
|
|||
|
|
│ ├── skills.py # Fähigkeiten (Admin + CRUD)
|
|||
|
|
│ ├── methods.py # Trainingsmethoden (Admin + CRUD)
|
|||
|
|
│ ├── exercises.py # Übungen (Kern-Modul)
|
|||
|
|
│ ├── training_units.py # Trainingseinheiten
|
|||
|
|
│ ├── training_programs.py # Trainingsprogramme
|
|||
|
|
│ ├── planning.py # Planungsansichten
|
|||
|
|
│ ├── import_wiki.py # MediaWiki-Import
|
|||
|
|
│ ├── admin.py # Admin-Panel
|
|||
|
|
│ └── membership.py # Subscription (vereinfacht)
|
|||
|
|
│
|
|||
|
|
├── frontend/
|
|||
|
|
│ ├── src/
|
|||
|
|
│ │ ├── App.jsx # Root, Auth-Gates, Navigation
|
|||
|
|
│ │ ├── app.css # CSS-Variablen + Styles
|
|||
|
|
│ │ ├── version.js # Frontend-Versionierung
|
|||
|
|
│ │ ├── config/
|
|||
|
|
│ │ │ ├── appNav.js # Hauptnavigation
|
|||
|
|
│ │ │ └── adminNav.js # Admin-Navigation
|
|||
|
|
│ │ ├── context/
|
|||
|
|
│ │ │ ├── AuthContext.jsx
|
|||
|
|
│ │ │ └── ProfileContext.jsx
|
|||
|
|
│ │ ├── pages/
|
|||
|
|
│ │ │ ├── Dashboard.jsx
|
|||
|
|
│ │ │ ├── ExercisesPage.jsx # Übungssuche + CRUD
|
|||
|
|
│ │ │ ├── PlanningPage.jsx # Trainingsplanung
|
|||
|
|
│ │ │ ├── GroupsPage.jsx # Gruppenverwaltung
|
|||
|
|
│ │ │ ├── SkillsPage.jsx # Fähigkeiten (Admin)
|
|||
|
|
│ │ │ ├── MethodsPage.jsx # Methoden (Admin)
|
|||
|
|
│ │ │ ├── ImportPage.jsx # MediaWiki-Import
|
|||
|
|
│ │ │ └── SettingsPage.jsx
|
|||
|
|
│ │ └── utils/
|
|||
|
|
│ │ ├── api.js # ALLE API-Calls
|
|||
|
|
│ │ └── planning.js # Planungshelfer
|
|||
|
|
│ └── public/
|
|||
|
|
│ ├── manifest.json # PWA-Manifest
|
|||
|
|
│ └── icons/
|
|||
|
|
│
|
|||
|
|
├── .claude/
|
|||
|
|
│ ├── commands/ # Slash-Commands
|
|||
|
|
│ ├── docs/
|
|||
|
|
│ │ ├── functional/
|
|||
|
|
│ │ │ └── SHINKAN_REQUIREMENTS.md # Anforderungsdokument
|
|||
|
|
│ │ ├── technical/
|
|||
|
|
│ │ │ └── SHINKAN_DOMAIN_MODEL.md # Domänenmodell
|
|||
|
|
│ │ └── rules/ # Architektur-Regeln (wie Mitai)
|
|||
|
|
│ └── library/
|
|||
|
|
│
|
|||
|
|
├── docker-compose.yml # Production
|
|||
|
|
├── docker-compose.dev-env.yml # Development
|
|||
|
|
├── .env
|
|||
|
|
├── .gitignore
|
|||
|
|
└── CLAUDE.md # Agent-Einstieg
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. Domänenmodell (MVP Core)
|
|||
|
|
|
|||
|
|
### 5.1 Organisationsstruktur
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- Vereine
|
|||
|
|
clubs (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
name VARCHAR(200) NOT NULL,
|
|||
|
|
abbreviation VARCHAR(50),
|
|||
|
|
description TEXT,
|
|||
|
|
status VARCHAR(50) DEFAULT 'active',
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
-- Sparten (optional, kann auch später)
|
|||
|
|
divisions (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
club_id INT REFERENCES clubs(id),
|
|||
|
|
name VARCHAR(200) NOT NULL,
|
|||
|
|
focus_area VARCHAR(100), -- karate, selbstverteidigung, gewaltschutz
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
-- Trainingsgruppen
|
|||
|
|
training_groups (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
club_id INT REFERENCES clubs(id),
|
|||
|
|
division_id INT REFERENCES divisions(id),
|
|||
|
|
name VARCHAR(200) NOT NULL,
|
|||
|
|
focus VARCHAR(100),
|
|||
|
|
level VARCHAR(50),
|
|||
|
|
age_group VARCHAR(50),
|
|||
|
|
weekday VARCHAR(20),
|
|||
|
|
time_start TIME,
|
|||
|
|
time_end TIME,
|
|||
|
|
location VARCHAR(200),
|
|||
|
|
trainer_id INT REFERENCES profiles(id),
|
|||
|
|
co_trainer_ids JSONB, -- [1, 2, 3]
|
|||
|
|
status VARCHAR(50) DEFAULT 'active',
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.2 Fähigkeiten und Methoden (Kataloge)
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- Fähigkeiten (global)
|
|||
|
|
skills (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
name VARCHAR(200) NOT NULL,
|
|||
|
|
category VARCHAR(100), -- kihon, kumite, kata, selbstverteidigung, fitness
|
|||
|
|
description TEXT,
|
|||
|
|
importance INT, -- 1-5
|
|||
|
|
keywords JSONB,
|
|||
|
|
status VARCHAR(50) DEFAULT 'active',
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
-- Trainingsmethoden (global)
|
|||
|
|
training_methods (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
name VARCHAR(200) NOT NULL,
|
|||
|
|
abbreviation VARCHAR(20),
|
|||
|
|
category VARCHAR(100), -- intervall, rollenspiel, zirkel, koordination, etc.
|
|||
|
|
description TEXT,
|
|||
|
|
typical_duration INT, -- in Minuten
|
|||
|
|
typical_group_size VARCHAR(50),
|
|||
|
|
related_skills JSONB, -- [skill_id, skill_id, ...]
|
|||
|
|
keywords JSONB,
|
|||
|
|
status VARCHAR(50) DEFAULT 'active',
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.3 Übungen (Kernobjekt)
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- Übungen
|
|||
|
|
exercises (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
title VARCHAR(300) NOT NULL,
|
|||
|
|
summary TEXT, -- Kurzbeschreibung
|
|||
|
|
goal TEXT NOT NULL, -- Ziel der Übung
|
|||
|
|
execution TEXT NOT NULL, -- Durchführung
|
|||
|
|
preparation TEXT, -- Vorbereitung / Aufbau
|
|||
|
|
trainer_notes TEXT, -- Hinweise für Trainer
|
|||
|
|
equipment JSONB, -- ["Matten", "Pratzen", "Bälle"]
|
|||
|
|
|
|||
|
|
-- Metadaten
|
|||
|
|
duration_min INT,
|
|||
|
|
duration_max INT,
|
|||
|
|
group_size_min INT,
|
|||
|
|
group_size_max INT,
|
|||
|
|
age_groups JSONB, -- ["minis", "kinder", "erwachsene"]
|
|||
|
|
|
|||
|
|
-- Fachliche Zuordnung
|
|||
|
|
focus_area VARCHAR(100), -- karate, selbstverteidigung, gewaltschutz
|
|||
|
|
secondary_areas JSONB,
|
|||
|
|
training_character VARCHAR(50), -- grundlage, aufbau, vertiefung, festigung, diagnose
|
|||
|
|
|
|||
|
|
-- Methode
|
|||
|
|
primary_method_id INT REFERENCES training_methods(id),
|
|||
|
|
secondary_method_ids JSONB,
|
|||
|
|
|
|||
|
|
-- Freigabe
|
|||
|
|
visibility VARCHAR(50) DEFAULT 'private', -- private, club, official
|
|||
|
|
status VARCHAR(50) DEFAULT 'draft', -- draft, in_review, approved, archived
|
|||
|
|
created_by INT REFERENCES profiles(id),
|
|||
|
|
club_id INT REFERENCES clubs(id),
|
|||
|
|
|
|||
|
|
-- Import
|
|||
|
|
import_source VARCHAR(50), -- mediawiki, manual
|
|||
|
|
import_id VARCHAR(200),
|
|||
|
|
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
-- Übungs-Fähigkeiten (M:N)
|
|||
|
|
exercise_skills (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
exercise_id INT REFERENCES exercises(id) ON DELETE CASCADE,
|
|||
|
|
skill_id INT REFERENCES skills(id),
|
|||
|
|
is_primary BOOLEAN DEFAULT false,
|
|||
|
|
intensity INT, -- 1-5
|
|||
|
|
development_contribution VARCHAR(50), -- low, medium, high
|
|||
|
|
required_level INT, -- Eingangs-Niveau
|
|||
|
|
target_level INT, -- Ziel-Niveau
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
-- Übungsvarianten
|
|||
|
|
exercise_variants (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
exercise_id INT REFERENCES exercises(id) ON DELETE CASCADE,
|
|||
|
|
variant_name VARCHAR(200) NOT NULL,
|
|||
|
|
description TEXT,
|
|||
|
|
execution_changes TEXT,
|
|||
|
|
duration_min INT,
|
|||
|
|
duration_max INT,
|
|||
|
|
equipment_changes JSONB,
|
|||
|
|
difficulty_adjustment VARCHAR(50), -- easier, harder, adapted
|
|||
|
|
age_group_override JSONB,
|
|||
|
|
skill_focus_override JSONB,
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
-- Medien (1:N)
|
|||
|
|
exercise_media (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
exercise_id INT REFERENCES exercises(id) ON DELETE CASCADE,
|
|||
|
|
media_type VARCHAR(50), -- image, video, document, sketch
|
|||
|
|
file_path TEXT,
|
|||
|
|
title VARCHAR(200),
|
|||
|
|
description TEXT,
|
|||
|
|
sort_order INT,
|
|||
|
|
is_primary BOOLEAN DEFAULT false,
|
|||
|
|
context VARCHAR(100), -- ablauf, detail, trainer_hint
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.4 Trainingsplanung
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- Training Templates / Standards (vereinbar)
|
|||
|
|
training_templates (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
name VARCHAR(300) NOT NULL,
|
|||
|
|
type VARCHAR(50), -- template, standard
|
|||
|
|
club_id INT REFERENCES clubs(id),
|
|||
|
|
division_id INT REFERENCES divisions(id),
|
|||
|
|
|
|||
|
|
goal TEXT,
|
|||
|
|
focus_areas JSONB,
|
|||
|
|
duration_total INT,
|
|||
|
|
|
|||
|
|
visibility VARCHAR(50) DEFAULT 'private',
|
|||
|
|
status VARCHAR(50) DEFAULT 'active',
|
|||
|
|
version INT DEFAULT 1,
|
|||
|
|
created_by INT REFERENCES profiles(id),
|
|||
|
|
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
-- Trainingsabschnitte (für Templates + Units)
|
|||
|
|
training_sections (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
parent_type VARCHAR(50), -- template, unit
|
|||
|
|
parent_id INT,
|
|||
|
|
|
|||
|
|
title VARCHAR(200) NOT NULL,
|
|||
|
|
section_type VARCHAR(100), -- aufwaermen, kihon, kumite, kata, abschluss, etc.
|
|||
|
|
sort_order INT,
|
|||
|
|
duration_planned INT,
|
|||
|
|
goal TEXT,
|
|||
|
|
notes TEXT,
|
|||
|
|
|
|||
|
|
is_combination BOOLEAN DEFAULT false, -- Übungen als Komplex
|
|||
|
|
combination_method_id INT REFERENCES training_methods(id),
|
|||
|
|
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
-- Übungen in Abschnitten
|
|||
|
|
section_exercises (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
section_id INT REFERENCES training_sections(id) ON DELETE CASCADE,
|
|||
|
|
exercise_id INT REFERENCES exercises(id),
|
|||
|
|
variant_id INT REFERENCES exercise_variants(id),
|
|||
|
|
sort_order INT,
|
|||
|
|
duration_planned INT,
|
|||
|
|
notes TEXT,
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
-- Konkrete Trainingseinheiten
|
|||
|
|
training_units (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
group_id INT REFERENCES training_groups(id),
|
|||
|
|
date DATE NOT NULL,
|
|||
|
|
time_start TIME,
|
|||
|
|
time_end TIME,
|
|||
|
|
|
|||
|
|
derived_from_template_id INT REFERENCES training_templates(id),
|
|||
|
|
derived_from_unit_id INT REFERENCES training_units(id),
|
|||
|
|
|
|||
|
|
title VARCHAR(300),
|
|||
|
|
goal TEXT,
|
|||
|
|
focus_areas JSONB,
|
|||
|
|
|
|||
|
|
-- Durchführung
|
|||
|
|
actual_time_start TIME,
|
|||
|
|
actual_time_end TIME,
|
|||
|
|
completion_status VARCHAR(50), -- planned, in_progress, completed
|
|||
|
|
|
|||
|
|
-- Reflexion
|
|||
|
|
reflection_text TEXT,
|
|||
|
|
what_worked_well TEXT,
|
|||
|
|
what_to_improve TEXT,
|
|||
|
|
|
|||
|
|
created_by INT REFERENCES profiles(id),
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
-- Trainingsprogramme
|
|||
|
|
training_programs (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
club_id INT REFERENCES clubs(id),
|
|||
|
|
division_id INT REFERENCES divisions(id),
|
|||
|
|
|
|||
|
|
name VARCHAR(300) NOT NULL,
|
|||
|
|
description TEXT,
|
|||
|
|
goal TEXT,
|
|||
|
|
duration_weeks INT,
|
|||
|
|
focus_areas JSONB,
|
|||
|
|
|
|||
|
|
visibility VARCHAR(50) DEFAULT 'private',
|
|||
|
|
status VARCHAR(50) DEFAULT 'active',
|
|||
|
|
created_by INT REFERENCES profiles(id),
|
|||
|
|
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
-- Programm-Einheiten (Reihenfolge)
|
|||
|
|
program_units (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
program_id INT REFERENCES training_programs(id) ON DELETE CASCADE,
|
|||
|
|
unit_order INT,
|
|||
|
|
template_id INT REFERENCES training_templates(id),
|
|||
|
|
week_number INT,
|
|||
|
|
notes TEXT,
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.5 Governance
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- Änderungsanfragen (für geschützte Inhalte)
|
|||
|
|
content_change_requests (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
content_type VARCHAR(50), -- exercise, template, skill, method
|
|||
|
|
content_id INT,
|
|||
|
|
requested_by INT REFERENCES profiles(id),
|
|||
|
|
change_description TEXT,
|
|||
|
|
change_details JSONB,
|
|||
|
|
status VARCHAR(50) DEFAULT 'pending', -- pending, approved, rejected
|
|||
|
|
reviewed_by INT REFERENCES profiles(id),
|
|||
|
|
review_notes TEXT,
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|||
|
|
reviewed_at TIMESTAMP
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.6 MediaWiki-Import
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- Import-Tracking
|
|||
|
|
wiki_import_log (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
import_type VARCHAR(50), -- skill, method, exercise
|
|||
|
|
import_status VARCHAR(50), -- success, partial, failed
|
|||
|
|
items_total INT,
|
|||
|
|
items_imported INT,
|
|||
|
|
items_failed INT,
|
|||
|
|
error_log JSONB,
|
|||
|
|
imported_by INT REFERENCES profiles(id),
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
-- Import-Referenzen (für Re-Import-Schutz)
|
|||
|
|
wiki_import_references (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
wiki_page_title VARCHAR(300),
|
|||
|
|
wiki_page_id VARCHAR(100),
|
|||
|
|
content_type VARCHAR(50), -- skill, method, exercise
|
|||
|
|
local_id INT,
|
|||
|
|
last_imported TIMESTAMP,
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|||
|
|
UNIQUE(wiki_page_title, content_type)
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. MVP Core-Features (Release 1)
|
|||
|
|
|
|||
|
|
### 6.1 Pflicht in MVP
|
|||
|
|
|
|||
|
|
**Organisationsstruktur:**
|
|||
|
|
- ✅ Verein anlegen/verwalten
|
|||
|
|
- ✅ Trainingsgruppen anlegen/verwalten
|
|||
|
|
- ✅ Trainer zuordnen
|
|||
|
|
|
|||
|
|
**Kataloge:**
|
|||
|
|
- ✅ Fähigkeiten-Katalog (Admin CRUD)
|
|||
|
|
- ✅ Methoden-Katalog (Admin CRUD)
|
|||
|
|
|
|||
|
|
**Übungen:**
|
|||
|
|
- ✅ Übung anlegen (minimal: Titel, Ziel, Durchführung)
|
|||
|
|
- ✅ Übung vollständig beschreiben (alle Felder)
|
|||
|
|
- ✅ Übungsvarianten anlegen
|
|||
|
|
- ✅ Fähigkeiten zuordnen (Haupt/Neben, Intensität)
|
|||
|
|
- ✅ Methoden zuordnen (Haupt/Neben)
|
|||
|
|
- ✅ Medien hochladen (Bilder, Videos)
|
|||
|
|
- ✅ Übung suchen und filtern
|
|||
|
|
- Schnellsuche (Titel, Schlagworte)
|
|||
|
|
- Filter (Bereich, Zielgruppe, Fähigkeit, Dauer, Gruppengröße)
|
|||
|
|
- ✅ Übung drucken
|
|||
|
|
- ✅ Freigabelogik (privat / Verein / offiziell)
|
|||
|
|
|
|||
|
|
**Trainingsplanung:**
|
|||
|
|
- ✅ Trainingseinheit für Gruppe + Termin planen
|
|||
|
|
- ✅ Training aus Vorlage ableiten
|
|||
|
|
- ✅ Training aus altem Training kopieren
|
|||
|
|
- ✅ Trainingsabschnitte verwalten
|
|||
|
|
- ✅ Übungen zu Abschnitten zuordnen
|
|||
|
|
- ✅ Kombinations-Flag für Abschnitte
|
|||
|
|
- ✅ Kalenderansicht (Gruppe, Datum)
|
|||
|
|
- ✅ Druckansicht
|
|||
|
|
- ✅ Mobile Durchführungssicht
|
|||
|
|
- ✅ Notizen zu Training + Übungen
|
|||
|
|
- ✅ Reflexion nach Training
|
|||
|
|
|
|||
|
|
**Import:**
|
|||
|
|
- ✅ Einseitiger MediaWiki-Import
|
|||
|
|
- Fähigkeiten
|
|||
|
|
- Methoden
|
|||
|
|
- Übungen
|
|||
|
|
- ✅ Import-Tracking (Erfolg/Fehler)
|
|||
|
|
- ✅ Duplikat-Erkennung (Wiki-Referenz)
|
|||
|
|
|
|||
|
|
### 6.2 Bewusst NICHT in MVP
|
|||
|
|
|
|||
|
|
**Kern-Features, die warten:**
|
|||
|
|
- ❌ KI-Trainingsplanung
|
|||
|
|
- ❌ KI-Suche mit externen Calls
|
|||
|
|
- ❌ Sportler-Tracking (individuelle Entwicklung)
|
|||
|
|
- ❌ Gürtel/Graduierungs-System
|
|||
|
|
- ❌ Technik-Mastery-Tracking
|
|||
|
|
- ❌ Reifegradmodell (vollständig)
|
|||
|
|
- ❌ Turnier-/Wettkampfbegleitung
|
|||
|
|
- ❌ Community/Marktplatz
|
|||
|
|
- ❌ Komplexe Membership-Matrix
|
|||
|
|
- ❌ Vollhistorisierung jeder Änderung
|
|||
|
|
- ❌ Bidirektionale Wiki-Sync
|
|||
|
|
- ❌ Offline-Sync (vollständig)
|
|||
|
|
|
|||
|
|
**Rollen/Governance (vereinfacht):**
|
|||
|
|
- ❌ Feingranulare Rechte-Matrix
|
|||
|
|
- ❌ Workflow-basierte Freigabe
|
|||
|
|
- ❌ Multi-Tenant-Administration
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. Initiale Migrationen (MVP)
|
|||
|
|
|
|||
|
|
### 7.1 001_auth_membership.sql
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- Von Mitai übernehmen:
|
|||
|
|
-- profiles, sessions, features, tier_limits, subscriptions
|
|||
|
|
-- (siehe Mitai 001_*.sql + 002_*.sql)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 7.2 002_organization.sql
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- Vereine
|
|||
|
|
CREATE TABLE clubs (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
name VARCHAR(200) NOT NULL,
|
|||
|
|
abbreviation VARCHAR(50),
|
|||
|
|
description TEXT,
|
|||
|
|
status VARCHAR(50) DEFAULT 'active',
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- Sparten (optional, kann später)
|
|||
|
|
CREATE TABLE divisions (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
club_id INT REFERENCES clubs(id) ON DELETE CASCADE,
|
|||
|
|
name VARCHAR(200) NOT NULL,
|
|||
|
|
focus_area VARCHAR(100),
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- Trainingsgruppen
|
|||
|
|
CREATE TABLE training_groups (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
club_id INT REFERENCES clubs(id) ON DELETE CASCADE,
|
|||
|
|
division_id INT REFERENCES divisions(id),
|
|||
|
|
name VARCHAR(200) NOT NULL,
|
|||
|
|
focus VARCHAR(100),
|
|||
|
|
level VARCHAR(50),
|
|||
|
|
age_group VARCHAR(50),
|
|||
|
|
weekday VARCHAR(20),
|
|||
|
|
time_start TIME,
|
|||
|
|
time_end TIME,
|
|||
|
|
location VARCHAR(200),
|
|||
|
|
trainer_id INT REFERENCES profiles(id),
|
|||
|
|
co_trainer_ids JSONB,
|
|||
|
|
status VARCHAR(50) DEFAULT 'active',
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_groups_club ON training_groups(club_id);
|
|||
|
|
CREATE INDEX idx_groups_trainer ON training_groups(trainer_id);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 7.3 003_catalogs.sql
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- Fähigkeiten
|
|||
|
|
CREATE TABLE skills (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
name VARCHAR(200) NOT NULL,
|
|||
|
|
category VARCHAR(100),
|
|||
|
|
description TEXT,
|
|||
|
|
importance INT CHECK (importance BETWEEN 1 AND 5),
|
|||
|
|
keywords JSONB,
|
|||
|
|
status VARCHAR(50) DEFAULT 'active',
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- Trainingsmethoden
|
|||
|
|
CREATE TABLE training_methods (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
name VARCHAR(200) NOT NULL,
|
|||
|
|
abbreviation VARCHAR(20),
|
|||
|
|
category VARCHAR(100),
|
|||
|
|
description TEXT,
|
|||
|
|
typical_duration INT,
|
|||
|
|
typical_group_size VARCHAR(50),
|
|||
|
|
related_skills JSONB,
|
|||
|
|
keywords JSONB,
|
|||
|
|
status VARCHAR(50) DEFAULT 'active',
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_skills_category ON skills(category);
|
|||
|
|
CREATE INDEX idx_methods_category ON training_methods(category);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 7.4 004_exercises.sql
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- Übungen
|
|||
|
|
CREATE TABLE exercises (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
title VARCHAR(300) NOT NULL,
|
|||
|
|
summary TEXT,
|
|||
|
|
goal TEXT NOT NULL,
|
|||
|
|
execution TEXT NOT NULL,
|
|||
|
|
preparation TEXT,
|
|||
|
|
trainer_notes TEXT,
|
|||
|
|
equipment JSONB,
|
|||
|
|
|
|||
|
|
duration_min INT,
|
|||
|
|
duration_max INT,
|
|||
|
|
group_size_min INT,
|
|||
|
|
group_size_max INT,
|
|||
|
|
age_groups JSONB,
|
|||
|
|
|
|||
|
|
focus_area VARCHAR(100),
|
|||
|
|
secondary_areas JSONB,
|
|||
|
|
training_character VARCHAR(50),
|
|||
|
|
|
|||
|
|
primary_method_id INT REFERENCES training_methods(id),
|
|||
|
|
secondary_method_ids JSONB,
|
|||
|
|
|
|||
|
|
visibility VARCHAR(50) DEFAULT 'private',
|
|||
|
|
status VARCHAR(50) DEFAULT 'draft',
|
|||
|
|
created_by INT REFERENCES profiles(id),
|
|||
|
|
club_id INT REFERENCES clubs(id),
|
|||
|
|
|
|||
|
|
import_source VARCHAR(50),
|
|||
|
|
import_id VARCHAR(200),
|
|||
|
|
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- Übungs-Fähigkeiten
|
|||
|
|
CREATE TABLE exercise_skills (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
exercise_id INT REFERENCES exercises(id) ON DELETE CASCADE,
|
|||
|
|
skill_id INT REFERENCES skills(id),
|
|||
|
|
is_primary BOOLEAN DEFAULT false,
|
|||
|
|
intensity INT CHECK (intensity BETWEEN 1 AND 5),
|
|||
|
|
development_contribution VARCHAR(50),
|
|||
|
|
required_level INT,
|
|||
|
|
target_level INT,
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- Varianten
|
|||
|
|
CREATE TABLE exercise_variants (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
exercise_id INT REFERENCES exercises(id) ON DELETE CASCADE,
|
|||
|
|
variant_name VARCHAR(200) NOT NULL,
|
|||
|
|
description TEXT,
|
|||
|
|
execution_changes TEXT,
|
|||
|
|
duration_min INT,
|
|||
|
|
duration_max INT,
|
|||
|
|
equipment_changes JSONB,
|
|||
|
|
difficulty_adjustment VARCHAR(50),
|
|||
|
|
age_group_override JSONB,
|
|||
|
|
skill_focus_override JSONB,
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- Medien
|
|||
|
|
CREATE TABLE exercise_media (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
exercise_id INT REFERENCES exercises(id) ON DELETE CASCADE,
|
|||
|
|
media_type VARCHAR(50),
|
|||
|
|
file_path TEXT,
|
|||
|
|
title VARCHAR(200),
|
|||
|
|
description TEXT,
|
|||
|
|
sort_order INT,
|
|||
|
|
is_primary BOOLEAN DEFAULT false,
|
|||
|
|
context VARCHAR(100),
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_exercises_created_by ON exercises(created_by);
|
|||
|
|
CREATE INDEX idx_exercises_club ON exercises(club_id);
|
|||
|
|
CREATE INDEX idx_exercises_visibility ON exercises(visibility);
|
|||
|
|
CREATE INDEX idx_exercise_skills_skill ON exercise_skills(skill_id);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 7.5 005_training_planning.sql
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- Templates / Standards
|
|||
|
|
CREATE TABLE training_templates (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
name VARCHAR(300) NOT NULL,
|
|||
|
|
type VARCHAR(50),
|
|||
|
|
club_id INT REFERENCES clubs(id),
|
|||
|
|
division_id INT REFERENCES divisions(id),
|
|||
|
|
goal TEXT,
|
|||
|
|
focus_areas JSONB,
|
|||
|
|
duration_total INT,
|
|||
|
|
visibility VARCHAR(50) DEFAULT 'private',
|
|||
|
|
status VARCHAR(50) DEFAULT 'active',
|
|||
|
|
version INT DEFAULT 1,
|
|||
|
|
created_by INT REFERENCES profiles(id),
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- Abschnitte
|
|||
|
|
CREATE TABLE training_sections (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
parent_type VARCHAR(50),
|
|||
|
|
parent_id INT,
|
|||
|
|
title VARCHAR(200) NOT NULL,
|
|||
|
|
section_type VARCHAR(100),
|
|||
|
|
sort_order INT,
|
|||
|
|
duration_planned INT,
|
|||
|
|
goal TEXT,
|
|||
|
|
notes TEXT,
|
|||
|
|
is_combination BOOLEAN DEFAULT false,
|
|||
|
|
combination_method_id INT REFERENCES training_methods(id),
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- Übungen in Abschnitten
|
|||
|
|
CREATE TABLE section_exercises (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
section_id INT REFERENCES training_sections(id) ON DELETE CASCADE,
|
|||
|
|
exercise_id INT REFERENCES exercises(id),
|
|||
|
|
variant_id INT REFERENCES exercise_variants(id),
|
|||
|
|
sort_order INT,
|
|||
|
|
duration_planned INT,
|
|||
|
|
notes TEXT,
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- Trainingseinheiten
|
|||
|
|
CREATE TABLE training_units (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
group_id INT REFERENCES training_groups(id) ON DELETE CASCADE,
|
|||
|
|
date DATE NOT NULL,
|
|||
|
|
time_start TIME,
|
|||
|
|
time_end TIME,
|
|||
|
|
derived_from_template_id INT REFERENCES training_templates(id),
|
|||
|
|
derived_from_unit_id INT REFERENCES training_units(id),
|
|||
|
|
title VARCHAR(300),
|
|||
|
|
goal TEXT,
|
|||
|
|
focus_areas JSONB,
|
|||
|
|
actual_time_start TIME,
|
|||
|
|
actual_time_end TIME,
|
|||
|
|
completion_status VARCHAR(50),
|
|||
|
|
reflection_text TEXT,
|
|||
|
|
what_worked_well TEXT,
|
|||
|
|
what_to_improve TEXT,
|
|||
|
|
created_by INT REFERENCES profiles(id),
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- Programme
|
|||
|
|
CREATE TABLE training_programs (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
club_id INT REFERENCES clubs(id),
|
|||
|
|
division_id INT REFERENCES divisions(id),
|
|||
|
|
name VARCHAR(300) NOT NULL,
|
|||
|
|
description TEXT,
|
|||
|
|
goal TEXT,
|
|||
|
|
duration_weeks INT,
|
|||
|
|
focus_areas JSONB,
|
|||
|
|
visibility VARCHAR(50) DEFAULT 'private',
|
|||
|
|
status VARCHAR(50) DEFAULT 'active',
|
|||
|
|
created_by INT REFERENCES profiles(id),
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE TABLE program_units (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
program_id INT REFERENCES training_programs(id) ON DELETE CASCADE,
|
|||
|
|
unit_order INT,
|
|||
|
|
template_id INT REFERENCES training_templates(id),
|
|||
|
|
week_number INT,
|
|||
|
|
notes TEXT,
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_units_group_date ON training_units(group_id, date);
|
|||
|
|
CREATE INDEX idx_sections_parent ON training_sections(parent_type, parent_id);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 7.6 006_governance.sql
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- Änderungsanfragen
|
|||
|
|
CREATE TABLE content_change_requests (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
content_type VARCHAR(50),
|
|||
|
|
content_id INT,
|
|||
|
|
requested_by INT REFERENCES profiles(id),
|
|||
|
|
change_description TEXT,
|
|||
|
|
change_details JSONB,
|
|||
|
|
status VARCHAR(50) DEFAULT 'pending',
|
|||
|
|
reviewed_by INT REFERENCES profiles(id),
|
|||
|
|
review_notes TEXT,
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|||
|
|
reviewed_at TIMESTAMP
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_change_requests_status ON content_change_requests(status);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 7.7 007_wiki_import.sql
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- Import-Log
|
|||
|
|
CREATE TABLE wiki_import_log (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
import_type VARCHAR(50),
|
|||
|
|
import_status VARCHAR(50),
|
|||
|
|
items_total INT,
|
|||
|
|
items_imported INT,
|
|||
|
|
items_failed INT,
|
|||
|
|
error_log JSONB,
|
|||
|
|
imported_by INT REFERENCES profiles(id),
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- Import-Referenzen
|
|||
|
|
CREATE TABLE wiki_import_references (
|
|||
|
|
id SERIAL PRIMARY KEY,
|
|||
|
|
wiki_page_title VARCHAR(300),
|
|||
|
|
wiki_page_id VARCHAR(100),
|
|||
|
|
content_type VARCHAR(50),
|
|||
|
|
local_id INT,
|
|||
|
|
last_imported TIMESTAMP,
|
|||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|||
|
|
UNIQUE(wiki_page_title, content_type)
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_wiki_refs_page ON wiki_import_references(wiki_page_title);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8. MediaWiki-Import-Strategie
|
|||
|
|
|
|||
|
|
### 8.1 Grundprinzip
|
|||
|
|
|
|||
|
|
**Einseitig, einmalig, dann Shinkan-nativ weiter**
|
|||
|
|
|
|||
|
|
- ✅ Import aus MediaWiki nach Shinkan
|
|||
|
|
- ❌ KEINE bidirektionale Synchronisation
|
|||
|
|
- ❌ KEINE Live-Kopplung
|
|||
|
|
- ❌ KEINE kontinuierliche Aktualisierung
|
|||
|
|
|
|||
|
|
### 8.2 Import-Reihenfolge
|
|||
|
|
|
|||
|
|
1. **Fähigkeiten** (skills) - Basis-Katalog
|
|||
|
|
2. **Methoden** (training_methods) - Methodenkatalog
|
|||
|
|
3. **Übungen** (exercises) - Hauptinhalt
|
|||
|
|
|
|||
|
|
**Programme/Trainings:** Nur wenn Datenqualität ausreicht
|
|||
|
|
|
|||
|
|
### 8.3 Import-Logik
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
# Pseudo-Code Import-Workflow
|
|||
|
|
for wiki_page in wiki_pages:
|
|||
|
|
# Duplikat-Check
|
|||
|
|
existing = check_wiki_reference(wiki_page.title, content_type)
|
|||
|
|
if existing:
|
|||
|
|
log_skip(wiki_page)
|
|||
|
|
continue
|
|||
|
|
|
|||
|
|
# Parse + Transform
|
|||
|
|
data = parse_wiki_page(wiki_page)
|
|||
|
|
|
|||
|
|
# Validate
|
|||
|
|
if not validate_minimal_fields(data):
|
|||
|
|
log_error(wiki_page, "missing required fields")
|
|||
|
|
continue
|
|||
|
|
|
|||
|
|
# Import
|
|||
|
|
try:
|
|||
|
|
local_id = create_content(data)
|
|||
|
|
create_wiki_reference(wiki_page, local_id)
|
|||
|
|
log_success(wiki_page, local_id)
|
|||
|
|
except Exception as e:
|
|||
|
|
log_error(wiki_page, str(e))
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 8.4 Import-Metadaten
|
|||
|
|
|
|||
|
|
Jeder importierte Inhalt erhält:
|
|||
|
|
- `import_source = 'mediawiki'`
|
|||
|
|
- `import_id = wiki_page_id`
|
|||
|
|
- Referenz in `wiki_import_references`
|
|||
|
|
- Status = `draft` (muss nachbearbeitet werden)
|
|||
|
|
|
|||
|
|
### 8.5 Nach-Import-Workflow
|
|||
|
|
|
|||
|
|
Nach Import müssen Trainer/Admins:
|
|||
|
|
- Importierte Inhalte prüfen
|
|||
|
|
- Unvollständige Felder ergänzen
|
|||
|
|
- Fähigkeiten/Methoden zuordnen
|
|||
|
|
- Status auf `approved` setzen
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 9. Docker-Setup (wie Mitai)
|
|||
|
|
|
|||
|
|
### 9.1 docker-compose.yml (Production)
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
version: '3.8'
|
|||
|
|
|
|||
|
|
services:
|
|||
|
|
postgres:
|
|||
|
|
image: postgres:16-alpine
|
|||
|
|
container_name: shinkan-db-prod
|
|||
|
|
environment:
|
|||
|
|
POSTGRES_DB: shinkan
|
|||
|
|
POSTGRES_USER: shinkan_user
|
|||
|
|
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
|||
|
|
volumes:
|
|||
|
|
- shinkan-db-data:/var/lib/postgresql/data
|
|||
|
|
ports:
|
|||
|
|
- "5434:5432"
|
|||
|
|
restart: unless-stopped
|
|||
|
|
|
|||
|
|
backend:
|
|||
|
|
build:
|
|||
|
|
context: ./backend
|
|||
|
|
dockerfile: Dockerfile
|
|||
|
|
container_name: shinkan-api
|
|||
|
|
environment:
|
|||
|
|
DB_HOST: postgres
|
|||
|
|
DB_PORT: 5432
|
|||
|
|
DB_NAME: shinkan
|
|||
|
|
DB_USER: shinkan_user
|
|||
|
|
DB_PASSWORD: ${DB_PASSWORD}
|
|||
|
|
APP_URL: https://shinkan.jinkendo.de
|
|||
|
|
ALLOWED_ORIGINS: https://shinkan.jinkendo.de
|
|||
|
|
volumes:
|
|||
|
|
- shinkan-media:/app/media
|
|||
|
|
ports:
|
|||
|
|
- "8003:8000"
|
|||
|
|
depends_on:
|
|||
|
|
- postgres
|
|||
|
|
restart: unless-stopped
|
|||
|
|
|
|||
|
|
frontend:
|
|||
|
|
build:
|
|||
|
|
context: ./frontend
|
|||
|
|
dockerfile: Dockerfile
|
|||
|
|
args:
|
|||
|
|
VITE_API_URL: https://shinkan.jinkendo.de
|
|||
|
|
container_name: shinkan-ui
|
|||
|
|
ports:
|
|||
|
|
- "3003:80"
|
|||
|
|
restart: unless-stopped
|
|||
|
|
|
|||
|
|
volumes:
|
|||
|
|
shinkan-db-data:
|
|||
|
|
shinkan-media:
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 9.2 docker-compose.dev-env.yml (Development)
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
version: '3.8'
|
|||
|
|
|
|||
|
|
services:
|
|||
|
|
postgres:
|
|||
|
|
image: postgres:16-alpine
|
|||
|
|
container_name: dev-shinkan-postgres
|
|||
|
|
environment:
|
|||
|
|
POSTGRES_DB: shinkan_dev
|
|||
|
|
POSTGRES_USER: shinkan_dev
|
|||
|
|
POSTGRES_PASSWORD: dev_password
|
|||
|
|
volumes:
|
|||
|
|
- dev-shinkan-db-data:/var/lib/postgresql/data
|
|||
|
|
ports:
|
|||
|
|
- "5435:5432"
|
|||
|
|
restart: unless-stopped
|
|||
|
|
|
|||
|
|
backend:
|
|||
|
|
build:
|
|||
|
|
context: ./backend
|
|||
|
|
dockerfile: Dockerfile
|
|||
|
|
container_name: dev-shinkan-api
|
|||
|
|
environment:
|
|||
|
|
DB_HOST: postgres
|
|||
|
|
DB_PORT: 5432
|
|||
|
|
DB_NAME: shinkan_dev
|
|||
|
|
DB_USER: shinkan_dev
|
|||
|
|
DB_PASSWORD: dev_password
|
|||
|
|
APP_URL: https://dev.shinkan.jinkendo.de
|
|||
|
|
ALLOWED_ORIGINS: https://dev.shinkan.jinkendo.de
|
|||
|
|
volumes:
|
|||
|
|
- dev-shinkan-media:/app/media
|
|||
|
|
ports:
|
|||
|
|
- "8098:8000"
|
|||
|
|
depends_on:
|
|||
|
|
- postgres
|
|||
|
|
restart: unless-stopped
|
|||
|
|
|
|||
|
|
frontend:
|
|||
|
|
build:
|
|||
|
|
context: ./frontend
|
|||
|
|
dockerfile: Dockerfile
|
|||
|
|
args:
|
|||
|
|
VITE_API_URL: https://dev.shinkan.jinkendo.de
|
|||
|
|
container_name: dev-shinkan-ui
|
|||
|
|
ports:
|
|||
|
|
- "3098:80"
|
|||
|
|
restart: unless-stopped
|
|||
|
|
|
|||
|
|
volumes:
|
|||
|
|
dev-shinkan-db-data:
|
|||
|
|
dev-shinkan-media:
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 10. Initiale Version
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
# backend/version.py
|
|||
|
|
|
|||
|
|
APP_VERSION = "0.1.0"
|
|||
|
|
BUILD_DATE = "2026-04-21"
|
|||
|
|
DB_SCHEMA_VERSION = "20260421"
|
|||
|
|
|
|||
|
|
MODULE_VERSIONS = {
|
|||
|
|
"auth": "1.0.0",
|
|||
|
|
"profiles": "1.0.0",
|
|||
|
|
"clubs": "0.1.0",
|
|||
|
|
"groups": "0.1.0",
|
|||
|
|
"skills": "0.1.0",
|
|||
|
|
"methods": "0.1.0",
|
|||
|
|
"exercises": "0.1.0",
|
|||
|
|
"training_units": "0.1.0",
|
|||
|
|
"training_programs": "0.1.0",
|
|||
|
|
"planning": "0.1.0",
|
|||
|
|
"import_wiki": "0.1.0",
|
|||
|
|
"admin": "1.0.0",
|
|||
|
|
"membership": "1.0.0",
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
CHANGELOG = [
|
|||
|
|
{
|
|||
|
|
"version": "0.1.0",
|
|||
|
|
"date": "2026-04-21",
|
|||
|
|
"changes": [
|
|||
|
|
"Initial MVP Setup",
|
|||
|
|
"Feature: Übungsverwaltung (Kern-Modul)",
|
|||
|
|
"Feature: Fähigkeiten- und Methodenkataloge",
|
|||
|
|
"Feature: Trainingsplanung für Gruppen",
|
|||
|
|
"Feature: Trainingsabschnitte mit Kombinations-Flag",
|
|||
|
|
"Feature: MediaWiki-Import (einseitig)",
|
|||
|
|
"Feature: Freigabelogik (privat/Verein/offiziell)",
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 11. Umsetzungs-Reihenfolge (Empfehlung)
|
|||
|
|
|
|||
|
|
### Phase 1: Basis (2-3 Tage)
|
|||
|
|
- Repository + Docker-Setup
|
|||
|
|
- Auth + Membership von Mitai kopieren
|
|||
|
|
- DB-Migrationen 001-003
|
|||
|
|
- Version.py anpassen
|
|||
|
|
|
|||
|
|
### Phase 2: Kataloge (2 Tage)
|
|||
|
|
- Skills CRUD (Admin)
|
|||
|
|
- Methods CRUD (Admin)
|
|||
|
|
- Frontend Admin-Pages
|
|||
|
|
|
|||
|
|
### Phase 3: Übungen (5-7 Tage)
|
|||
|
|
- Exercises CRUD
|
|||
|
|
- Exercise-Skills M:N
|
|||
|
|
- Exercise-Variants
|
|||
|
|
- Exercise-Media
|
|||
|
|
- Suche + Filter
|
|||
|
|
- Druckansicht
|
|||
|
|
|
|||
|
|
### Phase 4: Trainingsplanung (5-7 Tage)
|
|||
|
|
- Training-Groups CRUD
|
|||
|
|
- Training-Templates/Standards
|
|||
|
|
- Training-Sections
|
|||
|
|
- Training-Units
|
|||
|
|
- Kalenderansicht
|
|||
|
|
- Mobile Durchführungssicht
|
|||
|
|
|
|||
|
|
### Phase 5: Import (3-4 Tage)
|
|||
|
|
- MediaWiki-Parser
|
|||
|
|
- Import-Workflow (Skills, Methods, Exercises)
|
|||
|
|
- Import-Log + Duplikat-Erkennung
|
|||
|
|
|
|||
|
|
### Phase 6: Governance (2-3 Tage)
|
|||
|
|
- Freigabelogik
|
|||
|
|
- Change-Requests (Basis)
|
|||
|
|
- Eigene vs. Vereins-Inhalte
|
|||
|
|
|
|||
|
|
**Geschätzte Gesamtdauer MVP:** 4-5 Wochen
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 12. Bewusst nur vorbereitet, nicht umgesetzt (in MVP)
|
|||
|
|
|
|||
|
|
Diese Elemente sollen durch das Datenmodell **nicht verbaut** werden, gehören aber **nicht in MVP**:
|
|||
|
|
|
|||
|
|
**Reifegradmodelle:**
|
|||
|
|
- Skill-Levels pro Modell
|
|||
|
|
- Maturity-Stages
|
|||
|
|
- Target-Descriptions pro Level
|
|||
|
|
|
|||
|
|
**Individuelle Sportler-Entwicklung:**
|
|||
|
|
- Athlete-Profiles
|
|||
|
|
- Skill-Progress-Tracking
|
|||
|
|
- Assessment-History
|
|||
|
|
|
|||
|
|
**Erweiterte Governance:**
|
|||
|
|
- Workflow-basierte Freigabe
|
|||
|
|
- Review-Zyklen
|
|||
|
|
- Versionierung mit Branches
|
|||
|
|
|
|||
|
|
**Community:**
|
|||
|
|
- Shared Content-Pool
|
|||
|
|
- Bewertungen
|
|||
|
|
- Kommentare
|
|||
|
|
|
|||
|
|
**KI:**
|
|||
|
|
- Trainingsplanung
|
|||
|
|
- Übungssuche mit Semantik
|
|||
|
|
- Automatische Programm-Generierung
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 13. Offene Punkte / Entscheidungsbedarf
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
🤔 MediaWiki-Parser: Welches Format nutzt das aktuelle Wiki? (Semantic MediaWiki)
|
|||
|
|
🤔 Medien-Upload: Lokal oder S3/Cloud?
|
|||
|
|
🤔 Suche: PostgreSQL Full-Text oder ElasticSearch später?
|
|||
|
|
🤔 Offline: Service Worker + IndexedDB oder nur gute Mobile-UX?
|
|||
|
|
🤔 Druckformat: PDF-Export oder nur HTML-Print?
|
|||
|
|
🤔 Sparten: Schon in MVP oder erst später?
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 14. Nächste konkrete Schritte
|
|||
|
|
|
|||
|
|
1. **Repository erstellen** auf Gitea: `shinkan-jinkendo`
|
|||
|
|
2. **Basis-Dateien kopieren** aus Mitai:
|
|||
|
|
- `backend/auth.py`, `db.py`, `db_init.py`
|
|||
|
|
- `frontend/src/context/`, `utils/api.js`
|
|||
|
|
3. **Migrationen schreiben** (001-007)
|
|||
|
|
4. **Version.py anpassen**
|
|||
|
|
5. **CLAUDE.md erstellen** für Shinkan
|
|||
|
|
6. **Erste Router implementieren:**
|
|||
|
|
- `skills.py`
|
|||
|
|
- `methods.py`
|
|||
|
|
- `exercises.py`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**Version:** 2.0 (komplett überarbeitet)
|
|||
|
|
**Stand:** 21.04.2026
|
|||
|
|
**Autor:** Claude Code (basierend auf Anforderungsdokument)
|