同质量或体积单位不再要求手填系数,普通 http 页面也能生成幂等操作号。 Co-authored-by: Cursor <cursoragent@cursor.com>
193 lines
5.7 KiB
TypeScript
193 lines
5.7 KiB
TypeScript
import assert from 'node:assert/strict'
|
|
import test from 'node:test'
|
|
import {
|
|
measuredSources,
|
|
configurationPayload,
|
|
sourceLabel,
|
|
stopUsageRows,
|
|
unitConversions,
|
|
coefficientFromQuantities,
|
|
permitQuantityFromCoefficient
|
|
} from '../src/components/business/pl-plan-quota-dialog/stop-model'
|
|
const load: any = {
|
|
sourceStopType: 'load',
|
|
sourceStopProductId: 'a',
|
|
planProductId: 'p',
|
|
productName: '硫酸',
|
|
stopOrder: 1,
|
|
quantity: 100,
|
|
unit: '吨',
|
|
contractId: 'c1',
|
|
contractProductId: 'cp1'
|
|
}
|
|
const delivery: any = {
|
|
...load,
|
|
sourceStopType: 'delivery',
|
|
sourceStopProductId: 'b',
|
|
quantity: 40,
|
|
contractId: 'c2',
|
|
contractProductId: 'cp2'
|
|
}
|
|
const plan: any = {
|
|
measurementVersion: 'per_stop_v2',
|
|
configuration: {},
|
|
sourceOptions: [load, delivery],
|
|
usages: []
|
|
}
|
|
test('v2 measures every stop and never sends legacy pairs; absent version stays legacy', () => {
|
|
assert.deepEqual(measuredSources(plan, { p: 'load' }), [load, delivery])
|
|
assert.equal(
|
|
configurationPayload(plan, { sourceMapping: [{ old: true }] } as any, [load], {}).sourceMapping,
|
|
null
|
|
)
|
|
assert.deepEqual(measuredSources({ ...plan, measurementVersion: undefined }, { p: 'load' }), [
|
|
load
|
|
])
|
|
})
|
|
test('source labels use stop and product instead of source UUID', () => {
|
|
assert.equal(sourceLabel('delivery:b', plan.sourceOptions), '送货段1 · 硫酸')
|
|
assert.equal(sourceLabel('load:unknown', []), '来源已不可用')
|
|
})
|
|
test('all stop products are visible and each certificate keeps its unit and quantity', () => {
|
|
const data = {
|
|
...plan,
|
|
stopProducts: [
|
|
{ ...load, isToxic: true },
|
|
{ ...delivery, isToxic: true },
|
|
{ ...load, sourceStopProductId: 'e', isToxic: false, isExplosive: true }
|
|
],
|
|
usages: [
|
|
{
|
|
certType: 'purchase',
|
|
certNoSnapshot: 'BUY',
|
|
quantityUnit: '吨',
|
|
items: [
|
|
{ sourceStopType: 'load', sourceStopProductId: 'a', reservedQty: '100', usedQty: '0' }
|
|
]
|
|
},
|
|
{
|
|
certType: 'transport',
|
|
certNoSnapshot: 'MOVE',
|
|
quantityUnit: '千克',
|
|
items: [
|
|
{ sourceStopType: 'load', sourceStopProductId: 'a', reservedQty: '100000', usedQty: '0' }
|
|
]
|
|
}
|
|
]
|
|
}
|
|
const rows = stopUsageRows(data)
|
|
assert.equal(rows.length, 3)
|
|
assert.equal(rows[0].purchase, 'BUY · 预占 100.000 吨 · 已用 0.000 吨')
|
|
assert.equal(rows[0].transport, 'MOVE · 预占 100000.000 千克 · 已用 0.000 千克')
|
|
assert.equal(rows[1].purchase, '缺配')
|
|
assert.equal(rows[2].purchase, '无需两证')
|
|
})
|
|
test('draft bindings show zeros in their own units and hidden scope never claims missing', () => {
|
|
const rows = stopUsageRows({
|
|
...plan,
|
|
stopProducts: [
|
|
{
|
|
...load,
|
|
isToxic: true,
|
|
bindingsReadable: true,
|
|
certificates: [{ certType: 'purchase', certId: 'cert', certNo: 'BUY', quantityUnit: '桶' }]
|
|
},
|
|
{ ...delivery, isToxic: true, bindingsReadable: false }
|
|
]
|
|
})
|
|
assert.equal(rows[0].purchase, 'BUY · 已绑定 · 预占 0.000 桶 · 已用 0.000 桶')
|
|
assert.equal(rows[1].purchase, '合同或证件不可读取')
|
|
})
|
|
test('legacy counterpart is traceability only, never a second missing allocation', () => {
|
|
const legacy = {
|
|
...plan,
|
|
measurementVersion: 'legacy_single_side',
|
|
configuration: {
|
|
sourceMapping: [
|
|
{ sourceStopType: 'load', sourceStopProductId: 'a', relatedStopProductIds: ['b'] }
|
|
]
|
|
}
|
|
}
|
|
assert.equal(stopUsageRows(legacy as any)[1].purchase, '原口径:关联追溯,不另计量')
|
|
})
|
|
test('unit conversion is only required when the plan unit differs from a bound certificate', () => {
|
|
const same = unitConversions(
|
|
{
|
|
...plan,
|
|
stopProducts: [
|
|
{
|
|
...load,
|
|
certificates: [{ certType: 'purchase', certId: 'buy', certNo: 'BUY', quantityUnit: '吨' }]
|
|
}
|
|
]
|
|
},
|
|
[load]
|
|
)
|
|
const different = unitConversions(
|
|
{
|
|
...plan,
|
|
stopProducts: [
|
|
{
|
|
...load,
|
|
certificates: [
|
|
{ certType: 'purchase', certId: 'buy', certNo: 'BUY', quantityUnit: '吨' },
|
|
{ certType: 'transport', certId: 'move', certNo: 'MOVE', quantityUnit: '千克' },
|
|
{ certType: 'transport', certId: 'pack', certNo: 'PACK', quantityUnit: '瓶' }
|
|
]
|
|
}
|
|
]
|
|
},
|
|
[load]
|
|
)
|
|
assert.deepEqual(same, [])
|
|
assert.deepEqual(
|
|
different.map((row) => row.cert.certNo),
|
|
['PACK']
|
|
)
|
|
const labelAndCode = unitConversions(
|
|
{
|
|
...plan,
|
|
stopProducts: [
|
|
{
|
|
...load,
|
|
certificates: [
|
|
{ certType: 'purchase', certId: 'buy', certNo: 'BUY', quantityUnit: '吨' },
|
|
{ certType: 'transport', certId: 'move', certNo: 'MOVE', quantityUnit: '千克' },
|
|
{ certType: 'transport', certId: 'pack', certNo: 'PACK', quantityUnit: '瓶' }
|
|
]
|
|
}
|
|
]
|
|
},
|
|
[{ ...load, unit: 'dun' }]
|
|
)
|
|
assert.deepEqual(
|
|
labelAndCode.map((row) => row.cert.certNo),
|
|
['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', () => {
|
|
assert.equal(permitQuantityFromCoefficient(30, '1000'), '30000')
|
|
assert.equal(permitQuantityFromCoefficient(30, '0'), '')
|
|
assert.equal(coefficientFromQuantities('30.000', '30000'), '1000')
|
|
})
|