fix(dropship): generate pallet numbers atomically and extend full regressions
This commit is contained in:
@@ -113,7 +113,7 @@ async function waitForCompletedMeasurement(context, measurementPath, expectedSta
|
||||
return { response, measurement, attempts }
|
||||
}
|
||||
|
||||
async function completeDropshipPalletization(context, { inboundId, inboundCode, warehouseId, measurement }) {
|
||||
export async function completeDropshipPalletization(context, { inboundId, inboundCode, warehouseId, measurement }) {
|
||||
const pendingResponse = await context.request('GET',
|
||||
`/api/platform/v1/first-leg/pda-dropship/tasks/pending?keyword=${encodeURIComponent(inboundCode)}`)
|
||||
const pending = context.apiSuccess(MODULE, '查询一件代发待合托任务', pendingResponse,
|
||||
@@ -135,15 +135,31 @@ async function completeDropshipPalletization(context, { inboundId, inboundCode,
|
||||
`taskStatus=${claimed?.taskStatus ?? 'missing'}`, OPTIONS)
|
||||
|
||||
const totalCartons = Number(measurement?.actualPackageCount)
|
||||
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')}`
|
||||
const createPath = `/api/platform/v1/first-leg/pda-dropship/tasks/${taskId}/pallets/create-and-bind`
|
||||
const taskPath = `/api/platform/v1/first-leg/pda-dropship/tasks/${taskId}?warehouseId=${warehouseId}`
|
||||
const createPayload = { warehouseId, operationId: `${context.marker}-dropship-create-bind`.slice(0, 128) }
|
||||
let palletNo = ''
|
||||
let countedCartons = 0
|
||||
let pallet = null
|
||||
|
||||
const palletSnapshot = (value) => JSON.stringify({
|
||||
counted: value?.countedCartons, bound: value?.boundCartons, unbound: value?.unboundCartons,
|
||||
pallets: value?.pallets?.map((item) => ({ id: asId(item.palletId), no: item.palletNo,
|
||||
count: item.cartonCount, status: item.status, version: item.version })),
|
||||
})
|
||||
async function rejectEmptyCreation(before, suffix) {
|
||||
const response = await context.request('POST', createPath,
|
||||
{ ...createPayload, operationId: `${context.marker}-dropship-empty-${suffix}`.slice(0, 128) })
|
||||
context.assert(MODULE, `无待绑箱创建托盘被拒绝-${suffix}`, response,
|
||||
response.http === 200 && String(response.body?.code) === 'A0409',
|
||||
`HTTP=${response.http}, code=${response.body?.code || 'missing'}`, OPTIONS)
|
||||
const afterResponse = await context.request('GET', taskPath)
|
||||
const after = context.apiSuccess(MODULE, `拒绝创建后回查任务-${suffix}`, afterResponse, '', OPTIONS)
|
||||
context.assert(MODULE, `拒绝创建没有空托或计数漂移-${suffix}`, afterResponse,
|
||||
palletSnapshot(after) === palletSnapshot(before), `pallets=${after?.pallets?.length ?? 'missing'}`, OPTIONS)
|
||||
}
|
||||
await rejectEmptyCreation(claimed, 'before-count')
|
||||
|
||||
for (let index = 0; index < totalCartons; index += 1) {
|
||||
const boxCode = `${inboundCode}#${totalCartons}-${index + 1}`
|
||||
const resolveResponse = await context.request('GET',
|
||||
@@ -189,18 +205,21 @@ async function completeDropshipPalletization(context, { inboundId, inboundCode,
|
||||
&& 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
|
||||
const bindResponse = await context.request('POST', createPath, createPayload)
|
||||
const bound = context.apiSuccess(MODULE, '系统发码创建托盘并绑定全部待组托箱', bindResponse,
|
||||
`taskId=${taskId}`, OPTIONS)
|
||||
pallet = bound?.pallets?.find((item) => Number(item.cartonCount) === 1) || null
|
||||
palletNo = pallet?.palletNo || ''
|
||||
context.assert(MODULE, '待组托箱绑定到OPEN托盘且不再游离', bindResponse,
|
||||
Number(bound?.unboundCartons) === 0 && Number(pallet?.cartonCount) === 1
|
||||
&& pallet?.status === 'OPEN',
|
||||
&& pallet?.status === 'OPEN' && /^DP-\d{6}-\d{4}$/.test(palletNo)
|
||||
&& bound?.pallets?.length === 1,
|
||||
`unbound=${bound?.unboundCartons ?? 'missing'}, palletStatus=${pallet?.status ?? 'missing'}`, OPTIONS)
|
||||
const createReplayResponse = await context.request('POST', createPath, createPayload)
|
||||
const createReplay = context.apiSuccess(MODULE, '系统发码同operationId重放', createReplayResponse, '', OPTIONS)
|
||||
context.assert(MODULE, '系统发码重放不新增托盘且业务码和计数稳定', createReplayResponse,
|
||||
palletSnapshot(createReplay) === palletSnapshot(bound), `palletNo=${palletNo}`, OPTIONS)
|
||||
await rejectEmptyCreation(bound, 'after-bind')
|
||||
} else {
|
||||
pallet = counted?.pallet || pallet
|
||||
context.assert(MODULE, `第${index + 1}箱直接进入当前OPEN托盘`, countResponse,
|
||||
@@ -229,6 +248,11 @@ async function completeDropshipPalletization(context, { inboundId, inboundCode,
|
||||
&& Number(sealed?.unboundCartons) === 0
|
||||
&& sealed?.pallets?.every((item) => item?.status === 'SEALED'),
|
||||
`taskStatus=${sealed?.taskStatus ?? 'missing'}, counted=${sealed?.countedCartons ?? 'missing'}, bound=${sealed?.boundCartons ?? 'missing'}`, OPTIONS)
|
||||
const sealedReplayResponse = await context.request('POST', createPath, createPayload)
|
||||
const sealedReplay = context.apiSuccess(MODULE, '封托完成后系统发码原操作仍可重放', sealedReplayResponse, '', OPTIONS)
|
||||
context.assert(MODULE, '完成后重放不重开任务或新建空托', sealedReplayResponse,
|
||||
sealedReplay?.taskStatus === 'COMPLETED' && palletSnapshot(sealedReplay) === palletSnapshot(sealed),
|
||||
`taskStatus=${sealedReplay?.taskStatus || 'missing'}, palletNo=${palletNo}`, OPTIONS)
|
||||
return sealed
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user