feat: project skeleton + DB migrations V1-V12 + ga-common framework

- Gradle multi-module: ga-common, ga-core, ga-api, ga-batch, ga-admin
- Flyway V1-V12: org/product/rule/receive/ledger/settle/batch/code/menu/system + seed
- ga-common (complete):
  - model: ApiResponse, PageResponse, SearchParam, TreeNode
  - exception: ErrorCode, BizException, GlobalExceptionHandler
  - annotation + aop: @RequirePermission, @DataChangeLog, ApiLog
  - auth + security: JWT, SecurityConfig
  - mybatis: BaseMapper, EncryptTypeHandler, JsonTypeHandler, AuditInterceptor
  - code (Redis cached) / menu (RBAC tree) / file / system / notification
  - excel: SXSSF+Cursor export, SAX+batch import (1M/700K rows)
  - util: Date/Money/Mask/Encrypt/Security
This commit is contained in:
GA Pro
2026-05-09 21:29:18 +09:00
parent c716f5eb70
commit cef4e48e27
100 changed files with 4914 additions and 0 deletions
@@ -0,0 +1,54 @@
-- V10: 메뉴 / 권한 / 역할
CREATE TABLE menu (
menu_id SERIAL PRIMARY KEY,
parent_menu_id BIGINT REFERENCES menu(menu_id),
menu_code VARCHAR(50) NOT NULL UNIQUE,
menu_name VARCHAR(100) NOT NULL,
menu_type VARCHAR(20) NOT NULL, -- DIRECTORY / PAGE / LINK
menu_path VARCHAR(200),
menu_icon VARCHAR(50),
component_path VARCHAR(200),
menu_level INT NOT NULL,
sort_order INT NOT NULL DEFAULT 0,
is_visible CHAR(1) NOT NULL DEFAULT 'Y',
is_active CHAR(1) NOT NULL DEFAULT 'Y',
description VARCHAR(300)
);
CREATE INDEX idx_menu_parent ON menu(parent_menu_id, sort_order);
CREATE TABLE menu_permission (
perm_id SERIAL PRIMARY KEY,
menu_id BIGINT NOT NULL REFERENCES menu(menu_id),
perm_code VARCHAR(20) NOT NULL, -- READ / CREATE / UPDATE / DELETE / APPROVE / EXPORT / PRINT
perm_name VARCHAR(50) NOT NULL,
sort_order INT NOT NULL DEFAULT 0,
UNIQUE (menu_id, perm_code)
);
CREATE TABLE role (
role_id SERIAL PRIMARY KEY,
role_code VARCHAR(50) NOT NULL UNIQUE,
role_name VARCHAR(100) NOT NULL,
role_desc VARCHAR(300),
role_level INT NOT NULL DEFAULT 0,
is_system CHAR(1) NOT NULL DEFAULT 'N',
is_active CHAR(1) NOT NULL DEFAULT 'Y'
);
CREATE TABLE role_menu_permission (
rmp_id SERIAL PRIMARY KEY,
role_id BIGINT NOT NULL REFERENCES role(role_id),
menu_id BIGINT NOT NULL REFERENCES menu(menu_id),
perm_code VARCHAR(20) NOT NULL,
is_granted CHAR(1) NOT NULL DEFAULT 'Y',
UNIQUE (role_id, menu_id, perm_code)
);
CREATE INDEX idx_rmp_role ON role_menu_permission(role_id);
CREATE TABLE user_role (
ur_id SERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(user_id),
role_id BIGINT NOT NULL REFERENCES role(role_id),
UNIQUE (user_id, role_id)
);
@@ -0,0 +1,83 @@
-- V11: 시스템관리 (로그인로그/API로그/변경이력/파일/알림/시스템설정)
CREATE TABLE login_log (
log_id SERIAL PRIMARY KEY,
user_id BIGINT,
login_id VARCHAR(50),
login_type VARCHAR(20), -- SUCCESS / FAIL / LOGOUT
fail_reason VARCHAR(200),
ip_address VARCHAR(50),
user_agent VARCHAR(500),
login_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_ll_user ON login_log(user_id, login_at);
CREATE TABLE api_access_log (
log_id SERIAL PRIMARY KEY,
user_id BIGINT,
method VARCHAR(10),
url VARCHAR(500),
request_param TEXT,
response_code VARCHAR(10),
response_time INT,
ip_address VARCHAR(50),
error_message TEXT,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_aal_user ON api_access_log(user_id, created_at);
CREATE TABLE data_change_log (
log_id SERIAL PRIMARY KEY,
user_id BIGINT,
menu_code VARCHAR(50),
table_name VARCHAR(50),
record_id VARCHAR(100),
action_type VARCHAR(20), -- INSERT / UPDATE / DELETE
before_data JSONB,
after_data JSONB,
changed_keys VARCHAR(1000),
ip_address VARCHAR(50),
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_dcl_table ON data_change_log(table_name, record_id, created_at);
CREATE TABLE file_storage (
file_id SERIAL PRIMARY KEY,
file_group VARCHAR(50),
original_name VARCHAR(300) NOT NULL,
stored_name VARCHAR(300) NOT NULL,
file_path VARCHAR(500) NOT NULL,
file_size BIGINT,
content_type VARCHAR(100),
extension VARCHAR(20),
download_count INT NOT NULL DEFAULT 0,
is_deleted CHAR(1) NOT NULL DEFAULT 'N',
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
created_by BIGINT
);
CREATE INDEX idx_fs_group ON file_storage(file_group, is_deleted);
CREATE TABLE notification (
noti_id SERIAL PRIMARY KEY,
user_id BIGINT NOT NULL,
noti_type VARCHAR(30),
title VARCHAR(200) NOT NULL,
content VARCHAR(1000),
link_url VARCHAR(300),
is_read CHAR(1) NOT NULL DEFAULT 'N',
read_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_noti_user ON notification(user_id, is_read, created_at);
CREATE TABLE system_config (
config_key VARCHAR(100) PRIMARY KEY,
config_value VARCHAR(2000),
config_group VARCHAR(50),
value_type VARCHAR(20), -- STRING / NUMBER / BOOLEAN / JSON
is_encrypted CHAR(1) NOT NULL DEFAULT 'N',
is_editable CHAR(1) NOT NULL DEFAULT 'Y',
description VARCHAR(300),
updated_at TIMESTAMP,
updated_by BIGINT
);
@@ -0,0 +1,103 @@
-- V12: 공통코드 / 역할 / 메뉴 / 시스템설정 초기 데이터
-- 1. 공통코드 그룹 18개
INSERT INTO common_code_group (group_code, group_name, description, is_system, sort_order) VALUES
('AGENT_STATUS', '설계사상태', 'ACTIVE/LEAVE/SUSPEND', 'Y', 10),
('CONTRACT_STATUS', '계약상태', 'ACTIVE/LAPSE/...', 'Y', 20),
('SETTLE_STATUS', '정산상태', 'CALCULATED/CONFIRMED/..', 'Y', 30),
('PAYMENT_STATUS', '지급상태', 'PENDING/SENT/DONE/FAIL', 'Y', 40),
('LEDGER_STATUS', '원장상태', 'CALCULATED/...', 'Y', 50),
('PAY_CYCLE', '납입주기', 'MONTHLY/QUARTERLY/...', 'Y', 60),
('PAY_METHOD', '납입방법', 'CARD/AUTO/CASH', 'Y', 70),
('INSURANCE_TYPE', '보험종류', 'WHOLE_LIFE/...', 'Y', 80),
('ORG_TYPE', '조직유형', 'HQ/BR/TM', 'Y', 90),
('GRADE_GROUP', '직급그룹', 'NORMAL/MANAGER/EXEC', 'Y',100),
('BANK_CODE', '은행코드', '주요 은행', 'N',110),
('YN', 'Y/N', '예/아니오', 'Y',120),
('APPROVE_STATUS', '승인상태', 'PENDING/APPROVED/...', 'Y',130),
('RECON_STATUS', '대사상태', 'PENDING/MATCHED/DIFF', 'Y',140),
('EXCEPTION_DIRECTION','예외방향', 'PLUS/MINUS', 'Y',150),
('CHANGE_TYPE', '인사변동유형', 'JOIN/LEAVE/TRANSFER...', 'Y',160),
('NOTI_TYPE', '알림유형', 'INFO/WARN/ERROR', 'Y',170),
('MENU_TYPE', '메뉴유형', 'DIRECTORY/PAGE/LINK', 'Y',180);
-- 2. 공통코드 상세 (대표 40건)
INSERT INTO common_code (group_code, code, code_name, sort_order) VALUES
('AGENT_STATUS','ACTIVE','정상',10),
('AGENT_STATUS','LEAVE','퇴사',20),
('AGENT_STATUS','SUSPEND','정지',30),
('CONTRACT_STATUS','ACTIVE','유효',10),
('CONTRACT_STATUS','LAPSE','실효',20),
('CONTRACT_STATUS','REVIVE','부활',30),
('CONTRACT_STATUS','TERMINATE','해지',40),
('SETTLE_STATUS','CALCULATED','계산완료',10),
('SETTLE_STATUS','CONFIRMED','확정',20),
('SETTLE_STATUS','HOLD','보류',30),
('SETTLE_STATUS','PAID','지급완료',40),
('PAYMENT_STATUS','PENDING','대기',10),
('PAYMENT_STATUS','SENT','이체요청',20),
('PAYMENT_STATUS','DONE','완료',30),
('PAYMENT_STATUS','FAIL','실패',40),
('PAY_CYCLE','MONTHLY','월납',10),
('PAY_CYCLE','QUARTERLY','분기납',20),
('PAY_CYCLE','ANNUAL','연납',30),
('PAY_CYCLE','LUMP','일시납',40),
('PAY_METHOD','CARD','카드',10),
('PAY_METHOD','AUTO','자동이체',20),
('PAY_METHOD','CASH','현금',30),
('INSURANCE_TYPE','WHOLE_LIFE','종신',10),
('INSURANCE_TYPE','TERM','정기',20),
('INSURANCE_TYPE','SAVINGS','저축',30),
('INSURANCE_TYPE','HEALTH','건강',40),
('ORG_TYPE','HQ','본부',10),
('ORG_TYPE','BR','지점',20),
('ORG_TYPE','TM','',30),
('YN','Y','',10),
('YN','N','아니오',20),
('APPROVE_STATUS','PENDING','대기',10),
('APPROVE_STATUS','APPROVED','승인',20),
('APPROVE_STATUS','REJECTED','반려',30),
('RECON_STATUS','PENDING','대기',10),
('RECON_STATUS','MATCHED','일치',20),
('RECON_STATUS','DIFF','차이',30),
('EXCEPTION_DIRECTION','PLUS','지급',10),
('EXCEPTION_DIRECTION','MINUS','공제',20),
('NOTI_TYPE','INFO','정보',10),
('NOTI_TYPE','WARN','경고',20),
('NOTI_TYPE','ERROR','오류',30);
-- 3. 역할 4건
INSERT INTO role (role_code, role_name, role_desc, role_level, is_system) VALUES
('SUPER_ADMIN','슈퍼관리자','전체 권한', 100,'Y'),
('ADMIN', '관리자', '시스템 운영', 80, 'Y'),
('MANAGER', '매니저', '업무 담당', 50, 'Y'),
('AGENT', '설계사', '본인 정보 조회', 10, 'Y');
-- 4. 메뉴 (대분류 10건 + 세부 일부)
INSERT INTO menu (menu_code, menu_name, menu_type, menu_path, menu_icon, menu_level, sort_order) VALUES
('DASHBOARD','대시보드','PAGE','/','DashboardOutlined',1,10),
('ORG','조직관리','DIRECTORY',NULL,'TeamOutlined',1,20),
('CONTRACT','계약관리','DIRECTORY',NULL,'FileTextOutlined',1,30),
('RULE','수수료규정','DIRECTORY',NULL,'SettingOutlined',1,40),
('RECEIVE','데이터수신','DIRECTORY',NULL,'CloudUploadOutlined',1,50),
('LEDGER','원장관리','DIRECTORY',NULL,'BookOutlined',1,60),
('SETTLE','정산관리','DIRECTORY',NULL,'CalculatorOutlined',1,70),
('PAYMENT','지급관리','DIRECTORY',NULL,'BankOutlined',1,80),
('REPORT','리포트','DIRECTORY',NULL,'BarChartOutlined',1,90),
('SYSTEM','시스템관리','DIRECTORY',NULL,'ToolOutlined',1,100);
-- 5. 시스템 설정 13건
INSERT INTO system_config (config_key, config_value, config_group, value_type, description) VALUES
('TAX_RATE', '3.3', 'TAX', 'NUMBER', '원천세율(%)'),
('SETTLE_DAY', '5', 'SETTLE', 'NUMBER', '정산 기준일'),
('PAY_DAY', '10', 'SETTLE', 'NUMBER', '지급일'),
('PASSWORD_MIN_LEN', '8', 'SECURITY','NUMBER', '비밀번호 최소 길이'),
('PASSWORD_EXPIRE', '90', 'SECURITY','NUMBER', '비밀번호 만료일(일)'),
('LOGIN_FAIL_LIMIT', '5', 'SECURITY','NUMBER', '로그인 실패 잠금 횟수'),
('TOKEN_EXPIRE', '7200', 'SECURITY','NUMBER', '토큰 만료(초)'),
('UPLOAD_MAX_MB', '100', 'COMMON', 'NUMBER', '업로드 최대 용량(MB)'),
('ALLOW_EXTENSIONS', 'xlsx,xls,csv,pdf,jpg,png','COMMON','STRING','허용 확장자'),
('SMTP_HOST', '', 'MAIL', 'STRING', 'SMTP 서버'),
('SMTP_PORT', '587', 'MAIL', 'NUMBER', 'SMTP 포트'),
('BATCH_RETRY', '3', 'BATCH', 'NUMBER', '배치 재시도 횟수'),
('BATCH_TIMEOUT', '7200', 'BATCH', 'NUMBER', '배치 타임아웃(초)');
@@ -0,0 +1,67 @@
-- V1: 조직 / 인사 (직급, 조직, 설계사, 이력)
CREATE TABLE grade (
grade_id SERIAL PRIMARY KEY,
grade_name VARCHAR(50) NOT NULL,
grade_level INT NOT NULL,
grade_group VARCHAR(20),
description VARCHAR(200),
is_active CHAR(1) NOT NULL DEFAULT 'Y',
sort_order INT NOT NULL DEFAULT 0
);
COMMENT ON TABLE grade IS '직급';
CREATE TABLE organization (
org_id SERIAL PRIMARY KEY,
parent_org_id BIGINT REFERENCES organization(org_id),
org_name VARCHAR(100) NOT NULL,
org_type VARCHAR(10) NOT NULL, -- HQ / BR / TM
org_level INT NOT NULL,
region VARCHAR(50),
effective_from DATE NOT NULL,
effective_to DATE,
is_active CHAR(1) NOT NULL DEFAULT 'Y',
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP,
created_by BIGINT
);
COMMENT ON TABLE organization IS '조직';
CREATE INDEX idx_org_parent ON organization(parent_org_id);
CREATE INDEX idx_org_type ON organization(org_type, is_active);
CREATE TABLE agent (
agent_id SERIAL PRIMARY KEY,
org_id BIGINT NOT NULL REFERENCES organization(org_id),
grade_id BIGINT NOT NULL REFERENCES grade(grade_id),
agent_name VARCHAR(50) NOT NULL,
resident_no VARCHAR(200), -- AES 암호화
license_no VARCHAR(50),
phone VARCHAR(20),
email VARCHAR(100),
bank_code VARCHAR(10),
account_no VARCHAR(200), -- AES 암호화
status VARCHAR(10) NOT NULL DEFAULT 'ACTIVE', -- ACTIVE / LEAVE / SUSPEND
join_date DATE,
leave_date DATE,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP
);
COMMENT ON TABLE agent IS '설계사';
CREATE INDEX idx_agent_org ON agent(org_id, status);
CREATE INDEX idx_agent_lic ON agent(license_no);
CREATE INDEX idx_agent_status ON agent(status);
CREATE TABLE agent_org_history (
history_id SERIAL PRIMARY KEY,
agent_id BIGINT NOT NULL REFERENCES agent(agent_id),
from_org_id BIGINT,
to_org_id BIGINT,
from_grade_id BIGINT,
to_grade_id BIGINT,
change_type VARCHAR(20) NOT NULL, -- TRANSFER / PROMOTE / DEMOTE / JOIN / LEAVE
change_date DATE NOT NULL,
change_reason VARCHAR(200),
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
created_by BIGINT
);
CREATE INDEX idx_aoh_agent ON agent_org_history(agent_id, change_date);
@@ -0,0 +1,55 @@
-- V2: 보험사 / 상품 / 계약
CREATE TABLE insurance_company (
company_id SERIAL PRIMARY KEY,
company_code VARCHAR(20) NOT NULL UNIQUE,
company_name VARCHAR(100) NOT NULL,
company_type VARCHAR(20), -- LIFE / NONLIFE / GA
biz_no VARCHAR(20),
contact_name VARCHAR(50),
contact_phone VARCHAR(20),
contact_email VARCHAR(100),
is_active CHAR(1) NOT NULL DEFAULT 'Y'
);
COMMENT ON TABLE insurance_company IS '보험사';
CREATE TABLE product (
product_id SERIAL PRIMARY KEY,
company_id BIGINT NOT NULL REFERENCES insurance_company(company_id),
product_code VARCHAR(50) NOT NULL,
product_name VARCHAR(200) NOT NULL,
insurance_type VARCHAR(30) NOT NULL, -- WHOLE_LIFE / TERM / SAVINGS / HEALTH ...
product_group VARCHAR(30),
pay_period_type VARCHAR(20), -- MONTHLY / QUARTERLY / ANNUAL / LUMP
is_active CHAR(1) NOT NULL DEFAULT 'Y',
launch_date DATE,
end_date DATE,
UNIQUE (company_id, product_code)
);
COMMENT ON TABLE product IS '상품';
CREATE INDEX idx_product_company ON product(company_id, is_active);
CREATE INDEX idx_product_type ON product(insurance_type);
CREATE TABLE contract (
contract_id SERIAL PRIMARY KEY,
agent_id BIGINT NOT NULL REFERENCES agent(agent_id),
product_id BIGINT NOT NULL REFERENCES product(product_id),
policy_no VARCHAR(50) NOT NULL UNIQUE,
contractor_name VARCHAR(100),
insured_name VARCHAR(100),
premium DECIMAL(15,2) NOT NULL,
pay_cycle VARCHAR(10), -- MONTHLY / QUARTERLY / ANNUAL / LUMP
pay_period INT,
coverage_period INT,
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE', -- ACTIVE / LAPSE / REVIVE / TERMINATE
contract_date DATE NOT NULL,
effective_date DATE,
lapse_date DATE,
revival_date DATE,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP
);
COMMENT ON TABLE contract IS '계약';
CREATE INDEX idx_contract_agent ON contract(agent_id, status);
CREATE INDEX idx_contract_policy ON contract(policy_no);
CREATE INDEX idx_contract_date ON contract(contract_date);
@@ -0,0 +1,72 @@
-- V3: 수수료 규정 (보험사율, 지급율, 오버라이드, 환수, 예외코드)
CREATE TABLE commission_rate (
rate_id SERIAL PRIMARY KEY,
product_id BIGINT NOT NULL REFERENCES product(product_id),
commission_year INT NOT NULL,
rate_pct DECIMAL(7,4) NOT NULL,
pay_method_cond VARCHAR(50),
min_premium DECIMAL(15,2),
effective_from DATE NOT NULL,
effective_to DATE,
version INT NOT NULL DEFAULT 1,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
created_by BIGINT
);
CREATE INDEX idx_cr_product ON commission_rate(product_id, effective_from);
CREATE TABLE payout_rule (
rule_id SERIAL PRIMARY KEY,
grade_id BIGINT NOT NULL REFERENCES grade(grade_id),
insurance_type VARCHAR(30) NOT NULL,
commission_year INT NOT NULL,
payout_pct DECIMAL(7,4) NOT NULL,
pay_method_cond VARCHAR(50),
performance_grade VARCHAR(20),
effective_from DATE NOT NULL,
effective_to DATE,
version INT NOT NULL DEFAULT 1,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
created_by BIGINT
);
CREATE INDEX idx_pr_grade ON payout_rule(grade_id, insurance_type, effective_from);
CREATE TABLE override_rule (
override_id SERIAL PRIMARY KEY,
from_grade BIGINT NOT NULL,
to_grade BIGINT NOT NULL,
override_pct DECIMAL(7,4) NOT NULL,
calc_type VARCHAR(20) NOT NULL, -- DIRECT / TREE
insurance_type_cond VARCHAR(30),
cap_amount DECIMAL(15,2),
effective_from DATE NOT NULL,
effective_to DATE
);
CREATE INDEX idx_or_grade ON override_rule(from_grade, to_grade, effective_from);
CREATE TABLE chargeback_rule (
cb_rule_id SERIAL PRIMARY KEY,
company_code VARCHAR(20),
insurance_type VARCHAR(30),
lapse_month_from INT NOT NULL,
lapse_month_to INT NOT NULL,
cb_rate DECIMAL(7,4) NOT NULL,
include_override CHAR(1) NOT NULL DEFAULT 'N',
installment_allowed CHAR(1) NOT NULL DEFAULT 'N',
max_installments INT,
effective_from DATE NOT NULL,
effective_to DATE
);
CREATE INDEX idx_cb_lookup ON chargeback_rule(company_code, insurance_type, effective_from);
CREATE TABLE exception_type_code (
exception_code VARCHAR(20) PRIMARY KEY,
exception_name VARCHAR(100) NOT NULL,
category VARCHAR(30),
direction VARCHAR(10) NOT NULL, -- PLUS / MINUS
auto_calc_yn CHAR(1) NOT NULL DEFAULT 'N',
approval_required CHAR(1) NOT NULL DEFAULT 'N',
tax_included CHAR(1) NOT NULL DEFAULT 'N',
description VARCHAR(200),
is_active CHAR(1) NOT NULL DEFAULT 'Y'
);
@@ -0,0 +1,81 @@
-- V4: 데이터 수신 (보험사 프로파일 / 필드매핑 / 코드매핑 / 원본데이터 / 파싱에러)
CREATE TABLE company_profile (
company_code VARCHAR(20) PRIMARY KEY REFERENCES insurance_company(company_code),
data_format VARCHAR(20), -- EXCEL / CSV / EDI / API
receive_method VARCHAR(20), -- MANUAL / FTP / API / SFTP
file_encoding VARCHAR(20) DEFAULT 'UTF-8',
delimiter VARCHAR(5),
header_row INT DEFAULT 1,
data_start_row INT DEFAULT 2,
sheet_name VARCHAR(50),
date_format VARCHAR(30),
amount_format VARCHAR(30),
api_url VARCHAR(300),
ftp_host VARCHAR(100),
ftp_path VARCHAR(300),
receive_schedule VARCHAR(50),
is_active CHAR(1) NOT NULL DEFAULT 'Y'
);
CREATE TABLE company_field_mapping (
mapping_id SERIAL PRIMARY KEY,
company_code VARCHAR(20) NOT NULL REFERENCES company_profile(company_code),
source_field VARCHAR(100) NOT NULL,
source_col_index INT,
target_table VARCHAR(50) NOT NULL,
target_field VARCHAR(50) NOT NULL,
data_type VARCHAR(20),
transform_rule VARCHAR(50),
default_value VARCHAR(100),
is_required CHAR(1) NOT NULL DEFAULT 'N',
sort_order INT NOT NULL DEFAULT 0,
version INT NOT NULL DEFAULT 1,
effective_from DATE NOT NULL DEFAULT CURRENT_DATE
);
CREATE INDEX idx_cfm_company ON company_field_mapping(company_code, target_table);
CREATE TABLE code_mapping (
code_id SERIAL PRIMARY KEY,
company_code VARCHAR(20) NOT NULL,
code_type VARCHAR(30) NOT NULL, -- INSURANCE_TYPE / PAY_METHOD ...
source_code VARCHAR(50) NOT NULL,
source_name VARCHAR(100),
target_code VARCHAR(50) NOT NULL,
target_name VARCHAR(100),
is_active CHAR(1) NOT NULL DEFAULT 'Y',
UNIQUE (company_code, code_type, source_code)
);
CREATE TABLE raw_commission_data (
raw_id SERIAL PRIMARY KEY,
company_code VARCHAR(20),
batch_id VARCHAR(50),
settle_month CHAR(6),
data_type VARCHAR(20),
raw_content TEXT,
parse_status VARCHAR(20) NOT NULL DEFAULT 'PENDING', -- PENDING / OK / ERROR
mapped_ledger_id BIGINT,
mapped_table VARCHAR(50),
file_name VARCHAR(300),
row_number INT,
received_at TIMESTAMP NOT NULL DEFAULT NOW(),
parsed_at TIMESTAMP
);
CREATE INDEX idx_raw_lookup ON raw_commission_data(company_code, settle_month, parse_status);
CREATE TABLE parse_error_log (
error_id SERIAL PRIMARY KEY,
raw_id BIGINT REFERENCES raw_commission_data(raw_id),
company_code VARCHAR(20),
error_type VARCHAR(30),
error_field VARCHAR(50),
error_value VARCHAR(500),
error_message VARCHAR(500),
resolve_status VARCHAR(20) NOT NULL DEFAULT 'OPEN',
resolved_by BIGINT,
resolve_note VARCHAR(500),
resolved_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_pel_status ON parse_error_log(resolve_status, created_at);
@@ -0,0 +1,88 @@
-- V5: 원장 관리 (모집수수료 / 유지수수료 / 예외금액)
CREATE TABLE recruit_ledger (
ledger_id SERIAL PRIMARY KEY,
contract_id BIGINT REFERENCES contract(contract_id),
agent_id BIGINT NOT NULL REFERENCES agent(agent_id),
policy_no VARCHAR(50),
company_code VARCHAR(20),
product_code VARCHAR(50),
insurance_type VARCHAR(30),
commission_year INT,
premium DECIMAL(15,2),
pay_method VARCHAR(20),
company_rate DECIMAL(7,4),
company_amount DECIMAL(15,2),
payout_rate DECIMAL(7,4),
agent_amount DECIMAL(15,2),
tax_amount DECIMAL(15,2),
reconcile_status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
reconcile_diff DECIMAL(15,2),
advance_yn CHAR(1) NOT NULL DEFAULT 'N',
advance_amount DECIMAL(15,2),
chargeback_yn CHAR(1) NOT NULL DEFAULT 'N',
settle_month CHAR(6) NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'CALCULATED',
version INT NOT NULL DEFAULT 1,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP
);
CREATE INDEX idx_rl_settle ON recruit_ledger(settle_month, agent_id);
CREATE INDEX idx_rl_policy ON recruit_ledger(policy_no);
CREATE TABLE maintain_ledger (
ledger_id SERIAL PRIMARY KEY,
contract_id BIGINT REFERENCES contract(contract_id),
agent_id BIGINT NOT NULL REFERENCES agent(agent_id),
policy_no VARCHAR(50),
company_code VARCHAR(20),
product_code VARCHAR(50),
insurance_type VARCHAR(30),
commission_year INT,
premium DECIMAL(15,2),
pay_method VARCHAR(20),
company_rate DECIMAL(7,4),
company_amount DECIMAL(15,2),
payout_rate DECIMAL(7,4),
agent_amount DECIMAL(15,2),
tax_amount DECIMAL(15,2),
reconcile_status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
reconcile_diff DECIMAL(15,2),
advance_yn CHAR(1) NOT NULL DEFAULT 'N',
advance_amount DECIMAL(15,2),
chargeback_yn CHAR(1) NOT NULL DEFAULT 'N',
settle_month CHAR(6) NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'CALCULATED',
version INT NOT NULL DEFAULT 1,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP
);
CREATE INDEX idx_ml_settle ON maintain_ledger(settle_month, agent_id);
CREATE INDEX idx_ml_policy ON maintain_ledger(policy_no);
CREATE TABLE exception_ledger (
ledger_id SERIAL PRIMARY KEY,
contract_id BIGINT REFERENCES contract(contract_id),
agent_id BIGINT NOT NULL REFERENCES agent(agent_id),
exception_code VARCHAR(20) NOT NULL REFERENCES exception_type_code(exception_code),
policy_no VARCHAR(50),
company_code VARCHAR(20),
insurance_type VARCHAR(30),
commission_year INT,
amount DECIMAL(15,2) NOT NULL,
tax_amount DECIMAL(15,2),
settle_month CHAR(6) NOT NULL,
description VARCHAR(500),
approve_status VARCHAR(20) NOT NULL DEFAULT 'PENDING', -- PENDING / APPROVED / REJECTED
approver_id BIGINT,
approve_date TIMESTAMP,
recurring_yn CHAR(1) NOT NULL DEFAULT 'N',
recurring_months INT,
recurring_left INT,
status VARCHAR(20) NOT NULL DEFAULT 'NEW',
version INT NOT NULL DEFAULT 1,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP
);
CREATE INDEX idx_el_settle ON exception_ledger(settle_month, agent_id);
CREATE INDEX idx_el_status ON exception_ledger(approve_status);
@@ -0,0 +1,72 @@
-- V6: 정산 마스터 / 오버라이드 / 환수 / 지급
CREATE TABLE settle_master (
settle_id SERIAL PRIMARY KEY,
agent_id BIGINT NOT NULL REFERENCES agent(agent_id),
settle_month CHAR(6) NOT NULL,
recruit_total DECIMAL(15,2) NOT NULL DEFAULT 0,
maintain_total DECIMAL(15,2) NOT NULL DEFAULT 0,
exception_plus DECIMAL(15,2) NOT NULL DEFAULT 0,
exception_minus DECIMAL(15,2) NOT NULL DEFAULT 0,
override_total DECIMAL(15,2) NOT NULL DEFAULT 0,
chargeback_total DECIMAL(15,2) NOT NULL DEFAULT 0,
gross_amount DECIMAL(15,2) NOT NULL DEFAULT 0,
tax_amount DECIMAL(15,2) NOT NULL DEFAULT 0,
net_amount DECIMAL(15,2) NOT NULL DEFAULT 0,
status VARCHAR(20) NOT NULL DEFAULT 'CALCULATED', -- CALCULATED / CONFIRMED / HOLD / PAID
calc_date TIMESTAMP,
confirmed_by BIGINT,
confirmed_at TIMESTAMP,
hold_reason VARCHAR(500),
UNIQUE (agent_id, settle_month)
);
CREATE INDEX idx_sm_month ON settle_master(settle_month, status);
CREATE TABLE override_settle (
os_id SERIAL PRIMARY KEY,
settle_id BIGINT NOT NULL REFERENCES settle_master(settle_id),
upper_agent_id BIGINT NOT NULL REFERENCES agent(agent_id),
lower_agent_id BIGINT NOT NULL REFERENCES agent(agent_id),
settle_month CHAR(6) NOT NULL,
base_amount DECIMAL(15,2) NOT NULL,
override_pct DECIMAL(7,4) NOT NULL,
override_amount DECIMAL(15,2) NOT NULL,
calc_date TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_os_settle ON override_settle(settle_id);
CREATE INDEX idx_os_upper ON override_settle(upper_agent_id, settle_month);
CREATE TABLE chargeback (
cb_id SERIAL PRIMARY KEY,
contract_id BIGINT REFERENCES contract(contract_id),
agent_id BIGINT NOT NULL REFERENCES agent(agent_id),
policy_no VARCHAR(50),
lapse_month INT,
cb_rate DECIMAL(7,4),
cb_amount DECIMAL(15,2) NOT NULL,
paid_amount DECIMAL(15,2) NOT NULL DEFAULT 0,
remain_amount DECIMAL(15,2) NOT NULL,
settle_month CHAR(6) NOT NULL,
installment_no INT,
max_installments INT,
status VARCHAR(20) NOT NULL DEFAULT 'NEW',
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_cb_agent ON chargeback(agent_id, settle_month);
CREATE TABLE payment (
payment_id SERIAL PRIMARY KEY,
settle_id BIGINT NOT NULL REFERENCES settle_master(settle_id),
agent_id BIGINT NOT NULL REFERENCES agent(agent_id),
pay_amount DECIMAL(15,2) NOT NULL,
bank_code VARCHAR(10),
account_no VARCHAR(200),
pay_date DATE,
pay_status VARCHAR(20) NOT NULL DEFAULT 'PENDING', -- PENDING / SENT / DONE / FAIL
transfer_file_id BIGINT,
fail_reason VARCHAR(500),
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP
);
CREATE INDEX idx_pay_status ON payment(pay_status, created_at);
CREATE INDEX idx_pay_agent ON payment(agent_id, pay_date);
@@ -0,0 +1,67 @@
-- V7: 배치 / 대사 / 감사 / 사용자
CREATE TABLE batch_job_log (
job_id SERIAL PRIMARY KEY,
job_name VARCHAR(100) NOT NULL,
job_params TEXT,
settle_month CHAR(6),
status VARCHAR(20) NOT NULL DEFAULT 'STARTED',
current_step VARCHAR(50),
progress_pct INT DEFAULT 0,
total_count INT,
processed_count INT,
error_count INT DEFAULT 0,
error_message TEXT,
started_at TIMESTAMP NOT NULL DEFAULT NOW(),
finished_at TIMESTAMP,
duration_sec INT,
triggered_by BIGINT
);
CREATE INDEX idx_bjl_lookup ON batch_job_log(job_name, started_at);
CREATE TABLE reconciliation (
recon_id SERIAL PRIMARY KEY,
company_code VARCHAR(20),
settle_month CHAR(6) NOT NULL,
company_total DECIMAL(15,2),
system_total DECIMAL(15,2),
diff_amount DECIMAL(15,2),
diff_count INT,
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
resolve_note VARCHAR(500),
resolved_by BIGINT,
resolved_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_recon ON reconciliation(company_code, settle_month);
CREATE TABLE audit_log (
audit_id SERIAL PRIMARY KEY,
user_id BIGINT,
action_type VARCHAR(30) NOT NULL,
target_type VARCHAR(50),
target_id VARCHAR(100),
description VARCHAR(500),
ip_address VARCHAR(50),
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_audit_user ON audit_log(user_id, created_at);
CREATE TABLE users (
user_id SERIAL PRIMARY KEY,
login_id VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(200) NOT NULL,
user_name VARCHAR(50) NOT NULL,
email VARCHAR(100),
phone VARCHAR(20),
agent_id BIGINT REFERENCES agent(agent_id),
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE', -- ACTIVE / LOCKED / RETIRED
fail_count INT NOT NULL DEFAULT 0,
last_login_at TIMESTAMP,
pwd_changed_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
created_by BIGINT,
updated_at TIMESTAMP,
updated_by BIGINT
);
CREATE INDEX idx_users_status ON users(status);
@@ -0,0 +1,21 @@
-- V8: 초기 데이터 (직급, 예외코드)
INSERT INTO grade (grade_name, grade_level, grade_group, description, sort_order) VALUES
('FC', 1, 'NORMAL', '일반 설계사', 10),
('SFC', 2, 'NORMAL', '시니어 설계사', 20),
('MGR', 3, 'MANAGER','매니저', 30),
('SMGR', 4, 'MANAGER','시니어 매니저', 40),
('DM', 5, 'EXEC', '본부장', 50),
('GM', 6, 'EXEC', '지사장', 60);
INSERT INTO exception_type_code (exception_code, exception_name, category, direction, auto_calc_yn, approval_required, tax_included, description) VALUES
('ADV', '선지급', 'ADVANCE', 'PLUS', 'N','Y','N','선지급 수수료'),
('PERF', '실적격려금', 'BONUS', 'PLUS', 'N','Y','Y','실적 격려금 지급'),
('AWARD', '시상금', 'BONUS', 'PLUS', 'N','Y','Y','시상 인센티브'),
('SUPPORT', '운영지원금', 'SUPPORT', 'PLUS', 'N','Y','Y','운영 지원 보조'),
('REFUND', '환급금', 'REFUND', 'PLUS', 'Y','N','N','자동 환급'),
('PEN', '제재금', 'PENALTY', 'MINUS', 'N','Y','N','징계/벌과금'),
('PRECOL', '선차감', 'OFFSET', 'MINUS', 'N','Y','N','전월 미공제분'),
('LOAN', '대여금공제', 'LOAN', 'MINUS', 'Y','N','N','대여금 자동 공제'),
('TAX_ADJ', '세금조정', 'TAX', 'MINUS', 'Y','N','N','세금 조정'),
('ETC', '기타', 'ETC', 'PLUS', 'N','Y','Y','기타 항목');
@@ -0,0 +1,35 @@
-- V9: 공통 코드
CREATE TABLE common_code_group (
group_code VARCHAR(20) PRIMARY KEY,
group_name VARCHAR(100) NOT NULL,
description VARCHAR(300),
is_system CHAR(1) NOT NULL DEFAULT 'N',
is_active CHAR(1) NOT NULL DEFAULT 'Y',
sort_order INT NOT NULL DEFAULT 0,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
created_by BIGINT,
updated_at TIMESTAMP,
updated_by BIGINT
);
CREATE TABLE common_code (
code_id SERIAL PRIMARY KEY,
group_code VARCHAR(20) NOT NULL REFERENCES common_code_group(group_code),
code VARCHAR(30) NOT NULL,
code_name VARCHAR(100) NOT NULL,
code_name_en VARCHAR(100),
code_desc VARCHAR(300),
attr1 VARCHAR(100),
attr2 VARCHAR(100),
attr3 VARCHAR(100),
ref_code VARCHAR(50),
sort_order INT NOT NULL DEFAULT 0,
is_active CHAR(1) NOT NULL DEFAULT 'Y',
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
created_by BIGINT,
updated_at TIMESTAMP,
updated_by BIGINT,
UNIQUE (group_code, code)
);
CREATE INDEX idx_cc_group_active ON common_code(group_code, is_active, sort_order);