refactor(db): DDL 스크립트 현행화 + wing_auth→auth 스키마 문서 전면 수정

- database/schema/ 14개 DDL 파일 신규 생성 (운영 DB pg_dump 기반)
- database/seed/ 14개 초기 데이터 파일 분리
- database/_deprecated/로 구 init.sql, auth_init.sql 이동
- database/README.md 신규 작성 (DB 아키텍처, 설치 절차)
- docs/ 6개 가이드 문서 wing_auth→auth 스키마 구조로 수정
- README.md, CLAUDE.md wing 단일 DB 구조 반영

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
htlee 2026-03-01 15:16:38 +09:00
부모 a2cfc02b70
커밋 13d6ca69e2
40개의 변경된 파일4048개의 추가작업 그리고 88개의 파일을 삭제

파일 보기

@ -5,7 +5,7 @@
- **타입**: react-ts 모노레포 (frontend + backend)
- **Frontend**: React 19 + Vite 7 + TypeScript 5.9 + Tailwind CSS 3
- **Backend**: Express 4 + PostgreSQL (pg) + TypeScript
- **DB**: PostgreSQL 16 + PostGIS (wing 운영DB + wing_auth 인증DB)
- **DB**: PostgreSQL 16 + PostGIS (wing 단일 DB: public, auth, wing 3개 스키마)
- **상태관리**: Zustand (클라이언트), TanStack Query (서버)
- **지도**: MapLibre GL JS 5.x + deck.gl 9.x (Leaflet 제거됨)
- **실시간**: Socket.IO
@ -86,8 +86,12 @@ wing/
│ ├── hns/ HNS 물질 검색 API
│ ├── routes/ 레이어, 시뮬레이션
│ ├── middleware/ 보안 (입력 살균, rate-limit, Helmet CORP cross-origin)
│ └── db/ DB 연결 (wingDb, authDb), seed
├── database/ SQL 스크립트 + 마이그레이션 (001~016)
│ └── db/ DB 연결 (wingDb), seed
├── database/ DB 스크립트
│ ├── schema/ ERD용 순수 DDL (14파일)
│ ├── seed/ 초기 데이터 (14파일)
│ ├── migration/ 증분 마이그레이션 (001~016)
│ └── _deprecated/ 구 스크립트 (통합 이전)
├── docs/ 개발 문서
├── .claude/ 팀 워크플로우 (rules, skills, scripts, agents)
└── .githooks/ Git hooks (pre-commit, commit-msg)

파일 보기

