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>
This commit is contained in:
GA Pro
2026-05-21 22:22:34 +09:00
parent d5ed642c80
commit 49f08f001d
80 changed files with 4506 additions and 62 deletions
@@ -40,18 +40,22 @@ public class BatchConfig {
CalcOverrideStep step7,
AggregateStep step8,
AccountingEntryGenerateStep step9,
YearEndIncomeAggregateStep step10) {
YearEndIncomeAggregateStep step10,
WithholdingTaxQuarterlyStep step11,
VatReportQuarterlyStep step12) {
return new JobBuilder("MONTHLY_SETTLEMENT", jobRepository)
.start(taskletStep("receiveData", step1, jobRepository, tx))
.next(taskletStep("transformData", step2, jobRepository, tx))
.next(taskletStep("reconcile", step3, jobRepository, tx))
.next(taskletStep("calcRecruit", step4, jobRepository, tx))
.next(taskletStep("calcMaintain", step5, jobRepository, tx))
.next(taskletStep("chargebackException", step6, jobRepository, tx))
.next(taskletStep("calcOverride", step7, jobRepository, tx))
.next(taskletStep("aggregate", step8, jobRepository, tx))
.next(taskletStep("accountingEntryGenerate", step9, jobRepository, tx))
.next(taskletStep("yearEndIncomeAggregate", step10, jobRepository, tx))
.start(taskletStep("receiveData", step1, jobRepository, tx))
.next(taskletStep("transformData", step2, jobRepository, tx))
.next(taskletStep("reconcile", step3, jobRepository, tx))
.next(taskletStep("calcRecruit", step4, jobRepository, tx))
.next(taskletStep("calcMaintain", step5, jobRepository, tx))
.next(taskletStep("chargebackException", step6, jobRepository, tx))
.next(taskletStep("calcOverride", step7, jobRepository, tx))
.next(taskletStep("aggregate", step8, jobRepository, tx))
.next(taskletStep("accountingEntryGenerate", step9, jobRepository, tx))
.next(taskletStep("yearEndIncomeAggregate", step10, jobRepository, tx))
.next(taskletStep("withholdingTaxQuarterly", step11, jobRepository, tx))
.next(taskletStep("vatReportQuarterly", step12, jobRepository, tx))
.build();
}