-- Migration 054: Trainingsmodule (Bibliothek / Planung) — Phase 1 MVP -- Fachgrundlage: functional/Shinkan Trainingsmodule Kombinationsuebungen Spezifikation V2.md CREATE TABLE IF NOT EXISTS training_modules ( id SERIAL PRIMARY KEY, club_id INT REFERENCES clubs(id) ON DELETE SET NULL, created_by INT REFERENCES profiles(id) ON DELETE SET NULL, title VARCHAR(200) NOT NULL, summary TEXT, goal TEXT, recommended_duration_min INT, target_group_notes TEXT, deployment_context_notes TEXT, primary_method_id INT REFERENCES training_methods(id) ON DELETE SET NULL, visibility VARCHAR(50) NOT NULL DEFAULT 'club' CHECK (visibility IN ('private', 'club', 'official')), created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_training_modules_club ON training_modules(club_id); CREATE INDEX IF NOT EXISTS idx_training_modules_creator ON training_modules(created_by); CREATE INDEX IF NOT EXISTS idx_training_modules_visibility ON training_modules(visibility); CREATE INDEX IF NOT EXISTS idx_training_modules_method ON training_modules(primary_method_id) WHERE primary_method_id IS NOT NULL; DROP TRIGGER IF EXISTS training_modules_update ON training_modules; CREATE TRIGGER training_modules_update BEFORE UPDATE ON training_modules FOR EACH ROW EXECUTE FUNCTION update_timestamp(); CREATE TABLE IF NOT EXISTS training_module_items ( id SERIAL PRIMARY KEY, module_id INT NOT NULL REFERENCES training_modules(id) ON DELETE CASCADE, order_index INT NOT NULL, item_type VARCHAR(20) NOT NULL CHECK (item_type IN ('exercise', 'note')), exercise_id INT REFERENCES exercises(id) ON DELETE SET NULL, exercise_variant_id INT REFERENCES exercise_variants(id) ON DELETE SET NULL, planned_duration_min INT, notes TEXT, note_body TEXT, UNIQUE (module_id, order_index), CHECK ( (item_type = 'exercise' AND exercise_id IS NOT NULL AND note_body IS NULL) OR (item_type = 'note' AND exercise_id IS NULL) ) ); CREATE INDEX IF NOT EXISTS idx_training_module_items_module ON training_module_items(module_id); CREATE INDEX IF NOT EXISTS idx_training_module_items_exercise ON training_module_items(exercise_id) WHERE exercise_id IS NOT NULL; -- Herkunft bei Übernahme aus Modul-Bibliothek (Kopie, keine Live-Verknüpfung) ALTER TABLE training_unit_section_items ADD COLUMN IF NOT EXISTS source_training_module_id INT REFERENCES training_modules(id) ON DELETE SET NULL; CREATE INDEX IF NOT EXISTS idx_training_unit_section_items_source_module ON training_unit_section_items(source_training_module_id) WHERE source_training_module_id IS NOT NULL;