# E2E 시나리오 — 보험이 어떻게 들어와서 수수료가 어떻게 나가는가

> 이 문서는 **계약 1건이 인입되어 설계사 통장에 돈이 꽂힐 때까지**의 전체 순서를
> "등장인물 + 숫자"로 따라가는 시나리오입니다.
> 각 단계는 실제 계산 코드(`CommissionCalculator`, `RegulatoryLimitChecker`,
> `InstallmentPlanGenerator`, `ChargebackCalculator`, `TaxCalculator`)와 1:1로 대응하며,
> 이 시나리오를 그대로 검증하는 단위테스트가 `SettlementScenarioTest` 입니다.

---

## 0. 등장인물 (이 시나리오의 테스트 데이터)

| 역할 | 식별자 | 속성 |
|---|---|---|
| 원 모집설계사 **김설계** | `agentId=10`, `gradeId=5` | 사업소득(BUSINESS_INCOME) · 과세사업자(TAXABLE) |
| 후임 승계설계사 **박승계** | `agentId=20`, `gradeId=3` | (계약 승계 단계에서 등장) |
| 상위 직책자 **이지점** | `agentId=30` | 오버라이드 수령 |
| 상품 **무배당 종신보험** | `productId=1`, `WHOLE_LIFE`, 카테고리 `LIFE` | |
| 계약 | `contractId=100`, `policyNo=POL-0001` | 연납보험료 **1,000,000원**, 계약일 **2024-01-15** |

기준 룰(테스트에서 Mock으로 주입하는 데이터):

| 룰 | 값 |
|---|---|
| 보험사요율(company_rate) 1차년 | 60% |
| 보험사요율 2차년 | 10% |
| 지급률(payout_rate) 등급5·WHOLE_LIFE·1차년 | 75% |
| 지급률 등급5·2차년 | 50% |
| 지급률 등급3(후임)·2차년 | 40% |
| 분급 비율(7년) | 35 / 25 / 15 / 10 / 7 / 5 / 3 (%) |
| 차등환수 13~24개월 구간 | 50% |
| 1200% 한도(TOTAL_RATIO) | 12,000,000원 (연납 1,000,000 × 1200%) |
| 원천세 | 사업소득 3.3% · 지방세 = 소득세 10% · 부가세 10%(과세사업자) |

---

## 1. 한눈에 보는 순서

```
[보험사] 실적데이터 인입
   │  (Step1 receive → Step2 transform → Step3 reconcile)
   ▼
① 모집수수료 원장 계산  (Step4 calcRecruit)         ← premium × company_rate × payout_rate
   │
② 1200% 룰 한도 체크    (RegulatoryLimitChecker)     ← 누적이 한도를 넘으면 잘라냄
   │
③ 분급(7년) 계획 생성   (InstallmentPlanGenerator)   ← 큰 모집수수료를 7년에 나눠 지급
   │
④ 유지수수료 원장 계산  (Step5 calcMaintain)         ← 2차년 이후 매년
   │     └ ⑤ 계약 승계 시 후임에게 귀속 전환 (모집은 원설계사 유지)
   │
⑥ 오버라이드 계산       (Step7 calcOverride)         ← 하위실적 × 율 (cap 제한)
   │
⑦ 조기 해지 환수        (Step6 chargeback)           ← 유지개월 짧을수록 많이 환수
   │
⑧ 설계사×월 집계        (Step8 aggregate)            ← gross 합산
   │     └ 세금 원천징수 + 공제 차감 → net(실지급액)
   ▼
[설계사 통장]  ← 펌뱅킹 이체(KFTC)
```

---

## 2. 단계별 숫자 (시나리오 본문)

### ① 모집수수료 원장 계산 — 보험이 "들어오는" 첫 돈
계약이 인입되면 설계사 김설계(등급5)의 모집수수료 원장 1줄이 생긴다.

```
① 보험사지급액 = 보험료 1,000,000 × 보험사요율 60%  = 600,000
② 설계사수수료 = 600,000        × 지급률   75%      = 450,000  ← gross
③ 원장 원천세  = 450,000        × 3.3%             = 14,850
```
→ 원장: `agent_id=10`, `commission_year=1`, `agent_amount=450,000`, `tax_amount=14,850`

### ② 1200% 룰 한도 체크
초년도 모집수수료 누적이 연납보험료의 1200%(=12,000,000)를 넘으면 안 된다.
- 현재 누적 0 + 450,000 = 450,000 ≤ 12,000,000 → **통과**
- 만약 추가분이 한도를 넘기면 `ViolationResult.violated` 로 막고 초과분을 잘라낸다.

### ③ 분급(7년 분할) 계획 생성
모집수수료 450,000을 한 번에 안 주고 7년에 나눈다.

| 차년 | 비율 | 지급액 |
|---|---|---|
| 1 | 35% | 157,500 |
| 2 | 25% | 112,500 |
| 3 | 15% | 67,500 |
| 4 | 10% | 45,000 |
| 5 | 7% | 31,500 |
| 6 | 5% | 22,500 |
| 7 | 3% | 13,500 |
| **합** | **100%** | **450,000** |

