fix: serialize phase4 inventory and outbound gates
This commit is contained in:
@@ -916,7 +916,7 @@ export class AcceptanceRun {
|
||||
const matrixMarker = this.marker
|
||||
const variantMarker = `${matrixMarker}-P4-${label}`
|
||||
const contextKeys = ['orderDestinationType', 'phase4ProducerMatrixMarker']
|
||||
const createdKeys = ['phase3Loading', 'phase3LoadingCompletedProducer', 'orchestrationFixtures']
|
||||
const createdKeys = ['phase3Loading', 'phase3LoadingCompletedProducer', 'orchestrationFixtures', 'oceanBooking']
|
||||
const contextSnapshot = new Map(contextKeys.map((key) => [key, {
|
||||
present: Object.hasOwn(this.context, key), value: this.context[key],
|
||||
}]))
|
||||
|
||||
@@ -80,7 +80,7 @@ test('cross-region normalization keeps existing producers ahead of every phase-t
|
||||
test('phase-four producer variants restore the primary orchestration fixture after each matrix branch', async () => {
|
||||
const source = await import('node:fs/promises').then((fs) => fs.readFile(
|
||||
new URL('../admin-test-env-acceptance.mjs', import.meta.url), 'utf8'))
|
||||
assert.match(source, /const createdKeys = \['phase3Loading', 'phase3LoadingCompletedProducer', 'orchestrationFixtures'\]/)
|
||||
assert.match(source, /const createdKeys = \['phase3Loading', 'phase3LoadingCompletedProducer', 'orchestrationFixtures', 'oceanBooking'\]/)
|
||||
})
|
||||
|
||||
test('contract covers dual audience, canonical 403, both event directions and diagnostics', () => {
|
||||
|
||||
@@ -138,6 +138,25 @@ async function uploadPhotos(context, token) {
|
||||
return photos
|
||||
}
|
||||
|
||||
async function awaitProducerCandidates(context, token, producers) {
|
||||
const expected = [...new Set(producers.map((item) => id(item?.containerNo)).filter(nonBlank))]
|
||||
if (!expected.length) return false
|
||||
let response = null
|
||||
let seen = new Set()
|
||||
for (let attempt = 1; attempt <= 30; attempt += 1) {
|
||||
response = await context.requestOverseas('GET',
|
||||
'/api/pda/v1/last-leg/receiving-containers/candidates', undefined, {}, token)
|
||||
const records = success(response) && Array.isArray(response.body?.data) ? response.body.data : []
|
||||
seen = new Set(records.map((item) => id(item?.containerNo)).filter(nonBlank))
|
||||
if (expected.every((containerNo) => seen.has(containerNo))) break
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000))
|
||||
}
|
||||
const ready = expected.every((containerNo) => seen.has(containerNo))
|
||||
context.addStep(MODULE, '三期生产矩阵全部进入海外待收候选后再开始PDA', response, ready,
|
||||
`expected=${expected.join('|')}, seen=${[...seen].join('|')}; ${trace(response)}`, OPTIONS)
|
||||
return ready
|
||||
}
|
||||
|
||||
function skuFixtures(context) {
|
||||
const boxes = context.createdResources?.orders?.boxTypes
|
||||
const orchestration = context.createdResources?.orchestrationFixtures || {}
|
||||
@@ -301,7 +320,9 @@ async function runReceiving(context, token, secondaryToken, merchantToken, prefe
|
||||
palletCode: pallets.get(firstFba.inboundCode).palletCode, idempotencyKey: key(context, 'fba-carton-forbidden'),
|
||||
}, (response) => conflictMessage(response, /FBA.*bulk|bulk.*FBA/i))
|
||||
for (const inbound of fbaInbounds) await receiveFba(context, token, inbound, pallets.get(inbound.inboundCode))
|
||||
} else blockerGap(context, 'FBA SKU按箱数链', '当前柜没有带真实托盘的 FBA 入仓码')
|
||||
} else if (preferredProducer?.destinationType !== 'OVERSEAS') {
|
||||
blockerGap(context, 'FBA SKU按箱数链', '当前FBA柜没有带真实托盘的 FBA 入仓码')
|
||||
}
|
||||
if (overseasInbound && pallets.has(overseasInbound.inboundCode)) {
|
||||
const pallet = pallets.get(overseasInbound.inboundCode)
|
||||
await expected(context, token, 'POST', 'OVERSEAS模式硬拒绝批量收货', '/api/pda/v1/last-leg/receiving-containers/current/receipts/bulk', {
|
||||
@@ -309,7 +330,9 @@ async function runReceiving(context, token, secondaryToken, merchantToken, prefe
|
||||
packageCount: 1, idempotencyKey: key(context, 'overseas-bulk-forbidden'),
|
||||
}, (response) => conflictMessage(response, /OVERSEAS.*carton|bulk.*forbidden/i))
|
||||
await receiveOverseas(context, token, overseasInbound, pallet, preferredProducer?.cartonMark)
|
||||
} else blockerGap(context, 'OVERSEAS逐箱链', '当前柜没有带真实冻结箱唛与托盘的 OVERSEAS 入仓码')
|
||||
} else if (preferredProducer?.destinationType !== 'FBA') {
|
||||
blockerGap(context, 'OVERSEAS逐箱链', '当前OVERSEAS柜没有带真实冻结箱唛与托盘的 OVERSEAS 入仓码')
|
||||
}
|
||||
const refreshed = await pda(context, token, 'GET', '回查柜内逐入仓码实收进度', '/api/pda/v1/last-leg/receiving-containers/current')
|
||||
if (!success(refreshed.response) || Number(refreshed.data?.pendingPackages) !== 0) {
|
||||
blockerGap(context, '完成当前柜', `柜内实收尚未精确核平;pendingPackages=${refreshed.data?.pendingPackages ?? 'missing'}`, 'receiving-incomplete', refreshed.response)
|
||||
@@ -356,6 +379,12 @@ export async function run(context) {
|
||||
const matrix = context.createdResources?.phase4InboundProducerFixtures
|
||||
const producers = [matrix?.byDestinationType?.FBA?.[0], matrix?.byDestinationType?.OVERSEAS?.[0]]
|
||||
.filter((item) => nonBlank(item?.containerNo))
|
||||
const allProducers = Array.isArray(matrix?.containers) ? matrix.containers : producers
|
||||
if (allProducers.length && !(await awaitProducerCandidates(context, primary.token, allProducers))) {
|
||||
blockerGap(context, '海外待收柜生产矩阵',
|
||||
'三期已发布的FBA、OVERSEAS和第二柜尚未全部被海外事件消费者提交,禁止与消费事务并发入库')
|
||||
return
|
||||
}
|
||||
for (const [index, producer] of (producers.length ? producers : [null]).entries()) {
|
||||
context.pdaContainerSuffix = producer?.containerNo || `CONTAINER-${index + 1}`
|
||||
context.createdResources.phase4OverseasPda.finalStatus = null
|
||||
|
||||
Reference in New Issue
Block a user