-- ============================================================ -- 032: gsc.tgs_acdnt_info → wing.ACDNT 동기화 (2026-04-10 이후) -- ------------------------------------------------------------ -- 목적 -- 3개 예측 탭(유출유확산예측 / HNS 대기확산 / 긴급구난)의 사고 -- 선택 셀렉트박스에 노출되는 gsc 사고 레코드를 wing.ACDNT에 -- 이관하여 wing 운영 로직과 동일한 사고 마스터를 공유한다. -- -- 필터 정책 (backend/src/gsc/gscAccidentsService.ts 의 listGscAccidents 와 동일) -- - acdnt_asort_code IN (12개 코드) -- - acdnt_title IS NOT NULL -- - 좌표(tgs_acdnt_lc.la, lo) 존재 -- - rcept_dt >= '2026-04-10' (본 이관 추가 조건) -- -- ACDNT_CD 생성 규칙 -- 'INC-YYYY-NNNN' (YYYY = rcept_dt 의 연도, NNNN = 해당 연도 내 순번 4자리) -- 기존 wing.ACDNT 에 이미 부여된 'INC-YYYY-NNNN' 중 같은 연도의 최대 순번을 -- 구해 이어서 증가시킨다. -- -- 중복 방지 -- (ACDNT_NM = acdnt_title, OCCRN_DTM = rcept_dt) 조합이 이미 존재하면 제외. -- acdnt_mng_no 를 별도 컬럼으로 보관하지 않으므로 이 조합을 자연 키로 사용. -- -- ACDNT_TP_CD -- gsc.tcm_code.code_nm 으로 치환 (JOIN: tcm_code.code = acdnt_asort_code) -- 매핑 누락 시 원본 코드값으로 폴백. -- -- 사전 확인 쿼리 (실행 전 참고) -- SELECT COUNT(DISTINCT a.acdnt_mng_no) -- FROM gsc.tgs_acdnt_info a JOIN gsc.tgs_acdnt_lc b USING (acdnt_mng_no) -- WHERE a.acdnt_asort_code = ANY(ARRAY[ -- '055001001','055001002','055001003','055001004','055001005','055001006', -- '055003001','055003002','055003003','055003004','055003005','055004003' -- ]::varchar[]) -- AND a.acdnt_title IS NOT NULL -- AND a.rcept_dt >= '2026-04-10'; -- ============================================================ WITH src AS ( SELECT DISTINCT ON (a.acdnt_mng_no) a.acdnt_mng_no, a.acdnt_title, a.acdnt_asort_code, a.rcept_dt, b.la, b.lo FROM gsc.tgs_acdnt_info AS a JOIN gsc.tgs_acdnt_lc AS b ON a.acdnt_mng_no = b.acdnt_mng_no WHERE a.acdnt_asort_code = ANY(ARRAY[ '055001001','055001002','055001003','055001004','055001005','055001006', '055003001','055003002','055003003','055003004','055003005','055004003' ]::varchar[]) AND a.acdnt_title IS NOT NULL AND a.rcept_dt >= '2026-04-10'::timestamptz AND b.la IS NOT NULL AND b.lo IS NOT NULL AND NOT EXISTS ( SELECT 1 FROM wing.ACDNT w WHERE w.ACDNT_NM = a.acdnt_title AND w.OCCRN_DTM = a.rcept_dt ) ORDER BY a.acdnt_mng_no, b.acdnt_lc_sn ASC ), numbered AS ( SELECT src.*, EXTRACT(YEAR FROM src.rcept_dt)::int AS yr, ROW_NUMBER() OVER ( PARTITION BY EXTRACT(YEAR FROM src.rcept_dt) ORDER BY src.rcept_dt ASC, src.acdnt_mng_no ASC ) AS rn_in_year FROM src ), year_max AS ( SELECT (split_part(ACDNT_CD, '-', 2))::int AS yr, MAX((split_part(ACDNT_CD, '-', 3))::int) AS max_seq FROM wing.ACDNT WHERE ACDNT_CD ~ '^INC-[0-9]{4}-[0-9]+$' GROUP BY split_part(ACDNT_CD, '-', 2) ) INSERT INTO wing.ACDNT ( ACDNT_CD, ACDNT_NM, ACDNT_TP_CD, ACDNT_STTS_CD, LAT, LNG, LOC_GEOM, LOC_DC, OCCRN_DTM, REG_DTM, MDFCN_DTM ) SELECT 'INC-' || lpad(n.yr::text, 4, '0') || '-' || lpad((COALESCE(ym.max_seq, 0) + n.rn_in_year)::text, 4, '0') AS ACDNT_CD, n.acdnt_title AS ACDNT_NM, COALESCE(c.code_nm, n.acdnt_asort_code) AS ACDNT_TP_CD, 'ACTIVE' AS ACDNT_STTS_CD, n.la::numeric AS LAT, n.lo::numeric AS LNG, ST_SetSRID(ST_MakePoint(n.lo::float8, n.la::float8), 4326) AS LOC_GEOM, NULL AS LOC_DC, n.rcept_dt AS OCCRN_DTM, NOW(), NOW() FROM numbered n LEFT JOIN year_max ym ON ym.yr = n.yr LEFT JOIN gsc.tcm_code c ON c.code = n.acdnt_asort_code ORDER BY n.rcept_dt ASC, n.acdnt_mng_no ASC; -- ============================================================ -- 사후 검증 (필요 시 주석 해제 실행) -- SELECT COUNT(*) FROM wing.ACDNT WHERE OCCRN_DTM >= '2026-04-10'; -- -- SELECT ACDNT_CD, ACDNT_NM, ACDNT_TP_CD, ST_AsText(LOC_GEOM), OCCRN_DTM -- FROM wing.ACDNT -- WHERE OCCRN_DTM >= '2026-04-10' -- ORDER BY ACDNT_CD DESC -- LIMIT 20; -- -- SELECT ACDNT_TP_CD, COUNT(*) -- FROM wing.ACDNT -- WHERE OCCRN_DTM >= '2026-04-10' -- GROUP BY 1 -- ORDER BY 2 DESC; -- ============================================================