test(acceptance): reuse fixed customers and align native fulfillment flows
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
const API = '/api/platform/v1/last-leg'
|
||||
const OPTIONS = { scenario: 'looseboard-pool-receipt', deploymentBlocker: true }
|
||||
const PNG = Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+aH1kAAAAASUVORK5CYII=', 'base64')
|
||||
const validVersion = value => Number.isSafeInteger(value) && value >= 0
|
||||
const validVersion = value => /^(0|[1-9]\d*)$/.test(String(value)) && Number.isSafeInteger(Number(value))
|
||||
const id = value => String(value ?? '')
|
||||
|
||||
/** 原承运来货经PDA实收及运营确认;测量值由调用方明确给出,不借历史库存。 */
|
||||
@@ -13,6 +13,11 @@ export async function receiveLooseboardPool(context, { demand, tripProof, pdaTok
|
||||
|| typeof context.checkpoint !== 'function' || !Array.isArray(measurements) || !measurements.length
|
||||
|| measurements.length !== binding.createRequest.expectedPalletCount
|
||||
|| measurements.some(m => !Number.isSafeInteger(m.cartonCount) || m.cartonCount <= 0
|
||||
|| !Array.isArray(m.boxes) || m.boxes.length !== m.cartonCount
|
||||
|| m.boxes.some(box => ['length', 'width', 'height', 'weight'].some(field => !Number.isFinite(box[field]) || box[field] <= 0)
|
||||
|| !Number.isSafeInteger(box.quantity) || box.quantity <= 0)
|
||||
|| Math.abs(m.boxes.reduce((sum, box) => sum + box.length * box.width * box.height / 1000000, 0) - m.volumeCbm) > 0.000001
|
||||
|| m.boxes.reduce((sum, box) => sum + box.weight, 0) !== m.grossWeightKg
|
||||
|| ['lengthCm', 'widthCm', 'heightCm', 'volumeCbm', 'grossWeightKg'].some(k => !Number.isFinite(m[k]) || m[k] <= 0))
|
||||
|| measurements.reduce((sum, m) => sum + m.cartonCount, 0) !== cargo?.packageCount) {
|
||||
throw Error('散板实收缺少本轮原单承运、PDA身份或逐托测量与箱数依据')
|
||||
@@ -63,11 +68,17 @@ export async function receiveLooseboardPool(context, { demand, tripProof, pdaTok
|
||||
check('来货范围与初始实收状态正确', initial?.incomingNo === proof.incomingNo && id(initial.warehouseId) === id(tripProof.warehouseId)
|
||||
&& initial.destinationKey === cargo.destinationKey && initial.status === 'WAIT_PDA_RECEIVING' && initial.pallets?.length === 0)
|
||||
const pda = `/api/pda/v1/last-leg/warehouse-transfers/${encodeURIComponent(proof.incomingNo)}`
|
||||
const forecast = await io('GET', pda, undefined, pdaToken)
|
||||
check('逐箱实收只使用原来货预报箱号和唯一预报SKU', forecast?.transferNo === proof.incomingNo
|
||||
&& id(forecast.operatingWarehouseId) === id(tripProof.warehouseId) && forecast.packageCount === cargo.packageCount
|
||||
&& forecast.items?.length === 1 && forecast.items[0].skuCode && forecast.cartons?.length === cargo.packageCount
|
||||
&& new Set(forecast.cartons.map(box => box.cartonMark)).size === cargo.packageCount
|
||||
&& forecast.cartons.every(box => box.cartonMark && box.status === 'EXPECTED' && id(box.transferItemId) === id(forecast.items[0].id)))
|
||||
for (const [index, measurement] of measurements.entries()) {
|
||||
const draft = await io('POST', `${pda}/pallets/drafts`, { ...measurement, idempotencyKey: key(`measure-${index}`) }, pdaToken)
|
||||
const draft = await io('POST', `${pda}/pallets/drafts`, { idempotencyKey: key(`measure-${index}`) }, pdaToken)
|
||||
const newPallets = draft?.pallets?.filter(row => !proof.pallets.some(p => id(p.id) === id(row.id))) || []
|
||||
check('逐托测量只新增本次一个草稿', draft?.transferNo === proof.incomingNo && draft?.pallets?.length === index + 1 && newPallets.length === 1
|
||||
&& newPallets[0].status === 'DRAFT' && newPallets[0].cartonCount === measurement.cartonCount
|
||||
&& newPallets[0].status === 'DRAFT' && newPallets[0].cartonCount === 0
|
||||
&& /^[1-9]\d*$/.test(id(newPallets[0].id)))
|
||||
const palletId = newPallets[0].id, path = `${pda}/pallets/${encodeURIComponent(palletId)}`
|
||||
const generated = await io('POST', `${path}/generate`, { idempotencyKey: key(`generate-${index}`) }, pdaToken)
|
||||
@@ -77,6 +88,21 @@ export async function receiveLooseboardPool(context, { demand, tripProof, pdaTok
|
||||
await io('POST', `${path}/bind`, { palletCode: pallet.palletNo, idempotencyKey: key(`bind-${index}`) }, pdaToken)
|
||||
proof.pallets.push({ id: palletId, warehousePalletId: id(pallet.warehousePalletId), palletNo: pallet.palletNo, packages: measurement.cartonCount })
|
||||
}
|
||||
let offset = 0
|
||||
const boxes = measurements.flatMap((measurement, index) => measurement.boxes.map(input => {
|
||||
const carton = forecast.cartons[offset++]
|
||||
return { cartonMark: carton.cartonMark, transferItemId: id(carton.transferItemId), transferPalletId: id(proof.pallets[index].id),
|
||||
length: input.length, width: input.width, height: input.height, weight: input.weight,
|
||||
items: [{ skuCode: forecast.items[0].skuCode, quantity: input.quantity }] }
|
||||
}))
|
||||
proof.controlledBoxInputs = { syntheticTestMaterials: true, boxes }
|
||||
const counted = await io('POST', `${pda}/cartons/count`, { idempotencyKey: key('count-boxes'), forecastPackageCount: forecast.packageCount, boxes }, pdaToken)
|
||||
check('逐箱尺寸重量SKU实点与实际托盘归属已保存', counted?.transferNo === proof.incomingNo && counted.cartons?.length === boxes.length
|
||||
&& boxes.every(input => counted.cartons.some(box => box.cartonMark === input.cartonMark && box.status === 'COUNTED'
|
||||
&& id(box.transferPalletId) === input.transferPalletId && ['length', 'width', 'height', 'weight'].every(field => Number(box[field]) === input[field])
|
||||
&& box.items?.length === 1 && box.items[0].skuCode === input.items[0].skuCode && Number(box.items[0].quantity) === input.items[0].quantity))
|
||||
&& proof.pallets.every((p, index) => counted.pallets?.some(row => id(row.id) === id(p.id) && row.cartonCount === p.packages
|
||||
&& Number(row.volumeCbm) === measurements[index].volumeCbm && Number(row.grossWeightKg) === measurements[index].grossWeightKg)))
|
||||
const uploaded = await io('POST', `${pda}/measurement-photos/files`, { name: `${context.marker}-TEST-looseboard.png`, type: 'image/png', content: PNG }, pdaToken, true)
|
||||
check('实收测试图片已正式上传', /^[1-9]\d*$/.test(id(uploaded?.fileId)))
|
||||
const received = await io('POST', `${pda}/palletize`, { idempotencyKey: key('palletize'), photoFileIds: [id(uploaded.fileId)] }, pdaToken)
|
||||
|
||||
Reference in New Issue
Block a user