From 969ff058157f4b6506431bf36f3de9b0fb08f4ef Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Fri, 28 Aug 2026 22:54:23 +0800 Subject: [PATCH] test(firstleg): correct mixed customs completion probe --- ...ainer-customs-acceptance-contract.test.mjs | 3 ++ .../phase3-container-customs-fixture.mjs | 2 ++ .../phase3-container-customs.mjs | 30 +++++++++++-------- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/scripts/admin-test-env-modules/container-customs-acceptance-contract.test.mjs b/scripts/admin-test-env-modules/container-customs-acceptance-contract.test.mjs index 372d056ec..ae7b4af76 100644 --- a/scripts/admin-test-env-modules/container-customs-acceptance-contract.test.mjs +++ b/scripts/admin-test-env-modules/container-customs-acceptance-contract.test.mjs @@ -42,6 +42,7 @@ test('mixed fixture producer is registered and uses only public HTTP composition assert.match(fixtureSource, /phase3-loading-finalize\.mjs/) assert.match(fixtureSource, /LOADING_LIST_BUY_DECLARATION_ITEMS/) assert.match(fixtureSource, /merchantQualificationFixture/) + assert.match(fixtureSource, /merchantPlatformDetail/) assert.doesNotMatch(fixtureSource, /customerToken:/) assert.doesNotMatch(fixtureSource, /\b(?:INSERT\s+INTO|DELETE\s+FROM|UPDATE\s+(?:fl_|ll_|wh_|ord_))/i) }) @@ -72,6 +73,8 @@ test('HTTP scenario contains file, state, idempotency, concurrency and zero-drif '混合柜平台详情精确包含BUY与TAX长ID票', 'Client只见本客户TAX票且完全隐藏BUY票', '买单导出只处理实际装柜BUY行', '混合柜最后一份完成文件后整柜COMPLETED', '自动离仓只写一次SYSTEM历史', '自动离仓只创建一个OUTBOUND_CONFIRM长ID任务', + 'documentId: customer.documentId, expectedVersion: 0', + '完成文件未成功或同键重放未收敛,已停止后续自动离仓写入', '已停止后续完成写入并保留现场', '自动离仓失败不回滚报关完成', '自动或待条件重试后整柜单次离仓', '同幂等键异载荷A0409', 'Promise.all', 'requestId=', 'traceId=', 'xlsxMagic']) { diff --git a/scripts/admin-test-env-modules/phase3-container-customs-fixture.mjs b/scripts/admin-test-env-modules/phase3-container-customs-fixture.mjs index 337511139..3e0784a70 100644 --- a/scripts/admin-test-env-modules/phase3-container-customs-fixture.mjs +++ b/scripts/admin-test-env-modules/phase3-container-customs-fixture.mjs @@ -64,6 +64,8 @@ function routes(context, merchantToken) { platformDetail: (ctx, value) => ctx.request('GET', `${PLATFORM}/${encodeURIComponent(id(value.loadingPlanId))}`), merchantDetail: (ctx, fixture, customer, token = merchantToken) => ctx.request('GET', `${MERCHANT}/orders/${encodeURIComponent(id(customer.orderId))}`, undefined, token), + merchantPlatformDetail: (ctx, fixture) => ctx.request('GET', + `${PLATFORM}/${encodeURIComponent(id(fixture.loadingPlanId))}`, undefined, merchantToken), merchantUploadDocument: (ctx, fixture, customer, file, idempotencyKey) => multipart( `${MERCHANT}/loading-plans/${encodeURIComponent(id(fixture.loadingPlanId))}/documents/upload?${customer.inboundIds.map((value) => `inboundIds=${encodeURIComponent(id(value))}`).join('&')}`, {}, file, customer.customerToken || merchantToken, idempotencyKey), diff --git a/scripts/admin-test-env-modules/phase3-container-customs.mjs b/scripts/admin-test-env-modules/phase3-container-customs.mjs index 8933348da..dfe66a3f5 100644 --- a/scripts/admin-test-env-modules/phase3-container-customs.mjs +++ b/scripts/admin-test-env-modules/phase3-container-customs.mjs @@ -246,9 +246,7 @@ async function runMixedConcurrency(context, routes, fixture) { && merchant.body.data.inbounds.every((item) => item.taxMode === 'TAX_REFUND') && !merchant.body.data.inbounds.some((item) => fixture.buyInboundIds.includes(id(item.inboundId))), evidence(merchant), OPTIONS) - const merchantPlatform = await context.request('GET', - `/api/platform/v1/customs/loading-plans/${encodeURIComponent(id(fixture.loadingPlanId))}`, - undefined, customer.customerToken) + const merchantPlatform = await routes.merchantPlatformDetail(context, fixture) context.assert(MODULE, 'Client身份禁止读取平台整柜报关入口', merchantPlatform, merchantPlatform?.http === 403 || (merchantPlatform?.http === 200 && ['A0401', 'A0403', 'S0503'].includes(code(merchantPlatform))), @@ -312,20 +310,26 @@ async function runMixedConcurrency(context, routes, fixture) { await assertZeroDrift(context, '开始后资料范围锁定A0409零漂移', routes, fixture, { body: { data: frozen } }, locked) const completionRequest = { - documentId: customer.documentId, expectedVersion: customer.documentVersion, + documentId: customer.documentId, expectedVersion: 0, finalConfirmation: true, fileName: `${context.marker}-mixed-result.done`, contentType: 'application/x-customs-completion', content: Uint8Array.from([0x52, 0x45, 0x53]), } const completionKey = key(context, 'mixed-completion') - const completions = await Promise.all([ - routes.platformUploadCompletion(context, fixture, completionRequest, completionKey), - routes.platformUploadCompletion(context, fixture, completionRequest, completionKey), - ]) - context.assert(MODULE, '最后一份TAX完成文件并发同键收敛同一结果', completions[1], - completions.every(success) - && id(completions[0].body?.data?.documentId) === id(completions[1].body?.data?.documentId) - && id(completions[0].body?.data?.completion?.fileId) === id(completions[1].body?.data?.completion?.fileId), - completions.map((response) => evidence(response)).join('; '), OPTIONS) + const completion = await routes.platformUploadCompletion(context, fixture, completionRequest, completionKey) + const completionReplay = success(completion) + ? await routes.platformUploadCompletion(context, fixture, completionRequest, completionKey) : null + const completionConverged = success(completion) && success(completionReplay) + && id(completion.body?.data?.documentId) === id(completionReplay.body?.data?.documentId) + && id(completion.body?.data?.completion?.fileId) === id(completionReplay.body?.data?.completion?.fileId) + context.assert(MODULE, '最后一份TAX完成文件二次确认并同键重放', completionReplay || completion, + completionConverged, + [completion, completionReplay].filter(Boolean).map((response) => evidence(response)).join('; '), OPTIONS) + if (!completionConverged) { + context.addCoverageGap(MODULE, OPTIONS.scenario, '最后一份完成文件二次确认', + '完成文件未成功或同键重放未收敛,已停止后续自动离仓写入', + 'completion-idempotency', { deploymentBlocker: true }) + return + } const completionDifferent = await routes.platformUploadCompletion(context, fixture, { ...completionRequest, content: Uint8Array.from([0x44, 0x49, 0x46]) }, completionKey) context.assert(MODULE, '完成文件同键异载荷A0409', completionDifferent,