test(admin): keep phase3 producer fixtures aligned

This commit is contained in:
2026-08-11 14:07:16 +08:00
parent 7c2274be31
commit df0f05c74d
3 changed files with 88 additions and 7 deletions
@@ -67,11 +67,25 @@ async function detail(context, caseId) {
return { response, data }
}
export function selectCustomsFlow(createdResources) {
const fixtures = [
createdResources?.orchestrationFixtures?.inboundMeasurement,
createdResources?.orchestrationFixtures?.phase3Container,
].filter(Boolean)
const containers = [
createdResources?.phase3Loading,
createdResources?.phase3ContainerLoading,
].filter(Boolean)
for (const container of containers) {
const fixture = fixtures.find((candidate) => id(candidate?.tenantId) === id(container?.tenantId)
&& id(candidate?.inboundId) === id(container?.inboundId))
if (fixture) return { fixture, container }
}
return { fixture: null, container: null }
}
export async function run(context) {
const fixture = context.createdResources?.orchestrationFixtures?.inboundMeasurement
|| context.createdResources?.orchestrationFixtures?.phase3Container
const container = context.createdResources?.phase3Loading
|| context.createdResources?.phase3ContainerLoading
const { fixture, container } = selectCustomsFlow(context.createdResources)
const tenantId = id(fixture?.tenantId)
const parentOrderId = id(fixture?.orderId)
const inboundId = id(fixture?.inboundId)
@@ -2,6 +2,23 @@ const MODULE = 'phase3-loading-finalize'
const OPTIONS = { scenario: 'phase3-loading-hard-gate-finalize', deploymentBlocker: true }
function id(value) { return value == null ? '' : String(value) }
function codeOf(response) { return response?.body?.code == null ? 'missing' : String(response.body.code) }
export function buildFinalizeResource(fixture, finalData, completeResponse) {
const observedStatus = finalData?.summary?.processStatus || fixture?.inboundStatus || 'UNKNOWN'
const observedVersion = Number(finalData?.summary?.version)
const loaded = observedStatus === 'LOADED'
const version = Number.isInteger(observedVersion) ? observedVersion : fixture?.inboundVersion
return {
...fixture,
...(Number.isInteger(version) ? { inboundVersion: version } : {}),
inboundStatus: observedStatus,
finalStatus: observedStatus,
finalizeSucceeded: loaded,
notCleanedReason: loaded ? null
: `装柜完成未成功,保留真实状态 ${observedStatus};completeCode=${codeOf(completeResponse)}`,
}
}
async function request(context, method, path, body, headers = {}) {
try {
@@ -69,7 +86,5 @@ export async function run(context) {
&& item.operatorName && item.fromStatus === 'LOADING' && item.toStatus === 'LOADED'),
`status=${finalData?.summary?.processStatus || 'missing'}, version=${finalData?.summary?.version ?? 'missing'}, histories=${finalData?.statusHistory?.length ?? 'n/a'}`, OPTIONS)
context.createdResources.phase3Loading = {
...fixture, inboundVersion: Number(finalData?.summary?.version), inboundStatus: 'LOADED', finalStatus: 'LOADED',
}
context.createdResources.phase3Loading = buildFinalizeResource(fixture, finalData, completeResponse)
}
@@ -0,0 +1,52 @@
import assert from 'node:assert/strict'
import test from 'node:test'
import { selectCustomsFlow } from './phase3-customs.mjs'
import { buildFinalizeResource } from './phase3-loading-finalize.mjs'
test('pairs customs source fixture with the matching loading container', () => {
const resources = {
orchestrationFixtures: {
inboundMeasurement: { tenantId: 10001, orderId: 101, inboundId: 201 },
phase3Container: { tenantId: 10001, orderId: 102, inboundId: 202 },
},
phase3Loading: { tenantId: 10001, inboundId: 201, containerBookingId: 301 },
phase3ContainerLoading: { tenantId: 10001, inboundId: 202, containerBookingId: 302 },
}
const selected = selectCustomsFlow(resources)
assert.equal(selected.fixture.orderId, 101)
assert.equal(selected.container.containerBookingId, 301)
})
test('falls back to the matching container fixture without crossing source identities', () => {
const resources = {
orchestrationFixtures: { phase3Container: { tenantId: 10001, orderId: 102, inboundId: 202 } },
phase3Loading: { tenantId: 10001, inboundId: 201, containerBookingId: 301 },
phase3ContainerLoading: { tenantId: 10001, inboundId: 202, containerBookingId: 302 },
}
const selected = selectCustomsFlow(resources)
assert.equal(selected.fixture.orderId, 102)
assert.equal(selected.container.containerBookingId, 302)
})
test('records LOADING and a cleanup reason when finalize returns S0500', () => {
const result = buildFinalizeResource(
{ inboundStatus: 'LOADING', inboundVersion: 5, finalStatus: 'COMPLETED' },
{ summary: { processStatus: 'LOADING', version: 5 } },
{ http: 200, body: { code: 'S0500' } },
)
assert.equal(result.finalStatus, 'LOADING')
assert.equal(result.finalizeSucceeded, false)
assert.match(result.notCleanedReason, /S0500/)
})
test('records LOADED and clears the reason only after a real LOADED reread', () => {
const result = buildFinalizeResource(
{ inboundStatus: 'LOADING', inboundVersion: 5, finalStatus: 'COMPLETED' },
{ summary: { processStatus: 'LOADED', version: 6 } },
{ http: 200, body: { code: '200' } },
)
assert.equal(result.finalStatus, 'LOADED')
assert.equal(result.finalizeSucceeded, true)
assert.equal(result.notCleanedReason, null)
})