2026-10-04 12:07:37 +08:00
import fs from 'node:fs'
import { createHash } from 'node:crypto'
2026-10-20 10:35:52 +08:00
import { resolve , dirname } from 'node:path'
import { fileURLToPath , pathToFileURL } from 'node:url'
import { AcceptanceRun } from './admin-test-env-acceptance.mjs'
import { redactEvidence } from './fba-core-regression-test-env.mjs'
2026-10-04 12:07:37 +08:00
import { parseCrossCustomerArguments , runCrossCustomer } from './fleet-cross-customer-test-env.mjs'
2026-10-20 10:35:52 +08:00
import { fixtureContract } from './admin-test-env-modules/fleet-cross-customer-acceptance.mjs'
import { version } from './admin-test-env-modules/grouped-dispatch-acceptance.mjs'
2026-10-04 12:07:37 +08:00
import { verifyFleetExternalReceipt } from './admin-test-env-modules/fleet-external-receipt-acceptance.mjs'
import { verifyFleetExternalDispatch } from './admin-test-env-modules/fleet-external-dispatch-acceptance.mjs'
import { expectedAllocations } from './admin-test-env-modules/fleet-trip-cost-acceptance.mjs'
const ROOT = '/api/platform/v1/last-leg' , PDA = '/api/pda/v1/last-leg/dispatches' , MODULE = 'fleet-same-route-cost'
2026-10-20 10:35:52 +08:00
const REPO = resolve ( dirname ( fileURLToPath ( import . meta . url )), '..' )
const demand = ( value , message )=>{ if ( ! value ) throw Error ( message )}
const id = value =>{ demand ( typeof value !== 'number' || Number . isSafeInteger ( value ), 'UNSAFE_ID' ); return String ( value ?? '' )}
const integer = value =>{ demand ([ 'number' , 'string' ]. includes ( typeof value ) && /^(0|[1-9]\d*)$/ . test ( id ( value )) && Number . isSafeInteger ( Number ( value )), 'INVALID_QUANTITY' ); return Number ( value )}
const sorted = value => Array . isArray ( value ) ? value . map ( sorted ) : value && typeof value === 'object' ? Object . fromEntries ( Object . keys ( value ). sort (). map ( key =>[ key , sorted ( value [ key ])])) : value
2026-10-04 12:07:37 +08:00
const same = ( a , b )=> JSON . stringify ( sorted ( a )) === JSON . stringify ( sorted ( b ))
2026-10-20 10:35:52 +08:00
const cents = value =>{ const text = String ( value ); demand ( /^\d+(?:\.\d{1,2})?$/ . test ( text ), 'INVALID_MONEY' ); const [ whole , fraction = '' ] = text . split ( '.' ); return BigInt ( whole ) * 100 n + BigInt ( fraction . padEnd ( 2 , '0' ))}
const encode = encodeURIComponent
const actualValue = ( row , field )=> row ? . evidence ? . some ( e => e . field === field && e . actual === true && e . sourceType && e . sourceBusinessNo && Number . isFinite ( Date . parse ( e . observedAt )) && Number ( e . value ) === Number ( row [ field ]))
// Capacity planning may precede picking. Read native physical pallets and their actual evidence;
// never pass capacity-plan cargo to the loading helper or supply invented picked counts.
export function sameRouteMeasurements ( context , fixture , trip , preview ,{ external = false } = {}) {
demand ( preview ? . dispatchNo === fixture . dispatchNo && preview . status === 'ACTIVE' && preview . pallets ? . length , 'CURRENT_NATIVE_PHYSICAL_PREVIEW_REQUIRED' )
const supplied = fixture . loadingMeasurements
demand ( ! supplied || supplied . environment === 'TEST' && supplied . marker === context . marker && supplied . dispatchNo === fixture . dispatchNo && Array . isArray ( supplied . pallets ), 'CURRENT_TEST_MEASUREMENT_RECEIPT_REQUIRED' )
const actual = structuredClone ( supplied ? . pallets || []), receipt = external ? trip . externalReceipt ? . finalBooking ? . receipt : null
demand ( new Set ( preview . pallets . map ( p => id ( p . warehousePalletId ))). size === preview . pallets . length && preview . pallets . every ( p => id ( p . warehousePalletId ) && p . palletNo ), 'CURRENT_NATIVE_PHYSICAL_PALLET_IDENTITY_REQUIRED' )
if ( external ){
demand ( trip . externalReceipt ? . status === 'VERIFIED' && receipt ? . operatorId && Number . isFinite ( Date . parse ( receipt . confirmedAt )) && receipt . source ? . incomingNo , 'ACTUAL_EXTERNAL_MEASUREMENT_REQUIRED' )
for ( const measured of receipt . pallets || []){
const source = receipt . source . pallets ? . find ( p => id ( p . warehousePalletId ) === id ( measured . warehousePalletId ))
demand ( source , 'ACTUAL_EXTERNAL_MEASUREMENT_REQUIRED' )
actual . push ({ warehousePalletId : id ( measured . warehousePalletId ), palletSpaces : measured . palletSpaces , weightKg : measured . weightKg ?? source . weightKg , volumeCbm : measured . volumeCbm ?? source . volumeCbm ,
deliveryIndex : trip . stops . findIndex ( stop => stop . destinationKey === trip . externalReceipt . finalBooking . cargo . destinationKey ),
evidence : [ 'palletSpaces' , 'weightKg' , 'volumeCbm' ]. map ( field =>({ field , value : field === 'palletSpaces' ? measured [ field ] : measured [ field ] ?? source [ field ], actual : true ,
sourceType : 'FLEET_RECEIPT_CONFIRMATION' , sourceBusinessNo : receipt . source . incomingNo , observedAt : receipt . confirmedAt }))})
}
}
demand ( new Set ( actual . map ( p => id ( p . warehousePalletId ))). size === actual . length , 'DUPLICATE_ACTUAL_MEASUREMENT' )
const expected = new Set ([... preview . pallets . map ( p => id ( p . warehousePalletId )),...( receipt ? . source ? . pallets || []). map ( p => id ( p . warehousePalletId ))])
demand ( actual . every ( p => expected . has ( id ( p . warehousePalletId ))), 'FOREIGN_ACTUAL_MEASUREMENT' )
const pallets = [... expected ]. map ( palletId =>{
const physical = preview . pallets . find ( p => id ( p . warehousePalletId ) === palletId ), suppliedRow = actual . find ( p => id ( p . warehousePalletId ) === palletId ), output = { warehousePalletId : palletId , evidence : []}
const sourceBusinessNo = fixture . members ? . find ( m => id ( m . palletId ) === palletId ) ? . incomingNo || ( receipt ? . source ? . pallets ? . some ( p => id ( p . warehousePalletId ) === palletId ) ? receipt . source . incomingNo : null )
demand ( sourceBusinessNo , 'CURRENT_MEASUREMENT_SOURCE_REQUIRED' )
for ( const field of [ 'palletSpaces' , 'weightKg' , 'volumeCbm' ]){
const row = physical ? .[ field ] == null ? suppliedRow : physical , value = row ? .[ field ]
demand ( Number . isFinite ( Number ( value )) && Number ( value ) > 0 && actualValue ( row , field ), 'ACTUAL_LOADING_MEASUREMENT_REQUIRED:' + field )
demand ( actualValue ({... row , evidence : row . evidence . filter ( e => e . sourceBusinessNo === sourceBusinessNo )}, field ), 'CURRENT_MEASUREMENT_SOURCE_REQUIRED' )
demand ( field !== 'palletSpaces' || Number . isSafeInteger ( value ), 'ACTUAL_PALLET_SPACES_MUST_BE_INTEGER' )
demand ( physical ? .[ field ] == null || suppliedRow ? .[ field ] == null || Number ( physical [ field ]) === Number ( suppliedRow [ field ]), 'ACTUAL_MEASUREMENT_CONFLICT' )
output [ field ] = value ; output . evidence . push (... row . evidence . filter ( e => e . field === field ))
}
output . deliveryIndex = physical ? . deliveryIndex ?? suppliedRow ? . deliveryIndex
demand ( Number . isSafeInteger ( output . deliveryIndex ) && output . deliveryIndex > 0 && trip . stops ? .[ output . deliveryIndex ] ? . destinationKey , 'ACTUAL_UNLOADING_STOP_REQUIRED' )
demand ( physical ? . deliveryIndex == null || suppliedRow ? . deliveryIndex == null || physical . deliveryIndex === suppliedRow . deliveryIndex , 'ACTUAL_UNLOADING_STOP_CONFLICT' )
return output
})
return { environment : 'TEST' , marker : context . marker , dispatchNo : fixture . dispatchNo , pallets }
}
2026-10-04 12:07:37 +08:00
export function assertSameRouteBasis ( departure , shares ) {
const load = departure ? . snapshot ? . confirmedLoad , stops = departure ? . snapshot ? . trip ? . stops
2026-10-20 10:35:52 +08:00
demand ( departure ? . action === 'DEPART' && load ? . manifestHash , 'ACTUAL_DEPART_HISTORY_REQUIRED' ); version ( departure . recordVersion )
demand ( shares ? . length === 2 && shares . filter ( s => s . sourceType === 'OWN' ). length === 1 && shares . filter ( s => s . sourceType === 'EXTERNAL' ). length === 1 , 'TWO_ACTUAL_BUSINESS_COST_SOURCES_REQUIRED' )
const own = shares . find ( s => s . sourceType === 'OWN' ), external = shares . find ( s => s . sourceType === 'EXTERNAL' )
demand ( own . dispatchNo && own . businessNo === own . dispatchNo && external . dispatchNo === own . dispatchNo && external . businessNo !== own . businessNo , 'ONE_NATIVE_MAIN_TWO_BUSINESS_IDENTITIES_REQUIRED' )
demand ( own . warehousePalletIds ? . length === 2 && external . warehousePalletIds ? . length === 1 && shares . every ( s => Number . isSafeInteger ( s . palletSpaces ) && s . palletSpaces > 0 ), 'THREE_ACTUAL_PHYSICAL_PALLETS_REQUIRED' )
const ids = shares . flatMap ( s => s . warehousePalletIds ). map ( id )
demand ( new Set ( ids ). size === 3 && load . pallets ? . length === 3 && same ([... ids ]. sort (), load . pallets . map ( p => id ( p . warehousePalletId )). sort ()), 'COMPLETE_DEPART_PALLET_SCOPE_REQUIRED' )
demand ( load . cargo ? . length >= 3 && new Set ( load . pallets . map ( p => p . deliveryIndex )). size === 1 && load . pallets . every ( p => Number . isSafeInteger ( p . deliveryIndex ) && p . deliveryIndex > 0 && stops ? .[ p . deliveryIndex ] ? . destinationKey ), 'SINGLE_REAL_UNLOADING_STOP_REQUIRED' )
demand ( load . cargo . every ( c => ids . includes ( id ( c . warehousePalletId ))), 'FOREIGN_DEPART_CARGO' )
2026-10-04 12:07:37 +08:00
for ( const share of shares ){
2026-10-20 10:35:52 +08:00
const pallets = load . pallets . filter ( p => share . warehousePalletIds . map ( id ). includes ( id ( p . warehousePalletId )))
demand ( pallets . every ( p => Number . isSafeInteger ( p . palletSpaces ) && p . palletSpaces > 0 ) && pallets . reduce (( sum , p )=> sum + p . palletSpaces , 0 ) === share . palletSpaces , 'ACTUAL_CAPACITY_SUM_REQUIRED' )
for ( const pallet of pallets ){
const cargo = load . cargo . filter ( c => id ( c . warehousePalletId ) === id ( pallet . warehousePalletId ))
demand ( cargo . length > 0 && cargo . every ( c => c . dispatchNo === share . dispatchNo && id ( c . customerId ) && integer ( c . packages ) > 0 && c . destinationKey === stops [ pallet . deliveryIndex ]. destinationKey )
&& cargo . reduce (( sum , c )=> sum + integer ( c . packages ), 0 ) === 1 && new Set ( cargo . map ( c => id ( c . customerId ))). size === 1 , 'SOURCE_AND_DESTINATION_MISMATCH' )
}
2026-10-04 12:07:37 +08:00
}
2026-10-20 10:35:52 +08:00
const ownCustomers = new Set ( load . cargo . filter ( c => own . warehousePalletIds . map ( id ). includes ( id ( c . warehousePalletId ))). map ( c => id ( c . customerId )))
demand ( ownCustomers . size === 2 && same ([... ownCustomers ]. sort (), own . customerIds ? . map ( id ). sort ()) && ownCustomers . has ( id ( external . customerId )), 'TWO_REAL_OWN_CUSTOMERS_REQUIRED' )
const externals = ( departure . snapshot . externalBookings || []). filter ( b => ! [ 'DRAFT' , 'CANCELLED' ]. includes ( b . status )), booking = externals [ 0 ]
const accepted = booking ? . receipt , physical = accepted ? . source ? . pallets
demand ( externals . length === 1 && booking . status === 'BOUND' && booking . bookingNo === external . businessNo && booking . dispatchNo === external . dispatchNo && id ( booking . customerId ) === id ( external . customerId )
&& integer ( accepted ? . source ? . receivedPackages ) === 1 && physical ? . length === 1 && integer ( physical [ 0 ]. packages ) === 1 && id ( physical [ 0 ]. warehousePalletId ) === id ( external . warehousePalletIds [ 0 ])
&& load . cargo . filter ( c => id ( c . warehousePalletId ) === id ( physical [ 0 ]. warehousePalletId )). every ( c => id ( c . customerId ) === id ( booking . customerId )), 'ACTUAL_EXTERNAL_RECEIPT_REQUIRED' )
demand ( accepted . pallets ? . length === 1 && id ( accepted . pallets [ 0 ]. warehousePalletId ) === id ( physical [ 0 ]. warehousePalletId ) && accepted . pallets [ 0 ]. palletSpaces === external . palletSpaces , 'ACTUAL_EXTERNAL_CAPACITY_REQUIRED' )
2026-10-04 12:07:37 +08:00
return load
}
2026-10-20 10:35:52 +08:00
export function sameRouteShares ( departure , fixture , receipt , bundle ) {
demand ( bundle ? . detail ? . dispatchNo === fixture . dispatchNo && bundle . items ? . dispatchNo === fixture . dispatchNo && id ( version ( bundle . detail . recordVersion )) === id ( version ( bundle . items . recordVersion )), 'NATIVE_DETAIL_ITEMS_REQUIRED' )
const members = fixture . members , externalId = id ( receipt . warehousePalletId ), ownIds = members . map ( m => id ( m . palletId ))
const items = bundle . items . items , load = departure ? . snapshot ? . confirmedLoad
demand ( items ? . length === 3 && new Set ( items . map ( i => id ( i . warehousePalletId ))). size === 3 && members . every ( m => items . some ( i => id ( i . warehousePalletId ) === id ( m . palletId ) && id ( i . customerId ) === id ( m . customerId ) && i . inboundCode === m . incomingNo && integer ( i . scheduledPackages ) === 1 ))
&& items . some ( i => id ( i . warehousePalletId ) === externalId && id ( i . customerId ) === id ( receipt . createRequest . customerId ) && i . inboundCode === receipt . incomingNo && integer ( i . scheduledPackages ) === 1 ), 'CURRENT_THREE_SOURCE_ITEMS_REQUIRED' )
demand ( load ? . pallets ? . length === 3 , 'ACTUAL_DEPART_HISTORY_REQUIRED' )
const spaces = ids => load . pallets . filter ( p => ids . includes ( id ( p . warehousePalletId ))). reduce (( sum , p )=>{ demand ( Number . isSafeInteger ( p . palletSpaces ) && p . palletSpaces > 0 , 'ACTUAL_CAPACITY_SUM_REQUIRED' ); return sum + p . palletSpaces }, 0 )
const shares = [{ businessNo : fixture . dispatchNo , dispatchNo : fixture . dispatchNo , sourceType : 'OWN' , customerIds : members . map ( m => id ( m . customerId )), warehousePalletIds : ownIds , palletSpaces : spaces ( ownIds )},
{ businessNo : receipt . bookingNo , dispatchNo : fixture . dispatchNo , sourceType : 'EXTERNAL' , customerId : id ( receipt . createRequest . customerId ), warehousePalletIds : [ externalId ], palletSpaces : spaces ([ externalId ])}]
assertSameRouteBasis ( departure , shares ); return shares
}
2026-10-04 12:07:37 +08:00
export function assertSameRouteCost ( summary , departure , shares , amount = '1.00' ) {
const load = assertSameRouteBasis ( departure , shares )
demand ( summary ? . allocationMethod === 'SAME_ROUTE_PALLET_SPACES' && summary . allocationBlockReason == null && id ( summary . departureVersion ) === id ( departure . recordVersion ) && summary . manifestHash === load . manifestHash , 'IMMUTABLE_DEPART_BASIS_REQUIRED' )
demand ( summary . totals ? . length === 1 && summary . totals [ 0 ]. currency === 'USD' , 'SINGLE_ORIGINAL_CURRENCY_REQUIRED' )
2026-10-20 10:35:52 +08:00
const total = summary . totals [ 0 ], expected = expectedAllocations ( amount , shares ), actual = [...( total . allocations || [])]. sort (( a , b )=> a . businessNo < b . businessNo ?- 1 : a . businessNo > b . businessNo ? 1 : 0 ). map ( s =>({ businessNo : s . businessNo , sourceType : s . sourceType , dispatchNo : s . dispatchNo , palletSpaces : integer ( s . palletSpaces ), cents : String ( cents ( s . amount ))}))
2026-10-04 12:07:37 +08:00
demand ( cents ( total . directCost ) === cents ( amount ) && same ( actual , expected ), 'EXACT_LARGEST_REMAINDER_ALLOCATION_REQUIRED' )
2026-10-20 10:35:52 +08:00
demand ( cents ( total . ownCost ) === expected . filter ( s => s . sourceType === 'OWN' ). reduce (( sum , s )=> sum + BigInt ( s . cents ), 0 n ) && cents ( total . externalCost ) === expected . filter ( s => s . sourceType === 'EXTERNAL' ). reduce (( sum , s )=> sum + BigInt ( s . cents ), 0 n ) && cents ( total . ownCost ) + cents ( total . externalCost ) === cents ( amount ), 'OWN_EXTERNAL_CENT_CONSERVATION_REQUIRED' )
2026-10-04 12:07:37 +08:00
return expected
}
2026-10-20 10:35:52 +08:00
// Explicit test fees belong to each actual own customer/destination group. The
// received external pallet shares its customer's group and retains its own quote.
export function sameRouteArrangement ( context , fixture ) {
demand ( context . marker === fixture . marker && fixture . dispatchNo && fixture . members ? . length === 2 && new Set ( fixture . members . map ( m => id ( m . customerId ))). size === 2
&& fixture . members . every ( m => m . marker === context . marker && m . dispatchNo === fixture . dispatchNo && /^[1-9]\d*$/ . test ( id ( m . customerId )) && m . destination ? . key ? . startsWith ( 'FBA:' ))
&& new Set ( fixture . members . map ( m => m . destination . key )). size === 1 , 'CURRENT_TWO_CUSTOMER_DESTINATION_GROUPS_REQUIRED' )
return { mode : 'NATIVE' , marker : context . marker , dispatchNo : fixture . dispatchNo , plannedDeliveryAt : new Date ( Date . now () + 21600000 ). toISOString (),
deliveryMethod : 'TRUCK_PALLET' , pickupMethod : 'WAREHOUSE_PICKUP' , loadingType : 'PALLET' , appointmentAccount : 'SELF' , vehicleType : 'TRUCK' , remark : ` ${ context . marker } TEST synthetic customer delivery fees` ,
groups : fixture . members . map ( m =>({ customerId : id ( m . customerId ), destinationKey : m . destination . key ,
fees : [{ direction : 'RECEIVABLE' , feeType : 'DELIVERY_FEE' , feeName : '本轮合成测试派送费' , currency : 'CNY' , amount : '30.00' }]}))}
}
// Unknown writes stop this proof and all dispatch helpers sharing the context.
export function sameRouteIo ( context , proof ) {
demand ( typeof context . checkpoint === 'function' , 'DURABLE_CHECKPOINT_REQUIRED' )
context . createdResources . dispatchWriteBoundary ??= { stopped : false }
const boundary = context . createdResources . dispatchWriteBoundary
const check = ( label , condition )=>{ context . assert ( MODULE , label , null , Boolean ( condition ), '' ,{ scenario : MODULE , deploymentBlocker : true }); demand ( condition , label )}
const send = async ( method , path , body , token = context . token , multipart = false )=>{
const write =! [ 'GET' , 'HEAD' ]. includes ( method )
demand ( ! write ||! boundary . stopped , 'UNKNOWN_WRITE_RESULT_STOPPED' )
const entry = { method , path , body : multipart ? { name : body . name , type : body . type , sizeBytes : body . content . byteLength } : structuredClone ( body ), status : 'SENDING' }
proof . requests . push ( entry )
try { await context . checkpoint ()} catch ( error ){ boundary . stopped = true ; entry . status = 'NOT_SENT' ; throw error }
let response
try { response = await ( multipart ? context . requestMultipart ( method , path , body , token ) : context . request ( method , path , body , token ))}
catch ( error ){ entry . status = 'UNKNOWN_RESULT' ; if ( write ){ boundary . stopped = true ; boundary . outcomeUnknown = true ; proof . outcomeUnknown = true } await context . checkpoint (); throw error }
const unknown = write && ( ! response ? . http || response . http >= 500 || response . body ? . code == null || String ( response . body . code ) === '200' && response . body . data == null )
Object . assign ( entry ,{ status : unknown ? 'UNKNOWN_RESULT' : 'RESPONDED' , http : response ? . http , code : response ? . body ? . code , requestId : response ? . requestId , traceId : response ? . traceId , result : structuredClone ( response ? . body ? . data )})
if ( unknown ){ boundary . stopped = true ; boundary . outcomeUnknown = true ; proof . outcomeUnknown = true }
try { await context . checkpoint ()} catch ( error ){ if ( write ) boundary . stopped = true ; throw error }
check ( ` ${ method } ${ path } ` , ! unknown && response ? . http === 200 && id ( response . body ? . code ) === '200' && response . requestId && response . traceId )
return response . body . data
}
return { check , request : send , upload : ( path , body )=> send ( 'POST' , path , body , context . token , true )}
}
2026-10-04 12:07:37 +08:00
export async function verifySameRouteCost ( context , fixture ,{ execute = false , readInventory } = {}) {
if ( ! execute ) return { scope : 'SAME_ROUTE_COST_WITH_TWO_OWN_AND_ONE_EXTERNAL' , businessSqlWrites : false }
2026-10-20 10:35:52 +08:00
demand ( context ? . marker === fixture ? . marker && context ? . marker && fixture . stage === fixtureContract . stage && fixture . dispatchNo && fixture . pdaToken && fixture . members ? . length === 2
&& fixture . members . every ( m => m . marker === context . marker && m . dispatchNo === fixture . dispatchNo && m . receiptVerified === true ) && new Set ( fixture . members . map ( m => id ( m . customerId ))). size === 2
&& fixture . tripProof ? . dispatchNo === fixture . dispatchNo && context . createdResources ? . fleetTrips ? . includes ( fixture . tripProof ) && typeof readInventory === 'function' , 'CURRENT_TWO_CUSTOMER_FIXTURE_REQUIRED' )
2026-10-04 12:07:37 +08:00
demand ( ! context . createdResources . fleetSameRouteCost , 'SAME_ROUTE_VERIFICATION_ALREADY_STARTED' )
2026-10-20 10:35:52 +08:00
const proof = context . createdResources . fleetSameRouteCost = { status : 'CHECKING' , tripNo : fixture . tripNo , dispatchNo : fixture . dispatchNo , marker : context . marker , scope : 'SAME_ROUTE_COST_WITH_TWO_OWN_AND_ONE_EXTERNAL' , snapshots : {}, requests : []}
const { check , request , upload } = sameRouteIo ( context , proof ), trip = fixture . tripProof , base = ` ${ ROOT } /fleet/trips/ ${ encode ( fixture . tripNo ) } ` , path = ` ${ ROOT } /dispatches/ ${ encode ( fixture . dispatchNo ) } ` , pdaPath = ` ${ PDA } / ${ encode ( fixture . dispatchNo ) } ` , key = suffix => ` ${ context . marker } -SAME- ${ suffix } `
const inventory = async label =>{
const rows = []
for ( const customerId of [... new Set ( fixture . members . map ( m => id ( m . customerId )))]){
const scope = { marker : context . marker , customerId , warehouseId : id ( fixture . warehouseId )}, raw = await readInventory ( scope )
check ( 'Inventory reader proves complete current customer and warehouse' , same ( raw ? . scope ,{... scope , coverage : 'CUSTOMER_WAREHOUSE_COMPLETE' }))
for ( const collection of [ 'balances' , 'positions' , 'ledger' ]) check ( 'Raw customer inventory has unique owned rows' , Array . isArray ( raw [ collection ]) && new Set ( raw [ collection ]. map ( r => id ( r . id ))). size === raw [ collection ]. length && raw [ collection ]. every ( r => id ( r . customerId ) === customerId && id ( r . overseasWarehouseId ) === scope . warehouseId ))
for ( const balance of raw . balances ){
for ( const field of [ 'inTransitPackages' , 'procurementPackages' ]) integer ( balance [ field ])
for ( const field of [ 'availablePackages' , 'holdPackages' , 'allocatedPackages' , 'pickedPackages' , 'receivingPackages' ]) check ( 'All raw position buckets conserve their balance' , integer ( balance [ field ]) === raw . positions . filter ( p => id ( p . balanceId ) === id ( balance . id )). reduce (( sum , p )=> sum + integer ( p [ field ]), 0 ))
}
check ( 'No orphan physical positions' , raw . positions . every ( p => raw . balances . some ( b => id ( b . id ) === id ( p . balanceId ))))
rows . push ( raw )
}
proof . snapshots [ label ] = rows ; await context . checkpoint (); return rows
}
2026-10-04 12:07:37 +08:00
try {
2026-10-20 10:35:52 +08:00
const detail = await request ( 'GET' , base ), plan = await request ( 'GET' , ` ${ base } /capacity-plan` ), physical = await request ( 'GET' , ` ${ path } /loading` )
check ( 'Two own physical sources share one native dispatch and FBA stop' , detail . dispatches ? . length === 1 && detail . dispatches [ 0 ]. dispatchNo === fixture . dispatchNo && plan . cargo ? . length === 2 && plan . cargo . every ( c => c . dispatchNo === fixture . dispatchNo ) && new Set ( plan . cargo . map ( c => c . destinationKey )). size === 1 && plan . cargo . every ( c => c . destinationKey ? . startsWith ( 'FBA:' )))
check ( 'Capacity uses exactly both current receipt pallets before any scanning' , physical . pallets ? . length === 2 && fixture . members . every ( m => physical . pallets . some ( p => id ( p . warehousePalletId ) === id ( m . palletId ) && p . palletNo === m . palletNo && integer ( p . scheduledPackages ) === 1 && integer ( p . pickedPackages ) === 0 )))
trip . stops = detail . trip . stops
const measured = sameRouteMeasurements ( context , fixture , trip , physical )
proof . capacityRequest = { recordVersion : version ( plan . recordVersion ), manifestHash : plan . manifestHash , pallets : measured . pallets . map (({ evidence ,... p })=> p ), reason : context . marker }
const planned = await request ( 'POST' , ` ${ base } /capacity-plan` , proof . capacityRequest )
check ( 'Actual capacity plan is valid' , planned . planValid === true )
2026-10-04 12:07:37 +08:00
await verifyFleetExternalReceipt ( context , MODULE , trip , fixture . pdaToken )
2026-10-20 10:35:52 +08:00
const beforePick = await inventory ( 'BEFORE_PICK' )
const measurements = sameRouteMeasurements ( context , fixture , trip , await request ( 'GET' , ` ${ path } /loading` ),{ external : true })
proof . arrangementSource = sameRouteArrangement ( context , fixture ); await context . checkpoint ()
await verifyFleetExternalDispatch ( context , MODULE , trip ,{ pickerToken : fixture . pdaToken , actualMeasurements : measurements , arrangement : proof . arrangementSource })
2026-10-04 12:07:37 +08:00
const receipt = trip . externalReceipt , external = trip . externalDispatch
2026-10-20 10:35:52 +08:00
check ( 'Actual external source is added to the same original main' , receipt ? . status === 'VERIFIED' && external ? . status === 'VERIFIED' && external . dispatchNo === fixture . dispatchNo )
const members = proof . members = [... fixture . members . map ( m =>({... m })),{ customerId : id ( external . customerId ), dispatchNo : fixture . dispatchNo , incomingNo : receipt . incomingNo , palletId : id ( receipt . warehousePalletId ), palletNo : receipt . palletNo ,
positionId : id ( receipt . finalInventory . positions [ 0 ]. id ), balanceId : id ( receipt . finalInventory . positions [ 0 ]. balanceId )}]
check ( 'Exactly three distinct original physical pallets and positions' , new Set ( members . map ( m => id ( m . palletId ))). size === 3 && new Set ( members . map ( m => id ( m . positionId ))). size === 3 )
const stock = await inventory ( 'PICKED' )
for ( const member of members ){
const before = beforePick . find ( s => id ( s . scope . customerId ) === id ( member . customerId )), after = stock . find ( s => id ( s . scope . customerId ) === id ( member . customerId ))
check ( 'Original one-box position alone is depleted by scanning' , before . positions . some ( p => id ( p . id ) === member . positionId && integer ( p . availablePackages ) === 1 ) && after . positions . some ( p => id ( p . id ) === member . positionId && integer ( p . availablePackages ) === 0 ))
const shipped = after . ledger . filter ( r => ! before . ledger . some ( old => id ( old . id ) === id ( r . id )) && r . businessType === 'SHIP' && id ( r . positionId ) === member . positionId )
check ( 'Exactly one actual SHIP per original position' , shipped . length === 1 && shipped [ 0 ]. businessOrderNo === fixture . dispatchNo && Number ( shipped [ 0 ]. deltaPackages ) ===- 1 )
2026-10-04 12:07:37 +08:00
}
2026-10-20 10:35:52 +08:00
for ( const before of beforePick ){
const after = stock . find ( s => id ( s . scope . customerId ) === id ( before . scope . customerId )), owned = members . filter ( m => id ( m . customerId ) === id ( before . scope . customerId )), oldIds = new Set ( before . ledger . map ( r => id ( r . id )))
check ( 'All original immutable inventory movements remain exact' , same ( before . ledger , after . ledger . filter ( r => oldIds . has ( id ( r . id )))))
const added = after . ledger . filter ( r => ! oldIds . has ( id ( r . id )))
check ( 'Only one ALLOCATE PICK SHIP sequence exists per physical source' , added . length === owned . length * 3 && owned . every ( m =>[ 'ALLOCATE' , 'PICK' , 'SHIP' ]. every ( type => added . filter ( r => r . businessType === type && id ( r . positionId ) === m . positionId && r . businessOrderNo === fixture . dispatchNo && Number ( r . deltaPackages ) === ( type === 'SHIP' ?- 1 : 1 )). length === 1 )))
const quantities = raw => Object . fromEntries ([ 'balances' , 'positions' ]. map ( collection =>[ collection , raw [ collection ]. map ( row =>({ id : id ( row . id ),... Object . fromEntries ([ 'availablePackages' , 'holdPackages' , 'allocatedPackages' , 'pickedPackages' , 'receivingPackages' ,...( collection === 'balances' ? [ 'inTransitPackages' , 'procurementPackages' ] : [])]. map ( field =>[ field , integer ( row [ field ])]))}))]))
const expected = structuredClone ( before )
for ( const member of owned ){
expected . positions . find ( p => id ( p . id ) === member . positionId ). availablePackages = 0
const balance = expected . balances . find ( b => id ( b . id ) === member . balanceId ); balance . availablePackages = integer ( balance . availablePackages ) - 1
}
check ( 'Exactly each own customer position and balance loses its single physical box' , same ( quantities ( expected ), quantities ( after )))
}
const current = { detail : await request ( 'GET' , path ), items : await request ( 'GET' , ` ${ path } /items` )}, ready = await request ( 'GET' , pdaPath , undefined , fixture . pdaToken )
check ( 'All three boxes are loaded and arranged before native departure' , current . detail . status === 'ACTIVE' && current . detail . stage === 'AFTER_LOADING' && current . detail . pickingReconciled === true && integer ( current . detail . counts . packageCount ) === 3 && integer ( current . detail . counts . pickedPackageCount ) === 3 && integer ( current . detail . counts . shippedPackageCount ) === 0
&& ready . dispatchNo === fixture . dispatchNo && ready . status === 'ACTIVE' && ready . stage === 'AFTER_LOADING' && ready . pickingReconciled === true && id ( ready . warehouseId ) === id ( fixture . warehouseId ) && id ( version ( ready . recordVersion )) === id ( version ( current . detail . recordVersion )) && ready . actions ? . DEPART ? . allowed === true && current . detail . actions ? . DEPART ? . allowed === true )
const deliveries = proof . deliveries = current . detail . documents ? . deliveries
check ( 'Exactly two customer-isolated deliveries cover three actual boxes' , deliveries ? . length === 2 && new Set ( deliveries . map ( d => d . deliveryNo )). size === 2 && deliveries . reduce (( sum , d )=> sum + integer ( d . packageCount ), 0 ) === 3 && members . every ( m => deliveries . some ( d => id ( d . customerId ) === id ( m . customerId ))))
const outbounds = current . detail . documents . outbounds
check ( 'Each delivery belongs to exactly its real customer outbound' , outbounds ? . length === 2 && new Set ( outbounds . map ( o => o . outboundNo )). size === 2 && outbounds . every ( o => deliveries . filter ( d => d . outboundNo === o . outboundNo && id ( d . customerId ) === id ( o . customerId )). reduce (( sum , d )=> sum + integer ( d . packageCount ), 0 ) === integer ( o . packageCount )))
proof . departureRequest = { recordVersion : version ( ready . recordVersion ), idempotencyKey : key ( 'DEPART' ), remark : context . marker }
proof . departure = await request ( 'POST' , ` ${ pdaPath } /depart` , proof . departureRequest , fixture . pdaToken )
check ( 'One native departure covers the whole current main' , proof . departure . dispatchNo === fixture . dispatchNo && proof . departure . action === 'DEPART' && proof . departure . status === 'ACTIVE' && proof . departure . stage === 'DELIVERING' && integer ( proof . departure . result ? . shippedPackages ) === 3 && BigInt ( version ( proof . departure . recordVersion )) > BigInt ( version ( ready . recordVersion ))
&& proof . departure . result . deliveries ? . length === deliveries . length && deliveries . every ( d => proof . departure . result . deliveries . some ( r => r . deliveryNo === d . deliveryNo && r . outboundNo === d . outboundNo && id ( r . customerId ) === id ( d . customerId ) && integer ( r . packageCount ) === integer ( d . packageCount ))))
const departedTrip = proof . departedTrip = await request ( 'GET' , base ), departed = await request ( 'GET' , path ), replay = await request ( 'POST' , ` ${ path } /depart` , proof . departureRequest )
check ( 'Actual main and its single resource record are delivering in transit' , departedTrip . trip ? . status === 'IN_TRANSIT' && departedTrip . dispatches ? . length === 1 && departedTrip . dispatches [ 0 ]. dispatchNo === fixture . dispatchNo && departed . status === 'ACTIVE' && departed . stage === 'DELIVERING' && integer ( departed . counts . shippedPackageCount ) === 3 && id ( version ( departed . recordVersion )) === id ( version ( proof . departure . recordVersion )))
check ( 'Platform replay returns the original PDA departure and version' , replay . replayed === true && id ( version ( replay . recordVersion )) === id ( version ( proof . departure . recordVersion )) && same ( replay . result , proof . departure . result ))
check ( 'Departure and replay do not deduct stock again or mutate facts' , same ( departedTrip , await request ( 'GET' , base )) && same ( departed , await request ( 'GET' , path )) && same ( stock , await inventory ( 'DEPARTED' )))
2026-10-04 12:07:37 +08:00
const history = await request ( 'GET' , ` ${ base } /history?page=1&size=200` )
2026-10-20 10:35:52 +08:00
check ( 'Complete history has one immutable actual departure' , integer ( history . total ) === history . records . length && history . records . filter ( r => r . action === 'DEPART' ). length === 1 )
const departure = proof . departureHistory = history . records . find ( r => r . action === 'DEPART' ), shares = proof . shares = sameRouteShares ( departure , fixture , receipt , current )
2026-10-04 12:07:37 +08:00
const costPath = ` ${ base } /costs` , before = await request ( 'GET' , ` ${ costPath } ?page=1&size=100` )
2026-10-20 10:35:52 +08:00
check ( 'Fresh trip has no prior costs' , integer ( before . page . total ) === 0 && before . page . records . length === 0 && before . summary . totals . length === 0 )
check ( 'Empty query already locks actual departure basis' , before . summary . allocationMethod === 'SAME_ROUTE_PALLET_SPACES' && before . summary . allocationBlockReason == null && id ( before . summary . departureVersion ) === id ( departure . recordVersion ) && before . summary . manifestHash === departure . snapshot . confirmedLoad . manifestHash )
proof . costRequest = { idempotencyKey : key ( 'COST-USD' ), details : { category : 'FUEL' , currency : 'USD' , amount : '1.00' , incurredAt : new Date (). toISOString (), remark : ` ${ context . marker } TEST synthetic cost` }}
2026-10-04 12:07:37 +08:00
const cost = proof . cost = await request ( 'POST' , costPath , proof . costRequest ), result = proof . costResult = await request ( 'GET' , ` ${ costPath } ?page=1&size=100` )
2026-10-20 10:35:52 +08:00
check ( 'Exactly one original-currency cost was created at legal zero version' , cost . tripNo === fixture . tripNo && cost . costNo && BigInt ( version ( cost . recordVersion )) === 0 n && integer ( result . page . total ) === 1 && result . page . records . length === 1 && result . page . records [ 0 ]. costNo === cost . costNo )
2026-10-04 12:07:37 +08:00
proof . expectedAllocations = assertSameRouteCost ( result . summary , departure , shares )
2026-10-20 10:35:52 +08:00
check ( 'Exact cost command replay returns the same persisted cost and allocation' , same ( result . page . records [ 0 ], await request ( 'POST' , costPath , proof . costRequest )) && same ( result , await request ( 'GET' , ` ${ costPath } ?page=1&size=100` )))
const costHistory = proof . costHistory = await request ( 'GET' , ` ${ costPath } / ${ encode ( cost . costNo ) } /history?page=1&size=100` )
check ( 'Exactly one immutable cost CREATE exists' , integer ( costHistory . total ) === 1 && costHistory . records . length === 1 && costHistory . records [ 0 ]. action === 'CREATE' && costHistory . records [ 0 ]. snapshot ? . cost ? . costNo === cost . costNo )
2026-10-04 12:07:37 +08:00
assertSameRouteCost ( costHistory . records [ 0 ]. snapshot . summary , departure , shares )
2026-10-20 10:35:52 +08:00
check ( 'Cost writes preserve original DEPART history, main, trip and all stock' , same ( history , await request ( 'GET' , ` ${ base } /history?page=1&size=200` )) && same ( departed , await request ( 'GET' , path )) && same ( departedTrip , await request ( 'GET' , base )) && same ( stock , await inventory ( 'COST_REPLAY' )))
for ( const [ index , ref ] of deliveries . entries ()){
const deliveryPath = ` ${ ROOT } /delivery-orders/ ${ encode ( ref . deliveryNo ) } ` , scope = `?customerId= ${ encode ( id ( ref . customerId )) } ` , delivery = await request ( 'GET' , deliveryPath + scope )
check ( 'Only this customer actual delivery is signing' , delivery . order ? . dispatchNo === fixture . dispatchNo && id ( delivery . order . customerId ) === id ( ref . customerId ) && delivery . order . status === 'DELIVERING' )
const others = await Promise . all ( deliveries . filter ( d => d . deliveryNo !== ref . deliveryNo ). map ( d => request ( 'GET' , ` ${ ROOT } /delivery-orders/ ${ encode ( d . deliveryNo ) } ?customerId= ${ encode ( id ( d . customerId )) } ` )))
const docsPath = ` ${ deliveryPath } /documents ${ scope } ` , docs = await request ( 'GET' , docsPath )
const uploaded = await upload ( ` ${ deliveryPath } /documents/RECEIPT/files ${ scope } ` ,{ name : ` ${ context . marker } - ${ index } -TEST-receipt.txt` , type : 'text/plain' , content : new TextEncoder (). encode ( ` ${ context . marker } TEST synthetic receipt ${ ref . deliveryNo } ` )})
check ( 'Actual receipt file has a persisted identity' , uploaded ? . fileId )
const documents = ( docs . categories || []). filter ( d => d . category !== 'RECEIPT' ). map ( d =>({ category : d . category , fileIds : ( d . files || []). map ( f => f . fileId )})); documents . push ({ category : 'RECEIPT' , fileIds : [ id ( uploaded . fileId )]})
const body = { expectedVersion : docs . version , idempotencyKey : key ( `SIGN- ${ index } ` ), bolNo : docs . bolNo || null , documents }
const signed = await request ( 'PUT' , docsPath , body ), after = await request ( 'GET' , deliveryPath + scope )
check ( 'Real saved receipt completes this delivery' , after . order . status === 'DELIVERED' )
await request ( 'PUT' , docsPath , body )
check ( 'Signing replay preserves complete delivery evidence' , same ( after , await request ( 'GET' , deliveryPath + scope )))
check ( 'Other customer delivery is unchanged by this signature' , same ( others , await Promise . all ( deliveries . filter ( d => d . deliveryNo !== ref . deliveryNo ). map ( d => request ( 'GET' , ` ${ ROOT } /delivery-orders/ ${ encode ( d . deliveryNo ) } ?customerId= ${ encode ( id ( d . customerId )) } ` )))))
proof . signatures ??= []; proof . signatures . push ({ deliveryNo : ref . deliveryNo , customerId : ref . customerId , request : body , result : signed }); await context . checkpoint ()
2026-10-04 12:07:37 +08:00
}
2026-10-20 10:35:52 +08:00
const completed = await request ( 'GET' , path )
check ( 'All normal signatures aggregate current native main completion' , completed . status === 'ACTIVE' && completed . stage === 'DELIVERED' )
2026-10-04 12:07:37 +08:00
check ( 'Signing preserves all customer stock and original cost allocation' , same ( stock , await inventory ( 'SIGNED' )) && same ( result , await request ( 'GET' , ` ${ costPath } ?page=1&size=100` )))
2026-10-20 10:35:52 +08:00
proof . status = 'VERIFIED' ; await context . checkpoint (); return proof
} catch ( error ){ proof . status = proof . outcomeUnknown || context . createdResources . dispatchWriteBoundary ? . outcomeUnknown ? 'OUTCOME_UNKNOWN' : 'FAILED' ; proof . error = error . message ; await context . checkpoint (); throw error }
2026-10-04 12:07:37 +08:00
}
export async function runSameRouteCost ( config ,{ env = process . env ,... dependencies } = {}) {
2026-10-20 10:35:52 +08:00
if ( ! config . execute ) return {... config , scope : 'TWO_FRESH_OWN_RECEIPTS_PLUS_ONE_EXTERNAL_SAME_ROUTE' , cost : 'USD 1.00, one OWN dispatch and one EXTERNAL booking on the same main, actual pallet-space largest remainder' , sqlWrites : false , deploy : false , cleanup : 'Retain samples; disable own PDA and close own sessions' }
const files = [ 'scripts/fleet-same-route-cost-test-env.mjs' , 'scripts/admin-test-env-modules/fleet-cross-customer-fixture.mjs' , 'scripts/admin-test-env-modules/fleet-external-receipt-acceptance.mjs' , 'scripts/admin-test-env-modules/fleet-external-dispatch-acceptance.mjs' , 'scripts/admin-test-env-modules/fleet-trip-cost-acceptance.mjs' ], sources = files . map ( path =>({ path , sha256 : createHash ( 'sha256' ). update ( fs . readFileSync ( resolve ( REPO , path ))). digest ( 'hex' )}))
const factory = dependencies . contextFactory || ( options => new AcceptanceRun ( options ))
let runOutput
return runCrossCustomer ( config ,{... dependencies , env , verificationScope : 'SAME_ROUTE_COST' , contextFactory : options =>{
runOutput = options . output
const context = factory ( options ), prior = context . checkpoint ? . bind ( context )
context . checkpoint = async ()=>{
await prior ? .()
const path = resolve ( options . output , 'same-route-progress.json' ), temp = ` ${ path } .tmp`
fs . writeFileSync ( temp , JSON . stringify ( redactEvidence ({ marker : context . marker , createdResources : context . createdResources }), null , 2 ) + '\n' ); fs . renameSync ( temp , path )
}
return context
}, verify : async ( context , fixture , options )=>{
fs . writeFileSync ( resolve ( runOutput , 'same-route-source.json' ), JSON . stringify ({ scope : 'SAME_ROUTE_COST_WITH_TWO_OWN_AND_ONE_EXTERNAL' , sources }, null , 2 ),{ flag : 'wx' })
2026-10-04 12:07:37 +08:00
return verifySameRouteCost ( context , fixture , options )
}})
}
if ( process . argv [ 1 ] && import . meta . url === pathToFileURL ( resolve ( process . argv [ 1 ])). href ){ try { const config = parseCrossCustomerArguments ( process . argv . slice ( 2 )), result = await runSameRouteCost ( config ); console . log ( JSON . stringify ( config . execute ? { success : result . success , error : result . error , summary : result . summary , requestCount : result . requestCount , goalComplete : false } : result , null , 2 )); if ( config . execute &&! result . success ) process . exitCode = 1 } catch ( error ){ console . error ( error . message ); process . exitCode = 1 }}