Files
baiyue-firstleg/scripts/fleet-inventory-evidence.mjs
T

54 lines
4.1 KiB
JavaScript
Raw Normal View History

// Internal read-only snapshot for two-customer fleet acceptance. Import has no side effects.
const collections = {
balances: { table: 'll_inventory_balance', fields: 'id customerId customerName overseasWarehouseId overseasWarehouseCode overseasWarehouseName destinationWarehouseId destinationWarehouseCode destinationWarehouseName inboundOrderId inboundOrderNo inboundCode skuCode productNameZh productNameEn availablePackages holdPackages allocatedPackages pickedPackages inTransitPackages receivingPackages procurementPackages version createdAt updatedAt' },
positions: { table: 'll_inventory_position', fields: 'id customerId balanceId overseasWarehouseId destinationWarehouseCode palletId palletNo batchNo warehouseLocationId warehouseLocationCode availablePackages holdPackages allocatedPackages pickedPackages receivingPackages status version createdAt updatedAt' },
ledger: { table: 'll_inventory_ledger', fields: 'id customerId customerName balanceId positionId overseasWarehouseId destinationWarehouseCode inboundOrderId palletId palletNo batchNo warehouseLocationCode skuCode cartonMark cartonPackages businessType businessOrderId businessOrderNo inboundCode inboundOrderNo outboundOrderNo sourceEventId idempotencyKey statusFrom statusTo beforePackages deltaPackages afterPackages operatorId remark occurredAt createdAt' },
}
const snake = value => value.replace(/[A-Z]/g, letter => '_' + letter.toLowerCase())
function validate(scope) {
if (!scope || !/^[A-Za-z0-9_-]{1,100}$/.test(scope.marker || '')
|| ['customerId', 'warehouseId'].some(key => typeof scope[key] !== 'string' || !/^[1-9][0-9]{0,19}$/.test(scope[key]))) {
throw Error('Invalid fleet inventory scope')
}
}
const literal = value => `CONVERT(0x${Buffer.from(value, 'utf8').toString('hex')} USING utf8mb4) COLLATE utf8mb4_bin`
export function buildFleetInventorySql(scope) {
validate(scope)
const where = `BINARY customer_id=BINARY (${literal(scope.customerId)}) AND BINARY overseas_warehouse_id=BINARY (${literal(scope.warehouseId)})`
const queries = []
for (const [collection, { table, fields }] of Object.entries(collections)) {
const json = fields.split(' ').map(field => `'${field}',CAST(${snake(field)} AS CHAR)`).join(',')
queries.push(`SELECT JSON_OBJECT('collection','${collection}','row',JSON_OBJECT(${json})) FROM ${table} WHERE ${where} ORDER BY id;`)
queries.push(`SELECT JSON_OBJECT('collection','${collection}','count',CAST(COUNT(*) AS CHAR)) FROM ${table} WHERE ${where};`)
}
return ['SET NAMES utf8mb4 COLLATE utf8mb4_bin;', 'SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;',
'START TRANSACTION WITH CONSISTENT SNAPSHOT, READ ONLY;', ...queries, 'COMMIT;'].join('\n')
}
export function fleetInventoryFromRows(scope, rows) {
validate(scope)
if (!Array.isArray(rows)) throw Error('Missing fleet inventory snapshot')
const result = { scope: { marker: scope.marker, customerId: scope.customerId, warehouseId: scope.warehouseId, coverage: 'CUSTOMER_WAREHOUSE_COMPLETE' }, balances: [], positions: [], ledger: [] }
const counts = new Map()
for (const entry of rows) {
const definition = collections[entry?.collection]
if (!definition) throw Error('Unexpected fleet inventory collection')
if (Object.hasOwn(entry, 'count')) {
if (counts.has(entry.collection) || entry.row || !/^(0|[1-9][0-9]*)$/.test(String(entry.count))) throw Error('Invalid fleet inventory count')
counts.set(entry.collection, BigInt(entry.count)); continue
}
const row = entry.row
if (!row || definition.fields.split(' ').some(field => !Object.hasOwn(row, field))
|| typeof row.id !== 'string' || !/^[1-9][0-9]*$/.test(row.id)
|| row.customerId !== scope.customerId || row.overseasWarehouseId !== scope.warehouseId) throw Error('Incomplete or foreign fleet inventory row')
result[entry.collection].push(row)
}
for (const name of Object.keys(collections)) {
if (counts.get(name) !== BigInt(result[name].length) || new Set(result[name].map(row => row.id)).size !== result[name].length) {
throw Error('Truncated or duplicated fleet inventory snapshot')
}
}
return result
}