@ -120,8 +120,12 @@ wing/
│ ├── hns/ HNS 물질 검색 API
│ ├── routes/ 레이어, 시뮬레이션
│ ├── middleware/ 보안 (입력 살균, rate-limit)
│ └── db/ DB 연결 (wingDb, authDb), seed
├── database/ SQL 스크립트 + 마이그레이션 (001~016)
│ └── db/ DB 연결 (wingDb), seed
├── database/ DB 스크립트
│ ├── schema/ ERD용 순수 DDL (14파일)
│ ├── seed/ 초기 데이터 (14파일)
│ ├── migration/ 증분 마이그레이션 (001~016)
│ └── _deprecated/ 구 스크립트 (통합 이전)
├── docs/ 개발 문서
├── .claude/ 팀 워크플로우 (rules, skills, scripts, agents)
└── .githooks/ Git hooks (pre-commit, commit-msg)
@ -142,7 +146,7 @@ wing/
| Backend | Express 4, TypeScript, pg (PostgreSQL) |
| 보안 | Helmet, CORS, Rate-limit, Input sanitization |
| 인증 | JWT (HttpOnly Cookie `WING_SESSION`), bcrypt, Google OAuth |
| DB | PostgreSQL 16 + PostGIS (wing 운영DB + wing_auth 인증DB) |
| DB | PostgreSQL 16 + PostGIS (wing 단일 DB: public, auth, wing 3개 스키마) |
| CI/CD | Gitea Actions (.gitea/workflows/deploy.yml) |
---
@ -188,11 +192,11 @@ VITE_GOOGLE_CLIENT_ID=your-google-client-id
PORT=3001
NODE_ENV=development
JWT_SECRET=your-jwt-secret
AUTH_DB_HOST=localhost
AUTH_DB_PORT=5432
AUTH_DB_NAME=wing_auth
AUTH_DB_USER=wing_auth
AUTH_DB_PASSWORD=<비밀번호>
DB_HOST=211.208.115.83
DB_PORT=5432
DB_NAME=wing
DB_USER=wing
DB_PASSWORD=<비밀번호>
GOOGLE_CLIENT_ID=your-google-client-id
```

106
database/README.md Normal file
파일 보기

@ -0,0 +1,106 @@
# WING-OPS Database
## 아키텍처
wing 단일 DB에 3개 스키마로 구성. `search_path = wing, auth, public` 설정으로 스키마 접두사 없이 쿼리 가능.
```
wing (database)
├── public PostGIS 확장 (geometry, geography, spatial_ref_sys)
├── auth 인증/권한 (9 테이블)
└── wing 운영 데이터 (35+ 테이블)
```
| 스키마 | 역할 | 주요 테이블 |
|--------|------|-------------|
| public | PostGIS 공간 함수, pg_trgm, uuid-ossp | (확장 전용) |
| auth | 사용자 인증, 역할, 권한, 감사로그 | auth_user, auth_role, auth_perm, auth_perm_tree, auth_audit_log |
| wing | 사고, 확산예측, HNS, SCAT, 자산, 게시판, 보고서 | acdnt, pred_exec, hns_substance, cst_sect, asset_org, board_post, report |
## 초기 설치
```bash
# 1. DB 생성 + 사용자
createdb -U postgres wing
psql -U postgres -c "CREATE USER wing WITH PASSWORD 'Wing2026';"
psql -U postgres -c "GRANT ALL ON DATABASE wing TO wing;"
# 2. 스키마 DDL 실행 (순서대로)
for f in database/schema/0*.sql database/schema/1*.sql; do
psql -U wing -d wing -f "$f"
done
# 3. Seed 데이터 (SQL)
for f in database/seed/0[1-8]*.sql database/seed/1[1-4]*.sql; do
psql -U wing -d wing -f "$f"
done
# 4. Seed 데이터 (Node.js — layer 160건, HNS 1,316건)
cd backend && npm run db:seed
```
## 디렉토리 구조
```
database/
├── schema/ ERD용 순수 DDL (현행 운영 DB 기준)
│ ├── 00_extensions.sql 확장 + 스키마 생성
│ ├── 01_auth_tables.sql auth 스키마 (9 테이블)
│ ├── 02_common_tables.sql 공통코드, 레이어
│ ├── 03_org_user_tables.sql 조직, 사용자
│ ├── 04_accident_tables.sql 사고, 유출, 예측, 기상, 미디어
│ ├── 05_hns_tables.sql HNS 물질, 분석
│ ├── 06_scat_tables.sql 해안조사 구역, 구간
│ ├── 07_boom_backtrack_tables.sql 오일붐, 역추적, 선박
│ ├── 08_asset_tables.sql 자산 기관, 장비, 연락처
│ ├── 09_board_manual_tables.sql 게시판, 매뉴얼
│ ├── 10_report_tables.sql 보고서, 템플릿, 분석카테고리
│ ├── 11_aerial_rescue_tables.sql 항공, CCTV, 위성, 구조
│ ├── 12_incidents_tables.sql 사건사고
│ └── 13_indexes.sql 인덱스 (GiST, GIN, btree)
├── seed/ 초기 데이터 (INSERT)
│ ├── 01~06 auth 스키마 seed
│ ├── 07~08 공통코드, 조직
│ ├── 09~10 참조 안내 (Node.js seed)
│ ├── 11~14 샘플 데이터
│ └── README.md 실행 순서 안내
├── migration/ 증분 마이그레이션 (001~016)
└── _deprecated/ 구 스크립트 (통합 이전 버전)
├── init.sql 구 wing DB 초기 스키마
└── auth_init.sql 구 wing_auth DB 초기 스키마
```
## 마이그레이션 규칙
- 번호 체계: `NNN_설명.sql` (예: `017_add_feature.sql`)
- DDL(CREATE/ALTER)과 seed(INSERT)를 분리
- DDL만 포함하는 파일: `NNN_설명.sql`
- seed만 포함하는 파일: `NNN_설명_seed.sql`
- 새 테이블 추가 시 `schema/` 파일도 함께 업데이트
## PostGIS 컬럼
| 테이블 | 컬럼 | 타입 | 인덱스 |
|--------|------|------|--------|
| acdnt | loc_geom | Point, 4326 | GiST |
| aerial_media | geom | Point, 4326 | GiST |
| asset_org | geom | Point, 4326 | GiST |
| backtrack | geom | Point, 4326 | GiST |
| boom_line | geom | LineString, 4326 | GiST |
| cctv_camera | geom | Point, 4326 | GiST |
| cst_sect | geom | Point, 4326 | GiST |
| cst_srvy_zone | geom | Point, 4326 | GiST |
| hns_analysis | geom | Point, 4326 | - |
| rescue_ops | geom | Point, 4326 | GiST |
| sat_request | geom | Point, 4326 | GiST |
## 접속 정보
| 항목 | 값 |
|------|------|
| Host | 211.208.115.83 |
| Port | 5432 |
| Database | wing |
| User | wing |
| Schema | wing, auth, public |
| search_path | wing, auth, public |

파일 보기

@ -0,0 +1,21 @@
-- WING-OPS Database Schema: Extensions & Schemas
-- PostgreSQL 16 + PostGIS
-- ============================================================
-- 스키마 생성
-- ============================================================
CREATE SCHEMA IF NOT EXISTS auth;
CREATE SCHEMA IF NOT EXISTS wing;
-- ============================================================
-- 확장 설치
-- (postgis_topology는 운영 환경 전용, 여기서는 제외)
-- ============================================================
CREATE EXTENSION IF NOT EXISTS pg_trgm WITH SCHEMA public;
CREATE EXTENSION IF NOT EXISTS postgis WITH SCHEMA public;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA public;
-- ============================================================
-- 기본 검색 경로
-- ============================================================
SET search_path = wing, auth, public;

파일 보기

@ -0,0 +1,252 @@
-- WING-OPS Database Schema: Auth Tables
-- auth 스키마 9개 테이블 (인증/인가/감사)
-- ============================================================
-- 1. auth_role — 역할 (FK 없음, 최상위)
-- ============================================================
CREATE TABLE auth.auth_role (
role_sn integer NOT NULL,
role_cd character varying(20) NOT NULL,
role_nm character varying(50) NOT NULL,
role_dc character varying(200),
dflt_yn character(1) DEFAULT 'N'::bpchar NOT NULL,
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT pk_auth_role PRIMARY KEY (role_sn),
CONSTRAINT uk_auth_role_cd UNIQUE (role_cd),
CONSTRAINT ck_auth_role_dflt CHECK ((dflt_yn = ANY (ARRAY['Y'::bpchar, 'N'::bpchar])))
);
CREATE SEQUENCE auth.auth_role_role_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE auth.auth_role_role_sn_seq OWNED BY auth.auth_role.role_sn;
ALTER TABLE ONLY auth.auth_role ALTER COLUMN role_sn SET DEFAULT nextval('auth.auth_role_role_sn_seq'::regclass);
-- ============================================================
-- 2. auth_org — 조직 (자기참조 FK)
-- ============================================================
CREATE TABLE auth.auth_org (
org_sn integer NOT NULL,
org_nm character varying(100) NOT NULL,
org_abbr_nm character varying(20) NOT NULL,
org_tp_cd character varying(20) NOT NULL,
upper_org_sn integer,
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT pk_auth_org PRIMARY KEY (org_sn)
);
CREATE SEQUENCE auth.auth_org_org_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE auth.auth_org_org_sn_seq OWNED BY auth.auth_org.org_sn;
ALTER TABLE ONLY auth.auth_org ALTER COLUMN org_sn SET DEFAULT nextval('auth.auth_org_org_sn_seq'::regclass);
-- ============================================================
-- 3. auth_user — 사용자 (FK: auth_org)
-- ============================================================
CREATE TABLE auth.auth_user (
user_id uuid DEFAULT public.uuid_generate_v4() NOT NULL,
user_acnt character varying(50) NOT NULL,
pswd_hash character varying(255),
user_nm character varying(50) NOT NULL,
rnkp_nm character varying(30),
org_sn integer,
user_stts_cd character varying(20) DEFAULT 'ACTIVE'::character varying NOT NULL,
fail_cnt integer DEFAULT 0 NOT NULL,
last_login_dtm timestamp with time zone,
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
mdfcn_dtm timestamp with time zone DEFAULT now() NOT NULL,
oauth_provider character varying(20),
oauth_sub character varying(255),
email character varying(255),
CONSTRAINT pk_auth_user PRIMARY KEY (user_id),
CONSTRAINT uk_auth_user_acnt UNIQUE (user_acnt),
CONSTRAINT ck_auth_user_stts CHECK (((user_stts_cd)::text = ANY (ARRAY[('ACTIVE'::character varying)::text, ('LOCKED'::character varying)::text, ('INACTIVE'::character varying)::text])))
);
-- 조건부 유니크 인덱스 (NULL 값 제외)
CREATE UNIQUE INDEX uk_auth_user_email ON auth.auth_user USING btree (email) WHERE (email IS NOT NULL);
CREATE UNIQUE INDEX uk_auth_user_oauth ON auth.auth_user USING btree (oauth_provider, oauth_sub) WHERE (oauth_provider IS NOT NULL);
-- ============================================================
-- 4. auth_user_role — 사용자-역할 매핑 (FK: auth_user, auth_role)
-- ============================================================
CREATE TABLE auth.auth_user_role (
user_id uuid NOT NULL,
role_sn integer NOT NULL,
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT pk_auth_user_role PRIMARY KEY (user_id, role_sn)
);
-- ============================================================
-- 5. auth_perm_tree — 권한 트리 (자기참조 FK)
-- ============================================================
CREATE TABLE auth.auth_perm_tree (
rsrc_cd character varying(50) NOT NULL,
parent_cd character varying(50),
rsrc_nm character varying(100) NOT NULL,
rsrc_desc character varying(200),
icon character varying(20),
rsrc_level smallint DEFAULT 0 NOT NULL,
sort_ord smallint DEFAULT 0 NOT NULL,
use_yn character(1) DEFAULT 'Y'::bpchar NOT NULL,
CONSTRAINT pk_perm_tree PRIMARY KEY (rsrc_cd)
);
-- ============================================================
-- 6. auth_perm — 역할별 권한 (FK: auth_role)
-- ============================================================
CREATE TABLE auth.auth_perm (
perm_sn integer NOT NULL,
role_sn integer NOT NULL,
rsrc_cd character varying(50) NOT NULL,
grant_yn character(1) DEFAULT 'Y'::bpchar NOT NULL,
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
oper_cd character varying(20) NOT NULL,
CONSTRAINT pk_auth_perm PRIMARY KEY (perm_sn),
CONSTRAINT uk_auth_perm UNIQUE (role_sn, rsrc_cd, oper_cd),
CONSTRAINT ck_auth_perm_grant CHECK ((grant_yn = ANY (ARRAY['Y'::bpchar, 'N'::bpchar]))),
CONSTRAINT ck_auth_perm_oper CHECK (((oper_cd)::text = ANY (ARRAY[('READ'::character varying)::text, ('CREATE'::character varying)::text, ('UPDATE'::character varying)::text, ('DELETE'::character varying)::text, ('MANAGE'::character varying)::text, ('EXPORT'::character varying)::text])))
);
CREATE SEQUENCE auth.auth_perm_perm_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE auth.auth_perm_perm_sn_seq OWNED BY auth.auth_perm.perm_sn;
ALTER TABLE ONLY auth.auth_perm ALTER COLUMN perm_sn SET DEFAULT nextval('auth.auth_perm_perm_sn_seq'::regclass);
-- ============================================================
-- 7. auth_setting — 시스템 설정
-- ============================================================
CREATE TABLE auth.auth_setting (
setting_key character varying(100) NOT NULL,
setting_val text NOT NULL,
setting_dc character varying(500),
mdfcn_dtm timestamp without time zone DEFAULT now(),
CONSTRAINT auth_setting_pkey PRIMARY KEY (setting_key)
);
-- ============================================================
-- 8. auth_login_hist — 로그인 이력 (FK: auth_user)
-- ============================================================
CREATE TABLE auth.auth_login_hist (
hist_sn integer NOT NULL,
user_id uuid NOT NULL,
login_dtm timestamp with time zone DEFAULT now() NOT NULL,
ip_addr character varying(45),
user_agent character varying(500),
success_yn character(1) DEFAULT 'Y'::bpchar NOT NULL,
CONSTRAINT pk_auth_login_hist PRIMARY KEY (hist_sn),
CONSTRAINT ck_alh_success CHECK ((success_yn = ANY (ARRAY['Y'::bpchar, 'N'::bpchar])))
);
CREATE SEQUENCE auth.auth_login_hist_hist_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE auth.auth_login_hist_hist_sn_seq OWNED BY auth.auth_login_hist.hist_sn;
ALTER TABLE ONLY auth.auth_login_hist ALTER COLUMN hist_sn SET DEFAULT nextval('auth.auth_login_hist_hist_sn_seq'::regclass);
-- ============================================================
-- 9. auth_audit_log — 감사 로그
-- ============================================================
CREATE TABLE auth.auth_audit_log (
log_sn integer NOT NULL,
user_id uuid,
action_cd character varying(30) NOT NULL,
action_dtl character varying(100),
http_method character varying(10),
crud_type character varying(10),
req_url character varying(500),
req_dtm timestamp with time zone DEFAULT now() NOT NULL,
res_dtm timestamp with time zone,
res_status smallint,
res_size integer,
ip_addr character varying(45),
user_agent character varying(500),
extra jsonb,
CONSTRAINT pk_auth_audit_log PRIMARY KEY (log_sn)
);
CREATE SEQUENCE auth.auth_audit_log_log_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE auth.auth_audit_log_log_sn_seq OWNED BY auth.auth_audit_log.log_sn;
ALTER TABLE ONLY auth.auth_audit_log ALTER COLUMN log_sn SET DEFAULT nextval('auth.auth_audit_log_log_sn_seq'::regclass);
-- ============================================================
-- FK 제약조건
-- ============================================================
ALTER TABLE ONLY auth.auth_org
ADD CONSTRAINT fk_auth_org_upper FOREIGN KEY (upper_org_sn) REFERENCES auth.auth_org(org_sn);
ALTER TABLE ONLY auth.auth_user
ADD CONSTRAINT fk_auth_user_org FOREIGN KEY (org_sn) REFERENCES auth.auth_org(org_sn);
ALTER TABLE ONLY auth.auth_user_role
ADD CONSTRAINT fk_aur_user FOREIGN KEY (user_id) REFERENCES auth.auth_user(user_id) ON DELETE CASCADE;
ALTER TABLE ONLY auth.auth_user_role
ADD CONSTRAINT fk_aur_role FOREIGN KEY (role_sn) REFERENCES auth.auth_role(role_sn) ON DELETE CASCADE;
ALTER TABLE ONLY auth.auth_perm_tree
ADD CONSTRAINT fk_perm_tree_parent FOREIGN KEY (parent_cd) REFERENCES auth.auth_perm_tree(rsrc_cd);
ALTER TABLE ONLY auth.auth_perm
ADD CONSTRAINT fk_ap_role FOREIGN KEY (role_sn) REFERENCES auth.auth_role(role_sn) ON DELETE CASCADE;
ALTER TABLE ONLY auth.auth_login_hist
ADD CONSTRAINT fk_alh_user FOREIGN KEY (user_id) REFERENCES auth.auth_user(user_id) ON DELETE CASCADE;
-- ============================================================
-- 인덱스
-- ============================================================
CREATE INDEX idx_auth_user_org ON auth.auth_user USING btree (org_sn);
CREATE INDEX idx_auth_user_stts ON auth.auth_user USING btree (user_stts_cd);
CREATE INDEX idx_auth_perm_role ON auth.auth_perm USING btree (role_sn);
CREATE INDEX idx_auth_perm_rsrc ON auth.auth_perm USING btree (rsrc_cd);
CREATE INDEX idx_auth_perm_oper ON auth.auth_perm USING btree (oper_cd);
CREATE INDEX idx_perm_tree_parent ON auth.auth_perm_tree USING btree (parent_cd);
CREATE INDEX idx_auth_login_user ON auth.auth_login_hist USING btree (user_id);
CREATE INDEX idx_auth_login_dtm ON auth.auth_login_hist USING btree (login_dtm);
CREATE INDEX idx_audit_log_user ON auth.auth_audit_log USING btree (user_id);
CREATE INDEX idx_audit_log_action ON auth.auth_audit_log USING btree (action_cd);
CREATE INDEX idx_audit_log_dtm ON auth.auth_audit_log USING btree (req_dtm);

파일 보기

@ -0,0 +1,88 @@
-- WING-OPS Database Schema: Common Tables
-- wing 스키마 공통 테이블 (공통코드, 레이어)
-- ============================================================
-- 1. cmn_cd_grp — 공통코드그룹
-- (pg_dump에 없음, init.sql 기반으로 wing 스키마 변환)
-- ============================================================
CREATE TABLE wing.cmn_cd_grp (
cmn_cd_grp_id character varying(20) NOT NULL,
cmn_cd_grp_nm character varying(100) NOT NULL,
grp_dc character varying(500),
use_yn character(1) DEFAULT 'Y'::bpchar NOT NULL,
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT pk_cmn_cd_grp PRIMARY KEY (cmn_cd_grp_id),
CONSTRAINT ck_cmn_cd_grp_use_yn CHECK ((use_yn = ANY (ARRAY['Y'::bpchar, 'N'::bpchar])))
);
COMMENT ON TABLE wing.cmn_cd_grp IS '공통코드그룹';
COMMENT ON COLUMN wing.cmn_cd_grp.cmn_cd_grp_id IS '공통코드그룹아이디';
COMMENT ON COLUMN wing.cmn_cd_grp.cmn_cd_grp_nm IS '공통코드그룹명';
COMMENT ON COLUMN wing.cmn_cd_grp.grp_dc IS '그룹설명';
COMMENT ON COLUMN wing.cmn_cd_grp.use_yn IS '사용여부 (Y:사용, N:미사용)';
COMMENT ON COLUMN wing.cmn_cd_grp.reg_dtm IS '등록일시';
-- ============================================================
-- 2. cmn_cd — 공통코드
-- (pg_dump에 없음, init.sql 기반으로 wing 스키마 변환)
-- ============================================================
CREATE TABLE wing.cmn_cd (
cmn_cd_grp_id character varying(20) NOT NULL,
cmn_cd character varying(20) NOT NULL,
cmn_cd_nm character varying(100) NOT NULL,
cd_dc character varying(500),
sort_ord integer DEFAULT 0,
use_yn character(1) DEFAULT 'Y'::bpchar NOT NULL,
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT pk_cmn_cd PRIMARY KEY (cmn_cd_grp_id, cmn_cd),
CONSTRAINT ck_cmn_cd_use_yn CHECK ((use_yn = ANY (ARRAY['Y'::bpchar, 'N'::bpchar])))
);
COMMENT ON TABLE wing.cmn_cd IS '공통코드';
COMMENT ON COLUMN wing.cmn_cd.cmn_cd_grp_id IS '공통코드그룹아이디';
COMMENT ON COLUMN wing.cmn_cd.cmn_cd IS '공통코드';
COMMENT ON COLUMN wing.cmn_cd.cmn_cd_nm IS '공통코드명';
COMMENT ON COLUMN wing.cmn_cd.cd_dc IS '코드설명';
COMMENT ON COLUMN wing.cmn_cd.sort_ord IS '정렬순서';
COMMENT ON COLUMN wing.cmn_cd.use_yn IS '사용여부 (Y:사용, N:미사용)';
COMMENT ON COLUMN wing.cmn_cd.reg_dtm IS '등록일시';
-- ============================================================
-- 3. layer — 레이어 (자기참조 FK)
-- ============================================================
CREATE TABLE wing.layer (
layer_cd character varying(50) NOT NULL,
up_layer_cd character varying(50),
layer_full_nm character varying(200) NOT NULL,
layer_nm character varying(100) NOT NULL,
layer_level integer NOT NULL,
wms_layer_nm character varying(100),
use_yn character(1) DEFAULT 'Y'::bpchar NOT NULL,
sort_ord integer DEFAULT 0,
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT pk_layer PRIMARY KEY (layer_cd),
CONSTRAINT ck_layer_use_yn CHECK ((use_yn = ANY (ARRAY['Y'::bpchar, 'N'::bpchar])))
);
-- ============================================================
-- FK 제약조건
-- ============================================================
ALTER TABLE ONLY wing.cmn_cd
ADD CONSTRAINT fk_cmn_cd_grp FOREIGN KEY (cmn_cd_grp_id) REFERENCES wing.cmn_cd_grp(cmn_cd_grp_id);
ALTER TABLE ONLY wing.layer
ADD CONSTRAINT fk_layer_up FOREIGN KEY (up_layer_cd) REFERENCES wing.layer(layer_cd);
-- ============================================================
-- 인덱스
-- ============================================================
CREATE INDEX idx_cmn_cd_grp_use ON wing.cmn_cd_grp USING btree (use_yn);
CREATE INDEX idx_cmn_cd_use ON wing.cmn_cd USING btree (use_yn);
CREATE INDEX idx_layer_up ON wing.layer USING btree (up_layer_cd);
CREATE INDEX idx_layer_level ON wing.layer USING btree (layer_level);
CREATE INDEX idx_layer_use ON wing.layer USING btree (use_yn);

파일 보기

@ -0,0 +1,83 @@
-- WING-OPS Database Schema: Org & User Tables
-- wing 스키마 조직/사용자 테이블
-- (pg_dump에 없음, init.sql 기반으로 wing 스키마 변환)
-- ============================================================
-- 1. org — 조직 (자기참조 FK)
-- ============================================================
CREATE TABLE wing.org (
org_sn integer NOT NULL,
org_nm character varying(100) NOT NULL,
org_abbr_nm character varying(20) NOT NULL,
org_tp_cd character varying(20) NOT NULL,
upper_org_sn integer,
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT pk_org PRIMARY KEY (org_sn)
);
CREATE SEQUENCE wing.org_org_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.org_org_sn_seq OWNED BY wing.org.org_sn;
ALTER TABLE ONLY wing.org ALTER COLUMN org_sn SET DEFAULT nextval('wing.org_org_sn_seq'::regclass);
COMMENT ON TABLE wing.org IS '조직';
COMMENT ON COLUMN wing.org.org_sn IS '조직순번';
COMMENT ON COLUMN wing.org.org_nm IS '조직명 (기관 전체 명칭)';
COMMENT ON COLUMN wing.org.org_abbr_nm IS '조직약칭명 (기관 약칭)';
COMMENT ON COLUMN wing.org.org_tp_cd IS '조직유형코드 (ORG_TP: headquarters, regional, station, agency)';
COMMENT ON COLUMN wing.org.upper_org_sn IS '상위조직순번 (상위 기관 참조)';
COMMENT ON COLUMN wing.org.reg_dtm IS '등록일시';
-- ============================================================
-- 2. user_info — 사용자정보 (FK: wing.org)
-- (USER는 PostgreSQL 예약어이므로 user_info 사용)
-- ============================================================
CREATE TABLE wing.user_info (
user_id uuid DEFAULT public.uuid_generate_v4() NOT NULL,
user_acnt character varying(50) NOT NULL,
pswd_hash character varying(255) NOT NULL,
user_nm character varying(50) NOT NULL,
rnkp_nm character varying(30),
org_sn integer,
role_cd character varying(20) DEFAULT 'USER'::character varying NOT NULL,
actv_yn character(1) DEFAULT 'Y'::bpchar NOT NULL,
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT pk_user_info PRIMARY KEY (user_id),
CONSTRAINT uk_user_acnt UNIQUE (user_acnt),
CONSTRAINT ck_user_role_cd CHECK (((role_cd)::text = ANY (ARRAY[('ADMIN'::character varying)::text, ('MANAGER'::character varying)::text, ('USER'::character varying)::text]))),
CONSTRAINT ck_user_actv_yn CHECK ((actv_yn = ANY (ARRAY['Y'::bpchar, 'N'::bpchar])))
);
COMMENT ON TABLE wing.user_info IS '사용자정보';
COMMENT ON COLUMN wing.user_info.user_id IS '사용자아이디 (UUID)';
COMMENT ON COLUMN wing.user_info.user_acnt IS '사용자계정 (로그인 ID)';
COMMENT ON COLUMN wing.user_info.pswd_hash IS '비밀번호해시 (bcrypt 해시값)';
COMMENT ON COLUMN wing.user_info.user_nm IS '사용자명';
COMMENT ON COLUMN wing.user_info.rnkp_nm IS '직급명';
COMMENT ON COLUMN wing.user_info.org_sn IS '조직순번 (소속 조직)';
COMMENT ON COLUMN wing.user_info.role_cd IS '역할코드 (ADMIN, MANAGER, USER)';
COMMENT ON COLUMN wing.user_info.actv_yn IS '활성여부 (Y:활성, N:비활성)';
COMMENT ON COLUMN wing.user_info.reg_dtm IS '등록일시';
-- ============================================================
-- FK 제약조건
-- ============================================================
ALTER TABLE ONLY wing.org
ADD CONSTRAINT fk_org_upper FOREIGN KEY (upper_org_sn) REFERENCES wing.org(org_sn);
ALTER TABLE ONLY wing.user_info
ADD CONSTRAINT fk_user_org FOREIGN KEY (org_sn) REFERENCES wing.org(org_sn);
-- ============================================================
-- 인덱스
-- ============================================================
CREATE INDEX idx_user_org_sn ON wing.user_info USING btree (org_sn);

파일 보기

@ -0,0 +1,202 @@
-- WING-OPS Database Schema: Accident Tables
-- wing 스키마 사고 관련 테이블
-- ============================================================
-- 1. acdnt — 사고
-- ============================================================
CREATE TABLE wing.acdnt (
acdnt_sn integer NOT NULL,
acdnt_cd character varying(20) NOT NULL,
acdnt_nm character varying(200) NOT NULL,
acdnt_tp_cd character varying(50) NOT NULL,
acdnt_stts_cd character varying(20) DEFAULT 'ACTIVE'::character varying NOT NULL,
lat numeric(9,6),
lng numeric(10,6),
loc_dc character varying(200),
occrn_dtm timestamp with time zone NOT NULL,
rpt_dtm timestamp with time zone,
region_nm character varying(20),
office_nm character varying(30),
svrt_cd character varying(10),
vessel_tp character varying(30),
phase_cd character varying(20) DEFAULT 'RESPONSE'::character varying,
analyst_nm character varying(50),
rgtr_id uuid,
use_yn character(1) DEFAULT 'Y'::bpchar,
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
mdfcn_dtm timestamp with time zone,
loc_geom public.geometry(Point,4326),
CONSTRAINT pk_acdnt PRIMARY KEY (acdnt_sn),
CONSTRAINT uk_acdnt_cd UNIQUE (acdnt_cd),
CONSTRAINT ck_acdnt_stts CHECK (((acdnt_stts_cd)::text = ANY (ARRAY[('ACTIVE'::character varying)::text, ('INVESTIGATING'::character varying)::text, ('CLOSED'::character varying)::text]))),
CONSTRAINT ck_acdnt_svrt CHECK (((svrt_cd IS NULL) OR ((svrt_cd)::text = ANY (ARRAY[('DANGER'::character varying)::text, ('ALERT'::character varying)::text, ('CAUTION'::character varying)::text, ('INTEREST'::character varying)::text])))),
CONSTRAINT ck_acdnt_phase CHECK (((phase_cd IS NULL) OR ((phase_cd)::text = ANY (ARRAY[('RESPONSE'::character varying)::text, ('STANDBY'::character varying)::text, ('CLOSED'::character varying)::text]))))
);
CREATE SEQUENCE wing.acdnt_acdnt_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.acdnt_acdnt_sn_seq OWNED BY wing.acdnt.acdnt_sn;
ALTER TABLE ONLY wing.acdnt ALTER COLUMN acdnt_sn SET DEFAULT nextval('wing.acdnt_acdnt_sn_seq'::regclass);
-- ============================================================
-- 2. spil_data — 유출정보
-- ============================================================
CREATE TABLE wing.spil_data (
spil_data_sn integer NOT NULL,
acdnt_sn integer NOT NULL,
oil_tp_cd character varying(50) NOT NULL,
spil_qty numeric(12,2),
spil_unit_cd character varying(10) DEFAULT 'KL'::character varying,
spil_tp_cd character varying(20),
fcst_hr integer,
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT pk_spil_data PRIMARY KEY (spil_data_sn)
);
CREATE SEQUENCE wing.spil_data_spil_data_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.spil_data_spil_data_sn_seq OWNED BY wing.spil_data.spil_data_sn;
ALTER TABLE ONLY wing.spil_data ALTER COLUMN spil_data_sn SET DEFAULT nextval('wing.spil_data_spil_data_sn_seq'::regclass);
-- ============================================================
-- 3. pred_exec — 예측실행
-- ============================================================
CREATE TABLE wing.pred_exec (
pred_exec_sn integer NOT NULL,
acdnt_sn integer NOT NULL,
algo_cd character varying(20) NOT NULL,
exec_stts_cd character varying(20) DEFAULT 'PENDING'::character varying NOT NULL,
bgng_dtm timestamp with time zone,
cmpl_dtm timestamp with time zone,
reqd_sec integer,
rslt_data jsonb,
err_msg text,
CONSTRAINT pk_pred_exec PRIMARY KEY (pred_exec_sn),
CONSTRAINT ck_pred_stts CHECK (((exec_stts_cd)::text = ANY (ARRAY[('PENDING'::character varying)::text, ('RUNNING'::character varying)::text, ('COMPLETED'::character varying)::text, ('FAILED'::character varying)::text])))
);
CREATE SEQUENCE wing.pred_exec_pred_exec_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.pred_exec_pred_exec_sn_seq OWNED BY wing.pred_exec.pred_exec_sn;
ALTER TABLE ONLY wing.pred_exec ALTER COLUMN pred_exec_sn SET DEFAULT nextval('wing.pred_exec_pred_exec_sn_seq'::regclass);
-- ============================================================
-- 4. acdnt_weather — 사고기상정보
-- ============================================================
CREATE TABLE wing.acdnt_weather (
weather_sn integer NOT NULL,
acdnt_sn integer NOT NULL,
loc_nm character varying(100),
obs_dtm timestamp with time zone,
icon character varying(10),
temp character varying(20),
weather_dc character varying(50),
wind character varying(30),
wave character varying(20),
humid character varying(20),
vis character varying(20),
sst character varying(20),
tide character varying(30),
high_tide character varying(30),
low_tide character varying(30),
forecast jsonb,
impact_dc text,
reg_dtm timestamp with time zone DEFAULT now(),
CONSTRAINT acdnt_weather_pkey PRIMARY KEY (weather_sn)
);
CREATE SEQUENCE wing.acdnt_weather_weather_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.acdnt_weather_weather_sn_seq OWNED BY wing.acdnt_weather.weather_sn;
ALTER TABLE ONLY wing.acdnt_weather ALTER COLUMN weather_sn SET DEFAULT nextval('wing.acdnt_weather_weather_sn_seq'::regclass);
-- ============================================================
-- 5. acdnt_media — 사고미디어
-- ============================================================
CREATE TABLE wing.acdnt_media (
media_sn integer NOT NULL,
acdnt_sn integer NOT NULL,
photo_cnt smallint DEFAULT 0,
video_cnt smallint DEFAULT 0,
sat_cnt smallint DEFAULT 0,
cctv_cnt smallint DEFAULT 0,
photo_meta jsonb,
drone_meta jsonb,
sat_meta jsonb,
cctv_meta jsonb,
reg_dtm timestamp with time zone DEFAULT now(),
CONSTRAINT acdnt_media_pkey PRIMARY KEY (media_sn)
);
CREATE SEQUENCE wing.acdnt_media_media_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.acdnt_media_media_sn_seq OWNED BY wing.acdnt_media.media_sn;
ALTER TABLE ONLY wing.acdnt_media ALTER COLUMN media_sn SET DEFAULT nextval('wing.acdnt_media_media_sn_seq'::regclass);
-- ============================================================
-- FK 제약조건
-- ============================================================
ALTER TABLE ONLY wing.spil_data
ADD CONSTRAINT fk_spil_acdnt FOREIGN KEY (acdnt_sn) REFERENCES wing.acdnt(acdnt_sn) ON DELETE CASCADE;
ALTER TABLE ONLY wing.pred_exec
ADD CONSTRAINT fk_pred_acdnt FOREIGN KEY (acdnt_sn) REFERENCES wing.acdnt(acdnt_sn) ON DELETE CASCADE;
ALTER TABLE ONLY wing.acdnt_weather
ADD CONSTRAINT acdnt_weather_acdnt_sn_fkey FOREIGN KEY (acdnt_sn) REFERENCES wing.acdnt(acdnt_sn) ON DELETE CASCADE;
ALTER TABLE ONLY wing.acdnt_media
ADD CONSTRAINT acdnt_media_acdnt_sn_fkey FOREIGN KEY (acdnt_sn) REFERENCES wing.acdnt(acdnt_sn) ON DELETE CASCADE;
-- ============================================================
-- 인덱스
-- ============================================================
-- 공간 인덱스
CREATE INDEX idx_acdnt_loc_geom ON wing.acdnt USING gist (loc_geom);
-- 상태/분류 인덱스
CREATE INDEX idx_acdnt_stts ON wing.acdnt USING btree (acdnt_stts_cd);
CREATE INDEX idx_acdnt_occrn ON wing.acdnt USING btree (occrn_dtm DESC);
CREATE INDEX idx_acdnt_region ON wing.acdnt USING btree (region_nm);
-- 외래키 인덱스
CREATE INDEX idx_spil_acdnt ON wing.spil_data USING btree (acdnt_sn);
CREATE INDEX idx_pred_acdnt ON wing.pred_exec USING btree (acdnt_sn);
CREATE INDEX idx_weather_acdnt ON wing.acdnt_weather USING btree (acdnt_sn);
CREATE INDEX idx_media_acdnt ON wing.acdnt_media USING btree (acdnt_sn);

파일 보기

@ -0,0 +1,106 @@
-- WING-OPS Database Schema: HNS Tables
-- wing 스키마 HNS(위험유해물질) 분석 테이블
-- ============================================================
-- 1. hns_substance — HNS물질정보
-- ============================================================
CREATE TABLE wing.hns_substance (
sbst_sn integer NOT NULL,
abbreviation character varying(50),
nm_kr character varying(200) NOT NULL,
nm_en character varying(200),
un_no character varying(10),
cas_no character varying(20),
sebc character varying(50),
data jsonb NOT NULL,
use_yn character(1) DEFAULT 'Y'::bpchar NOT NULL,
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT pk_hns_substance PRIMARY KEY (sbst_sn),
CONSTRAINT ck_hns_sbst_use CHECK ((use_yn = ANY (ARRAY['Y'::bpchar, 'N'::bpchar])))
);
CREATE SEQUENCE wing.hns_substance_sbst_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.hns_substance_sbst_sn_seq OWNED BY wing.hns_substance.sbst_sn;
ALTER TABLE ONLY wing.hns_substance ALTER COLUMN sbst_sn SET DEFAULT nextval('wing.hns_substance_sbst_sn_seq'::regclass);
-- ============================================================
-- 2. hns_analysis — HNS분석
-- ============================================================
CREATE TABLE wing.hns_analysis (
hns_anlys_sn integer NOT NULL,
acdnt_sn integer,
anlys_nm character varying(200) NOT NULL,
acdnt_dtm timestamp with time zone,
loc_nm character varying(200),
lon numeric(10,6),
lat numeric(9,6),
geom public.geometry(Point,4326),
loc_dc character varying(100),
sbst_sn integer,
sbst_nm character varying(100),
un_no character varying(10),
cas_no character varying(20),
spil_qty numeric(10,2),
spil_unit_cd character varying(10) DEFAULT 'KL'::character varying,
spil_tp_cd character varying(20),
fcst_hr integer,
algo_cd character varying(20),
crit_mdl_cd character varying(10),
wind_spd numeric(5,1),
wind_dir character varying(10),
temp numeric(4,1),
humid numeric(4,1),
atm_stbl_cd character varying(10),
exec_stts_cd character varying(20) DEFAULT 'COMPLETED'::character varying,
risk_cd character varying(20),
analyst_nm character varying(50),
rslt_data jsonb,
use_yn character(1) DEFAULT 'Y'::bpchar,
reg_dtm timestamp with time zone DEFAULT now(),
mdfcn_dtm timestamp with time zone DEFAULT now(),
CONSTRAINT hns_analysis_pkey PRIMARY KEY (hns_anlys_sn),
CONSTRAINT ck_hns_stts CHECK (((exec_stts_cd)::text = ANY (ARRAY[('PENDING'::character varying)::text, ('RUNNING'::character varying)::text, ('COMPLETED'::character varying)::text, ('FAILED'::character varying)::text])))
);
CREATE SEQUENCE wing.hns_analysis_hns_anlys_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.hns_analysis_hns_anlys_sn_seq OWNED BY wing.hns_analysis.hns_anlys_sn;
ALTER TABLE ONLY wing.hns_analysis ALTER COLUMN hns_anlys_sn SET DEFAULT nextval('wing.hns_analysis_hns_anlys_sn_seq'::regclass);
-- ============================================================
-- FK 제약조건
-- ============================================================
ALTER TABLE ONLY wing.hns_analysis
ADD CONSTRAINT hns_analysis_acdnt_sn_fkey FOREIGN KEY (acdnt_sn) REFERENCES wing.acdnt(acdnt_sn);
-- ============================================================
-- 인덱스
-- ============================================================
-- hns_substance 검색 인덱스 (GIN trgm — 텍스트 검색)
CREATE INDEX idx_hns_sbst_nm_kr ON wing.hns_substance USING gin (nm_kr public.gin_trgm_ops);
CREATE INDEX idx_hns_sbst_nm_en ON wing.hns_substance USING gin (nm_en public.gin_trgm_ops);
CREATE INDEX idx_hns_sbst_abbr ON wing.hns_substance USING gin (abbreviation public.gin_trgm_ops);
-- hns_substance 코드 인덱스
CREATE INDEX idx_hns_sbst_un ON wing.hns_substance USING btree (un_no);
CREATE INDEX idx_hns_sbst_cas ON wing.hns_substance USING btree (cas_no);
CREATE INDEX idx_hns_sbst_sebc ON wing.hns_substance USING btree (sebc);
-- hns_substance JSONB 인덱스
CREATE INDEX idx_hns_sbst_data ON wing.hns_substance USING gin (data jsonb_path_ops);

파일 보기

@ -0,0 +1,188 @@
-- WING-OPS Database Schema: SCAT Tables
-- wing 스키마 해안조사/SCAT 테이블
-- ============================================================
-- 1. cst_srvy_zone — 해안조사구역
-- ============================================================
CREATE TABLE wing.cst_srvy_zone (
cst_srvy_zone_sn integer NOT NULL,
zone_cd character varying(10) NOT NULL,
zone_nm character varying(100) NOT NULL,
jrsd_nm character varying(20),
sect_cnt integer DEFAULT 0,
lat_center numeric(9,6),
lng_center numeric(9,6),
lat_range numeric(9,6),
lng_range numeric(9,6),
geom public.geometry(Point,4326),
use_yn character(1) DEFAULT 'Y'::bpchar,
reg_dtm timestamp with time zone DEFAULT now(),
CONSTRAINT cst_srvy_zone_pkey PRIMARY KEY (cst_srvy_zone_sn),
CONSTRAINT cst_srvy_zone_zone_cd_key UNIQUE (zone_cd)
);
CREATE SEQUENCE wing.cst_srvy_zone_cst_srvy_zone_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.cst_srvy_zone_cst_srvy_zone_sn_seq OWNED BY wing.cst_srvy_zone.cst_srvy_zone_sn;
ALTER TABLE ONLY wing.cst_srvy_zone ALTER COLUMN cst_srvy_zone_sn SET DEFAULT nextval('wing.cst_srvy_zone_cst_srvy_zone_sn_seq'::regclass);
-- ============================================================
-- 2. cst_sect — 해안구간
-- ============================================================
CREATE TABLE wing.cst_sect (
cst_sect_sn integer NOT NULL,
cst_srvy_zone_sn integer,
sect_cd character varying(20) NOT NULL,
sect_nm character varying(200),
cst_tp_cd character varying(30),
esi_cd character varying(5),
esi_num smallint,
len_m numeric(8,1),
snstvt_cd character varying(10),
srvy_stts_cd character varying(10) DEFAULT '미조사'::character varying,
lat numeric(9,6),
lng numeric(9,6),
geom public.geometry(Point,4326),
tags jsonb DEFAULT '[]'::jsonb,
shore_tp character varying(20),
access_dc character varying(500),
access_pt character varying(200),
sensitive_info jsonb DEFAULT '[]'::jsonb,
cleanup_methods jsonb DEFAULT '[]'::jsonb,
end_criteria jsonb DEFAULT '[]'::jsonb,
notes jsonb DEFAULT '[]'::jsonb,
use_yn character(1) DEFAULT 'Y'::bpchar,
reg_dtm timestamp with time zone DEFAULT now(),
CONSTRAINT cst_sect_pkey PRIMARY KEY (cst_sect_sn),
CONSTRAINT cst_sect_sect_cd_key UNIQUE (sect_cd)
);
CREATE SEQUENCE wing.cst_sect_cst_sect_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.cst_sect_cst_sect_sn_seq OWNED BY wing.cst_sect.cst_sect_sn;
ALTER TABLE ONLY wing.cst_sect ALTER COLUMN cst_sect_sn SET DEFAULT nextval('wing.cst_sect_cst_sect_sn_seq'::regclass);
-- ============================================================
-- 3. scat_srvy — SCAT조사
-- (pg_dump에 없음, init.sql 기반으로 wing 스키마 변환)
-- ============================================================
CREATE TABLE wing.scat_srvy (
scat_srvy_sn integer NOT NULL,
cst_sect_sn integer NOT NULL,
acdnt_sn integer,
srvy_ymd character(8),
srvy_tp_cd character varying(20),
srvy_phase_cd character varying(20),
polut_cd character varying(20),
srvyr_id uuid,
rmk character varying(500),
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT pk_scat_srvy PRIMARY KEY (scat_srvy_sn)
);
CREATE SEQUENCE wing.scat_srvy_scat_srvy_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.scat_srvy_scat_srvy_sn_seq OWNED BY wing.scat_srvy.scat_srvy_sn;
ALTER TABLE ONLY wing.scat_srvy ALTER COLUMN scat_srvy_sn SET DEFAULT nextval('wing.scat_srvy_scat_srvy_sn_seq'::regclass);
COMMENT ON TABLE wing.scat_srvy IS 'SCAT조사';
COMMENT ON COLUMN wing.scat_srvy.scat_srvy_sn IS 'SCAT조사순번';
COMMENT ON COLUMN wing.scat_srvy.cst_sect_sn IS '해안구간순번 (해안구간 참조)';
COMMENT ON COLUMN wing.scat_srvy.acdnt_sn IS '사고순번 (관련 사고 참조)';
COMMENT ON COLUMN wing.scat_srvy.srvy_ymd IS '조사일자 (YYYYMMDD 저장형식)';
COMMENT ON COLUMN wing.scat_srvy.srvy_tp_cd IS '조사유형코드 (SRVY_TP: Pre-SCAT, SCAT, Post-SCAT)';
COMMENT ON COLUMN wing.scat_srvy.srvy_phase_cd IS '조사단계코드 (SRVY_PHASE: 1차, 2차, 3차 등)';
COMMENT ON COLUMN wing.scat_srvy.polut_cd IS '오염도코드 (POLUT: HEAVY, MODERATE, LIGHT, CLEAN)';
COMMENT ON COLUMN wing.scat_srvy.srvyr_id IS '조사자아이디';
COMMENT ON COLUMN wing.scat_srvy.rmk IS '비고';
COMMENT ON COLUMN wing.scat_srvy.reg_dtm IS '등록일시';
-- ============================================================
-- 4. scat_srvy_photo — SCAT조사사진
-- (pg_dump에 없음, init.sql 기반으로 wing 스키마 변환)
-- ============================================================
CREATE TABLE wing.scat_srvy_photo (
scat_photo_sn integer NOT NULL,
scat_srvy_sn integer NOT NULL,
photo_file_path character varying(500) NOT NULL,
photo_dc character varying(200),
takng_dtm timestamp with time zone,
sort_ord integer DEFAULT 0,
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT pk_scat_photo PRIMARY KEY (scat_photo_sn)
);
CREATE SEQUENCE wing.scat_srvy_photo_scat_photo_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.scat_srvy_photo_scat_photo_sn_seq OWNED BY wing.scat_srvy_photo.scat_photo_sn;
ALTER TABLE ONLY wing.scat_srvy_photo ALTER COLUMN scat_photo_sn SET DEFAULT nextval('wing.scat_srvy_photo_scat_photo_sn_seq'::regclass);
COMMENT ON TABLE wing.scat_srvy_photo IS 'SCAT조사사진';
COMMENT ON COLUMN wing.scat_srvy_photo.scat_photo_sn IS 'SCAT조사사진순번';
COMMENT ON COLUMN wing.scat_srvy_photo.scat_srvy_sn IS 'SCAT조사순번 (SCAT조사 참조)';
COMMENT ON COLUMN wing.scat_srvy_photo.photo_file_path IS '사진파일경로';
COMMENT ON COLUMN wing.scat_srvy_photo.photo_dc IS '사진설명';
COMMENT ON COLUMN wing.scat_srvy_photo.takng_dtm IS '촬영일시';
COMMENT ON COLUMN wing.scat_srvy_photo.sort_ord IS '정렬순서';
COMMENT ON COLUMN wing.scat_srvy_photo.reg_dtm IS '등록일시';
-- ============================================================
-- FK 제약조건
-- ============================================================
ALTER TABLE ONLY wing.cst_sect
ADD CONSTRAINT cst_sect_cst_srvy_zone_sn_fkey FOREIGN KEY (cst_srvy_zone_sn) REFERENCES wing.cst_srvy_zone(cst_srvy_zone_sn);
ALTER TABLE ONLY wing.scat_srvy
ADD CONSTRAINT fk_scat_sect FOREIGN KEY (cst_sect_sn) REFERENCES wing.cst_sect(cst_sect_sn);
ALTER TABLE ONLY wing.scat_srvy
ADD CONSTRAINT fk_scat_acdnt FOREIGN KEY (acdnt_sn) REFERENCES wing.acdnt(acdnt_sn);
ALTER TABLE ONLY wing.scat_srvy_photo
ADD CONSTRAINT fk_photo_srvy FOREIGN KEY (scat_srvy_sn) REFERENCES wing.scat_srvy(scat_srvy_sn) ON DELETE CASCADE;
-- ============================================================
-- 인덱스
-- ============================================================
-- 공간 인덱스
CREATE INDEX idx_cst_srvy_zone_geom ON wing.cst_srvy_zone USING gist (geom);
CREATE INDEX idx_cst_sect_geom ON wing.cst_sect USING gist (geom);
-- 외래키/상태 인덱스
CREATE INDEX idx_cst_sect_zone ON wing.cst_sect USING btree (cst_srvy_zone_sn);
CREATE INDEX idx_cst_sect_stts ON wing.cst_sect USING btree (srvy_stts_cd);
CREATE INDEX idx_cst_sect_esi ON wing.cst_sect USING btree (esi_num);
-- SCAT 조사 인덱스
CREATE INDEX idx_scat_sect_sn ON wing.scat_srvy USING btree (cst_sect_sn);
CREATE INDEX idx_scat_acdnt_sn ON wing.scat_srvy USING btree (acdnt_sn);
CREATE INDEX idx_photo_srvy_sn ON wing.scat_srvy_photo USING btree (scat_srvy_sn);

파일 보기

@ -0,0 +1,128 @@
-- WING-OPS Database Schema: Boom & Backtrack Tables
-- wing 스키마 오일펜스/역추적/선박 테이블
-- ============================================================
-- 1. boom_line — 오일펜스배치
-- ============================================================
CREATE TABLE wing.boom_line (
boom_line_sn integer NOT NULL,
acdnt_sn integer NOT NULL,
boom_nm character varying(100),
priority_ord integer DEFAULT 0,
geom public.geometry(LineString,4326),
length_m numeric(8,1),
efficiency_pct numeric(5,1),
deploy_dtm timestamp with time zone,
stts_cd character varying(20) DEFAULT 'PLANNED'::character varying,
use_yn character(1) DEFAULT 'Y'::bpchar,
reg_dtm timestamp with time zone DEFAULT now(),
CONSTRAINT boom_line_pkey PRIMARY KEY (boom_line_sn),
CONSTRAINT ck_boom_stts CHECK (((stts_cd)::text = ANY (ARRAY[('PLANNED'::character varying)::text, ('DEPLOYED'::character varying)::text, ('RETRIEVED'::character varying)::text])))
);
CREATE SEQUENCE wing.boom_line_boom_line_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.boom_line_boom_line_sn_seq OWNED BY wing.boom_line.boom_line_sn;
ALTER TABLE ONLY wing.boom_line ALTER COLUMN boom_line_sn SET DEFAULT nextval('wing.boom_line_boom_line_sn_seq'::regclass);
-- ============================================================
-- 2. backtrack — 역추적분석
-- ============================================================
CREATE TABLE wing.backtrack (
backtrack_sn integer NOT NULL,
acdnt_sn integer NOT NULL,
est_spil_dtm timestamp with time zone,
anlys_range character varying(20),
lon numeric(10,6),
lat numeric(9,6),
geom public.geometry(Point,4326),
loc_dc character varying(100),
srch_radius_nm numeric(5,1),
total_vessels integer,
exec_stts_cd character varying(20) DEFAULT 'PENDING'::character varying,
rslt_data jsonb,
use_yn character(1) DEFAULT 'Y'::bpchar,
reg_dtm timestamp with time zone DEFAULT now(),
CONSTRAINT backtrack_pkey PRIMARY KEY (backtrack_sn),
CONSTRAINT ck_backtrack_stts CHECK (((exec_stts_cd)::text = ANY (ARRAY[('PENDING'::character varying)::text, ('RUNNING'::character varying)::text, ('COMPLETED'::character varying)::text, ('FAILED'::character varying)::text])))
);
CREATE SEQUENCE wing.backtrack_backtrack_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.backtrack_backtrack_sn_seq OWNED BY wing.backtrack.backtrack_sn;
ALTER TABLE ONLY wing.backtrack ALTER COLUMN backtrack_sn SET DEFAULT nextval('wing.backtrack_backtrack_sn_seq'::regclass);
-- ============================================================
-- 3. vessel_info — 선박정보
-- ============================================================
CREATE TABLE wing.vessel_info (
vessel_info_sn integer NOT NULL,
acdnt_sn integer NOT NULL,
imo_no character varying(10),
mmsi_no character varying(10),
vessel_nm character varying(100),
vessel_tp character varying(30),
loa_m numeric(6,1),
breadth_m numeric(5,1),
draft_m numeric(5,1),
gt numeric(10,0),
dwt numeric(10,0),
built_yr smallint,
flag_cd character varying(5),
callsign character varying(10),
engine_dc character varying(100),
insurance_data jsonb,
reg_dtm timestamp with time zone DEFAULT now(),
CONSTRAINT vessel_info_pkey PRIMARY KEY (vessel_info_sn)
);
CREATE SEQUENCE wing.vessel_info_vessel_info_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.vessel_info_vessel_info_sn_seq OWNED BY wing.vessel_info.vessel_info_sn;
ALTER TABLE ONLY wing.vessel_info ALTER COLUMN vessel_info_sn SET DEFAULT nextval('wing.vessel_info_vessel_info_sn_seq'::regclass);
-- ============================================================
-- FK 제약조건
-- ============================================================
ALTER TABLE ONLY wing.boom_line
ADD CONSTRAINT boom_line_acdnt_sn_fkey FOREIGN KEY (acdnt_sn) REFERENCES wing.acdnt(acdnt_sn) ON DELETE CASCADE;
ALTER TABLE ONLY wing.backtrack
ADD CONSTRAINT backtrack_acdnt_sn_fkey FOREIGN KEY (acdnt_sn) REFERENCES wing.acdnt(acdnt_sn) ON DELETE CASCADE;
ALTER TABLE ONLY wing.vessel_info
ADD CONSTRAINT vessel_info_acdnt_sn_fkey FOREIGN KEY (acdnt_sn) REFERENCES wing.acdnt(acdnt_sn) ON DELETE CASCADE;
-- ============================================================
-- 인덱스
-- ============================================================
-- 공간 인덱스
CREATE INDEX idx_boom_geom ON wing.boom_line USING gist (geom);
CREATE INDEX idx_backtrack_geom ON wing.backtrack USING gist (geom);
-- 외래키 인덱스
CREATE INDEX idx_boom_acdnt ON wing.boom_line USING btree (acdnt_sn);
CREATE INDEX idx_backtrack_acdnt ON wing.backtrack USING btree (acdnt_sn);
CREATE INDEX idx_vessel_acdnt ON wing.vessel_info USING btree (acdnt_sn);

파일 보기

@ -0,0 +1,130 @@
-- WING-OPS Database Schema: Asset Management Tables
-- wing 스키마: asset_org, asset_equip, asset_contact, asset_upload_log
-- ============================================================
-- 1. 자산 기관 (asset_org)
-- ============================================================
CREATE TABLE wing.asset_org (
org_sn integer NOT NULL,
org_tp character varying(30) NOT NULL,
jrsd_nm character varying(50) NOT NULL,
area_nm character varying(30) NOT NULL,
org_nm character varying(100) NOT NULL,
addr character varying(300),
tel character varying(30),
lat numeric(9,6),
lng numeric(10,6),
pin_size character varying(5) DEFAULT 'md'::character varying,
vessel_cnt smallint DEFAULT 0,
skimmer_cnt smallint DEFAULT 0,
pump_cnt smallint DEFAULT 0,
vehicle_cnt smallint DEFAULT 0,
sprayer_cnt smallint DEFAULT 0,
total_assets smallint DEFAULT 0,
use_yn character(1) DEFAULT 'Y'::bpchar,
reg_dtm timestamp with time zone DEFAULT now(),
mdfcn_dtm timestamp with time zone,
geom public.geometry(Point, 4326),
CONSTRAINT asset_org_pkey PRIMARY KEY (org_sn),
CONSTRAINT ck_asset_org_pin CHECK (
((pin_size)::text = ANY ((ARRAY['hq'::character varying, 'lg'::character varying, 'md'::character varying])::text[]))
)
);
CREATE SEQUENCE wing.asset_org_org_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.asset_org_org_sn_seq OWNED BY wing.asset_org.org_sn;
ALTER TABLE ONLY wing.asset_org ALTER COLUMN org_sn SET DEFAULT nextval('wing.asset_org_org_sn_seq'::regclass);
-- ============================================================
-- 2. 자산 장비 (asset_equip)
-- ============================================================
CREATE TABLE wing.asset_equip (
equip_sn integer NOT NULL,
org_sn integer NOT NULL,
ctgr_nm character varying(50) NOT NULL,
icon character varying(10),
qty smallint DEFAULT 0,
sort_ord smallint DEFAULT 0,
CONSTRAINT asset_equip_pkey PRIMARY KEY (equip_sn),
CONSTRAINT asset_equip_org_sn_ctgr_nm_key UNIQUE (org_sn, ctgr_nm)
);
CREATE SEQUENCE wing.asset_equip_equip_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.asset_equip_equip_sn_seq OWNED BY wing.asset_equip.equip_sn;
ALTER TABLE ONLY wing.asset_equip ALTER COLUMN equip_sn SET DEFAULT nextval('wing.asset_equip_equip_sn_seq'::regclass);
-- ============================================================
-- 3. 자산 연락처 (asset_contact)
-- ============================================================
CREATE TABLE wing.asset_contact (
contact_sn integer NOT NULL,
org_sn integer NOT NULL,
role_nm character varying(50),
contact_nm character varying(50),
tel character varying(30),
sort_ord smallint DEFAULT 0,
CONSTRAINT asset_contact_pkey PRIMARY KEY (contact_sn)
);
CREATE SEQUENCE wing.asset_contact_contact_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.asset_contact_contact_sn_seq OWNED BY wing.asset_contact.contact_sn;
ALTER TABLE ONLY wing.asset_contact ALTER COLUMN contact_sn SET DEFAULT nextval('wing.asset_contact_contact_sn_seq'::regclass);
-- ============================================================
-- 4. 자산 업로드 로그 (asset_upload_log)
-- ============================================================
CREATE TABLE wing.asset_upload_log (
log_sn integer NOT NULL,
file_nm character varying(200) NOT NULL,
uploader_nm character varying(50),
upload_cnt integer DEFAULT 0,
reg_dtm timestamp with time zone DEFAULT now(),
CONSTRAINT asset_upload_log_pkey PRIMARY KEY (log_sn)
);
CREATE SEQUENCE wing.asset_upload_log_log_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.asset_upload_log_log_sn_seq OWNED BY wing.asset_upload_log.log_sn;
ALTER TABLE ONLY wing.asset_upload_log ALTER COLUMN log_sn SET DEFAULT nextval('wing.asset_upload_log_log_sn_seq'::regclass);
-- ============================================================
-- FK 제약조건
-- ============================================================
ALTER TABLE ONLY wing.asset_equip
ADD CONSTRAINT asset_equip_org_sn_fkey
FOREIGN KEY (org_sn) REFERENCES wing.asset_org(org_sn) ON DELETE CASCADE;
ALTER TABLE ONLY wing.asset_contact
ADD CONSTRAINT asset_contact_org_sn_fkey
FOREIGN KEY (org_sn) REFERENCES wing.asset_org(org_sn) ON DELETE CASCADE;

파일 보기

@ -0,0 +1,109 @@
-- WING-OPS Database Schema: Board & Manual Tables
-- wing 스키마: board_post, board_attach, manual_file
-- 주의: board_post.author_id 는 auth.auth_user(user_id) 크로스스키마 FK
-- ============================================================
-- 1. 게시글 (board_post)
-- ============================================================
CREATE TABLE wing.board_post (
post_sn integer NOT NULL,
category_cd character varying(20) NOT NULL,
title character varying(200) NOT NULL,
content text,
author_id uuid NOT NULL,
view_cnt integer DEFAULT 0 NOT NULL,
pinned_yn character(1) DEFAULT 'N'::bpchar NOT NULL,
use_yn character(1) DEFAULT 'Y'::bpchar NOT NULL,
reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
mdfcn_dtm timestamp with time zone,
CONSTRAINT board_post_pkey PRIMARY KEY (post_sn),
CONSTRAINT ck_board_category CHECK (
((category_cd)::text = ANY ((ARRAY['NOTICE'::character varying, 'DATA'::character varying, 'QNA'::character varying, 'MANUAL'::character varying])::text[]))
),
CONSTRAINT ck_board_pinned CHECK ((pinned_yn = ANY (ARRAY['Y'::bpchar, 'N'::bpchar]))),
CONSTRAINT ck_board_use CHECK ((use_yn = ANY (ARRAY['Y'::bpchar, 'N'::bpchar])))
);
CREATE SEQUENCE wing.board_post_post_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.board_post_post_sn_seq OWNED BY wing.board_post.post_sn;
ALTER TABLE ONLY wing.board_post ALTER COLUMN post_sn SET DEFAULT nextval('wing.board_post_post_sn_seq'::regclass);
-- ============================================================
-- 2. 첨부파일 (board_attach)
-- ============================================================
CREATE TABLE wing.board_attach (
attach_sn integer NOT NULL,
post_sn integer NOT NULL,
file_nm character varying(200) NOT NULL,
orgnl_nm character varying(200),
file_path character varying(500),
file_sz integer,
file_ext character varying(10),
sort_ord integer DEFAULT 0,
reg_dtm timestamp with time zone DEFAULT now(),
CONSTRAINT board_attach_pkey PRIMARY KEY (attach_sn)
);
CREATE SEQUENCE wing.board_attach_attach_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.board_attach_attach_sn_seq OWNED BY wing.board_attach.attach_sn;
ALTER TABLE ONLY wing.board_attach ALTER COLUMN attach_sn SET DEFAULT nextval('wing.board_attach_attach_sn_seq'::regclass);
-- ============================================================
-- 3. 매뉴얼 파일 (manual_file)
-- ============================================================
CREATE TABLE wing.manual_file (
manual_sn integer NOT NULL,
catg_nm character varying(50),
title character varying(200) NOT NULL,
version character varying(20),
file_tp character varying(20),
file_sz character varying(20),
file_path character varying(500),
author_nm character varying(50),
dwnld_cnt integer DEFAULT 0,
use_yn character(1) DEFAULT 'Y'::bpchar,
reg_dtm timestamp with time zone DEFAULT now(),
mdfcn_dtm timestamp with time zone DEFAULT now(),
CONSTRAINT manual_file_pkey PRIMARY KEY (manual_sn)
);
CREATE SEQUENCE wing.manual_file_manual_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.manual_file_manual_sn_seq OWNED BY wing.manual_file.manual_sn;
ALTER TABLE ONLY wing.manual_file ALTER COLUMN manual_sn SET DEFAULT nextval('wing.manual_file_manual_sn_seq'::regclass);
-- ============================================================
-- FK 제약조건
-- ============================================================
-- 크로스스키마 FK: board_post.author_id → auth.auth_user(user_id)
ALTER TABLE ONLY wing.board_post
ADD CONSTRAINT fk_board_author
FOREIGN KEY (author_id) REFERENCES auth.auth_user(user_id);
-- 동일스키마 FK: board_attach.post_sn → board_post
ALTER TABLE ONLY wing.board_attach
ADD CONSTRAINT board_attach_post_sn_fkey
FOREIGN KEY (post_sn) REFERENCES wing.board_post(post_sn) ON DELETE CASCADE;

파일 보기

@ -0,0 +1,235 @@
-- WING-OPS Database Schema: Report Tables
-- wing 스키마: report_tmpl, report_tmpl_sect, report_analysis_ctgr,
-- report_ctgr_tmpl, report_ctgr_sect, report, report_sect_data
-- FK 의존성 순서: report_tmpl, report_analysis_ctgr → report → report_sect_data
-- ============================================================
-- 1. 보고서 템플릿 (report_tmpl)
-- ============================================================
CREATE TABLE wing.report_tmpl (
tmpl_sn integer NOT NULL,
tmpl_cd character varying(30) NOT NULL,
tmpl_nm character varying(100) NOT NULL,
icon character varying(10),
tmpl_dc character varying(500),
sort_ord smallint DEFAULT 0,
use_yn character(1) DEFAULT 'Y'::bpchar,
reg_dtm timestamp with time zone DEFAULT now(),
CONSTRAINT report_tmpl_pkey PRIMARY KEY (tmpl_sn),
CONSTRAINT report_tmpl_tmpl_cd_key UNIQUE (tmpl_cd)
);
CREATE SEQUENCE wing.report_tmpl_tmpl_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.report_tmpl_tmpl_sn_seq OWNED BY wing.report_tmpl.tmpl_sn;
ALTER TABLE ONLY wing.report_tmpl ALTER COLUMN tmpl_sn SET DEFAULT nextval('wing.report_tmpl_tmpl_sn_seq'::regclass);
-- ============================================================
-- 2. 템플릿 섹션 (report_tmpl_sect)
-- ============================================================
CREATE TABLE wing.report_tmpl_sect (
sect_sn integer NOT NULL,
tmpl_sn integer NOT NULL,
sect_cd character varying(50) NOT NULL,
sect_nm character varying(100) NOT NULL,
field_def jsonb NOT NULL,
sort_ord smallint DEFAULT 0,
use_yn character(1) DEFAULT 'Y'::bpchar,
CONSTRAINT report_tmpl_sect_pkey PRIMARY KEY (sect_sn),
CONSTRAINT report_tmpl_sect_tmpl_sn_sect_cd_key UNIQUE (tmpl_sn, sect_cd)
);
CREATE SEQUENCE wing.report_tmpl_sect_sect_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.report_tmpl_sect_sect_sn_seq OWNED BY wing.report_tmpl_sect.sect_sn;
ALTER TABLE ONLY wing.report_tmpl_sect ALTER COLUMN sect_sn SET DEFAULT nextval('wing.report_tmpl_sect_sect_sn_seq'::regclass);
-- ============================================================
-- 3. 분석 카테고리 (report_analysis_ctgr)
-- ============================================================
CREATE TABLE wing.report_analysis_ctgr (
ctgr_sn integer NOT NULL,
ctgr_cd character varying(30) NOT NULL,
ctgr_nm character varying(100) NOT NULL,
icon character varying(10),
ctgr_dc character varying(500),
color_cd character varying(30),
border_color character varying(50),
bg_active character varying(50),
report_nm character varying(100),
sort_ord smallint DEFAULT 0,
use_yn character(1) DEFAULT 'Y'::bpchar,
CONSTRAINT report_analysis_ctgr_pkey PRIMARY KEY (ctgr_sn),
CONSTRAINT report_analysis_ctgr_ctgr_cd_key UNIQUE (ctgr_cd)
);
CREATE SEQUENCE wing.report_analysis_ctgr_ctgr_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.report_analysis_ctgr_ctgr_sn_seq OWNED BY wing.report_analysis_ctgr.ctgr_sn;
ALTER TABLE ONLY wing.report_analysis_ctgr ALTER COLUMN ctgr_sn SET DEFAULT nextval('wing.report_analysis_ctgr_ctgr_sn_seq'::regclass);
-- ============================================================
-- 4. 카테고리 템플릿 (report_ctgr_tmpl)
-- ============================================================
CREATE TABLE wing.report_ctgr_tmpl (
ctgr_tmpl_sn integer NOT NULL,
ctgr_sn integer NOT NULL,
icon character varying(10),
label character varying(50) NOT NULL,
sort_ord smallint DEFAULT 0,
CONSTRAINT report_ctgr_tmpl_pkey PRIMARY KEY (ctgr_tmpl_sn)
);
CREATE SEQUENCE wing.report_ctgr_tmpl_ctgr_tmpl_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.report_ctgr_tmpl_ctgr_tmpl_sn_seq OWNED BY wing.report_ctgr_tmpl.ctgr_tmpl_sn;
ALTER TABLE ONLY wing.report_ctgr_tmpl ALTER COLUMN ctgr_tmpl_sn SET DEFAULT nextval('wing.report_ctgr_tmpl_ctgr_tmpl_sn_seq'::regclass);
-- ============================================================
-- 5. 카테고리 섹션 (report_ctgr_sect)
-- ============================================================
CREATE TABLE wing.report_ctgr_sect (
sect_sn integer NOT NULL,
ctgr_sn integer NOT NULL,
sect_cd character varying(50) NOT NULL,
sect_nm character varying(100) NOT NULL,
icon character varying(10),
sect_dc character varying(200),
dflt_yn character(1) DEFAULT 'Y'::bpchar,
sort_ord smallint DEFAULT 0,
CONSTRAINT report_ctgr_sect_pkey PRIMARY KEY (sect_sn),
CONSTRAINT report_ctgr_sect_ctgr_sn_sect_cd_key UNIQUE (ctgr_sn, sect_cd)
);
CREATE SEQUENCE wing.report_ctgr_sect_sect_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.report_ctgr_sect_sect_sn_seq OWNED BY wing.report_ctgr_sect.sect_sn;
ALTER TABLE ONLY wing.report_ctgr_sect ALTER COLUMN sect_sn SET DEFAULT nextval('wing.report_ctgr_sect_sect_sn_seq'::regclass);
-- ============================================================
-- 6. 보고서 (report)
-- 의존: report_tmpl, report_analysis_ctgr, auth.auth_user, wing.acdnt
-- ============================================================
CREATE TABLE wing.report (
report_sn integer NOT NULL,
tmpl_sn integer,
ctgr_sn integer,
acdnt_sn integer,
title character varying(200) NOT NULL,
jrsd_cd character varying(20),
stts_cd character varying(20) DEFAULT 'DRAFT'::character varying,
author_id uuid NOT NULL,
use_yn character(1) DEFAULT 'Y'::bpchar,
reg_dtm timestamp with time zone DEFAULT now(),
mdfcn_dtm timestamp with time zone,
CONSTRAINT report_pkey PRIMARY KEY (report_sn),
CONSTRAINT ck_report_status CHECK (
((stts_cd)::text = ANY ((ARRAY['DRAFT'::character varying, 'IN_PROGRESS'::character varying, 'COMPLETED'::character varying])::text[]))
)
);
CREATE SEQUENCE wing.report_report_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.report_report_sn_seq OWNED BY wing.report.report_sn;
ALTER TABLE ONLY wing.report ALTER COLUMN report_sn SET DEFAULT nextval('wing.report_report_sn_seq'::regclass);
-- ============================================================
-- 7. 보고서 섹션 데이터 (report_sect_data)
-- 의존: report
-- ============================================================
CREATE TABLE wing.report_sect_data (
data_sn integer NOT NULL,
report_sn integer NOT NULL,
sect_cd character varying(50) NOT NULL,
include_yn character(1) DEFAULT 'Y'::bpchar,
sect_data jsonb DEFAULT '{}'::jsonb NOT NULL,
sort_ord smallint DEFAULT 0,
CONSTRAINT report_sect_data_pkey PRIMARY KEY (data_sn),
CONSTRAINT report_sect_data_report_sn_sect_cd_key UNIQUE (report_sn, sect_cd)
);
CREATE SEQUENCE wing.report_sect_data_data_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.report_sect_data_data_sn_seq OWNED BY wing.report_sect_data.data_sn;
ALTER TABLE ONLY wing.report_sect_data ALTER COLUMN data_sn SET DEFAULT nextval('wing.report_sect_data_data_sn_seq'::regclass);
-- ============================================================
-- FK 제약조건
-- ============================================================
ALTER TABLE ONLY wing.report_tmpl_sect
ADD CONSTRAINT report_tmpl_sect_tmpl_sn_fkey
FOREIGN KEY (tmpl_sn) REFERENCES wing.report_tmpl(tmpl_sn);
ALTER TABLE ONLY wing.report_ctgr_tmpl
ADD CONSTRAINT report_ctgr_tmpl_ctgr_sn_fkey
FOREIGN KEY (ctgr_sn) REFERENCES wing.report_analysis_ctgr(ctgr_sn);
ALTER TABLE ONLY wing.report_ctgr_sect
ADD CONSTRAINT report_ctgr_sect_ctgr_sn_fkey
FOREIGN KEY (ctgr_sn) REFERENCES wing.report_analysis_ctgr(ctgr_sn);
-- 크로스스키마 FK: report.author_id → auth.auth_user
ALTER TABLE ONLY wing.report
ADD CONSTRAINT report_author_id_fkey
FOREIGN KEY (author_id) REFERENCES auth.auth_user(user_id);
ALTER TABLE ONLY wing.report
ADD CONSTRAINT report_tmpl_sn_fkey
FOREIGN KEY (tmpl_sn) REFERENCES wing.report_tmpl(tmpl_sn);
ALTER TABLE ONLY wing.report
ADD CONSTRAINT report_ctgr_sn_fkey
FOREIGN KEY (ctgr_sn) REFERENCES wing.report_analysis_ctgr(ctgr_sn);
ALTER TABLE ONLY wing.report_sect_data
ADD CONSTRAINT report_sect_data_report_sn_fkey
FOREIGN KEY (report_sn) REFERENCES wing.report(report_sn) ON DELETE CASCADE;

파일 보기

@ -0,0 +1,217 @@
-- WING-OPS Database Schema: Aerial & Rescue Tables
-- wing 스키마: aerial_media, cctv_camera, sat_request, rescue_ops, rescue_scenario
-- FK 의존성: rescue_scenario → rescue_ops
-- ============================================================
-- 1. 항공 미디어 (aerial_media)
-- ============================================================
CREATE TABLE wing.aerial_media (
aerial_media_sn integer NOT NULL,
acdnt_sn integer,
file_nm character varying(200) NOT NULL,
orgnl_nm character varying(200),
file_path character varying(500),
lon numeric(10,6),
lat numeric(9,6),
geom public.geometry(Point, 4326),
loc_dc character varying(100),
equip_tp_cd character varying(20),
equip_nm character varying(50),
media_tp_cd character varying(20),
takng_dtm timestamp with time zone,
file_sz character varying(20),
resolution character varying(30),
use_yn character(1) DEFAULT 'Y'::bpchar,
reg_dtm timestamp with time zone DEFAULT now(),
CONSTRAINT aerial_media_pkey PRIMARY KEY (aerial_media_sn)
);
CREATE SEQUENCE wing.aerial_media_aerial_media_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.aerial_media_aerial_media_sn_seq OWNED BY wing.aerial_media.aerial_media_sn;
ALTER TABLE ONLY wing.aerial_media ALTER COLUMN aerial_media_sn SET DEFAULT nextval('wing.aerial_media_aerial_media_sn_seq'::regclass);
-- ============================================================
-- 2. CCTV 카메라 (cctv_camera)
-- ============================================================
CREATE TABLE wing.cctv_camera (
cctv_sn integer NOT NULL,
camera_nm character varying(100) NOT NULL,
region_nm character varying(20),
lon numeric(10,6),
lat numeric(9,6),
geom public.geometry(Point, 4326),
loc_dc character varying(200),
coord_dc character varying(50),
stts_cd character varying(20) DEFAULT 'LIVE'::character varying,
ptz_yn character(1) DEFAULT 'N'::bpchar,
source_nm character varying(50),
stream_url character varying(500),
use_yn character(1) DEFAULT 'Y'::bpchar,
reg_dtm timestamp with time zone DEFAULT now(),
CONSTRAINT cctv_camera_pkey PRIMARY KEY (cctv_sn)
);
CREATE SEQUENCE wing.cctv_camera_cctv_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.cctv_camera_cctv_sn_seq OWNED BY wing.cctv_camera.cctv_sn;
ALTER TABLE ONLY wing.cctv_camera ALTER COLUMN cctv_sn SET DEFAULT nextval('wing.cctv_camera_cctv_sn_seq'::regclass);
-- ============================================================
-- 3. 위성 촬영 요청 (sat_request)
-- ============================================================
CREATE TABLE wing.sat_request (
sat_req_sn integer NOT NULL,
req_cd character varying(20) NOT NULL,
acdnt_sn integer,
lon numeric(10,6),
lat numeric(9,6),
geom public.geometry(Point, 4326),
zone_dc character varying(200),
coord_dc character varying(50),
zone_area_km2 numeric(8,2),
sat_nm character varying(50),
provider_nm character varying(50),
resolution character varying(20),
purpose_dc character varying(200),
reqstr_nm character varying(50),
req_dtm timestamp with time zone,
expected_rcv_dtm timestamp with time zone,
stts_cd character varying(20) DEFAULT 'PENDING'::character varying,
use_yn character(1) DEFAULT 'Y'::bpchar,
reg_dtm timestamp with time zone DEFAULT now(),
CONSTRAINT sat_request_pkey PRIMARY KEY (sat_req_sn),
CONSTRAINT sat_request_req_cd_key UNIQUE (req_cd),
CONSTRAINT ck_sat_stts CHECK (
((stts_cd)::text = ANY ((ARRAY['PENDING'::character varying, 'SHOOTING'::character varying, 'COMPLETED'::character varying, 'CANCELLED'::character varying])::text[]))
)
);
CREATE SEQUENCE wing.sat_request_sat_req_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.sat_request_sat_req_sn_seq OWNED BY wing.sat_request.sat_req_sn;
ALTER TABLE ONLY wing.sat_request ALTER COLUMN sat_req_sn SET DEFAULT nextval('wing.sat_request_sat_req_sn_seq'::regclass);
-- ============================================================
-- 4. 구조 작전 (rescue_ops)
-- ============================================================
CREATE TABLE wing.rescue_ops (
rescue_ops_sn integer NOT NULL,
acdnt_sn integer,
ops_cd character varying(20) NOT NULL,
acdnt_tp_cd character varying(20),
vessel_nm character varying(100),
commander_nm character varying(50),
lon numeric(10,6),
lat numeric(9,6),
geom public.geometry(Point, 4326),
loc_dc character varying(100),
depth_m numeric(6,1),
current_dc character varying(50),
gm_m numeric(5,2),
list_deg numeric(5,1),
trim_m numeric(5,2),
buoyancy_pct numeric(5,1),
oil_rate_lpm numeric(8,1),
bm_ratio_pct numeric(5,1),
total_crew integer,
survivors integer,
missing integer,
hydro_data jsonb,
gmdss_data jsonb,
stts_cd character varying(20) DEFAULT 'ACTIVE'::character varying,
use_yn character(1) DEFAULT 'Y'::bpchar,
reg_dtm timestamp with time zone DEFAULT now(),
mdfcn_dtm timestamp with time zone DEFAULT now(),
CONSTRAINT rescue_ops_pkey PRIMARY KEY (rescue_ops_sn),
CONSTRAINT rescue_ops_ops_cd_key UNIQUE (ops_cd)
);
CREATE SEQUENCE wing.rescue_ops_rescue_ops_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.rescue_ops_rescue_ops_sn_seq OWNED BY wing.rescue_ops.rescue_ops_sn;
ALTER TABLE ONLY wing.rescue_ops ALTER COLUMN rescue_ops_sn SET DEFAULT nextval('wing.rescue_ops_rescue_ops_sn_seq'::regclass);
-- ============================================================
-- 5. 구조 시나리오 (rescue_scenario)
-- 의존: rescue_ops
-- ============================================================
CREATE TABLE wing.rescue_scenario (
scenario_sn integer NOT NULL,
rescue_ops_sn integer NOT NULL,
time_step character varying(10) NOT NULL,
scenario_dtm timestamp with time zone,
svrt_cd character varying(20),
gm_m numeric(5,2),
list_deg numeric(5,1),
trim_m numeric(5,2),
buoyancy_pct numeric(5,1),
oil_rate_lpm numeric(8,1),
bm_ratio_pct numeric(5,1),
description text,
compartments jsonb,
assessment jsonb,
actions jsonb,
sort_ord integer DEFAULT 0,
reg_dtm timestamp with time zone DEFAULT now(),
CONSTRAINT rescue_scenario_pkey PRIMARY KEY (scenario_sn)
);
CREATE SEQUENCE wing.rescue_scenario_scenario_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.rescue_scenario_scenario_sn_seq OWNED BY wing.rescue_scenario.scenario_sn;
ALTER TABLE ONLY wing.rescue_scenario ALTER COLUMN scenario_sn SET DEFAULT nextval('wing.rescue_scenario_scenario_sn_seq'::regclass);
-- ============================================================
-- FK 제약조건
-- ============================================================
ALTER TABLE ONLY wing.aerial_media
ADD CONSTRAINT aerial_media_acdnt_sn_fkey
FOREIGN KEY (acdnt_sn) REFERENCES wing.acdnt(acdnt_sn);
ALTER TABLE ONLY wing.sat_request
ADD CONSTRAINT sat_request_acdnt_sn_fkey
FOREIGN KEY (acdnt_sn) REFERENCES wing.acdnt(acdnt_sn);
ALTER TABLE ONLY wing.rescue_ops
ADD CONSTRAINT rescue_ops_acdnt_sn_fkey
FOREIGN KEY (acdnt_sn) REFERENCES wing.acdnt(acdnt_sn);
ALTER TABLE ONLY wing.rescue_scenario
ADD CONSTRAINT rescue_scenario_rescue_ops_sn_fkey
FOREIGN KEY (rescue_ops_sn) REFERENCES wing.rescue_ops(rescue_ops_sn) ON DELETE CASCADE;

파일 보기

@ -0,0 +1,190 @@
-- WING-OPS Database Schema: Incidents Tables
-- wing 스키마: acdnt, spil_data, pred_exec, acdnt_weather, acdnt_media
-- 출처: pg_dump 현행 DDL (migration/009_incidents.sql 기반, wing 스키마 적용)
-- 주의: pg_dump 기준 acdnt에는 loc_geom(geometry) 컬럼이 추가되어 있음
-- ============================================================
-- 1. 사고 (acdnt)
-- ============================================================
CREATE TABLE wing.acdnt (
acdnt_sn integer NOT NULL,
acdnt_cd character varying(20) NOT NULL,
acdnt_nm character varying(200) NOT NULL,
acdnt_tp_cd character varying(50) NOT NULL,
acdnt_stts_cd character varying(20) NOT NULL DEFAULT 'ACTIVE'::character varying,
lat numeric(9,6),
lng numeric(10,6),
loc_dc character varying(200),
occrn_dtm timestamp with time zone NOT NULL,
rpt_dtm timestamp with time zone,
region_nm character varying(20),
office_nm character varying(30),
svrt_cd character varying(10),
vessel_tp character varying(30),
phase_cd character varying(20) DEFAULT 'RESPONSE'::character varying,
analyst_nm character varying(50),
rgtr_id uuid,
use_yn character(1) DEFAULT 'Y'::bpchar,
reg_dtm timestamp with time zone NOT NULL DEFAULT now(),
mdfcn_dtm timestamp with time zone,
loc_geom public.geometry(Point, 4326),
CONSTRAINT pk_acdnt PRIMARY KEY (acdnt_sn),
CONSTRAINT uk_acdnt_cd UNIQUE (acdnt_cd),
CONSTRAINT ck_acdnt_stts CHECK (((acdnt_stts_cd)::text = ANY ((ARRAY['ACTIVE'::character varying, 'INVESTIGATING'::character varying, 'CLOSED'::character varying])::text[]))),
CONSTRAINT ck_acdnt_svrt CHECK (((svrt_cd IS NULL) OR ((svrt_cd)::text = ANY ((ARRAY['DANGER'::character varying, 'ALERT'::character varying, 'CAUTION'::character varying, 'INTEREST'::character varying])::text[])))),
CONSTRAINT ck_acdnt_phase CHECK (((phase_cd IS NULL) OR ((phase_cd)::text = ANY ((ARRAY['RESPONSE'::character varying, 'STANDBY'::character varying, 'CLOSED'::character varying])::text[]))))
);
CREATE SEQUENCE wing.acdnt_acdnt_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.acdnt_acdnt_sn_seq OWNED BY wing.acdnt.acdnt_sn;
ALTER TABLE ONLY wing.acdnt ALTER COLUMN acdnt_sn SET DEFAULT nextval('wing.acdnt_acdnt_sn_seq'::regclass);
-- ============================================================
-- 2. 유출정보 (spil_data)
-- ============================================================
CREATE TABLE wing.spil_data (
spil_data_sn integer NOT NULL,
acdnt_sn integer NOT NULL,
oil_tp_cd character varying(50) NOT NULL,
spil_qty numeric(12,2),
spil_unit_cd character varying(10) DEFAULT 'KL'::character varying,
spil_tp_cd character varying(20),
fcst_hr integer,
reg_dtm timestamp with time zone NOT NULL DEFAULT now(),
CONSTRAINT pk_spil_data PRIMARY KEY (spil_data_sn)
);
CREATE SEQUENCE wing.spil_data_spil_data_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.spil_data_spil_data_sn_seq OWNED BY wing.spil_data.spil_data_sn;
ALTER TABLE ONLY wing.spil_data ALTER COLUMN spil_data_sn SET DEFAULT nextval('wing.spil_data_spil_data_sn_seq'::regclass);
-- ============================================================
-- 3. 예측 실행 (pred_exec)
-- ============================================================
CREATE TABLE wing.pred_exec (
pred_exec_sn integer NOT NULL,
acdnt_sn integer NOT NULL,
algo_cd character varying(20) NOT NULL,
exec_stts_cd character varying(20) NOT NULL DEFAULT 'PENDING'::character varying,
bgng_dtm timestamp with time zone,
cmpl_dtm timestamp with time zone,
reqd_sec integer,
rslt_data jsonb,
err_msg text,
CONSTRAINT pk_pred_exec PRIMARY KEY (pred_exec_sn),
CONSTRAINT ck_pred_stts CHECK (((exec_stts_cd)::text = ANY ((ARRAY['PENDING'::character varying, 'RUNNING'::character varying, 'COMPLETED'::character varying, 'FAILED'::character varying])::text[])))
);
CREATE SEQUENCE wing.pred_exec_pred_exec_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.pred_exec_pred_exec_sn_seq OWNED BY wing.pred_exec.pred_exec_sn;
ALTER TABLE ONLY wing.pred_exec ALTER COLUMN pred_exec_sn SET DEFAULT nextval('wing.pred_exec_pred_exec_sn_seq'::regclass);
-- ============================================================
-- 4. 사고별 기상정보 스냅샷 (acdnt_weather)
-- ============================================================
CREATE TABLE wing.acdnt_weather (
weather_sn integer NOT NULL,
acdnt_sn integer NOT NULL,
loc_nm character varying(100),
obs_dtm timestamp with time zone,
icon character varying(10),
temp character varying(20),
weather_dc character varying(50),
wind character varying(30),
wave character varying(20),
humid character varying(20),
vis character varying(20),
sst character varying(20),
tide character varying(30),
high_tide character varying(30),
low_tide character varying(30),
forecast jsonb,
impact_dc text,
reg_dtm timestamp with time zone DEFAULT now(),
CONSTRAINT acdnt_weather_pkey PRIMARY KEY (weather_sn)
);
CREATE SEQUENCE wing.acdnt_weather_weather_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.acdnt_weather_weather_sn_seq OWNED BY wing.acdnt_weather.weather_sn;
ALTER TABLE ONLY wing.acdnt_weather ALTER COLUMN weather_sn SET DEFAULT nextval('wing.acdnt_weather_weather_sn_seq'::regclass);
-- ============================================================
-- 5. 사고별 미디어 메타데이터 (acdnt_media)
-- ============================================================
CREATE TABLE wing.acdnt_media (
media_sn integer NOT NULL,
acdnt_sn integer NOT NULL,
photo_cnt smallint DEFAULT 0,
video_cnt smallint DEFAULT 0,
sat_cnt smallint DEFAULT 0,
cctv_cnt smallint DEFAULT 0,
photo_meta jsonb,
drone_meta jsonb,
sat_meta jsonb,
cctv_meta jsonb,
reg_dtm timestamp with time zone DEFAULT now(),
CONSTRAINT acdnt_media_pkey PRIMARY KEY (media_sn)
);
CREATE SEQUENCE wing.acdnt_media_media_sn_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE wing.acdnt_media_media_sn_seq OWNED BY wing.acdnt_media.media_sn;
ALTER TABLE ONLY wing.acdnt_media ALTER COLUMN media_sn SET DEFAULT nextval('wing.acdnt_media_media_sn_seq'::regclass);
-- ============================================================
-- FK 제약조건
-- ============================================================
ALTER TABLE ONLY wing.spil_data
ADD CONSTRAINT fk_spil_acdnt
FOREIGN KEY (acdnt_sn) REFERENCES wing.acdnt(acdnt_sn) ON DELETE CASCADE;
ALTER TABLE ONLY wing.pred_exec
ADD CONSTRAINT fk_pred_acdnt
FOREIGN KEY (acdnt_sn) REFERENCES wing.acdnt(acdnt_sn) ON DELETE CASCADE;
ALTER TABLE ONLY wing.acdnt_weather
ADD CONSTRAINT acdnt_weather_acdnt_sn_fkey
FOREIGN KEY (acdnt_sn) REFERENCES wing.acdnt(acdnt_sn) ON DELETE CASCADE;
ALTER TABLE ONLY wing.acdnt_media
ADD CONSTRAINT acdnt_media_acdnt_sn_fkey
FOREIGN KEY (acdnt_sn) REFERENCES wing.acdnt(acdnt_sn) ON DELETE CASCADE;

파일 보기

@ -0,0 +1,135 @@
-- WING-OPS Database Schema: Additional Indexes
-- 01~12 파일의 PK/UNIQUE 제약조건을 제외한 추가 인덱스 모음
-- (CREATE INDEX 만 포함, ALTER TABLE ... ADD CONSTRAINT 형태의 UNIQUE는 각 테이블 파일에 포함)
-- ============================================================
-- auth 스키마 인덱스
-- ============================================================
-- auth_audit_log
CREATE INDEX idx_audit_log_action ON auth.auth_audit_log USING btree (action_cd);
CREATE INDEX idx_audit_log_dtm ON auth.auth_audit_log USING btree (req_dtm);
CREATE INDEX idx_audit_log_user ON auth.auth_audit_log USING btree (user_id);
-- auth_login_hist
CREATE INDEX idx_auth_login_dtm ON auth.auth_login_hist USING btree (login_dtm);
CREATE INDEX idx_auth_login_user ON auth.auth_login_hist USING btree (user_id);
-- auth_perm
CREATE INDEX idx_auth_perm_oper ON auth.auth_perm USING btree (oper_cd);
CREATE INDEX idx_auth_perm_role ON auth.auth_perm USING btree (role_sn);
CREATE INDEX idx_auth_perm_rsrc ON auth.auth_perm USING btree (rsrc_cd);
-- auth_user
CREATE INDEX idx_auth_user_org ON auth.auth_user USING btree (org_sn);
CREATE INDEX idx_auth_user_stts ON auth.auth_user USING btree (user_stts_cd);
-- auth_perm_tree
CREATE INDEX idx_perm_tree_parent ON auth.auth_perm_tree USING btree (parent_cd);
-- auth_user — 부분 유니크 인덱스 (조건부)
CREATE UNIQUE INDEX uk_auth_user_email ON auth.auth_user USING btree (email)
WHERE (email IS NOT NULL);
CREATE UNIQUE INDEX uk_auth_user_oauth ON auth.auth_user USING btree (oauth_provider, oauth_sub)
WHERE (oauth_provider IS NOT NULL);
-- ============================================================
-- wing 스키마 인덱스 — GiST 공간 인덱스
-- ============================================================
CREATE INDEX idx_acdnt_loc_geom ON wing.acdnt USING gist (loc_geom);
CREATE INDEX idx_aerial_media_geom ON wing.aerial_media USING gist (geom);
CREATE INDEX idx_asset_org_geom ON wing.asset_org USING gist (geom);
CREATE INDEX idx_backtrack_geom ON wing.backtrack USING gist (geom);
CREATE INDEX idx_boom_geom ON wing.boom_line USING gist (geom);
CREATE INDEX idx_cctv_geom ON wing.cctv_camera USING gist (geom);
CREATE INDEX idx_cst_sect_geom ON wing.cst_sect USING gist (geom);
CREATE INDEX idx_cst_srvy_zone_geom ON wing.cst_srvy_zone USING gist (geom);
CREATE INDEX idx_rescue_ops_geom ON wing.rescue_ops USING gist (geom);
CREATE INDEX idx_sat_req_geom ON wing.sat_request USING gist (geom);
-- ============================================================
-- wing 스키마 인덱스 — GIN (전문검색 / jsonb)
-- ============================================================
CREATE INDEX idx_hns_sbst_abbr ON wing.hns_substance USING gin (abbreviation public.gin_trgm_ops);
CREATE INDEX idx_hns_sbst_nm_en ON wing.hns_substance USING gin (nm_en public.gin_trgm_ops);
CREATE INDEX idx_hns_sbst_nm_kr ON wing.hns_substance USING gin (nm_kr public.gin_trgm_ops);
CREATE INDEX idx_hns_sbst_data ON wing.hns_substance USING gin (data jsonb_path_ops);
-- ============================================================
-- wing 스키마 인덱스 — btree
-- ============================================================
-- acdnt
CREATE INDEX idx_acdnt_occrn ON wing.acdnt USING btree (occrn_dtm DESC);
CREATE INDEX idx_acdnt_region ON wing.acdnt USING btree (region_nm);
CREATE INDEX idx_acdnt_stts ON wing.acdnt USING btree (acdnt_stts_cd);
-- aerial_media
CREATE INDEX idx_aerial_media_acdnt ON wing.aerial_media USING btree (acdnt_sn);
-- asset_org
CREATE INDEX idx_asset_org_jrsd ON wing.asset_org USING btree (jrsd_nm);
CREATE INDEX idx_asset_org_tp ON wing.asset_org USING btree (org_tp);
-- asset_equip / asset_contact
CREATE INDEX idx_asset_equip_org ON wing.asset_equip USING btree (org_sn);
CREATE INDEX idx_asset_contact_org ON wing.asset_contact USING btree (org_sn);
-- backtrack
CREATE INDEX idx_backtrack_acdnt ON wing.backtrack USING btree (acdnt_sn);
-- board_post
CREATE INDEX idx_board_author ON wing.board_post USING btree (author_id);
CREATE INDEX idx_board_category ON wing.board_post USING btree (category_cd);
CREATE INDEX idx_board_reg_dtm ON wing.board_post USING btree (reg_dtm DESC);
-- boom_line
CREATE INDEX idx_boom_acdnt ON wing.boom_line USING btree (acdnt_sn);
-- cst_sect
CREATE INDEX idx_cst_sect_esi ON wing.cst_sect USING btree (esi_num);
CREATE INDEX idx_cst_sect_stts ON wing.cst_sect USING btree (srvy_stts_cd);
CREATE INDEX idx_cst_sect_zone ON wing.cst_sect USING btree (cst_srvy_zone_sn);
-- hns_substance (btree)
CREATE INDEX idx_hns_sbst_cas ON wing.hns_substance USING btree (cas_no);
CREATE INDEX idx_hns_sbst_sebc ON wing.hns_substance USING btree (sebc);
CREATE INDEX idx_hns_sbst_un ON wing.hns_substance USING btree (un_no);
-- layer
CREATE INDEX idx_layer_level ON wing.layer USING btree (layer_level);
CREATE INDEX idx_layer_up ON wing.layer USING btree (up_layer_cd);
CREATE INDEX idx_layer_use ON wing.layer USING btree (use_yn);
-- acdnt_media
CREATE INDEX idx_media_acdnt ON wing.acdnt_media USING btree (acdnt_sn);
-- pred_exec
CREATE INDEX idx_pred_acdnt ON wing.pred_exec USING btree (acdnt_sn);
-- report
CREATE INDEX idx_report_author ON wing.report USING btree (author_id);
CREATE INDEX idx_report_ctgr ON wing.report USING btree (ctgr_sn);
CREATE INDEX idx_report_reg_dtm ON wing.report USING btree (reg_dtm DESC);
CREATE INDEX idx_report_stts ON wing.report USING btree (stts_cd);
CREATE INDEX idx_report_tmpl ON wing.report USING btree (tmpl_sn);
-- report_sect_data
CREATE INDEX idx_report_sect_report ON wing.report_sect_data USING btree (report_sn);
-- rescue_ops / rescue_scenario
CREATE INDEX idx_rescue_ops_acdnt ON wing.rescue_ops USING btree (acdnt_sn);
CREATE INDEX idx_rescue_scenario_ops ON wing.rescue_scenario USING btree (rescue_ops_sn);
-- spil_data
CREATE INDEX idx_spil_acdnt ON wing.spil_data USING btree (acdnt_sn);
-- vessel_info
CREATE INDEX idx_vessel_acdnt ON wing.vessel_info USING btree (acdnt_sn);
-- acdnt_weather
CREATE INDEX idx_weather_acdnt ON wing.acdnt_weather USING btree (acdnt_sn);

파일 보기

@ -0,0 +1,11 @@
-- WING-OPS Seed Data: Auth Roles
-- 역할 4건 (ADMIN, MANAGER, USER, VIEWER)
-- 출처: database/auth_init.sql
SET search_path TO public;
INSERT INTO auth.auth_role (role_cd, role_nm, role_dc, dflt_yn) VALUES
('ADMIN', '관리자', '시스템 전체 관리 권한', 'N'),
('MANAGER', '운영자', '운영 및 사용자 관리 권한', 'N'),
('USER', '일반사용자', '기본 업무 기능 접근 권한', 'Y'),
('VIEWER', '뷰어', '조회 전용 접근 권한', 'N');

파일 보기

@ -0,0 +1,147 @@
-- WING-OPS Seed Data: Auth Permissions (RCUD 2차원 권한 모델)
-- 역할별 리소스 × 오퍼레이션 매트릭스
-- 출처: database/auth_init.sql (004_oper_cd.sql 적용 후 최종 상태)
-- role_sn 1=ADMIN, 2=MANAGER, 3=USER, 4=VIEWER
-- ============================================================
-- ADMIN (role_sn=1): 모든 탭 × RCUD 전체 허용
-- ============================================================
INSERT INTO auth.auth_perm (role_sn, rsrc_cd, oper_cd, grant_yn) VALUES
(1, 'prediction', 'READ', 'Y'),
(1, 'prediction', 'CREATE', 'Y'),
(1, 'prediction', 'UPDATE', 'Y'),
(1, 'prediction', 'DELETE', 'Y'),
(1, 'hns', 'READ', 'Y'),
(1, 'hns', 'CREATE', 'Y'),
(1, 'hns', 'UPDATE', 'Y'),
(1, 'hns', 'DELETE', 'Y'),
(1, 'rescue', 'READ', 'Y'),
(1, 'rescue', 'CREATE', 'Y'),
(1, 'rescue', 'UPDATE', 'Y'),
(1, 'rescue', 'DELETE', 'Y'),
(1, 'reports', 'READ', 'Y'),
(1, 'reports', 'CREATE', 'Y'),
(1, 'reports', 'UPDATE', 'Y'),
(1, 'reports', 'DELETE', 'Y'),
(1, 'aerial', 'READ', 'Y'),
(1, 'aerial', 'CREATE', 'Y'),
(1, 'aerial', 'UPDATE', 'Y'),
(1, 'aerial', 'DELETE', 'Y'),
(1, 'assets', 'READ', 'Y'),
(1, 'assets', 'CREATE', 'Y'),
(1, 'assets', 'UPDATE', 'Y'),
(1, 'assets', 'DELETE', 'Y'),
(1, 'scat', 'READ', 'Y'),
(1, 'scat', 'CREATE', 'Y'),
(1, 'scat', 'UPDATE', 'Y'),
(1, 'scat', 'DELETE', 'Y'),
(1, 'incidents', 'READ', 'Y'),
(1, 'incidents', 'CREATE', 'Y'),
(1, 'incidents', 'UPDATE', 'Y'),
(1, 'incidents', 'DELETE', 'Y'),
(1, 'board', 'READ', 'Y'),
(1, 'board', 'CREATE', 'Y'),
(1, 'board', 'UPDATE', 'Y'),
(1, 'board', 'DELETE', 'Y'),
(1, 'weather', 'READ', 'Y'),
(1, 'weather', 'CREATE', 'Y'),
(1, 'weather', 'UPDATE', 'Y'),
(1, 'weather', 'DELETE', 'Y'),
(1, 'admin', 'READ', 'Y'),
(1, 'admin', 'CREATE', 'Y'),
(1, 'admin', 'UPDATE', 'Y'),
(1, 'admin', 'DELETE', 'Y');
-- ============================================================
-- MANAGER (role_sn=2): admin 탭 제외, 나머지 탭 RCUD 전체 허용
-- ============================================================
INSERT INTO auth.auth_perm (role_sn, rsrc_cd, oper_cd, grant_yn) VALUES
(2, 'prediction', 'READ', 'Y'),
(2, 'prediction', 'CREATE', 'Y'),
(2, 'prediction', 'UPDATE', 'Y'),
(2, 'prediction', 'DELETE', 'Y'),
(2, 'hns', 'READ', 'Y'),
(2, 'hns', 'CREATE', 'Y'),
(2, 'hns', 'UPDATE', 'Y'),
(2, 'hns', 'DELETE', 'Y'),
(2, 'rescue', 'READ', 'Y'),
(2, 'rescue', 'CREATE', 'Y'),
(2, 'rescue', 'UPDATE', 'Y'),
(2, 'rescue', 'DELETE', 'Y'),
(2, 'reports', 'READ', 'Y'),
(2, 'reports', 'CREATE', 'Y'),
(2, 'reports', 'UPDATE', 'Y'),
(2, 'reports', 'DELETE', 'Y'),
(2, 'aerial', 'READ', 'Y'),
(2, 'aerial', 'CREATE', 'Y'),
(2, 'aerial', 'UPDATE', 'Y'),
(2, 'aerial', 'DELETE', 'Y'),
(2, 'assets', 'READ', 'Y'),
(2, 'assets', 'CREATE', 'Y'),
(2, 'assets', 'UPDATE', 'Y'),
(2, 'assets', 'DELETE', 'Y'),
(2, 'scat', 'READ', 'Y'),
(2, 'scat', 'CREATE', 'Y'),
(2, 'scat', 'UPDATE', 'Y'),
(2, 'scat', 'DELETE', 'Y'),
(2, 'incidents', 'READ', 'Y'),
(2, 'incidents', 'CREATE', 'Y'),
(2, 'incidents', 'UPDATE', 'Y'),
(2, 'incidents', 'DELETE', 'Y'),
(2, 'board', 'READ', 'Y'),
(2, 'board', 'CREATE', 'Y'),
(2, 'board', 'UPDATE', 'Y'),
(2, 'board', 'DELETE', 'Y'),
(2, 'weather', 'READ', 'Y'),
(2, 'weather', 'CREATE', 'Y'),
(2, 'weather', 'UPDATE', 'Y'),
(2, 'weather', 'DELETE', 'Y'),
(2, 'admin', 'READ', 'N');
-- ============================================================
-- USER (role_sn=3): assets/admin 조회 거부, 나머지는 READ/CREATE/UPDATE
-- ============================================================
INSERT INTO auth.auth_perm (role_sn, rsrc_cd, oper_cd, grant_yn) VALUES
(3, 'prediction', 'READ', 'Y'),
(3, 'prediction', 'CREATE', 'Y'),
(3, 'prediction', 'UPDATE', 'Y'),
(3, 'hns', 'READ', 'Y'),
(3, 'hns', 'CREATE', 'Y'),
(3, 'hns', 'UPDATE', 'Y'),
(3, 'rescue', 'READ', 'Y'),
(3, 'rescue', 'CREATE', 'Y'),
(3, 'rescue', 'UPDATE', 'Y'),
(3, 'reports', 'READ', 'Y'),
(3, 'reports', 'CREATE', 'Y'),
(3, 'reports', 'UPDATE', 'Y'),
(3, 'aerial', 'READ', 'Y'),
(3, 'aerial', 'CREATE', 'Y'),
(3, 'aerial', 'UPDATE', 'Y'),
(3, 'assets', 'READ', 'N'),
(3, 'scat', 'READ', 'Y'),
(3, 'scat', 'CREATE', 'Y'),
(3, 'scat', 'UPDATE', 'Y'),
(3, 'incidents', 'READ', 'Y'),
(3, 'incidents', 'CREATE', 'Y'),
(3, 'incidents', 'UPDATE', 'Y'),
(3, 'board', 'READ', 'Y'),
(3, 'board', 'CREATE', 'Y'),
(3, 'board', 'UPDATE', 'Y'),
(3, 'weather', 'READ', 'Y'),
(3, 'admin', 'READ', 'N');
-- ============================================================
-- VIEWER (role_sn=4): 제한된 탭 READ만 허용 (CUD 없음)
-- ============================================================
INSERT INTO auth.auth_perm (role_sn, rsrc_cd, oper_cd, grant_yn) VALUES
(4, 'prediction', 'READ', 'Y'),
(4, 'hns', 'READ', 'Y'),
(4, 'rescue', 'READ', 'Y'),
(4, 'reports', 'READ', 'N'),
(4, 'aerial', 'READ', 'Y'),
(4, 'assets', 'READ', 'N'),
(4, 'scat', 'READ', 'N'),
(4, 'incidents', 'READ', 'Y'),
(4, 'board', 'READ', 'Y'),
(4, 'weather', 'READ', 'Y'),
(4, 'admin', 'READ', 'N');

파일 보기

@ -0,0 +1,96 @@
-- WING-OPS Seed Data: Auth Permission Tree
-- 트리 구조 기반 리소스(메뉴) 권한 정의 (48건)
-- 출처: database/migration/003_perm_tree.sql
-- ============================================================
-- Level 0: 메인 탭 (11건)
-- ============================================================
INSERT INTO auth.auth_perm_tree (rsrc_cd, parent_cd, rsrc_nm, rsrc_desc, rsrc_level, sort_ord) VALUES
('prediction', NULL, '유출유 확산예측', '확산 예측 실행 및 결과 조회', 0, 1),
('hns', NULL, 'HNS·대기확산', '대기확산 분석 실행 및 조회', 0, 2),
('rescue', NULL, '긴급구난', '구난 예측 실행 및 조회', 0, 3),
('reports', NULL, '보고자료', '사고 보고서 작성 및 조회', 0, 4),
('aerial', NULL, '항공탐색', '항공 탐색 데이터 조회', 0, 5),
('assets', NULL, '방제자산 관리', '방제 장비 및 자산 관리', 0, 6),
('scat', NULL, '해안평가', 'SCAT 조사 실행 및 조회', 0, 7),
('board', NULL, '게시판', '자료실 및 공지사항 조회', 0, 8),
('weather', NULL, '기상정보', '기상 및 해상 정보 조회', 0, 9),
('incidents', NULL, '통합조회', '사고 상세 정보 조회', 0, 10),
('admin', NULL, '관리', '사용자 및 권한 관리', 0, 11);
-- ============================================================
-- Level 1: prediction 하위 (4건)
-- ============================================================
INSERT INTO auth.auth_perm_tree (rsrc_cd, parent_cd, rsrc_nm, rsrc_level, sort_ord) VALUES
('prediction:analysis', 'prediction', '확산분석', 1, 1),
('prediction:list', 'prediction', '분석 목록', 1, 2),
('prediction:theory', 'prediction', '확산모델 이론', 1, 3),
('prediction:boom-theory', 'prediction', '오일펜스 배치 이론', 1, 4);
-- ============================================================
-- Level 1: hns 하위 (6건)
-- ============================================================
INSERT INTO auth.auth_perm_tree (rsrc_cd, parent_cd, rsrc_nm, rsrc_level, sort_ord) VALUES
('hns:analysis', 'hns', '대기확산 분석', 1, 1),
('hns:list', 'hns', '분석 목록', 1, 2),
('hns:scenario', 'hns', '시나리오 관리', 1, 3),
('hns:manual', 'hns', 'HNS 대응매뉴얼', 1, 4),
('hns:theory', 'hns', '확산모델 이론', 1, 5),
('hns:substance', 'hns', 'HNS 물질정보', 1, 6);
-- ============================================================
-- Level 1: rescue 하위 (4건)
-- ============================================================
INSERT INTO auth.auth_perm_tree (rsrc_cd, parent_cd, rsrc_nm, rsrc_level, sort_ord) VALUES
('rescue:rescue', 'rescue', '긴급구난예측', 1, 1),
('rescue:list', 'rescue', '긴급구난 목록', 1, 2),
('rescue:scenario', 'rescue', '시나리오 관리', 1, 3),
('rescue:theory', 'rescue', '긴급구난모델 이론', 1, 4);
-- ============================================================
-- Level 1: reports 하위 (3건)
-- ============================================================
INSERT INTO auth.auth_perm_tree (rsrc_cd, parent_cd, rsrc_nm, rsrc_level, sort_ord) VALUES
('reports:report-list', 'reports', '보고서 목록', 1, 1),
('reports:template', 'reports', '표준보고서 템플릿', 1, 2),
('reports:generate', 'reports', '보고서 생성', 1, 3);
-- ============================================================
-- Level 1: aerial 하위 (7건)
-- ============================================================
INSERT INTO auth.auth_perm_tree (rsrc_cd, parent_cd, rsrc_nm, rsrc_level, sort_ord) VALUES
('aerial:media', 'aerial', '영상사진관리', 1, 1),
('aerial:analysis', 'aerial', '유출유면적분석', 1, 2),
('aerial:realtime', 'aerial', '실시간드론', 1, 3),
('aerial:sensor', 'aerial', '오염/선박3D분석', 1, 4),
('aerial:satellite', 'aerial', '위성요청', 1, 5),
('aerial:cctv', 'aerial', 'CCTV 조회', 1, 6),
('aerial:theory', 'aerial', '항공탐색 이론', 1, 7);
-- ============================================================
-- Level 1: assets 하위 (4건)
-- ============================================================
INSERT INTO auth.auth_perm_tree (rsrc_cd, parent_cd, rsrc_nm, rsrc_level, sort_ord) VALUES
('assets:management', 'assets', '자산 관리', 1, 1),
('assets:upload', 'assets', '자산 현행화', 1, 2),
('assets:theory', 'assets', '방제자원 이론', 1, 3),
('assets:insurance', 'assets', '선박 보험정보', 1, 4);
-- ============================================================
-- Level 1: board 하위 (5건)
-- ============================================================
INSERT INTO auth.auth_perm_tree (rsrc_cd, parent_cd, rsrc_nm, rsrc_level, sort_ord) VALUES
('board:all', 'board', '전체', 1, 1),
('board:notice', 'board', '공지사항', 1, 2),
('board:data', 'board', '자료실', 1, 3),
('board:qna', 'board', 'Q&A', 1, 4),
('board:manual', 'board', '해경매뉴얼', 1, 5);
-- ============================================================
-- Level 1: admin 하위 (4건)
-- ============================================================
INSERT INTO auth.auth_perm_tree (rsrc_cd, parent_cd, rsrc_nm, rsrc_level, sort_ord) VALUES
('admin:users', 'admin', '사용자 관리', 1, 1),
('admin:permissions', 'admin', '권한 관리', 1, 2),
('admin:menus', 'admin', '메뉴 관리', 1, 3),
('admin:settings', 'admin', '시스템 설정', 1, 4);

파일 보기

@ -0,0 +1,16 @@
-- WING-OPS Seed Data: Auth Organizations
-- 인증 조직 6건
-- 출처: database/auth_init.sql
INSERT INTO auth.auth_org (org_nm, org_abbr_nm, org_tp_cd) VALUES
('해양경찰청', '해경청', 'HEADQUARTERS'),
('남해지방해양경찰청', '남해청', 'REGIONAL'),
('제주지방해양경찰청', '제주청', 'REGIONAL'),
('여수해양경찰서', '여수서', 'STATION'),
('서귀포해양경찰서', '서귀포서', 'STATION'),
('제주해양경찰서', '제주서', 'STATION');
-- 상위조직 설정 (org_sn은 SERIAL 순서: 1=해경청, 2=남해청, 3=제주청, 4=여수서, 5=서귀포서, 6=제주서)
UPDATE auth.auth_org SET upper_org_sn = 1 WHERE org_sn IN (2, 3);
UPDATE auth.auth_org SET upper_org_sn = 2 WHERE org_sn = 4;
UPDATE auth.auth_org SET upper_org_sn = 3 WHERE org_sn IN (5, 6);

파일 보기

@ -0,0 +1,20 @@
-- WING-OPS Seed Data: Auth Settings
-- 시스템 설정 4건
-- 출처: database/auth_init.sql
INSERT INTO auth.auth_setting (setting_key, setting_val, setting_dc) VALUES
('registration.auto-approve',
'true',
'신규 사용자 자동 승인 여부 (true: 즉시 ACTIVE, false: PENDING 대기)'),
('registration.default-role',
'true',
'신규 사용자에게 기본 역할(dflt_yn=Y) 자동 할당 여부'),
('oauth.auto-approve-domains',
'gcsc.co.kr',
'OAuth 자동 승인 도메인 (쉼표 구분)'),
('menu.config',
'[{"id":"prediction","label":"유출유 확산예측","icon":"🛢️","enabled":true,"order":1},{"id":"hns","label":"HNS·대기확산","icon":"🧪","enabled":true,"order":2},{"id":"rescue","label":"긴급구난","icon":"🚨","enabled":true,"order":3},{"id":"reports","label":"보고자료","icon":"📊","enabled":true,"order":4},{"id":"aerial","label":"항공탐색","icon":"✈️","enabled":true,"order":5},{"id":"assets","label":"방제자산 관리","icon":"🚢","enabled":true,"order":6},{"id":"scat","label":"해안평가","icon":"🏖️","enabled":true,"order":7},{"id":"board","label":"게시판","icon":"📌","enabled":true,"order":8},{"id":"weather","label":"기상정보","icon":"⛅","enabled":true,"order":9},{"id":"incidents","label":"통합조회","icon":"🔍","enabled":true,"order":10}]',
'메뉴 표시 여부 및 순서 설정 (JSON 배열)');

파일 보기

@ -0,0 +1,19 @@
-- WING-OPS Seed Data: Auth Admin User
-- 관리자 계정 생성 (admin / admin1234)
-- 출처: database/auth_init.sql
-- 주의: pgcrypto 확장이 설치되어 있어야 함 (CREATE EXTENSION IF NOT EXISTS pgcrypto)
-- 관리자 계정 (비밀번호: admin1234, bcrypt 해시)
INSERT INTO auth.auth_user (user_acnt, pswd_hash, user_nm, rnkp_nm, org_sn, user_stts_cd)
VALUES (
'admin',
crypt('admin1234', gen_salt('bf', 10)),
'관리자',
'경정',
1,
'ACTIVE'
);
-- admin 사용자에 ADMIN 역할 할당 (role_sn=1)
INSERT INTO auth.auth_user_role (user_id, role_sn)
SELECT user_id, 1 FROM auth.auth_user WHERE user_acnt = 'admin';

파일 보기

@ -0,0 +1,192 @@
-- WING-OPS Seed Data: Common Codes
-- 공통코드그룹 16건, 공통코드 약 100건
-- 출처: database/init.sql
-- ============================================================
-- 공통코드그룹 (CMN_CD_GRP)
-- ============================================================
-- 조직유형 (ORG_TP)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('ORG_TP', '조직유형', '조직의 유형을 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('ORG_TP', 'HEADQUARTERS', '본청', 1),
('ORG_TP', 'REGIONAL', '지방청', 2),
('ORG_TP', 'STATION', '해양경찰서', 3),
('ORG_TP', 'AGENCY', '유관기관', 4);
-- 사용자역할 (USER_ROLE)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('USER_ROLE', '사용자역할', '사용자의 시스템 역할을 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('USER_ROLE', 'ADMIN', '관리자', 1),
('USER_ROLE', 'MANAGER', '운영자', 2),
('USER_ROLE', 'USER', '일반사용자', 3);
-- 사고유형 (ACDNT_TP)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('ACDNT_TP', '사고유형', '해양사고의 유형을 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('ACDNT_TP', 'COLLISION', '충돌', 1),
('ACDNT_TP', 'GROUNDING', '좌초', 2),
('ACDNT_TP', 'SINKING', '침몰', 3),
('ACDNT_TP', 'LEAK', '누출', 4),
('ACDNT_TP', 'EXPLOSION', '폭발', 5),
('ACDNT_TP', 'ETC', '기타', 99);
-- 사고상태 (ACDNT_STTS)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('ACDNT_STTS', '사고상태', '사고의 진행 상태를 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('ACDNT_STTS', 'ACTIVE', '진행중', 1),
('ACDNT_STTS', 'MONITORING', '감시중', 2),
('ACDNT_STTS', 'CLOSED', '종료', 3);
-- 심각도 (SVRT)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('SVRT', '심각도', '사고의 심각도를 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('SVRT', 'DANGER', '위험', 1),
('SVRT', 'ALERT', '경계', 2),
('SVRT', 'CAUTION', '주의', 3),
('SVRT', 'INTEREST', '관심', 4);
-- 유종 (OIL_TP)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('OIL_TP', '유종', '유출유의 종류를 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('OIL_TP', 'CRUDE', '원유', 1),
('OIL_TP', 'BUNKER_C', '벙커C유', 2),
('OIL_TP', 'DIESEL', '경유', 3),
('OIL_TP', 'GASOLINE', '휘발유', 4),
('OIL_TP', 'KEROSENE', '등유', 5),
('OIL_TP', 'LUBE', '윤활유', 6),
('OIL_TP', 'ETC', '기타', 99);
-- 유출단위 (SPIL_UNIT)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('SPIL_UNIT', '유출단위', '유출량의 측정 단위를 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('SPIL_UNIT', 'KL', '킬로리터', 1),
('SPIL_UNIT', 'L', '리터', 2),
('SPIL_UNIT', 'BBL', '배럴', 3),
('SPIL_UNIT', 'TON', '', 4);
-- 유출유형 (SPIL_TP)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('SPIL_TP', '유출유형', '유출의 형태를 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('SPIL_TP', 'CONTINUOUS', '연속유출', 1),
('SPIL_TP', 'INSTANTANEOUS', '순간유출', 2);
-- 예측알고리즘 (ALGO)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('ALGO', '예측알고리즘', '유출 확산 예측에 사용되는 알고리즘 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('ALGO', 'GNOME', 'GNOME 모델', 1),
('ALGO', 'OSCAR', 'OSCAR 모델', 2),
('ALGO', 'MOHID', 'MOHID 모델', 3);
-- 실행상태 (EXEC_STTS)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('EXEC_STTS', '실행상태', '예측 실행의 상태를 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('EXEC_STTS', 'PENDING', '대기', 1),
('EXEC_STTS', 'RUNNING', '실행중', 2),
('EXEC_STTS', 'COMPLETED', '완료', 3),
('EXEC_STTS', 'FAILED', '실패', 4);
-- 오일펜스우선순위 (BOOM_PRIORT)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('BOOM_PRIORT', '오일펜스우선순위', '오일펜스 배치 우선순위를 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('BOOM_PRIORT', 'CRITICAL', '긴급', 1),
('BOOM_PRIORT', 'HIGH', '높음', 2),
('BOOM_PRIORT', 'MEDIUM', '보통', 3),
('BOOM_PRIORT', 'LOW', '낮음', 4);
-- 오일펜스배치상태 (DPLY_STTS)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('DPLY_STTS', '배치상태', '오일펜스의 배치 상태를 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('DPLY_STTS', 'PLANNED', '계획', 1),
('DPLY_STTS', 'DEPLOYING', '배치중', 2),
('DPLY_STTS', 'DEPLOYED', '배치완료', 3),
('DPLY_STTS', 'REMOVED', '회수', 4);
-- 해안유형 (CST_TP)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('CST_TP', '해안유형', '해안의 지형 유형을 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('CST_TP', 'ROCK', '암반해안', 1),
('CST_TP', 'GRAVEL', '자갈해안', 2),
('CST_TP', 'SAND', '모래해안', 3),
('CST_TP', 'MUD', '갯벌', 4),
('CST_TP', 'MIXED', '혼합해안', 5),
('CST_TP', 'SEAWALL', '인공구조물', 6),
('CST_TP', 'TETRAPOD', '테트라포드', 7);
-- 민감도 (SNSTVT)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('SNSTVT', '민감도', '해안구간의 환경 민감도를 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('SNSTVT', 'HIGH', '', 1),
('SNSTVT', 'MEDIUM', '', 2),
('SNSTVT', 'LOW', '', 3);
-- 조사상태 (SRVY_STTS)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('SRVY_STTS', '조사상태', '해안구간 조사의 진행 상태를 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('SRVY_STTS', 'PENDING', '미조사', 1),
('SRVY_STTS', 'PROGRESS', '진행중', 2),
('SRVY_STTS', 'COMPLETED', '완료', 3);
-- 조사유형 (SRVY_TP)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('SRVY_TP', '조사유형', 'SCAT 조사의 유형을 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('SRVY_TP', 'PRE_SCAT', 'Pre-SCAT', 1),
('SRVY_TP', 'SCAT', 'SCAT', 2),
('SRVY_TP', 'POST_SCAT', 'Post-SCAT', 3);
-- 조사단계 (SRVY_PHASE)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('SRVY_PHASE', '조사단계', 'SCAT 조사의 단계를 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('SRVY_PHASE', 'PHASE_1', '1차 조사', 1),
('SRVY_PHASE', 'PHASE_2', '2차 조사', 2),
('SRVY_PHASE', 'PHASE_3', '3차 조사', 3);
-- 오염도 (POLUT)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('POLUT', '오염도', '해안구간의 오염 정도를 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('POLUT', 'HEAVY', '심각', 1),
('POLUT', 'MODERATE', '보통', 2),
('POLUT', 'LIGHT', '경미', 3),
('POLUT', 'CLEAN', '깨끗', 4);
-- 물리상태 (PHYS_STATE)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('PHYS_STATE', '물리상태', '화학물질의 물리적 상태를 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('PHYS_STATE', 'SOLID', '고체', 1),
('PHYS_STATE', 'LIQUID', '액체', 2),
('PHYS_STATE', 'GAS', '기체', 3);
-- 수용성 (WATER_SLBLT)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('WATER_SLBLT', '수용성', '화학물질의 수용성 정도를 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('WATER_SLBLT', 'SOLUBLE', '수용성', 1),
('WATER_SLBLT', 'PARTIAL', '부분용해', 2),
('WATER_SLBLT', 'INSOLUBLE', '불용성', 3);
-- 독성 (TOXICITY)
INSERT INTO wing.cmn_cd_grp (cmn_cd_grp_id, cmn_cd_grp_nm, grp_dc) VALUES
('TOXICITY', '독성', '화학물질의 독성 수준을 구분하는 코드');
INSERT INTO wing.cmn_cd (cmn_cd_grp_id, cmn_cd, cmn_cd_nm, sort_ord) VALUES
('TOXICITY', 'HIGH', '고독성', 1),
('TOXICITY', 'MEDIUM', '중독성', 2),
('TOXICITY', 'LOW', '저독성', 3);

파일 보기

@ -0,0 +1,16 @@
-- WING-OPS Seed Data: Organizations
-- wing.org 6건
-- 출처: database/init.sql
INSERT INTO wing.org (org_nm, org_abbr_nm, org_tp_cd) VALUES
('해양경찰청', '해경청', 'HEADQUARTERS'),
('남해지방해양경찰청', '남해청', 'REGIONAL'),
('제주지방해양경찰청', '제주청', 'REGIONAL'),
('여수해양경찰서', '여수서', 'STATION'),
('서귀포해양경찰서', '서귀포서', 'STATION'),
('제주해양경찰서', '제주서', 'STATION');
-- 상위조직 설정 (org_sn은 SERIAL 순서: 1=해경청, 2=남해청, 3=제주청, 4=여수서, 5=서귀포서, 6=제주서)
UPDATE wing.org SET upper_org_sn = 1 WHERE org_sn IN (2, 3);
UPDATE wing.org SET upper_org_sn = 2 WHERE org_sn = 4;
UPDATE wing.org SET upper_org_sn = 3 WHERE org_sn IN (5, 6);

파일 보기

@ -0,0 +1,4 @@
-- WING-OPS Seed Data: Layers
-- layer 테이블 데이터는 Node.js 스크립트로 삽입됩니다.
-- 실행: cd backend && npm run db:seed
-- 소스: backend/src/db/seed.ts (CSV 파싱 → 160건 INSERT)

파일 보기

@ -0,0 +1,4 @@
-- WING-OPS Seed Data: HNS Substances
-- hns_substance 테이블 데이터는 Node.js 스크립트로 삽입됩니다.
-- 실행: cd backend && npm run db:seed
-- 소스: backend/src/db/seedHns.ts (프론트엔드 데이터 → 1,316건 INSERT)

파일 보기

@ -0,0 +1,29 @@
-- WING-OPS Seed Data: Sample Accident
-- 샘플 사고 및 유출정보
-- 출처: database/init.sql
-- 주의: 08_organizations.sql 실행 후 실행 (org_sn=4 여수해양경찰서 참조)
-- 06_auth_admin.sql 실행 후 실행 (rgtr_id 생략, NULL로 삽입)
-- 샘플 사고 (여수 앞바다)
INSERT INTO wing.acdnt (acdnt_cd, acdnt_nm, acdnt_tp_cd, loc_geom, loc_dc, occrn_dtm, rspns_org_sn, svrt_cd) VALUES
('INC-2025-0042',
'여수 앞바다 유조선 충돌',
'COLLISION',
ST_SetSRID(ST_MakePoint(127.8, 34.5), 4326),
'여수 돌산 남방 5NM',
'2025-02-10 06:30:00+09',
4,
'DANGER');
-- 유출정보 (샘플 사고 연결)
INSERT INTO wing.spil_data (acdnt_sn, oil_tp_cd, spil_qty, spil_unit_cd, spil_tp_cd, spil_loc_geom, fcst_hr)
SELECT
acdnt_sn,
'BUNKER_C',
150.00,
'KL',
'INSTANTANEOUS',
ST_SetSRID(ST_MakePoint(127.8, 34.5), 4326),
72
FROM wing.acdnt
WHERE acdnt_cd = 'INC-2025-0042';

999
database/seed/12_assets.sql Normal file
파일 보기

@ -0,0 +1,999 @@
-- WING-OPS Seed Data: Assets (기관, 장비, 연락처)
-- Source: database/migration/008_assets_seed.sql
-- 자동 생성: assetMockData.ts → SQL INSERT
-- 생성일: 2026-02-28
SET search_path TO wing;
-- ============================================================
-- ASSET_ORG 초기 데이터 (84건)
-- ============================================================
INSERT INTO ASSET_ORG (ORG_TP, JRSD_NM, AREA_NM, ORG_NM, ADDR, TEL, LAT, LNG, PIN_SIZE, VESSEL_CNT, SKIMMER_CNT, PUMP_CNT, VEHICLE_CNT, SPRAYER_CNT, TOTAL_ASSETS) VALUES
('해경관할', '중부지방해양경찰청', '인천', '인천해양경찰서', '인천광역시 중구 북성동1가 80-8', '010-4779-4191', 37.4563, 126.5922, 'hq', 19, 30, 18, 2, 15, 234),
('해경경찰서', '중부지방해양경찰청', '평택', '평택해양경찰서', '평택시 만호리 706번지', '010-9812-8102', 36.9694, 126.83, 'lg', 14, 27, 33, 3, 22, 193),
('해경경찰서', '중부지방해양경찰청', '태안', '태안해양경찰서', '충남 태안군 근흥면 신진부두길2', '010-2965-4423', 36.7456, 126.2978, 'lg', 10, 27, 21, 8, 15, 185),
('파출소', '중부지방해양경찰청', '보령', '보령해양경찰서', '보령시 해안로 740', '010-2940-6343', 36.3335, 126.5874, 'md', 3, 8, 5, 3, 11, 80),
('해경관할', '서해지방해양경찰청', '여수', '여수해양경찰서', '광양시 항만9로 89', '010-2785-2493', 34.7407, 127.7385, 'hq', 55, 92, 63, 12, 47, 464),
('해경경찰서', '서해지방해양경찰청', '목포', '목포해양경찰서', '목포시 고하대로 597번길 99-64', '010-9812-8439', 34.7936, 126.3839, 'lg', 10, 19, 18, 3, 16, 169),
('해경경찰서', '서해지방해양경찰청', '군산', '군산해양경찰서', '전북 군산시 오식도동 506', '010-2618-3406', 35.99, 126.7133, 'lg', 6, 22, 12, 3, 17, 155),
('해경경찰서', '서해지방해양경찰청', '완도', '완도해양경찰서', '완도군 완도읍 장보고대로 383', '061-550-2183', 34.311, 126.755, 'lg', 3, 9, 7, 3, 11, 75),
('파출소', '서해지방해양경찰청', '부안', '부안해양경찰서', '전북 군산시 오식도동 506', '063-928-xxxx', 35.7316, 126.7328, 'md', 2, 8, 7, 2, 7, 66),
('해경관할', '남해지방해양경찰청', '부산', '부산해양경찰서', '부산시 영도구 해양로 293', '010-2609-1456', 35.0746, 129.0686, 'hq', 108, 22, 25, 10, 24, 313),
('해경관할', '남해지방해양경찰청', '울산', '울산해양경찰서', '울산광역시 남구 장생포 고래로 166', '010-9812-8210', 35.5008, 129.3824, 'hq', 46, 69, 26, 11, 20, 311),
('해경경찰서', '남해지방해양경찰청', '창원', '창원해양경찰서', '창원시 마산합포구 신포동 1가', '010-4634-7364', 35.1796, 128.5681, 'lg', 12, 25, 14, 10, 10, 139),
('해경경찰서', '남해지방해양경찰청', '통영', '통영해양경찰서', '통영시 광도면 죽림리 1564-4', '010-9812-8495', 34.8544, 128.4331, 'lg', 6, 15, 9, 5, 13, 104),
('해경경찰서', '남해지방해양경찰청', '사천', '사천해양경찰서', '사천시 신항만길 1길 17', '010-9812-8352', 34.931, 128.066, 'lg', 2, 9, 6, 2, 7, 80),
('해경경찰서', '동해지방해양경찰청', '동해', '동해해양경찰서', '동해시 임항로 130', '010-9812-8073', 37.5247, 129.1143, 'lg', 6, 23, 11, 6, 14, 156),
('해경경찰서', '동해지방해양경찰청', '포항', '포항해양경찰서', '포항시 남구 희망대로 1341', '010-3108-2183', 36.019, 129.3651, 'lg', 10, 13, 21, 4, 21, 135),
('파출소', '동해지방해양경찰청', '속초', '속초해양경찰서', '속초시 설악금강대교로 206', '033-634-2186', 38.207, 128.5918, 'md', 2, 6, 4, 1, 17, 85),
('파출소', '동해지방해양경찰청', '울진', '울진해양경찰서', '울진군 후포면 후포리 623-148', '010-9812-8076', 36.9932, 129.4003, 'md', 2, 6, 4, 1, 8, 66),
('해경경찰서', '제주지방해양경찰청', '제주', '제주해양경찰서', '제주시 임항로 85', '064-766-2691', 33.5154, 126.5268, 'lg', 4, 21, 17, 3, 16, 113),
('해경경찰서', '제주지방해양경찰청', '서귀포', '서귀포해양경찰서', '서귀포시 안덕면 화순해안로69', '064-793-2186', 33.2469, 126.56, 'lg', 3, 9, 15, 3, 14, 67),
('관련기관', '해양경찰청(중앙)', '중앙', '중앙특수구조단', '부산광역시 영도구 해양로 301', '051-580-2044', 35.058, 129.059, 'md', 1, 0, 5, 2, 0, 39),
('기름저장시설', '서해지방해양경찰청', '여수', '오일허브코리아여수㈜ 외 4개', '전남 여수시 신덕동 325', '061-686-3611', 34.745, 127.745, 'md', 0, 0, 0, 0, 0, 1),
('기름저장시설', '남해지방해양경찰청', '부산', 'SK에너지 외 2개', '부산시 영도구 해양로 1', '051-643-3331', 35.175, 129.075, 'md', 0, 0, 0, 0, 0, 3),
('기름저장시설', '남해지방해양경찰청', '울산', 'SK지오센트릭 외 5개', '울산광역시 남구 신여천로 2', '052-208-2851', 35.535, 129.305, 'md', 0, 0, 0, 0, 0, 9),
('기름저장시설', '남해지방해양경찰청', '통영', '한국가스공사 통영기지본부', '통영시 광도면 안정로 770', '055-640-6014', 35.05, 128.41, 'md', 0, 0, 0, 0, 0, 1),
('기름저장시설', '동해지방해양경찰청', '동해', 'HD현대오일뱅크㈜ 외 4개', '강릉시 옥계면 동해대로 206', '033-534-2093', 37.52, 129.11, 'md', 0, 0, 0, 0, 0, 9),
('기름저장시설', '동해지방해양경찰청', '포항', '포스코케미칼 외 1개', '포항시 남구 동해안로 6262', '054-290-8222', 37.73, 129.01, 'md', 0, 0, 0, 0, 1, 2),
('기름저장시설', '서해지방해양경찰청', '목포', '흑산도내연발전소 외 2개', '전남 신안군 흑산일주로70', '061-351-2342', 35.04, 126.58, 'md', 0, 0, 0, 0, 0, 4),
('기름저장시설', '서해지방해양경찰청', '여수', '오일허브코리아여수㈜ 외 4개', '전남 여수시 신덕동 325', '061-686-3611', 34.75, 127.735, 'md', 0, 0, 0, 0, 0, 4),
('기름저장시설', '중부지방해양경찰청', '인천', 'GS칼텍스㈜ 외 10개', '인천광역시 중구 월미로 182', '010-8777-6922', 37.45, 126.505, 'md', 0, 0, 0, 0, 0, 13),
('기름저장시설', '중부지방해양경찰청', '태안', 'HD현대케미칼 외 4개', '충남 서산시 대산읍 평신2로 26', '041-924-1068', 36.91, 126.415, 'md', 0, 0, 0, 0, 0, 4),
('기름저장시설', '중부지방해양경찰청', '평택', '현대오일터미널(주) 외 4개', '평택시 포승읍 포승공단순환로 11', '031-683-5101', 36.985, 126.835, 'md', 0, 0, 0, 0, 1, 4),
('기타', '남해지방해양경찰청', '사천', '한국남동발전(주) 외 2개', '고성군 하이면 하이로1', '070-4486-7474', 34.965, 128.56, 'md', 0, 0, 0, 0, 0, 8),
('기타', '남해지방해양경찰청', '울산', 'HD현대미포', '울산광역시 동구 방어진순환도로100', '052-250-3551', 35.53, 129.315, 'md', 0, 0, 0, 0, 0, 1),
('기타', '남해지방해양경찰청', '통영', '삼성중공업 외 1개', '거제시 장평3로 80', '055-630-5373', 35.05, 128.41, 'md', 0, 0, 0, 0, 0, 2),
('기타', '동해지방해양경찰청', '동해', '한국남부발전㈜', '삼척시 원덕읍 삼척로 734', '070-7713-5153', 37.45, 129.17, 'md', 0, 0, 0, 0, 0, 2),
('기타', '동해지방해양경찰청', '울진', '한울원전', '울진군 북면 울진북로 2040', '054-785-4833', 37.065, 129.39, 'md', 0, 0, 0, 0, 0, 4),
('기타', '서해지방해양경찰청', '여수', '㈜HR-PORT 외 5개', '여수시 제철로', '061-791-0358', 34.755, 127.73, 'md', 0, 0, 0, 0, 0, 16),
('기타', '중부지방해양경찰청', '인천', '삼광조선공업㈜ 외 1개', '인천 동구 보세로42번길41', '010-3321-2959', 37.45, 126.505, 'md', 0, 0, 0, 0, 0, 5),
('업체', '중부지방해양경찰청', '인천', '방제유창청소업체(㈜클린포트)', '㈜클린포트', '032-882-8279', 37.45, 126.505, 'md', 0, 0, 0, 0, 0, 3),
('업체', '남해지방해양경찰청', '부산', '방제유창청소업체(대용환경㈜ 외 38개)', '㈜태평양해양산업', '051-242-0622', 35.18, 129.085, 'md', 0, 0, 0, 0, 0, 51),
('업체', '남해지방해양경찰청', '울산', '방제유창청소업체((주)한유마린서비스 외 8개)', '대상해운(주)', '010-5499-7401', 35.54, 129.295, 'md', 0, 0, 0, 0, 0, 12),
('업체', '동해지방해양경찰청', '포항', '방제유창청소업체(블루씨 외 1개)', '(주)블루씨', '054-278-8200', 36.015, 129.365, 'md', 0, 0, 0, 0, 1, 3),
('업체', '서해지방해양경찰청', '목포', '방제유창청소업체(㈜한국해운 외 1개)', '㈜한국해운 목포지사', '010-8615-4326', 35.04, 126.58, 'md', 0, 0, 0, 0, 0, 1),
('업체', '서해지방해양경찰청', '여수', '방제유창청소업체(마로해운 외 11개)', '㈜우진실업', '061-654-9603', 34.74, 127.75, 'md', 0, 0, 0, 0, 2, 54),
('업체', '중부지방해양경찰청', '태안', '방제유창청소업체(우진해운㈜)', '우진해운㈜', '010-4384-6817', 36.905, 126.42, 'md', 0, 0, 0, 0, 0, 6),
('업체', '중부지방해양경찰청', '평택', '방제유창청소업체((주)씨앤 외 3개)', '㈜씨앤', '031-683-2389', 36.99, 126.825, 'md', 0, 0, 0, 0, 0, 6),
('업체', '남해지방해양경찰청', '부산', '방제유창청소업체(㈜지앤비마린서비스)', '㈜지앤비마린서비스', '051-242-0622', 35.185, 129.07, 'md', 0, 0, 0, 0, 0, 1),
('정유사', '남해지방해양경찰청', '울산', 'SK엔텀(주) 외 4개', '울산광역시 남구 고사동 110-64', '052-231-2318', 35.545, 129.31, 'md', 0, 0, 0, 0, 0, 5),
('정유사', '서해지방해양경찰청', '여수', 'GS칼텍스㈜', '여수시 낙포단지길 251', '061-680-2121', 34.735, 127.755, 'md', 0, 0, 0, 0, 20, 27),
('정유사', '중부지방해양경찰청', '태안', 'HD현대오일뱅크㈜', '서산시 대산읍 평신2로 182', '010-2050-5291', 36.915, 126.41, 'md', 0, 0, 0, 0, 0, 2),
('지자체', '남해지방해양경찰청', '부산', '부산광역시 외 8개', '부산광역시 동구 좌천동', '051-607-4484', 35.17, 129.08, 'md', 0, 0, 0, 0, 0, 12),
('지자체', '남해지방해양경찰청', '사천', '사천시 외 3개', '사천시 신항로 3', '055-670-2484', 34.935, 128.075, 'md', 0, 0, 0, 0, 0, 6),
('지자체', '남해지방해양경찰청', '울산', '울산북구청 외 2개', '울산광역시 북구 구유동 654-2', '051-709-4611', 35.55, 129.32, 'md', 0, 0, 0, 0, 0, 4),
('지자체', '남해지방해양경찰청', '창원', '창원 진해구 외 1개', '창원시 진해구 천자로 105', '051-970-4482', 35.055, 128.645, 'md', 0, 0, 0, 0, 0, 2),
('지자체', '동해지방해양경찰청', '동해', '삼척시 외 1개', '삼척시 근덕면 덕산리 107-74', '033-640-5284', 37.45, 129.16, 'md', 0, 0, 0, 0, 0, 4),
('지자체', '동해지방해양경찰청', '울진', '영덕군', '남정면 장사리 74-1', '054-730-6562', 36.35, 129.4, 'md', 0, 0, 0, 0, 0, 3),
('지자체', '서해지방해양경찰청', '목포', '영광군 외 1개', '영광군 염산면 향화로', '061-270-3419', 35.04, 126.58, 'md', 0, 0, 0, 0, 0, 5),
('지자체', '서해지방해양경찰청', '여수', '광양시 외 1개', '순천시 진상면 성지로 8', '061-797-2791', 34.76, 127.725, 'md', 0, 0, 0, 0, 0, 3),
('지자체', '중부지방해양경찰청', '인천', '옹진군청 외 4개', '인천광역시 옹진군 덕적면 진리 387', '010-2740-9388', 37.45, 126.505, 'md', 0, 0, 0, 0, 0, 10),
('지자체', '중부지방해양경찰청', '태안', '태안군청', '충남 태안군 근흥면 신진도리 75-36', '041-670-2877', 36.745, 126.305, 'md', 0, 0, 0, 0, 0, 1),
('지자체', '중부지방해양경찰청', '평택', '안산시청 외 2개', '경기도 안산시 단원구 진두길 97', '041-350-4292', 37.32, 126.83, 'md', 0, 0, 0, 0, 0, 6),
('기타', '서해지방해양경찰청', '여수', '㈜HR-PORT 외 5개', '여수시 제철로', '061-791-0358', 34.748, 127.74, 'md', 0, 0, 0, 0, 0, 1),
('해군', '동해지방해양경찰청', '동해', '해군1함대사령부 외 1개', '동해시 대동로 430', '033-539-7323', 37.525, 129.115, 'md', 0, 0, 0, 0, 0, 1),
('해군', '중부지방해양경찰청', '인천', '해병대 제9518부대', '인천광역시 옹진군', '010-4801-3473', 37.45, 126.505, 'md', 0, 0, 0, 0, 0, 2),
('해양환경공단', '남해지방해양경찰청', '부산', '부산지사', '창원시 진해구 안골동', '051-466-3944', 35.105, 128.715, 'md', 0, 0, 0, 0, 6, 14),
('해양환경공단', '남해지방해양경찰청', '사천', '마산지사', '사천시 신항만1길 23', '010-3598-4202', 34.925, 128.065, 'md', 0, 0, 0, 0, 0, 9),
('해양환경공단', '남해지방해양경찰청', '울산', '울산지사', '울산광역시 남구 장생포고래로 276번길 27', '052-238-7718', 35.538, 129.3, 'md', 0, 0, 0, 0, 1, 16),
('해양환경공단', '남해지방해양경찰청', '창원', '마산지사', '창원시 마산합포구 드림베이대로59', '010-2265-3928', 35.055, 128.645, 'md', 0, 0, 0, 0, 1, 7),
('해양환경공단', '남해지방해양경찰청', '통영', '마산지사', '거제시 장승로 112', '010-2636-5313', 35.05, 128.41, 'md', 0, 0, 0, 0, 0, 8),
('해양환경공단', '동해지방해양경찰청', '동해', '동해지사', '동해시 대동로 210', '010-7499-0257', 37.515, 129.105, 'md', 0, 0, 0, 0, 2, 17),
('해양환경공단', '동해지방해양경찰청', '울진', '포항지사', '울진군 죽변면 죽변리 36-88', '054-273-5595', 37.06, 129.42, 'md', 0, 0, 0, 0, 0, 2),
('해양환경공단', '동해지방해양경찰청', '포항', '포항지사', '포항시 북구 해안로 44-10', '054-273-5595', 36.025, 129.375, 'md', 0, 0, 0, 0, 2, 8),
('해양환경공단', '서해지방해양경찰청', '군산', '군산지사', '군산시 임해로 452', '063-443-4813', 35.975, 126.715, 'md', 0, 0, 0, 0, 4, 12),
('해양환경공단', '서해지방해양경찰청', '목포', '목포지사', '전남 목포시 죽교동 683', '061-242-9663', 35.04, 126.58, 'md', 0, 0, 0, 0, 0, 10),
('해양환경공단', '서해지방해양경찰청', '여수', '여수지사', '여수시 덕충동', '061-654-6431', 34.742, 127.748, 'md', 0, 0, 0, 0, 3, 12),
('해양환경공단', '서해지방해양경찰청', '완도', '목포지사 완도사업소', '완도군 완도읍 해변공원로 20-1', '061-242-9663', 34.315, 126.755, 'md', 0, 0, 0, 0, 0, 3),
('해양환경공단', '제주지방해양경찰청', '서귀포', '제주지사(서귀포)', '서귀포시 칠십리로72번길 14', '064-753-4356', 33.245, 126.565, 'md', 0, 0, 0, 0, 1, 1),
('해양환경공단', '제주지방해양경찰청', '제주', '제주지사(제주)', '제주시 임항로97', '064-753-4356', 33.517, 126.528, 'md', 0, 0, 0, 0, 3, 20),
('해양환경공단', '중부지방해양경찰청', '보령', '대산지사(보령)', '보령시 해안로 740', '041-664-9101', 36.333, 126.612, 'md', 0, 0, 0, 0, 0, 5),
('해양환경공단', '중부지방해양경찰청', '인천', '인천지사', '인천광역시 중구 연안부두로 128번길 35', '010-7133-2167', 37.45, 126.505, 'md', 0, 0, 0, 0, 0, 11),
('해양환경공단', '중부지방해양경찰청', '태안', '대산지사(태안)', '서산시 대산읍 대죽1로 325', '041-664-9101', 36.908, 126.413, 'md', 0, 0, 0, 0, 1, 17),
('해양환경공단', '중부지방해양경찰청', '평택', '평택지사', '당진시 송악읍 고대공단2길', '031-683-7973', 36.905, 126.635, 'md', 0, 0, 0, 0, 1, 13),
('기타', '남해지방해양경찰청', '통영', '삼성중공업 외 1개', '거제시 장평3로 80', '055-630-5373', 35.05, 128.41, 'md', 0, 0, 0, 0, 0, 1);
-- ============================================================
-- ASSET_EQUIP 초기 데이터
-- ============================================================
-- 인천해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천해양경찰서' LIMIT 1), '방제선', '🚢', 19, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천해양경찰서' LIMIT 1), '유회수기', '', 30, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천해양경찰서' LIMIT 1), '비치크리너', '🏖', 2, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천해양경찰서' LIMIT 1), '이송펌프', '🔧', 18, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천해양경찰서' LIMIT 1), '방제차량', '🚛', 2, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천해양경찰서' LIMIT 1), '해안운반차', '🚜', 1, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천해양경찰서' LIMIT 1), '고압세척기', '💧', 26, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천해양경찰서' LIMIT 1), '저압세척기', '🚿', 3, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천해양경찰서' LIMIT 1), '동력분무기', '💨', 14, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천해양경찰서' LIMIT 1), '방제창고', '🏭', 19, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천해양경찰서' LIMIT 1), '발전기', '', 9, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천해양경찰서' LIMIT 1), '현장지휘소', '🏕', 2, 12),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천해양경찰서' LIMIT 1), '지원장비', '🔩', 9, 13),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천해양경찰서' LIMIT 1), '장비부품', '🔗', 46, 14),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천해양경찰서' LIMIT 1), '경비함정방제', '', 18, 15),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천해양경찰서' LIMIT 1), '살포장치', '🌊', 15, 16);
-- 평택해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택해양경찰서' LIMIT 1), '방제선', '🚢', 14, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택해양경찰서' LIMIT 1), '유회수기', '', 27, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택해양경찰서' LIMIT 1), '비치크리너', '🏖', 1, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택해양경찰서' LIMIT 1), '이송펌프', '🔧', 33, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택해양경찰서' LIMIT 1), '방제차량', '🚛', 3, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택해양경찰서' LIMIT 1), '해안운반차', '🚜', 1, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택해양경찰서' LIMIT 1), '고압세척기', '💧', 12, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택해양경찰서' LIMIT 1), '저압세척기', '🚿', 5, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택해양경찰서' LIMIT 1), '동력분무기', '💨', 2, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택해양경찰서' LIMIT 1), '방제창고', '🏭', 35, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택해양경찰서' LIMIT 1), '발전기', '', 9, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택해양경찰서' LIMIT 1), '지원장비', '🔩', 10, 12),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택해양경찰서' LIMIT 1), '장비부품', '🔗', 4, 13),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택해양경찰서' LIMIT 1), '경비함정방제', '', 14, 14),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택해양경찰서' LIMIT 1), '살포장치', '🌊', 22, 15);
-- 태안해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '태안해양경찰서' LIMIT 1), '방제선', '🚢', 10, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '태안해양경찰서' LIMIT 1), '유회수기', '', 27, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '태안해양경찰서' LIMIT 1), '비치크리너', '🏖', 4, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '태안해양경찰서' LIMIT 1), '이송펌프', '🔧', 21, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '태안해양경찰서' LIMIT 1), '방제차량', '🚛', 8, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '태안해양경찰서' LIMIT 1), '해안운반차', '🚜', 8, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '태안해양경찰서' LIMIT 1), '고압세척기', '💧', 14, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '태안해양경찰서' LIMIT 1), '저압세척기', '🚿', 8, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '태안해양경찰서' LIMIT 1), '동력분무기', '💨', 6, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '태안해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '태안해양경찰서' LIMIT 1), '방제창고', '🏭', 28, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '태안해양경찰서' LIMIT 1), '발전기', '', 11, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '태안해양경찰서' LIMIT 1), '지원장비', '🔩', 16, 12),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '태안해양경찰서' LIMIT 1), '경비함정방제', '', 8, 13),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '태안해양경찰서' LIMIT 1), '살포장치', '🌊', 15, 14);
-- 보령해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '보령해양경찰서' LIMIT 1), '방제선', '🚢', 3, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '보령해양경찰서' LIMIT 1), '유회수기', '', 8, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '보령해양경찰서' LIMIT 1), '이송펌프', '🔧', 5, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '보령해양경찰서' LIMIT 1), '방제차량', '🚛', 3, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '보령해양경찰서' LIMIT 1), '해안운반차', '🚜', 1, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '보령해양경찰서' LIMIT 1), '고압세척기', '💧', 5, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '보령해양경찰서' LIMIT 1), '저압세척기', '🚿', 2, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '보령해양경찰서' LIMIT 1), '동력분무기', '💨', 1, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '보령해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '보령해양경찰서' LIMIT 1), '방제창고', '🏭', 22, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '보령해양경찰서' LIMIT 1), '발전기', '', 2, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '보령해양경찰서' LIMIT 1), '지원장비', '🔩', 6, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '보령해양경찰서' LIMIT 1), '장비부품', '🔗', 4, 12),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '보령해양경찰서' LIMIT 1), '경비함정방제', '', 6, 13),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '보령해양경찰서' LIMIT 1), '살포장치', '🌊', 11, 14);
-- 여수해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수해양경찰서' LIMIT 1), '방제선', '🚢', 55, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수해양경찰서' LIMIT 1), '유회수기', '', 92, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수해양경찰서' LIMIT 1), '비치크리너', '🏖', 5, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수해양경찰서' LIMIT 1), '이송펌프', '🔧', 63, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수해양경찰서' LIMIT 1), '방제차량', '🚛', 12, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수해양경찰서' LIMIT 1), '해안운반차', '🚜', 4, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수해양경찰서' LIMIT 1), '고압세척기', '💧', 48, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수해양경찰서' LIMIT 1), '저압세척기', '🚿', 7, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수해양경찰서' LIMIT 1), '동력분무기', '💨', 25, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수해양경찰서' LIMIT 1), '방제창고', '🏭', 37, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수해양경찰서' LIMIT 1), '발전기', '', 16, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수해양경찰서' LIMIT 1), '현장지휘소', '🏕', 2, 12),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수해양경찰서' LIMIT 1), '지원장비', '🔩', 14, 13),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수해양경찰서' LIMIT 1), '장비부품', '🔗', 14, 14),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수해양경찰서' LIMIT 1), '경비함정방제', '', 22, 15),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수해양경찰서' LIMIT 1), '살포장치', '🌊', 47, 16);
-- 목포해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포해양경찰서' LIMIT 1), '방제선', '🚢', 10, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포해양경찰서' LIMIT 1), '유회수기', '', 19, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포해양경찰서' LIMIT 1), '이송펌프', '🔧', 18, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포해양경찰서' LIMIT 1), '방제차량', '🚛', 3, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포해양경찰서' LIMIT 1), '해안운반차', '🚜', 1, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포해양경찰서' LIMIT 1), '고압세척기', '💧', 7, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포해양경찰서' LIMIT 1), '저압세척기', '🚿', 4, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포해양경찰서' LIMIT 1), '동력분무기', '💨', 2, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포해양경찰서' LIMIT 1), '방제창고', '🏭', 21, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포해양경찰서' LIMIT 1), '발전기', '', 4, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포해양경찰서' LIMIT 1), '지원장비', '🔩', 31, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포해양경찰서' LIMIT 1), '장비부품', '🔗', 17, 12),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포해양경찰서' LIMIT 1), '경비함정방제', '', 15, 13),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포해양경찰서' LIMIT 1), '살포장치', '🌊', 16, 14);
-- 군산해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산해양경찰서' LIMIT 1), '방제선', '🚢', 6, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산해양경찰서' LIMIT 1), '유회수기', '', 22, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산해양경찰서' LIMIT 1), '비치크리너', '🏖', 2, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산해양경찰서' LIMIT 1), '이송펌프', '🔧', 12, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산해양경찰서' LIMIT 1), '방제차량', '🚛', 3, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산해양경찰서' LIMIT 1), '해안운반차', '🚜', 1, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산해양경찰서' LIMIT 1), '고압세척기', '💧', 5, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산해양경찰서' LIMIT 1), '저압세척기', '🚿', 4, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산해양경찰서' LIMIT 1), '동력분무기', '💨', 2, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산해양경찰서' LIMIT 1), '방제창고', '🏭', 6, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산해양경찰서' LIMIT 1), '발전기', '', 5, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산해양경찰서' LIMIT 1), '현장지휘소', '🏕', 3, 12),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산해양경찰서' LIMIT 1), '지원장비', '🔩', 11, 13),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산해양경찰서' LIMIT 1), '장비부품', '🔗', 50, 14),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산해양경찰서' LIMIT 1), '경비함정방제', '', 5, 15),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산해양경찰서' LIMIT 1), '살포장치', '🌊', 17, 16);
-- 완도해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '완도해양경찰서' LIMIT 1), '방제선', '🚢', 3, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '완도해양경찰서' LIMIT 1), '유회수기', '', 9, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '완도해양경찰서' LIMIT 1), '이송펌프', '🔧', 7, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '완도해양경찰서' LIMIT 1), '방제차량', '🚛', 3, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '완도해양경찰서' LIMIT 1), '해안운반차', '🚜', 1, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '완도해양경찰서' LIMIT 1), '고압세척기', '💧', 3, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '완도해양경찰서' LIMIT 1), '저압세척기', '🚿', 2, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '완도해양경찰서' LIMIT 1), '동력분무기', '💨', 1, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '완도해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '완도해양경찰서' LIMIT 1), '방제창고', '🏭', 24, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '완도해양경찰서' LIMIT 1), '발전기', '', 2, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '완도해양경찰서' LIMIT 1), '경비함정방제', '', 8, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '완도해양경찰서' LIMIT 1), '살포장치', '🌊', 11, 12);
-- 부안해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부안해양경찰서' LIMIT 1), '방제선', '🚢', 2, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부안해양경찰서' LIMIT 1), '유회수기', '', 8, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부안해양경찰서' LIMIT 1), '이송펌프', '🔧', 7, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부안해양경찰서' LIMIT 1), '방제차량', '🚛', 2, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부안해양경찰서' LIMIT 1), '해안운반차', '🚜', 1, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부안해양경찰서' LIMIT 1), '고압세척기', '💧', 2, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부안해양경찰서' LIMIT 1), '저압세척기', '🚿', 2, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부안해양경찰서' LIMIT 1), '동력분무기', '💨', 1, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부안해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부안해양경찰서' LIMIT 1), '방제창고', '🏭', 15, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부안해양경찰서' LIMIT 1), '발전기', '', 3, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부안해양경찰서' LIMIT 1), '현장지휘소', '🏕', 2, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부안해양경찰서' LIMIT 1), '지원장비', '🔩', 6, 12),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부안해양경찰서' LIMIT 1), '경비함정방제', '', 7, 13),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부안해양경찰서' LIMIT 1), '살포장치', '🌊', 7, 14);
-- 부산해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산해양경찰서' LIMIT 1), '방제선', '🚢', 108, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산해양경찰서' LIMIT 1), '유회수기', '', 22, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산해양경찰서' LIMIT 1), '이송펌프', '🔧', 25, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산해양경찰서' LIMIT 1), '방제차량', '🚛', 10, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산해양경찰서' LIMIT 1), '해안운반차', '🚜', 1, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산해양경찰서' LIMIT 1), '고압세척기', '💧', 38, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산해양경찰서' LIMIT 1), '저압세척기', '🚿', 8, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산해양경찰서' LIMIT 1), '동력분무기', '💨', 6, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산해양경찰서' LIMIT 1), '방제창고', '🏭', 21, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산해양경찰서' LIMIT 1), '발전기', '', 11, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산해양경찰서' LIMIT 1), '현장지휘소', '🏕', 2, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산해양경찰서' LIMIT 1), '지원장비', '🔩', 20, 12),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산해양경찰서' LIMIT 1), '경비함정방제', '', 16, 13),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산해양경찰서' LIMIT 1), '살포장치', '🌊', 24, 14);
-- 울산해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산해양경찰서' LIMIT 1), '방제선', '🚢', 46, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산해양경찰서' LIMIT 1), '유회수기', '', 69, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산해양경찰서' LIMIT 1), '비치크리너', '🏖', 4, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산해양경찰서' LIMIT 1), '이송펌프', '🔧', 26, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산해양경찰서' LIMIT 1), '방제차량', '🚛', 11, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산해양경찰서' LIMIT 1), '해안운반차', '🚜', 5, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산해양경찰서' LIMIT 1), '고압세척기', '💧', 23, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산해양경찰서' LIMIT 1), '저압세척기', '🚿', 6, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산해양경찰서' LIMIT 1), '동력분무기', '💨', 6, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산해양경찰서' LIMIT 1), '방제창고', '🏭', 32, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산해양경찰서' LIMIT 1), '발전기', '', 7, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산해양경찰서' LIMIT 1), '현장지휘소', '🏕', 1, 12),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산해양경찰서' LIMIT 1), '지원장비', '🔩', 40, 13),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산해양경찰서' LIMIT 1), '경비함정방제', '', 14, 14),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산해양경찰서' LIMIT 1), '살포장치', '🌊', 20, 15);
-- 창원해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원해양경찰서' LIMIT 1), '방제선', '🚢', 12, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원해양경찰서' LIMIT 1), '유회수기', '', 25, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원해양경찰서' LIMIT 1), '비치크리너', '🏖', 2, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원해양경찰서' LIMIT 1), '이송펌프', '🔧', 14, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원해양경찰서' LIMIT 1), '방제차량', '🚛', 10, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원해양경찰서' LIMIT 1), '해안운반차', '🚜', 1, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원해양경찰서' LIMIT 1), '고압세척기', '💧', 7, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원해양경찰서' LIMIT 1), '저압세척기', '🚿', 2, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원해양경찰서' LIMIT 1), '동력분무기', '💨', 1, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원해양경찰서' LIMIT 1), '방제창고', '🏭', 21, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원해양경찰서' LIMIT 1), '발전기', '', 4, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원해양경찰서' LIMIT 1), '현장지휘소', '🏕', 2, 12),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원해양경찰서' LIMIT 1), '지원장비', '🔩', 20, 13),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원해양경찰서' LIMIT 1), '경비함정방제', '', 7, 14),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원해양경찰서' LIMIT 1), '살포장치', '🌊', 10, 15);
-- 통영해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '통영해양경찰서' LIMIT 1), '방제선', '🚢', 6, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '통영해양경찰서' LIMIT 1), '유회수기', '', 15, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '통영해양경찰서' LIMIT 1), '비치크리너', '🏖', 2, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '통영해양경찰서' LIMIT 1), '이송펌프', '🔧', 9, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '통영해양경찰서' LIMIT 1), '방제차량', '🚛', 5, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '통영해양경찰서' LIMIT 1), '해안운반차', '🚜', 1, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '통영해양경찰서' LIMIT 1), '고압세척기', '💧', 3, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '통영해양경찰서' LIMIT 1), '저압세척기', '🚿', 2, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '통영해양경찰서' LIMIT 1), '동력분무기', '💨', 1, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '통영해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '통영해양경찰서' LIMIT 1), '방제창고', '🏭', 18, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '통영해양경찰서' LIMIT 1), '발전기', '', 4, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '통영해양경찰서' LIMIT 1), '현장지휘소', '🏕', 1, 12),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '통영해양경찰서' LIMIT 1), '지원장비', '🔩', 11, 13),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '통영해양경찰서' LIMIT 1), '경비함정방제', '', 12, 14),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '통영해양경찰서' LIMIT 1), '살포장치', '🌊', 13, 15);
-- 사천해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '사천해양경찰서' LIMIT 1), '방제선', '🚢', 2, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '사천해양경찰서' LIMIT 1), '유회수기', '', 9, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '사천해양경찰서' LIMIT 1), '이송펌프', '🔧', 6, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '사천해양경찰서' LIMIT 1), '방제차량', '🚛', 2, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '사천해양경찰서' LIMIT 1), '해안운반차', '🚜', 1, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '사천해양경찰서' LIMIT 1), '고압세척기', '💧', 2, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '사천해양경찰서' LIMIT 1), '저압세척기', '🚿', 2, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '사천해양경찰서' LIMIT 1), '동력분무기', '💨', 4, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '사천해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '사천해양경찰서' LIMIT 1), '방제창고', '🏭', 31, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '사천해양경찰서' LIMIT 1), '발전기', '', 2, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '사천해양경찰서' LIMIT 1), '현장지휘소', '🏕', 2, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '사천해양경찰서' LIMIT 1), '지원장비', '🔩', 1, 12),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '사천해양경찰서' LIMIT 1), '경비함정방제', '', 8, 13),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '사천해양경찰서' LIMIT 1), '살포장치', '🌊', 7, 14);
-- 동해해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해해양경찰서' LIMIT 1), '방제선', '🚢', 6, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해해양경찰서' LIMIT 1), '유회수기', '', 23, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해해양경찰서' LIMIT 1), '비치크리너', '🏖', 1, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해해양경찰서' LIMIT 1), '이송펌프', '🔧', 11, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해해양경찰서' LIMIT 1), '방제차량', '🚛', 6, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해해양경찰서' LIMIT 1), '해안운반차', '🚜', 3, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해해양경찰서' LIMIT 1), '고압세척기', '💧', 5, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해해양경찰서' LIMIT 1), '저압세척기', '🚿', 2, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해해양경찰서' LIMIT 1), '동력분무기', '💨', 5, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해해양경찰서' LIMIT 1), '방제창고', '🏭', 38, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해해양경찰서' LIMIT 1), '발전기', '', 2, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해해양경찰서' LIMIT 1), '현장지휘소', '🏕', 1, 12),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해해양경찰서' LIMIT 1), '지원장비', '🔩', 20, 13),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해해양경찰서' LIMIT 1), '장비부품', '🔗', 10, 14),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해해양경찰서' LIMIT 1), '경비함정방제', '', 8, 15),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해해양경찰서' LIMIT 1), '살포장치', '🌊', 14, 16);
-- 포항해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항해양경찰서' LIMIT 1), '방제선', '🚢', 10, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항해양경찰서' LIMIT 1), '유회수기', '', 13, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항해양경찰서' LIMIT 1), '비치크리너', '🏖', 1, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항해양경찰서' LIMIT 1), '이송펌프', '🔧', 21, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항해양경찰서' LIMIT 1), '방제차량', '🚛', 4, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항해양경찰서' LIMIT 1), '해안운반차', '🚜', 1, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항해양경찰서' LIMIT 1), '고압세척기', '💧', 7, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항해양경찰서' LIMIT 1), '저압세척기', '🚿', 2, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항해양경찰서' LIMIT 1), '동력분무기', '💨', 3, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항해양경찰서' LIMIT 1), '방제창고', '🏭', 15, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항해양경찰서' LIMIT 1), '발전기', '', 5, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항해양경찰서' LIMIT 1), '현장지휘소', '🏕', 1, 12),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항해양경찰서' LIMIT 1), '지원장비', '🔩', 20, 13),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항해양경찰서' LIMIT 1), '경비함정방제', '', 10, 14),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항해양경찰서' LIMIT 1), '살포장치', '🌊', 21, 15);
-- 속초해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '속초해양경찰서' LIMIT 1), '방제선', '🚢', 2, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '속초해양경찰서' LIMIT 1), '유회수기', '', 6, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '속초해양경찰서' LIMIT 1), '이송펌프', '🔧', 4, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '속초해양경찰서' LIMIT 1), '방제차량', '🚛', 1, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '속초해양경찰서' LIMIT 1), '해안운반차', '🚜', 1, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '속초해양경찰서' LIMIT 1), '고압세척기', '💧', 2, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '속초해양경찰서' LIMIT 1), '저압세척기', '🚿', 2, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '속초해양경찰서' LIMIT 1), '동력분무기', '💨', 1, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '속초해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '속초해양경찰서' LIMIT 1), '방제창고', '🏭', 16, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '속초해양경찰서' LIMIT 1), '발전기', '', 2, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '속초해양경찰서' LIMIT 1), '지원장비', '🔩', 11, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '속초해양경찰서' LIMIT 1), '장비부품', '🔗', 11, 12),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '속초해양경찰서' LIMIT 1), '경비함정방제', '', 8, 13),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '속초해양경찰서' LIMIT 1), '살포장치', '🌊', 17, 14);
-- 울진해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울진해양경찰서' LIMIT 1), '방제선', '🚢', 2, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울진해양경찰서' LIMIT 1), '유회수기', '', 6, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울진해양경찰서' LIMIT 1), '이송펌프', '🔧', 4, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울진해양경찰서' LIMIT 1), '방제차량', '🚛', 1, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울진해양경찰서' LIMIT 1), '해안운반차', '🚜', 1, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울진해양경찰서' LIMIT 1), '고압세척기', '💧', 3, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울진해양경찰서' LIMIT 1), '저압세척기', '🚿', 2, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울진해양경찰서' LIMIT 1), '동력분무기', '💨', 1, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울진해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울진해양경찰서' LIMIT 1), '방제창고', '🏭', 13, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울진해양경찰서' LIMIT 1), '발전기', '', 4, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울진해양경찰서' LIMIT 1), '현장지휘소', '🏕', 2, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울진해양경찰서' LIMIT 1), '지원장비', '🔩', 4, 12),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울진해양경찰서' LIMIT 1), '장비부품', '🔗', 4, 13),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울진해양경찰서' LIMIT 1), '경비함정방제', '', 10, 14),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울진해양경찰서' LIMIT 1), '살포장치', '🌊', 8, 15);
-- 제주해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주해양경찰서' LIMIT 1), '방제선', '🚢', 4, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주해양경찰서' LIMIT 1), '유회수기', '', 21, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주해양경찰서' LIMIT 1), '비치크리너', '🏖', 2, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주해양경찰서' LIMIT 1), '이송펌프', '🔧', 17, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주해양경찰서' LIMIT 1), '방제차량', '🚛', 3, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주해양경찰서' LIMIT 1), '해안운반차', '🚜', 1, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주해양경찰서' LIMIT 1), '고압세척기', '💧', 5, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주해양경찰서' LIMIT 1), '저압세척기', '🚿', 3, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주해양경찰서' LIMIT 1), '동력분무기', '💨', 4, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주해양경찰서' LIMIT 1), '방제창고', '🏭', 24, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주해양경찰서' LIMIT 1), '발전기', '', 6, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주해양경찰서' LIMIT 1), '현장지휘소', '🏕', 2, 12),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주해양경찰서' LIMIT 1), '경비함정방제', '', 4, 13),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주해양경찰서' LIMIT 1), '살포장치', '🌊', 16, 14);
-- 서귀포해양경찰서
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '서귀포해양경찰서' LIMIT 1), '방제선', '🚢', 3, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '서귀포해양경찰서' LIMIT 1), '유회수기', '', 9, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '서귀포해양경찰서' LIMIT 1), '비치크리너', '🏖', 1, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '서귀포해양경찰서' LIMIT 1), '이송펌프', '🔧', 15, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '서귀포해양경찰서' LIMIT 1), '방제차량', '🚛', 3, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '서귀포해양경찰서' LIMIT 1), '해안운반차', '🚜', 1, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '서귀포해양경찰서' LIMIT 1), '고압세척기', '💧', 2, 6),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '서귀포해양경찰서' LIMIT 1), '동력분무기', '💨', 1, 7),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '서귀포해양경찰서' LIMIT 1), '유량계측기', '📏', 1, 8),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '서귀포해양경찰서' LIMIT 1), '방제창고', '🏭', 10, 9),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '서귀포해양경찰서' LIMIT 1), '발전기', '', 3, 10),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '서귀포해양경찰서' LIMIT 1), '경비함정방제', '', 4, 11),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '서귀포해양경찰서' LIMIT 1), '살포장치', '🌊', 14, 12);
-- 중앙특수구조단
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '중앙특수구조단' LIMIT 1), '방제선', '🚢', 1, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '중앙특수구조단' LIMIT 1), '이송펌프', '🔧', 5, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '중앙특수구조단' LIMIT 1), '방제차량', '🚛', 2, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '중앙특수구조단' LIMIT 1), '유량계측기', '📏', 1, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '중앙특수구조단' LIMIT 1), '발전기', '', 2, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '중앙특수구조단' LIMIT 1), '지원장비', '🔩', 27, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '중앙특수구조단' LIMIT 1), '경비함정방제', '', 1, 6);
-- 오일허브코리아여수㈜ 외 4개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '오일허브코리아여수㈜ 외 4개' LIMIT 1), '고압세척기', '💧', 1, 0);
-- SK에너지 외 2개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'SK에너지 외 2개' LIMIT 1), '고압세척기', '💧', 1, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'SK에너지 외 2개' LIMIT 1), '동력분무기', '💨', 1, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'SK에너지 외 2개' LIMIT 1), '방제창고', '🏭', 1, 2);
-- SK지오센트릭 외 5개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'SK지오센트릭 외 5개' LIMIT 1), '동력분무기', '💨', 4, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'SK지오센트릭 외 5개' LIMIT 1), '방제창고', '🏭', 5, 1);
-- 한국가스공사 통영기지본부
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '한국가스공사 통영기지본부' LIMIT 1), '방제창고', '🏭', 1, 0);
-- HD현대오일뱅크㈜ 외 4개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'HD현대오일뱅크㈜ 외 4개' LIMIT 1), '동력분무기', '💨', 2, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'HD현대오일뱅크㈜ 외 4개' LIMIT 1), '방제창고', '🏭', 6, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'HD현대오일뱅크㈜ 외 4개' LIMIT 1), '발전기', '', 1, 2);
-- 포스코케미칼 외 1개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포스코케미칼 외 1개' LIMIT 1), '동력분무기', '💨', 1, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포스코케미칼 외 1개' LIMIT 1), '살포장치', '🌊', 1, 1);
-- 흑산도내연발전소 외 2개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '흑산도내연발전소 외 2개' LIMIT 1), '고압세척기', '💧', 3, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '흑산도내연발전소 외 2개' LIMIT 1), '발전기', '', 1, 1);
-- 오일허브코리아여수㈜ 외 4개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '오일허브코리아여수㈜ 외 4개' LIMIT 1), '동력분무기', '💨', 1, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '오일허브코리아여수㈜ 외 4개' LIMIT 1), '방제창고', '🏭', 3, 1);
-- GS칼텍스㈜ 외 10개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'GS칼텍스㈜ 외 10개' LIMIT 1), '고압세척기', '💧', 7, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'GS칼텍스㈜ 외 10개' LIMIT 1), '동력분무기', '💨', 6, 1);
-- HD현대케미칼 외 4개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'HD현대케미칼 외 4개' LIMIT 1), '해안운반차', '🚜', 2, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'HD현대케미칼 외 4개' LIMIT 1), '동력분무기', '💨', 2, 1);
-- 현대오일터미널(주) 외 4개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '현대오일터미널(주) 외 4개' LIMIT 1), '고압세척기', '💧', 2, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '현대오일터미널(주) 외 4개' LIMIT 1), '발전기', '', 1, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '현대오일터미널(주) 외 4개' LIMIT 1), '살포장치', '🌊', 1, 2);
-- 한국남동발전(주) 외 2개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '한국남동발전(주) 외 2개' LIMIT 1), '동력분무기', '💨', 3, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '한국남동발전(주) 외 2개' LIMIT 1), '방제창고', '🏭', 5, 1);
-- HD현대미포
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'HD현대미포' LIMIT 1), '방제창고', '🏭', 1, 0);
-- 삼성중공업 외 1개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '삼성중공업 외 1개' LIMIT 1), '동력분무기', '💨', 2, 0);
-- 한국남부발전㈜
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '한국남부발전㈜' LIMIT 1), '방제창고', '🏭', 2, 0);
-- 한울원전
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '한울원전' LIMIT 1), '방제창고', '🏭', 2, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '한울원전' LIMIT 1), '지원장비', '🔩', 2, 1);
-- ㈜HR-PORT 외 5개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '㈜HR-PORT 외 5개' LIMIT 1), '고압세척기', '💧', 1, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '㈜HR-PORT 외 5개' LIMIT 1), '저압세척기', '🚿', 1, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '㈜HR-PORT 외 5개' LIMIT 1), '동력분무기', '💨', 7, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '㈜HR-PORT 외 5개' LIMIT 1), '방제창고', '🏭', 3, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '㈜HR-PORT 외 5개' LIMIT 1), '발전기', '', 1, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '㈜HR-PORT 외 5개' LIMIT 1), '지원장비', '🔩', 3, 5);
-- 삼광조선공업㈜ 외 1개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '삼광조선공업㈜ 외 1개' LIMIT 1), '고압세척기', '💧', 5, 0);
-- 방제유창청소업체(㈜클린포트)
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(㈜클린포트)' LIMIT 1), '고압세척기', '💧', 2, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(㈜클린포트)' LIMIT 1), '발전기', '', 1, 1);
-- 방제유창청소업체(대용환경㈜ 외 38개)
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(대용환경㈜ 외 38개)' LIMIT 1), '고압세척기', '💧', 31, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(대용환경㈜ 외 38개)' LIMIT 1), '저압세척기', '🚿', 5, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(대용환경㈜ 외 38개)' LIMIT 1), '동력분무기', '💨', 3, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(대용환경㈜ 외 38개)' LIMIT 1), '방제창고', '🏭', 5, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(대용환경㈜ 외 38개)' LIMIT 1), '발전기', '', 6, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(대용환경㈜ 외 38개)' LIMIT 1), '현장지휘소', '🏕', 1, 5);
-- 방제유창청소업체((주)한유마린서비스 외 8개)
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체((주)한유마린서비스 외 8개)' LIMIT 1), '고압세척기', '💧', 11, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체((주)한유마린서비스 외 8개)' LIMIT 1), '방제창고', '🏭', 1, 1);
-- 방제유창청소업체(블루씨 외 1개)
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(블루씨 외 1개)' LIMIT 1), '고압세척기', '💧', 2, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(블루씨 외 1개)' LIMIT 1), '살포장치', '🌊', 1, 1);
-- 방제유창청소업체(㈜한국해운 외 1개)
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(㈜한국해운 외 1개)' LIMIT 1), '고압세척기', '💧', 1, 0);
-- 방제유창청소업체(마로해운 외 11개)
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(마로해운 외 11개)' LIMIT 1), '고압세척기', '💧', 28, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(마로해운 외 11개)' LIMIT 1), '동력분무기', '💨', 15, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(마로해운 외 11개)' LIMIT 1), '방제창고', '🏭', 5, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(마로해운 외 11개)' LIMIT 1), '발전기', '', 4, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(마로해운 외 11개)' LIMIT 1), '살포장치', '🌊', 2, 4);
-- 방제유창청소업체(우진해운㈜)
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(우진해운㈜)' LIMIT 1), '고압세척기', '💧', 3, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(우진해운㈜)' LIMIT 1), '저압세척기', '🚿', 1, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(우진해운㈜)' LIMIT 1), '발전기', '', 2, 2);
-- 방제유창청소업체((주)씨앤 외 3개)
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체((주)씨앤 외 3개)' LIMIT 1), '고압세척기', '💧', 3, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체((주)씨앤 외 3개)' LIMIT 1), '저압세척기', '🚿', 1, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체((주)씨앤 외 3개)' LIMIT 1), '발전기', '', 2, 2);
-- 방제유창청소업체(㈜지앤비마린서비스)
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(㈜지앤비마린서비스)' LIMIT 1), '방제창고', '🏭', 1, 0);
-- SK엔텀(주) 외 4개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'SK엔텀(주) 외 4개' LIMIT 1), '방제창고', '🏭', 5, 0);
-- GS칼텍스㈜
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'GS칼텍스㈜' LIMIT 1), '고압세척기', '💧', 3, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'GS칼텍스㈜' LIMIT 1), '방제창고', '🏭', 4, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'GS칼텍스㈜' LIMIT 1), '살포장치', '🌊', 20, 2);
-- HD현대오일뱅크㈜
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'HD현대오일뱅크㈜' LIMIT 1), '동력분무기', '💨', 2, 0);
-- 부산광역시 외 8개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산광역시 외 8개' LIMIT 1), '고압세척기', '💧', 1, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산광역시 외 8개' LIMIT 1), '방제창고', '🏭', 11, 1);
-- 사천시 외 3개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '사천시 외 3개' LIMIT 1), '방제창고', '🏭', 6, 0);
-- 울산북구청 외 2개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산북구청 외 2개' LIMIT 1), '방제창고', '🏭', 4, 0);
-- 창원 진해구 외 1개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원 진해구 외 1개' LIMIT 1), '고압세척기', '💧', 1, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원 진해구 외 1개' LIMIT 1), '방제창고', '🏭', 1, 1);
-- 삼척시 외 1개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '삼척시 외 1개' LIMIT 1), '고압세척기', '💧', 1, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '삼척시 외 1개' LIMIT 1), '방제창고', '🏭', 3, 1);
-- 영덕군
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '영덕군' LIMIT 1), '방제창고', '🏭', 3, 0);
-- 영광군 외 1개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '영광군 외 1개' LIMIT 1), '방제창고', '🏭', 5, 0);
-- 광양시 외 1개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '광양시 외 1개' LIMIT 1), '방제창고', '🏭', 3, 0);
-- 옹진군청 외 4개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '옹진군청 외 4개' LIMIT 1), '고압세척기', '💧', 5, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '옹진군청 외 4개' LIMIT 1), '동력분무기', '💨', 4, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '옹진군청 외 4개' LIMIT 1), '발전기', '', 1, 2);
-- 태안군청
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '태안군청' LIMIT 1), '방제창고', '🏭', 1, 0);
-- 안산시청 외 2개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '안산시청 외 2개' LIMIT 1), '동력분무기', '💨', 1, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '안산시청 외 2개' LIMIT 1), '방제창고', '🏭', 5, 1);
-- ㈜HR-PORT 외 5개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '㈜HR-PORT 외 5개' LIMIT 1), '방제창고', '🏭', 1, 0);
-- 해군1함대사령부 외 1개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '해군1함대사령부 외 1개' LIMIT 1), '방제창고', '🏭', 1, 0);
-- 해병대 제9518부대
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '해병대 제9518부대' LIMIT 1), '발전기', '', 2, 0);
-- 부산지사
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산지사' LIMIT 1), '고압세척기', '💧', 3, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산지사' LIMIT 1), '저압세척기', '🚿', 1, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산지사' LIMIT 1), '방제창고', '🏭', 1, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산지사' LIMIT 1), '발전기', '', 2, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산지사' LIMIT 1), '현장지휘소', '🏕', 1, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산지사' LIMIT 1), '살포장치', '🌊', 6, 5);
-- 마산지사
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '마산지사' LIMIT 1), '방제창고', '🏭', 8, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '마산지사' LIMIT 1), '발전기', '', 1, 1);
-- 울산지사
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산지사' LIMIT 1), '고압세척기', '💧', 6, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산지사' LIMIT 1), '저압세척기', '🚿', 1, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산지사' LIMIT 1), '방제창고', '🏭', 4, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산지사' LIMIT 1), '발전기', '', 4, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산지사' LIMIT 1), '살포장치', '🌊', 1, 4);
-- 마산지사
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '마산지사' LIMIT 1), '고압세척기', '💧', 4, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '마산지사' LIMIT 1), '발전기', '', 2, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '마산지사' LIMIT 1), '살포장치', '🌊', 1, 2);
-- 마산지사
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '마산지사' LIMIT 1), '방제창고', '🏭', 8, 0);
-- 동해지사
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해지사' LIMIT 1), '해안운반차', '🚜', 2, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해지사' LIMIT 1), '고압세척기', '💧', 2, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해지사' LIMIT 1), '동력분무기', '💨', 2, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해지사' LIMIT 1), '방제창고', '🏭', 8, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해지사' LIMIT 1), '발전기', '', 1, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해지사' LIMIT 1), '살포장치', '🌊', 2, 5);
-- 포항지사
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항지사' LIMIT 1), '방제창고', '🏭', 2, 0);
-- 포항지사
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항지사' LIMIT 1), '고압세척기', '💧', 2, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항지사' LIMIT 1), '동력분무기', '💨', 1, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항지사' LIMIT 1), '발전기', '', 2, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항지사' LIMIT 1), '현장지휘소', '🏕', 1, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항지사' LIMIT 1), '살포장치', '🌊', 2, 4);
-- 군산지사
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산지사' LIMIT 1), '고압세척기', '💧', 2, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산지사' LIMIT 1), '저압세척기', '🚿', 2, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산지사' LIMIT 1), '동력분무기', '💨', 1, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산지사' LIMIT 1), '발전기', '', 3, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산지사' LIMIT 1), '살포장치', '🌊', 4, 4);
-- 목포지사
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포지사' LIMIT 1), '고압세척기', '💧', 1, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포지사' LIMIT 1), '저압세척기', '🚿', 2, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포지사' LIMIT 1), '방제창고', '🏭', 6, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포지사' LIMIT 1), '발전기', '', 1, 3);
-- 여수지사
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수지사' LIMIT 1), '고압세척기', '💧', 5, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수지사' LIMIT 1), '저압세척기', '🚿', 1, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수지사' LIMIT 1), '발전기', '', 3, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수지사' LIMIT 1), '살포장치', '🌊', 3, 3);
-- 목포지사 완도사업소
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포지사 완도사업소' LIMIT 1), '고압세척기', '💧', 1, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포지사 완도사업소' LIMIT 1), '방제창고', '🏭', 2, 1);
-- 제주지사(서귀포)
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주지사(서귀포)' LIMIT 1), '살포장치', '🌊', 1, 0);
-- 제주지사(제주)
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주지사(제주)' LIMIT 1), '고압세척기', '💧', 3, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주지사(제주)' LIMIT 1), '저압세척기', '🚿', 1, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주지사(제주)' LIMIT 1), '동력분무기', '💨', 2, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주지사(제주)' LIMIT 1), '방제창고', '🏭', 10, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주지사(제주)' LIMIT 1), '발전기', '', 1, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주지사(제주)' LIMIT 1), '살포장치', '🌊', 3, 5);
-- 대산지사(보령)
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '대산지사(보령)' LIMIT 1), '고압세척기', '💧', 1, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '대산지사(보령)' LIMIT 1), '방제창고', '🏭', 4, 1);
-- 인천지사
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천지사' LIMIT 1), '고압세척기', '💧', 5, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천지사' LIMIT 1), '저압세척기', '🚿', 1, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천지사' LIMIT 1), '동력분무기', '💨', 3, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천지사' LIMIT 1), '발전기', '', 2, 3);
-- 대산지사(태안)
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '대산지사(태안)' LIMIT 1), '해안운반차', '🚜', 1, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '대산지사(태안)' LIMIT 1), '고압세척기', '💧', 5, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '대산지사(태안)' LIMIT 1), '저압세척기', '🚿', 1, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '대산지사(태안)' LIMIT 1), '동력분무기', '💨', 1, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '대산지사(태안)' LIMIT 1), '방제창고', '🏭', 5, 4),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '대산지사(태안)' LIMIT 1), '발전기', '', 3, 5),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '대산지사(태안)' LIMIT 1), '살포장치', '🌊', 1, 6);
-- 평택지사
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택지사' LIMIT 1), '고압세척기', '💧', 3, 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택지사' LIMIT 1), '저압세척기', '🚿', 2, 1),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택지사' LIMIT 1), '방제창고', '🏭', 3, 2),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택지사' LIMIT 1), '발전기', '', 4, 3),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택지사' LIMIT 1), '살포장치', '🌊', 1, 4);
-- 삼성중공업 외 1개
INSERT INTO ASSET_EQUIP (ORG_SN, CTGR_NM, ICON, QTY, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '삼성중공업 외 1개' LIMIT 1), '고압세척기', '💧', 1, 0);
-- ============================================================
-- ASSET_CONTACT 초기 데이터
-- ============================================================
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천해양경찰서' LIMIT 1), '방제과장', '김○○', '032-835-0001', 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천해양경찰서' LIMIT 1), '방제담당', '이○○', '032-835-0002', 1);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택해양경찰서' LIMIT 1), '방제담당', '박○○', '031-682-0001', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '태안해양경찰서' LIMIT 1), '방제담당', '최○○', '041-674-0001', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '보령해양경찰서' LIMIT 1), '방제담당', '정○○', '041-931-0001', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수해양경찰서' LIMIT 1), '방제과장', '윤○○', '061-660-0001', 0),
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수해양경찰서' LIMIT 1), '방제담당', '장○○', '061-660-0002', 1);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포해양경찰서' LIMIT 1), '방제담당', '조○○', '061-244-0001', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산해양경찰서' LIMIT 1), '방제담당', '한○○', '063-462-0001', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '완도해양경찰서' LIMIT 1), '방제담당', '이○○', '061-550-0001', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부안해양경찰서' LIMIT 1), '방제담당', '김○○', '063-928-0001', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산해양경찰서' LIMIT 1), '방제과장', '임○○', '051-400-0001', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산해양경찰서' LIMIT 1), '방제과장', '강○○', '052-228-0001', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원해양경찰서' LIMIT 1), '방제담당', '송○○', '055-220-0001', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '통영해양경찰서' LIMIT 1), '방제담당', '서○○', '055-640-0001', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '사천해양경찰서' LIMIT 1), '방제담당', '박○○', '055-830-0001', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해해양경찰서' LIMIT 1), '방제담당', '남○○', '033-530-0001', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항해양경찰서' LIMIT 1), '방제담당', '오○○', '054-244-0001', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '속초해양경찰서' LIMIT 1), '방제담당', '양○○', '033-633-0001', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울진해양경찰서' LIMIT 1), '방제담당', '배○○', '054-782-0001', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주해양경찰서' LIMIT 1), '방제담당', '문○○', '064-750-0001', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '서귀포해양경찰서' LIMIT 1), '방제담당', '고○○', '064-730-0001', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '중앙특수구조단' LIMIT 1), '구조단장', '김○○', '051-580-2044', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '오일허브코리아여수㈜ 외 4개' LIMIT 1), '담당', '오일허브코리아여수㈜', '061-686-3611', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'SK에너지 외 2개' LIMIT 1), '담당', 'HD현대오일뱅크㈜', '051-643-3331', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'SK지오센트릭 외 5개' LIMIT 1), '담당', 'SK엔텀㈜', '052-208-2851', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '한국가스공사 통영기지본부' LIMIT 1), '담당', '한국가스공사', '055-640-6014', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'HD현대오일뱅크㈜ 외 4개' LIMIT 1), '담당', 'HD현대오일뱅크㈜', '033-534-2093', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포스코케미칼 외 1개' LIMIT 1), '담당', 'OCI(주)', '054-290-8222', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '흑산도내연발전소 외 2개' LIMIT 1), '담당', '안마도내연발전소', '061-351-2342', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '오일허브코리아여수㈜ 외 4개' LIMIT 1), '담당', '오일허브코리아여수㈜', '061-686-3611', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'GS칼텍스㈜ 외 10개' LIMIT 1), '담당', 'GS칼텍스㈜', '010-8777-6922', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'HD현대케미칼 외 4개' LIMIT 1), '담당', 'HD현대케미칼', '041-924-1068', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '현대오일터미널(주) 외 4개' LIMIT 1), '담당', '(주)경동탱크터미널', '031-683-5101', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '한국남동발전(주) 외 2개' LIMIT 1), '담당', '(주)고성그린파워', '070-4486-7474', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'HD현대미포' LIMIT 1), '담당', 'HD현대미포', '052-250-3551', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '삼성중공업 외 1개' LIMIT 1), '담당', '삼성중공업', '055-630-5373', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '한국남부발전㈜' LIMIT 1), '담당', '한국남부발전㈜', '070-7713-5153', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '한울원전' LIMIT 1), '담당', '한울원전', '054-785-4833', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '㈜HR-PORT 외 5개' LIMIT 1), '담당', '㈜ 한진', '061-791-0358', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '삼광조선공업㈜ 외 1개' LIMIT 1), '담당', '삼광조선공업㈜', '010-3321-2959', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(㈜클린포트)' LIMIT 1), '담당', '㈜클린포트', '032-882-8279', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(대용환경㈜ 외 38개)' LIMIT 1), '담당', '(주)경원마린서비스', '051-242-0622', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체((주)한유마린서비스 외 8개)' LIMIT 1), '담당', '(주)골든씨', '010-5499-7401', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(블루씨 외 1개)' LIMIT 1), '담당', '(주)블루씨', '054-278-8200', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(㈜한국해운 외 1개)' LIMIT 1), '담당', '㈜아라', '010-8615-4326', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(마로해운 외 11개)' LIMIT 1), '담당', '(유)피케이엘', '061-654-9603', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(우진해운㈜)' LIMIT 1), '담당', '우진해운㈜', '010-4384-6817', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체((주)씨앤 외 3개)' LIMIT 1), '담당', '(주)소스코리아', '031-683-2389', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '방제유창청소업체(㈜지앤비마린서비스)' LIMIT 1), '담당', '(주)경원마린서비스', '051-242-0622', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'SK엔텀(주) 외 4개' LIMIT 1), '담당', 'S-OIL㈜', '052-231-2318', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'GS칼텍스㈜' LIMIT 1), '담당', 'GS칼텍스㈜', '061-680-2121', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = 'HD현대오일뱅크㈜' LIMIT 1), '담당', 'HD현대오일뱅크㈜', '010-2050-5291', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산광역시 외 8개' LIMIT 1), '담당', '남구청', '051-607-4484', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '사천시 외 3개' LIMIT 1), '담당', '고성군', '055-670-2484', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산북구청 외 2개' LIMIT 1), '담당', '부산기장군청', '051-709-4611', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '창원 진해구 외 1개' LIMIT 1), '담당', '부산 강서구', '051-970-4482', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '삼척시 외 1개' LIMIT 1), '담당', '강릉시', '033-640-5284', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '영덕군' LIMIT 1), '담당', '영덕군', '054-730-6562', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '영광군 외 1개' LIMIT 1), '담당', '목포시', '061-270-3419', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '광양시 외 1개' LIMIT 1), '담당', '광양시', '061-797-2791', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '옹진군청 외 4개' LIMIT 1), '담당', '김포시청', '010-2740-9388', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '태안군청' LIMIT 1), '담당', '태안군청', '041-670-2877', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '안산시청 외 2개' LIMIT 1), '담당', '당진시청', '041-350-4292', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '㈜HR-PORT 외 5개' LIMIT 1), '담당', '㈜ 한진', '061-791-0358', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '해군1함대사령부 외 1개' LIMIT 1), '담당', '1함대 사령부', '033-539-7323', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '해병대 제9518부대' LIMIT 1), '담당', '해병대 제9518부대', '010-4801-3473', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '부산지사' LIMIT 1), '담당', '부산지사', '051-466-3944', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '마산지사' LIMIT 1), '담당', '마산지사', '010-3598-4202', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '울산지사' LIMIT 1), '담당', '울산지사', '052-238-7718', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '마산지사' LIMIT 1), '담당', '마산지사', '010-2265-3928', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '마산지사' LIMIT 1), '담당', '마산지사', '010-2636-5313', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '동해지사' LIMIT 1), '담당', '동해지사', '010-7499-0257', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항지사' LIMIT 1), '담당', '포항지사', '054-273-5595', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '포항지사' LIMIT 1), '담당', '포항지사', '054-273-5595', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '군산지사' LIMIT 1), '담당', '군산지사', '063-443-4813', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포지사' LIMIT 1), '담당', '목포지사', '061-242-9663', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '여수지사' LIMIT 1), '담당', '여수지사', '061-654-6431', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '목포지사 완도사업소' LIMIT 1), '담당', '목포지사', '061-242-9663', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주지사(서귀포)' LIMIT 1), '담당', '제주지사', '064-753-4356', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '제주지사(제주)' LIMIT 1), '담당', '제주지사', '064-753-4356', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '대산지사(보령)' LIMIT 1), '담당', '대산지사', '041-664-9101', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '인천지사' LIMIT 1), '담당', '인천지사', '010-7133-2167', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '대산지사(태안)' LIMIT 1), '담당', '대산지사', '041-664-9101', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '평택지사' LIMIT 1), '담당', '평택지사', '031-683-7973', 0);
INSERT INTO ASSET_CONTACT (ORG_SN, ROLE_NM, CONTACT_NM, TEL, SORT_ORD) VALUES
((SELECT ORG_SN FROM ASSET_ORG WHERE ORG_NM = '삼성중공업 외 1개' LIMIT 1), '담당', '삼성중공업', '055-630-5373', 0);

파일 보기

@ -0,0 +1,137 @@
-- WING-OPS Seed Data: Reports Templates
-- Source: database/migration/007_reports.sql (INSERT 부분)
SET search_path TO wing;
-- ============================================================
-- 보고서 템플릿 (5종)
-- ============================================================
INSERT INTO REPORT_TMPL (TMPL_CD, TMPL_NM, ICON, TMPL_DC, SORT_ORD) VALUES
('INITIAL', '초기보고서', '📋', '사고 발생 직후 초기 상황 보고', 1),
('COMMAND', '지휘부 보고', '📊', '지휘부 보고용 요약 문서', 2),
('FORECAST', '예측보고서', '📈', '확산예측 결과 및 민감자원 분석', 3),
('COMPREHENSIVE', '종합보고서', '📑', '전체 사고 대응 종합 보고 문서', 4),
('SPILL', '유출유 보고', '🛢️', '유류오염사고 대응지원 상황도', 5)
ON CONFLICT (TMPL_CD) DO NOTHING;
-- ============================================================
-- 초기보고서 섹션 (5 섹션)
-- ============================================================
INSERT INTO REPORT_TMPL_SECT (TMPL_SN, SECT_CD, SECT_NM, FIELD_DEF, SORT_ORD)
SELECT t.TMPL_SN, v.SECT_CD, v.SECT_NM, v.FIELD_DEF::jsonb, v.SORT_ORD
FROM REPORT_TMPL t, (VALUES
('basic-info', '1. 기본정보', '[{"key":"incident.writeTime","label":"보고일시","type":"text"},{"key":"author","label":"작성자","type":"text"},{"key":"targets","label":"보고대상","type":"checkbox-group","options":["본청","지방청","유관기서"]}]', 1),
('incident-overview','2. 사고개요', '[{"key":"incident.name","label":"사고명","type":"text"},{"key":"incident.occurTime","label":"발생일시","type":"text"},{"key":"incident.location","label":"발생위치","type":"text"},{"key":"incident.shipName","label":"사고선박","type":"text"},{"key":"incident.accidentType","label":"사고유형","type":"text"}]', 2),
('spill-status', '3. 유출현황', '[{"key":"incident.pollutant","label":"유출유종","type":"text"},{"key":"incident.spillAmount","label":"유출량","type":"text"},{"key":"spillPattern","label":"유출형태","type":"text"},{"key":"spreadStatus","label":"확산현황","type":"text"}]', 3),
('initial-response', '4. 초동조치 사항', '[{"key":"initialResponse","label":"","type":"textarea"}]', 4),
('future-plan', '5. 향후 대응계획', '[{"key":"futurePlan","label":"","type":"textarea"}]', 5)
) AS v(SECT_CD, SECT_NM, FIELD_DEF, SORT_ORD)
WHERE t.TMPL_CD = 'INITIAL'
ON CONFLICT (TMPL_SN, SECT_CD) DO NOTHING;
-- 지휘부 보고 (4 섹션)
INSERT INTO REPORT_TMPL_SECT (TMPL_SN, SECT_CD, SECT_NM, FIELD_DEF, SORT_ORD)
SELECT t.TMPL_SN, v.SECT_CD, v.SECT_NM, v.FIELD_DEF::jsonb, v.SORT_ORD
FROM REPORT_TMPL t, (VALUES
('basic-info', '1. 기본정보', '[{"key":"incident.writeTime","label":"보고일시","type":"text"},{"key":"author","label":"작성자","type":"text"}]', 1),
('incident-summary','2. 사고 요약', '[{"key":"incident.name","label":"사고명","type":"text"},{"key":"incident.occurTime","label":"발생일시","type":"text"},{"key":"incident.location","label":"발생위치","type":"text"},{"key":"incident.pollutant","label":"유출유종","type":"text"},{"key":"incident.spillAmount","label":"유출량","type":"text"}]', 2),
('response-status', '3. 대응현황', '[{"key":"responseStatus","label":"","type":"textarea"}]', 3),
('suggestions', '4. 건의사항', '[{"key":"suggestions","label":"","type":"textarea"}]', 4)
) AS v(SECT_CD, SECT_NM, FIELD_DEF, SORT_ORD)
WHERE t.TMPL_CD = 'COMMAND'
ON CONFLICT (TMPL_SN, SECT_CD) DO NOTHING;
-- 예측보고서 (5 섹션)
INSERT INTO REPORT_TMPL_SECT (TMPL_SN, SECT_CD, SECT_NM, FIELD_DEF, SORT_ORD)
SELECT t.TMPL_SN, v.SECT_CD, v.SECT_NM, v.FIELD_DEF::jsonb, v.SORT_ORD
FROM REPORT_TMPL t, (VALUES
('basic-info', '1. 기본정보', '[{"key":"incident.writeTime","label":"보고일시","type":"text"},{"key":"author","label":"작성자","type":"text"}]', 1),
('incident-overview','2. 사고개요', '[{"key":"incident.name","label":"사고명","type":"text"},{"key":"incident.occurTime","label":"발생일시","type":"text"},{"key":"incident.location","label":"발생위치","type":"text"},{"key":"incident.pollutant","label":"유출유종","type":"text"},{"key":"incident.spillAmount","label":"유출량","type":"text"}]', 2),
('weather-summary', '3. 해양기상 현황', '[{"key":"weatherSummary","label":"","type":"textarea"}]', 3),
('spread-result', '4. 확산예측 결과', '[{"key":"spreadResult","label":"","type":"textarea"}]', 4),
('sensitive-impact', '5. 민감자원 영향', '[{"key":"sensitiveImpact","label":"","type":"textarea"}]', 5)
) AS v(SECT_CD, SECT_NM, FIELD_DEF, SORT_ORD)
WHERE t.TMPL_CD = 'FORECAST'
ON CONFLICT (TMPL_SN, SECT_CD) DO NOTHING;
-- 종합보고서 (6 섹션)
INSERT INTO REPORT_TMPL_SECT (TMPL_SN, SECT_CD, SECT_NM, FIELD_DEF, SORT_ORD)
SELECT t.TMPL_SN, v.SECT_CD, v.SECT_NM, v.FIELD_DEF::jsonb, v.SORT_ORD
FROM REPORT_TMPL t, (VALUES
('basic-info', '1. 기본정보', '[{"key":"incident.writeTime","label":"보고일시","type":"text"},{"key":"author","label":"작성자","type":"text"}]', 1),
('incident-overview', '2. 사고개요', '[{"key":"incident.name","label":"사고명","type":"text"},{"key":"incident.occurTime","label":"발생일시","type":"text"},{"key":"incident.location","label":"발생위치","type":"text"},{"key":"incident.shipName","label":"사고선박","type":"text"},{"key":"incident.accidentType","label":"사고유형","type":"text"}]', 2),
('spill-spread', '3. 유출 및 확산현황', '[{"key":"incident.pollutant","label":"유출유종","type":"text"},{"key":"incident.spillAmount","label":"유출량","type":"text"},{"key":"spreadSummary","label":"확산현황","type":"textarea"}]', 3),
('response-detail', '4. 대응현황', '[{"key":"responseDetail","label":"","type":"textarea"}]', 4),
('damage-report', '5. 피해현황', '[{"key":"damageReport","label":"","type":"textarea"}]', 5),
('future-plan-detail','6. 향후계획', '[{"key":"futurePlanDetail","label":"","type":"textarea"}]', 6)
) AS v(SECT_CD, SECT_NM, FIELD_DEF, SORT_ORD)
WHERE t.TMPL_CD = 'COMPREHENSIVE'
ON CONFLICT (TMPL_SN, SECT_CD) DO NOTHING;
-- 유출유 보고 (14 섹션)
INSERT INTO REPORT_TMPL_SECT (TMPL_SN, SECT_CD, SECT_NM, FIELD_DEF, SORT_ORD)
SELECT t.TMPL_SN, v.SECT_CD, v.SECT_NM, v.FIELD_DEF::jsonb, v.SORT_ORD
FROM REPORT_TMPL t, (VALUES
('incident-info', '1. 사고 정보', '[{"key":"incident.name","label":"사고명","type":"text"},{"key":"incident.writeTime","label":"작성시간","type":"text"},{"key":"incident.shipName","label":"선명(시설명)","type":"text"},{"key":"incident.location","label":"사고위치","type":"text"},{"key":"incident.occurTime","label":"발생시각","type":"text"},{"key":"incident.accidentType","label":"사고유형","type":"text"},{"key":"incident.pollutant","label":"오염물질","type":"text"},{"key":"incident.spillAmount","label":"유출 추정량(㎘)","type":"text"}]', 1),
('tide-info', '2. 조석정보', '[{"key":"tideDate","label":"일자","type":"text"},{"key":"tideName","label":"물때","type":"text"},{"key":"lowTide1","label":"저조(1차)","type":"text"},{"key":"highTide1","label":"고조(1차)","type":"text"}]', 2),
('weather-info', '2. 기상예보', '[{"key":"weatherTime","label":"기상 예측시간","type":"text"},{"key":"windDir","label":"풍향","type":"text"},{"key":"windSpeed","label":"풍속(m/s)","type":"text"},{"key":"waveHeight","label":"파고(m)","type":"text"}]', 3),
('spread-detail', '3. 확산예측 상세', '[{"key":"spread3h_weathered","label":"3시간 풍화량(kL)","type":"text"},{"key":"spread3h_seaRemain","label":"3시간 해상잔존량(kL)","type":"text"},{"key":"spread3h_area","label":"3시간 오염면적(km²)","type":"text"}]', 4),
('analysis', '3. 분석', '[{"key":"spreadAnalysis","label":"","type":"textarea"}]', 5),
('aquaculture', '4. 양식장 분포', '[{"key":"aquaculture","label":"","type":"textarea"}]', 6),
('beaches', '4. 해수욕장/수산시장', '[{"key":"beaches","label":"","type":"textarea"}]', 7),
('esi-coast', '4. 해안선(ESI) 분포', '[{"key":"esi1_vertical","label":"ESI 1 수직암반(km)","type":"text"},{"key":"esi3_finesand","label":"ESI 3 세립질 모래(km)","type":"text"}]', 8),
('bio-species', '4. 생물종(보호종)', '[{"key":"bioSpecies","label":"","type":"textarea"}]', 9),
('sensitivity', '4. 통합민감도 평가', '[{"key":"sens_veryHigh","label":"매우 높음(km²)","type":"text"},{"key":"sens_high","label":"높음(km²)","type":"text"}]', 10),
('defense-strategy', '5. 방제자원 배치', '[{"key":"defenseShips","label":"","type":"textarea"}]', 11),
('other-equipment', '5. 기타 장비', '[{"key":"otherEquipment","label":"","type":"textarea"}]', 12),
('oil-recovery', '6. 방제선/자원 동원', '[{"key":"oilRecovery","label":"","type":"textarea"}]', 13),
('result-summary', '6. 동원 방제선 내역', '[{"key":"totalSpill","label":"유출량(kL)","type":"text"},{"key":"totalRecovered","label":"누적회수량(kL)","type":"text"}]', 14)
) AS v(SECT_CD, SECT_NM, FIELD_DEF, SORT_ORD)
WHERE t.TMPL_CD = 'SPILL'
ON CONFLICT (TMPL_SN, SECT_CD) DO NOTHING;
-- ============================================================
-- 분석 카테고리 (3종)
-- ============================================================
INSERT INTO REPORT_ANALYSIS_CTGR (CTGR_CD, CTGR_NM, ICON, CTGR_DC, COLOR_CD, BORDER_COLOR, BG_ACTIVE, REPORT_NM, SORT_ORD) VALUES
('OIL', '유출유 확산예측', '🛢', 'KOSPS · OpenDrift · POSEIDON', 'var(--cyan)', 'rgba(6,182,212,0.4)', 'rgba(6,182,212,0.08)', '유출유 확산예측 보고서', 1),
('HNS', 'HNS 대기확산', '🧪', 'ALOHA · WRF-Chem', 'var(--orange)', 'rgba(249,115,22,0.4)', 'rgba(249,115,22,0.08)','HNS 대기확산 예측보고서', 2),
('RESCUE', '긴급구난', '🚨', '복원성 · 좌초위험 분석', 'var(--red)', 'rgba(239,68,68,0.4)', 'rgba(239,68,68,0.08)', '긴급구난 상황보고서', 3)
ON CONFLICT (CTGR_CD) DO NOTHING;
-- 카테고리별 템플릿 목록
INSERT INTO REPORT_CTGR_TMPL (CTGR_SN, ICON, LABEL, SORT_ORD)
SELECT c.CTGR_SN, v.ICON, v.LABEL, v.SORT_ORD
FROM REPORT_ANALYSIS_CTGR c, (VALUES
('OIL', '🔬', '예측보고서', 1), ('OIL', '📋', '초기보고서', 2), ('OIL', '📊', '지휘부 보고', 3), ('OIL', '📑', '종합보고서', 4),
('HNS', '🧪', 'HNS 예측보고서', 1), ('HNS', '📋', '초기보고서', 2), ('HNS', '📊', '지휘부 보고', 3), ('HNS', '🆘', 'EmS 대응보고', 4),
('RESCUE', '🚨', '긴급구난 상황보고', 1), ('RESCUE', '📋', '초기보고서', 2), ('RESCUE', '📊', '지휘부 보고', 3), ('RESCUE', '📑', '종합보고서', 4)
) AS v(CTGR_CD, ICON, LABEL, SORT_ORD)
WHERE c.CTGR_CD = v.CTGR_CD;
-- 카테고리별 섹션
INSERT INTO REPORT_CTGR_SECT (CTGR_SN, SECT_CD, SECT_NM, ICON, SECT_DC, DFLT_YN, SORT_ORD)
SELECT c.CTGR_SN, v.SECT_CD, v.SECT_NM, v.ICON, v.SECT_DC, v.DFLT_YN, v.SORT_ORD
FROM REPORT_ANALYSIS_CTGR c, (VALUES
('OIL', 'oil-spread', '유출유 확산예측 결과', '🌊', 'KOSPS/OpenDrift/POSEIDON 예측 결과 및 비교', 'Y', 1),
('OIL', 'oil-pollution', '오염종합상황', '📊', '유출량, 풍화량, 해상잔유량, 오염면적', 'Y', 2),
('OIL', 'oil-sensitive', '민감자원 현황', '🐟', '어장정보, 양식업, 환경생태 자원', 'Y', 3),
('OIL', 'oil-coastal', '해안부착 현황', '🏖', '해안 부착 위치, 시간, 오염 길이', 'Y', 4),
('OIL', 'oil-defense', '방제전략·자원배치', '🛡', '방제방법, 방제자원 배치 계획', 'Y', 5),
('OIL', 'oil-tide', '조석·기상정보', '🌊', '사고 해역 조석·기상 현황', 'Y', 6),
('HNS', 'hns-atm', '대기확산 예측 결과', '💨', 'ALOHA/WRF-Chem 모델 확산 결과', 'Y', 1),
('HNS', 'hns-hazard', '위험구역·방제거리', '⚠️', 'ERPGs 기준 위험구역 범위', 'Y', 2),
('HNS', 'hns-substance', 'HNS 물질정보', '🧬', '물질 특성, 독성, UN번호', 'Y', 3),
('HNS', 'hns-ppe', 'PPE·대응장비', '🛡', '개인보호장비, 대응장비 배치', 'Y', 4),
('HNS', 'hns-facility', '영향시설·대피현황', '🏫', '주변 시설, 인구, 대피 계획', 'Y', 5),
('HNS', 'hns-3d', '3D 공간분포', '📐', '수직·수평 농도 분포', 'N', 6),
('HNS', 'hns-weather', '기상·해상 조건', '🌊', '풍향·풍속, 대기안정도', 'Y', 7),
('RESCUE', 'rescue-safety', '선박 안전성 평가', '🚢', 'GM, 경사각, 트림 분석', 'Y', 1),
('RESCUE', 'rescue-timeline', '사고 유형·경과', '', '사고 유형별 타임라인', 'Y', 2),
('RESCUE', 'rescue-casualty', '인명현황', '👥', '인원 현황, 구조 상태', 'Y', 3),
('RESCUE', 'rescue-resource', '구난 자원 현황', '🛟', '예인선, 헬기, 구난 장비 배치', 'Y', 4),
('RESCUE', 'rescue-grounding', '좌초위험 해역', '🗺', '좌초 위험 구역 분석', 'Y', 5),
('RESCUE', 'rescue-weather', '기상·해상 조건', '🌊', '파고, 풍속, 조류 현황', 'Y', 6)
) AS v(CTGR_CD, SECT_CD, SECT_NM, ICON, SECT_DC, DFLT_YN, SORT_ORD)
WHERE c.CTGR_CD = v.CTGR_CD
ON CONFLICT (CTGR_SN, SECT_CD) DO NOTHING;

파일 보기

@ -0,0 +1,18 @@
-- WING-OPS Seed Data: CCTV Cameras (12건)
-- Source: database/migration/015_aerial.sql
SET search_path TO wing;
INSERT INTO CCTV_CAMERA (CAMERA_NM, REGION_NM, LON, LAT, GEOM, LOC_DC, COORD_DC, STTS_CD, PTZ_YN, SOURCE_NM) VALUES
('서귀포항 동측', '제주', 126.57, 33.24, ST_SetSRID(ST_MakePoint(126.57::float, 33.24::float), 4326), '제주 서귀포시 서귀동', '33.24°N 126.57°E', 'LIVE', 'Y', 'TAGO'),
('제주항 외항', '제주', 126.53, 33.52, ST_SetSRID(ST_MakePoint(126.53::float, 33.52::float), 4326), '제주 제주시 건입동', '33.52°N 126.53°E', 'LIVE', 'Y', 'TAGO'),
('성산포항', '제주', 126.93, 33.46, ST_SetSRID(ST_MakePoint(126.93::float, 33.46::float), 4326), '제주 서귀포시 성산읍', '33.46°N 126.93°E', 'LIVE', 'N', 'KBS'),
('한림항', '제주', 126.27, 33.41, ST_SetSRID(ST_MakePoint(126.27::float, 33.41::float), 4326), '제주 제주시 한림읍', '33.41°N 126.27°E', 'LIVE', 'N', 'TAGO'),
('여수 돌산대교', '남해', 127.75, 34.74, ST_SetSRID(ST_MakePoint(127.75::float, 34.74::float), 4326), '전남 여수시 돌산읍', '34.74°N 127.75°E', 'LIVE', 'Y', 'KBS'),
('통영 해상공원', '남해', 128.42, 34.84, ST_SetSRID(ST_MakePoint(128.42::float, 34.84::float), 4326), '경남 통영시 동호동', '34.84°N 128.42°E', 'LIVE', 'N', 'TAGO'),
('거제 장승포항', '남해', 128.69, 34.87, ST_SetSRID(ST_MakePoint(128.69::float, 34.87::float), 4326), '경남 거제시 장승포동', '34.87°N 128.69°E', 'OFFLINE', 'N', 'TAGO'),
('목포 영산강', '서해', 126.39, 34.79, ST_SetSRID(ST_MakePoint(126.39::float, 34.79::float), 4326), '전남 목포시 산정동', '34.79°N 126.39°E', 'LIVE', 'Y', 'KBS'),
('인천 송도', '서해', 126.64, 37.38, ST_SetSRID(ST_MakePoint(126.64::float, 37.38::float), 4326), '인천 연수구 송도동', '37.38°N 126.64°E', 'LIVE', 'N', 'TAGO'),
('태안 만리포', '서해', 126.14, 36.79, ST_SetSRID(ST_MakePoint(126.14::float, 36.79::float), 4326), '충남 태안군 소원면', '36.79°N 126.14°E', 'LIVE', 'N', 'TAGO'),
('포항 영일대', '동해', 129.38, 36.06, ST_SetSRID(ST_MakePoint(129.38::float, 36.06::float), 4326), '경북 포항시 북구', '36.06°N 129.38°E', 'LIVE', 'Y', 'KBS'),
('울산 대왕암', '동해', 129.43, 35.49, ST_SetSRID(ST_MakePoint(129.43::float, 35.49::float), 4326), '울산 동구 일산동', '35.49°N 129.43°E', 'LIVE', 'N', 'TAGO');

53
database/seed/README.md Normal file
파일 보기

@ -0,0 +1,53 @@
# Seed Data (초기 데이터)
## 실행 순서
SQL seed 파일은 번호 순서대로 실행합니다. schema/ DDL이 먼저 실행되어야 합니다.
```bash
# 1. auth 스키마 seed (01-06)
psql -U wing -d wing -f database/seed/01_auth_roles.sql
psql -U wing -d wing -f database/seed/02_auth_perms.sql
psql -U wing -d wing -f database/seed/03_auth_perm_tree.sql
psql -U wing -d wing -f database/seed/04_auth_orgs.sql
psql -U wing -d wing -f database/seed/05_auth_settings.sql
psql -U wing -d wing -f database/seed/06_auth_admin.sql
# 2. wing 스키마 seed (07-08)
psql -U wing -d wing -f database/seed/07_common_codes.sql
psql -U wing -d wing -f database/seed/08_organizations.sql
# 3. 도메인 데이터 (11-14)
psql -U wing -d wing -f database/seed/11_sample_accident.sql
psql -U wing -d wing -f database/seed/12_assets.sql
psql -U wing -d wing -f database/seed/13_reports_templates.sql
psql -U wing -d wing -f database/seed/14_cctv_cameras.sql
# 4. Node.js seed (layer 160건 + HNS 1,316건)
cd backend && npm run db:seed
```
## 파일 목록
| 파일 | 내용 | 레코드 수 |
|------|------|-----------|
| 01_auth_roles.sql | 역할 (ADMIN, MANAGER, OPERATOR, VIEWER) | 4건 |
| 02_auth_perms.sql | 권한 매트릭스 (RCUD) | ~134건 |
| 03_auth_perm_tree.sql | 권한 리소스 트리 | ~48건 |
| 04_auth_orgs.sql | 기관 (해양경찰청 등) | 6건 |
| 05_auth_settings.sql | 시스템 설정 (세션, 메뉴, 비밀번호 정책) | 4건 |
| 06_auth_admin.sql | 관리자 계정 + 역할 매핑 | 2건 |
| 07_common_codes.sql | 공통코드 그룹 + 코드 | ~116건 |
| 08_organizations.sql | 조직 | 6건 |
| 09_layers.sql | 참조 안내 (seed.ts가 처리) | - |
| 10_hns_substances.sql | 참조 안내 (seedHns.ts가 처리) | - |
| 11_sample_accident.sql | 샘플 사고 + 유출 데이터 | 2건 |
| 12_assets.sql | 기관/장비/연락처 | ~640건 |
| 13_reports_templates.sql | 보고서 템플릿 + 섹션 + 카테고리 | ~70건 |
| 14_cctv_cameras.sql | CCTV 카메라 | 12건 |
## 주의사항
- 09, 10번은 참조 안내 파일입니다. 실제 데이터는 `npm run db:seed`로 삽입됩니다.
- seed 실행 전에 반드시 `database/schema/` DDL이 먼저 실행되어야 합니다.
- 운영 환경에서 관리자 비밀번호는 반드시 변경하세요.

파일 보기

@ -1420,16 +1420,19 @@ backend/src/
+-- incidents/ 사건/사고
+-- scat/ Pre-SCAT 조사
+-- db/
| +-- wingDb.ts wing DB Pool (운영 데이터)
| +-- authDb.ts wing_auth DB Pool (인증 데이터)
| +-- wingDb.ts wing DB Pool (운영 데이터, auth 스키마 포함)
| +-- authDb.ts wingPool re-export (하위 호환용, auth 스키마 접근)
+-- middleware/
| +-- security.ts 입력 살균, 크기 제한, 서버 정보 제거
+-- server.ts Express 진입점 + 보안 미들웨어 + 라우터 등록
database/
+-- auth_init.sql 인증 DB DDL + 초기 데이터
+-- init.sql 운영 DB DDL
+-- schema/
| +-- 00_init.sql wing DB 생성, PostGIS, 스키마 설정
| +-- 01_auth_tables.sql auth 스키마 테이블 DDL
+-- seed/ 초기 데이터 (01~06)
+-- migration/ 마이그레이션 스크립트
+-- _deprecated/ 사용 중단 파일 (auth_init.sql, init.sql 등)
+-- 003_perm_tree.sql 리소스 트리 (AUTH_PERM_TREE)
+-- 004_oper_cd.sql 오퍼레이션 코드 (OPER_CD) 추가
+-- 006_board.sql 게시판 (BOARD_POST)
@ -1460,7 +1463,8 @@ database/
import { wingPool } from '../db/wingDb.js';
const result = await wingPool.query('SELECT * FROM LAYER WHERE LAYER_CD = $1', [id]);
// wing_auth DB (인증 데이터: 사용자, 역할, 권한, 감사로그 등)
// auth 스키마 (인증 데이터: 사용자, 역할, 권한, 감사로그 등)
// authPool은 wingPool과 동일한 Pool 인스턴스를 re-export한 하위 호환용 별칭이다
import { authPool } from '../db/authDb.js';
const result = await authPool.query('SELECT * FROM AUTH_USER WHERE USER_ID = $1', [id]);
```

