@@ -60,7 +60,7 @@ CREATE TABLE IF NOT EXISTS users (
6060 usr_username VARCHAR (32 ) NOT NULL UNIQUE,
6161 usr_email VARCHAR (64 ) NOT NULL UNIQUE,
6262 usr_password VARCHAR (255 ) NOT NULL ,
63- usr_name VARCHAR (32 ),
63+ usr_name VARCHAR (64 ),
6464 usr_phone VARCHAR (10 ),
6565 usr_profile VARCHAR (255 ),
6666
@@ -96,7 +96,7 @@ CREATE TABLE IF NOT EXISTS events (
9696 evt_id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY ,
9797
9898 evt_icon VARCHAR (32 ) NOT NULL ,
99- evt_name VARCHAR (32 ) UNIQUE NOT NULL ,
99+ evt_name VARCHAR (32 ) NOT NULL ,
100100 evt_description TEXT ,
101101
102102 evt_created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
@@ -264,7 +264,8 @@ CREATE TABLE notification_thresholds (
264264 nth_critical BOOLEAN DEFAULT FALSE,
265265 nth_high BOOLEAN DEFAULT FALSE,
266266 nth_medium BOOLEAN DEFAULT FALSE,
267- nth_low BOOLEAN DEFAULT FALSE
267+ nth_low BOOLEAN DEFAULT FALSE,
268+ nth_status BOOLEAN DEFAULT TRUE
268269);
269270
270271CREATE TABLE event_priority (
@@ -293,7 +294,7 @@ CREATE TABLE notification_recipients (
293294CREATE TABLE IF NOT EXISTS reports (
294295 rpt_id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY ,
295296
296- rpt_name VARCHAR (32 ) NOT NULL ,
297+ rpt_name VARCHAR (64 ) NOT NULL ,
297298 rpt_template VARCHAR (16 ) NOT NULL DEFAULT ' general' CHECK (rpt_template IN (' general' , ' alert' , ' performance' )),
298299 rpt_type VARCHAR (16 ) NOT NULL DEFAULT ' pdf' CHECK (rpt_type IN (' pdf' )),
299300 rpt_range_start DATE NOT NULL ,
@@ -574,45 +575,93 @@ CREATE INDEX IF NOT EXISTS idx_rln_recipient_created_desc
574575-- -------------------------------[ Notification Emails ]--------------------------------
575576CREATE OR REPLACE VIEW v_notification_emails AS
576577SELECT
577- r .rcp_id ,
578- COALESCE(u .usr_email , r .rcp_email ) AS email,
579- COALESCE(u .usr_name , u .usr_username , NULL ) AS display_name,
580- (u .usr_id IS NOT NULL
581- OR EXISTS (SELECT 1 FROM users ux WHERE ux .usr_email = r .rcp_email )
582- ) AS is_internal,
583- rl .rln_entity ,
584- rl .rln_entity_id ,
585- r .rcp_created_at
578+ -- Link Info
579+ rl .rln_id AS link_id,
580+ rl .rln_entity AS entity,
581+ rl .rln_entity_id AS entity_id,
582+
583+ -- Recipient Info
584+ r .rcp_id AS recipient_id,
585+
586+ -- User Info (internal)
587+ u .usr_id AS user_id,
588+ u .usr_username AS username,
589+ u .usr_profile AS profile,
590+
591+ -- Email + Display
592+ COALESCE(u .usr_email , r .rcp_email ) AS email,
593+ COALESCE(u .usr_name , u .usr_username , NULL ) AS display_name,
594+
595+ -- Internal Flag
596+ (
597+ u .usr_id IS NOT NULL
598+ OR EXISTS (
599+ SELECT 1
600+ FROM users ux
601+ WHERE ux .usr_email = r .rcp_email
602+ )
603+ ) AS is_internal,
604+
605+ -- Timestamp TH
606+ TO_CHAR(
607+ r .rcp_created_at AT TIME ZONE ' Asia/Bangkok' ,
608+ ' YYYY-MM-DD HH24:MI:SS'
609+ ) AS created_at_th
610+
586611FROM recipient_links rl
587- JOIN recipients r ON r .rcp_id = rl .rln_rcp_id
588- LEFT JOIN users u ON u .usr_id = r .rcp_usr_id
612+ JOIN recipients r ON r .rcp_id = rl .rln_rcp_id
613+ LEFT JOIN users u ON u .usr_id = r .rcp_usr_id
589614WHERE rl .rln_entity <> ' scheduled_report'
590615ORDER BY r .rcp_created_at DESC ;
591616
592617-- -------------------------------[ Scheduled Report Emails ]--------------------------------
593618CREATE OR REPLACE VIEW v_scheduled_report_emails AS
594619SELECT
595- r .rcp_id ,
596- COALESCE(u .usr_email , r .rcp_email ) AS email,
597- COALESCE(u .usr_name , u .usr_username , NULL ) AS display_name,
598- (u .usr_id IS NOT NULL
599- OR EXISTS (SELECT 1 FROM users ux WHERE ux .usr_email = r .rcp_email )
600- ) AS is_internal,
601-
602- -- บอกว่าเป็นของ schedule ไหน / report ไหน
603- scr .scr_id AS schedule_id,
604- rpt .rpt_id AS report_id,
605- rpt .rpt_name AS report_name,
606-
607- -- เผื่ออยากดู metadata เพิ่มเติม
620+ -- Link Info
621+ rl .rln_id AS link_id,
622+ rl .rln_entity AS entity,
623+ rl .rln_entity_id AS entity_id,
624+
625+ -- Recipient Info
626+ r .rcp_id AS recipient_id,
627+
628+ -- User Info (internal)
629+ u .usr_id AS user_id,
630+ u .usr_username AS username,
631+ u .usr_profile AS profile,
632+
633+ -- Email + Display
634+ COALESCE(u .usr_email , r .rcp_email ) AS email,
635+ COALESCE(u .usr_name , u .usr_username , NULL ) AS display_name,
636+
637+ -- Internal Flag
638+ (
639+ u .usr_id IS NOT NULL
640+ OR EXISTS (
641+ SELECT 1
642+ FROM users ux
643+ WHERE ux .usr_email = r .rcp_email
644+ )
645+ ) AS is_internal,
646+
647+ -- Schedule Info
648+ scr .scr_id AS schedule_id,
649+ rpt .rpt_id AS report_id,
650+ rpt .rpt_name AS report_name,
608651 scr .scr_frequency ,
609652 scr .scr_time ,
610- r .rcp_created_at
653+
654+ -- Timestamp TH
655+ TO_CHAR(
656+ r .rcp_created_at AT TIME ZONE ' Asia/Bangkok' ,
657+ ' YYYY-MM-DD HH24:MI:SS'
658+ ) AS created_at_th
659+
611660FROM recipient_links rl
612- JOIN recipients r ON r .rcp_id = rl .rln_rcp_id
613- LEFT JOIN users u ON u .usr_id = r .rcp_usr_id
661+ JOIN recipients r ON r .rcp_id = rl .rln_rcp_id
662+ LEFT JOIN users u ON u .usr_id = r .rcp_usr_id
614663JOIN scheduled_reports scr ON scr .scr_id = rl .rln_entity_id
615- JOIN reports rpt ON rpt .rpt_id = scr .scr_rpt_id
664+ JOIN reports rpt ON rpt .rpt_id = scr .scr_rpt_id
616665WHERE rl .rln_entity = ' scheduled_report'
617666ORDER BY r .rcp_created_at DESC ;
618667
@@ -715,6 +764,7 @@ CREATE OR REPLACE VIEW v_events_in_cameras AS
715764SELECT
716765 e .evt_id AS event_id,
717766 e .evt_name AS event_name,
767+ e .evt_icon AS event_icon,
718768 c .cam_id AS camera_id,
719769 c .cam_name AS camera_name,
720770 l .loc_name AS location_name,
@@ -1030,8 +1080,12 @@ CREATE TRIGGER trg_events_after_insert_fill_priority
10301080AFTER INSERT ON events
10311081FOR EACH ROW EXECUTE FUNCTION trg_after_events_insert_fill_priority();
10321082
1083+ ALTER TABLE recipient_links
1084+ ADD CONSTRAINT uq_alert_unique_link
1085+ UNIQUE (rln_rcp_id, rln_entity, rln_entity_id);
1086+
10331087/* ============================================================
1034- ========= ===========
1088+ ========= FUNCTIONS ===========
10351089 ============================================================ */
10361090
10371091
@@ -1070,6 +1124,64 @@ FOR EACH ROW
10701124WHEN (OLD .evt_is_use IS DISTINCT FROM NEW .evt_is_use )
10711125EXECUTE FUNCTION aods_dev_v3 .fn_sync_cds_is_use ();
10721126
1127+ -- เพิ่ม recipient + link (คืนค่า rln_id และ rcp_id)
1128+ CREATE OR REPLACE FUNCTION aods_dev_v3 .fn_add_recipient_link(
1129+ p_email TEXT ,
1130+ p_usr_id INT ,
1131+ p_entity TEXT ,
1132+ p_entity_id INT
1133+ ) RETURNS TABLE(rln_id INT , rcp_id INT ) LANGUAGE plpgsql AS $$
1134+ DECLARE
1135+ v_rcp_id INT ;
1136+ BEGIN
1137+ -- หา recipient ที่มี usr_id หรือ email ตรงกันก่อน
1138+ IF p_usr_id IS NOT NULL THEN
1139+ SELECT rcp_id INTO v_rcp_id FROM aods_dev_v3 .recipients WHERE rcp_usr_id = p_usr_id LIMIT 1 ;
1140+ END IF;
1141+
1142+ IF v_rcp_id IS NULL AND p_email IS NOT NULL THEN
1143+ SELECT rcp_id INTO v_rcp_id FROM aods_dev_v3 .recipients WHERE rcp_email = p_email LIMIT 1 ;
1144+ END IF;
1145+
1146+ -- ถ้ายังไม่มี สร้าง
1147+ IF v_rcp_id IS NULL THEN
1148+ INSERT INTO aods_dev_v3 .recipients (rcp_usr_id, rcp_email)
1149+ VALUES (p_usr_id, p_email)
1150+ RETURNING rcp_id INTO v_rcp_id;
1151+ END IF;
1152+
1153+ -- สร้าง link (ป้องกัน duplicate ถ้าต้องการ)
1154+ INSERT INTO aods_dev_v3 .recipient_links (rln_rcp_id, rln_entity, rln_entity_id)
1155+ VALUES (v_rcp_id, p_entity, p_entity_id)
1156+ RETURNING rln_id INTO rln_id;
1157+
1158+ rcp_id := v_rcp_id;
1159+ RETURN NEXT;
1160+ END;
1161+ $$;
1162+
1163+ -- ลบ link (ตาม rln_id) และ cleanup recipients ที่ไม่ถูกอ้างอิง
1164+ CREATE OR REPLACE FUNCTION aods_dev_v3 .fn_remove_recipient_link(p_rln_id INT )
1165+ RETURNS VOID LANGUAGE plpgsql AS $$
1166+ DECLARE
1167+ v_rcp_id INT ;
1168+ v_count INT ;
1169+ BEGIN
1170+ SELECT rln_rcp_id INTO v_rcp_id FROM aods_dev_v3 .recipient_links WHERE rln_id = p_rln_id;
1171+ IF v_rcp_id IS NULL THEN
1172+ RAISE EXCEPTION ' recipient link % not found' , p_rln_id;
1173+ END IF;
1174+
1175+ DELETE FROM aods_dev_v3 .recipient_links WHERE rln_id = p_rln_id;
1176+
1177+ -- ถ้า recipient ไม่มี link ใดๆ เลย ให้ลบ (cleanup)
1178+ SELECT COUNT (* ) INTO v_count FROM aods_dev_v3 .recipient_links WHERE rln_rcp_id = v_rcp_id;
1179+ IF v_count = 0 THEN
1180+ DELETE FROM aods_dev_v3 .recipients WHERE rcp_id = v_rcp_id;
1181+ END IF;
1182+ END;
1183+ $$;
1184+
10731185-- ============================================================
10741186-- INSERT BASE DATA
10751187-- ============================================================
@@ -1175,3 +1287,7 @@ INSERT INTO maintenance_history (
11751287 (8 , ' 2025-10-17' , ' repair' , ' Technician H' , ' เปลี่ยน adapter กล้อง Server Room Cam 02' ),
11761288 (9 , ' 2025-10-18' , ' routine check' , ' Technician I' , ' ตรวจเช็คเลนส์และโฟกัสกล้อง Warehouse Exit Cam 01' ),
11771289 (10 ,' 2025-10-19' , ' installation' , ' Technician J' , ' ติดตั้งกล้อง Warehouse Exit Cam 02 ใหม่หลังซ่อมบำรุง' );
1290+
1291+ INSERT INTO alert_escalation(
1292+ aes_severity)
1293+ VALUES (' critical' ), (' high' ),(' medium' ),(' low' );
0 commit comments