From fe0f1665e55a0be6392e6b0a6db6173e57bfa065 Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Tue, 11 Aug 2026 11:11:57 +0800 Subject: [PATCH] test(admin): align phase3 PDA direct completion fixtures --- .../phase3-container-loading.mjs | 20 ++++++------- .../admin-test-env-modules/phase3-loading.mjs | 12 ++++++-- .../phase3-pda-convergence.mjs | 28 ++++++++++--------- 3 files changed, 34 insertions(+), 26 deletions(-) diff --git a/scripts/admin-test-env-modules/phase3-container-loading.mjs b/scripts/admin-test-env-modules/phase3-container-loading.mjs index 5047c3ed5..11af4f7a9 100644 --- a/scripts/admin-test-env-modules/phase3-container-loading.mjs +++ b/scripts/admin-test-env-modules/phase3-container-loading.mjs @@ -207,15 +207,17 @@ export async function run(context) { } const pickResponse = await request(context, 'POST', `${PDA}/tasks/${taskId}/items/${id(pickItem.id)}/pick`, pickPayload) const picked = context.apiSuccess(MODULE, '执行本轮 PDA 全量拣货', pickResponse, '', OPTIONS) - context.assert(MODULE, '最后一箱拣货后 PDA 任务等待复核', pickResponse, - picked?.taskStatus === 'LOADING' && picked?.workflowStatus === 'AWAITING_REVIEW' + const directPdaCompletion = picked?.taskStatus === 'COMPLETED' + && picked?.workflowStatus === 'COMPLETED' + context.assert(MODULE, '最后一箱拣货后 PDA 任务按已部署契约直接完成', pickResponse, + directPdaCompletion && picked?.items?.every?.((item) => Number(item.pickedPackageCount) === Number(item.plannedPackageCount)), `taskStatus=${picked?.taskStatus || 'missing'}, workflow=${picked?.workflowStatus || 'missing'}`, OPTIONS) const pickReplayResponse = await request(context, 'POST', `${PDA}/tasks/${taskId}/items/${id(pickItem.id)}/pick`, pickPayload) const pickReplay = context.apiSuccess(MODULE, 'PDA operationId 幂等重放', pickReplayResponse, '', OPTIONS) - context.assert(MODULE, 'PDA 重放保持待复核任务和拣货数', pickReplayResponse, - pickReplay?.taskStatus === 'LOADING' && pickReplay?.workflowStatus === 'AWAITING_REVIEW' + context.assert(MODULE, 'PDA 重放保持完成任务和拣货数', pickReplayResponse, + pickReplay?.taskStatus === 'COMPLETED' && pickReplay?.workflowStatus === 'COMPLETED' && pickReplay?.items?.every?.((item) => Number(item.pickedPackageCount) === Number(item.plannedPackageCount)), `taskStatus=${pickReplay?.taskStatus || 'missing'}`, OPTIONS) @@ -223,11 +225,9 @@ export async function run(context) { expectedTaskVersion: Number(picked?.version), operationId: `${context.marker}-pda-review`.slice(0, 128), remark: context.marker, }) - const reviewed = context.apiSuccess(MODULE, '复核本轮柜次 PDA 任务', reviewResponse, '', OPTIONS) - context.assert(MODULE, '复核后任务与柜次计划进入真实完成态', reviewResponse, - reviewed?.taskStatus === 'COMPLETED' && reviewed?.workflowStatus === 'COMPLETED' - && reviewed?.review?.status === 'APPROVED' && Boolean(reviewed?.review?.reviewedBy), - `taskStatus=${reviewed?.taskStatus || 'missing'}, review=${reviewed?.review?.status || 'missing'}`, OPTIONS) + context.addStep(MODULE, 'PDA 已完成后拒绝重复复核', reviewResponse, + directPdaCompletion && reviewResponse.http === 200 && codeOf(reviewResponse) === 'A0409', + `HTTP=${reviewResponse.http}, code=${codeOf(reviewResponse)}`, OPTIONS) const finalPlanResponse = await context.request('GET', `${SMART}/plans/${planId}`) const finalPlan = context.apiSuccess(MODULE, '回查柜次装柜计划终态', finalPlanResponse, '', OPTIONS) @@ -263,7 +263,7 @@ export async function run(context) { context.createdResources.phase3ContainerLoading = { marker: context.marker, tenantId, inboundId, warehouseId, containerBookingId: containerId, - loadingPlanId: planId, pdaTaskId: taskId, pdaReviewVersion: reviewed?.review?.version, + loadingPlanId: planId, pdaTaskId: taskId, finalStatus: 'COMPLETED', } } diff --git a/scripts/admin-test-env-modules/phase3-loading.mjs b/scripts/admin-test-env-modules/phase3-loading.mjs index 11c193184..c8e2c363e 100644 --- a/scripts/admin-test-env-modules/phase3-loading.mjs +++ b/scripts/admin-test-env-modules/phase3-loading.mjs @@ -249,7 +249,9 @@ export async function run(context) { operationId: `${context.marker}-bridge-review`.slice(0, 128), remark: context.marker, }) context.addStep(MODULE, '柜次 PDA 已完成后拒绝重复复核', canonicalReview, - directPdaCompletion ? failure(canonicalReview) : canonicalReview.http === 200 && codeOf(canonicalReview) === '200', + directPdaCompletion + ? canonicalReview.http === 200 && codeOf(canonicalReview) === 'A0409' + : canonicalReview.http === 200 && codeOf(canonicalReview) === '200', `HTTP=${canonicalReview.http}, code=${codeOf(canonicalReview)}`, OPTIONS) const forgedPickingStart = await request(context, 'POST', `${base}/loading/picking/start?tenantId=${encodeURIComponent(tenantId)}`, @@ -266,7 +268,9 @@ export async function run(context) { : context.apiSuccess(MODULE, '开始本轮 PDA 拣货任务', pickingStart, '', OPTIONS) context.addStep(MODULE, directPdaCompletion ? '柜次 PDA 已完成后拒绝旧入库级启动入口' : '开始本轮 PDA 拣货任务', pickingStart, - directPdaCompletion ? failure(pickingStart) : Boolean(pickingStarted), + directPdaCompletion + ? pickingStart.http === 200 && codeOf(pickingStart) === 'A0409' + : Boolean(pickingStarted), `HTTP=${pickingStart.http}, code=${codeOf(pickingStart)}, status=${pickingStarted?.status || 'n/a'}`, OPTIONS) if (!directPdaCompletion) { context.assert(MODULE, 'PDA 拣货任务处于 IN_PROGRESS 且计划数量正确', pickingStart, @@ -289,7 +293,9 @@ export async function run(context) { : context.apiSuccess(MODULE, '完成本轮 PDA 拣货复核', pickingComplete, '', OPTIONS) context.addStep(MODULE, directPdaCompletion ? '柜次 PDA 已完成后拒绝旧入库级完成入口' : '完成本轮 PDA 拣货复核', pickingComplete, - directPdaCompletion ? failure(pickingComplete) : Boolean(pickingCompleted), + directPdaCompletion + ? pickingComplete.http === 200 && codeOf(pickingComplete) === 'A0409' + : Boolean(pickingCompleted), `HTTP=${pickingComplete.http}, code=${codeOf(pickingComplete)}, status=${pickingCompleted?.status || 'n/a'}`, OPTIONS) if (!directPdaCompletion) { context.assert(MODULE, 'PDA 拣货任务 COMPLETED 且数量一致', pickingComplete, diff --git a/scripts/admin-test-env-modules/phase3-pda-convergence.mjs b/scripts/admin-test-env-modules/phase3-pda-convergence.mjs index 1ee63affd..eb19bfe69 100644 --- a/scripts/admin-test-env-modules/phase3-pda-convergence.mjs +++ b/scripts/admin-test-env-modules/phase3-pda-convergence.mjs @@ -19,20 +19,21 @@ export async function run(context) { const fixture = context.createdResources?.phase3Loading const tenantId = id(fixture?.tenantId); const inboundId = id(fixture?.inboundId) const taskId = id(fixture?.canonicalPdaTaskId); const containerNo = fixture?.containerNo - const warehouseId = id(fixture?.warehouseId) - if (!tenantId || !inboundId || !taskId || !containerNo || !warehouseId || fixture?.marker !== context.marker) { + const warehouseId = id(fixture?.warehouseId); const loadingPlanId = id(fixture?.loadingPlanId) + if (!tenantId || !inboundId || !taskId || !containerNo || !warehouseId || !loadingPlanId + || fixture?.marker !== context.marker) { context.addCoverageGap(MODULE, OPTIONS.scenario, 'PDA 柜次拣货与入库单汇总拣货收敛', '本轮未取得 marker 隔离的柜次 PDA 与入库汇总 fixture,未使用历史资源', 'fixture') return } - const taskResponse = await request(context, 'GET', - `/api/platform/v1/first-leg/pda-loading/tasks?containerNo=${encodeURIComponent(containerNo)}&warehouseId=${encodeURIComponent(warehouseId)}`) - const task = context.apiSuccess(MODULE, '回查柜次 PDA 唯一事实任务', taskResponse, '', OPTIONS) - context.assert(MODULE, '柜次任务已领取、复核且明细数量一致', taskResponse, - id(task?.id) === taskId && task?.taskStatus === 'COMPLETED' && task?.workflowStatus === 'COMPLETED' - && Boolean(task?.assignment?.assigneeId) && task?.review?.status === 'APPROVED' - && task?.items?.every?.((item) => Number(item.plannedPackageCount) === Number(item.pickedPackageCount)), - `taskStatus=${task?.taskStatus || 'missing'}, workflow=${task?.workflowStatus || 'missing'}`, OPTIONS) + const loadingListResponse = await request(context, 'GET', + `/api/platform/v1/first-leg/loading-lists/${loadingPlanId}?warehouseId=${encodeURIComponent(warehouseId)}`) + const loadingList = context.apiSuccess(MODULE, '回查柜次 PDA 完成后的装柜清单', loadingListResponse, '', OPTIONS) + context.assert(MODULE, '装柜清单保留 PDA 完成终态和操作者审计', loadingListResponse, + id(loadingList?.summary?.planId) === loadingPlanId && loadingList?.summary?.status === 'COMPLETED' + && loadingList?.histories?.some?.((item) => item.actionType === 'PDA_COMPLETE_LOADING' + && Boolean(item.operatorName) && Boolean(item.occurredAt)), + `planId=${id(loadingList?.summary?.planId) || 'missing'}, status=${loadingList?.summary?.status || 'missing'}`, OPTIONS) const projectionResponse = await request(context, 'GET', `/api/platform/v1/inbounds/${inboundId}/loading/picking?tenantId=${encodeURIComponent(tenantId)}`) const projection = context.apiSuccess(MODULE, '查询入库级 PDA 服务端聚合投影', projectionResponse, '', OPTIONS) @@ -43,9 +44,10 @@ export async function run(context) { const operationsResponse = await request(context, 'GET', `/api/platform/v1/first-leg/pda-loading/tasks/${taskId}/operations`) const operations = context.apiSuccess(MODULE, '查询柜次 PDA 不可变操作历史', operationsResponse, '', OPTIONS) - context.assert(MODULE, '领取和复核操作历史含操作者与时间', operationsResponse, - Array.isArray(operations) && ['CLAIM', 'ITEM_CLAIM', 'REVIEW'].every((action) => operations.some((item) => item.actionType === action - && Boolean(item.operatorId) && Boolean(item.createdAt))), + context.assert(MODULE, '直接完成契约保留领取操作且不伪造复核历史', operationsResponse, + Array.isArray(operations) && operations.some((item) => item.actionType === 'CLAIM' + && Boolean(item.operatorId) && Boolean(item.createdAt)) + && !operations.some((item) => item.actionType === 'REVIEW'), `actions=${Array.isArray(operations) ? operations.map((item) => item.actionType).join(',') : 'missing'}`, OPTIONS) const forged = await request(context, 'POST', `/api/platform/v1/inbounds/${inboundId}/loading/picking/start?tenantId=${encodeURIComponent(tenantId)}`,