This commit is contained in:
2026-08-18 15:43:58 +08:00
parent 4e4d047862
commit 4b0b3e9172
71 changed files with 523 additions and 724 deletions
@@ -104,6 +104,7 @@ async function createConfirmedWeightEvidence(context, { inboundId, tenantId, pal
const confirmed = context.apiSuccess(MODULE, '人工确认称重图片净重', confirmResponse,
`resultId=${created.id}, palletId=${palletId}`, OPTIONS)
const netWeightKg = Number(confirmed?.netWeightKg)
const grossWeightKg = Number(confirmed?.grossWeightKg)
if (confirmed?.recognitionStatus !== 'CONFIRMED' || !Number.isFinite(netWeightKg) || netWeightKg <= 0) {
return null
}
@@ -117,11 +118,12 @@ async function createConfirmedWeightEvidence(context, { inboundId, tenantId, pal
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)
&& closeTo(workspace?.actualGrossWeightKg, grossWeightKg, 0.001)
&& closeTo(workspace?.actualNetWeightKg, netWeightKg, 0.001)
context.assert(MODULE, '图片张数决定托数且净重汇总已落地', workspaceResponse, persisted,
`confirmedImages=${confirmedRows.length}, expectedPallets=${WEIGHING_IMAGE_COUNT}, netWeight=${netWeightKg}, actual=${workspace?.actualGrossWeightKg ?? 'missing'}`,
`confirmedImages=${confirmedRows.length}, expectedPallets=${WEIGHING_IMAGE_COUNT}, grossWeight=${grossWeightKg}, netWeight=${netWeightKg}, actualGross=${workspace?.actualGrossWeightKg ?? 'missing'}, actualNet=${workspace?.actualNetWeightKg ?? 'missing'}`,
OPTIONS)
return persisted ? { count: confirmedRows.length, netWeightKg } : null
return persisted ? { count: confirmedRows.length, grossWeightKg, netWeightKg } : null
}
function findIsolatedInbound(context) {
@@ -279,7 +281,7 @@ export async function run(context) {
const scanPath = `/api/platform/v1/first-leg/inbounds/${inboundId}/measurement/carton-scans?${query(tenantId)}`
// Keep the isolated sample inside the customer's largest configured inner box (60x50x50cm).
const firstDimensions = { length: 59.1, width: 40.2, height: 30.3, weight: 12.5 }
const firstDimensions = { length: 59.1, width: 40.2, height: 30.3 }
const firstShipmentId = `FBA-${context.marker.slice(-12)}-01`
const firstScanResponse = await multipartRequest(context, scanPath, {
boxCode, ...firstDimensions, scannedShipmentId: firstShipmentId,
@@ -323,7 +325,7 @@ export async function run(context) {
&& Number(countResult?.measurementVersion) === Number(firstScan.measurementVersion) + 1,
`version=${countResult?.measurementVersion ?? 'missing'}`, OPTIONS)
const replacement = { length: 59.5, width: 41.2, height: 31.3, weight: 13.6 }
const replacement = { length: 59.5, width: 41.2, height: 31.3 }
const replacementShipmentId = `FBA-${context.marker.slice(-12)}-02`
const rescanResponse = await multipartRequest(context, scanPath, {
boxCode, ...replacement, scannedShipmentId: replacementShipmentId,
@@ -387,13 +389,12 @@ export async function run(context) {
const draftPayload = {
measurementId: measured.measurementId, version: Number(measured.version),
originalDocumentNo: context.marker, originalGrossWeightKg: replacement.weight * originalPackageCount,
originalVolumeCbm: totalVolume, actualGoodsName: `墨家测量验收-${context.marker.slice(-12)}`,
actualGoodsName: `墨家测量验收-${context.marker.slice(-12)}`,
items: [{
inboundDetailId, itemNo: measuredItem.itemNo,
boxSpecification: measuredItem.boxSpecification, packageCount: originalPackageCount,
lengthCm: replacement.length, widthCm: replacement.width, heightCm: replacement.height,
unitWeightKg: replacement.weight, intelligentImageFileId: measuredItem.intelligentImageFileId,
intelligentImageFileId: measuredItem.intelligentImageFileId,
overLimitWarning: measuredItem.overLimitWarning ?? null,
outerLengthCm: measuredItem.outerLengthCm ?? null, outerWidthCm: measuredItem.outerWidthCm ?? null,
outerHeightCm: measuredItem.outerHeightCm ?? null, remark: context.marker,
@@ -479,16 +480,17 @@ 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?.actualGrossWeightKg, weightEvidence.grossWeightKg, 0.001)
&& closeTo(finalMeasurement?.actualNetWeightKg, weightEvidence.netWeightKg, 0.001)
&& closeTo(finalMeasurement?.actualVolumeCbm, totalVolume)
&& closeTo(finalMeasurement?.volumeWeightKg, volumeWeight),
`processStatus=${finalMeasurement?.processStatus ?? 'missing'}, measurementStatus=${finalMeasurement?.measurementStatus ?? 'missing'}, packages=${finalMeasurement?.actualPackageCount ?? 'missing'}, pallets=${weightEvidence.count}, cargoWeight=${finalMeasurement?.actualGrossWeightKg ?? 'missing'}`, OPTIONS)
`processStatus=${finalMeasurement?.processStatus ?? 'missing'}, measurementStatus=${finalMeasurement?.measurementStatus ?? 'missing'}, packages=${finalMeasurement?.actualPackageCount ?? 'missing'}, pallets=${weightEvidence.count}, grossWeight=${finalMeasurement?.actualGrossWeightKg ?? 'missing'}, netWeight=${finalMeasurement?.actualNetWeightKg ?? '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,
palletCount: weightEvidence.count, actualGrossWeightKg: weightEvidence.grossWeightKg,
}
finishScenario(context, start)
}
+15 -7
View File
@@ -285,10 +285,13 @@ async function fixtureDiscoveryModule() {
assertStringId(weight.fileId, 'weight image file id')
assertEqual(weight.recognitionStatus, 'CONFIRMED', 'weight recognition status')
assertPresent(weight.confirmedAt, 'weight confirmation time')
assertTrue(Number(weight.finalWeightKg) > 0, 'final weight must be positive')
assertTrue(Number(weight.grossWeightKg) > 0, 'gross weight must be positive')
assertTrue(Number(weight.netWeightKg) > 0, 'net weight must be positive')
}
assertApproxEqual(sum(platformMeasurement.weightResults, 'finalWeightKg'),
assertApproxEqual(sum(platformMeasurement.weightResults, 'grossWeightKg'),
platformMeasurement.actualGrossWeightKg, 0.001, 'measurement gross weight aggregate')
assertApproxEqual(sum(platformMeasurement.weightResults, 'netWeightKg'),
platformMeasurement.actualNetWeightKg, 0.001, 'measurement net weight aggregate')
}, {
actualGrossWeightKg: platformMeasurement.actualGrossWeightKg,
weightResultCount: platformMeasurement.weightResults.length,
@@ -468,6 +471,8 @@ async function terminalBillingModule() {
'measurement package count')
assertApproxEqual(summary.actualGrossWeightKg, platformMeasurement.actualGrossWeightKg, 0.001,
'measurement gross weight')
assertApproxEqual(summary.actualNetWeightKg, platformMeasurement.actualNetWeightKg, 0.001,
'measurement net weight')
assertApproxEqual(summary.actualVolumeCbm, platformMeasurement.actualVolumeCbm, 0.000001,
'measurement volume')
assertApproxEqual(summary.volumeWeightKg, platformMeasurement.volumeWeightKg, 0.001,
@@ -488,8 +493,8 @@ async function terminalBillingModule() {
assertStringId(item.id, 'published measurement item id')
const expected = platformById.get(String(item.id))
assertPresent(expected, `platform measurement item ${item.id}`)
for (const field of ['packageCount', 'lengthCm', 'widthCm', 'heightCm', 'unitWeightKg',
'totalWeightKg', 'unitVolumeCbm', 'totalVolumeCbm', 'volumeWeightKg']) {
for (const field of ['packageCount', 'lengthCm', 'widthCm', 'heightCm',
'unitVolumeCbm', 'totalVolumeCbm', 'volumeWeightKg']) {
assertApproxEqual(item[field], expected[field], 0.000001, `${item.itemNo} ${field}`)
}
}
@@ -521,10 +526,13 @@ async function terminalBillingModule() {
assertPresent(expected, `platform weight result ${weight.id}`)
assertEqual(String(weight.fileId), String(expected.fileId), 'weight image file id')
assertEqual(weight.recognitionStatus, 'CONFIRMED', 'published weight status')
assertApproxEqual(weight.finalWeightKg, expected.finalWeightKg, 0.001, 'published final weight')
assertApproxEqual(weight.grossWeightKg, expected.grossWeightKg, 0.001, 'published gross weight')
assertApproxEqual(weight.netWeightKg, expected.netWeightKg, 0.001, 'published net weight')
}
assertApproxEqual(sum(publishedWeights, 'finalWeightKg'),
assertApproxEqual(sum(publishedWeights, 'grossWeightKg'),
merchantBilling.measurementSummary.actualGrossWeightKg, 0.001, 'published weight aggregate')
assertApproxEqual(sum(publishedWeights, 'netWeightKg'),
merchantBilling.measurementSummary.actualNetWeightKg, 0.001, 'published net weight aggregate')
}, { weightResultCount: arrayData(merchantBilling.weightResults).length })
await softLocalStep('phase2-client-billing',
@@ -532,7 +540,7 @@ async function terminalBillingModule() {
const summary = merchantBilling.measurementSummary
const basis = merchantBilling.billingBasis
const fee = merchantBilling.latestFee
assertNumberEqual(basis.actualWeightKg, summary.actualGrossWeightKg, 'billing actual weight')
assertNumberEqual(basis.actualWeightKg, summary.actualNetWeightKg, 'billing actual weight')
assertNumberEqual(basis.actualVolumeCbm, summary.actualVolumeCbm, 'billing actual volume')
assertNumberEqual(basis.actualWeightKg, fee.actualWeightKg, 'fee actual weight')
assertNumberEqual(basis.actualVolumeCbm, fee.actualVolumeCbm, 'fee actual volume')
+3 -3
View File
@@ -126,7 +126,7 @@ export async function runMojiaMeasurementScenario(run, options = {}) {
const boxCode = `${afterPrint.summary.inboundCode}#${printedTotal}-1`
const scanPath = `/api/platform/v1/first-leg/inbounds/${inboundId}/measurement/carton-scans?tenantId=${resolvedTenantId}`
const firstFields = {
boxCode, length: 59.1, width: 40.2, height: 30.3, weight: 12.5,
boxCode, length: 59.1, width: 40.2, height: 30.3,
machineNo: 'MJ-ADMIN-E2E-01', measuredAt: '2026-08-08T10:00:00',
}
const firstResponse = await multipartRequest(run, scanPath, firstFields, imagePath)
@@ -149,7 +149,7 @@ export async function runMojiaMeasurementScenario(run, options = {}) {
}
const rescanResponse = await multipartRequest(run, scanPath, {
boxCode, length: 59.5, width: 41.2, height: 31.3, weight: 13.5,
boxCode, length: 59.5, width: 41.2, height: 31.3,
machineNo: 'MJ-ADMIN-E2E-02', measuredAt: '2026-08-08T10:01:00',
}, imagePath)
const rescan = requireData(run, '墨家同箱复测覆盖', rescanResponse)
@@ -174,7 +174,7 @@ export async function runMojiaMeasurementScenario(run, options = {}) {
if (!submittedPassed) throw new Error('墨家测量提交后状态不正确')
const blockedResponse = await multipartRequest(run, scanPath, {
boxCode, length: 99.1, width: 99.2, height: 99.3, weight: 99.4,
boxCode, length: 99.1, width: 99.2, height: 99.3,
machineNo: 'MJ-ADMIN-E2E-BLOCKED', measuredAt: '2026-08-08T10:02:00',
}, imagePath)
const blockedPassed = blockedResponse.body?.code === 'A0409'