> **무결성 규칙:** 분급액의 **합은 원수수료와 정확히 같아야 한다.**
> 금액이 딱 나눠떨어지지 않을 때(예: 435,150원) 회차별 반올림 잔차가 생기는데,
> 이때는 **마지막 회차가 잔차를 흡수**해서 합계를 원금에 맞춘다. (→ §4 보완)

### ④ 유지수수료 (2차년)
계약이 유지되면 2차년부터 유지수수료가 매년 발생한다.
```
보험사지급액 = 1,000,000 × 10%(2차년 요율) = 100,000
설계사수수료 = 100,000   × 50%(등급5 2차년) = 50,000
```

### ⑤ 계약 승계 (김설계 해촉 → 박승계 후임)
김설계가 해촉되면 그 계약의 **유지수수료만** 후임 박승계(등급3)에게 넘어간다.
```
유지수수료(후임) = 100,000 × 40%(등급3 2차년) = 40,000   → 원장 agent_id = 20(박승계)
```
- **모집수수료는 원 모집설계사 김설계(10)에게 그대로 남는다.** (고아계약 승계 표준)

### ⑥ 오버라이드 (상위 직책자 이지점)
하위 김설계의 실적에 대해 상위 이지점이 받는 수당.
```
오버라이드 = 하위실적 2,000,000 × 4% = 80,000   (cap 100,000 미만이므로 그대로)
```

### ⑦ 조기 해지 환수 — 13개월차 해지
계약이 13개월차(2024-01-15 → 2025-02-15)에 깨지면 13~24개월 구간 환수율 50%.
```
환수액 = 기지급 모집수수료 450,000 × 50% = 225,000   ← 다음 정산에서 (−) 차감
```

### ⑧ 집계 → 세금 → 실지급액(net)
김설계 한 달치를 settle_master로 집계하고 세금·공제를 반영한다.
과세사업자(TAXABLE) gross 450,000 기준:
```
소득세  = 450,000 × 3.3%        = 14,850
지방세  = 14,850  × 10%         =  1,485
부가세  = 450,000 × 10%         = 45,000  (과세사업자만 +)
실지급 = 450,000 − 14,850 − 1,485 + 45,000 = 478,665
```
- 여기에 가지급금 공제 100,000이 있으면 net = 478,665 − 100,000 = **378,665**
- 비과세(NONE) 설계사는 부가세가 없어 net = 450,000 − 14,850 − 1,485 = **433,665**

---

## 3. 시나리오 ↔ 코드 ↔ 테스트 대응표

| 단계 | 코드 | 테스트 메서드 |
|---|---|---|
| ① 모집수수료 | `CommissionCalculator.calcRecruitLedger` | `s1_보험인입_모집수수료_원장계산` |
| ② 1200% 룰 | `BatchRegulatoryLimitChecker.checkContractTotal` | `s2_규제_1200퍼센트_한도_통과및위반` |
| ③ 분급 7년 | `BatchInstallmentPlanGenerator.generate` | `s3_분급_7년_분할_합계100퍼센트` |
| ③ 분급 잔차 | 〃 | `s3b_분급_라운딩_잔차_마지막회차_흡수` |
| ④ 유지수수료 | `CommissionCalculator.calcMaintainLedger` | `s4_유지수수료_2차년` |
| ⑤ 계약 승계 | `CommissionCalculator.calcMaintainLedger(effectiveAgentId)` | `s5_계약승계_유지수수료_후임귀속` |
| ⑦ 차등 환수 | `BatchChargebackCalculator.calculate` | `s6_조기해지_차등환수_13개월_50퍼센트` |
| ⑧ 세금/실지급 | `BatchTaxCalculator.calculate` | `s7_세금_실지급액_과세사업자` / `s8_세금_비과세` |

---

## 4. 이 시나리오 작성 중 발견·보완한 사항

**분급 계획 합계 불일치(반올림 잔차) — 수정함.**
- 현상: 분급액을 회차별로 `총액 × 비율 / 100` 으로 각각 반올림하면,
  원금이 7로 나눠떨어지지 않을 때 분급 합계가 원금과 1~수원 어긋났다.
  (예: 435,150원 → 회차 합 435,153원, +3원 누수)
- 영향: 분급 총합 ≠ 원 모집수수료 → 정산 무결성(합계 일치) 위반, 과/미지급.
- 수정: **비율 합이 정확히 100%인 정규 스케줄**일 때 마지막 회차가
  `원금 − 직전 회차 합` 으로 잔차를 흡수하도록 보정.
  (비율 합이 100% 미만인 부분지급 스케줄은 기존 동작 유지 → 설계 의도 보존)
- 대상: `InstallmentPlanGenerator`(ga-api), `BatchInstallmentPlanGenerator`(ga-batch) 양쪽.

---

*기준: schema v108, DOMAIN_KNOWLEDGE.md 7장 공식. 모든 금액 BigDecimal HALF_UP.*
