feat: 추천 작업 5종 일괄 진행 (4 agents 병렬)
[A] 등록 모달 7페이지 (frontend) - CompanyList / ProductList / Commission / Payout / Override / Chargeback / ExceptionCode - ModalForm 580px, Switch Y/N 변환, 날짜 dayjs, PermissionButton - api/company/product/rule.ts 에 SaveReq + create/update/remove 추가 [B] BatchRun + RoleList 보강 (frontend) - BatchRun: 정산월/보험사 선택 → 실행, antd Steps 8단계 + 5초 폴링 (refetchInterval 자동 정지), KPI 4 카드, 최근 이력 - RoleList: 좌(역할 목록) 우(메뉴×6권한 매트릭스 체크박스), DIRECTORY 들여쓰기, 전체 토글, Modal.confirm 후 저장 [C] 이체파일 + 은행 어댑터 (api) - BankTransferFileGenerator 인터페이스 + GenericCsvTransferGenerator (UTF-8 BOM, 표준 CSV) + KbBankTransferGenerator (088, 고정폭 + 합계) - BankTransferFactory (Spring Map 빈) - TransferFileService: PENDING 조회 → 파일 생성 → file_storage 적재 → pay_file_ref 갱신 → status=SENT - POST /api/payments/transfer-file (DataChangeLog + EXPORT 권한) - account_no EncryptTypeHandler 자동 복호화 후 파일에 사용 - FileService.saveBytes(byte[]) 오버로드 추가 - PaymentList: 이체파일 생성 ModalForm + 다운로드 컬럼 [D] MockMvc Controller 테스트 (api) - AbstractControllerTest (SpringBootTest + MockMvc, JwtFilter doAnswer 로 chain 통과 처리), TestSecurityConfig (filter 빈 override) - 5 클래스 36 테스트: Agent/Contract/Ledger/Settle/User Controller - happy path + validation 400 + 권한 403 + 인증 401 검증: - ./gradlew clean build 성공 - 백엔드 단위테스트 94건 (common 33 + batch 19 + api 36 + 기타 6) 통과 - 프론트 tsc -b / vite build 통과 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
import api, { unwrap } from './request';
|
||||
|
||||
export interface BatchRunResp {
|
||||
jobLogId: number;
|
||||
}
|
||||
|
||||
export interface BatchJobLogResp {
|
||||
jobLogId: number;
|
||||
jobName: string;
|
||||
status: 'REQUESTED' | 'RUNNING' | 'COMPLETED' | 'FAILED';
|
||||
stepName?: string;
|
||||
totalCount?: number;
|
||||
successCount?: number;
|
||||
errorCount?: number;
|
||||
startedAt?: string;
|
||||
endedAt?: string;
|
||||
durationMs?: number;
|
||||
errorMessage?: string;
|
||||
}
|
||||
|
||||
export interface BatchHistoryResp {
|
||||
jobLogId: number;
|
||||
jobName: string;
|
||||
status: string;
|
||||
stepName?: string;
|
||||
startedAt?: string;
|
||||
endedAt?: string;
|
||||
durationMs?: number;
|
||||
errorMessage?: string;
|
||||
}
|
||||
|
||||
export const batchRunApi = {
|
||||
run: (settleMonth: string, companyCode?: string) =>
|
||||
unwrap<number>(
|
||||
api.post('/api/batch/settlement/run', null, {
|
||||
params: { settleMonth, companyCode },
|
||||
}),
|
||||
),
|
||||
status: (jobLogId: number) =>
|
||||
unwrap<BatchJobLogResp>(
|
||||
api.get('/api/batch/settlement/status', { params: { jobLogId } }),
|
||||
),
|
||||
history: (size = 10) =>
|
||||
unwrap<BatchHistoryResp[]>(
|
||||
api.get('/api/batch/settlement/history', { params: { size } }),
|
||||
),
|
||||
};
|
||||
@@ -12,6 +12,17 @@ export interface CompanyResp {
|
||||
isActive: string;
|
||||
}
|
||||
|
||||
export interface CompanySaveReq {
|
||||
companyCode: string;
|
||||
companyName: string;
|
||||
companyType?: string;
|
||||
bizNo?: string;
|
||||
contactName?: string;
|
||||
contactPhone?: string;
|
||||
contactEmail?: string;
|
||||
isActive: string;
|
||||
}
|
||||
|
||||
export interface CompanySearchParam {
|
||||
pageNum?: number;
|
||||
pageSize?: number;
|
||||
@@ -22,4 +33,8 @@ export interface CompanySearchParam {
|
||||
export const companyApi = {
|
||||
list: (p: CompanySearchParam) =>
|
||||
unwrap<PageResponse<CompanyResp>>(api.get('/api/companies', { params: p })),
|
||||
create: (req: CompanySaveReq) =>
|
||||
unwrap<number>(api.post('/api/companies', req)),
|
||||
update: (id: number, req: CompanySaveReq) =>
|
||||
unwrap<void>(api.put(`/api/companies/${id}`, req)),
|
||||
};
|
||||
|
||||
@@ -14,6 +14,14 @@ export interface PaymentResp {
|
||||
payStatusName?: string;
|
||||
failReason?: string;
|
||||
settleMonth: string;
|
||||
transferFileId?: number;
|
||||
}
|
||||
|
||||
export interface TransferFileResp {
|
||||
fileId: number;
|
||||
fileName: string;
|
||||
paymentCount: number;
|
||||
totalAmount: number;
|
||||
}
|
||||
|
||||
export const paymentApi = {
|
||||
@@ -21,4 +29,6 @@ export const paymentApi = {
|
||||
unwrap<PageResponse<PaymentResp>>(api.get('/api/payments', { params: p })),
|
||||
updateStatus: (paymentId: number, status: string, failReason?: string) =>
|
||||
unwrap<void>(api.put(`/api/payments/${paymentId}/status`, { status, failReason })),
|
||||
generateTransferFile: (settleMonth: string, bankCode: string) =>
|
||||
unwrap<TransferFileResp>(api.post('/api/payments/transfer-file', null, { params: { settleMonth, bankCode } })),
|
||||
};
|
||||
|
||||
@@ -14,6 +14,18 @@ export interface ProductResp {
|
||||
endDate?: string;
|
||||
}
|
||||
|
||||
export interface ProductSaveReq {
|
||||
productCode: string;
|
||||
productName: string;
|
||||
companyId: number;
|
||||
insuranceType: string;
|
||||
productGroup?: string;
|
||||
payPeriodType?: string;
|
||||
launchDate?: string;
|
||||
endDate?: string;
|
||||
isActive: string;
|
||||
}
|
||||
|
||||
export interface ProductSearchParam {
|
||||
pageNum?: number;
|
||||
pageSize?: number;
|
||||
@@ -26,4 +38,10 @@ export interface ProductSearchParam {
|
||||
export const productApi = {
|
||||
list: (p: ProductSearchParam) =>
|
||||
unwrap<PageResponse<ProductResp>>(api.get('/api/products', { params: p })),
|
||||
create: (req: ProductSaveReq) =>
|
||||
unwrap<number>(api.post('/api/products', req)),
|
||||
update: (id: number, req: ProductSaveReq) =>
|
||||
unwrap<void>(api.put(`/api/products/${id}`, req)),
|
||||
remove: (id: number) =>
|
||||
unwrap<void>(api.delete(`/api/products/${id}`)),
|
||||
};
|
||||
|
||||
@@ -13,6 +13,16 @@ export interface CommissionRateResp {
|
||||
version: number;
|
||||
}
|
||||
|
||||
export interface CommissionRateSaveReq {
|
||||
productId: number;
|
||||
commissionYear: number;
|
||||
ratePct: number;
|
||||
payMethodCond?: string;
|
||||
minPremium?: number;
|
||||
effectiveFrom?: string;
|
||||
effectiveTo?: string;
|
||||
}
|
||||
|
||||
export interface PayoutRuleResp {
|
||||
ruleId: number;
|
||||
gradeId: number;
|
||||
@@ -27,6 +37,17 @@ export interface PayoutRuleResp {
|
||||
version: number;
|
||||
}
|
||||
|
||||
export interface PayoutRuleSaveReq {
|
||||
gradeId: number;
|
||||
insuranceType: string;
|
||||
commissionYear: number;
|
||||
payoutPct: number;
|
||||
payMethodCond?: string;
|
||||
performanceGrade?: string;
|
||||
effectiveFrom?: string;
|
||||
effectiveTo?: string;
|
||||
}
|
||||
|
||||
export interface OverrideRuleResp {
|
||||
overrideId: number;
|
||||
fromGrade: number;
|
||||
@@ -41,6 +62,17 @@ export interface OverrideRuleResp {
|
||||
effectiveTo?: string;
|
||||
}
|
||||
|
||||
export interface OverrideRuleSaveReq {
|
||||
fromGrade: number;
|
||||
toGrade: number;
|
||||
overridePct: number;
|
||||
calcType?: string;
|
||||
insuranceTypeCond?: string;
|
||||
capAmount?: number;
|
||||
effectiveFrom?: string;
|
||||
effectiveTo?: string;
|
||||
}
|
||||
|
||||
export interface ChargebackRuleResp {
|
||||
cbRuleId: number;
|
||||
companyCode: string;
|
||||
@@ -55,6 +87,19 @@ export interface ChargebackRuleResp {
|
||||
effectiveTo?: string;
|
||||
}
|
||||
|
||||
export interface ChargebackRuleSaveReq {
|
||||
companyCode: string;
|
||||
insuranceType: string;
|
||||
lapseMonthFrom: number;
|
||||
lapseMonthTo: number;
|
||||
cbRate: number;
|
||||
includeOverride: string;
|
||||
installmentAllowed: string;
|
||||
maxInstallments?: number;
|
||||
effectiveFrom?: string;
|
||||
effectiveTo?: string;
|
||||
}
|
||||
|
||||
export interface ExceptionCodeResp {
|
||||
exceptionCode: string;
|
||||
exceptionName: string;
|
||||
@@ -67,13 +112,57 @@ export interface ExceptionCodeResp {
|
||||
isActive: string;
|
||||
}
|
||||
|
||||
export interface ExceptionCodeSaveReq {
|
||||
exceptionCode: string;
|
||||
exceptionName: string;
|
||||
category?: string;
|
||||
direction: string;
|
||||
autoCalcYn: string;
|
||||
approvalRequired: string;
|
||||
taxIncluded: string;
|
||||
description?: string;
|
||||
isActive: string;
|
||||
}
|
||||
|
||||
export const ruleApi = {
|
||||
commissionRates: (params?: { productId?: number; year?: number }) =>
|
||||
unwrap<CommissionRateResp[]>(api.get('/api/rules/commission-rates', { params })),
|
||||
createCommissionRate: (req: CommissionRateSaveReq) =>
|
||||
unwrap<number>(api.post('/api/rules/commission-rates', req)),
|
||||
updateCommissionRate: (id: number, req: CommissionRateSaveReq) =>
|
||||
unwrap<void>(api.put(`/api/rules/commission-rates/${id}`, req)),
|
||||
removeCommissionRate: (id: number) =>
|
||||
unwrap<void>(api.delete(`/api/rules/commission-rates/${id}`)),
|
||||
|
||||
payoutRules: (params?: { gradeId?: number; insuranceType?: string }) =>
|
||||
unwrap<PayoutRuleResp[]>(api.get('/api/rules/payout', { params })),
|
||||
createPayoutRule: (req: PayoutRuleSaveReq) =>
|
||||
unwrap<number>(api.post('/api/rules/payout', req)),
|
||||
updatePayoutRule: (id: number, req: PayoutRuleSaveReq) =>
|
||||
unwrap<void>(api.put(`/api/rules/payout/${id}`, req)),
|
||||
removePayoutRule: (id: number) =>
|
||||
unwrap<void>(api.delete(`/api/rules/payout/${id}`)),
|
||||
|
||||
overrideRules: () => unwrap<OverrideRuleResp[]>(api.get('/api/rules/override')),
|
||||
createOverrideRule: (req: OverrideRuleSaveReq) =>
|
||||
unwrap<number>(api.post('/api/rules/override', req)),
|
||||
updateOverrideRule: (id: number, req: OverrideRuleSaveReq) =>
|
||||
unwrap<void>(api.put(`/api/rules/override/${id}`, req)),
|
||||
removeOverrideRule: (id: number) =>
|
||||
unwrap<void>(api.delete(`/api/rules/override/${id}`)),
|
||||
|
||||
chargebackRules: (params?: { companyCode?: string }) =>
|
||||
unwrap<ChargebackRuleResp[]>(api.get('/api/rules/chargeback', { params })),
|
||||
createChargebackRule: (req: ChargebackRuleSaveReq) =>
|
||||
unwrap<number>(api.post('/api/rules/chargeback', req)),
|
||||
updateChargebackRule: (id: number, req: ChargebackRuleSaveReq) =>
|
||||
unwrap<void>(api.put(`/api/rules/chargeback/${id}`, req)),
|
||||
removeChargebackRule: (id: number) =>
|
||||
unwrap<void>(api.delete(`/api/rules/chargeback/${id}`)),
|
||||
|
||||
exceptionCodes: () => unwrap<ExceptionCodeResp[]>(api.get('/api/rules/exception-codes')),
|
||||
createExceptionCode: (req: ExceptionCodeSaveReq) =>
|
||||
unwrap<void>(api.post('/api/rules/exception-codes', req)),
|
||||
updateExceptionCode: (code: string, req: ExceptionCodeSaveReq) =>
|
||||
unwrap<void>(api.put(`/api/rules/exception-codes/${code}`, req)),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user