Files
baiyue-firstleg/scripts/admin-test-env-modules/manual-order-splitting-fixture.mjs
T
2026-08-26 16:50:22 +08:00

79 lines
4.6 KiB
JavaScript

const MODULE = 'manual-order-splitting-fixture'
const OPTIONS = { scenario: 'manual-order-splitting-fixture', deploymentBlocker: true }
function id(value) { return value == null ? '' : String(value) }
function positiveInteger(value) { return Number.isInteger(Number(value)) && Number(value) > 0 }
function normalizedFixture(value) {
return {
sequence: Number(value.sequence), tenantId: id(value.tenantId), orderId: id(value.orderId),
orderNo: value.orderNo || null, inboundId: id(value.inboundId), inboundCode: value.inboundCode || null,
warehouseId: id(value.receivingWarehouseId), warehouseName: value.receivingWarehouseName || null,
channelCode: value.channelCode || null, channelName: value.channelName || null,
totalPackageCount: Number(value.totalPackageCount), destinationType: value.destinationType || null,
fulfillmentType: value.fulfillmentType || null, containerMode: value.containerMode || null,
}
}
export async function run(context) {
const fixtures = (context.createdResources?.waitSplitFixtures || []).map(normalizedFixture)
const valid = fixtures.length >= 4 && fixtures.every((item) => item.tenantId && item.orderId
&& item.inboundId && item.warehouseId && item.channelCode && positiveInteger(item.totalPackageCount))
context.assert(MODULE, '至少取得四票本轮 WAIT_SPLIT 人工分柜数据', null, valid,
`count=${fixtures.length}, invalid=${fixtures.filter((item) => !item.tenantId || !item.orderId
|| !item.inboundId || !item.warehouseId || !item.channelCode || !positiveInteger(item.totalPackageCount)).length}`,
OPTIONS)
if (!valid) return
const tenantIds = new Set(fixtures.map((item) => item.tenantId))
const warehouseIds = new Set(fixtures.map((item) => item.warehouseId))
const channelCodes = new Set(fixtures.map((item) => item.channelCode))
const sameScope = tenantIds.size === 1 && warehouseIds.size === 1 && channelCodes.size === 1
context.assert(MODULE, '人工分柜正向样本固定同一客户、起运仓和渠道', null, sameScope,
`tenantIds=${[...tenantIds].join(',')}, warehouseIds=${[...warehouseIds].join(',')}, channelCodes=${[...channelCodes].join(',')}`,
OPTIONS)
if (!sameScope) return
const byPackages = [...fixtures].sort((left, right) => right.totalPackageCount - left.totalPackageCount
|| left.sequence - right.sequence)
const partial = byPackages.find((item) => item.totalPackageCount >= 2)
const remaining = fixtures.filter((item) => item.inboundId !== partial?.inboundId)
const full = remaining.slice(0, 2)
const control = remaining[2]
const scenarioReady = Boolean(partial && full.length === 2 && control)
context.assert(MODULE, '人工分柜场景包含部分分配、两票整票拼柜和未分配对照', null, scenarioReady,
`partial=${partial?.inboundCode || 'missing'}, full=${full.map((item) => item.inboundCode).join(',') || 'missing'}, control=${control?.inboundCode || 'missing'}`,
OPTIONS)
if (!scenarioReady) return
const assignments = [
{ role: 'PARTIAL', ...partial, expectedAllocatedPackageCount: partial.totalPackageCount - 1,
expectedRemainingPackageCount: 1 },
...full.map((item, index) => ({ role: `FULL_${index + 1}`, ...item,
expectedAllocatedPackageCount: item.totalPackageCount, expectedRemainingPackageCount: 0 })),
]
const manifest = {
schemaVersion: 1, marker: context.marker, stage: 'WAIT_SPLIT_READY_FOR_MANUAL_ASSIGNMENT',
tenantId: fixtures[0].tenantId, warehouseId: fixtures[0].warehouseId,
warehouseName: fixtures[0].warehouseName, channelCode: fixtures[0].channelCode,
channelName: fixtures[0].channelName,
adminEntry: '/container-loading',
instructions: [
'在智能装柜页面创建一个同仓同渠道的内部模拟柜。',
'创建智能装柜计划,并严格按 assignments 的 expectedAllocatedPackageCount 分配。',
'保留 unassignedControl 不加入计划,用于核对候选剩余与误选保护。',
'人工操作后记录 loadingPlanId,并运行 manual-order-splitting-verify 只读核验。',
],
assignments,
unassignedControl: { role: 'UNASSIGNED_CONTROL', ...control,
expectedAllocatedPackageCount: 0, expectedRemainingPackageCount: control.totalPackageCount },
allFixtures: fixtures,
}
context.createdResources.manualOrderSplittingFixture = manifest
context.assert(MODULE, '人工分柜清单数量守恒', null,
assignments.every((item) => item.totalPackageCount
=== item.expectedAllocatedPackageCount + item.expectedRemainingPackageCount),
`assignments=${assignments.length}, plannedPackages=${assignments.reduce((sum, item) => sum + item.expectedAllocatedPackageCount, 0)}`,
OPTIONS)
}