shinkan-jinkendo/backend/migrations/035_training_framework_programs.sql

93 lines
4.7 KiB
MySQL
Raw Permalink Normal View History

-- 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);