- Incremented application version to 0.8.0 and updated database schema version to 20260428031. - Introduced support for training plan templates, allowing users to create and manage reusable training structures. - Enhanced the Training Planning UI to include sections and exercises, improving the organization of training units. - Updated API endpoints for training plan templates, enabling CRUD operations for better integration with the frontend. - Improved validation and permission checks for creating training units, ensuring proper access control.
114 lines
4.5 KiB
SQL
114 lines
4.5 KiB
SQL
-- Migration 031: Trainingsvorlagen (Sektionen) und strukturierter Ablauf pro Einheit
|
|
-- Freie Anmerkungszeilen (note) zwischen Übungen (exercise) mit optionaler Variante/Dauer.
|
|
|
|
-- ── Vorlagen (wiederverwendbare Gliederung für Gruppen/Trainer) ─────────────
|
|
CREATE TABLE IF NOT EXISTS training_plan_templates (
|
|
id SERIAL PRIMARY KEY,
|
|
club_id INT REFERENCES clubs(id) ON DELETE SET NULL,
|
|
created_by INT REFERENCES profiles(id) ON DELETE SET NULL,
|
|
name VARCHAR(200) NOT NULL,
|
|
description TEXT,
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS training_plan_template_sections (
|
|
id SERIAL PRIMARY KEY,
|
|
template_id INT NOT NULL REFERENCES training_plan_templates(id) ON DELETE CASCADE,
|
|
order_index INT NOT NULL,
|
|
title VARCHAR(200) NOT NULL,
|
|
guidance_text TEXT,
|
|
UNIQUE (template_id, order_index)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_training_plan_templates_club ON training_plan_templates(club_id);
|
|
CREATE INDEX IF NOT EXISTS idx_training_plan_templates_creator ON training_plan_templates(created_by);
|
|
CREATE INDEX IF NOT EXISTS idx_training_plan_template_sections_template ON training_plan_template_sections(template_id);
|
|
|
|
DROP TRIGGER IF EXISTS training_plan_templates_update ON training_plan_templates;
|
|
CREATE TRIGGER training_plan_templates_update
|
|
BEFORE UPDATE ON training_plan_templates
|
|
FOR EACH ROW EXECUTE FUNCTION update_timestamp();
|
|
|
|
-- ── Verknüpfung Einheit ↔ genutzte Vorlage (nur Metadaten) ──────────────────
|
|
ALTER TABLE training_units
|
|
ADD COLUMN IF NOT EXISTS plan_template_id INT REFERENCES training_plan_templates(id) ON DELETE SET NULL;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_training_units_plan_template ON training_units(plan_template_id);
|
|
|
|
-- ── Konkrete Sektionen je Trainingseinheit ────────────────────────────────
|
|
CREATE TABLE IF NOT EXISTS training_unit_sections (
|
|
id SERIAL PRIMARY KEY,
|
|
training_unit_id INT NOT NULL REFERENCES training_units(id) ON DELETE CASCADE,
|
|
order_index INT NOT NULL,
|
|
title VARCHAR(200) NOT NULL DEFAULT 'Abschnitt',
|
|
guidance_notes TEXT,
|
|
source_template_section_id INT REFERENCES training_plan_template_sections(id) ON DELETE SET NULL,
|
|
UNIQUE (training_unit_id, order_index)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_training_unit_sections_unit ON training_unit_sections(training_unit_id);
|
|
|
|
-- ── Positionen: Übung oder freie Anmerkung ────────────────────────────────
|
|
CREATE TABLE IF NOT EXISTS training_unit_section_items (
|
|
id SERIAL PRIMARY KEY,
|
|
section_id INT NOT NULL REFERENCES training_unit_sections(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,
|
|
actual_duration_min INT,
|
|
notes TEXT,
|
|
modifications TEXT,
|
|
note_body TEXT,
|
|
UNIQUE (section_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_unit_section_items_section ON training_unit_section_items(section_id);
|
|
CREATE INDEX IF NOT EXISTS idx_training_unit_section_items_exercise ON training_unit_section_items(exercise_id)
|
|
WHERE exercise_id IS NOT NULL;
|
|
|
|
-- ── Bestehende Zeilen migrieren: eine Sektion „Übungen“ pro Einheit ─────────
|
|
INSERT INTO training_unit_sections (training_unit_id, order_index, title)
|
|
SELECT id, 0, 'Übungen'
|
|
FROM training_units tu
|
|
WHERE NOT EXISTS (
|
|
SELECT 1 FROM training_unit_sections tus WHERE tus.training_unit_id = tu.id
|
|
);
|
|
|
|
INSERT INTO training_unit_section_items (
|
|
section_id,
|
|
order_index,
|
|
item_type,
|
|
exercise_id,
|
|
exercise_variant_id,
|
|
planned_duration_min,
|
|
actual_duration_min,
|
|
notes,
|
|
modifications,
|
|
note_body
|
|
)
|
|
SELECT
|
|
tus.id,
|
|
tue.order_index,
|
|
'exercise',
|
|
tue.exercise_id,
|
|
tue.exercise_variant_id,
|
|
tue.planned_duration_min,
|
|
tue.actual_duration_min,
|
|
tue.notes,
|
|
tue.modifications,
|
|
NULL
|
|
FROM training_unit_exercises tue
|
|
INNER JOIN training_unit_sections tus
|
|
ON tus.training_unit_id = tue.training_unit_id
|
|
AND tus.order_index = 0;
|
|
|
|
DROP TABLE IF EXISTS training_unit_exercises;
|