feat: ga-core + ga-api + ga-batch + V13-V15 + Docker + frontend skeleton
ga-core (22 tables): - user/role: VO + Mapper + XML (login + RBAC) - org: Grade, Organization (CTE recursive tree), Agent + history - product: InsuranceCompany, Product, Contract - rule: CommissionRate, PayoutRule, OverrideRule, ChargebackRule, ExceptionTypeCode - receive: CompanyProfile, FieldMapping, CodeMapping, RawCommissionData, ParseError - ledger: Recruit, Maintain, Exception (batch insert + cursor) - settle: SettleMaster (UPSERT), Override, Chargeback, Payment, Reconciliation, BatchJobLog - All XMLs use EncryptTypeHandler for PII fields ga-api: - AuthController: login (lock on N fails), refresh, me, password, logout - Domain controllers: Agent, Organization, Contract, Company, Product, Rule, Receive, Ledger (recruit/maintain/exception + approve), Settle (confirm/hold/release), Payment, User, Role (matrix), BatchTrigger - All use @RequirePermission + @DataChangeLog ga-batch: - MonthlySettlementJob: 8 Steps (receiveData, transformData, reconcile, calcRecruit, calcMaintain, chargebackException, calcOverride, aggregate) - DataReceiver strategy + ManualReceiver, MappingEngine stub - CommissionCalculator (pct/tax via MoneyUtil), JobLauncherController DB V13~V15: - V13: 14 indexes (settle_master, ledgers, contract, chargeback, payment, raw, logs) - V14: create_monthly_partition() helper function - V15: v_agent_monthly_summary, v_org_settle_summary, v_chargeback_risk views Infra: - docker-compose: postgres + redis + api + batch + frontend - Multi-stage Dockerfile (gradle build → JRE) ga-frontend (skeleton): - Vite + React 18 + TypeScript + AntD 5 + AG Grid + React Query + Zustand - API request layer (axios + JWT), LoginPage, MainLayout (dynamic menu), Dashboard - nginx.conf for /api proxying
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# GA 수수료 정산 솔루션
|
||||
|
||||
법인보험대리점(GA) 수수료 정산 시스템.
|
||||
법인보험대리점(GA) 수수료 정산 시스템 — Multi-module Spring Boot + React.
|
||||
|
||||
## 기술 스택
|
||||
|
||||
@@ -8,106 +8,147 @@
|
||||
|------|------|
|
||||
| Backend | Java 17, Spring Boot 3.2, Spring Security, Spring Batch |
|
||||
| ORM | MyBatis 3 + PageHelper |
|
||||
| DB | PostgreSQL 14+ |
|
||||
| DB | PostgreSQL 16 |
|
||||
| Cache | Redis 7 |
|
||||
| Build | Gradle 멀티모듈 |
|
||||
| Frontend | (예정) React 18 + Ant Design 5 + AG Grid |
|
||||
| Frontend | React 18 + Vite + TypeScript + Ant Design 5 + AG Grid + React Query + Zustand |
|
||||
| Infra | Docker Compose, Nginx |
|
||||
|
||||
## 모듈 구조
|
||||
|
||||
```
|
||||
ga-commission-system/
|
||||
├── ga-common/ # 공통 프레임워크 (인증/권한/로그/엑셀/공통코드/메뉴 등)
|
||||
├── ga-core/ # 도메인 코어 (VO, Mapper, SQL) — 예정
|
||||
├── ga-api/ # REST API (실행 모듈)
|
||||
├── ga-batch/ # Spring Batch (실행 모듈) — 예정
|
||||
└── ga-admin/ # 관리자 기능 — 예정
|
||||
├── ga-common/ # 공통 프레임워크 (인증/권한/로그/엑셀/공통코드/메뉴)
|
||||
├── ga-core/ # 도메인 코어 (VO, Mapper, SQL)
|
||||
├── ga-api/ # REST API (포트 8080)
|
||||
├── ga-batch/ # Spring Batch (포트 8081)
|
||||
├── ga-admin/ # 관리자 라이브러리
|
||||
└── ga-frontend/ # React SPA (포트 3000)
|
||||
```
|
||||
|
||||
## 진행 상황
|
||||
|
||||
- [x] 1단계 — 프로젝트 뼈대 + DB 마이그레이션
|
||||
- [x] Gradle 멀티모듈 + 5개 모듈
|
||||
- [x] Flyway V1~V12 (조직/상품/규정/수신/원장/정산/배치/공통코드/메뉴/시스템/초기데이터)
|
||||
|
||||
- [x] **ga-common — 공통 프레임워크 (완성)**
|
||||
- [x] `model/` — ApiResponse, PageResponse, SearchParam, TreeNode
|
||||
- [x] `exception/` — ErrorCode, BizException, GlobalExceptionHandler
|
||||
- [x] `annotation/` — @RequirePermission, @DataChangeLog, @ExcelColumn, @Mask
|
||||
- [x] `aop/` — Permission/DataChangeLog/ApiLog Aspect
|
||||
- [x] `auth/` — JwtTokenProvider, JwtAuthFilter, LoginUser
|
||||
- [x] `security/` — SecurityConfig, JwtAuthEntryPoint, AccessDeniedHandler
|
||||
- [x] `config/` — MyBatis/Redis/Swagger/Web/Async Config
|
||||
- [x] `mybatis/` — BaseMapper, EncryptTypeHandler, JsonTypeHandler, AuditInterceptor
|
||||
- [x] `code/` — CommonCodeService(Redis 캐시) + Controller + Mapper
|
||||
- [x] `menu/` — MenuService, PermissionChecker, MenuTreeBuilder + Controller
|
||||
- [x] `excel/` — 대용량 Export(SXSSF+Cursor) / Import(SAX+배치)
|
||||
- [x] `file/` — FileService + Controller
|
||||
- [x] `system/` — SystemConfig, DataChangeLog, ApiAccessLog Service
|
||||
- [x] `notification/` — NotificationService + Controller
|
||||
- [x] `util/` — DateUtil, MoneyUtil, MaskUtil, EncryptUtil, SecurityUtil
|
||||
- [x] `grid/` — GridSearchParam, GridResponse (AG Grid 서버사이드)
|
||||
|
||||
- [ ] ga-core (예정) — 22개 테이블의 VO/Mapper/XML
|
||||
- [ ] ga-api (예정) — Controller + Service
|
||||
- [ ] ga-batch (예정) — MonthlySettlementJob 8 Step
|
||||
- [ ] ga-frontend (예정) — React + AntD + AG Grid
|
||||
|
||||
## 실행 (DB만 우선 검증)
|
||||
## 빠른 시작 (Docker Compose)
|
||||
|
||||
```bash
|
||||
# PostgreSQL & Redis 기동 후 (예: docker compose)
|
||||
psql -h localhost -U ga -c "CREATE DATABASE ga"
|
||||
docker compose up -d --build
|
||||
# 프론트: http://localhost:3000
|
||||
# API: http://localhost:8080/swagger-ui.html
|
||||
# Batch: http://localhost:8081 (내부)
|
||||
```
|
||||
|
||||
# Flyway 마이그레이션은 ga-api 부팅 시 자동 실행됨
|
||||
# (ga-api의 spring.datasource 와 Flyway 설정에 따름)
|
||||
## 로컬 개발
|
||||
|
||||
### 1. PostgreSQL + Redis 기동
|
||||
```bash
|
||||
docker compose up -d postgres redis
|
||||
```
|
||||
|
||||
### 2. ga-api 실행 (Flyway 자동 마이그레이션)
|
||||
```bash
|
||||
./gradlew :ga-api:bootRun
|
||||
```
|
||||
|
||||
## 핵심 사용 예시
|
||||
### 3. ga-batch 실행
|
||||
```bash
|
||||
./gradlew :ga-batch:bootRun
|
||||
```
|
||||
|
||||
### 1) 컨트롤러 표준 패턴
|
||||
### 4. 프론트 실행
|
||||
```bash
|
||||
cd ga-frontend
|
||||
npm install
|
||||
npm run dev
|
||||
# http://localhost:3000
|
||||
```
|
||||
|
||||
## 주요 기능
|
||||
|
||||
### 백엔드
|
||||
- **인증/권한**: JWT (HS256), 메뉴×권한 RBAC, BCrypt 비밀번호
|
||||
- **공통코드**: Redis 캐시, 시스템코드 잠금, REST CRUD
|
||||
- **메뉴**: 트리 구조, 사용자별 동적 메뉴 + 권한 매트릭스
|
||||
- **엑셀**: SXSSF+Cursor 다운로드(100만건), SAX+배치 업로드(70만건)
|
||||
- **로그**: 로그인/API/데이터변경 자동 기록 (비동기)
|
||||
- **암호화**: AES-256 CBC (resident_no, account_no)
|
||||
|
||||
### 도메인
|
||||
- **조직**: 트리 구조, CTE 재귀, 인사 이력
|
||||
- **계약**: 보험사/상품/계약 관리
|
||||
- **수수료 규정**: 보험사율, 지급율, 오버라이드, 환수, 예외코드
|
||||
- **원장**: 모집/유지/예외 (PageHelper, AG Grid 서버사이드 가능)
|
||||
- **정산**: 8 Step 배치 (수신→변환→대사→모집→유지→환수/예외→오버라이드→집계)
|
||||
- **지급**: 이체파일 생성, 상태 추적
|
||||
|
||||
### 정산 배치 8 Step
|
||||
1. **receiveData** — 보험사별 DataReceiver → raw_commission_data 적재
|
||||
2. **transformData** — MappingEngine으로 표준 변환
|
||||
3. **reconcile** — 보험사 통보액 vs 시스템 계산액 대사
|
||||
4. **calcRecruit** — 모집수수료 (계약시점 규정 적용)
|
||||
5. **calcMaintain** — 유지수수료 (납입주기 매칭)
|
||||
6. **chargebackException** — 환수 자동생성
|
||||
7. **calcOverride** — 조직 트리 오버라이드
|
||||
8. **aggregate** — 통합 집계 → settle_master UPSERT (3.3% 세금)
|
||||
|
||||
## 신입 개발자 표준 패턴
|
||||
|
||||
### Backend (5분)
|
||||
```java
|
||||
@RestController @RequestMapping("/api/agents")
|
||||
@RequiredArgsConstructor
|
||||
public class AgentController {
|
||||
private final AgentService service;
|
||||
// 1) VO (XxxVO + XxxResp + XxxSaveReq + XxxSearchParam)
|
||||
@Data
|
||||
public class FooSearchParam extends SearchParam { }
|
||||
|
||||
// 2) Mapper Interface + XML
|
||||
@Mapper
|
||||
public interface FooMapper {
|
||||
List<FooResp> selectList(FooSearchParam p);
|
||||
}
|
||||
|
||||
// 3) Service
|
||||
@Service @RequiredArgsConstructor
|
||||
public class FooService {
|
||||
private final FooMapper mapper;
|
||||
public PageResponse<FooResp> list(FooSearchParam p) {
|
||||
p.startPage();
|
||||
return PageResponse.of(mapper.selectList(p));
|
||||
}
|
||||
}
|
||||
|
||||
// 4) Controller
|
||||
@RestController @RequestMapping("/api/foos") @RequiredArgsConstructor
|
||||
public class FooController {
|
||||
private final FooService service;
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "ORG_AGENT", perm = "READ")
|
||||
public ApiResponse<PageResponse<AgentResp>> list(AgentSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
@RequirePermission(menu = "FOO", perm = "READ")
|
||||
public ApiResponse<PageResponse<FooResp>> list(FooSearchParam p) {
|
||||
return ApiResponse.ok(service.list(p));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2) 서비스 표준 패턴
|
||||
```java
|
||||
public PageResponse<AgentResp> list(AgentSearchParam param) {
|
||||
param.startPage(); // PageHelper
|
||||
return PageResponse.of(mapper.selectList(param));
|
||||
}
|
||||
```
|
||||
|
||||
### 3) 공통코드 검증
|
||||
```java
|
||||
codeService.validateCode("AGENT_STATUS", req.getStatus()); // 없으면 예외
|
||||
String name = codeService.getCodeName("AGENT_STATUS", "ACTIVE"); // "정상"
|
||||
```
|
||||
|
||||
### 4) 대용량 엑셀 다운로드
|
||||
```java
|
||||
@GetMapping("/export")
|
||||
@RequirePermission(menu = "LEDGER", perm = "EXPORT")
|
||||
public void export(LedgerSearchParam param, HttpServletResponse res) {
|
||||
excelService.exportLargeExcel("모집수수료원장",
|
||||
RecruitLedgerExcelVO.class,
|
||||
() -> ledgerMapper.selectCursor(param), res);
|
||||
}
|
||||
```
|
||||
|
||||
## 보안
|
||||
|
||||
- JWT (HS256) — 액세스 2시간, 리프레시 7일
|
||||
- AES-256 CBC 암호화 (`resident_no`, `account_no`) — `EncryptTypeHandler` 자동 적용
|
||||
- RBAC — `role_menu_permission` 기반 메뉴×권한 매트릭스
|
||||
- AES-256 CBC 암호화 (자동 적용 — `EncryptTypeHandler`)
|
||||
- RBAC — `role_menu_permission` 매트릭스
|
||||
- `@DataChangeLog` — 데이터 변경 이력 AOP 자동
|
||||
- API 접근 로그 — 비동기 저장
|
||||
|
||||
## DB 마이그레이션
|
||||
- V1~V8: 도메인 스키마 + 초기 데이터
|
||||
- V9~V12: 공통코드/메뉴/시스템관리 + 초기 데이터
|
||||
- V13: 인덱스 최적화
|
||||
- V14: 파티셔닝 helper 함수
|
||||
- V15: 통계/리포트 뷰 (v_agent_monthly_summary, v_org_settle_summary, v_chargeback_risk)
|
||||
|
||||
## 진행 상황
|
||||
|
||||
- [x] 1단계 — 프로젝트 뼈대 + DB (V1~V15)
|
||||
- [x] **ga-common** — 공통 프레임워크 (model/exception/auth/security/code/menu/excel/file/system/notification)
|
||||
- [x] **ga-core** — 22개 테이블의 VO/Mapper/XML
|
||||
- [x] **ga-api** — Auth + 도메인 컨트롤러 (org/product/rule/receive/ledger/settle/payment/system)
|
||||
- [x] **ga-batch** — MonthlySettlementJob 8 Step
|
||||
- [x] **Docker** — docker-compose + multi-stage Dockerfile + nginx
|
||||
- [x] **ga-frontend** — Vite + React + AntD + React Query 스켈레톤 (로그인 + 대시보드 + 동적 메뉴)
|
||||
|
||||
## 향후 확장
|
||||
- **프론트 페이지 추가**: menu 테이블 등록 → React 페이지 구현 → 동적 라우팅 적용
|
||||
- **신규 보험사**: company_profile + company_field_mapping 등록 + DataReceiver 구현
|
||||
- **신규 정산 규정**: commission_rate/payout_rule/override_rule/chargeback_rule 의 effective_from 만 다른 버전으로 추가
|
||||
|
||||
Reference in New Issue
Block a user