feat: P10(#3) 환수 보험사자료 업로드 — 보험사 통보 기반 chargeback 인입 (PL 자율진행)
incar '환수보험사자료 업로드' 대응. GA는 LAPSE 계약 기반 자동환수만 있고 보험사가 통보한 환수자료(증권번호+환수금액)를 직접 인입하는 경로가 없던 갭. 신규 테이블 없이 기존 chargeback(V6) 재사용. - DB(V113): 메뉴 CHARGEBACK_DATA(환수자료관리, GRP_SETTLE, /settle/chargeback-data) + 권한 READ/CREATE/EXPORT + 역할부여. - core: ChargebackUploadExcelVO(@ExcelColumn 증권번호/환수금액/실효월/환수율) + ChargebackResp/SearchParam + ChargebackMapper.selectList/countByCondition/ existsByContractAndMonth + ContractMapper.selectByPolicyNo(contract_date 포함). - api: ChargebackUploadService.upload(settleMonth,file) — ExcelService.importLargeExcel 로 SAX 파싱, policy_no→contract/agent 해소(미존재=에러행), 중복(contract+월) skip, 실효월 YYYYMM→경과월 변환(ChronoUnit), ChargebackVO status=NEW·remain=cb_amount insertBatch. ChargebackService.list/export. ChargebackController(/api/chargebacks /upload, GET 목록, export). - frontend: ChargebackData 화면(정산월+파일 업로드, 결과 성공/스킵/에러행 표시, AG Grid 목록 합계행, 엑셀) + api/chargeback.ts + App 라우트. 검증: build SUCCESSFUL, Flyway V113(schema v113). 라이브 업로드 e2e — 정상 2건 INSERT (NEW, remain=cb_amount) + 미존재 증권번호 1건 에러행 리포트 + 중복 skip, GET 목록 200, 경과월 변환 동작 확인. 테스트 chargeback 전건 정리. 스펙 docs/DOMAIN_GAP_P10. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
import api, { PageResponse, unwrap } from './request';
|
||||
|
||||
// ── Types ──────────────────────────────────────────
|
||||
|
||||
export type ChargebackStatus = 'NEW' | 'PROCESSING' | 'SETTLED' | 'CANCELLED';
|
||||
|
||||
export interface ChargebackRow extends Record<string, unknown> {
|
||||
cbId: number;
|
||||
policyNo: string;
|
||||
agentId: number;
|
||||
agentName: string;
|
||||
contractorName: string;
|
||||
lapseMonth: number | null;
|
||||
cbRate: number | null;
|
||||
cbAmount: number;
|
||||
paidAmount: number;
|
||||
remainAmount: number;
|
||||
settleMonth: string;
|
||||
status: ChargebackStatus;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface ChargebackSearchParam {
|
||||
settleMonth?: string;
|
||||
agentId?: number;
|
||||
status?: string;
|
||||
policyNo?: string;
|
||||
pageNum?: number;
|
||||
pageSize?: number;
|
||||
}
|
||||
|
||||
export interface ChargebackUploadResult {
|
||||
successCount: number;
|
||||
errorCount: number;
|
||||
skipCount: number;
|
||||
errors: Array<{ rowNo: number; reason: string }>;
|
||||
}
|
||||
|
||||
// ── API ───────────────────────────────────────────
|
||||
|
||||
export const chargebackApi = {
|
||||
list: (p: ChargebackSearchParam) =>
|
||||
unwrap<PageResponse<ChargebackRow>>(
|
||||
api.get('/api/chargebacks', { params: p }),
|
||||
),
|
||||
|
||||
upload: (settleMonth: string, file: File) => {
|
||||
const form = new FormData();
|
||||
form.append('file', file);
|
||||
return unwrap<ChargebackUploadResult>(
|
||||
api.post(`/api/chargebacks/upload?settleMonth=${settleMonth}`, form, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
}),
|
||||
);
|
||||
},
|
||||
|
||||
export: (p: ChargebackSearchParam) =>
|
||||
api.get('/api/chargebacks/export', {
|
||||
params: p,
|
||||
responseType: 'blob',
|
||||
}),
|
||||
};
|
||||
Reference in New Issue
Block a user