-- Migration 035: Trainingsrahmenprogramm (Rahmen‑Vorlage, CURR‑002 Stufe 2 / CURR‑009–013) -- + CURR‑007/008: training_plan_templates.visibility (Backfill club, dann NOT NULL + Default) -- ── Trainings‑Mikrovorlagen: gemeinsamer Governance‑Kern (visibility) ───── ALTER TABLE training_plan_templates ADD COLUMN IF NOT EXISTS visibility VARCHAR(50) CHECK (visibility IN ('private', 'club', 'official')); UPDATE training_plan_templates SET visibility = 'club' WHERE visibility IS NULL; ALTER TABLE training_plan_templates ALTER COLUMN visibility SET DEFAULT 'club'; ALTER TABLE training_plan_templates ALTER COLUMN visibility SET NOT NULL; CREATE INDEX IF NOT EXISTS idx_training_plan_templates_visibility ON training_plan_templates(visibility); -- ── Rahmen‑Header ──────────────────────────────────────────────────────────── CREATE TABLE IF NOT EXISTS training_framework_programs ( id SERIAL PRIMARY KEY, title VARCHAR(200) NOT NULL, description TEXT, plan_mode VARCHAR(20) NOT NULL CHECK (plan_mode IN ('concrete', 'library')), -- Modus B (library): immer NULL · Modus A (concrete): optional gebunden an eine Trainingsgruppe group_id INT REFERENCES training_groups(id) ON DELETE SET NULL, planned_period_start DATE, planned_period_end DATE, visibility VARCHAR(50) NOT NULL DEFAULT 'private' CHECK (visibility IN ('private', 'club', 'official')), club_id INT REFERENCES clubs(id) ON DELETE SET NULL, created_by INT REFERENCES profiles(id) ON DELETE SET NULL, created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW(), CHECK ( (plan_mode = 'library' AND group_id IS NULL) OR plan_mode = 'concrete' ) ); CREATE INDEX IF NOT EXISTS idx_training_framework_programs_creator ON training_framework_programs(created_by); CREATE INDEX IF NOT EXISTS idx_training_framework_programs_club ON training_framework_programs(club_id); CREATE INDEX IF NOT EXISTS idx_training_framework_programs_visibility ON training_framework_programs(visibility); CREATE INDEX IF NOT EXISTS idx_training_framework_programs_mode ON training_framework_programs(plan_mode); CREATE INDEX IF NOT EXISTS idx_training_framework_programs_group ON training_framework_programs(group_id); DROP TRIGGER IF EXISTS training_framework_programs_update ON training_framework_programs; CREATE TRIGGER training_framework_programs_update BEFORE UPDATE ON training_framework_programs FOR EACH ROW EXECUTE FUNCTION update_timestamp(); -- ── Zielliste (CURR‑011: ≥ 1 durch API beim Speichern) ───────────────────── CREATE TABLE IF NOT EXISTS training_framework_goals ( id SERIAL PRIMARY KEY, framework_program_id INT NOT NULL REFERENCES training_framework_programs(id) ON DELETE CASCADE, sort_order INT NOT NULL, title VARCHAR(500) NOT NULL, notes TEXT, UNIQUE (framework_program_id, sort_order) ); CREATE INDEX IF NOT EXISTS idx_training_framework_goals_framework ON training_framework_goals(framework_program_id); -- ── Slots (Sessions im Rahmen) ────────────────────────────────────────────── CREATE TABLE IF NOT EXISTS training_framework_slots ( id SERIAL PRIMARY KEY, framework_program_id INT NOT NULL REFERENCES training_framework_programs(id) ON DELETE CASCADE, sort_order INT NOT NULL, title VARCHAR(200), notes TEXT, training_unit_id INT REFERENCES training_units(id) ON DELETE SET NULL, UNIQUE (framework_program_id, sort_order) ); CREATE INDEX IF NOT EXISTS idx_training_framework_slots_framework ON training_framework_slots(framework_program_id); CREATE INDEX IF NOT EXISTS idx_training_framework_slots_unit ON training_framework_slots(training_unit_id); -- ── Übungen pro Slot (tragende „Stückliste“, CURR‑010) ──────────────────────── CREATE TABLE IF NOT EXISTS training_framework_slot_exercises ( id SERIAL PRIMARY KEY, slot_id INT NOT NULL REFERENCES training_framework_slots(id) ON DELETE CASCADE, exercise_id INT NOT NULL REFERENCES exercises(id) ON DELETE CASCADE, exercise_variant_id INT REFERENCES exercise_variants(id) ON DELETE SET NULL, order_index INT NOT NULL, UNIQUE (slot_id, order_index) ); CREATE INDEX IF NOT EXISTS idx_training_framework_slot_exercises_slot ON training_framework_slot_exercises(slot_id); CREATE INDEX IF NOT EXISTS idx_training_framework_slot_exercises_exercise ON training_framework_slot_exercises(exercise_id);