53 lines
2.5 KiB
TypeScript
53 lines
2.5 KiB
TypeScript
import { getMerchantUnifiedOrders } from '../api/unifiedOrders'
|
|
import { getMerchantCustomsForOrder, isMerchantCustomsUnavailable, type MerchantCustomsContainer } from '../api/customs'
|
|
import { isCustomsOrderCandidate } from './customsEligibility'
|
|
|
|
export interface CustomsDocumentRow {
|
|
order: { id: string; orderNo: string | null; businessSummary: { inboundCode: string } }
|
|
detail: MerchantCustomsContainer
|
|
}
|
|
|
|
// Isolated from the shared order store: scan sequential pages, with at most
|
|
// four document requests in flight. Inconsistent pagination must be visible.
|
|
export async function readCustomsDocuments() {
|
|
const records: CustomsDocumentRow[] = []
|
|
const seen = new Set<string>()
|
|
let expectedTotal: number | undefined
|
|
let failedCount = 0
|
|
const size = 200
|
|
for (let page = 1; ; page += 1) {
|
|
const response = await getMerchantUnifiedOrders({ page, size, taxMode: 'TAX_REFUND', loaded: true })
|
|
const total = Number(response.total)
|
|
const pages = Number(response.pages)
|
|
if (!Number.isSafeInteger(total) || total < 0 || Number(response.page) !== page
|
|
|| Number(response.size) !== size || pages !== Math.ceil(total / size)
|
|
|| (expectedTotal !== undefined && total !== expectedTotal)
|
|
|| response.records.length !== Math.min(size, Math.max(0, total - (page - 1) * size))) {
|
|
throw new Error('订单分页数据不完整或已变化,请重新加载报关资料')
|
|
}
|
|
expectedTotal = total
|
|
for (const row of response.records) {
|
|
const id = String(row.orderId)
|
|
if (seen.has(id)) throw new Error('订单分页存在重复记录,请重新加载报关资料')
|
|
seen.add(id)
|
|
}
|
|
const candidates = response.records.filter(row => isCustomsOrderCandidate({ status: row.mainStatus, taxMode: row.taxMode ?? 'BUY_DECLARATION' }))
|
|
for (let offset = 0; offset < candidates.length; offset += 4) {
|
|
const results = await Promise.all(candidates.slice(offset, offset + 4).map(async row => {
|
|
const id = String(row.orderId)
|
|
try {
|
|
const detail = await getMerchantCustomsForOrder(id)
|
|
if (!detail.inbounds.some(item => item.orderId === id && item.taxMode === 'TAX_REFUND')) return null
|
|
return { order: { id, orderNo: row.orderNo, businessSummary: { inboundCode: row.inboundCode ?? '' } }, detail }
|
|
} catch (error) {
|
|
if (!isMerchantCustomsUnavailable(error)) failedCount += 1
|
|
return null
|
|
}
|
|
}))
|
|
for (const result of results) if (result) records.push(result)
|
|
}
|
|
if (page >= pages) break
|
|
}
|
|
return { records, failedCount }
|
|
}
|