- Refactored club join requests, memberships, and clubs routers to utilize TenantContext for authentication and authorization, enhancing security and consistency. - Updated session handling to replace direct session dictionary access with TenantContext, improving code clarity and maintainability. - Ensured proper role and profile ID retrieval from TenantContext in various endpoints, streamlining access control for club management functionalities.
473 lines
22 KiB
Python
473 lines
22 KiB
Python
# Shinkan Jinkendo Version Information
|
||
|
||
APP_VERSION = "0.8.26"
|
||
BUILD_DATE = "2026-05-05"
|
||
DB_SCHEMA_VERSION = "20260505041"
|
||
|
||
MODULE_VERSIONS = {
|
||
"auth": "1.2.1", # Login-Rate-Limit 30/minute pro IP (vorher 5/minute)
|
||
"profiles": "1.4.1", # PUT /profiles*, Legacy /profile: Depends(get_tenant_context); profile_document für internes Laden
|
||
"tenant_context": "1.0.1", # Vereine/Mitglieder/Vereinsanträge/Profil-PUT nutzen get_tenant_context (Header-Membership)
|
||
"clubs": "0.4.1", # Alle geschützten Endpoints Depends(get_tenant_context); profile_id/role aus TenantContext
|
||
"club_memberships": "1.0.1", # Depends(get_tenant_context)
|
||
"club_join_requests": "1.0.1", # Depends(get_tenant_context)
|
||
"admin_users": "1.0.0", # GET /api/admin/users
|
||
"groups": "0.1.0",
|
||
"skills": "0.1.0",
|
||
"methods": "0.1.0",
|
||
"exercises": "2.6.2", # Progressionsgraphen: library_content_visibility_sql + Lesen wie Bibliothek; Schreiben Ersteller/Admin; Governance club_id wie Übungen
|
||
"training_units": "0.1.0",
|
||
"training_programs": "0.1.0",
|
||
"planning": "0.8.0", # TenantContext auf allen Planungs-Endpunkten; Vorlagen-Liste wie Übungen nach aktivem Verein
|
||
"import_wiki": "1.0.0",
|
||
"admin": "1.0.0",
|
||
"membership": "1.0.0",
|
||
"catalogs": "1.5.0", # Updated: Trainer Contexts API (Migration 012)
|
||
"maturity_models": "1.4.0", # matrix_stack_bundle: vollständiger Katalog+Modelle+Bindings Export/Import
|
||
}
|
||
|
||
CHANGELOG = [
|
||
{
|
||
"version": "0.8.26",
|
||
"date": "2026-05-05",
|
||
"changes": [
|
||
"ACCESS_LAYER: clubs-, club_memberships-, club_join_requests-Router nutzen Depends(get_tenant_context) statt nur require_auth",
|
||
"profiles: PUT /profiles/{id} und /profile mit TenantContext; profile_document für /auth/me und intern",
|
||
"exercise_progression_graphs: Liste/Detail nach library_content_visibility_sql; Leserechte Vereins-Graphs; POST/PUT mit assert_valid_governance_visibility und club_id wie Übungen",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.25",
|
||
"date": "2026-05-05",
|
||
"changes": [
|
||
"Übungen PUT: bei visibility club wird club_id aus aktivem Verein oder Body gesetzt (verhindert club ohne club_id für Vereinsnutzer)",
|
||
"club_tenancy: governance visibility club für Plattform-Admins ohne Vereinsmitgliedschaft (nur Existenz clubs.id)",
|
||
"Login POST /api/auth/login: Rate-Limit 30/minute pro IP (vorher 5/minute)",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.24",
|
||
"date": "2026-05-05",
|
||
"changes": [
|
||
"Übungen-Router: get/update/delete, Varianten, Medien — Depends(get_tenant_context); Upload-Limits via TenantContext; fehlenden DELETE decorator variants gefixt",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.23",
|
||
"date": "2026-05-05",
|
||
"changes": [
|
||
"ACCESS_LAYER: library_content_visibility_sql + TenantContext an Übungen-Liste, Rahmenprogramme, Trainingsplanung",
|
||
"POST Übung/Vorlage/Rahmenprogramm: visibility club ohne club_id → effective_club_id; POST Übung mit assert_valid_governance_visibility",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.22",
|
||
"date": "2026-05-05",
|
||
"changes": [
|
||
"ACCESS_LAYER Stufe B: Modul tenant_context (resolve_tenant_context, Depends(get_tenant_context)); GET /profiles/me liefert effective_club_id; veralteter X-Active-Club-Id wird dort verworfen (ignore), strikt auf anderen Endpoints via Depends",
|
||
"Arbeitspapier ACCESS_LAYER_ENDPOINT_AUDIT.md für Router-Inventar",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.21",
|
||
"date": "2026-05-05",
|
||
"changes": [
|
||
"FastAPI: Router club_memberships und club_join_requests registriert (GET /api/clubs/{id}/members, join-requests u. a.) — behoben 404 auf Vereinsseite Tab Mitglieder",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.20",
|
||
"date": "2026-05-05",
|
||
"changes": [
|
||
"Migration 041: wenn noch kein superadmin existiert, werden ältestes Profil mit role admin zu superadmin hochgestuft",
|
||
"Registrierung: erster Nutzer und ADMIN_BOOTSTRAP_EMAILS erhalten superadmin (vorher admin)",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.19",
|
||
"date": "2026-05-05",
|
||
"changes": [
|
||
"Portal-Admin: GET /api/admin/users (alle Nutzer + Vereine); PUT /profiles/{id} mit role/tier (Super-Admin nur durch Super-Admin); Mitgliedschaft inaktiv in Übersicht",
|
||
"GUI Admin → Nutzer: Portal-Rolle/Tier, Verein zuweisen, Vereinsrollen bearbeiten",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.18",
|
||
"date": "2026-05-05",
|
||
"changes": [
|
||
"DB 040 club_membership_requests; API Antrag/Abrufen/annehmen/ablehnen; öffentliches Vereinsverzeichnis; Mitglieder-Directory für Trainerwahl",
|
||
"GUI: Vereinsverwaltung Tab Mitglieder & Anträge; Registrierung/Einstellungen Vereinsantrag; Gruppenformular Haupt- und Co-Trainer",
|
||
"GET /profiles nur noch für Plattform-Admins",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.17",
|
||
"date": "2026-05-05",
|
||
"changes": [
|
||
"Multi-Tenancy Phase 4: training_plan_templates + training_framework_programs Listen und Lesen nach visibility/club wie Übungen; Schreiben nur Ersteller oder Plattform-Admin; club_tenancy.assert_valid_governance_visibility",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.16",
|
||
"date": "2026-05-05",
|
||
"changes": [
|
||
"API Vereinsmitglieder: GET/POST/GET-one/PUT/DELETE /api/clubs/{id}/members (Plattform- oder Vereinsadmin); Frontend api.js Hooks",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.15",
|
||
"date": "2026-05-05",
|
||
"changes": [
|
||
"DB 039 Fix: Co-Trainer-Backfill über Subquery + CASE (kein jsonb_array_length/jsonb_array_elements auf Nicht-Arrays durch Planner/LATERAL-Reihenfolge)",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.14",
|
||
"date": "2026-05-05",
|
||
"changes": [
|
||
"DB 039 Fix: Co-Trainer-Backfill nur wenn co_trainer_ids ein JSON-Array ist (vermeidet jsonb_array_length auf Nicht-Array)",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.13",
|
||
"date": "2026-05-05",
|
||
"changes": [
|
||
"Fix: Startup unter Windows (cp1252) — Emoji/Sonderzeichen in print durch ASCII ([OK]/[FAIL]/[WARN]) ersetzt (main, run_migrations, db_init)",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.12",
|
||
"date": "2026-05-05",
|
||
"changes": [
|
||
"DB 039: club_members, club_member_roles, clubs.primary_admin_profile_id, profiles.active_club_id + Backfill",
|
||
"Multi-Tenancy: Vereinslisten gefiltert, Vereinsanlage nur Plattform-Admin mit primary_admin_profile_id",
|
||
"Übungen: visibility club nur für Mitglieder des zugeordneten Vereins",
|
||
"GET /api/profiles/me: clubs[], ohne pin_hash; active_club_id setzen via PUT",
|
||
"Frontend: X-Active-Club-Id, Vereins-Umschalter, Vereinsseiten angepasst",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.11",
|
||
"date": "2026-05-05",
|
||
"changes": [
|
||
"DB 038: training_units.lead_trainer_profile_id (Vertretung / Leitung pro Termin)",
|
||
"API GET /api/training-units: club_id, assigned_to_me, sort, limit; Co-Trainer in Sichtbarkeit; lead_trainer_name / effective_lead_trainer_profile_id",
|
||
"API PUT /api/training-units/{id}: lead_trainer_profile_id (Validierung über Gruppe)",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.10",
|
||
"date": "2026-05-05",
|
||
"changes": [
|
||
"DB 037: Rahmen-Slot-Blueprints als training_units (framework_slot_id); migration training_framework_slot_exercises → Sektionen/Items; origin_framework_slot_id für Kopien",
|
||
"API: Rahmen-Slots mit sections/exercises aus Blueprint; Kalender list_training_units ohne Blueprints; POST /api/training-units/from-framework-slot",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.9",
|
||
"date": "2026-05-05",
|
||
"changes": [
|
||
"DB 036: Rahmenprogramm Kontext (Fokusbereich, Stilrichtung, M:N Trainingsarten & Zielgruppen); nur Bibliothek — plan_mode/group_id/Slot-training_unit entfernt.",
|
||
"API: /api/training-framework-programs ohne concrete/library; Payload focus_area_id, style_direction_id, training_type_ids, target_group_ids",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.8",
|
||
"date": "2026-05-05",
|
||
"changes": [
|
||
"DB 035: Trainingsrahmenprogramm (Rahmen, Ziele, Slots, Slot-Übungen); plan_mode concrete|library",
|
||
"DB 035: training_plan_templates.visibility + Backfill club (CURR-007/008)",
|
||
"API: CRUD /api/training-framework-programs (AuthZ wie Übungs-/Planungsbibliothek)",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.7",
|
||
"date": "2026-04-30",
|
||
"changes": [
|
||
"DB 034: Progressionskanten mit optionalen Varianten-Endpunkten",
|
||
"API: POST …/edges/sequence (Reihe auf einmal); POST …/edges/delete-batch",
|
||
"Frontend Progressions-UI: Sequenz-Editor, Ketten-Ansicht, Variantenwahl",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.6",
|
||
"date": "2026-04-30",
|
||
"changes": [
|
||
"DB 033: exercise_progression_edges.notes (Entwicklungsziel)",
|
||
"API: Kanten mit notes; JOIN Übungstitel in Listen; PUT Kanten-Notiz",
|
||
"Frontend: Progressionsgraphen-Tab unter Übungen + Bereich in Übung bearbeiten",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.5",
|
||
"date": "2026-04-30",
|
||
"changes": [
|
||
"DB 032: exercise_progression_graphs + exercise_progression_edges (Übung→Übung, edge_type next_exercise)",
|
||
"API: CRUD Progressionsgraphen und Kanten unter /api/exercise-progression-graphs",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.4",
|
||
"date": "2026-04-27",
|
||
"changes": [
|
||
"run_migrations: Warteschlange nach numerischem Präfix der Dateien (stabile Reihenfolge auch bei ungleich langen Zahlen wie 9 vs 10)",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.3",
|
||
"date": "2026-04-28",
|
||
"changes": [
|
||
"Migrationen: Warteschlange aller fehlenden *.sql; idempotent über schema_migrations",
|
||
"Ausführung vorzugsweise psql -1 -f (eine Transaktion pro Datei); Fallback psycopg2 + sqlparse.split",
|
||
"requirements: sqlparse wenn kein psql im PATH",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.2",
|
||
"date": "2026-04-28",
|
||
"changes": [
|
||
"main: run_migrations — Exit-Code auswerten; bei Fehler kein API-Start (verhindert Prod ohne Skill-Tabellen wie 022)",
|
||
"SKIP_DB_MIGRATE=1 optional für lokale Runs ohne Datenbank",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.1",
|
||
"date": "2026-04-28",
|
||
"changes": [
|
||
"skills: JSONB keywords per psycopg2.extras.Json (verhindert 500 wenn keywords als Objekt/Array gesendet wird)",
|
||
"GET /api/health/ready: DB-Verbindung + Kern-Tabellen + schema_migrations_count (ohne Auth, für Prod-Debugging)",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.0",
|
||
"date": "2026-04-28",
|
||
"changes": [
|
||
"DB 031: Trainingsvorlagen (Sektionen) + Struktur pro Einheit (Sektionen, Übungen/Notizen, Dauer)",
|
||
"API: /api/training-plan-templates CRUD; Trainingseinheiten mit sections[] + plan_template_id",
|
||
"Trainingsplanung UI: Abschnitte, Zwischen-Anmerkungen, Vorlagen auswählen / speichern",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.7.9",
|
||
"date": "2026-04-27",
|
||
"changes": [
|
||
"Übungsvarianten: POST/PUT/DELETE /api/exercises/{id}/variants + reorder",
|
||
"Übung bearbeiten: voller Varianten-Editor (Speichern pro Variante, Reihenfolge, Voraussetzung)",
|
||
"Übung Ansehen: Varianten-Metadaten (Dauer, Schwierigkeit, Material, Progression)",
|
||
"GET /exercises Detail: Varianten-Sortierung sequence_order → progression_level",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.7.8",
|
||
"date": "2026-04-27",
|
||
"changes": [
|
||
"DB 030: training_unit_exercises.exercise_variant_id (FK exercise_variants)",
|
||
"GET /exercises?include_variants=true liefert Varianten für Trainingsplanung",
|
||
"Trainingseinheiten: optional exercise_variant_id beim Anlegen/Aktualisieren",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.7.7",
|
||
"date": "2026-04-27",
|
||
"changes": [
|
||
"DB 029: Fähigkeitsstufen Einheit (basis–optimierung), model_levels Namen 1–5",
|
||
"Übungen: GET /exercises Filter Stilrichtung, Trainingsstil, Zielgruppe, Fähigkeits-Stufe min/max, ai_search (Volltext-Platzhalter)",
|
||
"API: exercise_skills Level-Normalisierung bei Schreiben/Lesen; Wiki-Import Slugs statt Zahl in DB",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.7.6",
|
||
"date": "2026-04-27",
|
||
"changes": [
|
||
"API: GET/POST /api/admin/matrix-stack (shinkan.matrix_stack.v1) – Fähigkeitskatalog, Reifegradmodelle, Kontext-Bindings für Test→Prod",
|
||
"DB 028: exercise_media (Embed/Metadaten), exercise_skills VARCHAR-Level/Intensität; API: POST/PUT/DELETE Medien, /media Static; Übungen-Listen-Fokus",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.7.5",
|
||
"date": "2026-04-27",
|
||
"changes": [
|
||
"Resolve/Export: Legacy M:N nur noch, wenn für den Fokus keine Kontext-Bindings existieren (korrekte Striktheit für Fokus+Trainingsstil / Teil-Kontexte)",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.7.4",
|
||
"date": "2026-04-27",
|
||
"changes": [
|
||
"DB 027: Bindings Fokus+Trainingsstil ohne Stilrichtung",
|
||
"resolve: alle passenden Bindings nach Spezifität mergen",
|
||
"API: Export/Import JSON (Modell + aufgelöste Matrix)",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.7.3",
|
||
"date": "2026-04-27",
|
||
"changes": [
|
||
"DB 026: maturity_model_context_bindings (Fokus / Stilrichtung / Trainingsstil)",
|
||
"API: resolve merged mehrere Modelle; CRUD Bindings; training_type_id Query",
|
||
"Admin-Tab Kontext-Zuordnung",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.7.2",
|
||
"date": "2026-04-27",
|
||
"changes": [
|
||
"DB: Migration 025 – maturity_model_focus_areas / _style_directions / _target_groups (M:N)",
|
||
"Bootstrap-Reifegradmodell für alle importierten Skills (Wiki), Stufen 1–5",
|
||
"API+UI: Kontext als Mehrfachauswahl; Matrix zeigt Haupt-/Untergruppe pro Fähigkeit",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.7.1",
|
||
"date": "2026-04-27",
|
||
"changes": [
|
||
"DB: Migration 024 – maturity_models, model_levels, model_skills, model_skill_levels",
|
||
"API: CRUD Reifegradmodelle, Matrix-Pflege, resolve-Kontext",
|
||
"Frontend: Admin Fähigkeitsmatrix (/admin/maturity-models)",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.7.0",
|
||
"date": "2026-04-24",
|
||
"changes": [
|
||
"BREAKING: Exercises v2.0 - Clean-Room Rebuild (kein Legacy-Code)",
|
||
"DB: Migration 014 - Variant Progression + Search Vector + Legacy DROP (age_groups, focus_area, secondary_areas, training_character)",
|
||
"DB: Migration 016 - Saved Exercise Searches",
|
||
"DB: Migration 017 - Exercise Blocks + Template Blocks",
|
||
"Backend: exercises.py komplett neu nach EXERCISES_API_SPEC.md v1.2",
|
||
"Backend: Nur M:N Relations, keine JSONB-Kataloge mehr",
|
||
"Backend: enrich_exercise_detail() für vollständige Objekte",
|
||
"Backend: assign_exercise_relations() für M:N Management",
|
||
"API: GET /exercises - Volltext-Suche via tsvector",
|
||
"API: POST/PUT /exercises - M:N Relations (focus_areas_multi, training_styles_multi, etc.)",
|
||
"Issue #53 konform: Import = Feld-Zuordnung, keine fachliche Interpretation",
|
||
]
|
||
},
|
||
{
|
||
"version": "0.6.0",
|
||
"date": "2026-04-24",
|
||
"changes": [
|
||
"Feature: MediaWiki Import (SMW Direct API)",
|
||
"DB: Migration 018 - wiki_import_log + wiki_import_references",
|
||
"Backend: SmwClient (login, browse, ask, categorymembers)",
|
||
"Backend: SmwMapper (SMW Properties → exercises/skills/methods)",
|
||
"Backend: import_wiki Router (preview, execute, status, logs, discover)",
|
||
"Config: MEDIAWIKI_API_URL=https://karatetrainer.net/api.php",
|
||
]
|
||
},
|
||
{
|
||
"version": "0.5.0",
|
||
"date": "2026-04-23",
|
||
"changes": [
|
||
"Feature: Trainer-Kontext-System für fokussierte Ansichten",
|
||
"DB: Migration 012 - exercise_training_characters (M:N)",
|
||
"DB: Migration 012 - trainer_contexts (Trainer-Profil-System)",
|
||
"Backend: CRUD API für Trainer-Kontexte (/api/trainer-contexts)",
|
||
"Frontend: TrainerContextsPage für Verwaltung eigener Arbeitsbereiche",
|
||
"Architektur: Flat Catalogs + Smart Filtering für 1000+ Übungen",
|
||
"Architektur: NULL = 'für alles geeignet', M:N = spezifische Zuordnung",
|
||
]
|
||
},
|
||
{
|
||
"version": "0.4.0",
|
||
"date": "2026-04-23",
|
||
"changes": [
|
||
"BREAKING: Migration 010 - Umbenennung training_styles → style_directions",
|
||
"BREAKING: Migration 011 - Neue Dimension training_types (Breitensport/Leistungssport)",
|
||
"DB: Konsistente Terminologie - Stilrichtungen vs. Trainingsstile",
|
||
"DB: Neue Tabelle training_types mit Seed-Daten (Breitensport, Leistungssport, Wettkampf)",
|
||
"DB: Neue Junction-Tabelle exercise_training_types (M:N)",
|
||
"Architektur: Fokusbereich → Stilrichtung → Trainingsstil → Zielgruppe (alle M:N)",
|
||
"Backend: Alle SQL Queries aktualisiert auf neue Tabellennamen (style_directions, style_direction_target_groups)",
|
||
"Backend: API Parameter umbenannt (training_style_id → style_direction_id)",
|
||
"Backend: CRUD Endpoints für training_types hinzugefügt",
|
||
]
|
||
},
|
||
{
|
||
"version": "0.3.4",
|
||
"date": "2026-04-23",
|
||
"changes": [
|
||
"BREAKING: Migration 009 - Zielgruppen M:N Refactoring",
|
||
"DB: target_groups.training_style_id entfernt (jetzt global unabhängig)",
|
||
"DB: Neue Junction-Tabelle training_style_target_groups (M:N)",
|
||
"API: 5 neue Endpoints für M:N Management (GET/POST/PUT/DELETE + hierarchy)",
|
||
"API: GET /training-style-target-groups mit Enrichment (focus_area_name, training_style_name)",
|
||
"API: GET /training-styles/hierarchy für Tree-View (verschachtelte Struktur)",
|
||
"API: POST /training-style-target-groups mit Upsert-Logik",
|
||
"Backward-Compatible: exercise_target_groups weiterhin unterstützt",
|
||
"Architecture: Eine Zielgruppe kann mehreren Stilen zugeordnet werden",
|
||
]
|
||
},
|
||
{
|
||
"version": "0.3.3",
|
||
"date": "2026-04-23",
|
||
"changes": [
|
||
"Fix: Admin-Navigation - Redirect /admin → /admin/catalogs",
|
||
"Fix: Admin-Link funktioniert jetzt (vorher 404)"
|
||
]
|
||
},
|
||
{
|
||
"version": "0.3.2",
|
||
"date": "2026-04-23",
|
||
"changes": [
|
||
"Feature: Zielgruppen-Verwaltung komplett (Backend + Frontend)",
|
||
"API: GET/POST/PUT/DELETE /target-groups mit hierarchischem Kontext (focus_area → training_style → target_group)",
|
||
"Admin UI: Neuer Tab 'Zielgruppen' in Katalogverwaltung",
|
||
"UX: Create/Edit-Forms mit Training-Stil-Auswahl, Altersbereich (min/max)",
|
||
"UX: Hierarchie-Anzeige in Liste (Fokusbereich → Stil → Zielgruppe)",
|
||
"Protection: DELETE mit CASCADE-Schutz (Fehler wenn Übungen zugeordnet)",
|
||
]
|
||
},
|
||
{
|
||
"version": "0.3.1",
|
||
"date": "2026-04-23",
|
||
"changes": [
|
||
"Feature: Exercises-Router unterstützt M:N Zuordnungen",
|
||
"API: GET /exercises/{id} liefert focus_areas[], training_styles[], target_groups[], age_groups_catalog[]",
|
||
"API: POST/PUT /exercises akzeptiert focus_areas_multi[], training_styles_multi[], target_groups_multi[], age_groups_catalog[]",
|
||
"Pattern: DELETE+INSERT für M:N Updates (konsistent mit skills)",
|
||
"Backward-Compatible: Legacy FK-Felder (focus_area_id, training_style_id) bleiben erhalten",
|
||
]
|
||
},
|
||
{
|
||
"version": "0.3.0",
|
||
"date": "2026-04-23",
|
||
"changes": [
|
||
"BREAKING: M:N Beziehungen für Übungen (statt 1:1)",
|
||
"Migration 008: M:N Zuordnungstabellen (exercise_focus_areas, exercise_styles, exercise_target_groups, exercise_age_groups)",
|
||
"Feature: Hierarchische Katalog-Struktur (Fokusbereich → Stil → Zielgruppe)",
|
||
"Feature: Zielgruppen-Verwaltung (training_styles.focus_area_id Hierarchie)",
|
||
"Feature: Primary/Secondary Assignments (is_primary Flag)",
|
||
"Doku: DATABASE_SCHEMA.md + DOMAIN_MODEL.md kontinuierlich gepflegt",
|
||
"Architecture: Smart Cascade-Logik (RESTRICT, Rerouting, Move)",
|
||
]
|
||
},
|
||
{
|
||
"version": "0.2.0",
|
||
"date": "2026-04-23",
|
||
"changes": [
|
||
"Feature: Admin-verwaltbare Kataloge (Focus Areas, Training Styles, Training Characters, Skill Categories)",
|
||
"Feature: Trainer-Fokusbereich-Zuordnung für rollenbasierte Filterung",
|
||
"Migration 007: Katalog-Tabellen + Seed-Daten",
|
||
"Frontend: AdminCatalogsPage mit 5 Tabs (CRUD für alle Kataloge)",
|
||
"Frontend: ExercisesPage nutzt Katalog-Dropdowns (kein Hard-Coding mehr)",
|
||
"Frontend: Trainingsstil-Dropdown hinzugefügt (fehlte komplett)",
|
||
"Standardisierung: Alle Formulare mit Labels oben, volle Breite, linksbündig",
|
||
]
|
||
},
|
||
{
|
||
"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)",
|
||
"Infrastructure: Auth + Membership von Mitai übernommen",
|
||
]
|
||
}
|
||
]
|