This commit is contained in:
2026-10-21 15:49:35 +08:00
parent e6c864a2a6
commit a4c7f8edd5
38 changed files with 466 additions and 95 deletions
@@ -8,8 +8,8 @@ describe('container arrival-time overseas API', () => {
beforeEach(() => vi.clearAllMocks())
it('queries visible containers and updates the whole-container expected arrival', async () => {
vi.mocked(http.post).mockResolvedValue({ code: '200', data: [{ sourceContainerBookingId: '9001', estimatedWarehouseArrivalAt: null, actualWarehouseArrivalAt: null, version: 0 }] })
vi.mocked(http.put).mockResolvedValue({ code: '200', data: { sourceContainerBookingId: '9001', estimatedWarehouseArrivalAt: '2026-09-25T15:31:00', actualWarehouseArrivalAt: null, version: 1 } } as never)
vi.mocked(http.post).mockResolvedValue({ code: '200', data: [{ sourceContainerBookingId: '9001', estimatedWarehouseArrivalAt: null, actualWarehouseArrivalAt: null, version: 0, planCount: 0 }] })
vi.mocked(http.put).mockResolvedValue({ code: '200', data: { sourceContainerBookingId: '9001', estimatedWarehouseArrivalAt: '2026-09-25T15:31:00', actualWarehouseArrivalAt: null, version: 1, planCount: 0 } } as never)
await listContainerArrivalTimes(['9001'])
await updateContainerExpectedArrival('9001', { estimatedWarehouseArrivalAt: '2026-09-25T15:31:00', expectedVersion: 0 })
@@ -17,4 +17,14 @@ describe('container arrival-time overseas API', () => {
expect(http.post).toHaveBeenCalledWith('/platform/v1/last-leg/orders/container-arrival-times/query', { sourceContainerBookingIds: ['9001'] })
expect(http.put).toHaveBeenCalledWith('/platform/v1/last-leg/orders/container-summaries/9001/expected-arrival', { estimatedWarehouseArrivalAt: '2026-09-25T15:31:00', expectedVersion: 0 }, { headers: { 'Idempotency-Key': expect.stringContaining('container-expected-arrival-9001-') } })
})
it('normalizes serialized plan counts and rejects unknown counts instead of showing a default', async () => {
const row = { sourceContainerBookingId: '9001', estimatedWarehouseArrivalAt: null, actualWarehouseArrivalAt: null, version: 0 }
vi.mocked(http.post).mockResolvedValue({ code: '200', data: [{ ...row, planCount: '1' }] })
expect(await listContainerArrivalTimes(['9001'])).toEqual([{ ...row, planCount: 1 }])
for (const planCount of [undefined, null, '', 'unknown', -1, 0.5]) {
vi.mocked(http.post).mockResolvedValue({ code: '200', data: [{ ...row, planCount }] })
await expect(listContainerArrivalTimes(['9001'])).rejects.toThrow('入库计划数量无效')
}
})
})
@@ -6,6 +6,14 @@ export interface ContainerArrivalTime {
estimatedWarehouseArrivalAt: string | null
actualWarehouseArrivalAt: string | null
version: number
planCount: number
}
function normalizeArrival(item: ContainerArrivalTime): ContainerArrivalTime {
if (typeof item.planCount !== 'number' && (typeof item.planCount !== 'string' || !/^(0|[1-9]\d*)$/.test(item.planCount))) throw new Error('到仓记录的入库计划数量无效,请刷新后重试')
const count = Number(item.planCount)
if (item.planCount == null || !Number.isSafeInteger(count) || count < 0) throw new Error('到仓记录的入库计划数量无效,请刷新后重试')
return { ...item, version: Number(item.version), planCount: count }
}
const queryPath = '/platform/v1/last-leg/orders/container-arrival-times/query'
@@ -20,7 +28,7 @@ export async function listContainerArrivalTimes(sourceContainerBookingIds: strin
queryPath,
{ sourceContainerBookingIds },
)
return (unwrapApiResponse(response) || []).map((item) => ({ ...item, version: Number(item.version || 0) }))
return (unwrapApiResponse(response) || []).map(normalizeArrival)
}
export async function updateContainerExpectedArrival(
@@ -33,5 +41,5 @@ export async function updateContainerExpectedArrival(
{ headers: { 'Idempotency-Key': operationId(sourceContainerBookingId) } },
)
const result = unwrapApiResponse(response)
return { ...result, version: Number(result.version || 0) }
return normalizeArrival(result)
}