Phase 2b: 11개 모듈 전량 실동작 (333 서비스, 전서버 부팅)

- 10개 모듈 추가/확장(au py rc st lg cl mm vl mg cm), 각 30 서비스 = 330 + tmsrv
- build.sh 자동발견으로 11 모듈서버 + dbio 라이브러리 23 + 배치 22 빌드
- schema.d 11파일 → 75 테이블, 모듈별 disjoint
- 부팅 리소스 규명: fs.mqueue.queues_max=8192(330큐>256), NDRX_MSGSIZEMAX 16000·
  MSGMAX 50(큐당 5.6MB→0.8MB), msgqueue ulimit 2GB → 전 12서버 runok
- 검증: xadmin psc 333 AVAIL, 매입체인 XA 커밋, prepared_xacts=0

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
forge-bot 2026-07-19 09:58:39 +00:00
parent 8219b85f14
commit bec83c721e
73 changed files with 10705 additions and 35 deletions

111
db/schema.d/20-au.sql Normal file
View file

@ -0,0 +1,111 @@
-- au 모듈 (승인/한도) 스키마 - 승인 원장 / 카드 한도 / 부정거래 / 예비승인 / 집계
-- Loaded into PostgreSQL on first boot (docker-entrypoint-initdb.d). Prefix 20.
-- ---------------------------------------------------------------------------
-- 승인 원장 (authorization)
-- status: A=승인, D=거절, C=취소, R=역전, H=보류, M=매입확정(capture),
-- S=정산반영, V=무효(void)
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS au_auth_seq;
CREATE TABLE IF NOT EXISTS au_authorization (
auth_id BIGINT PRIMARY KEY,
card_no TEXT NOT NULL,
merchant_id TEXT NOT NULL DEFAULT '',
amount BIGINT NOT NULL,
approval_code TEXT NOT NULL DEFAULT '',
auth_type TEXT NOT NULL DEFAULT 'AUTH', -- AUTH/STANDIN/INSTALL/PREAUTH
status TEXT NOT NULL,
decline_reason TEXT NOT NULL DEFAULT '',
biz_date DATE NOT NULL,
captured_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 카드 한도 (card_limit)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS card_limit (
card_no TEXT PRIMARY KEY,
daily_limit BIGINT NOT NULL DEFAULT 1000000,
used_amount BIGINT NOT NULL DEFAULT 0,
temp_limit BIGINT NOT NULL DEFAULT 0,
status TEXT NOT NULL DEFAULT 'ACTIVE',
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 부정거래 로그 (fraud_log)
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS au_fraud_seq;
CREATE TABLE IF NOT EXISTS au_fraud_log (
fraud_id BIGINT PRIMARY KEY,
auth_id BIGINT NOT NULL DEFAULT 0,
card_no TEXT NOT NULL,
score BIGINT NOT NULL,
reason TEXT NOT NULL DEFAULT '',
biz_date DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 블랙리스트 (au_blacklist)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS au_blacklist (
card_no TEXT PRIMARY KEY,
reason TEXT NOT NULL DEFAULT '',
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 예비승인 (au_preauth) - status: P=예비, C=확정, X=취소
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS au_preauth_seq;
CREATE TABLE IF NOT EXISTS au_preauth (
preauth_id BIGINT PRIMARY KEY,
card_no TEXT NOT NULL,
merchant_id TEXT NOT NULL DEFAULT '',
amount BIGINT NOT NULL,
status TEXT NOT NULL DEFAULT 'P',
biz_date DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 승인 취소 (au_cancel) - FULL / PARTIAL / VOID
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS au_cancel_seq;
CREATE TABLE IF NOT EXISTS au_cancel (
cancel_id BIGINT PRIMARY KEY,
auth_id BIGINT NOT NULL,
cancel_type TEXT NOT NULL,
amount BIGINT NOT NULL,
reason TEXT NOT NULL DEFAULT '',
biz_date DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 가맹점 일별 승인 집계 (au_summary) - 배치/서비스가 채움
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS au_summary (
merchant_id TEXT NOT NULL,
biz_date DATE NOT NULL,
auth_count BIGINT NOT NULL DEFAULT 0,
approve_count BIGINT NOT NULL DEFAULT 0,
decline_count BIGINT NOT NULL DEFAULT 0,
auth_amount BIGINT NOT NULL DEFAULT 0,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
PRIMARY KEY (merchant_id, biz_date)
);
-- Seed card limits + a blacklist entry so AUTH/LIMIT services have counterparties.
INSERT INTO card_limit (card_no, daily_limit, used_amount) VALUES
('4000123412341234', 1000000, 0),
('5100123412341234', 2000000, 0),
('3400123412341234', 5000000, 0)
ON CONFLICT (card_no) DO NOTHING;
INSERT INTO au_blacklist (card_no, reason) VALUES
('4000999999999999', 'REPORTED_STOLEN')
ON CONFLICT (card_no) DO NOTHING;

110
db/schema.d/25-py.sql Normal file
View file

@ -0,0 +1,110 @@
-- py 모듈 (지급) 스키마 - 지급 원장 / 지급계좌 / 지급파일 / 예약 / 조정 / 집계
-- Loaded into PostgreSQL on first boot (docker-entrypoint-initdb.d). Prefix 25.
-- ---------------------------------------------------------------------------
-- 지급 원장 (payout)
-- status: R=요청, H=보류, A=승인, J=반려, F=파일편성, P=지급완료,
-- C=취소, V=역분개, X=마감
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS py_payout_seq;
CREATE TABLE IF NOT EXISTS py_payout (
payout_id BIGINT PRIMARY KEY,
merchant_id TEXT NOT NULL DEFAULT '',
account_no TEXT NOT NULL DEFAULT '',
amount BIGINT NOT NULL,
fee BIGINT NOT NULL DEFAULT 0,
net BIGINT NOT NULL,
status TEXT NOT NULL,
channel TEXT NOT NULL DEFAULT 'STD', -- STD/SPLIT/BULK/ADVANCE
file_id BIGINT NOT NULL DEFAULT 0,
retry_count INTEGER NOT NULL DEFAULT 0,
reject_reason TEXT NOT NULL DEFAULT '',
biz_date DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 지급계좌 (py_account)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS py_account (
account_no TEXT PRIMARY KEY,
merchant_id TEXT NOT NULL DEFAULT '',
bank_code TEXT NOT NULL DEFAULT '',
holder TEXT NOT NULL DEFAULT '',
balance BIGINT NOT NULL DEFAULT 0,
status TEXT NOT NULL DEFAULT 'ACTIVE',
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 지급 파일 (py_file) - status: G=생성, C=확정
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS py_file_seq;
CREATE TABLE IF NOT EXISTS py_file (
file_id BIGINT PRIMARY KEY,
biz_date DATE NOT NULL,
file_name TEXT NOT NULL,
record_count BIGINT NOT NULL DEFAULT 0,
total_amount BIGINT NOT NULL DEFAULT 0,
status TEXT NOT NULL DEFAULT 'G',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
confirmed_at TIMESTAMPTZ
);
-- ---------------------------------------------------------------------------
-- 지급 예약 (py_schedule) - status: S=예약, D=실행
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS py_schedule_seq;
CREATE TABLE IF NOT EXISTS py_schedule (
schedule_id BIGINT PRIMARY KEY,
payout_id BIGINT NOT NULL,
run_date DATE NOT NULL,
status TEXT NOT NULL DEFAULT 'S',
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 지급 조정 (py_adjust)
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS py_adjust_seq;
CREATE TABLE IF NOT EXISTS py_adjust (
adj_id BIGINT PRIMARY KEY,
payout_id BIGINT NOT NULL,
delta BIGINT NOT NULL,
reason TEXT NOT NULL DEFAULT '',
biz_date DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 지급 원장 상세 (py_ledger) - 이체/연계 원장
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS py_ledger_seq;
CREATE TABLE IF NOT EXISTS py_ledger (
ledger_id BIGINT PRIMARY KEY,
payout_id BIGINT NOT NULL,
entry_type TEXT NOT NULL,
amount BIGINT NOT NULL,
biz_date DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 가맹점 일별 지급 집계 (py_summary) - 배치/서비스가 채움
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS py_summary (
merchant_id TEXT NOT NULL,
biz_date DATE NOT NULL,
payout_count BIGINT NOT NULL DEFAULT 0,
payout_amount BIGINT NOT NULL DEFAULT 0,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
PRIMARY KEY (merchant_id, biz_date)
);
-- Seed payout accounts so PAY_REMIT/PAY_ACCTCHK have counterparties.
INSERT INTO py_account (account_no, merchant_id, bank_code, holder, balance, status) VALUES
('110-1234-567890', 'M0001', '020', '클라로 커피', 500000000, 'ACTIVE'),
('333-9876-543210', 'M0002', '088', '포지 마트', 500000000, 'ACTIVE'),
('456-0000-111222', 'M0003', '004', '클라로 면세점', 900000000, 'ACTIVE')
ON CONFLICT (account_no) DO NOTHING;

69
db/schema.d/30-rc.sql Normal file
View file

@ -0,0 +1,69 @@
-- rc 모듈 (대사) 상세 테이블. Prefix 30 (00-base 다음, 35-st 이전에 로드).
-- ECPG 서버/배치가 참조하는 대사 로그/예외/차이/경보/요약 테이블 + 시퀀스.
-- ---------------------------------------------------------------------------
-- 대사 로그 (rc_match_log) - 서비스별 대사 결과 1행
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS rc_match_seq;
CREATE TABLE IF NOT EXISTS rc_match_log (
match_id BIGINT PRIMARY KEY,
purchase_id BIGINT NOT NULL,
match_type TEXT NOT NULL, -- APPR_ACQ/ACQ_DEP/3WAY/PARTIAL/MANUAL/RETURN/DELAY/TOLERANCE
amount BIGINT NOT NULL DEFAULT 0,
status TEXT NOT NULL DEFAULT 'MATCHED',-- MATCHED/HOLD/EXCEPTION/RELEASED/CONFIRMED/ROLLBACK
biz_date DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 대사 예외 (rc_exception)
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS rc_exc_seq;
CREATE TABLE IF NOT EXISTS rc_exception (
exc_id BIGINT PRIMARY KEY,
purchase_id BIGINT NOT NULL,
reason TEXT NOT NULL DEFAULT '',
biz_date DATE NOT NULL,
resolved BOOLEAN NOT NULL DEFAULT false,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 대사 차이 (rc_diff) - 금액/건수 차이 리포트 라인
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS rc_diff_seq;
CREATE TABLE IF NOT EXISTS rc_diff (
diff_id BIGINT PRIMARY KEY,
purchase_id BIGINT NOT NULL DEFAULT 0,
expected_amt BIGINT NOT NULL DEFAULT 0,
actual_amt BIGINT NOT NULL DEFAULT 0,
diff_amt BIGINT NOT NULL DEFAULT 0,
diff_kind TEXT NOT NULL DEFAULT 'AMT', -- AMT / CNT
biz_date DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 대사 경보 (rc_alert)
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS rc_alert_seq;
CREATE TABLE IF NOT EXISTS rc_alert (
alert_id BIGINT PRIMARY KEY,
purchase_id BIGINT NOT NULL DEFAULT 0,
lvl TEXT NOT NULL DEFAULT 'INFO',
message TEXT NOT NULL DEFAULT '',
biz_date DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 대사 요약 (rc_summary) - 영업일 1행 (배치/RC_SUMMARY가 upsert)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS rc_summary (
biz_date DATE PRIMARY KEY,
matched_cnt BIGINT NOT NULL DEFAULT 0,
unmatched_cnt BIGINT NOT NULL DEFAULT 0,
gross_amount BIGINT NOT NULL DEFAULT 0,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

77
db/schema.d/35-st.sql Normal file
View file

@ -0,0 +1,77 @@
-- st 모듈 (정산/수수료) 상세 테이블. Prefix 35 (30-rc 다음).
-- ECPG 서버/배치가 참조하는 정산 상세/수수료율/조정/지급/가맹점집계 테이블 + 시퀀스.
-- ---------------------------------------------------------------------------
-- 정산 상세 (st_settle_dtl) - 수수료 종류별 정산 라인
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS st_dtl_seq;
CREATE TABLE IF NOT EXISTS st_settle_dtl (
dtl_id BIGINT PRIMARY KEY,
settlement_id BIGINT NOT NULL DEFAULT 0,
purchase_id BIGINT NOT NULL DEFAULT 0,
merchant_id TEXT NOT NULL DEFAULT '',
fee_type TEXT NOT NULL, -- MDR/VAN/RELAY/WHT/VAT/ADJ/DELAYINT/CAP/RATE
amount BIGINT NOT NULL DEFAULT 0,
biz_date DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 수수료 요율표 (st_fee_rate) - 구간별 요율 (basis points)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS st_fee_rate (
fee_type TEXT NOT NULL,
band_min BIGINT NOT NULL DEFAULT 0, -- 이 금액 이상에 적용
rate_bps BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (fee_type, band_min)
);
-- ---------------------------------------------------------------------------
-- 정산 조정 (st_adjust) - 가감/상계/취소 조정
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS st_adj_seq;
CREATE TABLE IF NOT EXISTS st_adjust (
adj_id BIGINT PRIMARY KEY,
settlement_id BIGINT NOT NULL DEFAULT 0,
purchase_id BIGINT NOT NULL DEFAULT 0,
delta BIGINT NOT NULL DEFAULT 0,
reason TEXT NOT NULL DEFAULT '',
biz_date DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 지급 (st_payment) - 가맹점 지급 예정/보류/완료
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS st_pay_seq;
CREATE TABLE IF NOT EXISTS st_payment (
pay_id BIGINT PRIMARY KEY,
merchant_id TEXT NOT NULL,
net_amount BIGINT NOT NULL DEFAULT 0,
pay_date DATE NOT NULL,
status TEXT NOT NULL DEFAULT 'SCHEDULED', -- SCHEDULED/HELD/PAID/CANCELLED
biz_date DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 가맹점 정산 집계 (st_merch_settle) - 배치/ST_BYMERCH가 upsert
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS st_merch_settle (
merchant_id TEXT NOT NULL,
biz_date DATE NOT NULL,
txn_count BIGINT NOT NULL DEFAULT 0,
gross_amount BIGINT NOT NULL DEFAULT 0,
fee_amount BIGINT NOT NULL DEFAULT 0,
net_amount BIGINT NOT NULL DEFAULT 0,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
PRIMARY KEY (merchant_id, biz_date)
);
-- 수수료 구간 요율 시드 (ST_BANDRATE / ST_RATEAPPLY 가 조회)
INSERT INTO st_fee_rate (fee_type, band_min, rate_bps) VALUES
('MDR', 0, 25),
('MDR', 10000000, 20),
('VAN', 0, 10),
('RELAY', 0, 5)
ON CONFLICT (fee_type, band_min) DO NOTHING;

67
db/schema.d/40-lg.sql Normal file
View file

@ -0,0 +1,67 @@
-- ---------------------------------------------------------------------------
-- lg 모듈 (원장/ledger) - 복식부기 전표/원장/계정잔액 스키마 (prefix 40)
-- Loaded after 00-base.sql by docker-entrypoint-initdb.d.
-- lg 서비스/배치가 채우는 전표(voucher) + 원장 라인(ledger_line) + 계정잔액 테이블.
-- ---------------------------------------------------------------------------
-- 전표 (voucher) - 하나의 회계 이벤트(매입전기/정산전기/조정/대체 등)의 헤더
CREATE SEQUENCE IF NOT EXISTS lg_voucher_seq;
CREATE TABLE IF NOT EXISTS lg_voucher (
voucher_id BIGINT PRIMARY KEY,
voucher_type TEXT NOT NULL, -- POST/DOUBLE/ADJ/REVERSE/TRANSFER/SETTLE/ACQ/FEE
ref_id BIGINT NOT NULL DEFAULT 0, -- 연계 매입/정산 ID
biz_date DATE NOT NULL,
status TEXT NOT NULL DEFAULT 'D', -- D=작성, P=전기, M=대사, S=마감연계, X=취소
memo TEXT NOT NULL DEFAULT '',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- 원장 라인 (ledger_line) - 복식부기 차변(D)/대변(C) 개별 분개
CREATE SEQUENCE IF NOT EXISTS lg_line_seq;
CREATE TABLE IF NOT EXISTS lg_ledger_line (
line_id BIGINT PRIMARY KEY,
voucher_id BIGINT NOT NULL,
acct TEXT NOT NULL, -- 계정과목: RECV/MERCH_PAY/FEE_INC/CASH/ADJ ...
dc TEXT NOT NULL, -- D=차변(debit), C=대변(credit)
amount BIGINT NOT NULL,
merchant_id TEXT NOT NULL DEFAULT '',
biz_date DATE NOT NULL,
status TEXT NOT NULL DEFAULT 'posted', -- posted / closed
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS ix_lg_line_voucher ON lg_ledger_line(voucher_id);
CREATE INDEX IF NOT EXISTS ix_lg_line_acct ON lg_ledger_line(acct, biz_date);
-- 계정잔액 (account balance) - 계정과목 x 영업일 누계
CREATE TABLE IF NOT EXISTS lg_account_bal (
acct TEXT NOT NULL,
biz_date DATE NOT NULL,
debit_total BIGINT NOT NULL DEFAULT 0,
credit_total BIGINT NOT NULL DEFAULT 0,
balance BIGINT NOT NULL DEFAULT 0, -- 차변 - 대변
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
PRIMARY KEY (acct, biz_date)
);
-- 가맹점 잔액 (merchant balance) - 가맹점 x 영업일 미지급/미수 누계
CREATE TABLE IF NOT EXISTS lg_merch_bal (
merchant_id TEXT NOT NULL,
biz_date DATE NOT NULL,
debit_total BIGINT NOT NULL DEFAULT 0,
credit_total BIGINT NOT NULL DEFAULT 0,
balance BIGINT NOT NULL DEFAULT 0,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
PRIMARY KEY (merchant_id, biz_date)
);
-- 시산표 (trial balance) - 배치가 계정별로 채움
CREATE TABLE IF NOT EXISTS lg_trial_bal (
acct TEXT NOT NULL,
biz_date DATE NOT NULL,
debit_total BIGINT NOT NULL DEFAULT 0,
credit_total BIGINT NOT NULL DEFAULT 0,
diff BIGINT NOT NULL DEFAULT 0, -- 차변 - 대변 (0 이어야 정상)
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
PRIMARY KEY (acct, biz_date)
);

51
db/schema.d/45-cl.sql Normal file
View file

@ -0,0 +1,51 @@
-- ---------------------------------------------------------------------------
-- cl 모듈 (마감/closing) - 일/월/분기/연 마감 로그 + 스냅샷 + 기간잠금 (prefix 45)
-- Loaded after 40-lg.sql by docker-entrypoint-initdb.d.
-- cl 서비스/배치가 채우는 마감이력(close_log) + 마감스냅샷(snapshot) 테이블.
-- ---------------------------------------------------------------------------
-- 마감 이력 (close_log) - 하나의 마감 실행(일/월/분기/연/중간)의 헤더
CREATE SEQUENCE IF NOT EXISTS cl_close_seq;
CREATE TABLE IF NOT EXISTS cl_close_log (
close_id BIGINT PRIMARY KEY,
close_type TEXT NOT NULL, -- DAILY/MONTHLY/QUARTER/YEAREND/MID
period_key TEXT NOT NULL, -- YYYY-MM-DD / YYYY-MM / YYYY-Qn / YYYY
biz_date DATE NOT NULL,
status TEXT NOT NULL DEFAULT 'O', -- O=개시, C=마감완료, R=재마감, A=승인, L=잠금, X=취소
txn_count BIGINT NOT NULL DEFAULT 0,
total_amount BIGINT NOT NULL DEFAULT 0,
memo TEXT NOT NULL DEFAULT '',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS ix_cl_close_period ON cl_close_log(close_type, period_key);
-- 마감 스냅샷 (snapshot) - 마감 시점 가맹점별 집계 고정
CREATE SEQUENCE IF NOT EXISTS cl_snapshot_seq;
CREATE TABLE IF NOT EXISTS cl_snapshot (
snapshot_id BIGINT PRIMARY KEY,
close_id BIGINT NOT NULL,
period_key TEXT NOT NULL,
biz_date DATE NOT NULL,
merchant_id TEXT NOT NULL,
gross_amount BIGINT NOT NULL DEFAULT 0,
fee_amount BIGINT NOT NULL DEFAULT 0,
net_amount BIGINT NOT NULL DEFAULT 0,
txn_count BIGINT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS ix_cl_snapshot_close ON cl_snapshot(close_id);
-- 기간 잠금 (period lock) - 마감된 기간의 추가 정정 차단
CREATE TABLE IF NOT EXISTS cl_period_lock (
period_key TEXT PRIMARY KEY,
locked BOOLEAN NOT NULL DEFAULT true,
locked_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- 마감 시퀀스 관리 (close_type 별 마지막 순번)
CREATE TABLE IF NOT EXISTS cl_seq_reg (
close_type TEXT PRIMARY KEY,
last_seq BIGINT NOT NULL DEFAULT 0,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

162
db/schema.d/50-mm.sql Normal file
View file

@ -0,0 +1,162 @@
-- mm 모듈 (마스터/master) 상세 스키마
-- 가맹점 확장원장 / 수수료율 / BIN / 공통코드 / 한도 / 발급사 / 단말 / MCC /
-- 공휴일 / 환율 마스터 + 이력. Loaded on first boot (docker-entrypoint-initdb.d).
-- ---------------------------------------------------------------------------
-- 가맹점 확장 마스터 (mm_merchant_ext) - base merchant를 보강하는 마스터 원장
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS mm_merchant_ext (
merchant_id TEXT PRIMARY KEY,
name TEXT NOT NULL,
biz_reg_no TEXT NOT NULL DEFAULT '', -- 사업자등록번호
grade TEXT NOT NULL DEFAULT 'C', -- 가맹점 등급 (S/A/B/C)
settle_acct TEXT NOT NULL DEFAULT '', -- 정산 계좌
mcc TEXT NOT NULL DEFAULT '0000', -- 업종코드
status TEXT NOT NULL DEFAULT 'ACTIVE',-- ACTIVE / HOLD / DELETED
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- 가맹점 마스터 변경 이력
CREATE SEQUENCE IF NOT EXISTS mm_merch_hist_seq;
CREATE TABLE IF NOT EXISTS mm_merch_hist (
hist_id BIGINT PRIMARY KEY,
merchant_id TEXT NOT NULL,
action TEXT NOT NULL, -- REG / UPD / DEL / STATUS / GRADE / ACCT
before_val TEXT NOT NULL DEFAULT '',
after_val TEXT NOT NULL DEFAULT '',
memo TEXT NOT NULL DEFAULT '',
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 수수료율 마스터 (mm_fee_rate) + 이력
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS mm_fee_rate (
merchant_id TEXT NOT NULL,
card_type TEXT NOT NULL DEFAULT 'CREDIT',-- CREDIT / CHECK / PREPAID
rate_bps BIGINT NOT NULL DEFAULT 25, -- basis points
eff_date DATE NOT NULL DEFAULT current_date,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
PRIMARY KEY (merchant_id, card_type)
);
CREATE SEQUENCE IF NOT EXISTS mm_feerate_hist_seq;
CREATE TABLE IF NOT EXISTS mm_fee_rate_hist (
hist_id BIGINT PRIMARY KEY,
merchant_id TEXT NOT NULL,
card_type TEXT NOT NULL,
rate_bps BIGINT NOT NULL,
eff_date DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- BIN 마스터 (mm_bin)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS mm_bin (
bin TEXT PRIMARY KEY, -- 6-8 digit BIN
issuer_cd TEXT NOT NULL DEFAULT 'UNKNOWN',
card_brand TEXT NOT NULL DEFAULT 'LOCAL', -- VISA / MASTER / LOCAL
card_type TEXT NOT NULL DEFAULT 'CREDIT',
status TEXT NOT NULL DEFAULT 'ACTIVE',
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 공통코드 마스터 (mm_code)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS mm_code (
code_group TEXT NOT NULL,
code TEXT NOT NULL,
code_name TEXT NOT NULL DEFAULT '',
sort_order INTEGER NOT NULL DEFAULT 0,
status TEXT NOT NULL DEFAULT 'ACTIVE',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
PRIMARY KEY (code_group, code)
);
-- ---------------------------------------------------------------------------
-- 가맹점 한도 마스터 (mm_limit)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS mm_limit (
merchant_id TEXT PRIMARY KEY,
daily_limit BIGINT NOT NULL DEFAULT 100000000,
monthly_limit BIGINT NOT NULL DEFAULT 3000000000,
per_txn_limit BIGINT NOT NULL DEFAULT 10000000,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 발급사 마스터 (mm_issuer)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS mm_issuer (
issuer_cd TEXT PRIMARY KEY,
issuer_name TEXT NOT NULL DEFAULT '',
country TEXT NOT NULL DEFAULT 'KR',
status TEXT NOT NULL DEFAULT 'ACTIVE',
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 단말 마스터 (mm_terminal)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS mm_terminal (
terminal_id TEXT PRIMARY KEY,
merchant_id TEXT NOT NULL,
model TEXT NOT NULL DEFAULT 'STD',
status TEXT NOT NULL DEFAULT 'ACTIVE',
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- MCC 업종 마스터 (mm_mcc)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS mm_mcc (
mcc TEXT PRIMARY KEY,
mcc_name TEXT NOT NULL DEFAULT '',
risk_level INTEGER NOT NULL DEFAULT 1
);
-- ---------------------------------------------------------------------------
-- 공휴일 마스터 (mm_holiday)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS mm_holiday (
holiday_date DATE PRIMARY KEY,
holiday_name TEXT NOT NULL DEFAULT '',
nation TEXT NOT NULL DEFAULT 'KR'
);
-- ---------------------------------------------------------------------------
-- 환율 마스터 (mm_fx_rate)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS mm_fx_rate (
ccy TEXT PRIMARY KEY,
rate_bps BIGINT NOT NULL DEFAULT 100, -- KRW per unit, in bps of 100
base_date DATE NOT NULL DEFAULT current_date,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 등급 통계 (mm_grade_stat) - mm_stat_batch가 채움
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS mm_grade_stat (
stat_date DATE NOT NULL,
grade TEXT NOT NULL,
merch_cnt BIGINT NOT NULL DEFAULT 0,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
PRIMARY KEY (stat_date, grade)
);
-- Seed 몇 개 마스터 (테스트/데모용)
INSERT INTO mm_code (code_group, code, code_name, sort_order) VALUES
('CARD_TYPE', 'CREDIT', '신용카드', 1),
('CARD_TYPE', 'CHECK', '체크카드', 2),
('GRADE', 'S', '최우수', 1),
('GRADE', 'A', '우수', 2)
ON CONFLICT (code_group, code) DO NOTHING;
INSERT INTO mm_issuer (issuer_cd, issuer_name, country) VALUES
('BC', 'BC카드', 'KR'),
('SHC', '신한카드', 'KR')
ON CONFLICT (issuer_cd) DO NOTHING;

53
db/schema.d/55-vl.sql Normal file
View file

@ -0,0 +1,53 @@
-- vl 모듈 (정합성검증/validation) 상세 스키마
-- 검증 규칙 / 의심거래(suspect) / 검증 로그. Loaded on first boot.
-- ---------------------------------------------------------------------------
-- 검증 규칙 마스터 (vl_rule)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS vl_rule (
rule_code TEXT PRIMARY KEY,
rule_name TEXT NOT NULL DEFAULT '',
threshold BIGINT NOT NULL DEFAULT 0, -- 규칙별 임계값 (금액/건수 등)
severity TEXT NOT NULL DEFAULT 'WARN', -- INFO / WARN / ERROR / CRIT
status TEXT NOT NULL DEFAULT 'ACTIVE',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 의심거래 (vl_suspect) - 검증 실패/이상 거래 적재
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS vl_suspect_seq;
CREATE TABLE IF NOT EXISTS vl_suspect (
suspect_id BIGINT PRIMARY KEY,
purchase_id BIGINT NOT NULL DEFAULT 0,
rule_code TEXT NOT NULL,
severity TEXT NOT NULL DEFAULT 'WARN',
detail TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL DEFAULT 'OPEN', -- OPEN / CONFIRMED / CLOSED
biz_date DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 검증 로그 (vl_check_log) - 모든 검증 서비스 호출 기록
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS vl_checklog_seq;
CREATE TABLE IF NOT EXISTS vl_check_log (
log_id BIGINT PRIMARY KEY,
check_type TEXT NOT NULL, -- 서비스명 (VL_SALES 등)
target_id BIGINT NOT NULL DEFAULT 0, -- 검증 대상 (purchase_id 등)
result_code BIGINT NOT NULL DEFAULT 0, -- 0=정상, >0=검증 실패코드
detail TEXT NOT NULL DEFAULT '',
biz_date DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- Seed 기본 검증 규칙
INSERT INTO vl_rule (rule_code, rule_name, threshold, severity) VALUES
('AMT_MAX', '최대금액 초과', 50000000, 'ERROR'),
('AMT_ZERO', '0원/음수 금액', 0, 'ERROR'),
('DUP_TXN', '중복 매입', 1, 'WARN'),
('LIMIT_OVR', '일한도 초과', 0, 'WARN'),
('LEDGER_MIS','원장 불일치', 0, 'CRIT')
ON CONFLICT (rule_code) DO NOTHING;

119
db/schema.d/60-mg.sql Normal file
View file

@ -0,0 +1,119 @@
-- mg 모듈 (전문게이트웨이 / message gateway) 스키마
-- ISO8583 전문 로그/라우팅/채번/채널세션/큐/통계 테이블.
-- Loaded into PostgreSQL on first boot (docker-entrypoint-initdb.d). Prefix 60.
-- ---------------------------------------------------------------------------
-- 전문 채번 (STAN / 전문 시퀀스) - MG_STAN 이 nextval 로 채번
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS mg_stan_seq; -- System Trace Audit Number
CREATE SEQUENCE IF NOT EXISTS mg_msg_seq; -- 전문 로그 PK
CREATE SEQUENCE IF NOT EXISTS mg_route_seq; -- 라우팅 룰 PK
CREATE SEQUENCE IF NOT EXISTS mg_queue_seq; -- 송수신 큐 PK
-- 이름있는 카운터 (세션 시퀀스 등 채번용 - MG_SESSION/MG_KEYEXCH)
CREATE TABLE IF NOT EXISTS mg_seq (
seq_name TEXT PRIMARY KEY,
seq_val BIGINT NOT NULL DEFAULT 0,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 전문 로그 (mg_msg_log) - 수신/송신 전문의 원장
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS mg_msg_log (
msg_id BIGINT PRIMARY KEY,
stan BIGINT NOT NULL, -- 전문 추적번호
mti TEXT NOT NULL, -- 전문유형(0200/0210/0800...)
channel TEXT NOT NULL, -- 채널ID
direction TEXT NOT NULL, -- IN / OUT
proc_code TEXT NOT NULL DEFAULT '000000', -- 처리코드
bitmap TEXT NOT NULL DEFAULT '', -- 비트맵(hex)
amount BIGINT NOT NULL DEFAULT 0,
pan TEXT NOT NULL DEFAULT '', -- (마스킹된) 카드번호
mac TEXT NOT NULL DEFAULT '', -- 메시지 인증코드
rc TEXT NOT NULL DEFAULT '00', -- 응답코드
raw_msg TEXT NOT NULL DEFAULT '', -- 원 전문
status TEXT NOT NULL DEFAULT 'R', -- R=수신, S=송신, A=ACK, N=NACK, C=확인
biz_date DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS ix_mg_msg_log_stan ON mg_msg_log (stan);
CREATE INDEX IF NOT EXISTS ix_mg_msg_log_chan ON mg_msg_log (channel, biz_date);
-- ---------------------------------------------------------------------------
-- 라우팅 룰 (mg_route) - 채널/전문유형 -> 목적지 매핑
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS mg_route (
route_id BIGINT PRIMARY KEY,
channel TEXT NOT NULL,
mti TEXT NOT NULL,
dest TEXT NOT NULL, -- 목적지 서비스/노드
priority INTEGER NOT NULL DEFAULT 100,
active BOOLEAN NOT NULL DEFAULT true,
biz_date DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS ix_mg_route_lookup ON mg_route (channel, mti, active);
-- ---------------------------------------------------------------------------
-- 채널 (mg_channel) - 세션/사인온 상태
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS mg_channel (
channel TEXT PRIMARY KEY,
name TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL DEFAULT 'DOWN', -- UP / DOWN / SIGNON / SIGNOFF
session_key TEXT NOT NULL DEFAULT '',
last_stan BIGINT NOT NULL DEFAULT 0,
signon_at TIMESTAMPTZ,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 송수신 큐 (mg_queue) - 재전송 대상 관리
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS mg_queue (
queue_id BIGINT PRIMARY KEY,
stan BIGINT NOT NULL,
channel TEXT NOT NULL,
mti TEXT NOT NULL DEFAULT '',
payload TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL DEFAULT 'Q', -- Q=대기, S=송신, D=완료, F=실패
retry_cnt INTEGER NOT NULL DEFAULT 0,
biz_date DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS ix_mg_queue_status ON mg_queue (status, biz_date);
-- ---------------------------------------------------------------------------
-- 채널 일별 통계 (mg_stat) - mg_stat_batch 가 채움
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS mg_stat (
channel TEXT NOT NULL,
biz_date DATE NOT NULL,
in_cnt BIGINT NOT NULL DEFAULT 0,
out_cnt BIGINT NOT NULL DEFAULT 0,
err_cnt BIGINT NOT NULL DEFAULT 0,
amount_sum BIGINT NOT NULL DEFAULT 0,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
PRIMARY KEY (channel, biz_date)
);
-- ---------------------------------------------------------------------------
-- Seed: 채널 + 기본 라우팅 룰
-- ---------------------------------------------------------------------------
INSERT INTO mg_channel (channel, name, status) VALUES
('CH01', 'VAN 게이트웨이', 'DOWN'),
('CH02', '매입사 링크', 'DOWN'),
('CH03', '해외 네트워크', 'DOWN')
ON CONFLICT (channel) DO NOTHING;
INSERT INTO mg_route (route_id, channel, mti, dest, priority, active, biz_date) VALUES
(nextval('mg_route_seq'), 'CH01', '0200', 'ACQUIRE', 10, true, '2026-07-19'),
(nextval('mg_route_seq'), 'CH01', '0800', 'MG_ECHO', 20, true, '2026-07-19'),
(nextval('mg_route_seq'), 'CH02', '0200', 'ACQ_EDC', 10, true, '2026-07-19')
ON CONFLICT DO NOTHING;
INSERT INTO mg_seq (seq_name, seq_val) VALUES
('SESSION', 0), ('KEYVER', 0)
ON CONFLICT (seq_name) DO NOTHING;

112
db/schema.d/65-cm.sql Normal file
View file

@ -0,0 +1,112 @@
-- cm 모듈 (공통 / common) 스키마
-- 공통코드/파라미터/휴일/환율/채번/공통로그 + seed 데이터. Prefix 65.
-- Loaded into PostgreSQL on first boot (docker-entrypoint-initdb.d).
-- ---------------------------------------------------------------------------
-- 공통코드 (cm_code)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS cm_code (
code_grp TEXT NOT NULL, -- 코드 그룹 (예: CCY, CHANNEL)
code TEXT NOT NULL, -- 코드 값
code_name TEXT NOT NULL, -- 코드 명
sort_ord INTEGER NOT NULL DEFAULT 0,
use_yn TEXT NOT NULL DEFAULT 'Y',
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
PRIMARY KEY (code_grp, code)
);
-- ---------------------------------------------------------------------------
-- 공통 파라미터 (cm_param) - 시스템 운영 파라미터 (BIZ_DATE 포함)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS cm_param (
param_key TEXT PRIMARY KEY,
param_val TEXT NOT NULL,
descr TEXT NOT NULL DEFAULT '',
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 휴일 (cm_holiday) - 영업일 계산에 사용
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS cm_holiday (
holi_date DATE PRIMARY KEY,
holi_name TEXT NOT NULL,
nation TEXT NOT NULL DEFAULT 'KR'
);
-- ---------------------------------------------------------------------------
-- 환율 (cm_fx_rate) - 통화별 기준일 환율 (bps of 100 = KRW*100/unit)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS cm_fx_rate (
ccy TEXT NOT NULL,
base_date DATE NOT NULL,
rate_bps BIGINT NOT NULL, -- KRW per unit * 100
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
PRIMARY KEY (ccy, base_date)
);
-- ---------------------------------------------------------------------------
-- 채번 (cm_seq) - 이름있는 공통 시퀀스 (CM_SEQ 서비스)
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS cm_seq (
seq_name TEXT PRIMARY KEY,
seq_val BIGINT NOT NULL DEFAULT 0,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ---------------------------------------------------------------------------
-- 공통 로그 (cm_log) - CM_LOG 서비스 + cm_purge_batch 대상
-- ---------------------------------------------------------------------------
CREATE SEQUENCE IF NOT EXISTS cm_log_seq;
CREATE TABLE IF NOT EXISTS cm_log (
log_id BIGINT PRIMARY KEY,
svc_name TEXT NOT NULL DEFAULT '',
log_level TEXT NOT NULL DEFAULT 'I', -- I/W/E
msg TEXT NOT NULL DEFAULT '',
biz_date DATE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS ix_cm_log_date ON cm_log (biz_date);
-- ---------------------------------------------------------------------------
-- Seed rows
-- ---------------------------------------------------------------------------
INSERT INTO cm_code (code_grp, code, code_name, sort_ord) VALUES
('CCY', 'KRW', '원화', 1),
('CCY', 'USD', '미국 달러', 2),
('CCY', 'JPY', '일본 엔', 3),
('CCY', 'EUR', '유로', 4),
('CHANNEL', 'POS', 'POS 단말', 1),
('CHANNEL', 'EDC', 'EDC 단말', 2),
('CHANNEL', 'EDI', 'EDI 청구', 3),
('CHANNEL', 'FOREIGN', '해외 매입', 4),
('STATUS', 'A', '접수', 1),
('STATUS', 'S', '정산완료', 2),
('STATUS', 'C', '취소', 3)
ON CONFLICT (code_grp, code) DO NOTHING;
INSERT INTO cm_param (param_key, param_val, descr) VALUES
('BIZ_DATE', '2026-07-19', '현재 영업일'),
('VAT_RATE', '10', '부가세율(%)'),
('WHT_BPS', '2200', '원천징수율(bps)'),
('LOG_KEEP_DAYS','90', '공통로그 보존일수'),
('SETTLE_CYCLE','1', '정산주기(일)')
ON CONFLICT (param_key) DO NOTHING;
INSERT INTO cm_holiday (holi_date, holi_name, nation) VALUES
('2026-01-01', '신정', 'KR'),
('2026-03-01', '삼일절', 'KR'),
('2026-05-05', '어린이날', 'KR'),
('2026-08-15', '광복절', 'KR'),
('2026-12-25', '성탄절', 'KR')
ON CONFLICT (holi_date) DO NOTHING;
INSERT INTO cm_fx_rate (ccy, base_date, rate_bps) VALUES
('USD', '2026-07-19', 135000), -- 1350.00 KRW
('JPY', '2026-07-19', 900), -- 9.00 KRW
('EUR', '2026-07-19', 147000) -- 1470.00 KRW
ON CONFLICT (ccy, base_date) DO NOTHING;
INSERT INTO cm_seq (seq_name, seq_val) VALUES
('BATCH', 0), ('SLIP', 0), ('TICKET', 0)
ON CONFLICT (seq_name) DO NOTHING;