feat: P12(#2) 지급대상건 구성·수정 — 정산월 지급대상 배치 구성/확정 (PL 자율진행)
incar 지급대상건구성/수정/조회 대응. 기존 settle_master 건별 confirm/hold 위에 정산월 단위 지급대상 배치를 구성→포함/제외 편집→확정하는 워크플로우 레이어 추가 (AccountingClose DRAFT/마감 패턴 준용, settle_master 상태는 미변경=결합 최소화). - DB(V115): payment_batch(배치 마스터, status DRAFT/FINALIZED/CANCELLED, total_count/ total_payable) + payment_batch_item(건, settle_id FK, payable 스냅샷, included/exclude_reason, UNIQUE(batch_id,settle_id)) + 메뉴 PAYMENT_TARGET(GRP_SETTLE) + 권한 READ/CREATE/UPDATE/ EXECUTE + 공통코드 PAYMENT_BATCH_STATUS. - core: PaymentBatch/Item VO/Resp/SaveReq/SearchParam/Enum + Mapper. insertFromSettleMaster (INSERT-SELECT 자동채움: settle_month·payable>0·status!=PAID) + recalcTotals + updateInclude. - api: PaymentBatchService create(자동채움+집계)/list/detail/updateItem(DRAFT만,재집계)/ finalize(포함0건 거부)/cancel/export. Controller /api/payment-batches. - frontend: PaymentTarget 화면(배치 목록 + 구성 모달 + 상세 Drawer items 포함/제외 토글 + 합계 + 확정/취소/엑셀) + api 모듈 + App 라우트. export 권한 READ로 정렬. 검증: build+test SUCCESSFUL, Flyway V115(schema v115). 라이브 e2e: 202603 create→39건 자동채움(합 15,438,386.9) → 1건 제외 → 38건 재집계(정확히 −35,079) → finalize → 확정후 수정 400 차단 → cancel. 테스트 배치 정리. 스펙 docs/DOMAIN_GAP_P12. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
import api, { PageResponse, unwrap } from './request';
|
||||
|
||||
// ── Types ──────────────────────────────────────────────────────────────────
|
||||
|
||||
export type PaymentBatchStatus = 'DRAFT' | 'FINALIZED' | 'CANCELLED';
|
||||
|
||||
export interface PaymentBatchResp extends Record<string, unknown> {
|
||||
batchId: number;
|
||||
settleMonth: string;
|
||||
batchName: string;
|
||||
status: PaymentBatchStatus;
|
||||
statusName: string;
|
||||
totalCount: number;
|
||||
totalPayable: number;
|
||||
finalizedAt?: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface PaymentBatchItemResp extends Record<string, unknown> {
|
||||
itemId: number;
|
||||
settleId: number;
|
||||
agentId: number;
|
||||
agentName: string;
|
||||
payableAmount: number;
|
||||
included: boolean;
|
||||
excludeReason?: string;
|
||||
}
|
||||
|
||||
export interface PaymentBatchDetailResp extends PaymentBatchResp {
|
||||
items: PaymentBatchItemResp[];
|
||||
}
|
||||
|
||||
export interface PaymentBatchCreateReq {
|
||||
settleMonth: string;
|
||||
batchName: string;
|
||||
}
|
||||
|
||||
export interface PaymentBatchItemUpdateReq {
|
||||
included: boolean;
|
||||
excludeReason?: string;
|
||||
}
|
||||
|
||||
export interface PaymentBatchSearchParam {
|
||||
settleMonth?: string;
|
||||
status?: string;
|
||||
pageNum?: number;
|
||||
pageSize?: number;
|
||||
}
|
||||
|
||||
// ── API ────────────────────────────────────────────────────────────────────
|
||||
|
||||
export const paymentBatchApi = {
|
||||
list: (p: PaymentBatchSearchParam) =>
|
||||
unwrap<PageResponse<PaymentBatchResp>>(
|
||||
api.get('/api/payment-batches', { params: p }),
|
||||
),
|
||||
|
||||
detail: (id: number) =>
|
||||
unwrap<PaymentBatchDetailResp>(
|
||||
api.get(`/api/payment-batches/${id}`),
|
||||
),
|
||||
|
||||
create: (req: PaymentBatchCreateReq) =>
|
||||
unwrap<number>(api.post('/api/payment-batches', req)),
|
||||
|
||||
updateItem: (id: number, itemId: number, req: PaymentBatchItemUpdateReq) =>
|
||||
unwrap<void>(api.put(`/api/payment-batches/${id}/items/${itemId}`, req)),
|
||||
|
||||
finalize: (id: number) =>
|
||||
unwrap<void>(api.put(`/api/payment-batches/${id}/finalize`)),
|
||||
|
||||
cancel: (id: number) =>
|
||||
unwrap<void>(api.put(`/api/payment-batches/${id}/cancel`)),
|
||||
|
||||
export: (id: number) =>
|
||||
api.get(`/api/payment-batches/${id}/export`, { responseType: 'blob' }),
|
||||
};
|
||||
Reference in New Issue
Block a user