优化
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { http, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
|
||||
import type { CreatePayableSettlementPayload, CreateReceivableSettlementPayload, CreateReconciliationPayload, CreateSettlementPaymentPayload, FinanceAccountEntry, FinanceAccountSummary, FinanceBillDetail, FinanceBillLine, FinanceBillResource, FinanceBillRevision, FinanceCostResource, FinanceCustomerAccountReadModel, FinanceCustomerTerms, FinanceFeePoolItem, FinanceFeeSourceDetail, FinanceFeeSourceSummary, FinanceLedgerEntry, FinancePayableSettlement, FinanceReceivableSettlement, FinanceReceiptResource, FinanceReconciliationDetail, FinanceSettlementDetail, FinanceSettlementLine, FinanceStatementReadModel, FinanceVoucherResource, ReconciliationActionPayload } from '../types'
|
||||
import type { CreatePayableSettlementPayload, CreateReceivableSettlementPayload, CreateReconciliationPayload, CreateSettlementPaymentPayload, FinanceAccountEntry, FinanceAccountSummary, FinanceBillDetail, FinanceBillLine, FinanceBillResource, FinanceBillRevision, FinanceCostResource, FinanceCustomerAccountReadModel, FinanceCustomerTerms, FinanceFeePoolItem, FinanceFeeSourceDetail, FinanceFeeSourceSummary, FinanceLedgerEntry, FinancePayableSettlement, FinanceReceivableSettlement, FinanceReceiptResource, FinanceReconciliationDetail, FinanceSettlementDetail, FinanceSettlementLine, FinanceStatementReadModel, FinanceVoucherResource, ReceivableStatisticsResult, ReconciliationActionPayload } from '../types'
|
||||
|
||||
const basePath = '/platform/finance/v1'
|
||||
export interface FinanceCustomerAccountSummaryResource {
|
||||
@@ -18,7 +18,7 @@ export const financePhase1Capabilities = {
|
||||
accountLedger: true,
|
||||
feeSourceDetail: true,
|
||||
feeSourceReview: true,
|
||||
feeSourceSettlementInclusion: true,
|
||||
feeSourceEditReviewLifecycle: true,
|
||||
reconciliationCreate: true,
|
||||
reconciliationActions: true,
|
||||
receivableSettlementCreate: true,
|
||||
@@ -26,6 +26,27 @@ export const financePhase1Capabilities = {
|
||||
settlementDetail: true,
|
||||
settlementPayment: true,
|
||||
} as const
|
||||
|
||||
export async function getReceivableStatistics(params: { month: string; customerId?: string; page?: number; pageSize?: number }): Promise<ReceivableStatisticsResult> {
|
||||
const response = await http.get<ApiEnvelope<RawResource>, ApiEnvelope<RawResource>>(`${basePath}/receivable-statistics`, { params: {
|
||||
month: params.month,
|
||||
customerId: params.customerId?.trim() || undefined,
|
||||
page: params.page ?? 1,
|
||||
pageSize: params.pageSize ?? 20,
|
||||
} })
|
||||
const item = unwrapApiResponse(response)
|
||||
return {
|
||||
statisticsMonth: stringValue(item.statisticsMonth), currency: 'CNY',
|
||||
totalReceivable: stringValue(item.totalReceivable), totalReceived: stringValue(item.totalReceived),
|
||||
totalOutstanding: stringValue(item.totalOutstanding), totalCustomers: numberValue(item.totalCustomers),
|
||||
page: numberValue(item.page), pageSize: numberValue(item.pageSize),
|
||||
records: (Array.isArray(item.records) ? item.records : []).map((value) => {
|
||||
const row = value as RawResource
|
||||
return { customerId: stringValue(row.customerId), customerName: stringValue(row.customerName), currency: 'CNY' as const,
|
||||
totalReceivable: stringValue(row.totalReceivable), totalReceived: stringValue(row.totalReceived), totalOutstanding: stringValue(row.totalOutstanding) }
|
||||
}),
|
||||
}
|
||||
}
|
||||
function idempotencyKey(operation: string) { return `finance-${operation}-${Date.now()}-${Math.random().toString(36).slice(2)}` }
|
||||
type RawResource = Record<string, unknown>
|
||||
function stringValue(value: unknown) { return value == null ? '' : String(value) }
|
||||
@@ -122,8 +143,7 @@ export async function listFinanceFeeSources(params: {
|
||||
customerId?: string
|
||||
direction?: 'RECEIVABLE' | 'PAYABLE'
|
||||
status?: string
|
||||
reviewStatus?: 'PENDING' | 'APPROVED' | 'REJECTED'
|
||||
settlementIncluded?: boolean
|
||||
reviewStatus?: 'DRAFT' | 'PENDING' | 'APPROVED' | 'REJECTED'
|
||||
statementGenerated?: boolean
|
||||
businessDateFrom?: string
|
||||
businessDateTo?: string
|
||||
@@ -132,7 +152,7 @@ export async function listFinanceFeeSources(params: {
|
||||
const query = {
|
||||
page: params.page ?? 1, pageSize: params.size ?? 20, customerId: params.customerId || undefined,
|
||||
direction: params.direction || undefined, status: params.status || undefined,
|
||||
reviewStatus: params.reviewStatus || undefined, settlementIncluded: params.settlementIncluded,
|
||||
reviewStatus: params.reviewStatus || undefined,
|
||||
statementGenerated: params.statementGenerated, businessDateFrom: params.businessDateFrom || undefined,
|
||||
businessDateTo: params.businessDateTo || undefined, keyword: params.keyword?.trim() || undefined,
|
||||
}
|
||||
@@ -159,7 +179,7 @@ function normalizeFeeSourceSummary(item: RawResource): FinanceFeeSourceSummary {
|
||||
orderId: nullableString(item.orderId), inboundId: nullableString(item.inboundId), inboundCode: stringValue(item.inboundCode),
|
||||
containerId: nullableString(item.containerId), containerNo: stringValue(item.containerNo), businessDate: stringValue(item.businessDate),
|
||||
feeItemName: stringValue(item.feeItemName), quantity: nullableNumber(item.quantity), unitPrice: nullableNumber(item.unitPrice), amount: numberValue(item.amount), currency: 'CNY',
|
||||
reviewStatus: stringValue(item.reviewStatus) as FinanceFeeSourceDetail['reviewStatus'], settlementIncluded: Boolean(item.settlementIncluded),
|
||||
reviewStatus: stringValue(item.reviewStatus) as FinanceFeeSourceDetail['reviewStatus'],
|
||||
sourceStatus: stringValue(item.sourceStatus), status: stringValue(item.sourceStatus), statementGenerated: Boolean(item.statementGenerated),
|
||||
createdAt: stringValue(item.businessDate),
|
||||
}
|
||||
@@ -168,7 +188,7 @@ function normalizeFeeSourceSummary(item: RawResource): FinanceFeeSourceSummary {
|
||||
function normalizeFeeSourceDetail(item: RawResource): FinanceFeeSourceDetail {
|
||||
return {
|
||||
...normalizeFeeSourceSummary(item), sourceFeeId: stringValue(item.sourceFeeId),
|
||||
reviewReason: stringValue(item.reviewReason) || undefined, settlementReason: stringValue(item.settlementReason) || undefined,
|
||||
reviewReason: stringValue(item.reviewReason) || undefined,
|
||||
sourceHash: stringValue(item.sourceHash) || undefined, operationVersion: numberValue(item.operationVersion),
|
||||
operationLogs: (Array.isArray(item.operationLogs) ? item.operationLogs : []).map((entry) => { const row = entry as RawResource; return { occurredAt: stringValue(row.occurredAt), action: stringValue(row.action), operatorName: stringValue(row.operatorName), result: stringValue(row.result), remark: stringValue(row.remark) || undefined } }),
|
||||
}
|
||||
@@ -178,8 +198,20 @@ export async function reviewFinanceFeeSource(feeSourceId: string, payload: { act
|
||||
const response = await http.post<ApiEnvelope<RawResource>, ApiEnvelope<RawResource>>(`${basePath}/fee-sources/${feeSourceId}/review`, payload, mutationHeaders('fee-source-review'))
|
||||
return normalizeFeeSourceDetail(unwrapApiResponse(response))
|
||||
}
|
||||
export async function updateFinanceFeeSourceSettlementInclusion(feeSourceId: string, payload: { included: boolean; reason: string; expectedVersion: number }): Promise<FinanceFeeSourceDetail> {
|
||||
const response = await http.put<ApiEnvelope<RawResource>, ApiEnvelope<RawResource>>(`${basePath}/fee-sources/${feeSourceId}/settlement-inclusion`, payload, mutationHeaders('fee-source-settlement'))
|
||||
export async function editFinanceFeeSource(feeSourceId: string, payload: { amount: number; reason: string; expectedVersion: number }): Promise<FinanceFeeSourceDetail> {
|
||||
const response = await http.put<ApiEnvelope<RawResource>, ApiEnvelope<RawResource>>(`${basePath}/fee-sources/${feeSourceId}`, payload, mutationHeaders('fee-source-edit'))
|
||||
return normalizeFeeSourceDetail(unwrapApiResponse(response))
|
||||
}
|
||||
export async function submitFinanceFeeSource(feeSourceId: string, payload: { reason: string; expectedVersion: number }): Promise<FinanceFeeSourceDetail> {
|
||||
const response = await http.post<ApiEnvelope<RawResource>, ApiEnvelope<RawResource>>(`${basePath}/fee-sources/${feeSourceId}/submit`, payload, mutationHeaders('fee-source-submit'))
|
||||
return normalizeFeeSourceDetail(unwrapApiResponse(response))
|
||||
}
|
||||
export async function adjustFinanceFeeSource(feeSourceId: string, payload: { amount: number; reason: string; expectedVersion: number }): Promise<FinanceFeeSourceDetail> {
|
||||
const response = await http.post<ApiEnvelope<RawResource>, ApiEnvelope<RawResource>>(`${basePath}/fee-sources/${feeSourceId}/adjust`, payload, mutationHeaders('fee-source-adjust'))
|
||||
return normalizeFeeSourceDetail(unwrapApiResponse(response))
|
||||
}
|
||||
export async function voidFinanceFeeSource(feeSourceId: string, payload: { reason: string; expectedVersion: number }): Promise<FinanceFeeSourceDetail> {
|
||||
const response = await http.post<ApiEnvelope<RawResource>, ApiEnvelope<RawResource>>(`${basePath}/fee-sources/${feeSourceId}/void`, payload, mutationHeaders('fee-source-void'))
|
||||
return normalizeFeeSourceDetail(unwrapApiResponse(response))
|
||||
}
|
||||
function normalizeReconciliationDetail(item: RawResource): FinanceReconciliationDetail {
|
||||
@@ -197,7 +229,7 @@ function normalizeReconciliationDetail(item: RawResource): FinanceReconciliation
|
||||
return {
|
||||
id: stringValue(item.statementId), billNo: stringValue(item.statementNo), customerId: stringValue(item.customerId), customerName: stringValue(item.customerName),
|
||||
billDate: stringValue(item.periodEnd), dueDate: '', periodStart: stringValue(item.periodStart), periodEnd: stringValue(item.periodEnd), creditDays: numberValue(item.creditDays), currency: 'CNY',
|
||||
totalAmount: numberValue(item.totalReceivable), paidAmount: numberValue(item.receivedAmount), outstandingAmount: numberValue(item.outstandingAmount), settled: Boolean(item.settled), status: stringValue(item.status) as FinanceBillResource['status'], version: numberValue(item.version), remark: stringValue(item.remark), createdBy: stringValue(item.createdBy), createdByName: stringValue(item.createdByName), createdAt: stringValue(item.createdAt), updatedBy: stringValue(item.updatedBy), updatedByName: stringValue(item.updatedByName), updatedAt: stringValue(item.updatedAt), lines,
|
||||
totalAmount: numberValue(item.totalReceivable), paidAmount: numberValue(item.receivedAmount), outstandingAmount: numberValue(item.outstandingAmount), settled: Boolean(item.settled), status: stringValue(item.status) as FinanceBillResource['status'], version: numberValue(item.version), customerConfirmationStatus: stringValue(item.customerConfirmationStatus) as FinanceBillResource['customerConfirmationStatus'], customerConfirmedBy: stringValue(item.customerConfirmedBy) || undefined, customerConfirmedByName: stringValue(item.customerConfirmedByName) || undefined, customerConfirmedAt: stringValue(item.customerConfirmedAt) || undefined, remark: stringValue(item.remark), createdBy: stringValue(item.createdBy), createdByName: stringValue(item.createdByName), createdAt: stringValue(item.createdAt), updatedBy: stringValue(item.updatedBy), updatedByName: stringValue(item.updatedByName), updatedAt: stringValue(item.updatedAt), lines,
|
||||
paymentHistory: (Array.isArray(item.paymentHistory) ? item.paymentHistory : []).map((entry) => { const row = entry as RawResource; return { transactionId: stringValue(row.transactionId), transactionType: stringValue(row.transactionType), transactionDate: stringValue(row.transactionDate), amount: numberValue(row.amount), method: stringValue(row.method), referenceNo: stringValue(row.referenceNo), voucherFileIds: Array.isArray(row.voucherFileIds) ? row.voucherFileIds.map(stringValue) : [], createdBy: stringValue(row.createdBy), createdByName: stringValue(row.createdByName), occurredAt: stringValue(row.occurredAt ?? row.createdAt), remark: stringValue(row.remark) || undefined } }),
|
||||
revisions: (Array.isArray(item.revisions) ? item.revisions : []).map((entry) => { const row = entry as RawResource; return { revisionNo: numberValue(row.revisionNo), action: stringValue(row.action), beforeAmount: numberValue(row.beforeAmount), afterAmount: numberValue(row.afterAmount), reason: stringValue(row.reason) || undefined, operatorId: stringValue(row.operatorId), operatorName: stringValue(row.operatorName), occurredAt: stringValue(row.occurredAt) } }),
|
||||
}
|
||||
@@ -223,7 +255,7 @@ function normalizeSettlementLine(item: RawResource): FinanceSettlementLine {
|
||||
supplierId: nullableString(item.supplierId), supplierName: stringValue(item.supplierName), orderId: nullableString(item.orderId), orderNo: stringValue(item.orderNo),
|
||||
inboundId: nullableString(item.inboundId), inboundCode: stringValue(item.inboundCode), containerId: nullableString(item.containerId), containerNo: stringValue(item.containerNo),
|
||||
businessDate: stringValue(item.businessDate), feeItemName: stringValue(item.feeItemName), quantity: nullableNumber(item.quantity), unitPrice: nullableNumber(item.unitPrice),
|
||||
amount: numberValue(item.amount), currency: 'CNY', reviewStatus: stringValue(item.reviewStatus) as FinanceSettlementLine['reviewStatus'], settlementIncluded: Boolean(item.settlementIncluded), sourceStatus: stringValue(item.sourceStatus), statementGenerated: Boolean(item.statementGenerated),
|
||||
amount: numberValue(item.amount), currency: 'CNY', reviewStatus: stringValue(item.reviewStatus) as FinanceSettlementLine['reviewStatus'], sourceStatus: stringValue(item.sourceStatus), statementGenerated: Boolean(item.statementGenerated),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,7 +294,7 @@ export async function actionFinanceSettlement(settlementId: string, payload: imp
|
||||
|
||||
export async function listFinanceStatements(customerId?: string): Promise<FinanceStatementReadModel[]> {
|
||||
const response = await http.get<ApiEnvelope<RawResource[]>, ApiEnvelope<RawResource[]>>(`${basePath}/statements`, { params: { customerId: customerId?.trim() || undefined } })
|
||||
return unwrapApiResponse(response).map((item) => ({ id: stringValue(item.statementId ?? item.id), customerId: stringValue(item.customerId), billNo: stringValue(item.statementNo ?? item.billNo), customerName: stringValue(item.customerName), billDate: stringValue(item.periodEnd ?? item.billDate), dueDate: stringValue(item.dueDate), periodStart: stringValue(item.periodStart), periodEnd: stringValue(item.periodEnd), creditDays: item.creditDays == null ? undefined : numberValue(item.creditDays), lineCount: item.lineCount == null ? undefined : numberValue(item.lineCount), sourceCount: item.sourceCount == null ? undefined : numberValue(item.sourceCount), sourceAmount: item.sourceAmount == null ? undefined : numberValue(item.sourceAmount), adjustmentAmount: item.adjustmentAmount == null ? undefined : numberValue(item.adjustmentAmount), totalAmount: numberValue(item.totalReceivable ?? item.totalAmount), receivedAmount: numberValue(item.receivedAmount), outstandingAmount: numberValue(item.outstandingAmount), currency: 'CNY', settled: item.settled == null ? undefined : Boolean(item.settled), lastReceiptAt: stringValue(item.lastReceiptAt), submittedAt: stringValue(item.submittedAt), reviewedAt: stringValue(item.reviewedAt), issuedAt: stringValue(item.issuedAt), status: stringValue(item.status) as FinanceStatementReadModel['status'], version: numberValue(item.version), remark: stringValue(item.remark), createdBy: stringValue(item.createdBy), createdByName: stringValue(item.createdByName), createdAt: stringValue(item.createdAt), updatedBy: stringValue(item.updatedBy), updatedByName: stringValue(item.updatedByName), updatedAt: stringValue(item.updatedAt) }))
|
||||
return unwrapApiResponse(response).map((item) => ({ id: stringValue(item.statementId ?? item.id), customerId: stringValue(item.customerId), billNo: stringValue(item.statementNo ?? item.billNo), customerName: stringValue(item.customerName), billDate: stringValue(item.periodEnd ?? item.billDate), dueDate: stringValue(item.dueDate), periodStart: stringValue(item.periodStart), periodEnd: stringValue(item.periodEnd), creditDays: item.creditDays == null ? undefined : numberValue(item.creditDays), lineCount: item.lineCount == null ? undefined : numberValue(item.lineCount), sourceCount: item.sourceCount == null ? undefined : numberValue(item.sourceCount), sourceAmount: item.sourceAmount == null ? undefined : numberValue(item.sourceAmount), adjustmentAmount: item.adjustmentAmount == null ? undefined : numberValue(item.adjustmentAmount), totalAmount: numberValue(item.totalReceivable ?? item.totalAmount), receivedAmount: numberValue(item.receivedAmount), outstandingAmount: numberValue(item.outstandingAmount), currency: 'CNY', settled: item.settled == null ? undefined : Boolean(item.settled), lastReceiptAt: stringValue(item.lastReceiptAt), submittedAt: stringValue(item.submittedAt), reviewedAt: stringValue(item.reviewedAt), issuedAt: stringValue(item.issuedAt), status: stringValue(item.status) as FinanceStatementReadModel['status'], version: numberValue(item.version), customerConfirmationStatus: stringValue(item.customerConfirmationStatus) as FinanceStatementReadModel['customerConfirmationStatus'], customerConfirmedBy: stringValue(item.customerConfirmedBy) || undefined, customerConfirmedByName: stringValue(item.customerConfirmedByName) || undefined, customerConfirmedAt: stringValue(item.customerConfirmedAt) || undefined, remark: stringValue(item.remark), createdBy: stringValue(item.createdBy), createdByName: stringValue(item.createdByName), createdAt: stringValue(item.createdAt), updatedBy: stringValue(item.updatedBy), updatedByName: stringValue(item.updatedByName), updatedAt: stringValue(item.updatedAt) }))
|
||||
}
|
||||
|
||||
export async function listFinanceReceivableSettlements(customerId?: string): Promise<FinanceReceivableSettlement[]> {
|
||||
@@ -306,11 +338,6 @@ export async function updateFinanceCustomerTerms(customerId: string, payload: {
|
||||
return normalizeCustomerTerms(unwrapApiResponse(response), customerId)
|
||||
}
|
||||
|
||||
export async function createFinanceBill(payload: Record<string, unknown>) {
|
||||
const response = await http.post<ApiEnvelope<FinanceBillResource>, ApiEnvelope<FinanceBillResource>>(`${basePath}/bills`, { ...payload }, mutationHeaders('bill'))
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
|
||||
export async function getFinanceBill(billId: string) {
|
||||
const response = await http.get<ApiEnvelope<RawResource>, ApiEnvelope<RawResource>>(`${basePath}/bills/${billId}`)
|
||||
return normalizeBillDetail(unwrapApiResponse(response))
|
||||
@@ -369,8 +396,3 @@ export async function createFinanceCost(payload: Record<string, unknown>, vouche
|
||||
const response = await http.post<ApiEnvelope<FinanceCostResource>, ApiEnvelope<FinanceCostResource>>(`${basePath}/cost-entries`, { ...payload, currency: 'CNY', voucherFileIds }, { headers: { 'Idempotency-Key': idempotencyKey('cost') } })
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
|
||||
export async function issueFinanceBill(billId: string, expectedVersion: number) {
|
||||
const response = await http.post<ApiEnvelope<FinanceBillResource>, ApiEnvelope<FinanceBillResource>>(`${basePath}/bills/${billId}/issue`, { expectedVersion }, mutationHeaders('bill-issue'))
|
||||
return unwrapApiResponse(response)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user