fix repeatable migrations
This commit is contained in:
168
db/routines/R__044_fn_set_mode.sql
Normal file
168
db/routines/R__044_fn_set_mode.sql
Normal file
@@ -0,0 +1,168 @@
|
||||
-- =============================================================
|
||||
-- R__044_fn_set_mode.sql
|
||||
-- EMS Platform – přepínání provozních režimů
|
||||
-- Repeatable migration
|
||||
-- =============================================================
|
||||
|
||||
CREATE OR REPLACE FUNCTION ems.fn_set_mode(
|
||||
p_site_id INT,
|
||||
p_mode_code TEXT,
|
||||
p_activated_by TEXT DEFAULT 'system',
|
||||
p_valid_until TIMESTAMPTZ DEFAULT NULL,
|
||||
p_notes TEXT DEFAULT NULL
|
||||
)
|
||||
RETURNS TEXT
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
v_current_mode TEXT;
|
||||
v_mode_exists BOOLEAN;
|
||||
BEGIN
|
||||
-- Ověřit že režim existuje
|
||||
SELECT EXISTS(SELECT 1 FROM ems.operating_mode_def WHERE code = p_mode_code)
|
||||
INTO v_mode_exists;
|
||||
|
||||
IF NOT v_mode_exists THEN
|
||||
RAISE EXCEPTION 'Neznámý provozní režim: %', p_mode_code;
|
||||
END IF;
|
||||
|
||||
-- Zjistit aktuální režim (pro log a previous_mode)
|
||||
SELECT mode_code INTO v_current_mode
|
||||
FROM ems.site_operating_mode
|
||||
WHERE site_id = p_site_id;
|
||||
|
||||
-- Pokud se režim nemění, nic nedělat
|
||||
IF v_current_mode = p_mode_code THEN
|
||||
RETURN p_mode_code;
|
||||
END IF;
|
||||
|
||||
-- Uzavřít předchozí záznam v logu
|
||||
UPDATE ems.site_operating_mode_log
|
||||
SET deactivated_at = now()
|
||||
WHERE site_id = p_site_id
|
||||
AND deactivated_at IS NULL;
|
||||
|
||||
-- Upsert aktivního režimu
|
||||
INSERT INTO ems.site_operating_mode
|
||||
(site_id, mode_code, activated_at, activated_by, valid_until, previous_mode, notes)
|
||||
VALUES
|
||||
(p_site_id, p_mode_code, now(), p_activated_by, p_valid_until, v_current_mode, p_notes)
|
||||
ON CONFLICT (site_id) DO UPDATE SET
|
||||
mode_code = EXCLUDED.mode_code,
|
||||
activated_at = EXCLUDED.activated_at,
|
||||
activated_by = EXCLUDED.activated_by,
|
||||
valid_until = EXCLUDED.valid_until,
|
||||
previous_mode = EXCLUDED.previous_mode,
|
||||
notes = EXCLUDED.notes;
|
||||
|
||||
-- Přidat záznam do logu
|
||||
INSERT INTO ems.site_operating_mode_log
|
||||
(site_id, mode_code, activated_at, activated_by, notes)
|
||||
VALUES
|
||||
(p_site_id, p_mode_code, now(), p_activated_by, p_notes);
|
||||
|
||||
RETURN p_mode_code;
|
||||
END;
|
||||
$$;
|
||||
|
||||
COMMENT ON FUNCTION ems.fn_set_mode(INT, TEXT, TEXT, TIMESTAMPTZ, TEXT) IS
|
||||
'Přepne provozní režim lokality. Atomicky aktualizuje site_operating_mode a zapíše do audit logu.
|
||||
Ignoruje přepnutí na stejný režim. Vyhodí výjimku pro neznámý kód režimu.
|
||||
Příklad: SELECT ems.fn_set_mode(1, ''SELF_SUSTAIN'', ''user:jan'', NULL, ''Odjezd na dovolenou'');';
|
||||
|
||||
-- ============================================================
|
||||
|
||||
CREATE OR REPLACE FUNCTION ems.fn_restore_previous_mode(
|
||||
p_site_id INT,
|
||||
p_activated_by TEXT DEFAULT 'system'
|
||||
)
|
||||
RETURNS TEXT
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
v_previous TEXT;
|
||||
BEGIN
|
||||
SELECT previous_mode INTO v_previous
|
||||
FROM ems.site_operating_mode
|
||||
WHERE site_id = p_site_id;
|
||||
|
||||
IF v_previous IS NULL THEN
|
||||
-- Fallback na AUTO pokud není předchozí režim
|
||||
v_previous := 'AUTO';
|
||||
END IF;
|
||||
|
||||
RETURN ems.fn_set_mode(p_site_id, v_previous, p_activated_by, NULL, 'Obnova předchozího režimu');
|
||||
END;
|
||||
$$;
|
||||
|
||||
COMMENT ON FUNCTION ems.fn_restore_previous_mode(INT, TEXT) IS
|
||||
'Přepne lokalitu zpět na předchozí provozní režim (uložený v previous_mode).
|
||||
Pokud předchozí režim neexistuje, přepne na AUTO. Používat po skončení dočasného přepisu.';
|
||||
|
||||
-- ============================================================
|
||||
|
||||
drop function if exists ems.fn_expire_modes();
|
||||
|
||||
CREATE OR REPLACE FUNCTION ems.fn_expire_modes()
|
||||
RETURNS TABLE(site_id INT, site_code TEXT, old_mode TEXT, new_mode TEXT)
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
v_rec RECORD;
|
||||
v_new_mode TEXT;
|
||||
BEGIN
|
||||
FOR v_rec IN
|
||||
SELECT som.site_id,
|
||||
s.code AS site_code,
|
||||
som.mode_code AS old_mode,
|
||||
som.previous_mode
|
||||
FROM ems.site_operating_mode som
|
||||
JOIN ems.site s ON s.id = som.site_id
|
||||
WHERE som.valid_until IS NOT NULL
|
||||
AND som.valid_until <= now()
|
||||
AND som.mode_code <> 'AUTO'
|
||||
LOOP
|
||||
v_new_mode := COALESCE(v_rec.previous_mode, 'AUTO');
|
||||
PERFORM ems.fn_set_mode(
|
||||
v_rec.site_id,
|
||||
v_new_mode,
|
||||
'system:expiry',
|
||||
NULL,
|
||||
'Automatické vypršení dočasného režimu'
|
||||
);
|
||||
site_id := v_rec.site_id;
|
||||
site_code := v_rec.site_code;
|
||||
old_mode := v_rec.old_mode;
|
||||
new_mode := v_new_mode;
|
||||
RETURN NEXT;
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
COMMENT ON FUNCTION ems.fn_expire_modes() IS
|
||||
'Zkontroluje všechny lokality s dočasným režimem (valid_until IS NOT NULL) a přepne zpět ty s prosahlým časem.
|
||||
Volat každou minutu jako scheduled task. Vrátí řádky (site_id, site_code, old_mode, new_mode) pro každé provedené přepnutí — backend z toho pošle Discord notifikace.';
|
||||
|
||||
-- ============================================================
|
||||
|
||||
CREATE OR REPLACE FUNCTION ems.fn_update_heartbeat(
|
||||
p_site_id INT,
|
||||
p_status TEXT DEFAULT 'ok',
|
||||
p_ems_version TEXT DEFAULT NULL
|
||||
)
|
||||
RETURNS VOID
|
||||
LANGUAGE sql
|
||||
AS $$
|
||||
INSERT INTO ems.site_heartbeat (site_id, last_seen, status, ems_version)
|
||||
VALUES (p_site_id, now(), p_status, p_ems_version)
|
||||
ON CONFLICT (site_id) DO UPDATE SET
|
||||
last_seen = now(),
|
||||
status = EXCLUDED.status,
|
||||
ems_version = COALESCE(EXCLUDED.ems_version, ems.site_heartbeat.ems_version);
|
||||
$$;
|
||||
|
||||
COMMENT ON FUNCTION ems.fn_update_heartbeat(INT, TEXT, TEXT) IS
|
||||
'Aktualizuje informační heartbeat záznam EMS pro danou lokalitu.
|
||||
Volat každou minutu z backend service po úspěšném odeslání pulzu do Loxone.
|
||||
Slouží pouze pro EMS dashboard – Loxone watchdog nezávisí na této tabulce,
|
||||
sleduje HTTP pulzy přímo a nezávisle na dostupnosti DB.';
|
||||
Reference in New Issue
Block a user