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>
8.2 KiB
P8 — incar 갭 반영: 운영/정산 프로세스 7개 도메인 (🅱)
작성: PL (자율 모드), 2026-05-31. 사용자 지시 "다 적용". P7(🅰 수수료계산 7)에 이어 🅱 운영 7개로 incar 갭 14개 완성. 범위: 풀스택(DB→Core→API→Frontend→Infra). 패턴 100% 준수(template = 수금수수료 V41 / CollectionCommission*, P7과 동일). Flyway: V96이 최신 → V97부터. 메뉴는 적절한 상위그룹 하위. 금액 NUMERIC(15,2), 율 NUMERIC(7,4), HALF_UP.
확정 FK: agent(agent_id), contract(contract_id), organization(org_id), insurance_company(company_id), grade(grade_id), settle_master.
도메인별 설계
D8. 단계마감 (STEP_CLOSE) — V97
월 정산을 단계별로 마감(수신→계산→검증→지급). 기존 PERIOD_CLOSE(단일 잠금) 보강.
settlement_step_close
| 컬럼 | 타입 | 설명 |
|---|---|---|
| step_close_id | BIGSERIAL PK | |
| settle_month | CHAR(6) NN | |
| step_code | VARCHAR(20) NN | RECEIVE/CALC/VERIFY/PAY |
| step_seq | INT NN | 단계 순서 1~4 |
| status | VARCHAR(20) NN DEFAULT 'OPEN' | OPEN/CLOSED |
| closed_at TIMESTAMP / closed_by BIGINT / created_at | ||
| UNIQUE(settle_month, step_code); CHECK step_code IN(...); CHECK status IN('OPEN','CLOSED') | ||
| 공식 없음(워크플로우). 액션: close(단계마감), reopen. |
D9. 본사정산 (HQ_SETTLE) — V98
GA 본사 자체의 수입/비용 정산 항목(설계사 지급과 별개의 GA 손익).
hq_settle_item
| 컬럼 | 타입 | 설명 |
|---|---|---|
| item_id | BIGSERIAL PK | |
| settle_month | CHAR(6) NN | |
| item_type | VARCHAR(20) NN | INCOME(수입)/EXPENSE(비용) |
| item_name | VARCHAR(100) NN | 항목명 |
| amount | NUMERIC(15,2) NN | 금액 |
| memo | VARCHAR(300) | |
| status | VARCHAR(20) NN DEFAULT 'REGISTERED' | REGISTERED/CONFIRMED |
| created_at/created_by/updated_at | ||
| idx: (settle_month, item_type). CHECK item_type IN('INCOME','EXPENSE') | ||
| 공식: 본사손익 = Σ(INCOME amount) − Σ(EXPENSE amount). 조회 집계 엔드포인트 제공. |
D10. 등급평가 (GRADE_EVAL) — V99
설계사 실적 점수로 등급 산정. rule(점수구간→등급) + 평가원장.
grade_eval_rule
| 컬럼 | 타입 | 설명 |
|---|---|---|
| rule_id BIGSERIAL PK | ||
| grade_id | BIGINT NN FK grade | 부여 등급 |
| min_score | NUMERIC(7,2) NN | 이 점수 이상이면 해당 등급 |
| effective_from DATE NN / effective_to DATE |
agent_grade_evaluation
| 컬럼 | 타입 | 설명 |
|---|---|---|
| eval_id BIGSERIAL PK | ||
| agent_id BIGINT NN FK agent | ||
| eval_period CHAR(6) NN | 평가기준월 | |
| performance_score NUMERIC(7,2) NN | 실적점수 | |
| prev_grade_id BIGINT FK grade | 기존 등급 | |
| evaluated_grade_id BIGINT FK grade | 산정 등급 | |
| status VARCHAR(20) NN DEFAULT 'EVALUATED' | EVALUATED/APPLIED | |
| idx: (agent_id, eval_period). UNIQUE(agent_id, eval_period) | ||
| 공식: evaluated_grade = score 이상인 최대 min_score 룰의 grade. Service가 grade_eval_rule 조회해 결정. |
D11. 공동계약 (JOINT_CONTRACT) — V100
한 계약을 여러 설계사가 공동 모집 → 지분율(share_rate)로 수수료 배분.
joint_contract
| 컬럼 | 타입 | 설명 |
|---|---|---|
| joint_id BIGSERIAL PK | ||
| contract_id BIGINT NN FK contract | ||
| agent_id BIGINT NN FK agent | ||
| role VARCHAR(10) NN | LEAD/SUB | |
| share_rate NUMERIC(7,4) NN | 지분율(합=1) | |
| created_at/created_by | ||
| UNIQUE(contract_id, agent_id); CHECK role IN('LEAD','SUB'); CHECK share_rate>=0 AND share_rate<=1 | ||
| 공식: 설계사몫 = 계약수수료 × share_rate. (검증: 계약별 share_rate 합=1 — Service 가드) |
D12. 보증보험 (GUARANTEE_INS) — V101
설계사가 가입하는 신원보증보험 가입현황 추적(공식 없음, 관리).
agent_guarantee_insurance
| 컬럼 | 타입 | 설명 |
|---|---|---|
| guarantee_id BIGSERIAL PK | ||
| agent_id BIGINT NN FK agent | ||
| policy_no VARCHAR(50) NN | 증권번호 | |
| carrier_id BIGINT FK insurance_company(company_id) | 보증보험사 | |
| guarantee_amount NUMERIC(15,2) NN | 보증금액 | |
| start_date DATE NN / end_date DATE NN | 보증기간 | |
| status VARCHAR(20) NN DEFAULT 'ACTIVE' | ACTIVE/EXPIRED/CANCELLED | |
| idx: (agent_id, status),(end_date) |
D13. 적립금 (RESERVE_FUND) — V102
환수 대비 수수료 일부 적립 + 잔액 관리.
agent_reserve_fund
| 컬럼 | 타입 | 설명 |
|---|---|---|
| reserve_id BIGSERIAL PK | ||
| agent_id BIGINT NN FK agent | ||
| settle_month CHAR(6) NN | ||
| reserve_in NUMERIC(15,2) NN DEFAULT 0 | 적립액 | |
| reserve_out NUMERIC(15,2) NN DEFAULT 0 | 인출/사용액 | |
| balance NUMERIC(15,2) NN | = 전월잔액 + reserve_in − reserve_out | |
| created_at | ||
| UNIQUE(agent_id, settle_month). idx (agent_id, settle_month) | ||
| 공식: balance = (직전월 balance) + reserve_in − reserve_out. Service가 직전월 조회해 누적. |
D14. 수수료 시뮬레이터 (COMM_SIMULATOR) — V103
보험료/요율/지급률 입력 → 수수료·세금·실지급·분급·환수예상 산출. 시나리오 저장.
commission_simulation
| 컬럼 | 타입 | 설명 |
|---|---|---|
| sim_id BIGSERIAL PK | ||
| sim_name VARCHAR(100) NN | 시나리오명 | |
| premium_amount NUMERIC(15,2) NN | 입력 보험료 | |
| company_rate NUMERIC(7,4) NN | 보험사요율 | |
| payout_rate NUMERIC(7,4) NN | 지급률 | |
| commission_year INT NN | 회차 | |
| company_payment NUMERIC(15,2) NN | = 보험료×요율 | |
| agent_commission NUMERIC(15,2) NN | = 보험사지급액×지급률 | |
| withholding_tax NUMERIC(15,2) NN | = 설계사수수료×3.3% | |
| net_amount NUMERIC(15,2) NN | = 수수료−원천세 | |
| expected_chargeback NUMERIC(15,2) | 예상 환수(13개월 가정 50% 등) | |
| created_at/created_by | ||
| 공식(DOMAIN_KNOWLEDGE 7장과 동일): company_payment=premium×company_rate, agent_commission=company_payment×payout_rate, withholding_tax=agent_commission×0.033, net=agent_commission−withholding_tax. Service의 simulate 액션이 입력만 받아 계산 후 저장/반환. |
메뉴 (V104)
| menu_code | menu_name | 상위그룹 | menu_path | component_path |
|---|---|---|---|---|
| STEP_CLOSE | 단계마감 | GRP_SETTLE | /settle/step-close | settle/StepClose |
| HQ_SETTLE | 본사정산 | GRP_SETTLE | /settle/hq-settle | settle/HqSettle |
| GRADE_EVAL | 등급평가 | GRP_ORG | /org/grade-eval | org/GradeEvaluation |
| JOINT_CONTRACT | 공동계약 | GRP_PRD | /contracts/joint | contracts/JointContract |
| GUARANTEE_INS | 보증보험 | GRP_ORG | /org/guarantee | org/GuaranteeInsurance |
| RESERVE_FUND | 적립금 | GRP_COMMISSION | /commission/reserve | commission/ReserveFund |
| COMM_SIMULATOR | 수수료 시뮬레이터 | GRP_COMMISSION | /commission/simulator | commission/CommissionSimulator |
권한 READ/CREATE/UPDATE/DELETE/EXPORT(STEP_CLOSE는 READ/UPDATE/APPROVE). 역할부여 V54/V95 패턴.
공통코드 (V105)
| group_code | 코드 |
|---|---|
| STEP_CODE | RECEIVE=수신마감/CALC=계산마감/VERIFY=검증마감/PAY=지급마감 |
| STEP_STATUS | OPEN=열림/CLOSED=마감 |
| HQ_ITEM_TYPE | INCOME=수입/EXPENSE=비용 |
| JOINT_ROLE | LEAD=주설계사/SUB=공동설계사 |
| GUARANTEE_STATUS | ACTIVE=유효/EXPIRED=만료/CANCELLED=해지 |
| GRADE_EVAL_STATUS | EVALUATED=평가완료/APPLIED=반영완료 |
Wave 실행 (P7과 동일 팀/패턴)
1 dba: V97~V105 · 2 core: VO/Mapper/Enum · 3 api: Service/Controller(공식·집계 내장) · 4 front: 7페이지+commission/settle/org api+App.tsx · 5 infra: build+smoke PL 검증: GET뿐 아니라 액션 POST(close/reopen/simulate/recalc balance/등급산정)까지 실호출로 5xx 0 확인 — P7에서 GET-only smoke가 버그를 놓친 교훈 반영.
완료 상태 (2026-05-31)
schema v105 적용(Flyway V97~V105 success), 전체 ./gradlew build SUCCESSFUL, 프론트 빌드 OK, ga-api 8082 라이브. 8테이블·7메뉴 등록. GET 9 + 액션 POST 5(simulate/hq-settles/step-closes/close/reserve upsert) 전부 200, 5xx 0건. 시뮬레이터 공식 실측: 보험료 1,000,000×0.6=600,000 → ×0.75=450,000 → 원천세 14,850 → net 435,150 → 예상환수 225,000 ✓. 테스트데이터 정리 완료. (P8은 P7과 달리 액션까지 PL이 직접 호출 검증 → 숨은 버그 0.)