Files
ga-commission-system/HANDOFF.md
T
GA Pro 49f08f001d feat: P5-W3 본론 완료 — 회계결산/이상치예측/연말명세서 (V74~V78)
P5-W2 원천세·부가세 분기신고 미커밋분 + P5-W3 메뉴/권한 보강(V74) + P5-W3 본론(V75~V78)을 일괄 정리.

- V75 accounting_close / account_balance_snapshot (회계 결산)
- V76 retention_anomaly_alert / forecast_kpi_monthly (이상치·예측 KPI)
- V77 year_end_statement (연말 지급명세서)
- V78 P5-W3 본론 메뉴 4 + 권한 + 공통코드 7그룹 + 테스트데이터
- api: AccountingClose/YearEndStatement/ForecastKpi/RetentionAnomaly Service+Controller
- batch: BatchConfig Step 11/12 (원천세·부가세 분기) 연결
- frontend: 4화면(AccountingClose/YearEndStatement/RetentionAnomaly/ForecastKpi) + API 모듈 4 + 라우트
- frontend: usePermission/PermissionButton EXECUTE 권한 누락 보강
- fix: YearEndStatementMapper.xml 미존재 컬럼 a.agent_code 참조 제거

통합검증: Flyway V74~V78 운영DB 적용(v78), 4모듈 compileJava + 프론트 build PASS,
스모크 GET 8/8 + 쓰기 4/4 PASS, verify_v74.py 20/20 PASS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 22:22:34 +09:00

