优化
This commit is contained in:
@@ -3,7 +3,8 @@ import { readFile } from 'node:fs/promises'
|
||||
const MODULE = 'inbound-measurement'
|
||||
const SCENARIO = 'mojia-carton-measurement'
|
||||
const OPTIONS = { scenario: SCENARIO, deploymentBlocker: true }
|
||||
const DEFAULT_PALLET_CAPACITY_CBM = 1.2
|
||||
const WEIGHING_IMAGE_COUNT = 1
|
||||
const FIXTURE_PALLET_CAPACITY_CBM = 1.2
|
||||
|
||||
function asId(value) { return value == null ? '' : String(value) }
|
||||
function asNumber(value) { return Number(value) }
|
||||
@@ -37,21 +38,21 @@ async function waitForCompletedMeasurement(context, measurementPath, attempts =
|
||||
return { response, measurement, attempts }
|
||||
}
|
||||
|
||||
async function provisionWarehouseResources(context, { inboundId, warehouseId, totalVolumeCbm }) {
|
||||
const palletCount = Math.ceil(Number(totalVolumeCbm) / DEFAULT_PALLET_CAPACITY_CBM)
|
||||
if (!warehouseId || !Number.isFinite(palletCount) || palletCount < 1) return false
|
||||
async function provisionWarehouseResources(context, { inboundId, warehouseId, palletCount }) {
|
||||
if (!warehouseId || !Number.isInteger(palletCount) || palletCount < 1) return null
|
||||
|
||||
const suffix = `${String(context.marker).replace(/\D/g, '').slice(-8)}${String(inboundId).slice(-6)}`
|
||||
const palletResponse = await context.request('POST', '/api/platform/v1/pallets?tenantId=0', {
|
||||
warehouseId, palletType: 'STANDARD', capacityCbm: FIXTURE_PALLET_CAPACITY_CBM,
|
||||
weightKg: 8, color: '蓝色', remark: `${context.marker}-INBOUND-${inboundId}`,
|
||||
})
|
||||
const palletId = asId(context.apiSuccess(MODULE, '创建称重托盘主数据', palletResponse,
|
||||
`warehouseId=${warehouseId}`, OPTIONS))
|
||||
if (!palletId) return null
|
||||
|
||||
const resources = []
|
||||
for (let index = 1; index <= palletCount; index += 1) {
|
||||
const resourceSuffix = `${suffix}${String(index).padStart(2, '0')}`
|
||||
const palletResponse = await context.request('POST', '/api/platform/v1/pallets?tenantId=0', {
|
||||
warehouseId, palletType: 'STANDARD', capacityCbm: DEFAULT_PALLET_CAPACITY_CBM,
|
||||
weightKg: 8, color: '蓝色', remark: `${context.marker}-INBOUND-${inboundId}`,
|
||||
})
|
||||
const palletId = asId(context.apiSuccess(MODULE, `创建测量占用托盘 ${index}/${palletCount}`,
|
||||
palletResponse, `warehouseId=${warehouseId}`, OPTIONS))
|
||||
|
||||
let locationId = null
|
||||
if (context.context?.phase3LoadingRequireSharedOverflow !== true) {
|
||||
const locationResponse = await context.request('POST', '/api/platform/v1/locations?tenantId=0', {
|
||||
@@ -63,16 +64,64 @@ async function provisionWarehouseResources(context, { inboundId, warehouseId, to
|
||||
locationId = asId(context.apiSuccess(MODULE, `创建测量占用库位 ${index}/${palletCount}`,
|
||||
locationResponse, `warehouseId=${warehouseId}`, OPTIONS))
|
||||
}
|
||||
if (!palletId || (context.context?.phase3LoadingRequireSharedOverflow !== true && !locationId)) return false
|
||||
if (context.context?.phase3LoadingRequireSharedOverflow !== true && !locationId) return null
|
||||
resources.push({ palletId, locationId })
|
||||
}
|
||||
|
||||
context.createdResources.inboundWarehouseResources ??= {}
|
||||
context.createdResources.inboundWarehouseResources[inboundId] = {
|
||||
marker: context.marker, tenantId: '0', warehouseId: asId(warehouseId), palletCount,
|
||||
palletCapacityCbm: DEFAULT_PALLET_CAPACITY_CBM, resources,
|
||||
palletCapacityCbm: FIXTURE_PALLET_CAPACITY_CBM, resources,
|
||||
}
|
||||
return true
|
||||
return { palletId, palletCount, resources }
|
||||
}
|
||||
|
||||
async function createConfirmedWeightEvidence(context, { inboundId, tenantId, palletId }) {
|
||||
const image = await readFile(new URL('../../../apps/pda-uniapp/static/c7.png', import.meta.url))
|
||||
const uploadResponse = await context.requestMultipart('POST',
|
||||
`/api/platform/v1/files/measurements/${tenantId}/${inboundId}`, {
|
||||
content: image, type: 'image/png', name: `weight-${inboundId}.png`,
|
||||
})
|
||||
const upload = context.apiSuccess(MODULE, '上传称重图片并执行 OCR', uploadResponse,
|
||||
`inboundId=${inboundId}`, OPTIONS)
|
||||
const fileId = asId(upload?.fileId)
|
||||
if (!fileId) return null
|
||||
|
||||
const createResponse = await context.request('POST',
|
||||
`/api/platform/v1/first-leg/inbounds/${inboundId}/weight-results?${query(tenantId)}`, {
|
||||
fileId, palletId, ocrProvider: 'ADMIN_ACCEPTANCE', ocrRawText: null,
|
||||
ocrWeightValue: null, ocrWeightUnit: null, confidence: null,
|
||||
})
|
||||
const created = context.apiSuccess(MODULE, '登记称重图片与托盘快照', createResponse,
|
||||
`fileId=${fileId}, palletId=${palletId}`, OPTIONS)
|
||||
if (!created?.id) return null
|
||||
|
||||
const confirmResponse = await context.request('POST',
|
||||
`/api/platform/v1/first-leg/inbounds/${inboundId}/weight-results/${created.id}/confirm?${query(tenantId)}`, {
|
||||
version: Number(created.version), adjustedWeightValue: 100,
|
||||
adjustedWeightUnit: 'KG', adjustmentReason: `${context.marker} 自动化人工确认称重`,
|
||||
})
|
||||
const confirmed = context.apiSuccess(MODULE, '人工确认称重图片净重', confirmResponse,
|
||||
`resultId=${created.id}, palletId=${palletId}`, OPTIONS)
|
||||
const netWeightKg = Number(confirmed?.netWeightKg)
|
||||
if (confirmed?.recognitionStatus !== 'CONFIRMED' || !Number.isFinite(netWeightKg) || netWeightKg <= 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
const workspaceResponse = await context.request('GET',
|
||||
`/api/platform/v1/first-leg/inbounds/${inboundId}/measurement?${query(tenantId)}`)
|
||||
const workspace = context.apiSuccess(MODULE, '回查已确认称重图片和货物总重量', workspaceResponse,
|
||||
`resultId=${created.id}`, OPTIONS)
|
||||
const confirmedRows = (workspace?.weightResults || [])
|
||||
.filter((result) => result?.recognitionStatus === 'CONFIRMED')
|
||||
const persisted = confirmedRows.length === WEIGHING_IMAGE_COUNT
|
||||
&& asId(confirmedRows[0]?.id) === asId(created.id)
|
||||
&& asId(confirmedRows[0]?.palletId) === palletId
|
||||
&& closeTo(workspace?.actualGrossWeightKg, netWeightKg, 0.001)
|
||||
context.assert(MODULE, '图片张数决定托数且净重汇总已落地', workspaceResponse, persisted,
|
||||
`confirmedImages=${confirmedRows.length}, expectedPallets=${WEIGHING_IMAGE_COUNT}, netWeight=${netWeightKg}, actual=${workspace?.actualGrossWeightKg ?? 'missing'}`,
|
||||
OPTIONS)
|
||||
return persisted ? { count: confirmedRows.length, netWeightKg } : null
|
||||
}
|
||||
|
||||
function findIsolatedInbound(context) {
|
||||
@@ -364,17 +413,29 @@ export async function run(context) {
|
||||
}
|
||||
|
||||
const warehouseResourcesReady = await provisionWarehouseResources(context, {
|
||||
inboundId, warehouseId: asId(summary?.warehouseId), totalVolumeCbm: totalVolume,
|
||||
inboundId, warehouseId: asId(summary?.warehouseId), palletCount: WEIGHING_IMAGE_COUNT,
|
||||
})
|
||||
context.assert(MODULE, '测量提交前已创建足量真实托盘和库位', draftResponse,
|
||||
warehouseResourcesReady,
|
||||
`warehouseId=${asId(summary?.warehouseId) || 'missing'}, palletCount=${Math.ceil(totalVolume / DEFAULT_PALLET_CAPACITY_CBM)}`,
|
||||
context.assert(MODULE, '测量提交前按称重图片数准备真实库位', draftResponse,
|
||||
Boolean(warehouseResourcesReady),
|
||||
`warehouseId=${asId(summary?.warehouseId) || 'missing'}, palletCount=${WEIGHING_IMAGE_COUNT}`,
|
||||
OPTIONS)
|
||||
if (!warehouseResourcesReady) {
|
||||
finishScenario(context, start)
|
||||
return
|
||||
}
|
||||
|
||||
const weightEvidence = await createConfirmedWeightEvidence(context, {
|
||||
inboundId, tenantId, palletId: warehouseResourcesReady.palletId,
|
||||
})
|
||||
context.assert(MODULE, '测量提交前已通过正式接口确认称重图片', draftResponse,
|
||||
Boolean(weightEvidence),
|
||||
`confirmedImages=${weightEvidence?.count ?? 0}, expected=${WEIGHING_IMAGE_COUNT}`,
|
||||
OPTIONS)
|
||||
if (!weightEvidence) {
|
||||
finishScenario(context, start)
|
||||
return
|
||||
}
|
||||
|
||||
const submitResponse = await context.request('POST',
|
||||
`/api/platform/v1/first-leg/inbounds/${inboundId}/measurement/submit?${query(tenantId)}`,
|
||||
{ measurementId: draft.measurementId, version: Number(draft.version) })
|
||||
@@ -418,14 +479,16 @@ export async function run(context) {
|
||||
finalMeasurement?.processStatus === 'WAIT_SPLIT' && finalMeasurement?.measureReviewStatus === 'APPROVED'
|
||||
&& finalMeasurement?.measurementStatus === 'APPROVED'
|
||||
&& Number(finalMeasurement?.actualPackageCount) === originalPackageCount
|
||||
&& closeTo(finalMeasurement?.actualGrossWeightKg, weightEvidence.netWeightKg, 0.001)
|
||||
&& closeTo(finalMeasurement?.actualVolumeCbm, totalVolume)
|
||||
&& closeTo(finalMeasurement?.volumeWeightKg, volumeWeight),
|
||||
`processStatus=${finalMeasurement?.processStatus ?? 'missing'}, measurementStatus=${finalMeasurement?.measurementStatus ?? 'missing'}, packages=${finalMeasurement?.actualPackageCount ?? 'missing'}`, OPTIONS)
|
||||
`processStatus=${finalMeasurement?.processStatus ?? 'missing'}, measurementStatus=${finalMeasurement?.measurementStatus ?? 'missing'}, packages=${finalMeasurement?.actualPackageCount ?? 'missing'}, pallets=${weightEvidence.count}, cargoWeight=${finalMeasurement?.actualGrossWeightKg ?? 'missing'}`, OPTIONS)
|
||||
|
||||
context.createdResources.inboundMeasurement = {
|
||||
marker: context.marker, tenantId, inboundId, measurementId: asId(draft.measurementId),
|
||||
boxCode, finalStatus: finalMeasurement?.measurementStatus || null,
|
||||
processStatus: finalMeasurement?.processStatus || null,
|
||||
palletCount: weightEvidence.count, actualGrossWeightKg: weightEvidence.netWeightKg,
|
||||
}
|
||||
finishScenario(context, start)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user