파일 보기

@ -23,7 +23,7 @@ DB 설계부터 백엔드 구현, 프론트엔드 연동까지 End-to-End 패턴
[Frontend] [Backend] [Database]
tabs/{탭}/services/{tab}Api.ts src/{domain}/{domain}Router.ts PostgreSQL 16
Axios (withCredentials: true) requireAuth -> requirePermission
--HTTP--> src/{domain}/{domain}Service.ts wingPool / authPool
--HTTP--> src/{domain}/{domain}Service.ts wingPool (auth 스키마 포함)
wingPool.query(SQL, params) --SQL-->
```
@ -38,12 +38,12 @@ tabs/{탭}/services/{tab}Api.ts src/{domain}/{domain}Router.ts Postgre
### DB Pool 선택 기준
```ts
import { wingPool } from '../db/wingDb.js'; // 업무 데이터 (BOARD_POST, LAYER 등)
import { authPool } from '../db/authDb.js'; // 인증 데이터 (AUTH_USER, AUTH_ROLE 등)
import { wingPool } from '../db/wingDb.js'; // 업무 데이터 (wing 스키마: BOARD_POST, LAYER 등)
import { authPool } from '../db/authDb.js'; // 인증 데이터 (auth 스키마: AUTH_USER, AUTH_ROLE 등)
```
> **참고**: `authPool``wingPool`의 re-export이다 (동일 서버, search_path = wing, auth, public).
> 신규 코드는 `wingPool`을 사용한다. 다만 의미적으로 인증 데이터를 다룰 때 `authPool`을 쓰는 것도 허용한다.
> **참고**: `authPool``wingPool`의 re-export이다 (wing 단일 DB, search_path = wing, auth, public).
> 신규 코드는 `wingPool`을 사용한다. 다만 의미적으로 auth 스키마 데이터를 다룰 때 `authPool`을 쓰는 것도 허용한다.
### HTTP 메서드 정책

파일 보기

@ -100,20 +100,13 @@ cd ../backend && npm install
PORT=3001
NODE_ENV=development
# wing DB (운영 데이터)
# wing DB (운영 데이터 + auth 스키마 통합)
WING_DB_HOST=211.208.115.83
WING_DB_PORT=5432
WING_DB_USER=wing
WING_DB_PASS=<비밀번호>
WING_DB_NAME=wing
# wing_auth DB (인증/권한)
AUTH_DB_HOST=211.208.115.83
AUTH_DB_PORT=5432
AUTH_DB_USER=wing_auth
AUTH_DB_PASS=<비밀번호>
AUTH_DB_NAME=wing_auth
# JWT
JWT_SECRET=<시크릿>
JWT_EXPIRES_IN=24h
@ -287,8 +280,8 @@ backend/src/
│ └── {도메인}Service.ts
├── middleware/ 보안 (입력 살균, rate-limit)
└── db/
├── wingDb.ts wing DB Pool
├── authDb.ts wing_auth DB Pool
├── wingDb.ts wing DB Pool (auth 스키마 포함)
├── authDb.ts wingPool re-export (하위 호환용)
└── seed.ts 시드 데이터
```

