This commit is contained in:
2026-09-14 12:00:48 +08:00
parent fb66d9200a
commit e55ab73e61
11 changed files with 288 additions and 9 deletions
@@ -124,6 +124,30 @@ export async function run(context) {
const planId = id(candidate.planId)
const planPalletId = id(candidate.planPalletId)
// Exercise removal on a disposable dispatch, then reuse the released current-run pallet.
const removable = await api(context, 'POST', '创建本轮托盘移除对照排车', `${BASE}/pre-arrange`, {
planPalletIds: [planPalletId], route: `${context.marker}-REMOVE`,
})
const removableNo = id(removable.data?.dispatchNo)
const removableItem = removable.data?.items?.find(item => id(item.planPalletId) === planPalletId)
if (!success(removable.response) || !removableNo || !removableItem?.id) {
blocker(context, '移除对照排车前置', '本轮托盘未生成排车明细', removable.response)
return
}
const removePath = `${BASE}/${encodeURIComponent(removableNo)}/items/${encodeURIComponent(id(removableItem.id))}`
const removed = await api(context, 'DELETE', '排车移除未拣托盘并释放正式锁', removePath)
const removedDetail = await api(context, 'GET', '回查移除后排车数量', `${BASE}/${encodeURIComponent(removableNo)}`)
context.assert(MODULE, '移除最后托盘后箱数托数明细归零', removedDetail.response,
success(removed.response) && success(removedDetail.response)
&& Number(removedDetail.data?.packageCount) === 0 && Number(removedDetail.data?.palletCount) === 0
&& removedDetail.data?.items?.length === 0, trace(removedDetail.response), OPTIONS)
const removedAgain = await context.requestOverseas('DELETE', removePath)
context.addStep(MODULE, '重复删除已不存在排车明细返回A0404', removedAgain,
removedAgain?.http === 404 || (removedAgain?.http === 200 && codeOf(removedAgain) === 'A0404'), trace(removedAgain), OPTIONS)
const freed = await api(context, 'GET', '移除后本轮托盘重新可预排', query(`${BASE}/candidates`, { sourceStage: 'RECEIVED' }))
context.assert(MODULE, '正式锁释放后候选恢复', freed.response,
Array.isArray(freed.data) && freed.data.some(item => id(item.planPalletId) === planPalletId), trace(freed.response), OPTIONS)
context.createdResources.phase4OverseasDispatch.removalDispatchNo = removableNo
const draftToken = `${context.marker}-DISPATCH-DRAFT`.slice(0, 64)
const containersJson = JSON.stringify([{ key: 'C1', capacity: Math.max(1, Number(candidate.packageCount)) }])
const snapshotBody = { draftToken, planIds: [planId], containersJson }
@@ -145,7 +169,28 @@ export async function run(context) {
&& matchingDrafts[0].containersJson === containersJson,
`matches=${matchingDrafts.length}, planIds=${matchingDrafts[0]?.planIdsJson || 'missing'}; ${trace(draftsResult.response)}`, OPTIONS)
const lockBody = { planPalletId, draftToken }
const disposableContainer = await api(context, 'POST', '创建真实智能预排草稿柜', `${BASE}/drafts/containers`, { draftToken, capacity: 500 })
const containerId = id(disposableContainer.data?.id)
if (!success(disposableContainer.response) || !containerId) return
const boundBody = { planPalletId, draftToken, draftContainerId: containerId }
const bound = await api(context, 'POST', '托盘绑定真实草稿柜', `${BASE}/draft-locks/lock`, boundBody)
if (!success(bound.response)) return
const boundDrafts = await api(context, 'GET', '回查真实草稿柜及托盘绑定', `${BASE}/drafts`)
context.assert(MODULE, '草稿结构回显服务端柜ID和托盘', boundDrafts.response,
boundDrafts.data?.find(draft => draft.draftToken === draftToken)?.containers?.some(container =>
id(container.id) === containerId && container.palletIds?.map(id).includes(planPalletId)), trace(boundDrafts.response), OPTIONS)
await api(context, 'POST', '移出草稿托盘解锁', `${BASE}/draft-locks/unlock`, boundBody)
const unlocked = await api(context, 'GET', '解锁后回查候选恢复', query(`${BASE}/candidates`, { sourceStage: 'RECEIVED' }))
context.assert(MODULE, '草稿解锁恢复候选', unlocked.response,
unlocked.data?.some(item => id(item.planPalletId) === planPalletId), trace(unlocked.response), OPTIONS)
await api(context, 'POST', '重新锁定以验证删除柜释放锁', `${BASE}/draft-locks/lock`, boundBody)
await api(context, 'DELETE', '删除本轮草稿柜并释放绑定托盘', `${BASE}/drafts/${encodeURIComponent(draftToken)}/containers/${encodeURIComponent(containerId)}`)
const deletedDrafts = await api(context, 'GET', '删除后回查草稿柜消失', `${BASE}/drafts`)
context.assert(MODULE, '删除草稿柜不再出现在结构响应', deletedDrafts.response,
Array.isArray(deletedDrafts.data) && !deletedDrafts.data.find(draft => draft.draftToken === draftToken)?.containers?.some(container => id(container.id) === containerId), trace(deletedDrafts.response), OPTIONS)
const finalContainer = await api(context, 'POST', '创建正式预排使用的草稿柜', `${BASE}/drafts/containers`, { draftToken, capacity: 500 })
if (!success(finalContainer.response) || !finalContainer.data?.id) return
const lockBody = { planPalletId, draftToken, draftContainerId: id(finalContainer.data.id) }
const locked = await api(context, 'POST', '锁定本轮预排托盘', `${BASE}/draft-locks/lock`, lockBody)
if (!success(locked.response)) return
const lockReplay = await api(context, 'POST', '同草稿重复锁定托盘幂等成功', `${BASE}/draft-locks/lock`, lockBody)