test: adapt PDA loading completion contract
This commit is contained in:
@@ -237,33 +237,50 @@ export async function run(context) {
|
||||
const batchHeaders = { 'Idempotency-Key': `${context.marker}-pda-batch`.slice(0, 128) }
|
||||
const pickResponse = await request(context, 'POST', batchPath, batchPayload, batchHeaders)
|
||||
const picked = context.apiSuccess(MODULE, '单次调用 PDA 原子 batch 完成拣货', pickResponse, '', OPTIONS)
|
||||
const directPdaCompletion = picked?.taskStatus === 'COMPLETED'
|
||||
&& picked?.workflowStatus === 'COMPLETED'
|
||||
context.assert(MODULE, '最后一箱拣货后 PDA 任务按已部署契约直接完成', pickResponse,
|
||||
directPdaCompletion
|
||||
const awaitingReview = picked?.taskStatus === 'LOADING'
|
||||
&& picked?.workflowStatus === 'AWAITING_REVIEW'
|
||||
context.assert(MODULE, '最后一箱拣货后 PDA 任务等待人工确认装柜完成', pickResponse,
|
||||
awaitingReview
|
||||
&& picked?.items?.every?.((item) => Number(item.pickedPackageCount) === Number(item.plannedPackageCount)),
|
||||
`taskStatus=${picked?.taskStatus || 'missing'}, workflow=${picked?.workflowStatus || 'missing'}`, OPTIONS)
|
||||
|
||||
const pickReplayResponse = await request(context, 'POST', batchPath, batchPayload, batchHeaders)
|
||||
const pickReplay = context.apiSuccess(MODULE, 'PDA batch Idempotency-Key 幂等重放', pickReplayResponse, '', OPTIONS)
|
||||
context.assert(MODULE, 'PDA batch 重放保持完成任务和拣货数', pickReplayResponse,
|
||||
pickReplay?.taskStatus === 'COMPLETED' && pickReplay?.workflowStatus === 'COMPLETED'
|
||||
context.assert(MODULE, 'PDA batch 重放保持待确认任务和拣货数', pickReplayResponse,
|
||||
pickReplay?.taskStatus === 'LOADING' && pickReplay?.workflowStatus === 'AWAITING_REVIEW'
|
||||
&& pickReplay?.items?.every?.((item) => Number(item.pickedPackageCount) === Number(item.plannedPackageCount)),
|
||||
`taskStatus=${pickReplay?.taskStatus || 'missing'}`, OPTIONS)
|
||||
|
||||
const completePath = `${PDA}/tasks/${taskId}/complete`
|
||||
const completePayload = {
|
||||
expectedTaskVersion: Number(picked?.version),
|
||||
operationId: `${context.marker}-pda-complete`.slice(0, 128),
|
||||
remark: context.marker,
|
||||
}
|
||||
const completeResponse = await request(context, 'POST', completePath, completePayload)
|
||||
const completed = context.apiSuccess(MODULE, 'PDA 人工确认装柜完成', completeResponse, '', OPTIONS)
|
||||
const directPdaCompletion = completed?.taskStatus === 'COMPLETED'
|
||||
&& completed?.workflowStatus === 'COMPLETED'
|
||||
context.assert(MODULE, '人工确认后 PDA 任务进入 COMPLETED', completeResponse,
|
||||
directPdaCompletion
|
||||
&& completed?.items?.every?.((item) => Number(item.pickedPackageCount) === Number(item.plannedPackageCount)),
|
||||
`taskStatus=${completed?.taskStatus || 'missing'}, workflow=${completed?.workflowStatus || 'missing'}`, OPTIONS)
|
||||
|
||||
const operationsResponse = await request(context, 'GET', `${PDA}/tasks/${taskId}/operations`)
|
||||
const operations = context.apiSuccess(MODULE, '回查完成后的 PDA 操作审计', operationsResponse, '', OPTIONS)
|
||||
context.assert(MODULE, 'PDA 完成审计保留领取和原子批次操作者记录', operationsResponse,
|
||||
context.assert(MODULE, 'PDA 完成审计保留领取、原子批次和人工完成记录', operationsResponse,
|
||||
Array.isArray(operations)
|
||||
&& operations.some((item) => item.actionType === 'CLAIM'
|
||||
&& Boolean(item.operatorId) && Boolean(item.createdAt))
|
||||
&& operations.some((item) => item.actionType === 'BATCH'
|
||||
&& Boolean(item.operatorId) && Boolean(item.createdAt))
|
||||
&& operations.some((item) => item.actionType === 'COMPLETE_LOADING'
|
||||
&& Boolean(item.operatorId) && Boolean(item.createdAt))
|
||||
&& !operations.some((item) => item.actionType === 'REVIEW'),
|
||||
`actions=${Array.isArray(operations) ? operations.map((item) => item.actionType).join(',') : 'missing'}`, OPTIONS)
|
||||
|
||||
const reviewResponse = await request(context, 'POST', `${PDA}/tasks/${taskId}/review`, {
|
||||
expectedTaskVersion: Number(picked?.version), operationId: `${context.marker}-pda-review`.slice(0, 128),
|
||||
expectedTaskVersion: Number(completed?.version), operationId: `${context.marker}-pda-review`.slice(0, 128),
|
||||
remark: context.marker,
|
||||
})
|
||||
context.addStep(MODULE, 'PDA 已完成后拒绝重复复核', reviewResponse,
|
||||
|
||||
@@ -73,8 +73,13 @@ test('container loading follows push, claim, real pick, completed sequence', ()
|
||||
"pushed?.status === 'EDITING'",
|
||||
"claimedPlan?.status === 'LOADING'",
|
||||
"const pickResponse = await request",
|
||||
"const completeResponse = await request",
|
||||
"finalPlan?.status === 'COMPLETED'",
|
||||
])
|
||||
assert.match(value, /picked\?\.workflowStatus === 'AWAITING_REVIEW'/)
|
||||
assert.match(value, /`\$\{PDA\}\/tasks\/\$\{taskId\}\/complete`/)
|
||||
assert.match(value, /expectedTaskVersion: Number\(picked\?\.version\)/)
|
||||
assert.match(value, /operationId: `\$\{context\.marker\}-pda-complete`\.slice\(0, 128\)/)
|
||||
})
|
||||
|
||||
test('bridge loading starts through a real PDA batch before preload confirmation', () => {
|
||||
@@ -119,11 +124,12 @@ test('PDA inventory snapshot gates batch and records the only safe mutation gap'
|
||||
assert.match(convergence, /fixture\?\.inventoryMutationVerified !== true/)
|
||||
})
|
||||
|
||||
test('PDA completion acceptance verifies immutable BATCH audit with operator metadata', () => {
|
||||
test('PDA completion acceptance verifies immutable BATCH and COMPLETE_LOADING audit with operator metadata', () => {
|
||||
const container = source('./phase3-container-loading.mjs')
|
||||
const convergence = source('./phase3-pda-convergence.mjs')
|
||||
assert.match(container, /回查完成后的 PDA 操作审计/)
|
||||
assert.match(container, /item\.actionType === 'BATCH'/)
|
||||
assert.match(container, /item\.actionType === 'COMPLETE_LOADING'/)
|
||||
assert.match(container, /Boolean\(item\.operatorId\) && Boolean\(item\.createdAt\)/)
|
||||
assert.match(convergence, /PDA 原子批次完成审计包含 BATCH 操作/)
|
||||
assert.match(convergence, /item\.actionType === 'BATCH'/)
|
||||
|
||||
Reference in New Issue
Block a user