Files
GA Pro bfc724669b 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>
2026-05-31 15:45:10 +09:00

170 lines
8.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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_commissionwithholding_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.)