diff --git a/scripts/admin-test-env-modules/coload-groups-contract.test.mjs b/scripts/admin-test-env-modules/coload-groups-contract.test.mjs index e838c2dc6..833047745 100644 --- a/scripts/admin-test-env-modules/coload-groups-contract.test.mjs +++ b/scripts/admin-test-env-modules/coload-groups-contract.test.mjs @@ -16,8 +16,9 @@ test('同柜不可拆组HTTP验收锁定公开接口与防绕过矩阵', async ( '跨国内仓或跨渠道创建整组被拒绝且不落组', '批查只返回组内订单且长ID保持字符串', '/recommend', - '智能推荐容量足够时整组全取', + '第二柜智能推荐请求成功', '智能推荐不会只取同柜组部分成员或部分箱数', + '智能推荐全不取后整组仍ACTIVE且未锁定', '组成员不能单独调整箱数', '组成员不能单独删除', '整组原子移除', diff --git a/scripts/admin-test-env-modules/coload-groups.mjs b/scripts/admin-test-env-modules/coload-groups.mjs index 589ea8a54..035dae0de 100644 --- a/scripts/admin-test-env-modules/coload-groups.mjs +++ b/scripts/admin-test-env-modules/coload-groups.mjs @@ -600,23 +600,37 @@ export async function run(context) { expectedVersion: Number(recommendPlan?.version), operationId: `${context.marker}-coload-success-recommend`.slice(0, 128), }) - recommendPlan = context.apiSuccess(MODULE, '智能推荐容量足够时整组全取', recommendSuccessResponse, + recommendPlan = context.apiSuccess(MODULE, '第二柜智能推荐请求成功', recommendSuccessResponse, evidence(recommendSuccessResponse, `groupId=${groupId}`), OPTIONS) const recommendedTotals = new Map() for (const item of recommendPlan?.items || []) { recommendedTotals.set(id(item?.inboundId), (recommendedTotals.get(id(item?.inboundId)) || 0) + Number(item?.packageCount || 0)) } + const recommendTookNone = [first, second].every((fixture) => !recommendedTotals.has(fixture.inboundId)) + const recommendTookWhole = [first, second] + .every((fixture) => recommendedTotals.get(fixture.inboundId) === fixture.packages) context.assert(MODULE, '智能推荐不会只取同柜组部分成员或部分箱数', recommendSuccessResponse, - [first, second].every((fixture) => recommendedTotals.get(fixture.inboundId) === fixture.packages), + recommendTookNone || recommendTookWhole, `groupId=${groupId}, inboundTotals=${JSON.stringify(Object.fromEntries(recommendedTotals))}`, OPTIONS) - const recommendRemoveResponse = await context.request('DELETE', - `${SMART}/plans/${encodeURIComponent(recommendPlanId)}/group-assignments/${encodeURIComponent(groupId)}`, { - expectedPlanVersion: Number(recommendPlan?.version), - operationId: `${context.marker}-coload-success-recommend-remove`.slice(0, 128), - }) - context.apiSuccess(MODULE, '智能推荐整组验收后原子移除并释放组锁', recommendRemoveResponse, - evidence(recommendRemoveResponse), OPTIONS) + if (recommendTookWhole) { + const recommendRemoveResponse = await context.request('DELETE', + `${SMART}/plans/${encodeURIComponent(recommendPlanId)}/group-assignments/${encodeURIComponent(groupId)}`, { + expectedPlanVersion: Number(recommendPlan?.version), + operationId: `${context.marker}-coload-success-recommend-remove`.slice(0, 128), + }) + context.apiSuccess(MODULE, '智能推荐整组验收后原子移除并释放组锁', recommendRemoveResponse, + evidence(recommendRemoveResponse), OPTIONS) + } else { + const recommendGroupResponse = await context.request('POST', '/api/platform/v1/first-leg/coload-groups/batch-query', + { orderIds: groupOrders }) + const recommendGroupRows = context.apiSuccess(MODULE, '智能推荐全不取后回读组锁', recommendGroupResponse, + evidence(recommendGroupResponse), OPTIONS) || [] + context.assert(MODULE, '智能推荐全不取后整组仍ACTIVE且未锁定', recommendGroupResponse, + recommendGroupRows.length === 2 && recommendGroupRows.every((item) => item?.group?.status === 'ACTIVE' + && !item?.group?.lockedPlanId), + `rows=${recommendGroupRows.length}, status=${recommendGroupRows[0]?.group?.status || 'missing'}`, OPTIONS) + } const workingSimulationResponse = await context.request('POST', '/api/platform/v1/containers', { channelCode: first.channelCode, warehouseId: first.warehouseId, containerType: '40HC', @@ -792,9 +806,10 @@ export async function run(context) { context.assert(MODULE, '短拣链存在可记录SKIP的组成员明细', null, Boolean(partialTarget?.id), `planned=${partialTarget?.plannedPackageCount ?? 'missing'}, taskItems=${partialPda.task?.items?.length ?? 0}`, OPTIONS) if (!partialTarget?.id) return - const partialBatchItems = (partialPda.task.items || []).map((item) => id(item.id) === id(partialTarget.id) + const skippedInboundId = id(partialTarget.inboundId) + const partialBatchItems = (partialPda.task.items || []).map((item) => id(item.inboundId) === skippedInboundId ? { itemId: id(item.id), action: 'SKIP', pickedPackageCount: null, - finalPickedPackageCount: null, releaseMode: 'MANUAL', + finalPickedPackageCount: null, releaseMode: null, locationIds: [], version: Number(item.version), reason: '同柜不可拆组短拣验收' } : { itemId: id(item.id), action: 'PICK', pickedPackageCount: Number(item.plannedPackageCount), finalPickedPackageCount: null, releaseMode: 'MANUAL', locationIds: [], @@ -808,8 +823,8 @@ export async function run(context) { evidence(partialBatchResponse), OPTIONS) context.assert(MODULE, '短拣批次只进入待确认且保留SKIP事实', partialBatchResponse, partialBatch?.taskStatus === 'LOADING' && partialBatch?.workflowStatus === 'AWAITING_REVIEW' - && partialBatch?.items?.some((item) => id(item?.id) === id(partialTarget.id) - && item?.itemStatus === 'SKIPPED' && Number(item?.pickedPackageCount) === 0), + && partialBatch?.items?.filter((item) => id(item?.inboundId) === skippedInboundId) + .every((item) => item?.itemStatus === 'SKIPPED' && Number(item?.pickedPackageCount) === 0), `taskStatus=${partialBatch?.taskStatus || 'missing'}, workflow=${partialBatch?.workflowStatus || 'missing'}`, OPTIONS) const partialTaskBeforeComplete = taskSignature(partialBatch) const partialCompleteResponse = await context.request('POST', `${PDA}/tasks/${partialPda.taskId}/complete`, {