From 15b16634dbf0b80515cab0ec00a1a8ad50e446b0 Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Fri, 4 Sep 2026 15:36:56 +0800 Subject: [PATCH] test: cover smart loading quantity operations --- .../admin-test-env-modules/phase3-loading.mjs | 60 +++++++++++++++++-- ...source-allocation-recent-contract.test.mjs | 10 +++- 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/scripts/admin-test-env-modules/phase3-loading.mjs b/scripts/admin-test-env-modules/phase3-loading.mjs index 5ba1a6556..435c5d111 100644 --- a/scripts/admin-test-env-modules/phase3-loading.mjs +++ b/scripts/admin-test-env-modules/phase3-loading.mjs @@ -1336,6 +1336,20 @@ export async function run(context) { && authoritativeRemaining === authoritativeTotal - assignedPackageCount, `totalPackageCount=${reassignedPlanItem?.totalPackageCount ?? 'missing'}, packageCount=${reassignedPlanItem?.packageCount ?? 'missing'}, remainingPackageCount=${reassignedPlanItem?.remainingPackageCount ?? 'missing'}`, OPTIONS) + const assignedByBookingResponse = await context.request('GET', + `${smartLoadingBase}/plans/by-booking/${encodeURIComponent(containerBookingId)}`) + const assignedByBooking = context.apiSuccess(MODULE, '计划已有明细后按柜次读取智能装柜详情', + assignedByBookingResponse, '', OPTIONS) + const assignedByBookingItem = assignedByBooking?.items?.find?.((item) => + id(item?.id) === id(reassignedPlanItem?.id)) + context.assert(MODULE, '按柜次详情返回同一计划及权威箱数且数量守恒', assignedByBookingResponse, + id(assignedByBooking?.id) === loadingPlanId + && Number(assignedByBooking?.version) === Number(reassignedPlan?.version) + && Number(assignedByBookingItem?.packageCount) === assignedPackageCount + && Number(assignedByBookingItem?.totalPackageCount) === authoritativeTotal + && Number(assignedByBookingItem?.remainingPackageCount) === authoritativeRemaining, + `loadingPlanId=${id(assignedByBooking?.id) || 'missing'}, packageCount=${assignedByBookingItem?.packageCount ?? 'missing'}, totalPackageCount=${assignedByBookingItem?.totalPackageCount ?? 'missing'}, remainingPackageCount=${assignedByBookingItem?.remainingPackageCount ?? 'missing'}`, + OPTIONS) if (reassignedPlanItem?.id && Number.isInteger(authoritativeTotal) && authoritativeTotal > 0) { const overAuthorityResponse = await request(context, 'PATCH', `${smartLoadingBase}/plans/${loadingPlanId}/items/${encodeURIComponent(id(reassignedPlanItem.id))}`, { @@ -1343,8 +1357,8 @@ export async function run(context) { expectedItemVersion: Number(reassignedPlanItem.version), operationId: `${context.marker}-dynamic-over-authority`.slice(0, 128), }) - context.addStep(MODULE, '调整箱数超过服务端权威总箱数返回A0400', overAuthorityResponse, - overAuthorityResponse.http === 200 && codeOf(overAuthorityResponse) === 'A0400', + context.addStep(MODULE, '调整箱数超过服务端权威总箱数返回A0422', overAuthorityResponse, + overAuthorityResponse.http === 200 && codeOf(overAuthorityResponse) === 'A0422', responseEvidence(overAuthorityResponse), OPTIONS) const afterOverAuthorityResponse = await context.request('GET', `${smartLoadingBase}/plans/${loadingPlanId}`) const afterOverAuthority = context.apiSuccess(MODULE, '超权威总箱数失败后回查计划', @@ -1379,8 +1393,44 @@ export async function run(context) { && Number(adjustedItem?.packageCount) === 2 && adjustedItem?.warehouseRemark === reassignedPlanItem?.warehouseRemark && id(adjustedPlan?.pdaTaskId) === canonicalTaskId, `planVersion=${adjustedPlan?.version ?? 'missing'}, taskVersion=${adjustedPlan?.pdaTaskVersion ?? 'missing'}, itemVersion=${adjustedItem?.version ?? 'missing'}`, OPTIONS) - effectiveDynamicPlan = adjustedPlan - reassignedPlanItem = adjustedItem + const decreaseResponse = await request(context, 'PATCH', + `${smartLoadingBase}/plans/${loadingPlanId}/items/${encodeURIComponent(id(adjustedItem?.id))}`, { + packageCount: 1, expectedPlanVersion: Number(adjustedPlan?.version), + expectedItemVersion: Number(adjustedItem?.version), + operationId: `${context.marker}-dynamic-adjust-down`.slice(0, 128), + }) + const decreasedPlan = context.apiSuccess(MODULE, '未拣动态增量明细允许向下调整数量', + decreaseResponse, '', OPTIONS) + const decreasedItem = decreasedPlan?.items?.find?.((item) => id(item?.id) === id(adjustedItem?.id)) + context.assert(MODULE, '向下调整后版本递增且权威总数与剩余数同步', decreaseResponse, + Number(decreasedPlan?.version) > Number(adjustedPlan?.version) + && Number(decreasedItem?.version) > Number(adjustedItem?.version) + && Number(decreasedItem?.packageCount) === 1 + && Number(decreasedItem?.totalPackageCount) === authoritativeTotal + && Number(decreasedItem?.remainingPackageCount) === authoritativeTotal - 1 + && id(decreasedPlan?.pdaTaskId) === canonicalTaskId, + `planVersion=${decreasedPlan?.version ?? 'missing'}, itemVersion=${decreasedItem?.version ?? 'missing'}, packageCount=${decreasedItem?.packageCount ?? 'missing'}, remainingPackageCount=${decreasedItem?.remainingPackageCount ?? 'missing'}`, + OPTIONS) + const restoreAdjustedResponse = await request(context, 'PATCH', + `${smartLoadingBase}/plans/${loadingPlanId}/items/${encodeURIComponent(id(decreasedItem?.id))}`, { + packageCount: 2, expectedPlanVersion: Number(decreasedPlan?.version), + expectedItemVersion: Number(decreasedItem?.version), + operationId: `${context.marker}-dynamic-adjust-restore`.slice(0, 128), + }) + const restoredAdjustedPlan = context.apiSuccess(MODULE, '向下调整验证后恢复两箱供已拣下限校验', + restoreAdjustedResponse, '', OPTIONS) + const restoredAdjustedItem = restoredAdjustedPlan?.items?.find?.((item) => id(item?.id) === id(decreasedItem?.id)) + context.assert(MODULE, '恢复后版本递增且数量回到两箱', restoreAdjustedResponse, + Number(restoredAdjustedPlan?.version) > Number(decreasedPlan?.version) + && Number(restoredAdjustedItem?.version) > Number(decreasedItem?.version) + && Number(restoredAdjustedItem?.packageCount) === 2 + && Number(restoredAdjustedItem?.totalPackageCount) === authoritativeTotal + && Number(restoredAdjustedItem?.remainingPackageCount) === authoritativeTotal - 2 + && id(restoredAdjustedPlan?.pdaTaskId) === canonicalTaskId, + `planVersion=${restoredAdjustedPlan?.version ?? 'missing'}, itemVersion=${restoredAdjustedItem?.version ?? 'missing'}, packageCount=${restoredAdjustedItem?.packageCount ?? 'missing'}`, + OPTIONS) + effectiveDynamicPlan = restoredAdjustedPlan + reassignedPlanItem = restoredAdjustedItem } const refreshedDynamicTaskResponse = await context.request('GET', taskDetailPath) const refreshedDynamicTask = context.apiSuccess(MODULE, '重新增量后刷新 PDA task detail', refreshedDynamicTaskResponse, '', OPTIONS) @@ -1409,7 +1459,7 @@ export async function run(context) { const beforePickedMutationTask = context.apiSuccess(MODULE, '已拣项负向前读取任务快照', beforePickedMutationTaskResponse, '', OPTIONS) const reducePickedResponse = await request(context, 'PATCH', `${smartLoadingBase}/plans/${loadingPlanId}/items/${encodeURIComponent(id(pickedDynamicPlanItem?.id))}`, { - packageCount: Math.max(1, Number(pickedDynamicPlanItem?.minPackageCount) - 1), + packageCount: Number(pickedDynamicPlanItem?.minPackageCount) - 1, expectedPlanVersion: Number(pickedDynamicPlan?.version), expectedItemVersion: Number(pickedDynamicPlanItem?.version), operationId: `${context.marker}-dynamic-reduce-picked`.slice(0, 128), }) diff --git a/scripts/admin-test-env-modules/resource-allocation-recent-contract.test.mjs b/scripts/admin-test-env-modules/resource-allocation-recent-contract.test.mjs index 81acd3a0c..d93f08f2c 100644 --- a/scripts/admin-test-env-modules/resource-allocation-recent-contract.test.mjs +++ b/scripts/admin-test-env-modules/resource-allocation-recent-contract.test.mjs @@ -16,12 +16,18 @@ test('measurement HTTP acceptance preserves whole-ticket slot identities across assert.match(measurement, /asId\(current\.locationId\) === asId\(prior\.locationId\)/) }) -test('smart-loading HTTP acceptance uses authoritative totals and proves over-allocation zero drift', () => { +test('smart-loading HTTP acceptance covers by-booking reads and bidirectional quantity changes', () => { const loading = source('./phase3-loading.mjs') assert.match(loading, /计划详情由服务端返回权威总箱数和剩余箱数/) assert.match(loading, /authoritativeRemaining === authoritativeTotal - assignedPackageCount/) + assert.match(loading, /计划已有明细后按柜次读取智能装柜详情/) + assert.match(loading, /按柜次详情返回同一计划及权威箱数且数量守恒/) assert.match(loading, /packageCount: authoritativeTotal \+ 1/) - assert.match(loading, /调整箱数超过服务端权威总箱数返回A0400/) + assert.match(loading, /调整箱数超过服务端权威总箱数返回A0422/) + assert.match(loading, /未拣动态增量明细允许向下调整数量/) + assert.match(loading, /Number\(decreasedItem\?\.remainingPackageCount\) === authoritativeTotal - 1/) + assert.match(loading, /向下调整验证后恢复两箱供已拣下限校验/) + assert.match(loading, /packageCount: Number\(pickedDynamicPlanItem\?\.minPackageCount\) - 1/) assert.match(loading, /Number\(afterOverAuthority\?\.version\) === Number\(reassignedPlan\?\.version\)/) assert.match(loading, /Number\(afterOverAuthorityItem\?\.remainingPackageCount\) === authoritativeRemaining/) })