feat(pl): 吨千克克和升毫升按固定比例折算用证量。

同质量或体积单位不再要求手填系数,普通 http 页面也能生成幂等操作号。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
wuzilongandCursor committed 2026-11-05 21:14:15 +08:00
1 parent e7f942b399
commit da3ec62719
21 files changed
+277 -43

No files matched your search

+26 -4
View File
@@ -131,7 +131,8 @@ test('unit conversion is only required when the plan unit differs from a bound c
...load,
certificates: [
{ certType: 'purchase', certId: 'buy', certNo: 'BUY', quantityUnit: '吨' },
{ certType: 'transport', certId: 'move', certNo: 'MOVE', quantityUnit: '千克' }
{ certType: 'transport', certId: 'move', certNo: 'MOVE', quantityUnit: '千克' },
{ certType: 'transport', certId: 'pack', certNo: 'PACK', quantityUnit: '瓶' }
]
}
]
@@ -141,7 +142,7 @@ test('unit conversion is only required when the plan unit differs from a bound c
assert.deepEqual(same, [])
assert.deepEqual(
different.map((row) => row.cert.certNo),
['MOVE']
['PACK']
)
const labelAndCode = unitConversions(
{
@@ -151,7 +152,8 @@ test('unit conversion is only required when the plan unit differs from a bound c
...load,
certificates: [
{ certType: 'purchase', certId: 'buy', certNo: 'BUY', quantityUnit: '吨' },
{ certType: 'transport', certId: 'move', certNo: 'MOVE', quantityUnit: '千克' }
{ certType: 'transport', certId: 'move', certNo: 'MOVE', quantityUnit: '千克' },
{ certType: 'transport', certId: 'pack', certNo: 'PACK', quantityUnit: '瓶' }
]
}
]
@@ -160,7 +162,27 @@ test('unit conversion is only required when the plan unit differs from a bound c
)
assert.deepEqual(
labelAndCode.map((row) => row.cert.certNo),
['MOVE']
['PACK']
)
const volume = unitConversions(
{
...plan,
stopProducts: [
{
...load,
unit: '升',
certificates: [
{ certType: 'purchase', certId: 'ml', certNo: 'ML', quantityUnit: '毫升' },
{ certType: 'transport', certId: 'pack', certNo: 'PACK', quantityUnit: '瓶' }
]
}
]
},
[{ ...load, unit: '升' }]
)
assert.deepEqual(
volume.map((row) => row.cert.certNo),
['PACK']
)
})
test('conversion coefficient scales the certificate quantity and can be recovered', () => {
@@ -0,0 +1,33 @@
import assert from 'node:assert/strict'
import test from 'node:test'
import { randomOperationId } from '../src/utils/random-id'
const uuidV4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/
test('secure context keeps the native randomUUID value', () => {
assert.equal(
randomOperationId({ randomUUID: () => 'native-operation-id' }),
'native-operation-id'
)
})
test('insecure context still returns a uuid from getRandomValues', () => {
const insecure = {
getRandomValues(bytes: Uint8Array) {
crypto.getRandomValues(bytes)
return bytes
}
}
const first = randomOperationId(insecure)
const second = randomOperationId(insecure)
assert.match(first, uuidV4)
assert.match(second, uuidV4)
assert.notEqual(first, second)
assert.ok(first.length <= 64)
})
test('missing web crypto still returns a bounded operation id', () => {
const id = randomOperationId({})
assert.match(id, uuidV4)
assert.ok(id.length <= 64)
})