shinkan-jinkendo/backend/migrations/024_maturity_models.sql
Lars 5277f4f4cf
Some checks failed
Deploy Development / deploy (push) Successful in 34s
Test Suite / lint-backend (push) Successful in 1s
Test Suite / build-frontend (push) Successful in 5s
Test Suite / playwright-tests (push) Failing after 1m55s
feat: add maturity models functionality and update version
- Introduced new maturity models feature with CRUD operations in the API.
- Added routes and frontend components for managing maturity models.
- Updated version to 0.7.1 with corresponding build date and schema version.
- Enhanced admin navigation to include maturity models section.
- Documented changes in the changelog for version 0.7.1.
2026-04-27 11:32:30 +02:00

133 lines
5.2 KiB
SQL

-- Migration 024: Reifegradmodelle / Fähigkeitsmatrix (kontextbezogen)
-- Datum: 2026-04-27
-- ============================================================================
-- MATURITY MODELS
-- ============================================================================
CREATE TABLE IF NOT EXISTS maturity_models (
id SERIAL PRIMARY KEY,
name VARCHAR(200) NOT NULL,
description TEXT,
focus_area_id INT REFERENCES focus_areas(id) ON DELETE RESTRICT,
style_direction_id INT REFERENCES style_directions(id) ON DELETE RESTRICT,
target_group_id INT REFERENCES target_groups(id) ON DELETE RESTRICT,
level_count INT NOT NULL DEFAULT 5 CHECK (level_count BETWEEN 3 AND 10),
status VARCHAR(20) DEFAULT 'draft' CHECK (status IN ('draft', 'active', 'archived')),
version VARCHAR(20) DEFAULT '1.0',
created_by INT REFERENCES profiles(id) ON DELETE SET NULL,
club_id INT REFERENCES clubs(id) ON DELETE SET NULL,
import_source VARCHAR(50),
import_id VARCHAR(200),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
CONSTRAINT maturity_models_context_name_unique
UNIQUE (name, focus_area_id, style_direction_id, target_group_id)
);
-- ============================================================================
-- MODEL LEVELS (Stufen-Labels pro Modell)
-- ============================================================================
CREATE TABLE IF NOT EXISTS model_levels (
id SERIAL PRIMARY KEY,
maturity_model_id INT NOT NULL REFERENCES maturity_models(id) ON DELETE CASCADE,
level_number INT NOT NULL CHECK (level_number >= 1),
name VARCHAR(100) NOT NULL,
description TEXT,
sort_order INT NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
UNIQUE(maturity_model_id, level_number)
);
-- ============================================================================
-- MODEL SKILLS: Welche Fähigkeiten sind im Modell geführt (Matrix-Zeilen)
-- ============================================================================
CREATE TABLE IF NOT EXISTS model_skills (
id SERIAL PRIMARY KEY,
maturity_model_id INT NOT NULL REFERENCES maturity_models(id) ON DELETE CASCADE,
skill_id INT NOT NULL REFERENCES skills(id) ON DELETE CASCADE,
sort_order INT NOT NULL DEFAULT 0,
relevance VARCHAR(50),
created_at TIMESTAMP DEFAULT NOW(),
UNIQUE(maturity_model_id, skill_id)
);
CREATE INDEX IF NOT EXISTS idx_model_skills_model ON model_skills(maturity_model_id);
CREATE INDEX IF NOT EXISTS idx_model_skills_skill ON model_skills(skill_id);
-- ============================================================================
-- MODEL SKILL LEVELS (Zelltexte der Matrix)
-- ============================================================================
CREATE TABLE IF NOT EXISTS model_skill_levels (
id SERIAL PRIMARY KEY,
maturity_model_id INT NOT NULL REFERENCES maturity_models(id) ON DELETE CASCADE,
skill_id INT NOT NULL REFERENCES skills(id) ON DELETE CASCADE,
level_number INT NOT NULL CHECK (level_number >= 1),
description TEXT NOT NULL,
observable_criteria TEXT,
example_exercise_hints JSONB,
ai_generated BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
UNIQUE(maturity_model_id, skill_id, level_number)
);
-- ============================================================================
-- SKILLS: optionale Matrix-Felder (Spec)
-- ============================================================================
ALTER TABLE skills
ADD COLUMN IF NOT EXISTS primary_focus_area_id INT REFERENCES focus_areas(id) ON DELETE SET NULL;
ALTER TABLE skills
ADD COLUMN IF NOT EXISTS is_cross_domain BOOLEAN DEFAULT false;
-- ============================================================================
-- INDEXES
-- ============================================================================
CREATE INDEX IF NOT EXISTS idx_maturity_models_focus ON maturity_models(focus_area_id);
CREATE INDEX IF NOT EXISTS idx_maturity_models_style ON maturity_models(style_direction_id);
CREATE INDEX IF NOT EXISTS idx_maturity_models_target ON maturity_models(target_group_id);
CREATE INDEX IF NOT EXISTS idx_maturity_models_status ON maturity_models(status);
CREATE INDEX IF NOT EXISTS idx_model_levels_model ON model_levels(maturity_model_id);
CREATE INDEX IF NOT EXISTS idx_model_skill_levels_model ON model_skill_levels(maturity_model_id);
CREATE INDEX IF NOT EXISTS idx_model_skill_levels_skill ON model_skill_levels(skill_id);
CREATE INDEX IF NOT EXISTS idx_skills_primary_focus ON skills(primary_focus_area_id);
-- ============================================================================
-- TRIGGERS updated_at
-- ============================================================================
DROP TRIGGER IF EXISTS maturity_models_update ON maturity_models;
CREATE TRIGGER maturity_models_update
BEFORE UPDATE ON maturity_models
FOR EACH ROW EXECUTE FUNCTION update_timestamp();
DROP TRIGGER IF EXISTS model_skill_levels_update ON model_skill_levels;
CREATE TRIGGER model_skill_levels_update
BEFORE UPDATE ON model_skill_levels
FOR EACH ROW EXECUTE FUNCTION update_timestamp();