Files
client-web/src/modules/finance/api/finance.ts
T
2026-08-19 09:14:38 +08:00

72 lines
2.9 KiB
TypeScript

import { apiRequest } from '@/api/http'
import type { FinanceBillDetail, FinanceBillPage, FinanceBillQuery, FinanceCustomerConfirmationResult, FinanceReceiptRecord } from '../contracts'
import {
mapFinanceBillDetail,
mapFinanceBills,
mapFinanceReceipts,
sumDecimalStrings,
type FinanceBillDetailWire,
type FinanceBillWire,
type FinanceReceiptWire,
} from './adapters'
/** The customer scope is resolved by the authenticated merchant session. */
export async function getMerchantFinanceBills(params: FinanceBillQuery = {}): Promise<FinanceBillPage> {
const response = await apiRequest<FinanceBillWire[]>({
method: 'GET',
url: '/client/finance/v1/bills',
})
const keyword = params.keyword?.trim().toLocaleLowerCase('zh-CN')
const filtered = mapFinanceBills(response).filter((bill) => {
const matchesStatus = !params.status || bill.status === params.status
const matchesKeyword = !keyword || bill.billNo.toLocaleLowerCase('zh-CN').includes(keyword)
|| bill.customerName.toLocaleLowerCase('zh-CN').includes(keyword)
return matchesStatus && matchesKeyword
})
const page = Math.max(1, params.page ?? 1)
const size = Math.max(1, params.size ?? 20)
const start = (page - 1) * size
return {
records: filtered.slice(start, start + size),
total: filtered.length,
page,
size,
pages: Math.ceil(filtered.length / size),
totalBilledAmount: sumDecimalStrings(filtered.map((bill) => bill.totalAmount)),
totalReceivedAmount: sumDecimalStrings(filtered.map((bill) => bill.receivedAmount)),
totalOutstandingAmount: sumDecimalStrings(filtered.map((bill) => bill.outstandingAmount)),
currencyCode: 'CNY',
}
}
export async function getMerchantFinanceBill(id: string): Promise<FinanceBillDetail> {
const response = await apiRequest<FinanceBillDetailWire>({
method: 'GET',
url: `/client/finance/v1/bills/${encodeURIComponent(id)}`,
})
return mapFinanceBillDetail(response)
}
export async function getMerchantFinanceReceipts(billId: string): Promise<FinanceReceiptRecord[]> {
const response = await apiRequest<FinanceReceiptWire[]>({
method: 'GET',
url: '/client/finance/v1/receipts',
})
return mapFinanceReceipts(response, billId)
}
function confirmationIdempotencyKey(statementId: string) {
const randomPart = globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`
return `statement-confirm-${statementId}-${randomPart}`
}
export async function confirmMerchantFinanceStatement(statementId: string, expectedVersion: number,
idempotencyKey = confirmationIdempotencyKey(statementId)) {
return apiRequest<FinanceCustomerConfirmationResult>({
method: 'POST',
url: `/client/finance/v1/statements/${encodeURIComponent(statementId)}/confirm`,
headers: { 'Idempotency-Key': idempotencyKey },
data: { expectedVersion },
})
}