This commit is contained in:
2026-10-08 17:07:57 +08:00
parent 16d2d9111a
commit c1ddb658bd
111 changed files with 2914 additions and 941 deletions
+10 -52
View File
@@ -14,6 +14,7 @@ import { mkdir, writeFile } from 'node:fs/promises'
import { randomUUID } from 'node:crypto'
import { resolve } from 'node:path'
import { createInterface } from 'node:readline/promises'
import { frozenOuterMeasurement, publishedMeasurementItemsMatch } from './client-phase2-measurement-evidence.mjs'
const args = parseArgs(process.argv.slice(2))
const gateway = trimSlash(args.gateway ?? process.env.ADMIN_TEST_GATEWAY)
@@ -75,7 +76,6 @@ let pendingFixture
let foreignFixture
let platformTerminalDetail
let platformMeasurement
let dimensionRules = []
let merchantBilling
try {
@@ -192,7 +192,7 @@ async function fixtureDiscoveryModule() {
}))
platformTerminalDetail = detail.json.data
const dimensionConfig = await apiStep('phase2-measurement-fixture',
await apiStep('phase2-measurement-fixture',
'load four customer dimension weighting rules', {
method: 'GET',
path: `/api/platform/v1/first-leg/customer-dimension-config?tenantId=${report.resources.tenantId}`,
@@ -214,7 +214,6 @@ async function fixtureDiscoveryModule() {
version: rule.version,
})),
}))
dimensionRules = dimensionConfig.json.data.rules
const measurement = await apiStep('phase2-measurement-fixture',
'load approved terminal measurement detail', {
@@ -297,9 +296,9 @@ async function fixtureDiscoveryModule() {
})
await softLocalStep('phase2-measurement-fixture',
'carton billing volume uses current customer dimension weighting', () => {
'carton billing volume agrees with frozen calculated outer dimensions', () => {
for (const item of platformMeasurement.items) {
const expected = resolveWeightedDimensions(item, dimensionRules)
const expected = frozenOuterMeasurement(item)
assertApproxEqual(item.unitVolumeCbm, expected.unitVolumeCbm, 0.000001,
`${item.itemNo} weighted unit volume`)
}
@@ -310,7 +309,7 @@ async function fixtureDiscoveryModule() {
measured: dimensions(item),
storedOuter: dimensions(item, 'outer'),
unitVolumeCbm: item.unitVolumeCbm,
expected: resolveWeightedDimensions(item, dimensionRules),
expected: frozenOuterMeasurement(item),
})),
})
@@ -486,22 +485,13 @@ async function terminalBillingModule() {
await softLocalStep('phase2-client-billing', 'published carton measurements match platform snapshot', () => {
const publishedItems = arrayData(merchantBilling.measurementItems)
assertEqual(publishedItems.length, platformMeasurement.items.length, 'published measurement item count')
const platformById = new Map(platformMeasurement.items.map((item) => [String(item.id), item]))
for (const item of publishedItems) {
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',
'unitVolumeCbm', 'totalVolumeCbm', 'volumeWeightKg']) {
assertApproxEqual(item[field], expected[field], 0.000001, `${item.itemNo} ${field}`)
}
}
assertTrue(publishedMeasurementItemsMatch(publishedItems, platformMeasurement.items), 'published outer dimensions and frozen calculation metadata')
}, { measurementItemCount: arrayData(merchantBilling.measurementItems).length })
await softLocalStep('phase2-client-billing', 'published carton volumes follow current weighting rules', () => {
await softLocalStep('phase2-client-billing', 'published carton volumes follow frozen outer dimensions', () => {
const platformById = new Map(platformMeasurement.items.map(item => [String(item.id), item]))
for (const item of arrayData(merchantBilling.measurementItems)) {
const expected = resolveWeightedDimensions(item, dimensionRules)
const expected = frozenOuterMeasurement(platformById.get(String(item.id)))
assertApproxEqual(item.unitVolumeCbm, expected.unitVolumeCbm, 0.000001,
`${item.itemNo} published weighted unit volume`)
}
@@ -510,7 +500,7 @@ async function terminalBillingModule() {
itemNo: item.itemNo,
measured: dimensions(item),
unitVolumeCbm: item.unitVolumeCbm,
expected: resolveWeightedDimensions(item, dimensionRules),
frozenOuter: [item.lengthCm, item.widthCm, item.heightCm],
})),
})
@@ -816,33 +806,6 @@ function assertDimensionRule(rule) {
0.0005, `${rule.boxType} configured volume`)
}
function resolveWeightedDimensions(item, rules) {
const measured = [Number(item.lengthCm), Number(item.widthCm), Number(item.heightCm)]
.sort((left, right) => right - left)
const candidates = [...arrayData(rules)].sort((left, right) =>
Number(left.innerLengthCm) * Number(left.innerWidthCm) * Number(left.innerHeightCm)
- Number(right.innerLengthCm) * Number(right.innerWidthCm) * Number(right.innerHeightCm))
const rule = candidates.find((candidate) => {
const inner = [Number(candidate.innerLengthCm), Number(candidate.innerWidthCm),
Number(candidate.innerHeightCm)].sort((left, right) => right - left)
return measured.every((value, index) => value <= inner[index])
})
if (!rule) {
const rawVolume = measured.reduce((total, value) => total * value, 1) / 1_000_000
return { boxType: null, ruleVersion: null, outer: dimensions(item),
unitVolumeCbm: round(rawVolume, 3) }
}
const edgePair = Number(rule.edgeAdditionCm) * 2
const outer = [Number(rule.innerLengthCm) + edgePair, Number(rule.innerWidthCm) + edgePair,
Number(rule.innerHeightCm) + edgePair]
return {
boxType: rule.boxType,
ruleVersion: rule.version,
outer,
unitVolumeCbm: round(outer.reduce((total, value) => total * value, 1) / 1_000_000, 3),
}
}
function dimensions(value, prefix = '') {
const field = (name) => `${prefix}${prefix ? name[0].toUpperCase() + name.slice(1) : name}`
return [value?.[field('lengthCm')] ?? null, value?.[field('widthCm')] ?? null,
@@ -853,11 +816,6 @@ function sum(values, field) {
return arrayData(values).reduce((total, value) => total + Number(value?.[field] ?? 0), 0)
}
function round(value, scale) {
const factor = 10 ** scale
return Math.round((Number(value) + Number.EPSILON) * factor) / factor
}
function statusCounts(values) {
const counts = {}
for (const row of arrayData(values)) {