This commit is contained in:
2026-08-10 11:28:57 +08:00
parent e33fb923e4
commit 047f267d4f
17 changed files with 290 additions and 67 deletions
@@ -317,6 +317,21 @@ export async function run(context) {
const firstPhoto = evidenceItems.find((item) => item.evidenceType === 'PHOTO_STEP_1')
const sealEvidence = evidenceItems.find((item) => item.evidenceType === 'SEAL')
const appendedUpload = await uploadEvidence(context, tenantId, inboundId, 'PHOTO_STEP_1')
const appendedFile = context.apiSuccess(MODULE, '追加同类型第二张装柜证据文件', appendedUpload, '', OPTIONS)
const appendedFileId = id(appendedFile?.fileId)
const appended = appendedFileId
? await bindEvidence(context, base, tenantId, 'PHOTO_STEP_1', appendedFileId, suffix, 'PHOTO_STEP_1_APPEND')
: appendedUpload
const appendedData = context.apiSuccess(MODULE, '追加同类型第二张装柜证据', appended, '', OPTIONS)
const appendedItems = appendedData?.evidences?.evidences?.filter?.((item) => item.evidenceType === 'PHOTO_STEP_1') || []
context.assert(MODULE, '同类型装柜证据支持多图追加且不替换历史', appended,
Boolean(appendedFileId) && appendedItems.length >= 2
&& appendedItems.some((item) => id(item.fileId) === id(firstPhoto?.fileId))
&& appendedItems.some((item) => id(item.fileId) === appendedFileId),
`photoStep1Count=${appendedItems.length}, original=${id(firstPhoto?.fileId) || 'missing'}, appended=${appendedFileId || 'missing'}`, OPTIONS)
const wrongType = await bindEvidence(context, base, tenantId, 'PHOTO_STEP_2', id(firstPhoto?.fileId), suffix, 'wrong-type')
context.addStep(MODULE, '不同证据类型的真实 fileId 不可交叉绑定', wrongType, failure(wrongType),
`HTTP=${wrongType.http}, code=${codeOf(wrongType)}`, OPTIONS)
@@ -328,10 +343,29 @@ export async function run(context) {
context.addStep(MODULE, '伪造装柜证据 fileId 归属校验拒绝', forged, failure(forged),
`HTTP=${forged.http}, code=${codeOf(forged)}`, OPTIONS)
const missingSealText = await request(context, 'POST', `${base}/loading/evidence?tenantId=${encodeURIComponent(tenantId)}`, {
expectedVersion: Number(sealEvidence?.version), evidenceType: 'SEAL', fileId: id(sealEvidence?.fileId),
fileName: `${context.marker}-missing-seal-text.png`, sealNo: ' ', remark: context.marker,
}, { 'Idempotency-Key': `${context.marker}-p3-missing-seal-text`.slice(0, 128) })
context.addStep(MODULE, '带锁码照片缺少锁码文本时拒绝绑定', missingSealText, failure(missingSealText),
`HTTP=${missingSealText.http}, code=${codeOf(missingSealText)}`, OPTIONS)
const voidTarget = appendedItems.find((item) => id(item.fileId) === appendedFileId)
const voidResponse = voidTarget
? await request(context, 'POST', `${base}/loading/evidence/${encodeURIComponent(id(voidTarget.id))}/void?tenantId=${encodeURIComponent(tenantId)}`,
{ expectedVersion: Number(voidTarget.version), reason: `${context.marker}-wrong-photo` },
{ 'Idempotency-Key': `${context.marker}-p3-evidence-void`.slice(0, 128) })
: appended
const voidData = context.apiSuccess(MODULE, '作废错误装柜证据并保留审计', voidResponse, '', OPTIONS)
context.assert(MODULE, '错图作废后原记录保留且不再计入有效证据', voidResponse,
Boolean(voidTarget) && voidData?.evidences?.evidences?.some?.((item) => id(item.id) === id(voidTarget.id)
&& (item.status === 'VOID' || item.valid === false) && item.voidReason === `${context.marker}-wrong-photo`),
`evidenceId=${id(voidTarget?.id) || 'missing'}, status=${voidTarget?.status || 'missing'}`, OPTIONS)
const evidenceList = await context.request('GET', `${base}/loading/evidence?tenantId=${encodeURIComponent(tenantId)}`)
const evidenceListData = context.apiSuccess(MODULE, '回查五类装柜证据列表', evidenceList, '', OPTIONS)
context.assert(MODULE, '五类装柜证据完整且铅封号持久化', evidenceList,
evidenceListData?.evidences?.length === evidenceTypes.length
evidenceListData?.evidences?.length >= evidenceTypes.length
&& evidenceTypes.every((type) => evidenceListData.evidences.some((item) => item.evidenceType === type))
&& evidenceListData.evidences.some((item) => item.evidenceType === 'SEAL' && item.sealNo === `SEAL-${suffix}`),
`evidences=${evidenceListData?.evidences?.length ?? 'n/a'}`, OPTIONS)
@@ -340,7 +374,7 @@ export async function run(context) {
{ expectedVersion: loadingVersion, remark: context.marker }, { 'Idempotency-Key': `${context.marker}-p3-complete`.slice(0, 128) })
const completed = context.apiSuccess(MODULE, '确认本轮入库单装柜完成', complete, '', OPTIONS)
context.assert(MODULE, '装柜完成推进主状态 LOADED 且保留五类证据', complete,
completed?.mainStatus === 'LOADED' && completed?.evidences?.evidences?.length === evidenceTypes.length,
completed?.mainStatus === 'LOADED' && completed?.evidences?.evidences?.length >= evidenceTypes.length,
`mainStatus=${completed?.mainStatus || 'missing'}, evidences=${completed?.evidences?.evidences?.length ?? 'n/a'}`, OPTIONS)
const finalResponse = await context.request('GET', detailPath)
@@ -355,4 +389,7 @@ export async function run(context) {
pickingTaskId: id(pickingCompleted?.id), marker: context.marker, finalStatus: 'LOADED',
}
context.addCoverageGap(MODULE, OPTIONS.scenario, 'PDA 真机在线限制与设备持久化草稿批量提交',
'当前验收运行器只能发起平台 HTTP 请求,未具备 PDA 真机断网、设备草稿隔离及批量提交端点的可执行环境',
'device-and-batch-fixture')
}