test: stabilize full development acceptance

This commit is contained in:
2026-09-04 17:17:08 +08:00
parent 61b7b3fb02
commit 991bab9cb1
20 changed files with 155 additions and 87 deletions
@@ -223,8 +223,9 @@ export async function run(context) {
if (!containerBookingId) return
const candidateResponse = await context.request('GET', `${smartLoadingBase}/candidates?bookingId=${encodeURIComponent(containerBookingId)}&warehouseId=${encodeURIComponent(warehouseId)}`)
const candidates = context.apiSuccess(MODULE, '查询本轮入库单柜次装柜候选', candidateResponse, '', OPTIONS)
const candidate = Array.isArray(candidates) ? candidates.find((item) => id(item.inboundId) === inboundId
&& Number(item.availablePackageCount) > 0) : null
const inboundCandidates = Array.isArray(candidates) ? candidates.filter((item) => id(item.inboundId) === inboundId
&& Number(item.availablePackageCount) > 0) : []
const candidate = inboundCandidates[0]
context.assert(MODULE, '柜次装柜候选与入库单、客户和仓库一致', candidateResponse,
Boolean(candidate?.inboundDetailId) && id(candidate?.accountId) === tenantId
&& id(candidate?.warehouseId) === warehouseId,
@@ -237,16 +238,24 @@ export async function run(context) {
const loadingPlan = context.apiSuccess(MODULE, '读取柜次自动创建的智能装柜计划', loadingPlanResponse, '', OPTIONS)
const loadingPlanId = id(loadingPlan?.id)
if (!loadingPlanId) return
const assignmentResponse = await request(context, 'POST', `${smartLoadingBase}/plans/${loadingPlanId}/assignments`, {
inboundId, inboundDetailId: id(candidate.inboundDetailId), packageCount: 1,
expectedVersion: Number(loadingPlan.version),
operationId: `${context.marker}-${loadingPlanId}-bridge-assign`.slice(0, 128),
})
const dropshipAssignment = source?.fulfillmentType === 'ONE_CLICK_DROPSHIP'
const initialAssignmentCount = dropshipAssignment
? inboundCandidates.reduce((total, item) => total + Number(item.availablePackageCount || 0), 0) : 1
const assignmentPath = dropshipAssignment
? `${smartLoadingBase}/plans/${loadingPlanId}/inbound-assignments`
: `${smartLoadingBase}/plans/${loadingPlanId}/assignments`
const assignmentBody = dropshipAssignment
? { inboundId, packageCount: initialAssignmentCount, expectedVersion: Number(loadingPlan.version),
operationId: `${context.marker}-${loadingPlanId}-bridge-assign-inbound`.slice(0, 128) }
: { inboundId, inboundDetailId: id(candidate.inboundDetailId), packageCount: initialAssignmentCount,
expectedVersion: Number(loadingPlan.version), operationId: `${context.marker}-${loadingPlanId}-bridge-assign`.slice(0, 128) }
const assignmentResponse = await request(context, 'POST', assignmentPath, assignmentBody)
const assignedLoadingPlan = context.apiSuccess(MODULE, '将本轮入库货物分配到柜次计划', assignmentResponse, '', OPTIONS)
context.assert(MODULE, '柜次计划明细和版本真实持久化', assignmentResponse,
assignedLoadingPlan?.items?.some?.((item) => id(item.inboundId) === inboundId && Number(item.packageCount) === 1)
&& Number(assignedLoadingPlan?.version) === 1,
`loadingPlanId=${loadingPlanId}, version=${assignedLoadingPlan?.version ?? 'missing'}`, OPTIONS)
assignedLoadingPlan?.items?.filter?.((item) => id(item.inboundId) === inboundId)
.reduce((total, item) => total + Number(item.packageCount || 0), 0) === initialAssignmentCount
&& Number(assignedLoadingPlan?.version) >= 1,
`loadingPlanId=${loadingPlanId}, assignedPackages=${initialAssignmentCount}, version=${assignedLoadingPlan?.version ?? 'missing'}`, OPTIONS)
const assignedItem = assignedLoadingPlan?.items?.find?.((item) => id(item.inboundId) === inboundId)
const orderRemarks = source || {}
@@ -584,12 +593,15 @@ export async function run(context) {
const canonicalTaskId = id(canonicalTask?.id)
const taskDetailPath = `${pdaBase}/tasks/${canonicalTaskId}?warehouseId=${encodeURIComponent(warehouseId)}`
const canonicalItem = canonicalTask?.items?.find?.((item) => id(item.inboundId) === inboundId)
const canonicalPickItems = dropshipAssignment
? canonicalTask?.items?.filter?.((item) => id(item.inboundId) === inboundId) || []
: canonicalItem ? [canonicalItem] : []
context.assert(MODULE, '柜次 PDA 任务与桥接入库明细一致', canonicalTaskResponse,
Boolean(canonicalTaskId) && canonicalTaskId === confirmedTaskId && id(canonicalTask?.loadingPlanId) === loadingPlanId
&& id(canonicalTask?.containerBookingId) === containerBookingId
&& canonicalTask?.workflowStatus === 'UNASSIGNED' && Boolean(canonicalItem?.id),
`taskId=${canonicalTaskId || 'missing'}, itemId=${id(canonicalItem?.id) || 'missing'}`, OPTIONS)
if (!canonicalTaskId || !canonicalItem?.id) return
&& canonicalTask?.workflowStatus === 'UNASSIGNED' && canonicalPickItems.length > 0,
`taskId=${canonicalTaskId || 'missing'}, itemCount=${canonicalPickItems.length}`, OPTIONS)
if (!canonicalTaskId || !canonicalPickItems.length) return
const beforeClaimPlanResponse = await context.request('GET', `${smartLoadingBase}/plans/${loadingPlanId}`)
const beforeClaimPlan = context.apiSuccess(MODULE, '领取前读取柜次计划即时版本', beforeClaimPlanResponse, '', OPTIONS)
@@ -665,15 +677,18 @@ export async function run(context) {
const skipBatchKey = `${context.marker}-exception-skip-batch`.slice(0, 128)
const partialBatchKey = `${context.marker}-exception-partial-batch`.slice(0, 128)
const dynamicBatchKey = `${context.marker}-dynamic-pick`.slice(0, 128)
const expectedBatchOperationIds = [batchKey, skipBatchKey, partialBatchKey, dynamicBatchKey]
const dropshipWholePallet = source?.fulfillmentType === 'ONE_CLICK_DROPSHIP'
const expectedBatchOperationIds = dropshipWholePallet
? [batchKey]
: [batchKey, skipBatchKey, partialBatchKey, dynamicBatchKey]
const batchPayload = {
warehouseId, loadingPlanId, containerBookingId,
expectedVersion: Number(claimed?.version),
inventorySnapshotToken: inventory.snapshotToken,
items: [{
itemId: id(canonicalItem.id), action: 'PICK', pickedPackageCount: 1,
version: Number(canonicalItem.version),
}],
items: canonicalPickItems.map((item) => ({
itemId: id(item.id), action: 'PICK', pickedPackageCount: Number(item.plannedPackageCount),
version: Number(item.version),
})),
}
const staleBatch = await request(context, 'POST', batchPath,
@@ -1095,7 +1110,10 @@ export async function run(context) {
let partialBatchVerified = false
let partialBlockSnapshot = null
let dynamicIncrementVerified = false
if (!incrementalInboundId || incrementalFixture?.marker !== context.marker || incrementalInboundId === inboundId) {
if (dropshipWholePallet) {
context.addStep(MODULE, '一件代发整托生产者不执行可拆分动态增量场景', null, true,
'逐箱封托事实必须整托守恒;SKIP、PARTIAL 和动态增删改由 STANDARD 生产者覆盖', OPTIONS)
} else if (!incrementalInboundId || incrementalFixture?.marker !== context.marker || incrementalInboundId === inboundId) {
context.addStep(MODULE, '取得本轮独立动态增量入库单', null, false,
`inboundId=${incrementalInboundId || 'missing'}, primaryInboundId=${inboundId}, marker=${incrementalFixture?.marker || 'missing'}`, OPTIONS)
} else {
@@ -1507,9 +1525,9 @@ export async function run(context) {
cartonMarks: stableLoadedCartonMarks(stagedTask?.items),
fulfillmentType: source?.fulfillmentType || 'STANDARD',
skuCodes: [...new Set([...(Array.isArray(source?.skuCodes) ? source.skuCodes : []),
...(Array.isArray(incrementalFixture?.skuCodes) ? incrementalFixture.skuCodes : [])])],
...(!dropshipWholePallet && Array.isArray(incrementalFixture?.skuCodes) ? incrementalFixture.skuCodes : [])])],
skuLines: [...(Array.isArray(source?.skuLines) ? source.skuLines : []),
...(Array.isArray(incrementalFixture?.skuLines) ? incrementalFixture.skuLines : [])],
...(!dropshipWholePallet && Array.isArray(incrementalFixture?.skuLines) ? incrementalFixture.skuLines : [])],
destinationType: initial?.summary?.destinationType || source?.destinationType || null,
destinationWarehouseId: id(initial?.summary?.destinationWarehouseId || source?.destinationWarehouseId),
destinationWarehouseCode: initial?.summary?.destinationCode || source?.destinationWarehouseCode || null,