Some checks failed
Test Suite / pytest-backend (push) Waiting to run
Test Suite / lint-backend (push) Waiting to run
Test Suite / build-frontend (push) Waiting to run
Test Suite / k6 /health Baseline (push) Waiting to run
Test Suite / playwright-tests (push) Waiting to run
Deploy Development / deploy (push) Has been cancelled
- Bumped APP_VERSION to 0.8.137 and updated the changelog to reflect recent changes. - Introduced Migration 063 for training unit phases and parallel streams, enhancing the structure of training units. - Updated the training planning API to support nested phases and sections, improving data retrieval for UI components. - Enhanced section handling to accommodate new phase and stream structures, ensuring compatibility with existing workflows.
86 lines
3.9 KiB
SQL
86 lines
3.9 KiB
SQL
-- Migration 063: Phasen und parallele Streams pro Trainingseinheit (Grundlage Breakout).
|
|
-- Bestehende Sektionen werden einer Default-whole_group-Phase zugeordnet.
|
|
-- UNIQUE (training_unit_id, order_index) auf Sektionen entfällt zugunsten
|
|
-- eindeutiger order_index je Phase bzw. je parallel_stream.
|
|
|
|
-- ── Phasen ───────────────────────────────────────────────────────────────
|
|
CREATE TABLE IF NOT EXISTS training_unit_phases (
|
|
id SERIAL PRIMARY KEY,
|
|
training_unit_id INT NOT NULL REFERENCES training_units(id) ON DELETE CASCADE,
|
|
order_index INT NOT NULL,
|
|
phase_kind VARCHAR(20) NOT NULL CHECK (phase_kind IN ('whole_group', 'parallel')),
|
|
title VARCHAR(200),
|
|
guidance_notes TEXT,
|
|
UNIQUE (training_unit_id, order_index)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_training_unit_phases_unit ON training_unit_phases(training_unit_id);
|
|
|
|
-- ── Streams innerhalb einer Parallelphase ──────────────────────────────────
|
|
CREATE TABLE IF NOT EXISTS training_unit_parallel_streams (
|
|
id SERIAL PRIMARY KEY,
|
|
phase_id INT NOT NULL REFERENCES training_unit_phases(id) ON DELETE CASCADE,
|
|
order_index INT NOT NULL,
|
|
title VARCHAR(200),
|
|
notes TEXT,
|
|
assigned_trainer_profile_ids JSONB,
|
|
UNIQUE (phase_id, order_index)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_training_unit_parallel_streams_phase
|
|
ON training_unit_parallel_streams(phase_id);
|
|
|
|
COMMENT ON COLUMN training_unit_parallel_streams.assigned_trainer_profile_ids IS
|
|
'Optionale Co-Trainer-IDs (JSON-Array von Profil-IDs) für diese Teilstrecke; MVP+';
|
|
|
|
-- ── Sektionen: Zuordnung zu Phase (gemeinsam) oder Stream (parallel) ─────
|
|
ALTER TABLE training_unit_sections
|
|
ADD COLUMN IF NOT EXISTS phase_id INT REFERENCES training_unit_phases(id) ON DELETE CASCADE,
|
|
ADD COLUMN IF NOT EXISTS parallel_stream_id INT REFERENCES training_unit_parallel_streams(id) ON DELETE CASCADE;
|
|
|
|
-- Backfill: je Einheit mit Sektionen eine whole_group-Phase, alle Sektionen dorthin
|
|
INSERT INTO training_unit_phases (training_unit_id, order_index, phase_kind, title)
|
|
SELECT tu.id, 0, 'whole_group', NULL
|
|
FROM training_units tu
|
|
WHERE EXISTS (SELECT 1 FROM training_unit_sections s WHERE s.training_unit_id = tu.id)
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM training_unit_phases p
|
|
WHERE p.training_unit_id = tu.id AND p.order_index = 0 AND p.phase_kind = 'whole_group'
|
|
);
|
|
|
|
UPDATE training_unit_sections tus
|
|
SET phase_id = p.id
|
|
FROM training_unit_phases p
|
|
WHERE tus.phase_id IS NULL
|
|
AND p.training_unit_id = tus.training_unit_id
|
|
AND p.order_index = 0
|
|
AND p.phase_kind = 'whole_group';
|
|
|
|
-- Alte globale Reihenfolge-Eindeutigkeit pro Einheit entfernen
|
|
ALTER TABLE training_unit_sections
|
|
DROP CONSTRAINT IF EXISTS training_unit_sections_training_unit_id_order_index_key;
|
|
|
|
-- Genau eine Zielspalte gesetzt: gemeinsame Phase ODER paralleler Stream
|
|
ALTER TABLE training_unit_sections
|
|
DROP CONSTRAINT IF EXISTS training_unit_sections_phase_or_stream_chk;
|
|
|
|
ALTER TABLE training_unit_sections
|
|
ADD CONSTRAINT training_unit_sections_phase_or_stream_chk CHECK (
|
|
(phase_id IS NOT NULL AND parallel_stream_id IS NULL)
|
|
OR (phase_id IS NULL AND parallel_stream_id IS NOT NULL)
|
|
);
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS uq_training_unit_sections_phase_order
|
|
ON training_unit_sections (phase_id, order_index)
|
|
WHERE phase_id IS NOT NULL;
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS uq_training_unit_sections_stream_order
|
|
ON training_unit_sections (parallel_stream_id, order_index)
|
|
WHERE parallel_stream_id IS NOT NULL;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_training_unit_sections_phase
|
|
ON training_unit_sections(phase_id) WHERE phase_id IS NOT NULL;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_training_unit_sections_parallel_stream
|
|
ON training_unit_sections(parallel_stream_id) WHERE parallel_stream_id IS NOT NULL;
|