This commit is contained in:
2026-09-08 18:18:51 +08:00
parent c6657929da
commit 1fd2b544a5
2 changed files with 84 additions and 28 deletions
@@ -100,9 +100,13 @@ test('approval freezes measurement and requires quantity weight and volume conse
test('dropship measurement completes the formal palletization workflow before smart loading', () => {
assert.match(source, /pda-dropship\/tasks\/pending/)
assert.match(source, /pda-dropship\/tasks\/\$\{taskId\}\/claim/)
assert.match(source, /pallets\/open/)
assert.match(source, /pallets\/\$\{palletId\}\/scan/)
assert.match(source, /cartons\/resolve/)
assert.match(source, /cartons\/count/)
assert.match(source, /pallets\/bind-pending/)
assert.match(source, /pallets\/\$\{palletId\}\/seal/)
assert.match(source, /重复清点操作按operationId幂等返回/)
assert.doesNotMatch(source, /pallets\/open/)
assert.doesNotMatch(source, /pallets\/\$\{palletId\}\/scan/)
assert.match(source, /dropship \? \['WAIT_PALLETIZE'\] : \['WAIT_SPLIT'\]/)
assert.match(source, /一件代发合托完成后进入智能分柜门禁/)
})
@@ -134,35 +134,85 @@ async function completeDropshipPalletization(context, { inboundId, inboundCode,
claimed?.taskStatus === 'CLAIMED' && asId(claimed?.inboundId) === inboundId,
`taskStatus=${claimed?.taskStatus ?? 'missing'}`, OPTIONS)
const openResponse = await context.request('POST',
`/api/platform/v1/first-leg/pda-dropship/tasks/${taskId}/pallets/open`, {
warehouseId, operationId: `${context.marker}-dropship-open`.slice(0, 128),
})
let pallet = context.apiSuccess(MODULE, '开启一件代发工作托盘', openResponse,
`taskId=${taskId}`, OPTIONS)
const palletId = asId(pallet?.palletId)
if (!palletId) return null
const totalCartons = Number(measurement?.actualPackageCount)
let scannedCartons = 0
const palletDate = new Date().toISOString().slice(2, 10).replace(/-/g, '')
let palletHash = 0
for (const character of `${context.marker}:${taskId}`) {
palletHash = (Math.imul(palletHash, 31) + character.charCodeAt(0)) >>> 0
}
const palletNo = `DP-${palletDate}-${String(palletHash % 10_000).padStart(4, '0')}`
let countedCartons = 0
let pallet = null
for (let index = 0; index < totalCartons; index += 1) {
const boxCode = `${inboundCode}#${totalCartons}-${index + 1}`
const scanResponse = await context.request('POST',
`/api/platform/v1/first-leg/pda-dropship/tasks/${taskId}/pallets/${palletId}/scan`, {
warehouseId, boxCode, cartonCount: 1,
operationId: `${context.marker}-dropship-scan-${index + 1}`.slice(0, 128),
})
const scanned = context.apiSuccess(MODULE, `合托扫描第${index + 1}箱冻结箱唛`, scanResponse,
const resolveResponse = await context.request('GET',
`/api/platform/v1/first-leg/pda-dropship/tasks/${taskId}/cartons/resolve?warehouseId=${warehouseId}&boxCode=${encodeURIComponent(boxCode)}`)
const resolved = context.apiSuccess(MODULE, `解析第${index + 1}箱的冻结箱唛`, resolveResponse,
`boxCode=${boxCode}`, OPTIONS)
context.assert(MODULE, `第${index + 1}箱进入工作托盘`, scanResponse,
Number(scanned?.addedCartons) === 1 && asId(scanned?.pallet?.palletId) === palletId,
`added=${scanned?.addedCartons ?? 'missing'}, remaining=${scanned?.remainingCartons ?? 'missing'}`, OPTIONS)
pallet = scanned?.pallet || pallet
if (Number(scanned?.addedCartons) === 1) scannedCartons += 1
context.assert(MODULE, `第${index + 1}箱允许清点且每箱SKU数完整`, resolveResponse,
resolved?.canCount === true && Number(resolved?.expectedSkuQuantity) > 0,
`canCount=${resolved?.canCount ?? 'missing'}, expectedSkuQuantity=${resolved?.expectedSkuQuantity ?? 'missing'}`, OPTIONS)
if (resolved?.canCount !== true || Number(resolved?.expectedSkuQuantity) < 1) continue
const countPayload = {
warehouseId,
boxCode,
actualSkuQuantity: Number(resolved.expectedSkuQuantity),
discrepancyAction: 'MATCH',
discrepancyRemark: null,
palletNo: index === 0 ? null : palletNo,
operationId: `${context.marker}-dropship-count-${index + 1}`.slice(0, 128),
}
const countResponse = await context.request('POST',
`/api/platform/v1/first-leg/pda-dropship/tasks/${taskId}/cartons/count`, countPayload)
const counted = context.apiSuccess(MODULE, `清点第${index + 1}箱并冻结实收SKU数`, countResponse,
`boxCode=${boxCode}`, OPTIONS)
context.assert(MODULE, `第${index + 1}箱清点结果与冻结箱唛一致`, countResponse,
asId(counted?.carton?.cartonId) === asId(resolved?.cartonId)
&& Number(counted?.carton?.actualSkuQuantity) === Number(resolved?.expectedSkuQuantity)
&& counted?.carton?.discrepancyStatus === 'MATCHED',
`cartonId=${asId(counted?.carton?.cartonId) || 'missing'}, discrepancy=${counted?.carton?.discrepancyStatus ?? 'missing'}`, OPTIONS)
if (asId(counted?.carton?.cartonId) === asId(resolved?.cartonId)) countedCartons += 1
if (index === 0) {
context.assert(MODULE, '先扫箱模式将已清点箱暂存为待组托', countResponse,
Number(counted?.unboundCartons) === 1 && counted?.pallet == null,
`unboundCartons=${counted?.unboundCartons ?? 'missing'}`, OPTIONS)
const replayResponse = await context.request('POST',
`/api/platform/v1/first-leg/pda-dropship/tasks/${taskId}/cartons/count`, countPayload)
const replayed = context.apiSuccess(MODULE, '重复清点操作按operationId幂等返回', replayResponse,
`boxCode=${boxCode}`, OPTIONS)
context.assert(MODULE, '重复清点没有重复累计箱数', replayResponse,
Number(replayed?.countedCartons) === Number(counted?.countedCartons)
&& Number(replayed?.unboundCartons) === Number(counted?.unboundCartons),
`counted=${replayed?.countedCartons ?? 'missing'}, unbound=${replayed?.unboundCartons ?? 'missing'}`, OPTIONS)
const bindResponse = await context.request('POST',
`/api/platform/v1/first-leg/pda-dropship/tasks/${taskId}/pallets/bind-pending`, {
warehouseId, palletNo,
operationId: `${context.marker}-dropship-bind-pending`.slice(0, 128),
})
const bound = context.apiSuccess(MODULE, '扫描托盘并绑定全部待组托箱', bindResponse,
`taskId=${taskId}, palletNo=${palletNo}`, OPTIONS)
pallet = bound?.pallets?.find((item) => item?.palletNo === palletNo) || null
context.assert(MODULE, '待组托箱绑定到OPEN托盘且不再游离', bindResponse,
Number(bound?.unboundCartons) === 0 && Number(pallet?.cartonCount) === 1
&& pallet?.status === 'OPEN',
`unbound=${bound?.unboundCartons ?? 'missing'}, palletStatus=${pallet?.status ?? 'missing'}`, OPTIONS)
} else {
pallet = counted?.pallet || pallet
context.assert(MODULE, `第${index + 1}箱直接进入当前OPEN托盘`, countResponse,
counted?.pallet?.palletNo === palletNo && counted?.pallet?.status === 'OPEN',
`palletNo=${counted?.pallet?.palletNo ?? 'missing'}, status=${counted?.pallet?.status ?? 'missing'}`, OPTIONS)
}
}
context.assert(MODULE, '一件代发工作托盘覆盖测量冻结的全部箱数', null,
totalCartons > 0 && scannedCartons === totalCartons,
`scanned=${scannedCartons}, expected=${totalCartons || 'missing'}`, OPTIONS)
totalCartons > 0 && countedCartons === totalCartons && Number(pallet?.cartonCount) === totalCartons,
`counted=${countedCartons}, palletCartons=${pallet?.cartonCount ?? 'missing'}, expected=${totalCartons || 'missing'}`, OPTIONS)
const palletId = asId(pallet?.palletId)
if (!palletId) return null
const sealResponse = await context.request('POST',
`/api/platform/v1/first-leg/pda-dropship/tasks/${taskId}/pallets/${palletId}/seal`, {
@@ -173,9 +223,11 @@ async function completeDropshipPalletization(context, { inboundId, inboundCode,
`taskId=${taskId}, palletId=${palletId}`, OPTIONS)
context.assert(MODULE, '全部箱数封托后入仓单允许进入WAIT_SPLIT', sealResponse,
sealed?.taskStatus === 'COMPLETED'
&& Number(sealed?.allocatedCartons) === Number(sealed?.totalCartons)
&& sealed?.pallets?.every((item) => item?.palletStatus === 'COMPLETED'),
`taskStatus=${sealed?.taskStatus ?? 'missing'}, allocated=${sealed?.allocatedCartons ?? 'missing'}`, OPTIONS)
&& Number(sealed?.countedCartons) === Number(sealed?.totalCartons)
&& Number(sealed?.boundCartons) === Number(sealed?.totalCartons)
&& Number(sealed?.unboundCartons) === 0
&& sealed?.pallets?.every((item) => item?.status === 'SEALED'),
`taskStatus=${sealed?.taskStatus ?? 'missing'}, counted=${sealed?.countedCartons ?? 'missing'}, bound=${sealed?.boundCartons ?? 'missing'}`, OPTIONS)
return sealed
}