From 4ead51a5feedf65be9443ddfe3dd45da7ca49e64 Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Tue, 29 Sep 2026 15:45:37 +0800 Subject: [PATCH] fix: record customs results in Shanghai business time --- .../api/platformContainerCustoms.test.ts | 15 +++++++++++++++ .../api/platformContainerCustoms.ts | 8 +++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/modules/container-loading/api/platformContainerCustoms.test.ts b/src/modules/container-loading/api/platformContainerCustoms.test.ts index 3aae0473..70397885 100644 --- a/src/modules/container-loading/api/platformContainerCustoms.test.ts +++ b/src/modules/container-loading/api/platformContainerCustoms.test.ts @@ -1,5 +1,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' import { http } from '@/shared/api/http' +import { recordClearanceResult, type DeclarationBatch } from './platformContainerCustoms' import { completeAllBuyContainerCustoms, downloadContainerCustomsReceipt, downloadContainerCustomsDocument, getContainerCustoms, sendContainerCustomsToBroker, startContainerCustoms, uploadContainerCustomsReceipt } from './platformContainerCustoms' const customs = { @@ -14,6 +15,20 @@ const customs = { describe('platform container customs API', () => { beforeEach(() => vi.restoreAllMocks()) + it('records domestic customs time in Shanghai even when UTC falls on the previous day', async () => { + vi.useFakeTimers() + try { + vi.setSystemTime(new Date('2026-09-29T16:30:00Z')) + const post = vi.spyOn(http, 'post').mockResolvedValue({ code: '200', data: { id: '1' } }) + await recordClearanceResult({ id: '123', version: 1 } as DeclarationBatch, 'OTHER', 'test') + expect(post).toHaveBeenCalledWith('/platform/v1/customs/loading-plans/declaration-batches/123/results', + expect.objectContaining({ occurredAt: '2026-09-30T00:30:00', resultType: 'OTHER', resolution: 'test' }), + expect.objectContaining({ headers: { 'Idempotency-Key': expect.any(String) } })) + } finally { + vi.useRealTimers() + } + }) + it('uses the frozen customs-v1 paths and preserves long ids as strings', async () => { const get = vi.spyOn(http, 'get').mockResolvedValue({ code: '200', message: 'ok', data: customs }) const result = await getContainerCustoms('2092438843630391402') diff --git a/src/modules/container-loading/api/platformContainerCustoms.ts b/src/modules/container-loading/api/platformContainerCustoms.ts index a8bd6067..db2c3cd0 100644 --- a/src/modules/container-loading/api/platformContainerCustoms.ts +++ b/src/modules/container-loading/api/platformContainerCustoms.ts @@ -189,7 +189,13 @@ export async function submitDeclarationBatch(batch: DeclarationBatch, customsEnt } export async function recordClearanceResult(batch: DeclarationBatch, resultType: ClearanceResultType, resolution?: string) { - const response = await http.post, ApiEnvelope>(`${basePath}/declaration-batches/${encodeURIComponent(batch.id)}/results`, { expectedVersion: batch.version, resultType, occurredAt: new Date().toISOString(), resolution: resolution?.trim() || null, evidenceFileId: null, resolved: false }, { headers: { 'Idempotency-Key': operationId('customs-clearance-result-record') } }) + // The domestic API stores LocalDateTime; send Shanghai wall time, not UTC with a discarded offset. + const parts = Object.fromEntries(new Intl.DateTimeFormat('en-CA', { + timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit', + hour: '2-digit', minute: '2-digit', second: '2-digit', hourCycle: 'h23', + }).formatToParts(new Date()).map(({ type, value }) => [type, value])) + const occurredAt = `${parts.year}-${parts.month}-${parts.day}T${parts.hour}:${parts.minute}:${parts.second}` + const response = await http.post, ApiEnvelope>(`${basePath}/declaration-batches/${encodeURIComponent(batch.id)}/results`, { expectedVersion: batch.version, resultType, occurredAt, resolution: resolution?.trim() || null, evidenceFileId: null, resolved: false }, { headers: { 'Idempotency-Key': operationId('customs-clearance-result-record') } }) return normalizeClearanceResult(unwrapApiResponse(response)) }