feat: incar 갭 반영 수수료/운영 14개 도메인 풀스택 + 배치통합 + 신입교육자료
incar CMS(116메뉴) 벤치마킹 갭분석으로 ga-pro에 없던 14개 도메인을 풀스택 추가. P7 수수료 계산 7종 (V88~V96): - 수입수수료+수지차, 소개·이관수수료, 정착지원금, 인정실적+환산율, 시상, 생보운영지원수수료, 지점장수당 - 각 rule/ledger + 공식(보험료×요율, 수입−지급 등) Service 내장 P8 운영/정산 7종 (V97~V105): - 단계마감, 본사정산, 등급평가, 공동계약, 보증보험, 적립금, 수수료시뮬레이터 - close/reopen/apply/simulate/upsert 등 액션 + 손익·잔액·등급 산정 로직 배치 통합 (V106): - settle_master.other_commission_total 컬럼 추가(DEFAULT 0, 백필) - 설계사 지급성 9종 원장 aggregateByAgent → AggregateStep gross 합산 - 빈 원장 0 → 기존 정산결과·무결성 불변(비파괴적) 테스트: P7/P8 Service 공식 단위테스트 21건(ga-api:test 57건 전체 통과) 프론트: 화면 14개 + React.lazy 코드 스플리팅(단일 4MB → 130+ 청크) 문서: DOMAIN_GAP_P7/P8.md, 신입교육_보험과수수료_완전기초.md, DOMAIN_KNOWLEDGE/HANDOFF 갱신 검증: 전체 ./gradlew build(test 포함) SUCCESSFUL, Flyway V88~V106 success, GET+액션POST smoke 5xx 0건, 9개 집계쿼리 SQL 유효성 확인, 공식 런타임 실측. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
-- V100: 공동계약 (joint_contract)
|
||||
-- 한 계약을 여러 설계사가 공동 모집 → 지분율(share_rate)로 수수료 배분.
|
||||
-- 공식: 설계사몫 = 계약수수료 × share_rate
|
||||
-- 검증: 계약별 share_rate 합=1 — Service 가드
|
||||
|
||||
CREATE TABLE joint_contract (
|
||||
joint_id BIGSERIAL PRIMARY KEY,
|
||||
contract_id INT NOT NULL REFERENCES contract(contract_id),
|
||||
agent_id INT NOT NULL REFERENCES agent(agent_id),
|
||||
role VARCHAR(10) NOT NULL,
|
||||
share_rate NUMERIC(7,4) NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
created_by BIGINT,
|
||||
UNIQUE (contract_id, agent_id),
|
||||
CHECK (role IN ('LEAD','SUB')),
|
||||
CHECK (share_rate >= 0 AND share_rate <= 1)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE joint_contract IS '공동계약 — 복수 설계사의 계약별 지분율 관리';
|
||||
COMMENT ON COLUMN joint_contract.contract_id IS '대상 계약 FK';
|
||||
COMMENT ON COLUMN joint_contract.agent_id IS '참여 설계사 FK';
|
||||
COMMENT ON COLUMN joint_contract.role IS '역할 (LEAD=주설계사/SUB=공동설계사)';
|
||||
COMMENT ON COLUMN joint_contract.share_rate IS '지분율 (0~1, 계약별 합=1 Service 검증)';
|
||||
|
||||
CREATE INDEX idx_jcon_contract ON joint_contract(contract_id);
|
||||
CREATE INDEX idx_jcon_agent ON joint_contract(agent_id);
|
||||
@@ -0,0 +1,28 @@
|
||||
-- V101: 보증보험 (agent_guarantee_insurance)
|
||||
-- 설계사가 가입하는 신원보증보험 가입현황 추적(관리 목적, 공식 없음).
|
||||
|
||||
CREATE TABLE agent_guarantee_insurance (
|
||||
guarantee_id BIGSERIAL PRIMARY KEY,
|
||||
agent_id INT NOT NULL REFERENCES agent(agent_id),
|
||||
policy_no VARCHAR(50) NOT NULL,
|
||||
carrier_id INT REFERENCES insurance_company(company_id),
|
||||
guarantee_amount NUMERIC(15,2) NOT NULL,
|
||||
start_date DATE NOT NULL,
|
||||
end_date DATE NOT NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE',
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP,
|
||||
CHECK (status IN ('ACTIVE','EXPIRED','CANCELLED'))
|
||||
);
|
||||
|
||||
COMMENT ON TABLE agent_guarantee_insurance IS '보증보험 — 설계사 신원보증보험 가입현황';
|
||||
COMMENT ON COLUMN agent_guarantee_insurance.agent_id IS '설계사 FK';
|
||||
COMMENT ON COLUMN agent_guarantee_insurance.policy_no IS '증권번호';
|
||||
COMMENT ON COLUMN agent_guarantee_insurance.carrier_id IS '보증보험사 FK(insurance_company)';
|
||||
COMMENT ON COLUMN agent_guarantee_insurance.guarantee_amount IS '보증금액';
|
||||
COMMENT ON COLUMN agent_guarantee_insurance.start_date IS '보증 시작일';
|
||||
COMMENT ON COLUMN agent_guarantee_insurance.end_date IS '보증 종료일';
|
||||
COMMENT ON COLUMN agent_guarantee_insurance.status IS '상태 (ACTIVE=유효/EXPIRED=만료/CANCELLED=해지)';
|
||||
|
||||
CREATE INDEX idx_agi_agent_status ON agent_guarantee_insurance(agent_id, status);
|
||||
CREATE INDEX idx_agi_end_date ON agent_guarantee_insurance(end_date);
|
||||
@@ -0,0 +1,24 @@
|
||||
-- V102: 적립금 (agent_reserve_fund)
|
||||
-- 환수 대비 수수료 일부 적립 + 잔액 관리.
|
||||
-- 공식: balance = (직전월 balance) + reserve_in - reserve_out
|
||||
-- Service가 직전월 balance를 조회하여 누적 계산.
|
||||
|
||||
CREATE TABLE agent_reserve_fund (
|
||||
reserve_id BIGSERIAL PRIMARY KEY,
|
||||
agent_id INT NOT NULL REFERENCES agent(agent_id),
|
||||
settle_month CHAR(6) NOT NULL,
|
||||
reserve_in NUMERIC(15,2) NOT NULL DEFAULT 0,
|
||||
reserve_out NUMERIC(15,2) NOT NULL DEFAULT 0,
|
||||
balance NUMERIC(15,2) NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
UNIQUE (agent_id, settle_month)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE agent_reserve_fund IS '적립금 — 환수 대비 설계사별 월별 적립금 잔액';
|
||||
COMMENT ON COLUMN agent_reserve_fund.agent_id IS '설계사 FK';
|
||||
COMMENT ON COLUMN agent_reserve_fund.settle_month IS '정산 귀속월 (YYYYMM)';
|
||||
COMMENT ON COLUMN agent_reserve_fund.reserve_in IS '당월 적립액';
|
||||
COMMENT ON COLUMN agent_reserve_fund.reserve_out IS '당월 인출/사용액';
|
||||
COMMENT ON COLUMN agent_reserve_fund.balance IS '잔액 = 전월잔액 + reserve_in - reserve_out';
|
||||
|
||||
CREATE INDEX idx_arf_agent_month ON agent_reserve_fund(agent_id, settle_month);
|
||||
@@ -0,0 +1,39 @@
|
||||
-- V103: 수수료 시뮬레이터 (commission_simulation)
|
||||
-- 보험료/요율/지급률 입력 → 수수료·세금·실지급·예상환수 산출. 시나리오 저장.
|
||||
-- 공식:
|
||||
-- company_payment = premium_amount × company_rate
|
||||
-- agent_commission = company_payment × payout_rate
|
||||
-- withholding_tax = agent_commission × 0.033 (3.3%, HALF_UP)
|
||||
-- net_amount = agent_commission - withholding_tax
|
||||
|
||||
CREATE TABLE commission_simulation (
|
||||
sim_id BIGSERIAL PRIMARY KEY,
|
||||
sim_name VARCHAR(100) NOT NULL,
|
||||
premium_amount NUMERIC(15,2) NOT NULL,
|
||||
company_rate NUMERIC(7,4) NOT NULL,
|
||||
payout_rate NUMERIC(7,4) NOT NULL,
|
||||
commission_year INT NOT NULL,
|
||||
company_payment NUMERIC(15,2) NOT NULL,
|
||||
agent_commission NUMERIC(15,2) NOT NULL,
|
||||
withholding_tax NUMERIC(15,2) NOT NULL,
|
||||
net_amount NUMERIC(15,2) NOT NULL,
|
||||
expected_chargeback NUMERIC(15,2),
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
created_by BIGINT
|
||||
);
|
||||
|
||||
COMMENT ON TABLE commission_simulation IS '수수료 시뮬레이터 — 시나리오별 수수료 산출 결과 저장';
|
||||
COMMENT ON COLUMN commission_simulation.sim_name IS '시나리오명';
|
||||
COMMENT ON COLUMN commission_simulation.premium_amount IS '입력 보험료';
|
||||
COMMENT ON COLUMN commission_simulation.company_rate IS '보험사 요율 (소수)';
|
||||
COMMENT ON COLUMN commission_simulation.payout_rate IS '지급률 (소수)';
|
||||
COMMENT ON COLUMN commission_simulation.commission_year IS '회차';
|
||||
COMMENT ON COLUMN commission_simulation.company_payment IS '보험사 지급액 = 보험료 × company_rate';
|
||||
COMMENT ON COLUMN commission_simulation.agent_commission IS '설계사 수수료 = 보험사지급액 × payout_rate';
|
||||
COMMENT ON COLUMN commission_simulation.withholding_tax IS '원천세 = 설계사수수료 × 3.3%';
|
||||
COMMENT ON COLUMN commission_simulation.net_amount IS '실지급 = 설계사수수료 - 원천세';
|
||||
COMMENT ON COLUMN commission_simulation.expected_chargeback IS '예상 환수액 (13개월 50% 등 시나리오)';
|
||||
COMMENT ON COLUMN commission_simulation.created_by IS '시뮬레이션 요청자 FK(users)';
|
||||
|
||||
CREATE INDEX idx_simu_created_by ON commission_simulation(created_by, created_at);
|
||||
CREATE INDEX idx_simu_created_at ON commission_simulation(created_at DESC);
|
||||
@@ -0,0 +1,153 @@
|
||||
-- V104: incar 갭 운영 도메인 7개 PAGE 메뉴 등록 (V95 패턴 동일)
|
||||
-- GRP_SETTLE 하위: STEP_CLOSE, HQ_SETTLE
|
||||
-- GRP_ORG 하위: GRADE_EVAL, GUARANTEE_INS
|
||||
-- GRP_PRD 하위: JOINT_CONTRACT
|
||||
-- GRP_COMMISSION 하위: RESERVE_FUND, COMM_SIMULATOR
|
||||
--
|
||||
-- 권한:
|
||||
-- STEP_CLOSE → READ/UPDATE/APPROVE
|
||||
-- 나머지 6개 → READ/CREATE/UPDATE/DELETE/EXPORT
|
||||
-- 역할:
|
||||
-- SUPER_ADMIN/ADMIN → 전체 권한
|
||||
-- MANAGER → READ/CREATE/UPDATE/EXPORT (+ APPROVE for STEP_CLOSE, DELETE 제외)
|
||||
-- AGENT → 본인 관련 도메인 READ (RESERVE_FUND, GUARANTEE_INS, GRADE_EVAL)
|
||||
|
||||
-- ============================================================
|
||||
-- 1. GRP_SETTLE 하위: STEP_CLOSE, HQ_SETTLE
|
||||
-- ============================================================
|
||||
|
||||
INSERT INTO menu (parent_menu_id, menu_code, menu_name, menu_type, menu_path, component_path, menu_level, sort_order)
|
||||
SELECT p.menu_id, x.code, x.name, 'PAGE', x.path, x.cmpt, 2, x.sort
|
||||
FROM menu p
|
||||
JOIN (VALUES
|
||||
('STEP_CLOSE', '단계마감', '/settle/step-close', 'settle/StepClose', 90),
|
||||
('HQ_SETTLE', '본사정산', '/settle/hq-settle', 'settle/HqSettle', 100)
|
||||
) AS x(code, name, path, cmpt, sort)
|
||||
ON p.menu_code = 'GRP_SETTLE'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM menu WHERE menu_code = x.code);
|
||||
|
||||
-- ============================================================
|
||||
-- 2. GRP_ORG 하위: GRADE_EVAL, GUARANTEE_INS
|
||||
-- ============================================================
|
||||
|
||||
INSERT INTO menu (parent_menu_id, menu_code, menu_name, menu_type, menu_path, component_path, menu_level, sort_order)
|
||||
SELECT p.menu_id, x.code, x.name, 'PAGE', x.path, x.cmpt, 2, x.sort
|
||||
FROM menu p
|
||||
JOIN (VALUES
|
||||
('GRADE_EVAL', '등급평가', '/org/grade-eval', 'org/GradeEvaluation', 60),
|
||||
('GUARANTEE_INS', '보증보험', '/org/guarantee', 'org/GuaranteeInsurance', 70)
|
||||
) AS x(code, name, path, cmpt, sort)
|
||||
ON p.menu_code = 'GRP_ORG'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM menu WHERE menu_code = x.code);
|
||||
|
||||
-- ============================================================
|
||||
-- 3. GRP_PRD 하위: JOINT_CONTRACT
|
||||
-- ============================================================
|
||||
|
||||
INSERT INTO menu (parent_menu_id, menu_code, menu_name, menu_type, menu_path, component_path, menu_level, sort_order)
|
||||
SELECT p.menu_id, x.code, x.name, 'PAGE', x.path, x.cmpt, 2, x.sort
|
||||
FROM menu p
|
||||
JOIN (VALUES
|
||||
('JOINT_CONTRACT', '공동계약', '/contracts/joint', 'contracts/JointContract', 60)
|
||||
) AS x(code, name, path, cmpt, sort)
|
||||
ON p.menu_code = 'GRP_PRD'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM menu WHERE menu_code = x.code);
|
||||
|
||||
-- ============================================================
|
||||
-- 4. GRP_COMMISSION 하위: RESERVE_FUND, COMM_SIMULATOR
|
||||
-- ============================================================
|
||||
|
||||
INSERT INTO menu (parent_menu_id, menu_code, menu_name, menu_type, menu_path, component_path, menu_level, sort_order)
|
||||
SELECT p.menu_id, x.code, x.name, 'PAGE', x.path, x.cmpt, 2, x.sort
|
||||
FROM menu p
|
||||
JOIN (VALUES
|
||||
('RESERVE_FUND', '적립금', '/commission/reserve', 'commission/ReserveFund', 150),
|
||||
('COMM_SIMULATOR', '수수료 시뮬레이터', '/commission/simulator', 'commission/CommissionSimulator', 160)
|
||||
) AS x(code, name, path, cmpt, sort)
|
||||
ON p.menu_code = 'GRP_COMMISSION'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM menu WHERE menu_code = x.code);
|
||||
|
||||
-- ============================================================
|
||||
-- 5. STEP_CLOSE 권한 등록 (READ/UPDATE/APPROVE)
|
||||
-- ============================================================
|
||||
|
||||
INSERT INTO menu_permission (menu_id, perm_code, perm_name, sort_order)
|
||||
SELECT m.menu_id, p.code, p.name, p.sort
|
||||
FROM menu m
|
||||
CROSS JOIN (VALUES
|
||||
('READ', '조회', 10),
|
||||
('UPDATE', '수정', 30),
|
||||
('APPROVE', '승인', 50)
|
||||
) AS p(code, name, sort)
|
||||
WHERE m.menu_code = 'STEP_CLOSE'
|
||||
ON CONFLICT (menu_id, perm_code) DO NOTHING;
|
||||
|
||||
-- ============================================================
|
||||
-- 6. 나머지 6개 메뉴 권한 등록 (READ/CREATE/UPDATE/DELETE/EXPORT)
|
||||
-- ============================================================
|
||||
|
||||
INSERT INTO menu_permission (menu_id, perm_code, perm_name, sort_order)
|
||||
SELECT m.menu_id, p.code, p.name, p.sort
|
||||
FROM menu m
|
||||
CROSS JOIN (VALUES
|
||||
('READ', '조회', 10),
|
||||
('CREATE', '등록', 20),
|
||||
('UPDATE', '수정', 30),
|
||||
('DELETE', '삭제', 40),
|
||||
('EXPORT', '엑셀', 60)
|
||||
) AS p(code, name, sort)
|
||||
WHERE m.menu_code IN ('HQ_SETTLE','GRADE_EVAL','JOINT_CONTRACT','GUARANTEE_INS','RESERVE_FUND','COMM_SIMULATOR')
|
||||
ON CONFLICT (menu_id, perm_code) DO NOTHING;
|
||||
|
||||
-- ============================================================
|
||||
-- 7. SUPER_ADMIN / ADMIN — 7개 메뉴 전체 권한
|
||||
-- ============================================================
|
||||
|
||||
INSERT INTO role_menu_permission (role_id, menu_id, perm_code, is_granted)
|
||||
SELECT r.role_id, mp.menu_id, mp.perm_code, 'Y'
|
||||
FROM role r
|
||||
CROSS JOIN menu_permission mp
|
||||
JOIN menu m ON m.menu_id = mp.menu_id
|
||||
WHERE r.role_code IN ('SUPER_ADMIN','ADMIN')
|
||||
AND m.menu_code IN ('STEP_CLOSE','HQ_SETTLE','GRADE_EVAL','JOINT_CONTRACT','GUARANTEE_INS','RESERVE_FUND','COMM_SIMULATOR')
|
||||
ON CONFLICT (role_id, menu_id, perm_code) DO NOTHING;
|
||||
|
||||
-- ============================================================
|
||||
-- 8. MANAGER — READ/CREATE/UPDATE/EXPORT + APPROVE(STEP_CLOSE)
|
||||
-- ============================================================
|
||||
|
||||
-- STEP_CLOSE: READ/UPDATE/APPROVE
|
||||
INSERT INTO role_menu_permission (role_id, menu_id, perm_code, is_granted)
|
||||
SELECT r.role_id, mp.menu_id, mp.perm_code, 'Y'
|
||||
FROM role r
|
||||
CROSS JOIN menu_permission mp
|
||||
JOIN menu m ON m.menu_id = mp.menu_id
|
||||
WHERE r.role_code = 'MANAGER'
|
||||
AND mp.perm_code IN ('READ','UPDATE','APPROVE')
|
||||
AND m.menu_code = 'STEP_CLOSE'
|
||||
ON CONFLICT (role_id, menu_id, perm_code) DO NOTHING;
|
||||
|
||||
-- 나머지 6개: READ/CREATE/UPDATE/EXPORT (DELETE 제외)
|
||||
INSERT INTO role_menu_permission (role_id, menu_id, perm_code, is_granted)
|
||||
SELECT r.role_id, mp.menu_id, mp.perm_code, 'Y'
|
||||
FROM role r
|
||||
CROSS JOIN menu_permission mp
|
||||
JOIN menu m ON m.menu_id = mp.menu_id
|
||||
WHERE r.role_code = 'MANAGER'
|
||||
AND mp.perm_code IN ('READ','CREATE','UPDATE','EXPORT')
|
||||
AND m.menu_code IN ('HQ_SETTLE','GRADE_EVAL','JOINT_CONTRACT','GUARANTEE_INS','RESERVE_FUND','COMM_SIMULATOR')
|
||||
ON CONFLICT (role_id, menu_id, perm_code) DO NOTHING;
|
||||
|
||||
-- ============================================================
|
||||
-- 9. AGENT — 본인 관련 도메인 READ (RESERVE_FUND, GUARANTEE_INS, GRADE_EVAL)
|
||||
-- ============================================================
|
||||
|
||||
INSERT INTO role_menu_permission (role_id, menu_id, perm_code, is_granted)
|
||||
SELECT r.role_id, mp.menu_id, mp.perm_code, 'Y'
|
||||
FROM role r
|
||||
CROSS JOIN menu_permission mp
|
||||
JOIN menu m ON m.menu_id = mp.menu_id
|
||||
WHERE r.role_code = 'AGENT'
|
||||
AND mp.perm_code = 'READ'
|
||||
AND m.menu_code IN ('RESERVE_FUND','GUARANTEE_INS','GRADE_EVAL')
|
||||
ON CONFLICT (role_id, menu_id, perm_code) DO NOTHING;
|
||||
@@ -0,0 +1,37 @@
|
||||
-- V105: incar 갭 운영 도메인 공통코드 6종 (V96 패턴 동일)
|
||||
-- STEP_CODE / STEP_STATUS / HQ_ITEM_TYPE / JOINT_ROLE / GUARANTEE_STATUS / GRADE_EVAL_STATUS
|
||||
|
||||
-- ===== 그룹 =====
|
||||
INSERT INTO common_code_group (group_code, group_name, description, is_system, sort_order) VALUES
|
||||
('STEP_CODE', '단계코드', 'RECEIVE=수신마감/CALC=계산마감/VERIFY=검증마감/PAY=지급마감', 'Y', 490),
|
||||
('STEP_STATUS', '단계상태', 'OPEN=열림/CLOSED=마감', 'Y', 500),
|
||||
('HQ_ITEM_TYPE', '본사정산유형', 'INCOME=수입/EXPENSE=비용', 'Y', 510),
|
||||
('JOINT_ROLE', '공동계약역할', 'LEAD=주설계사/SUB=공동설계사', 'Y', 520),
|
||||
('GUARANTEE_STATUS', '보증보험상태', 'ACTIVE=유효/EXPIRED=만료/CANCELLED=해지', 'Y', 530),
|
||||
('GRADE_EVAL_STATUS', '등급평가상태', 'EVALUATED=평가완료/APPLIED=반영완료', 'Y', 540)
|
||||
ON CONFLICT (group_code) DO NOTHING;
|
||||
|
||||
-- ===== 상세 =====
|
||||
INSERT INTO common_code (group_code, code, code_name, sort_order) VALUES
|
||||
-- STEP_CODE
|
||||
('STEP_CODE', 'RECEIVE', '수신마감', 10),
|
||||
('STEP_CODE', 'CALC', '계산마감', 20),
|
||||
('STEP_CODE', 'VERIFY', '검증마감', 30),
|
||||
('STEP_CODE', 'PAY', '지급마감', 40),
|
||||
-- STEP_STATUS
|
||||
('STEP_STATUS', 'OPEN', '열림', 10),
|
||||
('STEP_STATUS', 'CLOSED', '마감', 20),
|
||||
-- HQ_ITEM_TYPE
|
||||
('HQ_ITEM_TYPE', 'INCOME', '수입', 10),
|
||||
('HQ_ITEM_TYPE', 'EXPENSE', '비용', 20),
|
||||
-- JOINT_ROLE
|
||||
('JOINT_ROLE', 'LEAD', '주설계사', 10),
|
||||
('JOINT_ROLE', 'SUB', '공동설계사', 20),
|
||||
-- GUARANTEE_STATUS
|
||||
('GUARANTEE_STATUS', 'ACTIVE', '유효', 10),
|
||||
('GUARANTEE_STATUS', 'EXPIRED', '만료', 20),
|
||||
('GUARANTEE_STATUS', 'CANCELLED', '해지', 30),
|
||||
-- GRADE_EVAL_STATUS
|
||||
('GRADE_EVAL_STATUS', 'EVALUATED', '평가완료', 10),
|
||||
('GRADE_EVAL_STATUS', 'APPLIED', '반영완료', 20)
|
||||
ON CONFLICT (group_code, code) DO NOTHING;
|
||||
@@ -0,0 +1,9 @@
|
||||
-- V106: settle_master에 기타수수료 합계 컬럼 추가
|
||||
-- 설계사 지급성 9종(수금·갱신·부활·유지보너스·소개·정착지원·시상·생보운영·지점장수당) 집계용
|
||||
-- 기존 행은 DEFAULT 0으로 백필되므로 기존 정산 결과 불변.
|
||||
|
||||
ALTER TABLE settle_master
|
||||
ADD COLUMN other_commission_total NUMERIC(15,2) NOT NULL DEFAULT 0;
|
||||
|
||||
COMMENT ON COLUMN settle_master.other_commission_total
|
||||
IS '기타수수료 합계(수금+갱신+부활+유지보너스+소개+정착지원+시상+생보운영+지점장수당, status!=CANCELLED)';
|
||||
@@ -0,0 +1,81 @@
|
||||
-- V88: 수입수수료 + 수지차 (income_commission_ledger + margin_summary)
|
||||
-- 보험사가 GA에 지급한 수입 측 원장. 수지차 = 수입 합계 - 지급 합계(settle_master 기준).
|
||||
--
|
||||
-- settle_master 지급 합계 집계 컬럼 (확인 완료):
|
||||
-- settle_master.agent_id : 설계사 FK (BIGINT)
|
||||
-- settle_master.settle_month : 정산월 CHAR(6)
|
||||
-- settle_master.net_amount : 설계사 실지급액 (세후) NUMERIC
|
||||
-- settle_master.gross_amount : 설계사 총지급액 (세전) NUMERIC
|
||||
-- payout_total 산출 시 net_amount 합산 권장 (tax_amount 차감 후 기준)
|
||||
|
||||
-- ============================================================
|
||||
-- 1. income_commission_ledger — 수입수수료 원장
|
||||
-- 보험사 → GA 수입 수수료. 계약 단위로 발생.
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE income_commission_ledger (
|
||||
income_id BIGSERIAL PRIMARY KEY,
|
||||
contract_id BIGINT NOT NULL REFERENCES contract(contract_id),
|
||||
carrier_id BIGINT NOT NULL REFERENCES insurance_company(company_id),
|
||||
settle_month CHAR(6) NOT NULL,
|
||||
premium_amount NUMERIC(15,2) NOT NULL,
|
||||
company_rate NUMERIC(7,4) NOT NULL,
|
||||
income_amount NUMERIC(15,2) NOT NULL,
|
||||
commission_type VARCHAR(20) NOT NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'CALCULATED',
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP,
|
||||
CHECK (commission_type IN ('RECRUIT','MAINTAIN','RENEWAL','REINSTATE','COLLECTION')),
|
||||
CHECK (status IN ('CALCULATED','CONFIRMED','CANCELLED')),
|
||||
CHECK (company_rate >= 0 AND company_rate <= 1),
|
||||
CHECK (premium_amount >= 0),
|
||||
CHECK (income_amount >= 0)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE income_commission_ledger IS '수입수수료 원장 — 보험사가 GA에 지급한 수입 수수료 (계약 단위)';
|
||||
COMMENT ON COLUMN income_commission_ledger.income_id IS '수입수수료 원장 PK';
|
||||
COMMENT ON COLUMN income_commission_ledger.contract_id IS '대상 계약 FK';
|
||||
COMMENT ON COLUMN income_commission_ledger.carrier_id IS '보험사 FK (insurance_company.company_id)';
|
||||
COMMENT ON COLUMN income_commission_ledger.settle_month IS '정산 귀속월 (YYYYMM)';
|
||||
COMMENT ON COLUMN income_commission_ledger.premium_amount IS '보험료';
|
||||
COMMENT ON COLUMN income_commission_ledger.company_rate IS '보험사 수수료율 (소수, 예: 0.12 = 12%)';
|
||||
COMMENT ON COLUMN income_commission_ledger.income_amount IS '수입수수료 = premium_amount × company_rate';
|
||||
COMMENT ON COLUMN income_commission_ledger.commission_type IS '수수료 유형 (RECRUIT/MAINTAIN/RENEWAL/REINSTATE/COLLECTION)';
|
||||
COMMENT ON COLUMN income_commission_ledger.status IS '상태 (CALCULATED/CONFIRMED/CANCELLED)';
|
||||
|
||||
CREATE INDEX idx_icl_carrier_month ON income_commission_ledger(carrier_id, settle_month);
|
||||
CREATE INDEX idx_icl_contract ON income_commission_ledger(contract_id);
|
||||
CREATE INDEX idx_icl_status_month ON income_commission_ledger(status, settle_month);
|
||||
|
||||
-- ============================================================
|
||||
-- 2. margin_summary — 수지차 집계
|
||||
-- 수지차 recalc 배치 액션으로 채움.
|
||||
-- agent_id NULL = 전체(GA 총 수지차).
|
||||
-- payout_total: settle_master.net_amount SUM (설계사별 세후 실지급액 기준)
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE margin_summary (
|
||||
margin_id BIGSERIAL PRIMARY KEY,
|
||||
settle_month CHAR(6) NOT NULL,
|
||||
agent_id BIGINT REFERENCES agent(agent_id),
|
||||
income_total NUMERIC(15,2) NOT NULL DEFAULT 0,
|
||||
payout_total NUMERIC(15,2) NOT NULL DEFAULT 0,
|
||||
margin_amount NUMERIC(15,2) NOT NULL DEFAULT 0,
|
||||
margin_rate NUMERIC(7,4),
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
UNIQUE (settle_month, agent_id),
|
||||
CHECK (income_total >= 0),
|
||||
CHECK (payout_total >= 0)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE margin_summary IS '수지차 집계 — settle_month + agent_id 단위 수입/지급 대비 수지차';
|
||||
COMMENT ON COLUMN margin_summary.margin_id IS '수지차 집계 PK';
|
||||
COMMENT ON COLUMN margin_summary.settle_month IS '정산월 (YYYYMM)';
|
||||
COMMENT ON COLUMN margin_summary.agent_id IS '설계사 FK (NULL = GA 전체 합산)';
|
||||
COMMENT ON COLUMN margin_summary.income_total IS '수입 합계 (income_commission_ledger SUM)';
|
||||
COMMENT ON COLUMN margin_summary.payout_total IS '지급 합계 (settle_master.net_amount SUM — 설계사 세후 실지급액)';
|
||||
COMMENT ON COLUMN margin_summary.margin_amount IS '수지차 = income_total - payout_total';
|
||||
COMMENT ON COLUMN margin_summary.margin_rate IS '수지차율 = margin_amount / income_total (income_total > 0 일 때)';
|
||||
|
||||
CREATE INDEX idx_ms_month ON margin_summary(settle_month);
|
||||
CREATE INDEX idx_ms_agent_month ON margin_summary(agent_id, settle_month);
|
||||
@@ -0,0 +1,72 @@
|
||||
-- V89: 소개·이관수수료 (referral_commission_rule + referral_commission_ledger)
|
||||
-- 계약을 소개(REFERRAL)하거나 이관(TRANSFER)한 설계사에게 지급하는 수수료.
|
||||
-- 정률(RATE): commission_amount = base_amount × commission_rate
|
||||
-- 정액(FIXED): commission_amount = fixed_amount
|
||||
|
||||
-- ============================================================
|
||||
-- 1. referral_commission_rule — 소개·이관수수료 룰 마스터
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE referral_commission_rule (
|
||||
rule_id BIGSERIAL PRIMARY KEY,
|
||||
referral_type VARCHAR(20) NOT NULL,
|
||||
calc_type VARCHAR(10) NOT NULL,
|
||||
commission_rate NUMERIC(7,4),
|
||||
fixed_amount NUMERIC(15,2),
|
||||
effective_from DATE NOT NULL,
|
||||
effective_to DATE,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
created_by BIGINT,
|
||||
updated_at TIMESTAMP,
|
||||
CHECK (referral_type IN ('REFERRAL','TRANSFER')),
|
||||
CHECK (calc_type IN ('RATE','FIXED')),
|
||||
CHECK (commission_rate IS NULL OR (commission_rate >= 0 AND commission_rate <= 1)),
|
||||
CHECK (fixed_amount IS NULL OR fixed_amount >= 0)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE referral_commission_rule IS '소개·이관수수료 룰 마스터 — 소개/이관 유형별 수수료율 또는 정액 정의';
|
||||
COMMENT ON COLUMN referral_commission_rule.rule_id IS '룰 PK';
|
||||
COMMENT ON COLUMN referral_commission_rule.referral_type IS '유형 (REFERRAL=소개 / TRANSFER=이관)';
|
||||
COMMENT ON COLUMN referral_commission_rule.calc_type IS '계산방식 (RATE=정률 / FIXED=정액)';
|
||||
COMMENT ON COLUMN referral_commission_rule.commission_rate IS '정률 요율 (소수, calc_type=RATE 일 때 사용)';
|
||||
COMMENT ON COLUMN referral_commission_rule.fixed_amount IS '정액 금액 (calc_type=FIXED 일 때 사용)';
|
||||
COMMENT ON COLUMN referral_commission_rule.effective_from IS '적용 시작일';
|
||||
COMMENT ON COLUMN referral_commission_rule.effective_to IS '적용 종료일 (NULL=현재 유효)';
|
||||
|
||||
CREATE INDEX idx_rfcr_type_from ON referral_commission_rule(referral_type, effective_from);
|
||||
|
||||
-- ============================================================
|
||||
-- 2. referral_commission_ledger — 소개·이관수수료 원장
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE referral_commission_ledger (
|
||||
ledger_id BIGSERIAL PRIMARY KEY,
|
||||
contract_id BIGINT NOT NULL REFERENCES contract(contract_id),
|
||||
referrer_agent_id BIGINT NOT NULL REFERENCES agent(agent_id),
|
||||
settle_month CHAR(6) NOT NULL,
|
||||
referral_type VARCHAR(20) NOT NULL,
|
||||
base_amount NUMERIC(15,2) NOT NULL,
|
||||
commission_rate NUMERIC(7,4),
|
||||
commission_amount NUMERIC(15,2) NOT NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'CALCULATED',
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP,
|
||||
CHECK (referral_type IN ('REFERRAL','TRANSFER')),
|
||||
CHECK (status IN ('CALCULATED','CONFIRMED','CANCELLED')),
|
||||
CHECK (base_amount >= 0),
|
||||
CHECK (commission_amount >= 0)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE referral_commission_ledger IS '소개·이관수수료 원장 — 소개/이관 설계사에게 지급하는 수수료 발생 이력';
|
||||
COMMENT ON COLUMN referral_commission_ledger.ledger_id IS '원장 PK';
|
||||
COMMENT ON COLUMN referral_commission_ledger.contract_id IS '대상 계약 FK';
|
||||
COMMENT ON COLUMN referral_commission_ledger.referrer_agent_id IS '소개/이관한 설계사 FK';
|
||||
COMMENT ON COLUMN referral_commission_ledger.settle_month IS '정산 귀속월 (YYYYMM)';
|
||||
COMMENT ON COLUMN referral_commission_ledger.referral_type IS '유형 (REFERRAL=소개 / TRANSFER=이관)';
|
||||
COMMENT ON COLUMN referral_commission_ledger.base_amount IS '기준금액 (수수료 또는 보험료)';
|
||||
COMMENT ON COLUMN referral_commission_ledger.commission_rate IS '적용 정률 요율 (RATE 방식 시)';
|
||||
COMMENT ON COLUMN referral_commission_ledger.commission_amount IS '수수료액 = base×rate (RATE) 또는 fixed_amount (FIXED)';
|
||||
COMMENT ON COLUMN referral_commission_ledger.status IS '상태 (CALCULATED/CONFIRMED/CANCELLED)';
|
||||
|
||||
CREATE INDEX idx_rfcl_agent_month ON referral_commission_ledger(referrer_agent_id, settle_month);
|
||||
CREATE INDEX idx_rfcl_contract ON referral_commission_ledger(contract_id);
|
||||
@@ -0,0 +1,65 @@
|
||||
-- V90: 정착지원금 (settling_support_rule + settling_support_ledger)
|
||||
-- 신입/경력 설계사 정착 지원금. 등급별 정액 월 지급 + 조기 해촉 시 환수.
|
||||
-- 공식: net_amount = support_amount - clawback_amount
|
||||
-- 환수: 조기해촉 시 clawback_amount = support_amount × (잔여약정개월 / 약정개월)
|
||||
|
||||
-- ============================================================
|
||||
-- 1. settling_support_rule — 정착지원금 룰 마스터
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE settling_support_rule (
|
||||
rule_id BIGSERIAL PRIMARY KEY,
|
||||
agent_grade VARCHAR(20) NOT NULL,
|
||||
support_amount NUMERIC(15,2) NOT NULL,
|
||||
duration_months INT NOT NULL,
|
||||
clawback_months INT NOT NULL,
|
||||
effective_from DATE NOT NULL,
|
||||
effective_to DATE,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
created_by BIGINT,
|
||||
updated_at TIMESTAMP,
|
||||
CHECK (support_amount >= 0),
|
||||
CHECK (duration_months > 0),
|
||||
CHECK (clawback_months >= 0)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE settling_support_rule IS '정착지원금 룰 마스터 — 설계사 등급별 월 정착지원금 및 약정 기간 정의';
|
||||
COMMENT ON COLUMN settling_support_rule.rule_id IS '룰 PK';
|
||||
COMMENT ON COLUMN settling_support_rule.agent_grade IS '설계사 등급';
|
||||
COMMENT ON COLUMN settling_support_rule.support_amount IS '월 정액 지원금';
|
||||
COMMENT ON COLUMN settling_support_rule.duration_months IS '약정 지원 개월수';
|
||||
COMMENT ON COLUMN settling_support_rule.clawback_months IS '이 개월 내 해촉 시 환수 대상 (0=환수 없음)';
|
||||
COMMENT ON COLUMN settling_support_rule.effective_from IS '적용 시작일';
|
||||
COMMENT ON COLUMN settling_support_rule.effective_to IS '적용 종료일 (NULL=현재 유효)';
|
||||
|
||||
CREATE INDEX idx_ssr_grade_from ON settling_support_rule(agent_grade, effective_from);
|
||||
|
||||
-- ============================================================
|
||||
-- 2. settling_support_ledger — 정착지원금 원장
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE settling_support_ledger (
|
||||
ledger_id BIGSERIAL PRIMARY KEY,
|
||||
agent_id BIGINT NOT NULL REFERENCES agent(agent_id),
|
||||
settle_month CHAR(6) NOT NULL,
|
||||
support_amount NUMERIC(15,2) NOT NULL,
|
||||
clawback_amount NUMERIC(15,2) NOT NULL DEFAULT 0,
|
||||
net_amount NUMERIC(15,2) NOT NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'CALCULATED',
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP,
|
||||
CHECK (status IN ('CALCULATED','PAID','CLAWED_BACK','CANCELLED')),
|
||||
CHECK (support_amount >= 0),
|
||||
CHECK (clawback_amount >= 0)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE settling_support_ledger IS '정착지원금 원장 — 설계사별 월 정착지원금 지급/환수 이력';
|
||||
COMMENT ON COLUMN settling_support_ledger.ledger_id IS '원장 PK';
|
||||
COMMENT ON COLUMN settling_support_ledger.agent_id IS '대상 설계사 FK';
|
||||
COMMENT ON COLUMN settling_support_ledger.settle_month IS '정산 귀속월 (YYYYMM)';
|
||||
COMMENT ON COLUMN settling_support_ledger.support_amount IS '지급액 (등급별 support_amount)';
|
||||
COMMENT ON COLUMN settling_support_ledger.clawback_amount IS '환수액 = support_amount × (잔여약정개월 / 약정개월) (조기해촉 시)';
|
||||
COMMENT ON COLUMN settling_support_ledger.net_amount IS '실지급액 = support_amount - clawback_amount';
|
||||
COMMENT ON COLUMN settling_support_ledger.status IS '상태 (CALCULATED/PAID/CLAWED_BACK/CANCELLED)';
|
||||
|
||||
CREATE INDEX idx_ssl_agent_month ON settling_support_ledger(agent_id, settle_month);
|
||||
@@ -0,0 +1,70 @@
|
||||
-- V91: 인정실적 + 환산보험료 (product_conversion_rate + recognized_performance_ledger)
|
||||
-- 환산보험료 = 보험료 × 상품별 환산율.
|
||||
-- 인정실적 = 환산보험료 × 인정율.
|
||||
-- 시상/등급 산정의 기초 데이터.
|
||||
|
||||
-- ============================================================
|
||||
-- 1. product_conversion_rate — 상품별 환산율 마스터
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE product_conversion_rate (
|
||||
rate_id BIGSERIAL PRIMARY KEY,
|
||||
product_id BIGINT NOT NULL REFERENCES product(product_id),
|
||||
conversion_rate NUMERIC(7,4) NOT NULL,
|
||||
effective_from DATE NOT NULL,
|
||||
effective_to DATE,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
created_by BIGINT,
|
||||
updated_at TIMESTAMP,
|
||||
UNIQUE (product_id, effective_from),
|
||||
CHECK (conversion_rate >= 0 AND conversion_rate <= 1)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE product_conversion_rate IS '상품별 환산율 마스터 — 인정실적 산출을 위한 보험료 환산율';
|
||||
COMMENT ON COLUMN product_conversion_rate.rate_id IS '환산율 PK';
|
||||
COMMENT ON COLUMN product_conversion_rate.product_id IS '적용 상품 FK';
|
||||
COMMENT ON COLUMN product_conversion_rate.conversion_rate IS '환산율 (소수, 예: 0.5 = 50%)';
|
||||
COMMENT ON COLUMN product_conversion_rate.effective_from IS '적용 시작일';
|
||||
COMMENT ON COLUMN product_conversion_rate.effective_to IS '적용 종료일 (NULL=현재 유효)';
|
||||
|
||||
CREATE INDEX idx_pcr_product_from ON product_conversion_rate(product_id, effective_from);
|
||||
|
||||
-- ============================================================
|
||||
-- 2. recognized_performance_ledger — 인정실적 원장
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE recognized_performance_ledger (
|
||||
ledger_id BIGSERIAL PRIMARY KEY,
|
||||
agent_id BIGINT NOT NULL REFERENCES agent(agent_id),
|
||||
contract_id BIGINT NOT NULL REFERENCES contract(contract_id),
|
||||
settle_month CHAR(6) NOT NULL,
|
||||
premium_amount NUMERIC(15,2) NOT NULL,
|
||||
conversion_rate NUMERIC(7,4) NOT NULL,
|
||||
converted_premium NUMERIC(15,2) NOT NULL,
|
||||
recognition_rate NUMERIC(7,4) NOT NULL,
|
||||
recognized_amount NUMERIC(15,2) NOT NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'CALCULATED',
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP,
|
||||
CHECK (status IN ('CALCULATED','CONFIRMED','CANCELLED')),
|
||||
CHECK (premium_amount >= 0),
|
||||
CHECK (conversion_rate >= 0 AND conversion_rate <= 1),
|
||||
CHECK (converted_premium >= 0),
|
||||
CHECK (recognition_rate >= 0 AND recognition_rate <= 1),
|
||||
CHECK (recognized_amount >= 0)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE recognized_performance_ledger IS '인정실적 원장 — 설계사별 계약 단위 환산보험료 및 인정실적';
|
||||
COMMENT ON COLUMN recognized_performance_ledger.ledger_id IS '원장 PK';
|
||||
COMMENT ON COLUMN recognized_performance_ledger.agent_id IS '설계사 FK';
|
||||
COMMENT ON COLUMN recognized_performance_ledger.contract_id IS '대상 계약 FK';
|
||||
COMMENT ON COLUMN recognized_performance_ledger.settle_month IS '정산 귀속월 (YYYYMM)';
|
||||
COMMENT ON COLUMN recognized_performance_ledger.premium_amount IS '보험료';
|
||||
COMMENT ON COLUMN recognized_performance_ledger.conversion_rate IS '적용 환산율 (product_conversion_rate 스냅샷)';
|
||||
COMMENT ON COLUMN recognized_performance_ledger.converted_premium IS '환산보험료 = premium_amount × conversion_rate';
|
||||
COMMENT ON COLUMN recognized_performance_ledger.recognition_rate IS '인정율 (설계사 등급/정책 기준)';
|
||||
COMMENT ON COLUMN recognized_performance_ledger.recognized_amount IS '인정실적 = converted_premium × recognition_rate';
|
||||
COMMENT ON COLUMN recognized_performance_ledger.status IS '상태 (CALCULATED/CONFIRMED/CANCELLED)';
|
||||
|
||||
CREATE INDEX idx_rpl_agent_month ON recognized_performance_ledger(agent_id, settle_month);
|
||||
CREATE INDEX idx_rpl_contract ON recognized_performance_ledger(contract_id);
|
||||
@@ -0,0 +1,71 @@
|
||||
-- V92: 시상 (award_rule + award_ledger)
|
||||
-- 신인도입/법인/유지율/실적 등 시상. 조건 충족 시 정률 또는 정액 지급.
|
||||
-- 정률(RATE): award_amount = base_amount × award_rate
|
||||
-- 정액(FIXED): award_amount = award_fixed
|
||||
|
||||
-- ============================================================
|
||||
-- 1. award_rule — 시상 룰 마스터
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE award_rule (
|
||||
rule_id BIGSERIAL PRIMARY KEY,
|
||||
award_type VARCHAR(20) NOT NULL,
|
||||
calc_type VARCHAR(10) NOT NULL,
|
||||
threshold_amount NUMERIC(15,2),
|
||||
award_rate NUMERIC(7,4),
|
||||
award_fixed NUMERIC(15,2),
|
||||
effective_from DATE NOT NULL,
|
||||
effective_to DATE,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
created_by BIGINT,
|
||||
updated_at TIMESTAMP,
|
||||
CHECK (award_type IN ('NEW_RECRUIT','CORPORATE','RETENTION','PERFORMANCE')),
|
||||
CHECK (calc_type IN ('RATE','FIXED')),
|
||||
CHECK (award_rate IS NULL OR (award_rate >= 0 AND award_rate <= 1)),
|
||||
CHECK (award_fixed IS NULL OR award_fixed >= 0),
|
||||
CHECK (threshold_amount IS NULL OR threshold_amount >= 0)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE award_rule IS '시상 룰 마스터 — 시상 유형별 조건 및 지급 기준';
|
||||
COMMENT ON COLUMN award_rule.rule_id IS '룰 PK';
|
||||
COMMENT ON COLUMN award_rule.award_type IS '시상 유형 (NEW_RECRUIT=신인도입/CORPORATE=법인/RETENTION=유지율/PERFORMANCE=실적)';
|
||||
COMMENT ON COLUMN award_rule.calc_type IS '계산방식 (RATE=정률 / FIXED=정액)';
|
||||
COMMENT ON COLUMN award_rule.threshold_amount IS '충족 기준 실적 (이상 시 시상 발생, NULL=조건 없음)';
|
||||
COMMENT ON COLUMN award_rule.award_rate IS '정률 시상율 (소수, calc_type=RATE 일 때 사용)';
|
||||
COMMENT ON COLUMN award_rule.award_fixed IS '정액 시상금 (calc_type=FIXED 일 때 사용)';
|
||||
COMMENT ON COLUMN award_rule.effective_from IS '적용 시작일';
|
||||
COMMENT ON COLUMN award_rule.effective_to IS '적용 종료일 (NULL=현재 유효)';
|
||||
|
||||
CREATE INDEX idx_awdr_type_from ON award_rule(award_type, effective_from);
|
||||
|
||||
-- ============================================================
|
||||
-- 2. award_ledger — 시상 원장
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE award_ledger (
|
||||
ledger_id BIGSERIAL PRIMARY KEY,
|
||||
agent_id BIGINT NOT NULL REFERENCES agent(agent_id),
|
||||
settle_month CHAR(6) NOT NULL,
|
||||
award_type VARCHAR(20) NOT NULL,
|
||||
base_amount NUMERIC(15,2) NOT NULL,
|
||||
award_amount NUMERIC(15,2) NOT NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'CALCULATED',
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP,
|
||||
CHECK (award_type IN ('NEW_RECRUIT','CORPORATE','RETENTION','PERFORMANCE')),
|
||||
CHECK (status IN ('CALCULATED','CONFIRMED','PAID','CANCELLED')),
|
||||
CHECK (base_amount >= 0),
|
||||
CHECK (award_amount >= 0)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE award_ledger IS '시상 원장 — 설계사별 시상 발생 이력';
|
||||
COMMENT ON COLUMN award_ledger.ledger_id IS '원장 PK';
|
||||
COMMENT ON COLUMN award_ledger.agent_id IS '설계사 FK';
|
||||
COMMENT ON COLUMN award_ledger.settle_month IS '정산 귀속월 (YYYYMM)';
|
||||
COMMENT ON COLUMN award_ledger.award_type IS '시상 유형 (NEW_RECRUIT/CORPORATE/RETENTION/PERFORMANCE)';
|
||||
COMMENT ON COLUMN award_ledger.base_amount IS '기준 실적 (인정실적 합산 등)';
|
||||
COMMENT ON COLUMN award_ledger.award_amount IS '시상금 = base×award_rate (RATE) 또는 award_fixed (FIXED)';
|
||||
COMMENT ON COLUMN award_ledger.status IS '상태 (CALCULATED/CONFIRMED/PAID/CANCELLED)';
|
||||
|
||||
CREATE INDEX idx_awdl_agent_month ON award_ledger(agent_id, settle_month);
|
||||
CREATE INDEX idx_awdl_type_month ON award_ledger(award_type, settle_month);
|
||||
@@ -0,0 +1,65 @@
|
||||
-- V93: 생보운영지원수수료 (life_support_rule + life_support_ledger)
|
||||
-- 생보 계약 운영지원 수수료. 설계사 등급별 지급률 × 생보 실적 + 환수.
|
||||
-- 공식: support_amount = base_amount × support_rate
|
||||
-- net_amount = support_amount - clawback_amount
|
||||
|
||||
-- ============================================================
|
||||
-- 1. life_support_rule — 생보운영지원수수료 룰 마스터
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE life_support_rule (
|
||||
rule_id BIGSERIAL PRIMARY KEY,
|
||||
agent_grade VARCHAR(20) NOT NULL,
|
||||
support_rate NUMERIC(7,4) NOT NULL,
|
||||
effective_from DATE NOT NULL,
|
||||
effective_to DATE,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
created_by BIGINT,
|
||||
updated_at TIMESTAMP,
|
||||
CHECK (support_rate >= 0 AND support_rate <= 1)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE life_support_rule IS '생보운영지원수수료 룰 마스터 — 등급별 생보 운영지원 수수료율';
|
||||
COMMENT ON COLUMN life_support_rule.rule_id IS '룰 PK';
|
||||
COMMENT ON COLUMN life_support_rule.agent_grade IS '설계사 등급';
|
||||
COMMENT ON COLUMN life_support_rule.support_rate IS '지급률 (소수, 예: 0.03 = 3%)';
|
||||
COMMENT ON COLUMN life_support_rule.effective_from IS '적용 시작일';
|
||||
COMMENT ON COLUMN life_support_rule.effective_to IS '적용 종료일 (NULL=현재 유효)';
|
||||
|
||||
CREATE INDEX idx_lsr_grade_from ON life_support_rule(agent_grade, effective_from);
|
||||
|
||||
-- ============================================================
|
||||
-- 2. life_support_ledger — 생보운영지원수수료 원장
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE life_support_ledger (
|
||||
ledger_id BIGSERIAL PRIMARY KEY,
|
||||
agent_id BIGINT NOT NULL REFERENCES agent(agent_id),
|
||||
settle_month CHAR(6) NOT NULL,
|
||||
base_amount NUMERIC(15,2) NOT NULL,
|
||||
support_rate NUMERIC(7,4) NOT NULL,
|
||||
support_amount NUMERIC(15,2) NOT NULL,
|
||||
clawback_amount NUMERIC(15,2) NOT NULL DEFAULT 0,
|
||||
net_amount NUMERIC(15,2) NOT NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'CALCULATED',
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP,
|
||||
CHECK (status IN ('CALCULATED','CONFIRMED','PAID','CLAWED_BACK','CANCELLED')),
|
||||
CHECK (base_amount >= 0),
|
||||
CHECK (support_rate >= 0 AND support_rate <= 1),
|
||||
CHECK (support_amount >= 0),
|
||||
CHECK (clawback_amount >= 0)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE life_support_ledger IS '생보운영지원수수료 원장 — 설계사별 생보 운영지원 수수료 발생/환수 이력';
|
||||
COMMENT ON COLUMN life_support_ledger.ledger_id IS '원장 PK';
|
||||
COMMENT ON COLUMN life_support_ledger.agent_id IS '설계사 FK';
|
||||
COMMENT ON COLUMN life_support_ledger.settle_month IS '정산 귀속월 (YYYYMM)';
|
||||
COMMENT ON COLUMN life_support_ledger.base_amount IS '생보 실적 기준금액';
|
||||
COMMENT ON COLUMN life_support_ledger.support_rate IS '적용 지급률 (life_support_rule 스냅샷)';
|
||||
COMMENT ON COLUMN life_support_ledger.support_amount IS '지원수수료 = base_amount × support_rate';
|
||||
COMMENT ON COLUMN life_support_ledger.clawback_amount IS '환수액';
|
||||
COMMENT ON COLUMN life_support_ledger.net_amount IS '실지급액 = support_amount - clawback_amount';
|
||||
COMMENT ON COLUMN life_support_ledger.status IS '상태 (CALCULATED/CONFIRMED/PAID/CLAWED_BACK/CANCELLED)';
|
||||
|
||||
CREATE INDEX idx_lsl_agent_month ON life_support_ledger(agent_id, settle_month);
|
||||
@@ -0,0 +1,69 @@
|
||||
-- V94: 지점장수당 (branch_mgr_allowance_rule + branch_mgr_allowance_ledger)
|
||||
-- 지점장이 소속 조직 실적에 대해 받는 수당. cap 제한 + 환수.
|
||||
-- 공식: allowance_amount = LEAST(base_amount × allowance_rate, cap_amount)
|
||||
-- (cap_amount NULL 이면 상한 없음)
|
||||
|
||||
-- ============================================================
|
||||
-- 1. branch_mgr_allowance_rule — 지점장수당 룰 마스터
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE branch_mgr_allowance_rule (
|
||||
rule_id BIGSERIAL PRIMARY KEY,
|
||||
position_code VARCHAR(20) NOT NULL,
|
||||
allowance_rate NUMERIC(7,4) NOT NULL,
|
||||
cap_amount NUMERIC(15,2),
|
||||
effective_from DATE NOT NULL,
|
||||
effective_to DATE,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
created_by BIGINT,
|
||||
updated_at TIMESTAMP,
|
||||
CHECK (allowance_rate >= 0 AND allowance_rate <= 1),
|
||||
CHECK (cap_amount IS NULL OR cap_amount >= 0)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE branch_mgr_allowance_rule IS '지점장수당 룰 마스터 — 직책별 수당율 및 상한 정의';
|
||||
COMMENT ON COLUMN branch_mgr_allowance_rule.rule_id IS '룰 PK';
|
||||
COMMENT ON COLUMN branch_mgr_allowance_rule.position_code IS '직책 코드 (지점장 등)';
|
||||
COMMENT ON COLUMN branch_mgr_allowance_rule.allowance_rate IS '수당율 (소수, 예: 0.02 = 2%)';
|
||||
COMMENT ON COLUMN branch_mgr_allowance_rule.cap_amount IS '수당 상한금액 (NULL=무제한)';
|
||||
COMMENT ON COLUMN branch_mgr_allowance_rule.effective_from IS '적용 시작일';
|
||||
COMMENT ON COLUMN branch_mgr_allowance_rule.effective_to IS '적용 종료일 (NULL=현재 유효)';
|
||||
|
||||
CREATE INDEX idx_bmar_position_from ON branch_mgr_allowance_rule(position_code, effective_from);
|
||||
|
||||
-- ============================================================
|
||||
-- 2. branch_mgr_allowance_ledger — 지점장수당 원장
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE branch_mgr_allowance_ledger (
|
||||
ledger_id BIGSERIAL PRIMARY KEY,
|
||||
manager_agent_id BIGINT NOT NULL REFERENCES agent(agent_id),
|
||||
org_id BIGINT NOT NULL REFERENCES organization(org_id),
|
||||
settle_month CHAR(6) NOT NULL,
|
||||
base_amount NUMERIC(15,2) NOT NULL,
|
||||
allowance_rate NUMERIC(7,4) NOT NULL,
|
||||
allowance_amount NUMERIC(15,2) NOT NULL,
|
||||
clawback_amount NUMERIC(15,2) NOT NULL DEFAULT 0,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'CALCULATED',
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP,
|
||||
CHECK (status IN ('CALCULATED','CONFIRMED','PAID','CLAWED_BACK','CANCELLED')),
|
||||
CHECK (base_amount >= 0),
|
||||
CHECK (allowance_rate >= 0 AND allowance_rate <= 1),
|
||||
CHECK (allowance_amount >= 0),
|
||||
CHECK (clawback_amount >= 0)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE branch_mgr_allowance_ledger IS '지점장수당 원장 — 지점장이 소속 조직 실적 기준으로 받는 수당 이력';
|
||||
COMMENT ON COLUMN branch_mgr_allowance_ledger.ledger_id IS '원장 PK';
|
||||
COMMENT ON COLUMN branch_mgr_allowance_ledger.manager_agent_id IS '지점장 설계사 FK';
|
||||
COMMENT ON COLUMN branch_mgr_allowance_ledger.org_id IS '대상 조직 FK';
|
||||
COMMENT ON COLUMN branch_mgr_allowance_ledger.settle_month IS '정산 귀속월 (YYYYMM)';
|
||||
COMMENT ON COLUMN branch_mgr_allowance_ledger.base_amount IS '조직 실적 기준금액';
|
||||
COMMENT ON COLUMN branch_mgr_allowance_ledger.allowance_rate IS '적용 수당율 (branch_mgr_allowance_rule 스냅샷)';
|
||||
COMMENT ON COLUMN branch_mgr_allowance_ledger.allowance_amount IS '수당액 = LEAST(base_amount × allowance_rate, cap_amount)';
|
||||
COMMENT ON COLUMN branch_mgr_allowance_ledger.clawback_amount IS '환수액';
|
||||
COMMENT ON COLUMN branch_mgr_allowance_ledger.status IS '상태 (CALCULATED/CONFIRMED/PAID/CLAWED_BACK/CANCELLED)';
|
||||
|
||||
CREATE INDEX idx_bmal_manager_month ON branch_mgr_allowance_ledger(manager_agent_id, settle_month);
|
||||
CREATE INDEX idx_bmal_org_month ON branch_mgr_allowance_ledger(org_id, settle_month);
|
||||
@@ -0,0 +1,90 @@
|
||||
-- V95: incar 갭 수수료 도메인 7개 PAGE 메뉴 등록
|
||||
-- GRP_COMMISSION 하위 PAGE 7개 추가 (V54 패턴 동일).
|
||||
-- 권한: READ/CREATE/UPDATE/DELETE/EXPORT
|
||||
-- 역할: SUPER_ADMIN/ADMIN 전체, MANAGER READ/CREATE/UPDATE/EXPORT,
|
||||
-- AGENT READ (INCOME_COMM 제외 — 본인 관련 도메인만)
|
||||
|
||||
-- ============================================================
|
||||
-- 1. GRP_COMMISSION 하위 PAGE 7개 (incar P7)
|
||||
-- ============================================================
|
||||
|
||||
INSERT INTO menu (parent_menu_id, menu_code, menu_name, menu_type, menu_path, component_path, menu_level, sort_order)
|
||||
SELECT p.menu_id, x.code, x.name, 'PAGE', x.path, x.cmpt, 2, x.sort
|
||||
FROM menu p
|
||||
JOIN (VALUES
|
||||
('INCOME_COMM', '수입수수료/수지차', '/commission/income', 'commission/IncomeCommission', 80),
|
||||
('REFERRAL_COMM', '소개·이관수수료', '/commission/referral', 'commission/ReferralCommission',90),
|
||||
('SETTLING_SUPPORT', '정착지원금', '/commission/settling-support', 'commission/SettlingSupport', 100),
|
||||
('RECOGNIZED_PERF', '인정실적', '/commission/recognized', 'commission/RecognizedPerformance',110),
|
||||
('AWARD', '시상', '/commission/award', 'commission/Award', 120),
|
||||
('LIFE_OP_SUPPORT', '생보운영지원수수료', '/commission/life-support', 'commission/LifeSupport', 130),
|
||||
('BRANCH_MGR_ALLOWANCE', '지점장수당', '/commission/branch-allowance', 'commission/BranchAllowance', 140)
|
||||
) AS x(code, name, path, cmpt, sort)
|
||||
ON p.menu_code = 'GRP_COMMISSION'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM menu WHERE menu_code = x.code);
|
||||
|
||||
-- ============================================================
|
||||
-- 2. 7개 메뉴에 권한 항목 등록 (READ/CREATE/UPDATE/DELETE/EXPORT)
|
||||
-- ============================================================
|
||||
|
||||
INSERT INTO menu_permission (menu_id, perm_code, perm_name, sort_order)
|
||||
SELECT m.menu_id, p.code, p.name, p.sort
|
||||
FROM menu m
|
||||
CROSS JOIN (VALUES
|
||||
('READ', '조회', 10),
|
||||
('CREATE', '등록', 20),
|
||||
('UPDATE', '수정', 30),
|
||||
('DELETE', '삭제', 40),
|
||||
('EXPORT', '엑셀', 60)
|
||||
) AS p(code, name, sort)
|
||||
WHERE m.menu_code IN (
|
||||
'INCOME_COMM','REFERRAL_COMM','SETTLING_SUPPORT',
|
||||
'RECOGNIZED_PERF','AWARD','LIFE_OP_SUPPORT','BRANCH_MGR_ALLOWANCE'
|
||||
)
|
||||
ON CONFLICT (menu_id, perm_code) DO NOTHING;
|
||||
|
||||
-- ============================================================
|
||||
-- 3. 역할별 권한 부여
|
||||
-- ============================================================
|
||||
|
||||
-- SUPER_ADMIN / ADMIN — 7개 메뉴 전체 권한
|
||||
INSERT INTO role_menu_permission (role_id, menu_id, perm_code, is_granted)
|
||||
SELECT r.role_id, mp.menu_id, mp.perm_code, 'Y'
|
||||
FROM role r
|
||||
CROSS JOIN menu_permission mp
|
||||
JOIN menu m ON m.menu_id = mp.menu_id
|
||||
WHERE r.role_code IN ('SUPER_ADMIN','ADMIN')
|
||||
AND m.menu_code IN (
|
||||
'INCOME_COMM','REFERRAL_COMM','SETTLING_SUPPORT',
|
||||
'RECOGNIZED_PERF','AWARD','LIFE_OP_SUPPORT','BRANCH_MGR_ALLOWANCE'
|
||||
)
|
||||
ON CONFLICT (role_id, menu_id, perm_code) DO NOTHING;
|
||||
|
||||
-- MANAGER — READ/CREATE/UPDATE/EXPORT (DELETE 제외)
|
||||
INSERT INTO role_menu_permission (role_id, menu_id, perm_code, is_granted)
|
||||
SELECT r.role_id, mp.menu_id, mp.perm_code, 'Y'
|
||||
FROM role r
|
||||
CROSS JOIN menu_permission mp
|
||||
JOIN menu m ON m.menu_id = mp.menu_id
|
||||
WHERE r.role_code = 'MANAGER'
|
||||
AND mp.perm_code IN ('READ','CREATE','UPDATE','EXPORT')
|
||||
AND m.menu_code IN (
|
||||
'INCOME_COMM','REFERRAL_COMM','SETTLING_SUPPORT',
|
||||
'RECOGNIZED_PERF','AWARD','LIFE_OP_SUPPORT','BRANCH_MGR_ALLOWANCE'
|
||||
)
|
||||
ON CONFLICT (role_id, menu_id, perm_code) DO NOTHING;
|
||||
|
||||
-- AGENT — INCOME_COMM 제외하고 READ 만
|
||||
-- (INCOME_COMM은 보험사-GA 수입 측 데이터로 설계사 공개 불가)
|
||||
INSERT INTO role_menu_permission (role_id, menu_id, perm_code, is_granted)
|
||||
SELECT r.role_id, mp.menu_id, mp.perm_code, 'Y'
|
||||
FROM role r
|
||||
CROSS JOIN menu_permission mp
|
||||
JOIN menu m ON m.menu_id = mp.menu_id
|
||||
WHERE r.role_code = 'AGENT'
|
||||
AND mp.perm_code = 'READ'
|
||||
AND m.menu_code IN (
|
||||
'REFERRAL_COMM','SETTLING_SUPPORT',
|
||||
'RECOGNIZED_PERF','AWARD','LIFE_OP_SUPPORT','BRANCH_MGR_ALLOWANCE'
|
||||
)
|
||||
ON CONFLICT (role_id, menu_id, perm_code) DO NOTHING;
|
||||
@@ -0,0 +1,35 @@
|
||||
-- V96: incar 갭 수수료 도메인 공통코드 5종 (V55 패턴 동일)
|
||||
-- INCOME_STATUS / REFERRAL_TYPE / CALC_TYPE / SUPPORT_STATUS / AWARD_TYPE
|
||||
|
||||
-- ===== 그룹 =====
|
||||
INSERT INTO common_code_group (group_code, group_name, description, is_system, sort_order) VALUES
|
||||
('INCOME_STATUS', '수입수수료상태', 'CALCULATED/CONFIRMED/CANCELLED', 'Y', 390),
|
||||
('REFERRAL_TYPE', '소개이관유형', 'REFERRAL=소개/TRANSFER=이관', 'Y', 400),
|
||||
('CALC_TYPE', '계산방식', 'RATE=정률/FIXED=정액', 'Y', 410),
|
||||
('SUPPORT_STATUS', '지원금상태', 'CALCULATED/PAID/CLAWED_BACK/CANCELLED', 'Y', 420),
|
||||
('AWARD_TYPE', '시상유형', 'NEW_RECRUIT/CORPORATE/RETENTION/PERFORMANCE', 'Y', 430)
|
||||
ON CONFLICT (group_code) DO NOTHING;
|
||||
|
||||
-- ===== 상세 =====
|
||||
INSERT INTO common_code (group_code, code, code_name, sort_order) VALUES
|
||||
-- INCOME_STATUS
|
||||
('INCOME_STATUS', 'CALCULATED', '계산완료', 10),
|
||||
('INCOME_STATUS', 'CONFIRMED', '확정', 20),
|
||||
('INCOME_STATUS', 'CANCELLED', '취소', 30),
|
||||
-- REFERRAL_TYPE
|
||||
('REFERRAL_TYPE', 'REFERRAL', '소개', 10),
|
||||
('REFERRAL_TYPE', 'TRANSFER', '이관', 20),
|
||||
-- CALC_TYPE
|
||||
('CALC_TYPE', 'RATE', '정률', 10),
|
||||
('CALC_TYPE', 'FIXED', '정액', 20),
|
||||
-- SUPPORT_STATUS
|
||||
('SUPPORT_STATUS', 'CALCULATED', '계산완료', 10),
|
||||
('SUPPORT_STATUS', 'PAID', '지급완료', 20),
|
||||
('SUPPORT_STATUS', 'CLAWED_BACK','환수완료', 30),
|
||||
('SUPPORT_STATUS', 'CANCELLED', '취소', 40),
|
||||
-- AWARD_TYPE
|
||||
('AWARD_TYPE', 'NEW_RECRUIT', '신인도입', 10),
|
||||
('AWARD_TYPE', 'CORPORATE', '법인', 20),
|
||||
('AWARD_TYPE', 'RETENTION', '유지율', 30),
|
||||
('AWARD_TYPE', 'PERFORMANCE', '실적', 40)
|
||||
ON CONFLICT (group_code, code) DO NOTHING;
|
||||
@@ -0,0 +1,27 @@
|
||||
-- V97: 단계마감 (settlement_step_close)
|
||||
-- 월 정산을 단계별로 마감(수신→계산→검증→지급). 기존 PERIOD_CLOSE 보강.
|
||||
|
||||
CREATE TABLE settlement_step_close (
|
||||
step_close_id BIGSERIAL PRIMARY KEY,
|
||||
settle_month CHAR(6) NOT NULL,
|
||||
step_code VARCHAR(20) NOT NULL,
|
||||
step_seq INT NOT NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'OPEN',
|
||||
closed_at TIMESTAMP,
|
||||
closed_by BIGINT,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
UNIQUE (settle_month, step_code),
|
||||
CHECK (step_code IN ('RECEIVE','CALC','VERIFY','PAY')),
|
||||
CHECK (status IN ('OPEN','CLOSED'))
|
||||
);
|
||||
|
||||
COMMENT ON TABLE settlement_step_close IS '단계마감 — 월 정산 단계별 마감 상태 관리';
|
||||
COMMENT ON COLUMN settlement_step_close.settle_month IS '정산 귀속월 (YYYYMM)';
|
||||
COMMENT ON COLUMN settlement_step_close.step_code IS '단계코드 (RECEIVE=수신/CALC=계산/VERIFY=검증/PAY=지급)';
|
||||
COMMENT ON COLUMN settlement_step_close.step_seq IS '단계 순서 1~4';
|
||||
COMMENT ON COLUMN settlement_step_close.status IS '상태 (OPEN=열림/CLOSED=마감)';
|
||||
COMMENT ON COLUMN settlement_step_close.closed_at IS '마감 처리 일시';
|
||||
COMMENT ON COLUMN settlement_step_close.closed_by IS '마감 처리자 FK(users)';
|
||||
|
||||
CREATE INDEX idx_ssc_month_status ON settlement_step_close(settle_month, status);
|
||||
CREATE INDEX idx_ssc_step_seq ON settlement_step_close(step_seq);
|
||||
@@ -0,0 +1,29 @@
|
||||
-- V98: 본사정산 (hq_settle_item)
|
||||
-- GA 본사 자체의 수입/비용 정산 항목(설계사 지급과 별개의 GA 손익).
|
||||
-- 본사손익 = SUM(INCOME amount) - SUM(EXPENSE amount)
|
||||
|
||||
CREATE TABLE hq_settle_item (
|
||||
item_id BIGSERIAL PRIMARY KEY,
|
||||
settle_month CHAR(6) NOT NULL,
|
||||
item_type VARCHAR(20) NOT NULL,
|
||||
item_name VARCHAR(100) NOT NULL,
|
||||
amount NUMERIC(15,2) NOT NULL,
|
||||
memo VARCHAR(300),
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'REGISTERED',
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
created_by BIGINT,
|
||||
updated_at TIMESTAMP,
|
||||
CHECK (item_type IN ('INCOME','EXPENSE')),
|
||||
CHECK (status IN ('REGISTERED','CONFIRMED'))
|
||||
);
|
||||
|
||||
COMMENT ON TABLE hq_settle_item IS '본사정산 항목 — GA 자체 수입/비용 정산';
|
||||
COMMENT ON COLUMN hq_settle_item.settle_month IS '정산 귀속월 (YYYYMM)';
|
||||
COMMENT ON COLUMN hq_settle_item.item_type IS '항목유형 (INCOME=수입/EXPENSE=비용)';
|
||||
COMMENT ON COLUMN hq_settle_item.item_name IS '항목명';
|
||||
COMMENT ON COLUMN hq_settle_item.amount IS '금액 (원, HALF_UP)';
|
||||
COMMENT ON COLUMN hq_settle_item.memo IS '비고';
|
||||
COMMENT ON COLUMN hq_settle_item.status IS '상태 (REGISTERED=등록/CONFIRMED=확정)';
|
||||
|
||||
CREATE INDEX idx_hqi_month_type ON hq_settle_item(settle_month, item_type);
|
||||
CREATE INDEX idx_hqi_month_status ON hq_settle_item(settle_month, status);
|
||||
@@ -0,0 +1,53 @@
|
||||
-- V99: 등급평가 (grade_eval_rule + agent_grade_evaluation)
|
||||
-- 설계사 실적 점수로 등급 산정.
|
||||
-- 공식: evaluated_grade = score 이상인 최대 min_score 룰의 grade (Service 결정)
|
||||
|
||||
-- ============================================================
|
||||
-- 1. grade_eval_rule — 점수구간별 등급 룰 마스터
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE grade_eval_rule (
|
||||
rule_id BIGSERIAL PRIMARY KEY,
|
||||
grade_id INT NOT NULL REFERENCES grade(grade_id),
|
||||
min_score NUMERIC(7,2) NOT NULL,
|
||||
effective_from DATE NOT NULL,
|
||||
effective_to DATE,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
COMMENT ON TABLE grade_eval_rule IS '등급평가 룰 — 실적점수 구간별 등급 매핑';
|
||||
COMMENT ON COLUMN grade_eval_rule.grade_id IS '부여 등급 FK(grade)';
|
||||
COMMENT ON COLUMN grade_eval_rule.min_score IS '최소 실적점수 (이 점수 이상이면 해당 등급)';
|
||||
COMMENT ON COLUMN grade_eval_rule.effective_from IS '룰 적용 시작일';
|
||||
COMMENT ON COLUMN grade_eval_rule.effective_to IS '룰 적용 종료일 (NULL=현재 유효)';
|
||||
|
||||
CREATE INDEX idx_ger_grade_from ON grade_eval_rule(grade_id, effective_from);
|
||||
CREATE INDEX idx_ger_score ON grade_eval_rule(min_score);
|
||||
|
||||
-- ============================================================
|
||||
-- 2. agent_grade_evaluation — 설계사 등급평가 원장
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE agent_grade_evaluation (
|
||||
eval_id BIGSERIAL PRIMARY KEY,
|
||||
agent_id INT NOT NULL REFERENCES agent(agent_id),
|
||||
eval_period CHAR(6) NOT NULL,
|
||||
performance_score NUMERIC(7,2) NOT NULL,
|
||||
prev_grade_id INT REFERENCES grade(grade_id),
|
||||
evaluated_grade_id INT REFERENCES grade(grade_id),
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'EVALUATED',
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
UNIQUE (agent_id, eval_period),
|
||||
CHECK (status IN ('EVALUATED','APPLIED'))
|
||||
);
|
||||
|
||||
COMMENT ON TABLE agent_grade_evaluation IS '설계사 등급평가 원장 — 월별 실적점수 기반 등급 산정 결과';
|
||||
COMMENT ON COLUMN agent_grade_evaluation.agent_id IS '대상 설계사 FK';
|
||||
COMMENT ON COLUMN agent_grade_evaluation.eval_period IS '평가 기준월 (YYYYMM)';
|
||||
COMMENT ON COLUMN agent_grade_evaluation.performance_score IS '실적 점수';
|
||||
COMMENT ON COLUMN agent_grade_evaluation.prev_grade_id IS '기존(직전) 등급 FK';
|
||||
COMMENT ON COLUMN agent_grade_evaluation.evaluated_grade_id IS '산정 등급 FK';
|
||||
COMMENT ON COLUMN agent_grade_evaluation.status IS '상태 (EVALUATED=평가완료/APPLIED=반영완료)';
|
||||
|
||||
CREATE INDEX idx_age_agent_period ON agent_grade_evaluation(agent_id, eval_period);
|
||||
CREATE INDEX idx_age_status ON agent_grade_evaluation(status, eval_period);
|
||||
Reference in New Issue
Block a user