-- Migration 012: Exercise Training Characters (M:N) + Trainer Contexts -- Author: Claude Code -- Date: 2026-04-23 -- Purpose: Add M:N relationship for training characters and trainer profile system DO $$ BEGIN -- ============================================================================ -- EXERCISE TRAINING CHARACTERS (M:N) -- ============================================================================ -- Create junction table for exercise ↔ training_characters IF NOT EXISTS ( SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'exercise_training_characters' ) THEN CREATE TABLE exercise_training_characters ( id SERIAL PRIMARY KEY, exercise_id INT NOT NULL REFERENCES exercises(id) ON DELETE CASCADE, training_character_id INT NOT NULL REFERENCES training_characters(id) ON DELETE RESTRICT, is_primary BOOLEAN DEFAULT false, created_at TIMESTAMP DEFAULT NOW(), UNIQUE(exercise_id, training_character_id) ); CREATE INDEX idx_exercise_training_characters_exercise ON exercise_training_characters(exercise_id); CREATE INDEX idx_exercise_training_characters_character ON exercise_training_characters(training_character_id); RAISE NOTICE 'Created table: exercise_training_characters'; END IF; -- ============================================================================ -- TRAINER CONTEXTS (Fokussierte Trainer-Ansichten) -- ============================================================================ -- Create trainer_contexts table IF NOT EXISTS ( SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'trainer_contexts' ) THEN CREATE TABLE trainer_contexts ( id SERIAL PRIMARY KEY, profile_id INT NOT NULL REFERENCES profiles(id) ON DELETE CASCADE, -- Context definition name VARCHAR(100) NOT NULL, -- "Karate Goju-Ryu Breitensport", "Gewaltschutz" -- Hierarchical filters (all optional) focus_area_id INT REFERENCES focus_areas(id) ON DELETE CASCADE, style_direction_id INT REFERENCES style_directions(id) ON DELETE CASCADE, training_type_id INT REFERENCES training_types(id) ON DELETE SET NULL, -- Flags is_style_independent BOOLEAN DEFAULT false, -- true = "Leistungssport stilunabhängig" is_active BOOLEAN DEFAULT true, -- Metadata description TEXT, sort_order INT DEFAULT 99, created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW(), -- Prevent duplicates UNIQUE(profile_id, focus_area_id, style_direction_id, training_type_id) ); CREATE INDEX idx_trainer_contexts_profile ON trainer_contexts(profile_id); CREATE INDEX idx_trainer_contexts_focus ON trainer_contexts(focus_area_id); CREATE INDEX idx_trainer_contexts_style ON trainer_contexts(style_direction_id); CREATE INDEX idx_trainer_contexts_type ON trainer_contexts(training_type_id); RAISE NOTICE 'Created table: trainer_contexts'; END IF; -- ============================================================================ -- SEED DATA: Example Trainer Contexts -- ============================================================================ -- Insert example contexts for profile_id = 1 (if exists) DO $seed$ BEGIN IF EXISTS (SELECT 1 FROM profiles WHERE id = 1) THEN -- Only insert if not already present IF NOT EXISTS (SELECT 1 FROM trainer_contexts WHERE profile_id = 1) THEN INSERT INTO trainer_contexts (profile_id, name, focus_area_id, style_direction_id, training_type_id, is_style_independent, description, sort_order) VALUES -- Karate Breitensport (if focus_area and style exist) (1, 'Karate Breitensport', (SELECT id FROM focus_areas WHERE name = 'Karate' LIMIT 1), NULL, -- all styles (SELECT id FROM training_types WHERE name = 'Breitensport' LIMIT 1), false, 'Breitensport für alle Karate-Stilrichtungen', 1 ); RAISE NOTICE 'Inserted example trainer contexts for profile_id = 1'; END IF; END IF; END $seed$; RAISE NOTICE 'Migration 012 completed successfully'; END $$;