파일 보기

@ -23,7 +23,7 @@
|-----------|----------|----------|------|
| Node.js | v20 | v20 LTS | Frontend/Backend 실행 |
| npm | v10 | v10+ | 패키지 관리 (Node.js 포함) |
| PostgreSQL | v15 | v16 | 운영 DB + 인증 DB |
| PostgreSQL | v15 | v16 | 운영 DB (wing 단일 DB) |
| PostGIS | v3.3 | v3.4 | 공간 데이터 처리 |
| Git | v2.30 | v2.40+ | 소스 코드 관리 |
@ -95,15 +95,18 @@ wing/
│ │ ├── auth/ 인증 (JWT, Google OAuth)
│ │ ├── users/ 사용자 관리
│ │ ├── roles/ 역할/권한 (RBAC 2차원 권한)
│ │ ├── db/ DB Pool (wingDb, authDb), seed
│ │ ├── db/ DB Pool (wingDb, authDb — re-export), seed
│ │ ├── middleware/ 보안 (입력 살균, rate-limit)
│ │ └── {도메인}/ 도메인별 모듈 (Router + Service)
│ ├── package.json
│ └── tsconfig.json
├── database/ SQL 스크립트
│ ├── init.sql wing DB 초기 스키마 (PostGIS)
│ ├── auth_init.sql wing_auth DB 초기 스키마
│ └── migration/ 마이그레이션 (001 ~ 016)
│ ├── schema/ DDL (스키마 정의)
│ │ ├── 00_init.sql wing DB 생성, PostGIS, 스키마 설정
│ │ └── 01_auth_tables.sql auth 스키마 테이블 (사용자, 역할, 권한 등)
│ ├── seed/ 초기 데이터 (01~06)
│ ├── migration/ 마이그레이션 (001 ~ 016)
│ └── _deprecated/ 사용 중단 파일 (auth_init.sql 등)
├── docs/ 개발 문서
├── .githooks/ Git Hooks (pre-commit, commit-msg)
├── .gitea/workflows/ CI/CD (Gitea Actions)
@ -166,15 +169,6 @@ WING_DB_USER=wing
WING_DB_PASS=<비밀번호>
WING_DB_NAME=wing
# ===========================================
# wing_auth DB (인증/권한 - PostgreSQL)
# ===========================================
AUTH_DB_HOST=211.208.115.83
AUTH_DB_PORT=5432
AUTH_DB_USER=wing_auth
AUTH_DB_PASS=<비밀번호>
AUTH_DB_NAME=wing_auth
# ===========================================
# JWT 인증
# ===========================================
@ -290,34 +284,44 @@ cd frontend && npm run dev # 터미널 2
### 5-1. DB 구성
프로젝트는 동일 PostgreSQL 서버에 2개의 데이터베이스를 사용한다:
프로젝트는 단일 PostgreSQL 데이터베이스(wing)에 3개의 스키마를 사용한다:
| DB | 용도 | 확장 |
|----|------|------|
| `wing` | 운영 데이터 (사고, 예측, 자산 등) | PostGIS |
| `wing_auth` | 인증/권한 (사용자, 역할, 메뉴) | uuid-ossp, pgcrypto |
| 스키마 | 용도 | 주요 테이블 |
|--------|------|------------|
| `public` | 운영 데이터 (사고, 예측, 자산 등) | PostGIS 확장 포함 |
| `auth` | 인증/권한 (사용자, 역할, 메뉴, 감사로그) | AUTH_USER, AUTH_ROLE, AUTH_PERM 등 |
| `wing` | 기타 도메인 테이블 | 레이어, 시뮬레이션 등 |
백엔드는 `search_path = wing, auth, public`으로 접속하므로 스키마 접두사 없이 테이블을 참조할 수 있다.
### 5-2. 신규 DB 초기화
PostgreSQL에 최초 설치 시 아래 순서로 실행한다.
```bash
# 1. wing DB 초기화 (PostgreSQL superuser로 실행)
psql -U postgres -f database/init.sql
# 1. wing DB 및 스키마 초기화 (PostgreSQL superuser로 실행)
psql -U postgres -f database/schema/00_init.sql
# 2. wing_auth DB 초기화
psql -U postgres -f database/auth_init.sql
# 2. auth 스키마 테이블 생성
psql -U postgres -d wing -f database/schema/01_auth_tables.sql
# 3. 초기 데이터 적재 (01~06 순서대로)
psql -U postgres -d wing -f database/seed/01_common_code.sql
psql -U postgres -d wing -f database/seed/02_org.sql
psql -U postgres -d wing -f database/seed/03_role.sql
psql -U postgres -d wing -f database/seed/04_perm_tree.sql
psql -U postgres -d wing -f database/seed/05_menu.sql
psql -U postgres -d wing -f database/seed/06_admin_user.sql
```
`init.sql`에 포함된 내용:
`database/schema/00_init.sql`에 포함된 내용:
- 사용자(wing) 및 데이터베이스(wing) 생성
- PostGIS 확장 설치
- PostGIS, uuid-ossp, pgcrypto 확장 설치
- public, auth, wing 스키마 생성 및 search_path 설정
- 공통코드, 시뮬레이션, 사고, 예측 등 핵심 테이블 생성
`auth_init.sql`에 포함된 내용:
- 사용자(wing_auth) 및 데이터베이스(wing_auth) 생성
- uuid-ossp, pgcrypto 확장 설치
- 조직, 역할, 사용자, 권한, 메뉴, 설정, 감사로그 테이블 생성
`database/schema/01_auth_tables.sql`에 포함된 내용:
- auth 스키마 내 조직, 역할, 사용자, 권한, 메뉴, 설정, 감사로그 테이블 생성
### 5-3. 마이그레이션 적용
@ -509,11 +513,6 @@ Environment=WING_DB_PORT=5432
Environment=WING_DB_USER=wing
Environment=WING_DB_PASS=<비밀번호>
Environment=WING_DB_NAME=wing
Environment=AUTH_DB_HOST=211.208.115.83
Environment=AUTH_DB_PORT=5432
Environment=AUTH_DB_USER=wing_auth
Environment=AUTH_DB_PASS=<비밀번호>
Environment=AUTH_DB_NAME=wing_auth
Environment=JWT_SECRET=<시크릿>
Environment=JWT_EXPIRES_IN=24h
Environment=FRONTEND_URL=https://wing-demo.gc-si.dev
@ -647,7 +646,6 @@ curl -s https://wing-demo.gc-si.dev/api/
| Backend API | http://localhost:3001 | 3001 |
| Backend 헬스 체크 | http://localhost:3001/health | 3001 |
| PostgreSQL (wing) | 211.208.115.83:5432/wing | 5432 |
| PostgreSQL (wing_auth) | 211.208.115.83:5432/wing_auth | 5432 |
### 운영 환경
@ -710,7 +708,7 @@ curl -s https://wing-demo.gc-si.dev/api/
| 증상 | 원인 | 해결 |
|------|------|------|
| `relation "XXX" does not exist` | 테이블 미생성 | `database/init.sql` 또는 해당 마이그레이션 SQL 실행 |
| `relation "XXX" does not exist` | 테이블 미생성 | `database/schema/*.sql` 또는 해당 마이그레이션 SQL 실행 |
| PostGIS 함수 에러 | PostGIS 확장 미설치 | `psql -U postgres -d wing -c "CREATE EXTENSION IF NOT EXISTS postgis"` |
| 인코딩 문제 (한글 깨짐) | DB 인코딩 설정 | DB 생성 시 `ENCODING='UTF8' LC_COLLATE='ko_KR.UTF-8'` 지정 |
| seed 실패 | 이미 데이터 존재 또는 FK 제약 | 에러 메시지 확인 후 해당 테이블 데이터 정리 |

