drop schema "public" show search_path; set schema "ptmain"; CREATE SCHEMA if not exists ptmain; GRANT USAGE, CREATE ON SCHEMA ptmain TO sathumper; GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA ptmain TO sathumper; GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA ptmain TO sathumper; ALTER DEFAULT PRIVILEGES IN SCHEMA ptmain GRANT ALL PRIVILEGES ON TABLES TO sathumper; -- Create schema if not exists insert into -- Create main configuration table CREATE TABLE app_configuration ( id BIGSERIAL PRIMARY KEY, key VARCHAR(255) NOT NULL, value TEXT NOT NULL, label VARCHAR(255), content_type VARCHAR(255) DEFAULT 'text/plain', valid_from TIMESTAMPTZ, expires_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, modified_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, etag UUID DEFAULT gen_random_uuid(), CONSTRAINT app_configuration_key_unique UNIQUE (key, valid_from) ); -- Create history table CREATE TABLE app_configuration_history ( history_id BIGSERIAL PRIMARY KEY, operation CHAR(1) NOT NULL, -- I = Insert, U = Update, D = Delete changed_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, changed_by TEXT NOT NULL DEFAULT CURRENT_USER, -- Original columns id BIGINT NOT NULL, key VARCHAR(255) NOT NULL, value TEXT NOT NULL, label VARCHAR(255), content_type VARCHAR(255), valid_from TIMESTAMPTZ, expires_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL, modified_at TIMESTAMPTZ NOT NULL, etag UUID ); -- Create function for updating modified_at CREATE OR REPLACE FUNCTION update_modified_at() RETURNS TRIGGER AS $$ BEGIN NEW.modified_at = CURRENT_TIMESTAMP; RETURN NEW; END; $$ LANGUAGE plpgsql; -- Create history tracking function CREATE OR REPLACE FUNCTION track_configuration_history() RETURNS TRIGGER AS $$ BEGIN -- Indsæt historikpost baseret på operationstypen IF TG_OP = 'INSERT' THEN INSERT INTO app_configuration_history( operation, id, key, value, label, content_type, valid_from, expires_at, created_at, modified_at, etag ) VALUES ( 'I', NEW.id, NEW.key, NEW.value, NEW.label, NEW.content_type, NEW.valid_from, NEW.expires_at, NEW.created_at, NEW.modified_at, NEW.etag ); ELSIF TG_OP = 'UPDATE' OR TG_OP = 'DELETE' THEN -- Brug OLD for både UPDATE og DELETE INSERT INTO app_configuration_history( operation, id, key, value, label, content_type, valid_from, expires_at, created_at, modified_at, etag ) VALUES ( CASE WHEN TG_OP = 'UPDATE' THEN 'U' WHEN TG_OP = 'DELETE' THEN 'D' END, OLD.id, OLD.key, OLD.value, OLD.label, OLD.content_type, OLD.valid_from, OLD.expires_at, OLD.created_at, OLD.modified_at, OLD.etag ); END IF; -- Returner NULL for AFTER-trigger RETURN NULL; EXCEPTION WHEN others THEN -- Log fejl og rejs undtagelse RAISE EXCEPTION 'Fejl i track_configuration_history: %', SQLERRM; END; $$ LANGUAGE plpgsql; -- Create triggers CREATE TRIGGER trg_app_configuration_modified_at BEFORE UPDATE ON app_configuration FOR EACH ROW EXECUTE FUNCTION update_modified_at(); CREATE TRIGGER trg_app_configuration_history AFTER INSERT OR UPDATE OR DELETE ON app_configuration FOR EACH ROW EXECUTE FUNCTION track_configuration_history(); CREATE TRIGGER trg_app_configuration_notify AFTER INSERT OR UPDATE ON app_configuration FOR EACH ROW EXECUTE FUNCTION notify_config_change(); -- Comments COMMENT ON TABLE app_configuration IS 'Application configuration with temporal validity'; COMMENT ON TABLE app_configuration_history IS 'Historical changes to application configuration'; COMMENT ON COLUMN app_configuration_history.operation IS 'Type of operation: I=Insert, U=Update, D=Delete'; COMMENT ON COLUMN app_configuration_history.changed_at IS 'When the change occurred'; COMMENT ON COLUMN app_configuration_history.changed_by IS 'User who made the change'; ```sql -- Email templates configuration INSERT INTO app_configuration (key, value, label, content_type, valid_from, expires_at) VALUES ('Email:Templates:Welcome', '{"subject":"Velkommen til vores platform","template":"welcome-dk.html","sender":"velkommen@firma.dk"}', 'Email Templates', 'application/json', '2024-01-01T00:00:00Z', NULL); select * from app_configuration_history update app_configuration set label = 'test' INSERT INTO app_configuration (key, value, label, content_type, valid_from, expires_at) VALUES ('Email:Templates:Password', '{"subject":"Nulstil dit kodeord","template":"reset-password-dk.html","sender":"support@firma.dk"}', 'Email Templates', 'application/json', '2024-01-01T00:00:00Z', NULL); -- API configuration INSERT INTO app_configuration (key, value, label, content_type, valid_from, expires_at) VALUES ('Api:Endpoints:BaseUrl', '{"production":"https://api.firma.dk","staging":"https://staging-api.firma.dk"}', 'API Settings', 'application/json', '2024-01-01T00:00:00Z', NULL); -- Feature flags INSERT INTO app_configuration (key, value, label, content_type, valid_from, expires_at) VALUES ('Features:NewUI', '{"enabled":false,"rolloutPercentage":0,"description":"New React based UI"}', 'Feature Flags', 'application/json', '2024-02-01T00:00:00Z', '2024-12-31T23:59:59Z'); -- System settings INSERT INTO app_configuration (key, value, label, content_type, valid_from, expires_at) VALUES ('System:Cache', '{"timeoutMinutes":15,"maxItems":1000,"distributed":true}', 'System Settings', 'application/json', '2024-01-01T00:00:00Z', NULL); ```