优化
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import test from 'node:test'
|
||||
|
||||
import {
|
||||
confirmedNetSummary,
|
||||
normalizedGrossKg,
|
||||
selectWeightPallet,
|
||||
workspaceWeightMatchesBaseline,
|
||||
} from './inbound-weight-ocr.mjs'
|
||||
|
||||
test('selects a stable complete pallet snapshot without status or availability', () => {
|
||||
const selected = selectWeightPallet([
|
||||
{ palletId: '20', palletCode: 'P-20', palletType: 'STANDARD', capacityCbm: 2, tareWeightKg: 18.5 },
|
||||
{ palletId: '3', palletCode: 'P-03', palletType: 'STANDARD', capacityCbm: 1.5, tareWeightKg: 12 },
|
||||
])
|
||||
assert.equal(selected.palletId, '3')
|
||||
assert.equal(selectWeightPallet([]), null)
|
||||
assert.equal(selectWeightPallet([
|
||||
{ palletId: '3', palletCode: 'P-03', palletType: 'STANDARD', capacityCbm: 1.5 },
|
||||
]), null)
|
||||
})
|
||||
|
||||
test('normalizes gross weight and summarizes confirmed net weight only', () => {
|
||||
assert.equal(normalizedGrossKg(50.125, 'LB'), 22.736)
|
||||
assert.equal(normalizedGrossKg(30, 'KG'), 30)
|
||||
assert.equal(normalizedGrossKg(30, 'UNKNOWN'), null)
|
||||
assert.deepEqual(confirmedNetSummary({ weightResults: [
|
||||
{ recognitionStatus: 'CONFIRMED', netWeightKg: 11.5 },
|
||||
{ recognitionStatus: 'PENDING_CONFIRM', netWeightKg: 99 },
|
||||
{ recognitionStatus: 'CONFIRMED', netWeightKg: 2.125 },
|
||||
] }), { count: 2, complete: true, total: 13.625 })
|
||||
})
|
||||
|
||||
test('cleanup restores a non-empty carton fallback when there were no confirmed images', () => {
|
||||
const initial = { actualGrossWeightKg: 54.4, weightResults: [] }
|
||||
assert.deepEqual(confirmedNetSummary(initial), { count: 0, complete: true, total: 0 })
|
||||
assert.equal(workspaceWeightMatchesBaseline({ actualGrossWeightKg: 54.4 }, 54.4), true)
|
||||
assert.equal(workspaceWeightMatchesBaseline({ actualGrossWeightKg: null }, 54.4), false)
|
||||
assert.equal(workspaceWeightMatchesBaseline({ actualGrossWeightKg: null }, null), true)
|
||||
})
|
||||
|
||||
test('HTTP scenario uses pallet option and net weight contracts without legacy final weight', () => {
|
||||
const source = readFileSync(new URL('inbound-weight-ocr.mjs', import.meta.url), 'utf8')
|
||||
assert.match(source, /\/weight-pallet-options\?tenantId=/)
|
||||
assert.ok(source.indexOf('const palletOptionsResponse') < source.lastIndexOf('const uploadPath'))
|
||||
assert.match(source, /form\.append\('file'/)
|
||||
assert.doesNotMatch(source, /form\.append\('palletId'/)
|
||||
assert.match(source, /palletId:\s*id\(pallet\.palletId\)/)
|
||||
assert.match(source, /grossWeightKg/)
|
||||
assert.match(source, /netWeightKg/)
|
||||
assert.match(source, /palletTareWeightKg/)
|
||||
assert.doesNotMatch(source, /finalWeightKg/)
|
||||
assert.doesNotMatch(source, /pallet\.(?:status|available)/)
|
||||
assert.doesNotMatch(source, /platform:pallet:list/)
|
||||
assert.match(source, /verifyDeleted\(context, target, original, baselineWorkspaceWeight\)/)
|
||||
assert.match(source, /workspaceWeightMatchesBaseline\(cleanup\.workspace, baselineWorkspaceWeight\)/)
|
||||
assert.doesNotMatch(source, /verifyDeleted\([^\n]+baselineConfirmedNet/)
|
||||
})
|
||||
@@ -22,6 +22,47 @@ function closeNumber(actual, expected, tolerance = 0.0005) {
|
||||
return Number.isFinite(Number(actual)) && Math.abs(Number(actual) - Number(expected)) < tolerance
|
||||
}
|
||||
|
||||
function palletSnapshotComplete(pallet) {
|
||||
return Boolean(id(pallet?.palletId))
|
||||
&& typeof pallet?.palletCode === 'string' && pallet.palletCode.length > 0
|
||||
&& typeof pallet?.palletType === 'string' && pallet.palletType.length > 0
|
||||
&& Number.isFinite(Number(pallet?.capacityCbm)) && Number(pallet.capacityCbm) > 0
|
||||
&& Number.isFinite(Number(pallet?.tareWeightKg)) && Number(pallet.tareWeightKg) >= 0
|
||||
}
|
||||
|
||||
export function selectWeightPallet(options) {
|
||||
if (!Array.isArray(options)) return null
|
||||
return [...options]
|
||||
.filter(palletSnapshotComplete)
|
||||
.sort((left, right) => id(left.palletId).localeCompare(id(right.palletId), 'en', { numeric: true }))[0] || null
|
||||
}
|
||||
|
||||
export function normalizedGrossKg(value, unit) {
|
||||
const numeric = Number(value)
|
||||
if (!Number.isFinite(numeric)) return null
|
||||
const normalizedUnit = String(unit || '').trim().toUpperCase()
|
||||
if (!['KG', 'KGS', 'LB', 'LBS'].includes(normalizedUnit)) return null
|
||||
const kg = ['LB', 'LBS'].includes(normalizedUnit) ? numeric * 0.45359237 : numeric
|
||||
return Math.round(kg * 1000) / 1000
|
||||
}
|
||||
|
||||
export function confirmedNetSummary(workspace) {
|
||||
const confirmed = (workspace?.weightResults || [])
|
||||
.filter((row) => row?.recognitionStatus === 'CONFIRMED')
|
||||
const values = confirmed.map((row) => Number(row?.netWeightKg))
|
||||
return {
|
||||
count: confirmed.length,
|
||||
complete: values.every((value) => Number.isFinite(value) && value > 0),
|
||||
total: Math.round(values.reduce((sum, value) => sum + value, 0) * 1000) / 1000,
|
||||
}
|
||||
}
|
||||
|
||||
export function workspaceWeightMatchesBaseline(workspace, baselineWorkspaceWeight) {
|
||||
return baselineWorkspaceWeight == null
|
||||
? workspace?.actualGrossWeightKg == null
|
||||
: closeNumber(workspace?.actualGrossWeightKg, baselineWorkspaceWeight, 0.0011)
|
||||
}
|
||||
|
||||
function expectedConflict(response) {
|
||||
return response?.http === 200 && ['A0409', '409'].includes(String(response?.body?.code))
|
||||
}
|
||||
@@ -161,7 +202,11 @@ function deletePath(tenantId, inboundId, resultId, version) {
|
||||
return `${resultPath(inboundId, resultId)}?tenantId=${encodeURIComponent(tenantId)}&version=${version}`
|
||||
}
|
||||
|
||||
async function createUploadedResult(context, target, image, overrides = {}) {
|
||||
function palletOptionsPath(tenantId, inboundId) {
|
||||
return `/api/platform/v1/first-leg/inbounds/${encodeURIComponent(inboundId)}/weight-pallet-options?tenantId=${encodeURIComponent(tenantId)}`
|
||||
}
|
||||
|
||||
async function createUploadedResult(context, target, pallet, image, overrides = {}) {
|
||||
const imagePath = `/api/platform/v1/files/measurements/${encodeURIComponent(target.tenantId)}/${encodeURIComponent(target.inboundId)}`
|
||||
const uploadResponse = await multipart(context, imagePath, image)
|
||||
const upload = context.apiSuccess(MODULE, '上传称重图片并执行 OCR', uploadResponse,
|
||||
@@ -195,6 +240,7 @@ async function createUploadedResult(context, target, image, overrides = {}) {
|
||||
|
||||
const payload = {
|
||||
fileId,
|
||||
palletId: id(pallet.palletId),
|
||||
ocrProvider: `ADMIN_ACCEPTANCE_${context.marker.replace(/[^A-Za-z0-9]/g, '').slice(-24)}`,
|
||||
ocrRawText: overrides.manual ? null : (recognized.ocrRawText || null),
|
||||
ocrWeightValue: overrides.manual ? null : recognized.weightValue,
|
||||
@@ -215,8 +261,9 @@ async function createUploadedResult(context, target, image, overrides = {}) {
|
||||
const resultId = id(result?.id)
|
||||
context.assert(MODULE, '重量结果 ID、文件 ID 和初始版本契约正确', createResponse,
|
||||
Boolean(resultId) && typeof result?.id === 'string' && typeof result?.fileId === 'string'
|
||||
&& id(result?.fileId) === fileId && Number(result?.version) === 0,
|
||||
`resultIdType=${typeof result?.id}, fileIdType=${typeof result?.fileId}, version=${result?.version ?? 'missing'}`,
|
||||
&& id(result?.fileId) === fileId && id(result?.palletId) === id(pallet.palletId)
|
||||
&& Number(result?.version) === 0,
|
||||
`resultIdType=${typeof result?.id}, fileIdType=${typeof result?.fileId}, palletId=${id(result?.palletId) || 'missing'}, version=${result?.version ?? 'missing'}`,
|
||||
SCENARIO_OPTIONS)
|
||||
if (!resultId) throw new Error(`文件 ${fileId} 已上传但重量结果登记失败,需要人工清理该测试文件`)
|
||||
return { upload: recognized, fileId, result, resultId, version: Number(result.version), deleted: false }
|
||||
@@ -267,14 +314,12 @@ async function deleteResult(context, target, item, name, options = NEW_CONTRACT_
|
||||
return { response, passed }
|
||||
}
|
||||
|
||||
async function verifyDeleted(context, target, item, baselineWeight) {
|
||||
async function verifyDeleted(context, target, item, baselineWorkspaceWeight) {
|
||||
const check = await loadWorkspace(context, target, '删除后回查重量工作区')
|
||||
const missing = !check.workspace?.weightResults?.some((row) => id(row.id) === item.resultId)
|
||||
context.assert(MODULE, '删除后结果消失且总毛重恢复基线', check.response,
|
||||
missing && (baselineWeight == null
|
||||
? check.workspace?.actualGrossWeightKg == null
|
||||
: closeNumber(check.workspace?.actualGrossWeightKg, baselineWeight)),
|
||||
`resultMissing=${missing}, baseline=${baselineWeight ?? 'null'}, actual=${check.workspace?.actualGrossWeightKg ?? 'null'}`,
|
||||
context.assert(MODULE, '删除后结果消失且工作区重量恢复运行前基线', check.response,
|
||||
missing && workspaceWeightMatchesBaseline(check.workspace, baselineWorkspaceWeight),
|
||||
`resultMissing=${missing}, baselineWorkspaceWeight=${baselineWorkspaceWeight ?? 'null'}, actual=${check.workspace?.actualGrossWeightKg ?? 'null'}`,
|
||||
NEW_CONTRACT_OPTIONS)
|
||||
|
||||
const imagePath = `/api/platform/v1/files/measurements/${encodeURIComponent(target.tenantId)}/${encodeURIComponent(target.inboundId)}/${encodeURIComponent(item.fileId)}`
|
||||
@@ -313,12 +358,50 @@ export async function run(context) {
|
||||
const image = { bytes: imageBytes, name: basename(imagePath), contentType: 'image/jpeg' }
|
||||
const initial = await loadWorkspace(context, target, '读取 OCR 测试前重量工作区')
|
||||
if (!initial.workspace) throw new Error('无法读取测试入库单重量工作区')
|
||||
const baselineWeight = initial.workspace.actualGrossWeightKg
|
||||
const baselineWorkspaceWeight = initial.workspace.actualGrossWeightKg
|
||||
const baselineImageSummary = confirmedNetSummary(initial.workspace)
|
||||
const baselineIds = new Set((initial.workspace.weightResults || []).map((row) => id(row.id)))
|
||||
context.assert(MODULE, '测试入库单身份与基线可追踪', initial.response,
|
||||
id(initial.workspace.inboundId) === target.inboundId
|
||||
&& initial.workspace.processStatus === target.detail.summary.processStatus,
|
||||
`existingResults=${baselineIds.size}, baselineWeight=${baselineWeight ?? 'null'}`, SCENARIO_OPTIONS)
|
||||
&& initial.workspace.processStatus === target.detail.summary.processStatus
|
||||
&& baselineImageSummary.complete,
|
||||
`existingResults=${baselineIds.size}, confirmedImageCount=${baselineImageSummary.count}, baselineImageNetTotal=${baselineImageSummary.total}, baselineWorkspaceWeight=${baselineWorkspaceWeight ?? 'null'}`,
|
||||
NEW_CONTRACT_OPTIONS)
|
||||
if (!baselineImageSummary.complete) {
|
||||
const steps = context.steps.slice(scenarioStart)
|
||||
context.createdResources.inboundWeightOcr.cleaned = true
|
||||
context.scenarios.push({
|
||||
name: SCENARIO, module: MODULE, success: false,
|
||||
deploymentBlocked: steps.some((step) => step.deploymentBlocker),
|
||||
passed: steps.filter((step) => step.passed).length,
|
||||
failed: steps.filter((step) => !step.passed).length,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const palletOptionsResponse = await context.request(
|
||||
'GET', palletOptionsPath(target.tenantId, target.inboundId),
|
||||
)
|
||||
const palletOptions = context.apiSuccess(MODULE, '读取同仓称重托盘候选', palletOptionsResponse,
|
||||
`inboundId=${target.inboundId}`, NEW_CONTRACT_OPTIONS)
|
||||
const palletOptionsComplete = Array.isArray(palletOptions) && palletOptions.length > 0
|
||||
&& palletOptions.every(palletSnapshotComplete)
|
||||
context.assert(MODULE, '托盘候选包含稳定快照字段且无需状态或占用资格', palletOptionsResponse,
|
||||
palletOptionsComplete,
|
||||
`count=${Array.isArray(palletOptions) ? palletOptions.length : 'invalid'}, fields=palletId/palletCode/palletType/capacityCbm/tareWeightKg`,
|
||||
NEW_CONTRACT_OPTIONS)
|
||||
const pallet = palletOptionsComplete ? selectWeightPallet(palletOptions) : null
|
||||
if (!pallet) {
|
||||
const steps = context.steps.slice(scenarioStart)
|
||||
context.createdResources.inboundWeightOcr.cleaned = true
|
||||
context.scenarios.push({
|
||||
name: SCENARIO, module: MODULE, success: false,
|
||||
deploymentBlocked: steps.some((step) => step.deploymentBlocker),
|
||||
passed: steps.filter((step) => step.passed).length,
|
||||
failed: steps.filter((step) => !step.passed).length,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const uploadPath = `/api/platform/v1/files/measurements/${encodeURIComponent(target.tenantId)}/${encodeURIComponent(target.inboundId)}`
|
||||
const noAuth = await multipart(context, uploadPath, image, '')
|
||||
@@ -337,7 +420,7 @@ export async function run(context) {
|
||||
expectedRejection(oversized), `HTTP=${oversized.http}, code=${oversized.body?.code ?? 'missing'}`, SCENARIO_OPTIONS)
|
||||
|
||||
try {
|
||||
const original = await createUploadedResult(context, target, image, { retry: true })
|
||||
const original = await createUploadedResult(context, target, pallet, image, { retry: true })
|
||||
created.push(original)
|
||||
context.createdResources.inboundWeightOcr.resultIds.push(original.resultId)
|
||||
await verifyImages(context, target, original, image)
|
||||
@@ -359,29 +442,41 @@ export async function run(context) {
|
||||
|
||||
const recognizedValue = Number(original.result.ocrWeightValue)
|
||||
const recognizedUnit = original.result.ocrWeightUnit
|
||||
const canConfirmOriginal = Number.isFinite(recognizedValue) && recognizedValue > 0
|
||||
&& ['KG', 'KGS', 'LB', 'LBS'].includes(String(recognizedUnit || '').trim().toUpperCase())
|
||||
const recognizedGrossKg = normalizedGrossKg(recognizedValue, recognizedUnit)
|
||||
const canConfirmOriginal = recognizedGrossKg != null
|
||||
&& recognizedGrossKg > Number(pallet.tareWeightKg)
|
||||
const confirmPayload = canConfirmOriginal
|
||||
? { version: original.version }
|
||||
: {
|
||||
version: original.version, adjustedWeightValue: 1.234, adjustedWeightUnit: 'KG',
|
||||
version: original.version,
|
||||
adjustedWeightValue: Math.round((Number(pallet.tareWeightKg) + 1.234) * 1000) / 1000,
|
||||
adjustedWeightUnit: 'KG',
|
||||
adjustmentReason: `${context.marker} OCR未返回有效重量,人工验收`,
|
||||
}
|
||||
const confirmResponse = await context.request('POST',
|
||||
confirmPath(target.tenantId, target.inboundId, original.resultId), confirmPayload)
|
||||
const confirmed = context.apiSuccess(MODULE, '确认 OCR 重量并计入实际总毛重', confirmResponse,
|
||||
const confirmed = context.apiSuccess(MODULE, '确认 OCR 重量并计入货物总重量', confirmResponse,
|
||||
`usedOriginal=${canConfirmOriginal}`, NEW_CONTRACT_OPTIONS)
|
||||
context.assert(MODULE, '确认结果状态、版本和最终KG正确', confirmResponse,
|
||||
const confirmedGross = Number(confirmed?.grossWeightKg)
|
||||
const confirmedTare = Number(confirmed?.palletTareWeightKg)
|
||||
const confirmedNet = Number(confirmed?.netWeightKg)
|
||||
context.assert(MODULE, '确认结果返回托盘快照、毛重和去皮净重', confirmResponse,
|
||||
confirmed?.recognitionStatus === 'CONFIRMED' && Number(confirmed?.version) === original.version + 1
|
||||
&& Number(confirmed?.finalWeightKg) > 0,
|
||||
`status=${confirmed?.recognitionStatus ?? 'missing'}, version=${confirmed?.version ?? 'missing'}, finalKg=${confirmed?.finalWeightKg ?? 'missing'}`,
|
||||
&& id(confirmed?.palletId) === id(pallet.palletId)
|
||||
&& confirmed?.palletCode === pallet.palletCode && confirmed?.palletType === pallet.palletType
|
||||
&& closeNumber(confirmed?.palletCapacityCbm, pallet.capacityCbm)
|
||||
&& closeNumber(confirmed?.palletTareWeightKg, pallet.tareWeightKg)
|
||||
&& confirmedGross > confirmedTare && confirmedNet > 0
|
||||
&& closeNumber(confirmedNet, confirmedGross - confirmedTare, 0.0011),
|
||||
`status=${confirmed?.recognitionStatus ?? 'missing'}, palletId=${id(confirmed?.palletId) || 'missing'}, grossKg=${confirmed?.grossWeightKg ?? 'missing'}, tareKg=${confirmed?.palletTareWeightKg ?? 'missing'}, netKg=${confirmed?.netWeightKg ?? 'missing'}`,
|
||||
NEW_CONTRACT_OPTIONS)
|
||||
original.version = Number(confirmed?.version ?? original.version)
|
||||
const afterConfirm = await loadWorkspace(context, target, '确认后回查实际总毛重')
|
||||
const expectedTotal = Number(baselineWeight || 0) + Number(confirmed?.finalWeightKg || 0)
|
||||
context.assert(MODULE, '确认后实际总毛重按服务端结果重算', afterConfirm.response,
|
||||
closeNumber(afterConfirm.workspace?.actualGrossWeightKg, expectedTotal),
|
||||
`baseline=${baselineWeight ?? 'null'}, added=${confirmed?.finalWeightKg ?? 'missing'}, actual=${afterConfirm.workspace?.actualGrossWeightKg ?? 'missing'}`,
|
||||
const afterConfirm = await loadWorkspace(context, target, '确认后回查货物总重量')
|
||||
const confirmedSummary = confirmedNetSummary(afterConfirm.workspace)
|
||||
context.assert(MODULE, '货物总重量按全部已确认净重由服务端汇总', afterConfirm.response,
|
||||
confirmedSummary.complete && confirmedSummary.count === baselineImageSummary.count + 1
|
||||
&& closeNumber(afterConfirm.workspace?.actualGrossWeightKg, confirmedSummary.total, 0.0011),
|
||||
`confirmedCount=${confirmedSummary.count}, confirmedNetTotal=${confirmedSummary.total}, actual=${afterConfirm.workspace?.actualGrossWeightKg ?? 'missing'}`,
|
||||
NEW_CONTRACT_OPTIONS)
|
||||
|
||||
const staleDelete = await context.request('DELETE',
|
||||
@@ -389,9 +484,9 @@ export async function run(context) {
|
||||
context.assert(MODULE, '旧版本删除返回并发冲突', staleDelete, expectedConflict(staleDelete),
|
||||
`HTTP=${staleDelete.http}, code=${staleDelete.body?.code ?? 'missing'}`, NEW_CONTRACT_OPTIONS)
|
||||
const deletedOriginal = await deleteResult(context, target, original, '删除本轮已确认图片及重量结果')
|
||||
if (deletedOriginal.passed) await verifyDeleted(context, target, original, baselineWeight)
|
||||
if (deletedOriginal.passed) await verifyDeleted(context, target, original, baselineWorkspaceWeight)
|
||||
|
||||
const manual = await createUploadedResult(context, target, image, { manual: true })
|
||||
const manual = await createUploadedResult(context, target, pallet, image, { manual: true })
|
||||
created.push(manual)
|
||||
context.createdResources.inboundWeightOcr.resultIds.push(manual.resultId)
|
||||
await rejectWithoutMutation(context, target, manual, '零重量确认被拒绝', {
|
||||
@@ -408,7 +503,7 @@ export async function run(context) {
|
||||
adjustedWeightUnit: 'KG', adjustmentReason: context.marker,
|
||||
})
|
||||
|
||||
const adjustedValue = 10.125
|
||||
const adjustedValue = Math.ceil(((Number(pallet.tareWeightKg) + 5) / 0.45359237) * 1000) / 1000
|
||||
const adjustedConfirmResponse = await context.request('POST',
|
||||
confirmPath(target.tenantId, target.inboundId, manual.resultId), {
|
||||
version: manual.version, adjustedWeightValue: adjustedValue, adjustedWeightUnit: 'LB',
|
||||
@@ -416,16 +511,19 @@ export async function run(context) {
|
||||
})
|
||||
const adjusted = context.apiSuccess(MODULE, '人工改重与确认原子完成', adjustedConfirmResponse,
|
||||
`adjusted=${adjustedValue} LB`, NEW_CONTRACT_OPTIONS)
|
||||
const expectedKg = Math.round(adjustedValue * 0.45359237 * 1000) / 1000
|
||||
context.assert(MODULE, 'LB 人工改重保留输入并正确换算最终KG', adjustedConfirmResponse,
|
||||
const expectedGrossKg = Math.round(adjustedValue * 0.45359237 * 1000) / 1000
|
||||
const expectedNetKg = Math.round((expectedGrossKg - Number(pallet.tareWeightKg)) * 1000) / 1000
|
||||
context.assert(MODULE, 'LB 人工改重保留毛重输入并正确换算去皮净重', adjustedConfirmResponse,
|
||||
adjusted?.recognitionStatus === 'CONFIRMED' && Number(adjusted?.version) === manual.version + 2
|
||||
&& closeNumber(adjusted?.adjustedWeightValue, adjustedValue)
|
||||
&& adjusted?.adjustedWeightUnit === 'LB' && closeNumber(adjusted?.finalWeightKg, expectedKg),
|
||||
`adjusted=${adjusted?.adjustedWeightValue ?? 'missing'} ${adjusted?.adjustedWeightUnit ?? ''}, finalKg=${adjusted?.finalWeightKg ?? 'missing'}, expectedKg=${expectedKg}`,
|
||||
&& adjusted?.adjustedWeightUnit === 'LB'
|
||||
&& closeNumber(adjusted?.grossWeightKg, expectedGrossKg, 0.0011)
|
||||
&& closeNumber(adjusted?.netWeightKg, expectedNetKg, 0.0011),
|
||||
`adjusted=${adjusted?.adjustedWeightValue ?? 'missing'} ${adjusted?.adjustedWeightUnit ?? ''}, grossKg=${adjusted?.grossWeightKg ?? 'missing'}, netKg=${adjusted?.netWeightKg ?? 'missing'}, expectedNetKg=${expectedNetKg}`,
|
||||
NEW_CONTRACT_OPTIONS)
|
||||
manual.version = Number(adjusted?.version ?? manual.version)
|
||||
const deletedManual = await deleteResult(context, target, manual, '删除本轮人工改重图片及结果')
|
||||
if (deletedManual.passed) await verifyDeleted(context, target, manual, baselineWeight)
|
||||
if (deletedManual.passed) await verifyDeleted(context, target, manual, baselineWorkspaceWeight)
|
||||
} finally {
|
||||
for (const item of created.filter((value) => !value.deleted)) {
|
||||
await deleteResult(context, target, item, '异常收尾清理本轮重量结果', NEW_CONTRACT_OPTIONS)
|
||||
@@ -433,11 +531,10 @@ export async function run(context) {
|
||||
const cleanup = await loadWorkspace(context, target, '最终清理后回查重量工作区')
|
||||
const createdIds = new Set(created.map((item) => item.resultId))
|
||||
const leftovers = (cleanup.workspace?.weightResults || []).filter((row) => createdIds.has(id(row.id)))
|
||||
const restored = leftovers.length === 0 && (baselineWeight == null
|
||||
? cleanup.workspace?.actualGrossWeightKg == null
|
||||
: closeNumber(cleanup.workspace?.actualGrossWeightKg, baselineWeight))
|
||||
context.assert(MODULE, '仅清理本轮结果且订单总毛重恢复运行前基线', cleanup.response,
|
||||
restored, `leftovers=${leftovers.length}, baseline=${baselineWeight ?? 'null'}, actual=${cleanup.workspace?.actualGrossWeightKg ?? 'null'}`,
|
||||
const restored = leftovers.length === 0
|
||||
&& workspaceWeightMatchesBaseline(cleanup.workspace, baselineWorkspaceWeight)
|
||||
context.assert(MODULE, '仅清理本轮结果且工作区重量恢复运行前基线', cleanup.response,
|
||||
restored, `leftovers=${leftovers.length}, baselineWorkspaceWeight=${baselineWorkspaceWeight ?? 'null'}, actual=${cleanup.workspace?.actualGrossWeightKg ?? 'null'}`,
|
||||
NEW_CONTRACT_OPTIONS)
|
||||
context.createdResources.inboundWeightOcr.cleaned = restored
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user