파일 보기

@ -42,7 +42,7 @@ board 탭을 기준 템플릿으로 사용하며, 각 단계별 실제 코드
| | `backend/src/{도메인}/{domain}Service.ts` | 서비스 생성 |
| **Step 5** | `backend/src/server.ts` | 라우트 등록 |
| | `backend/src/settings/settingsService.ts` | DEFAULT_MENU_CONFIG 추가 |
| | `database/auth_init.sql` | menu.config 초기 JSON 추가 |
| | `database/seed/05_auth_settings.sql` | menu.config 초기 JSON 추가 |
| | `database/migration/NNN_{domain}.sql` | DB 마이그레이션 |
---
@ -494,7 +494,7 @@ export async function createItem(input: CreateItemInput): Promise<{ sn: number }
| 항목 | 패턴 |
|------|------|
| DB Pool | `wingPool` (wing DB) 또는 `authPool` (wing_auth DB) |
| DB Pool | `wingPool` (wing DB, wing 스키마) 또는 `authPool` (wing DB re-export, auth 스키마) |
| 에러 처리 | `AuthError(message, status)` 활용 |
| 논리 삭제 | `USE_YN = 'Y'/'N'` 컬럼 사용, DELETE 대신 UPDATE |
| 페이징 | `LIMIT $N OFFSET $M`, 기본 size 20, 최대 100 |
@ -531,10 +531,10 @@ const DEFAULT_MENU_CONFIG: MenuConfigItem[] = [
];
```
### 5-3. auth_init.sql에 menu.config 초기 JSON 추가
### 5-3. seed/05_auth_settings.sql에 menu.config 초기 JSON 추가
```sql
-- database/auth_init.sql 의 menu.config INSERT 문에 새 항목 추가
-- database/seed/05_auth_settings.sql 의 menu.config INSERT 문에 새 항목 추가
-- (신규 설치 시에만 적용. 기존 운영 DB는 관리자 UI에서 관리)
```
@ -629,7 +629,7 @@ mkdir -p frontend/src/tabs/monitoring/services
```
- `database/migration/017_monitoring.sql` 생성
- `database/auth_init.sql` 의 menu.config JSON에 항목 추가
- `database/seed/05_auth_settings.sql` 의 menu.config JSON에 항목 추가
### 6단계: 검증
@ -663,7 +663,7 @@ cd backend && npx tsc --noEmit # 백엔드 컴파일 검증
### DB
- [ ] `database/migration/NNN_{domain}.sql` 마이그레이션 작성
- [ ] `database/auth_init.sql` menu.config 초기 JSON 업데이트
- [ ] `database/seed/05_auth_settings.sql` menu.config 초기 JSON 업데이트
- [ ] SQL 실행 검증
### 배포 후