294 lines
17 KiB
Markdown
Raw 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.
# Handoff Note — 2026-05-14 (Round 2 완료)
다음 세션에서 이어가기 위한 핸드오프 문서. Agent Teams 기반 자동 체인으로 진행 중인 작업의 현재 상태와 잔여 작업, 재개 절차를 기록한다.
## 1. 핸드오프 시점 상태
- **마지막 커밋**: P1-3-c (ChargebackCalculator + ChargebackGradeService + Controller)
- **빌드 상태**: `./gradlew :ga-common:compileJava :ga-core:compileJava :ga-api:compileJava` 모두 BUILD SUCCESSFUL
- **이번 세션 누적 커밋 수**: 26개 (Agent Teams 설정 1 + 코드 품질 7 + 도메인 P0 9 + 도메인 P1 11)
- **변경 사항 없음** (working tree clean)
## 2. 완료된 작업
### 2-1. 코드 품질 자동 체인 (7 커밋)
초기 ga-api 5명 리뷰 결과를 바탕으로 P0 이슈 일괄 해결.
| 단계 | 커밋 | 내용 |
|---|---|---|
| 1 | `5e58a54` | OrganizationSaveReq + 상태 Enum 4종 (Agent/Contract/Settle/Approve) |
| 2 | `a8f0b6e` | Controller→Service 분리 5개 + 매직 스트링 Enum 교체 + @DataChangeLog 17곳 |
| 3a | `693275e` | UserStatus + ExceptionLedgerStatus Enum |
| 3b | `af3c6b9` | Map→SaveReq DTO 4종 + 입력 검증 + 잔여 Enum 적용 |
| 4 | `498d0d4` | LookupCache 동시성 + UploadService/TransferFile 트랜잭션 분해 + readOnly 일괄 |
| 5a | `4b211ec` | AgentOrgHistoryResp + MapStruct mapper 3종 + AgentMapper.xml 조인 |
| 5b | `b16e678` | MapStruct 적용 + Resp 적용 + PaymentService/UploadTemplateService 신설 + PageHelper 통일 |
### 2-2. 도메인 P0 — 세무·공제·명세서 (9 커밋)
| 도메인 | a (DB) | b (core) | c (api) |
|---|---|---|---|
| P0-1 세무 | `ad5d62e` V23 | `92f3217` | `f8c7d84` TaxCalculator |
| P0-2 공제 | `0e73eb6` V24 | `a3ba7fa` | `b8f33f1` DeductionService |
| P0-3 명세서 | `930335c` V25 | `4f5a2f0` | `f5efcaa` ExcelStatementGenerator |
핵심 산출물:
- 표준 세율 system_config 외부화 (3.3%/8.8%/10%/10%)
- `agent`에 tax_type/business_no/vat_type 컬럼
- `payment`에 income_tax_amount/local_tax_amount/vat_amount/net_amount
- `agent_deduction` (월별 차감 마스터) + `payment_deduction_detail` (이체 명세)
- `commission_statement` (명세서 발급 마스터, agent+settle_month+statement_type UNIQUE)
- TaxCalculator pure 도메인 + ExcelStatementGenerator (PDF는 향후)
### 2-3. 도메인 P1 — 1200%룰·분급·차등환수 (11 커밋)
| 도메인 | a (DB) | b (core) | c (api) |
|---|---|---|---|
| P1-1 1200%룰 | `6a6ba9f` V26 | `1109253` | `bba4a33` RegulatoryLimitChecker |
| P1-2 분급 | `434e778` V27 | `5029bc5` | (P1-2-c 커밋) InstallmentPlanGenerator |
| P1-3 차등환수 | `cc5d0e5` V28 | `44dbbf3` | (P1-3-c 커밋) ChargebackCalculator |
**P1 보강 (병렬 트랙)**:
- `1aa31de` RecruitLedger/MaintainLedger sumByContract 메서드 추가
- `f6142a1` RegulatoryLimitChecker TODO 해소 (실제 누적값 사용)
핵심 산출물:
- `regulatory_limit` 마스터 (1200%/35%/7년 한도, effective_from/to 이력 추적)
- `installment_ratio` + `installment_plan` (분급 7년 비율 35/25/15/10/7/5/3)
- `chargeback_grade` (5단계: 1~12개월 100% → 85개월~ 0%)
- RegulatoryLimitChecker / InstallmentPlanGenerator / ChargebackCalculator pure 도메인
### 2-4. 병렬화 적용 (P1 후반부)
초반 직렬 a→b→c 패턴에서 후반에 도메인 간 sub-step 병렬로 전환.
- P1-2-c(api) + P1-3-a(dba) + P1 보강(core) 3명 동시 활성화
- P1-3-b(core) + P1-1-c TODO 교체(api) 2명 동시
- 모듈이 다른 사람끼리 묶어 머지 충돌 없음
## 3. Round 2 완료 사항 (2026-05-14)
### 3-1. P2 — 8 도메인 (V29~V36, ~50 VO·Mapper, 18 Service+Controller)
| # | 도메인 | 마이그레이션 | 상태 |
|---|---|---|---|
| P2-1 | 마감 (Period Close) | V29 | 완료 |
| P2-2 | 정정 (Correction) | V30 | 완료 |
| P2-3 | 이의신청 (Dispute) | V31 | 완료 |
| P2-4 | 보류사유 (Hold Reasons) | V32 | 완료 |
| P2-5 | 시책·인센티브 | V33 | 완료 |
| P2-6 | 해촉정산 (Termination) | V34 | 완료 |
| P2-7 | 세금계산서 (Tax Invoice) | V35 | 완료 |
| P2-8 | 외부회신 | V36 | 완료 |
화면: ga-frontend Wave 4 에서 P4-B 화면과 함께 작성됨.
### 3-2. P3 — KPI 대시보드 (V37~V39)
- dba: mv_monthly_summary / mv_org_summary / mv_retention_rate / mv_cumulative (V37)
- dba: 리포트 메뉴 + KPI 메뉴 INSERT (V38, V39)
- core: KpiMapper.java + XML
- api: KpiService + KpiController (`/api/kpi/*`)
- frontend: KpiMonthlySummary / KpiOrgSummary / KpiRetention / KpiCumulative (4개 화면)
### 3-3. P4-A — 수수료 종류 보강 (V40~V44, 5 도메인)
| # | 도메인 | 마이그레이션 | 상태 |
|---|---|---|---|
| P4-A-1 | commission_type 코드 + commission_master 통합 | V40 | 완료 |
| P4-A-2 | 수금수수료 (collection_commission_rule/ledger) | V41 | 완료 |
| P4-A-3 | 갱신·부활수수료 (renewal/reinstatement) | V42 | 완료 |
| P4-A-4 | 유지보수수당 (persistency_bonus_rule/bonus) | V43 | 완료 |
| P4-A-5 | 오버라이드 원장 (override_ledger/summary) | V44 | 완료 |
### 3-4. P4-B — 운영 필수 9 도메인 (V45~V53)
| # | 도메인 | 마이그레이션 | 상태 |
|---|---|---|---|
| P4-B-1 | 위촉계약 (agent_contract) | V45 | 완료 |
| P4-B-2 | 자격관리 (agent_license) | V46 | 완료 |
| P4-B-3 | 보수교육 (agent_training) | V47 | 완료 |
| P4-B-4 | 계약변경 (contract_endorsement) | V48 | 완료 |
| P4-B-5 | 민원관리 (complaint) | V49 | 완료 |
| P4-B-6 | 결재워크플로우 (approval_line/request) | V50 | 완료 |
| P4-B-7 | 공지·알림 (notice/user_notification) | V51 | 완료 |
| P4-B-8 | 첨부파일 (attachment) | V52 | 완료 |
| P4-B-9 | 출금신청 (withdraw_request) | V53 | 완료 |
### 3-5. V54~V55 + 프론트
- V54: P4 메뉴 INSERT (P4-A + P4-B 14개 메뉴)
- V55: P4 공통코드 추가 (approval_type, complaint_type, license_type, withdraw_status 등)
- 프론트: ErrorBoundary 전역 적용 + 토스 디자인 시스템 토큰 (`RADIUS`, `GRAY`, `SHADOW`) 일관 적용
- 프론트 화면 추가: AgentContracts / AgentLicenses / AgentTrainings / Complaints / ContractEndorsements / CollectionCommission / CommissionMaster / OverrideLedger / PersistencyBonus / ReinstatementCommission / RenewalCommission / WithdrawRequest / Approvals / Notices (14개)
### 3-6. P1 정산 통합 (batch-engineer 완료)
- ga-batch 8 Step에 TaxCalculator / DeductionService / RegulatoryLimitChecker / InstallmentPlanGenerator / ChargebackCalculator 통합 완료
## 3-7. P5 Wave 1 — agent + contract 회계 진입점 (V63~V66)
| 항목 | 마이그레이션 | 상태 |
|---|---|---|
| agent_annual_income 테이블 | V63 | 완료 |
| contract_accounting_entry 테이블 | V64 | 완료 |
| P5-W1 테스트 데이터 + 메뉴 INSERT (ANNUAL_INCOME / ACCOUNTING_JOURNAL) | V65 | 완료 |
| account_code 마스터 + 4건 초기 데이터 | V66 | 완료 |
| rule 감사 컬럼 보강 (commission_rate/payout_rule/override_rule 등) | V70 | 완료 |
| payment 세무 컬럼 보강 (income_tax_amount/local_tax_amount/vat_amount/net_amount) | V71 | 완료 |
핵심 산출물:
- `agent_annual_income` (agentId+settleYear 복합PK, 연도별 사업소득 집계)
- `contract_accounting_entry` (분개 엔트리, debit/credit 계정코드 + journalNo 마감)
- `account_code` 마스터 (account_type DEBIT/CREDIT/BOTH 구분, 초기 4건: 8350/2530/1130/4110)
- `AgentAnnualIncomeService` + `AgentAnnualIncomeController` (`/api/agent-annual-incomes`)
- `ContractAccountingService` + `ContractAccountingController` (`/api/accounting-entries`)
- `AccountCodeService` + `AccountCodeController` (`/api/common/account-codes`)
- `YearEndIncomeAggregateStep` (Step 10, 12월 마감 시만 실행, settleMonth.endsWith("12") 조건)
- `AccountingEntryGenerateStep` (Step 9, 매월 정산 후 분개 생성, ledger UNION 기반 contract_id 확보, journal_no=NULL 미전기)
- 프론트 화면: `AgentAnnualIncomeList` (`/commission/annual-income`) + `AccountingJournalList` (`/commission/accounting-journal`)
통합 검증 결과 (2026-05-15):
- Flyway: V63/V64/V65/V66/V70/V71 적용 확인 (현재 ga schema V71)
- GET /api/agent-annual-incomes → 200 OK
- POST /api/agent-annual-incomes/regenerate?year=2025 → 200 OK, affected=0 (payment 데이터 없음, 정상)
- GET /api/accounting-entries → 200 OK
- GET /api/common/account-codes?accountType=DEBIT → 200 OK, 2 items
보정 사항 (통합 검증 중 발견):
- App.tsx 라우트와 V65 menu_path 모두 `/commission/annual-income`, `/commission/accounting-journal`로 일치
- ANNUAL_INCOME EXECUTE 권한 누락 → DB 직접 INSERT로 보정
- payment 세무 컬럼 미적용 (V23 체크섬 충돌 이력) → V71로 idempotent 보강
운영 DB 적용: ga-api 재시작 → Flyway V18~V71 일괄 자동 적용.
## 3-8. P5 Wave 2 — 원천세/부가세 분기신고 (V67~V69)
| 항목 | 마이그레이션 | 상태 |
|---|---|---|
| withholding_tax_report 테이블 (원천세 분기신고) | V67 | 완료 |
| vat_report 테이블 (부가세 분기신고) | V68 | 완료 |
| P5-W2 테스트 데이터 + 메뉴 INSERT (WITHHOLDING_TAX / VAT_REPORT) | V69 | 완료 |
| EXECUTE 권한 보강 (WITHHOLDING_TAX / VAT_REPORT) | V73 | 완료 |
핵심 산출물:
- `withholding_tax_report` (분기별 원천세 신고 집계: settleQuarter/agentId/totalIncome/totalWithheld/totalLocalTax)
- `vat_report` (분기별 부가세 신고 집계: settleQuarter/totalSales/totalPurchase/totalVatPayable/taxInvoiceCount)
- `WithholdingTaxReportMapper` + `WithholdingTaxReportMapper.xml` (selectList/selectDetailById/upsertQuarterlyAggregate/updateFileStatusToFiled)
- `VatReportMapper` + `VatReportMapper.xml` (selectList/selectDetailById/upsertQuarterlyAggregate/updateFileStatusToFiled)
- `WithholdingTaxReportService` + `WithholdingTaxReportController` (`/api/withholding-tax-reports`)
- `VatReportService` + `VatReportController` (`/api/vat-reports`)
- `WithholdingTaxQuarterlyStep` (batch Step 11, 분기 마지막 월 실행)
- `VatReportQuarterlyStep` (batch Step 12, 분기 마지막 월 실행)
- 프론트 API 모듈: `ga-frontend/src/api/withholdingTax.ts` + `ga-frontend/src/api/vat.ts`
통합 검증 결과 (2026-05-17):
- Flyway: 운영 DB ga schema V73 (V67/V68/V69/V73 모두 적용 확인)
- GET /api/withholding-tax-reports → 200 OK, list 반환 (집계 데이터 있음)
- GET /api/withholding-tax-reports/1 → 200 OK, 단건 상세 반환
- POST /api/withholding-tax-reports/regenerate {"settleQuarter":"2025-Q4"} → 200 OK, affected=0 (이미 존재, 정상)
- PUT /api/withholding-tax-reports/complete {"ids":[1]} → 200 OK
- GET /api/vat-reports → 200 OK, list 반환
- GET /api/vat-reports/1 → 200 OK, 단건 상세 반환
- POST /api/vat-reports/regenerate {"settleQuarter":"2025-Q4"} → 200 OK, affected=1
- PUT /api/vat-reports/complete {"ids":[1]} → 200 OK
보정 사항 (통합 검증 중 발견):
- frontend build 실패: ChargebackGradeList/InstallmentRatioList/DeductionList validator 파라미터 implicit any, CommissionDispute/IncentiveProgram/TaxInvoiceList parser 반환타입 불일치 → 명시적 타입 어노테이션으로 수정 (6개 파일)
- complete 엔드포인트 요청 바디: `{"ids":[id]}` 형식 (단일 reportId 아님)
운영 DB 최신 상태: ga schema V73 적용 완료.
## 4. 잔여 작업 (P6)
P5-W2 / P5-W3(메뉴·권한 보강 V74 + 본론 V75~V78) 모두 완료. 잔여는 P6뿐.
### P6 — 외부 연동 (P5 이후)
| 항목 | 설명 |
|---|---|
| 펌뱅킹 실연동 | withdraw_request 결재 완료 → 은행 API 직접 호출 |
| SMS/카카오 발송 | user_notification 채널 실연동 |
| 모바일 셀프 조회 | 설계사 전용 모바일 앱 or PWA |
### 운영 DB 마이그레이션 상태
운영 DB `192.168.0.60:55432/trading_ai/ga` 현재 **V78 적용 완료** (2026-05-21).
V74~V78 Flyway 자동 적용 확인. ga-api 8082 가동 중.
단위/통합 테스트는 SqlSessionFactory 환경 설정 문제로 아직 미작성 상태입니다.
## 3-9. P5-W3 메뉴/권한 전수 정합 보강 (V74 — 완료, 2026-05-21 라이브 적용)
| 항목 | 상태 |
|---|---|
| AUDIT_P5W3.md §4 갭 리포트 작성 | 완료 (2026-05-17, infra) |
| V74 SQL 작성 | 완료 (2026-05-17, dba) |
| V74 정적검증 (PL) | 완료 (멱등·ON CONFLICT·스코프 확인) |
| 4모듈 compileJava | **PASS** (BUILD SUCCESSFUL) |
| ga-frontend npm run build | **PASS** (TS 오류 0) |
| 운영 DB 접속·Flyway V74 적용 | **완료** (2026-05-21, ga-api 재기동 시 자동 적용) |
| 스모크 검증 | **완료** (verify_v74.py 20/20 PASS) |
갭 요약 (총 27건):
- (a) menu 없음: 0건
- (b) menu_permission 없음: 3건 (NOTICE/DELETE, SYSTEM_DATA_DICT/DELETE, TERM_SETTLE/APPROVE)
- (c) grant 없음: 6건 (위 3 perm × SUPER_ADMIN+ADMIN, ADMIN/SYSTEM_* 7건은 보안상 의도적 제외)
- route/menu_path 불일치: 11건 (V74에서 UPDATE 처리)
갭 재검증 (V74 적용 후): `python verify_v74.py`**20/20 PASS** 확인 완료 (2026-05-21).
## 3-10. P5-W3 본론 — 결산 / 이상치·예측 / 연말명세서 (V75~V78, 2026-05-21 완료)
| 항목 | 마이그레이션 | 상태 |
|---|---|---|
| accounting_close + account_balance_snapshot (회계 결산) | V75 | 완료 |
| retention_anomaly_alert + forecast_kpi_monthly (이상치·예측 KPI) | V76 | 완료 |
| year_end_statement (연말 지급명세서) | V77 | 완료 |
| P5-W3 본론 메뉴 4개 + 권한 + 공통코드 7그룹 + 테스트데이터 | V78 | 완료 |
핵심 산출물:
- `AccountingCloseService/Controller` (`/api/accounting-closes`) — DRAFT 생성 / 마감 실행(분개 채번+잔액 스냅샷) / 재오픈
- `RetentionAnomalyAlertService/Controller` (`/api/retention-anomalies`) — 13M/25M 이상 탐지 / 검토 처리
- `ForecastKpiMonthlyService/Controller` (`/api/forecast-kpi`) — 이동평균(SMA3/6/NAIVE) 차월 예측
- `YearEndStatementService/Controller` (`/api/year-end-statements`) — 연 사업소득 명세서 재집계/발급/발송/엑셀
- 배치: BatchConfig 에 Step 11(WithholdingTaxQuarterly) / Step 12(VatReportQuarterly) 연결
- 프론트: `AccountingCloseList` / `YearEndStatementList` / `RetentionAnomalyList` / `ForecastKpiList` 4화면 + API 모듈 4개 + App.tsx 라우트 4개
- 공통: `usePermission`/`PermissionButton``EXECUTE` 권한 누락 보강 (canExecute)
통합 검증 (2026-05-21):
- Flyway: 운영 DB V74~V78 자동 적용 → 현재 **v78**
- 4모듈 compileJava + ga-frontend npm run build **PASS** (TS 오류 0)
- 스모크: 신규 4 + 회귀 4 = **GET 8/8 PASS**, 쓰기(regenerate/detect/draft) 4/4 PASS
- 보정: YearEndStatementMapper.xml 의 `a.agent_code` 미존재 컬럼 참조 제거 (agent 테이블에 agent_code 없음)
## 5. 재개 절차 (다음 세션 — P6 라운드)
1. **Claude Code 시작 시 cwd 확인**: `C:\Users\kyu\Desktop\ga_pro` (현재 세션과 동일)
2. **Agent Teams 활성화 확인**: `.claude/settings.json` 커밋되어 있음
3. **HANDOFF.md 읽기**: 본 문서 + 최근 git log로 컨텍스트 확보
4. **운영 DB 상태**: **V78 적용 완료**. ga-api 8082 가동 중 (필요 시 `python verify_v74.py` / `smoke_v78.py` 재실행)
5. **권장 시작 지점**: P6 외부 연동 — 펌뱅킹 실연동 / SMS·카카오 발송 / 모바일 셀프 조회
6. **사용자 결정 필요 항목**:
- P2-1 마감 도메인의 마감 후 수정 차단 AOP 구현 방식 (전역 AOP vs Service-level 가드)
- P6 펌뱅킹/메시징 외부 연동처 실제 스펙 (현재 미정 → 착수 전 확인 필요)
## 6. PL 가이드 (다음 세션 유의사항)
- **시간차 중복 메시지**: 팀원이 SendMessage로 같은 보고를 2~3번 보내는 경우 있음. 짧게 acknowledge만.
- **idle 알림**: 팀원이 작업 끝낼 때마다 idle 알림 보냄. 정상. 액션 필요 없음.
- **책임 경계**: dba=Flyway/SQL, core=VO/Mapper/Enum, api=Service/Controller. api-developer가 가끔 ga-core Mapper에 메서드 추가하는데 작은 변경이면 통과 가능, 큰 변경은 core-architect에 위임.
- **TODO 잔존**: api-developer가 부족한 ga-core 메서드 발견 시 TODO로 남기고 보고 → PL이 후속 보강 디스패치. 같은 단계에서 멈추지 말고 흐름 유지.
- **자동 정책**:
- 각 단계 완료 후 자동 커밋 (push 안 함)
- 빌드/테스트 실패 시 담당 팀원에 재지시
- 컴파일은 PL이 직접 검증, 테스트는 환경 문제(SqlSessionFactory)로 통과 안 되는 게 알려진 상태
## 7. 표준 가정 (도메인 작업 진행 시 채택한 값)
도메인 룰은 한국 보험업감독규정 표준 가정을 외부화 가능한 구조로 등록. 실제 회사 정책과 다르면 system_config / regulatory_limit / installment_ratio / chargeback_grade의 데이터만 수정하면 됨.
| 항목 | 표준값 | 근거 |
|---|---|---|
| 사업소득 원천징수 | 3.3% | 한국 표준 |
| 기타소득 원천징수 | 8.8% | 한국 표준 |
| 지방소득세 | 원천세의 10% | 한국 표준 |
| 부가세 | 10% | 한국 표준 |
| 1200% 룰 총 한도 | 1200% | 보험업감독규정 제5-15조의5 |
| 1차년 한도 | 35% | 2024년 기준 |
| 분급 연한 | 7년 | 2024년 기준 |
| 분급 비율 | 35/25/15/10/7/5/3 (합 100%) | 가정값 |
| 차등 환수 | 1~12: 100%, 13~24: 50%, 25~36: 25%, 37~84: 10%, 85~: 0% | 가정값 |
가정값과 실제가 다르면 운영 데이터 수정으로 해결 가능. 코드 변경 불필요.