-- Migration 037: Persönliche Referenzwerte (Typkatalog + historische Werte pro Profil) -- Date: 2026-04-06 -- Purpose: System-definierte Referenztyp-Schlüssel; Nutzer pflegt nur historische Einträge. CREATE TABLE IF NOT EXISTS reference_value_types ( id SERIAL PRIMARY KEY, key VARCHAR(64) NOT NULL UNIQUE, label VARCHAR(200) NOT NULL, description TEXT, default_unit VARCHAR(32), sort_order INT NOT NULL DEFAULT 0, active BOOLEAN NOT NULL DEFAULT TRUE, metadata JSONB NOT NULL DEFAULT '{}', created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW() ); COMMENT ON TABLE reference_value_types IS 'Systemdefinierte Typen persönlicher Referenzwerte (kein Nutzer-CRUD auf Typen)'; CREATE TABLE IF NOT EXISTS profile_reference_values ( id BIGSERIAL PRIMARY KEY, profile_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE, reference_value_type_id INT NOT NULL REFERENCES reference_value_types(id) ON DELETE RESTRICT, effective_date DATE NOT NULL, value_numeric NUMERIC(18, 6), value_text TEXT, unit VARCHAR(32) NOT NULL, source TEXT, confidence NUMERIC(5, 2), method TEXT, notes TEXT, extra JSONB NOT NULL DEFAULT '{}', created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), CONSTRAINT profile_reference_values_value_ck CHECK ( value_numeric IS NOT NULL OR (value_text IS NOT NULL AND length(trim(value_text)) > 0) ) ); COMMENT ON TABLE profile_reference_values IS 'Historische Referenzwerte pro Profil (kein Überschreiben eines Einzel-»aktuellen« Werts)'; CREATE INDEX IF NOT EXISTS idx_prv_profile_type_date ON profile_reference_values (profile_id, reference_value_type_id, effective_date DESC); CREATE INDEX IF NOT EXISTS idx_prv_profile ON profile_reference_values (profile_id); -- Seed: nur Typdefinitionen, keine Benutzerwerte INSERT INTO reference_value_types (key, label, description, default_unit, sort_order, active) VALUES ( 'max_heart_rate', 'Maximale Herzfrequenz', 'Individuelle HRmax (z. B. aus Leistungstest oder geschätzt).', 'bpm', 10, TRUE ), ( 'anaerobic_threshold_hr', 'Anaerober Schwellenwert (Herzfrequenz)', 'Laktatschwelle / anaerober Schwellenpuls.', 'bpm', 20, TRUE ), ( 'aerobic_threshold_hr', 'Aerober Schwellenwert (Herzfrequenz)', 'Erster aerobet/schwellenanaloger Trainingsbereich (GA2).', 'bpm', 30, TRUE ), ( 'training_frequency_weekly', 'Trainingshäufigkeit', 'Geplante oder beobachtete Einheiten pro Woche.', 'Sessions/Woche', 40, TRUE ), ( 'fitness_level', 'Fitnesslevel', 'Subjektive oder normierte Einstufung (Zahl oder Kurzbeschreibung im Freitextfeld).', 'Stufe', 50, TRUE ), ( 'resting_heart_rate', 'Ruhepuls (Referenz)', 'Ruheherzfrequenz als persönliche Referenz (z. B. morgens).', 'bpm', 15, TRUE ) ON CONFLICT (key) DO NOTHING;