This commit is contained in:
2026-08-27 11:09:51 +08:00
parent 4612181ab0
commit c1b136c3d6
4 changed files with 50 additions and 14 deletions
@@ -1,7 +1,8 @@
const MODULE = 'inbound-measurement'
const SCENARIO = 'mojia-carton-measurement'
const OPTIONS = { scenario: SCENARIO, deploymentBlocker: true }
const FIXTURE_PALLET_CAPACITY_CBM = 1.2
const REUSABLE_PALLET_CODES = Object.freeze(['TP-001', 'YW-TP-002'])
const reusablePalletsByWarehouse = new Map()
const WEIGHT_IMAGE = Uint8Array.from([137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82,
0, 0, 0, 1, 0, 0, 0, 1, 8, 6, 0, 0, 0, 31, 21, 196, 137, 0, 0, 0, 13, 73, 68, 65, 84,
8, 215, 99, 248, 207, 192, 240, 31, 0, 5, 0, 1, 255, 137, 153, 61, 29, 0, 0, 0, 0,
@@ -27,6 +28,33 @@ function validPdf(response) {
&& response.bytes?.length > 4 && new TextDecoder().decode(response.bytes.slice(0, 4)) === '%PDF'
}
async function reusablePallets(context, warehouseId) {
const cacheKey = asId(warehouseId)
if (reusablePalletsByWarehouse.has(cacheKey)) return reusablePalletsByWarehouse.get(cacheKey)
const pallets = []
for (const palletCode of REUSABLE_PALLET_CODES) {
const response = await context.request('GET',
`/api/platform/v1/pallets?page=1&size=20&tenantId=0&warehouseId=${encodeURIComponent(warehouseId)}&palletCode=${encodeURIComponent(palletCode)}`)
const page = context.apiSuccess(MODULE, `查询原有可复用托盘 ${palletCode}`, response,
`warehouseId=${warehouseId}`, OPTIONS)
const exact = (page?.records || []).find((item) => asId(item?.warehouseId) === cacheKey
&& String(item?.palletCode || '') === palletCode && asId(item?.id))
context.assert(MODULE, `原有托盘 ${palletCode} 属于当前仓库且可复用`, response, Boolean(exact),
`warehouseId=${warehouseId}, matched=${exact?.palletCode || 'missing'}`, OPTIONS)
if (!exact) return null
pallets.push({ id: asId(exact.id), code: palletCode })
}
reusablePalletsByWarehouse.set(cacheKey, pallets)
return pallets
}
function randomlyReusePalletIds(pallets, palletCount, randomValue) {
const seed = Number.isInteger(Number(randomValue)) ? Number(randomValue) : Date.now()
return Array.from({ length: palletCount }, (_, index) =>
pallets[(seed >>> (index % 31)) % pallets.length].id)
}
async function waitForCompletedMeasurement(context, measurementPath, attempts = 30) {
let response = null
let measurement = null
@@ -45,16 +73,15 @@ async function provisionWarehouseResources(context, { inboundId, warehouseId, pa
const suffix = `${String(context.marker).replace(/\D/g, '').slice(-8)}${String(inboundId).slice(-6)}`
const resources = []
const palletIds = []
const candidates = await reusablePallets(context, warehouseId)
if (!candidates) return null
const palletIds = randomlyReusePalletIds(candidates, palletCount,
context.context?.waitSplitVariant?.randomValue)
for (let index = 1; index <= palletCount; index += 1) {
const palletResponse = await context.request('POST', '/api/platform/v1/pallets?tenantId=0', {
warehouseId, palletType: 'STANDARD', capacityCbm: FIXTURE_PALLET_CAPACITY_CBM,
weightKg: 8, color: '蓝色', remark: `${context.marker}-INBOUND-${inboundId}-PALLET-${index}`,
})
const palletId = asId(context.apiSuccess(MODULE, `创建称重托盘主数据 ${index}/${palletCount}`,
palletResponse, `warehouseId=${warehouseId}`, OPTIONS))
if (!palletId) return null
palletIds.push(palletId)
const palletId = palletIds[index - 1]
context.assert(MODULE, `随机复用原有称重托盘 ${index}/${palletCount}`, null,
REUSABLE_PALLET_CODES.includes(candidates.find((item) => item.id === palletId)?.code),
`warehouseId=${warehouseId}, palletId=${palletId}`, OPTIONS)
const resourceSuffix = `${suffix}${String(index).padStart(2, '0')}`
let locationId = null
if (context.context?.phase3LoadingRequireSharedOverflow !== true) {
@@ -74,7 +101,7 @@ async function provisionWarehouseResources(context, { inboundId, warehouseId, pa
context.createdResources.inboundWarehouseResources ??= {}
context.createdResources.inboundWarehouseResources[inboundId] = {
marker: context.marker, tenantId: '0', warehouseId: asId(warehouseId), palletCount,
palletCapacityCbm: FIXTURE_PALLET_CAPACITY_CBM, resources,
reusablePalletCodes: REUSABLE_PALLET_CODES, resources,
}
return { palletId: palletIds[0], palletIds, palletCount, resources }
}
@@ -26,6 +26,15 @@ test('随机线路只固定义乌仓并从客户真实可计价候选选择', ()
assert.doesNotMatch(runner, /channel-name|channel-code/)
})
test('称重只随机复用义乌仓原有两个托盘且禁止按订单新增', () => {
assert.match(measurement, /REUSABLE_PALLET_CODES = Object\.freeze\(\['TP-001', 'YW-TP-002'\]\)/)
assert.match(measurement, /context\.request\('GET',[\s\S]*\/api\/platform\/v1\/pallets\?page=1&size=20/)
assert.match(measurement, /randomlyReusePalletIds\(candidates, palletCount/)
assert.match(measurement, /随机复用原有称重托盘/)
assert.doesNotMatch(measurement, /context\.request\('POST', '\/api\/platform\/v1\/pallets/)
assert.doesNotMatch(measurement, /创建称重托盘主数据/)
})
test('八千票执行器逐票记录且失败后继续', () => {
assert.match(runner, /positiveInteger\(values\.get\('count'\), 8000/)
assert.match(runner, /positiveInteger\(values\.get\('box-max'\), 300/)