파일 보기

@ -33,7 +33,7 @@
|--- WebSocket ------> [Socket.IO]
|
[PostgreSQL 16 + PostGIS]
wing DB (운영) + wing_auth DB (인증)
wing 단일 DB (public, auth, wing 3개 스키마)
```
### HTTP 정책
@ -90,11 +90,12 @@ wing/
│ ├── aerial/, rescue/ 업무 도메인
│ ├── routes/ layers, simulation
│ ├── middleware/ security (sanitize, rate-limit)
│ └── db/ wingDb, authDb, seed
│ └── db/ wingDb (authDb는 re-export), seed
├── database/
│ ├── init.sql wing DB 스키마
│ ├── auth_init.sql wing_auth DB 스키마
│ └── migration/ 001~016 마이그레이션
│ ├── schema/ ERD용 순수 DDL (14파일)
│ ├── seed/ 초기 데이터 (14파일)
│ ├── migration/ 증분 마이그레이션 (001~016)
│ └── _deprecated/ 구 스크립트 (통합 이전)
└── .gitea/workflows/ CI/CD 파이프라인
```
@ -165,12 +166,17 @@ wing/
## 데이터베이스
| DB | 용도 | 비고 |
|----|------|------|
| wing | 운영 데이터 | PostgreSQL 16 + PostGIS |
| wing_auth | 인증/권한 | 동일 서버, 별도 DB |
wing 단일 DB에 3개 스키마로 구성:
마이그레이션 파일: `database/migration/001~016`
| 스키마 | 용도 | 테이블 수 |
|--------|------|-----------|
| public | PostGIS 확장 | - |
| auth | 인증/권한/감사로그 | 9 |
| wing | 운영 데이터 | 35 |
- 초기 DDL: `database/schema/` (14파일)
- 초기 데이터: `database/seed/` (14파일)
- 마이그레이션: `database/migration/001~016`
---
@ -223,11 +229,11 @@ VITE_GOOGLE_CLIENT_ID=your-google-client-id
PORT=3001
NODE_ENV=development
JWT_SECRET=your-jwt-secret
AUTH_DB_HOST=localhost
AUTH_DB_PORT=5432
AUTH_DB_NAME=wing_auth
AUTH_DB_USER=wing_auth
AUTH_DB_PASSWORD=your-password
DB_HOST=211.208.115.83
DB_PORT=5432
DB_NAME=wing
DB_USER=wing
DB_PASSWORD=your-password
GOOGLE_CLIENT_ID=your-google-client-id
```