shinkan-jinkendo/backend/migrations/035_training_framework_programs.sql
Lars b054c642a3
Some checks failed
Deploy Development / deploy (push) Successful in 33s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 14s
Test Suite / playwright-tests (push) Failing after 40s
chore: update training framework specifications and versioning
- Incremented version to 0.8.8 and updated database schema version to 20260505035.
- Added new entity `training_framework_programs` to manage training frameworks, including goals and slots.
- Enhanced `training_plan_templates` with a visibility attribute and backfilled existing data.
- Updated API to support CRUD operations for training frameworks, ensuring proper authorization similar to existing planning libraries.
- Revised documentation in DOMAIN_MODEL.md, TRAINING_CURRICULUM_AND_GOVERNANCE_CONCEPT.md, and TRAINING_FRAMEWORK_SPEC.md to reflect these changes.
2026-05-05 08:41:43 +02:00

93 lines
4.7 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- Migration 035: Trainingsrahmenprogramm (RahmenVorlage, CURR002 Stufe 2 / CURR009013)
-- + CURR007/008: training_plan_templates.visibility (Backfill club, dann NOT NULL + Default)
-- ── TrainingsMikrovorlagen: gemeinsamer GovernanceKern (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);
-- ── RahmenHeader ────────────────────────────────────────────────────────────
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 (CURR011: ≥ 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“, CURR010) ────────────────────────
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);