2026-09-01 21:55:27 +08:00
import test from 'node:test'
2026-09-30 15:16:39 +08:00
import { relabelOutboundMarksMatch , inventoryQuantitySnapshot , inventorySnapshot , dispatchInventorySources , inventorySourcesPresent , dispatchStockConservation , verifyDepartureReadiness , verifyPartialOrderCompletion , verifyFulfillmentRootStatus ,
2026-10-18 16:34:14 +08:00
createDeliveryReturn , completeReturnedException , returnedExceptionFactsMatch , verifyCustomerSignedDocuments , createSignedDocumentIsolationCustomer ,
2026-10-20 10:35:52 +08:00
dispatchDestinationConservation , pickAll , arrangeDispatchDelivery , fulfillmentEvidenceContext } from './phase5-overseas-fulfillment.mjs'
2026-09-01 21:55:27 +08:00
import assert from 'node:assert/strict'
2026-10-20 10:35:52 +08:00
import { readFile , mkdtemp , rm } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
2026-09-01 21:55:27 +08:00
import { fileURLToPath } from 'node:url'
import { parseArguments } from '../admin-test-env-acceptance.mjs'
const source = await readFile ( fileURLToPath ( new URL ( './phase5-overseas-fulfillment.mjs' , import . meta . url )), 'utf8' )
const entry = await readFile ( fileURLToPath ( new URL ( '../admin-test-env-acceptance.mjs' , import . meta . url )), 'utf8' )
2026-10-08 17:07:57 +08:00
test ( '一箱实收从四箱派送退回仅保持RETURN_PENDING,全部实收才RETURNED,缺失收货或来源证据仍拒绝' , () => {
const expected = { customerId : '100' , outboundNo : 'OB-1' , deliveryNo : 'DL-1' , inboundCode : 'IN-1' , evidenceFileId : '91' }
const detail = { order : { ... expected , status : 'COMPLETED' , packageCount : 1 , evidenceFileIds : [ '91' ] },
returnSources : [], returnReceipts : [{ receiptNo : 'RSR-1' , receivedPackages : '1' , receivedAt : '2026-10-06T01:00:00' }] }
const delivery = { order : { customerId : '100' , outboundNo : 'OB-1' , deliveryNo : 'DL-1' , packageCount : 4 , status : 'RETURN_PENDING' } }
assert . equal ( returnedExceptionFactsMatch ( detail , delivery , expected ), true )
assert . equal ( returnedExceptionFactsMatch ( detail , { order : { ... delivery . order , packageCount : 1 , status : 'RETURNED' } }, expected ), true )
assert . equal ( returnedExceptionFactsMatch ( detail , { order : { ... delivery . order , status : 'RETURNED' } }, expected ), false )
assert . equal ( returnedExceptionFactsMatch ( detail , { order : { ... delivery . order , customerId : 'OTHER' } }, expected ), false )
for ( const mutate of [ v => { v . returnReceipts = [] }, v => { v . returnReceipts [ 0 ]. receivedPackages = 2 },
v => { v . order . outboundNo = 'OB-OTHER' }, v => { v . order . evidenceFileIds = [] },
v => { v . returnSources = [{ maxReturnPackages : 1 }] }, v => { v . returnReceipts . push ({ ... v . returnReceipts [ 0 ] }) }]) {
const changed = structuredClone ( detail ); mutate ( changed )
assert . equal ( returnedExceptionFactsMatch ( changed , delivery , expected ), false )
}
})
2026-10-20 10:35:52 +08:00
test ( 'native route conserves source keys and destinations while same destination may contain multiple customers' , () => {
const fixture = { sourceKeys : [ 'PLAN:10' , 'PLAN:11' , 'PLAN:12' ], destinationWarehouseCodes : [ 'ONT8' , 'LAX9' ] }
const detail = { dispatchInfo : { route : 'ONT8,LAX9' }, orderDetails : [
{ sourceKey : 'PLAN:10' , customerId : '100' , destinationFbaWarehouse : 'ONT8' },
{ sourceKey : 'PLAN:11' , customerId : '200' , destinationFbaWarehouse : 'LAX9' },
{ sourceKey : 'PLAN:12' , customerId : '200' , destinationFbaWarehouse : 'ONT8' }] }
const deliveries = [{ customerId : '100' , destination : { key : 'FBA:ONT8' , warehouseCode : 'ONT8' } },
{ customerId : '200' , destination : { key : 'FBA:ONT8' , warehouseCode : 'ONT8' } },
{ customerId : '200' , destination : { key : 'FBA:LAX9' , warehouseCode : 'LAX9' } }]
assert . equal ( dispatchDestinationConservation ( detail , fixture ), true )
assert . equal ( dispatchDestinationConservation ( detail , fixture , deliveries ), true )
for ( const mutate of [ value => { value . detail . dispatchInfo . route = 'ONT8' },
value => { value . detail . dispatchInfo . route = 'ONT8,ONT8,LAX9' },
value => { value . detail . orderDetails [ 1 ]. destinationFbaWarehouse = 'OTHER' },
value => { value . detail . orderDetails [ 1 ]. sourceKey = 'PLAN:99' },
value => { value . fixture . destinationWarehouseCodes . push ( 'UNSELECTED' ) },
value => { value . deliveries . pop () }, value => { value . deliveries . push ( value . deliveries [ 0 ]) }]) {
const value = structuredClone ({ detail , fixture , deliveries }); mutate ( value )
assert . equal ( dispatchDestinationConservation ( value . detail , value . fixture , value . deliveries ), false )
2026-09-30 17:13:11 +08:00
}
})
2026-09-01 21:55:27 +08:00
test ( 'phase-five fulfillment is a registered default HTTP module after the real phase-four dispatch fixture' , () => {
assert . match ( entry , /CONFIGURED_MODULES[^\n]*'phase4-overseas-dispatch', 'phase5-overseas-fulfillment'/ )
assert . match ( entry , /'phase5-overseas-fulfillment', \['phase4-overseas-dispatch'\]/ )
const modules = parseArguments ([ '--modules' , 'phase5-overseas-fulfillment' ]). modules
for ( const prerequisite of [ 'merchant-qualification-fixture' , 'phase3-loading' , 'phase3-loading-finalize' ,
'phase4-overseas-pda' , 'phase4-overseas-pda-operations' , 'phase4-overseas-dispatch' ]) {
assert . ok ( modules . indexOf ( prerequisite ) >= 0
&& modules . indexOf ( prerequisite ) < modules . indexOf ( 'phase5-overseas-fulfillment' ), prerequisite )
}
})
2026-10-20 10:35:52 +08:00
test ( 'native fulfillment uses real public DTOs and scans before loading, arranging and departing' , () => {
for ( const token of [ "const DISPATCH_BASE = '/api/platform/v1/last-leg/dispatches'" ,
"const PDA_DISPATCH_BASE = '/api/pda/v1/last-leg/dispatches'" , '/transfer-delivery' , '/delivery-arrangement' ,
'cargoHash: value.cargoHash' , 'loadingCompletionHash: value.loadingCompletionHash' ,
'recordVersion: version(detail.data.recordVersion)' , 'positionId: id' ,
'departed.data.result?.shippedPackages' , 'outboundRef.outboundNo' ]) {
if ( token === 'positionId: id' ) assert . match ( source , /positionId: source.position \? id\(source.position.positionId\)/ )
else assert . ok ( source . includes ( token ), token )
}
assert . doesNotMatch ( source , /READY_TO_DEPART|PENDING_DEPARTURE|DISPATCH-COMPLETE|\/items\/.*['"]DELETE['"]/ )
assert . match ( source , /data.status === 'ACTIVE' && data.stage === 'AFTER_LOADING'/ )
assert . match ( source , /departed.data.stage === 'DELIVERING'/ )
const run = source . slice ( source . indexOf ( 'export async function run' ))
assert . ok ( run . indexOf ( 'prepareFleetTrip(' ) < run . indexOf ( 'await pickAll(' ))
assert . ok ( run . indexOf ( 'await pickAll(' ) < run . indexOf ( 'await confirmFleetLoading(' ))
assert . ok ( run . indexOf ( 'await confirmFleetLoading(' ) < run . indexOf ( 'await arrangeDispatchDelivery(' ))
assert . ok ( run . indexOf ( 'await arrangeDispatchDelivery(' ) < run . indexOf ( 'await verifyDepartureReadiness(' ))
assert . ok ( run . indexOf ( '全部客户正常签收汇总整车DELIVERED' ) < run . indexOf ( 'await finishFleetTrip(' ))
assert . ok ( run . indexOf ( 'await finishFleetTrip(' ) < run . indexOf ( 'const returnRequest' ))
2026-09-01 21:55:27 +08:00
})
2026-10-20 10:35:52 +08:00
test ( 'client reads its own native-arranged deliveries and full nested document contract' , () => {
2026-09-02 02:51:58 +08:00
assert . match ( source , /loginMerchant\(context, customerId\)/ )
2026-10-20 10:35:52 +08:00
assert . match ( source , /context.options\?.merchantUsername/ )
assert . match ( source , /id\(profile\?.id\) === customerId/ )
2026-09-02 02:51:58 +08:00
assert . match ( source , /客户分页回查自身派送单/ )
assert . match ( source , /客户读取自身派送详情/ )
2026-10-20 10:35:52 +08:00
assert . match ( source , /merchantDetail.data\?.order\?.deliveryNo/ )
assert . match ( source , /merchantDetail.data\?.skus/ )
assert . match ( source , /merchantDetail.data\?.fees/ )
assert . match ( source , /merchantDetail.data\?.operations/ )
assert . doesNotMatch ( source , /merchant\(context, merchantToken, 'POST'.*创建派送/ )
2026-09-02 02:51:58 +08:00
})
2026-09-15 12:07:10 +08:00
test ( 'phase-five module proves receipt-save completion, cross-region convergence, customer visit, exception and return' , () => {
2026-09-01 21:55:27 +08:00
for ( const token of [
2026-09-29 19:48:34 +08:00
'/documents/RECEIPT/files' , 'requestMultipart' , "category: 'RECEIPT'" ,
2026-09-15 12:07:10 +08:00
'SAVE-RECEIPT' , 'RECEIPT_AUTO_COMPLETE' ,
2026-09-01 21:55:27 +08:00
'/customer-visits/${encodeURIComponent(visitId)}' ,
"visitResult: 'SATISFIED'" , '/exception-orders' ,
'/return-inbound-options' , '/mark-return' , "returnDirection: 'OVERSEAS_WAREHOUSE'" ,
2026-09-09 03:18:59 +08:00
'returnSources' , 'outboundPalletItemId' , 'inventoryPositionId' ,
2026-10-18 16:34:14 +08:00
'value.returnSources.some' , 'returnCandidate?.deliveryNo === deliveryNo' ,
2026-09-09 03:18:59 +08:00
"idempotencyKey: key(context, 'DELIVERY-RETURN')" , '派送退回同键同载荷重放' ,
2026-09-01 21:55:27 +08:00
'RETURN_PENDING_WITH_COMPLETED_VISIT' ,
]) assert . ok ( source . includes ( token ), token )
2026-09-15 12:07:10 +08:00
assert . match ( source , /saved\.data\?\.categories\?\.some/ )
assert . match ( source , /completed\.data\?\.order\?\.status === 'DELIVERED'/ )
assert . match ( source , /人工确认派送完成接口已移除/ )
assert . match ( source , /query\('\/api\/platform\/inbounds'/ )
assert . match ( source , /inboundCode: inbound\.inboundCode/ )
assert . match ( source , /inboundSummary\?\.processStatus === 'DELIVERED'/ )
2026-09-30 15:16:39 +08:00
assert . match ( source , /verifyFulfillmentRootStatus\(context, \{ sourceOrderId, customerId, merchantToken \}\)/ )
assert . match ( source , /\/api\/platform\/v1\/orders\/\$\{encodeURIComponent\(rootOrderId\)\}/ )
assert . match ( source , /\/fulfillment-tree/ )
2026-09-15 12:07:10 +08:00
assert . match ( source , /mainStatus === 'COMPLETED'/ )
assert . doesNotMatch ( source , /platform\(context, 'POST', '确认派送完成/ )
2026-09-01 21:55:27 +08:00
assert . match ( source , /manualExceptionNo/ )
assert . match ( source , /returnExceptionNo/ )
})
test ( 'phase-five module uses marker-owned fixtures and always disables its temporary PDA identity' , () => {
assert . match ( source , /dispatch\?\.marker !== context\.marker/ )
assert . match ( source , /receiving\?\.marker !== context\.marker/ )
assert . match ( source , /resolvePickerAccess\(context\)/ )
assert . match ( source , /createPicker\(context, 5, warehouseId, access\)/ )
assert . match ( source , /finally \{[\s\S]*disablePicker\(context, picker, 5\)[\s\S]*picker\.token = null/ )
2026-09-02 02:51:58 +08:00
assert . doesNotMatch ( source , /8\.163\.|password\s*:\s*['"`]/ )
2026-09-01 21:55:27 +08:00
})
test ( 'phase-five writes carry idempotency and record deployment blockers instead of passing empty fixtures' , () => {
2026-10-20 10:35:52 +08:00
assert . match ( source , /idempotencyKey: key\(context, 'TRANSFER', dispatchNo\)/ )
2026-09-01 21:55:27 +08:00
assert . match ( source , /idempotencyKey: key\(context, 'DISPATCH-PICK'/ )
2026-10-20 10:35:52 +08:00
assert . match ( source , /idempotencyKey: key\(context, 'DISPATCH-DEPART', dispatchNo\)/ )
2026-09-01 21:55:27 +08:00
assert . match ( source , /addCoverageGap\(MODULE, SCENARIO/ )
assert . match ( source , /deploymentBlocker: true/ )
})
2026-09-14 13:46:32 +08:00
test ( 'relabel marks are checked on the authoritative outbound DTO without weakening identity checks' , () => {
const relabel = { relabelCartonMarks : [ 'NEW-1' , 'NEW-2' ], sourceCartonMarks : [ 'OLD-1' , 'OLD-2' ] }
const detail = { outbound : { packageCount : 2 }, pallets : [{ cartonMarks : 'NEW-1,NEW-2' }] }
assert . equal ( relabelOutboundMarksMatch ( detail , relabel ), true )
for ( const cartonMarks of [ '' , 'NEW-1' , 'NEW-1,NEW-1' , 'NEW-1,OLD-2' , 'NEW-1,NEW-2,OTHER' ]) {
assert . equal ( relabelOutboundMarksMatch ({ ... detail , pallets : [{ cartonMarks }] }, relabel ), false )
}
assert . equal ( relabelOutboundMarksMatch ({ ... detail , outbound : { packageCount : 3 } }, relabel ), false )
assert . match ( source , /detail\.data\?\.outbound\?\.dispatchNo === relabel\.dispatchNo/ )
assert . match ( source , /relabel\?\.marker !== context\.marker/ )
})
2026-09-21 07:59:48 +08:00
2026-10-20 10:35:52 +08:00
test ( 'unknown writes preserve the original command and stop instead of transport retry' , () => {
assert . match ( source , /entry.status = 'UNKNOWN'/ )
assert . match ( source , /存在未知写结果/ )
assert . doesNotMatch ( source , /人工异常连接失败后使用同载荷重试/ )
2026-09-21 07:59:48 +08:00
assert . match ( source , /manualExceptionBody/ )
})
2026-09-30 12:58:15 +08:00
test ( 'quantity snapshots ignore timestamps but preserve every inventory bucket and source identity' , () => {
const original = { id : '1' , inboundCode : 'IN-1' , totalPackages : 5 , availablePackages : 3 ,
holdPackages : 2 , allocatedPackages : 0 , pickedPackages : 0 , updatedAt : 'earlier' }
assert . deepEqual ( inventoryQuantitySnapshot ([ original ]), inventoryQuantitySnapshot ([{ ... original , updatedAt : 'later' }]))
for ( const field of [ 'id' , 'inboundCode' , 'totalPackages' , 'availablePackages' , 'holdPackages' , 'allocatedPackages' , 'pickedPackages' ]) {
assert . notDeepEqual ( inventoryQuantitySnapshot ([ original ]),
inventoryQuantitySnapshot ([{ ... original , [ field ] : field === 'id' || field === 'inboundCode' ? 'different' : 99 }]))
}
})
function contextFor ( request ) {
const assertions = []
const calls = []
return { marker : 'TAIL-CURRENT' , options : { gateway : 'https://test.invalid' }, createdResources : {},
assertions , calls ,
async request ( method , path , body , token ) { calls . push ({ method , path , body , token }); return request ( method , path , body , token ) },
apiSuccess ( module , name , response ) { assertions . push ({ name , passed : response ? . body ? . code === '200' }); return response . body ? . data },
assert ( module , name , response , passed ) { assertions . push ({ name , passed }) },
addStep ( module , name , response , passed ) { assertions . push ({ name , passed }) },
addCoverageGap ( module , scenario , name ) { assertions . push ({ name , passed : false }) },
}
}
const ok = data => ({ http : 200 , body : { code : '200' , data } })
2026-10-18 16:34:14 +08:00
function deliveryReturnFixture () {
return { lastMileOrderId : '9007199254740993' , lastMileOrderNo : 'LM-1' , inboundOrderId : '81' , inboundCode : 'IN-A' ,
customerId : '100' , overseasWarehouseId : 'WH-1' , deliveryNo : 'DL-1' , outboundNo : 'OB-1' ,
returnSources : [{ outboundPalletItemId : '51' , inventoryPositionId : '61' , returnCartonId : null , maxReturnPackages : 2 }] }
}
const returnScope = { customerId : '100' , warehouseId : 'WH-1' , deliveryNo : 'DL-1' , outboundNo : 'OB-1' }
for ( const ordinaryInbound of [ '81' , null , undefined ]) test ( `phase5 mark-return sends the actual master key; inbound= ${ ordinaryInbound } ` , async () => {
const candidate = deliveryReturnFixture (); candidate . inboundOrderId = ordinaryInbound
if ( ! ordinaryInbound ) candidate . inboundCode = null
const context = contextFor (( method , path , body ) => {
if ( method === 'GET' ) { assert . match ( path , /return-inbound-options/ ); return ok ([ candidate ]) }
assert . equal ( method , 'POST' ); assert . match ( path , /mark-return/ )
assert . equal ( body . lastMileOrderId , candidate . lastMileOrderId )
assert . equal ( Object . hasOwn ( body , 'inboundOrderId' ), false )
assert . deepEqual ( body . items , [{ outboundPalletItemId : '51' , inventoryPositionId : '61' , packageCount : 1 }])
assert . equal ( body . returnDirection , 'OVERSEAS_WAREHOUSE' )
assert . ok ( body . idempotencyKey )
return ok ({ exceptionNo : 'EX-1' , status : 'PENDING' , version : 0 })
})
const result = await createDeliveryReturn ( context , returnScope )
assert . equal ( result . returned . data . exceptionNo , 'EX-1' )
assert . equal ( context . calls . filter ( row => row . method === 'POST' ). length , 1 )
assert . deepEqual ( context . assertions . filter ( row => ! row . passed ), [])
})
test ( 'phase5 keeps the selected master and its own source together when candidates share no inbound relation' , async () => {
const first = deliveryReturnFixture (); first . inboundOrderId = null ; first . inboundCode = null ; first . returnSources = []
const selected = { ... deliveryReturnFixture (), lastMileOrderId : '9007199254740995' , lastMileOrderNo : 'LM-2' , inboundOrderId : null , inboundCode : null ,
returnSources : [{ outboundPalletItemId : '52' , inventoryPositionId : '62' , maxReturnPackages : 1 }] }
const context = contextFor (( method , path , body ) => {
if ( method === 'GET' ) return ok ([ first , selected ])
assert . equal ( body . lastMileOrderId , selected . lastMileOrderId )
assert . equal ( Object . hasOwn ( body , 'inboundOrderId' ), false )
assert . deepEqual ( body . items , [{ outboundPalletItemId : '52' , inventoryPositionId : '62' , packageCount : 1 }])
return ok ({ exceptionNo : 'EX-2' })
})
await createDeliveryReturn ( context , returnScope )
assert . equal ( context . calls . filter ( row => row . method === 'POST' ). length , 1 )
})
for ( const [ name , mutate ] of [
[ 'missing-master' , row => { delete row . lastMileOrderId }], [ 'zero-master' , row => { row . lastMileOrderId = '0' }],
[ 'foreign-customer' , row => { row . customerId = 'OTHER' }], [ 'foreign-warehouse' , row => { row . overseasWarehouseId = 'OTHER' }],
[ 'wrong-delivery' , row => { row . deliveryNo = 'DL-OTHER' }], [ 'wrong-outbound' , row => { row . outboundNo = 'OB-OTHER' }],
[ 'missing-source' , row => { row . returnSources = [] }], [ 'missing-position' , row => { row . returnSources [ 0 ]. inventoryPositionId = null }],
[ 'ambiguous-source-type' , row => { row . returnSources [ 0 ]. returnCartonId = '701' }],
]) test ( `phase5 refuses ${ name } before any mark-return write even with an inbound ID` , async () => {
const candidate = deliveryReturnFixture (); mutate ( candidate )
const context = contextFor (( method ) => { assert . equal ( method , 'GET' ); return ok ([ candidate ]) })
assert . equal ( await createDeliveryReturn ( context , returnScope ), null )
assert . equal ( context . calls . length , 1 )
assert . ok ( context . assertions . some ( row => ! row . passed ))
})
test ( 'the phase5 lifecycle calls the tested request path and replays its exact returned body' , () => {
assert . match ( source , /const returnRequest = await createDeliveryReturn\(context, \{ customerId, warehouseId, deliveryNo, outboundNo \}\)/ )
assert . match ( source , /const \{ returned, returnBody \} = returnRequest/ )
assert . doesNotMatch ( source , /inboundOrderId:\s*id\(returnCandidate/ )
assert . match ( source , /lastMileOrderId: id\(returnCandidate\.lastMileOrderId\)/ )
})
2026-09-30 12:58:15 +08:00
test ( 'partial completion rejects different Orders and an already delivered pending fragment' , async () => {
for ( const second of [{ orderId : 'OTHER' , processStatus : 'WAIT_SHIP' },
{ orderId : 'ORDER' , processStatus : 'DELIVERED' }]) {
const context = contextFor (( method , path ) => ok ({ records : path . includes ( 'inboundCode=IN-A' )
? [{ inboundCode : 'IN-A' , orderId : 'ORDER' , processStatus : 'DELIVERED' }]
: [{ inboundCode : 'IN-B' , ... second }] }))
assert . equal ( await verifyPartialOrderCompletion ( context , { orderId : 'ORDER' , customerId : '100' ,
deliveredInboundCode : 'IN-A' , pendingInboundCodes : [ 'IN-B' ] }), false )
assert . equal ( context . calls . some ( call => call . path . startsWith ( '/api/platform/v1/orders/' )), false )
}
})
test ( 'partial completion verifies an unfinished valid sibling and catches premature COMPLETED' , async () => {
for ( const mainStatus of [ 'IN_TRANSIT' , 'COMPLETED' ]) {
const context = contextFor (( method , path ) => path . startsWith ( '/api/platform/v1/orders/' )
? ok ({ summary : { mainStatus } }) : ok ({ records : [{ inboundCode : path . includes ( 'inboundCode=IN-A' ) ? 'IN-A' : 'IN-B' ,
orderId : 'ORDER' , processStatus : path . includes ( 'inboundCode=IN-A' ) ? 'DELIVERED' : 'WAIT_SHIP' }] }))
assert . equal ( await verifyPartialOrderCompletion ( context , { orderId : 'ORDER' , customerId : '100' ,
deliveredInboundCode : 'IN-A' , pendingInboundCodes : [ 'IN-B' ] }), mainStatus !== 'COMPLETED' )
}
})
test ( 'same dispatch-return exception reaches actual restored inventory and retries without another ledger row' , async () => {
for ( const initialStatus of [ 'PENDING' , 'PROCESSING' ]) {
let completed = false
let version = initialStatus === 'PROCESSING' ? 1 : 0
let uploads = 0
const source = { outboundPalletItemId : '51' , inventoryPositionId : '61' , maxReturnPackages : 1 }
const context = contextFor (( method , path , body ) => {
2026-09-30 13:15:20 +08:00
if ( path . includes ( '/inventory/balances/1/positions' )) return ok ( path . includes ( 'palletNo=' ) ? ( completed ? [{ id : '3' , balanceId : '1' ,
2026-09-30 12:58:15 +08:00
customerId : '100' , overseasWarehouseId : 'WH-1' , inboundCode : 'IN-A' , palletId : '71' ,
2026-09-30 13:15:20 +08:00
palletNo : 'RET-TAIL-CURRENT' , warehouseLocationId : '72' , totalPackages : 1 , availablePackages : 1 ,
holdPackages : 0 , allocatedPackages : 0 , pickedPackages : 0 , receivingPackages : 0 }] : [])
2026-09-30 13:50:13 +08:00
: [{ id : '61' , balanceId : '1' , customerId : '100' , overseasWarehouseId : 'WH-1' , inboundCode : 'IN-A' ,
2026-09-30 13:15:20 +08:00
palletNo : 'SOURCE' , totalPackages : 8 , availablePackages : 8 , holdPackages : 0 , allocatedPackages : 0 , pickedPackages : 0 , receivingPackages : 0 },
...( completed ? [{ id : '3' , balanceId : '1' , customerId : '100' , overseasWarehouseId : 'WH-1' , inboundCode : 'IN-A' , palletId : '71' ,
palletNo : 'RET-TAIL-CURRENT' , warehouseLocationId : '72' , totalPackages : 1 , availablePackages : 1 , holdPackages : 0 , allocatedPackages : 0 , pickedPackages : 0 , receivingPackages : 0 }] : [])])
2026-09-30 13:50:13 +08:00
if ( path . includes ( '/inventory/balances' )) { const balance = { id : '1' , customerId : '100' ,
2026-09-30 13:15:20 +08:00
overseasWarehouseId : 'WH-1' , totalPackages : completed ? 9 : 8 ,
2026-09-30 13:50:13 +08:00
availablePackages : completed ? 9 : 8 , holdPackages : 0 , allocatedPackages : 0 , pickedPackages : 0 , receivingPackages : 0 , inTransitPackages : 0 , procurementPackages : 0 }; return ok ( path . includes ( '/balances/1?' ) ? balance : { total : 1 , records : [ balance ] }) }
2026-09-30 12:58:15 +08:00
if ( path . includes ( '/inventory/ledger' )) return ok ({ total : completed ? 1 : 0 , records : completed ? [{ id : '2' ,
customerId : '100' , inboundCode : 'IN-A' , businessType : 'RETURN_STOCK_IN' , businessOrderNo : 'EX-1' ,
outboundOrderNo : 'OB-1' , deltaPackages : 1 , beforePackages : 0 , afterPackages : 1 }] : [] })
if ( path . includes ( '/locations' )) return ok ({ total : 1 , records : [{ id : '72' , locationCode : 'L-1' }] })
if ( method === 'POST' && path . endsWith ( '/pallets' )) return ok ( '71' )
if ( path . endsWith ( '/pallets/71' )) return ok ({ id : '71' , warehouseId : 'WH-1' , palletCode : 'RET-TAIL-CURRENT' , locationId : '72' })
if ( path . includes ( '/start-processing' )) { version = 1 ; return ok ({ status : 'PROCESSING' , version }) }
if ( path . includes ( '/complete' )) {
assert . deepEqual ( body . receipts [ 0 ], { outboundPalletItemId : '51' , inventoryPositionId : '61' , receivedPackages : 1 ,
targetPalletId : '71' , targetPalletNo : 'RET-TAIL-CURRENT' , targetLocationId : '72' , targetLocationCode : 'L-1' })
const replayed = completed ; completed = true
return ok ({ status : 'COMPLETED' , restoredPackages : 1 , inventoryAdjustmentId : '81' , replayed })
}
2026-10-08 17:07:57 +08:00
if ( path . includes ( '/delivery-orders/' )) return ok ({ order : { status : 'RETURNED' , outboundNo : 'OB-1' , deliveryNo : 'DEL-1' , customerId : '100' , packageCount : 1 } })
2026-09-30 12:58:15 +08:00
return ok ({ order : { status : completed ? 'COMPLETED' : initialStatus , exceptionType : 'RETURN' ,
2026-10-08 17:07:57 +08:00
outboundNo : 'OB-1' , inboundCode : 'IN-A' , deliveryNo : 'DEL-1' , customerId : '100' , packageCount : 1 , version , evidenceFileIds : [ '91' ] },
returnSources : completed ? [] : [ source ], returnReceipts : completed ? [{ receiptNo : 'RSR-CURRENT' , receivedPackages : 1 , receivedAt : '2026-10-06T00:00:00' }] : [] })
2026-09-30 12:58:15 +08:00
})
context . requestMultipart = async () => { uploads += 1 ; return ok ({ fileId : '91' }) }
2026-09-30 13:50:13 +08:00
context . createdResources . phase5OverseasFulfillment = { marker : context . marker , returnExceptionNo : 'EX-1' , outboundNo : 'OB-1' , inventoryProof : { sourceBalanceIds : [ '1' ] } }
2026-09-30 12:58:15 +08:00
const resume = initialStatus === 'PROCESSING'
? { targetPalletId : '71' , targetPalletNo : 'RET-TAIL-CURRENT' , evidenceFileId : '91' , completeIdempotencyKey : 'ORIGINAL-COMPLETE' } : null
const result = await completeReturnedException ( context , { customerId : '100' , warehouseId : 'WH-1' , exceptionNo : 'EX-1' , outboundNo : 'OB-1' , resume })
assert . equal ( result ? . restoredPackages , 1 )
assert . deepEqual ( context . assertions . filter ( row => ! row . passed ), [])
assert . equal ( context . calls . filter ( call => call . path . includes ( '/complete' )). length , 2 )
if ( initialStatus === 'PROCESSING' ) {
assert . equal ( context . calls . some ( call => call . method === 'POST' && call . path . endsWith ( '/pallets' )), false )
assert . equal ( context . calls . some ( call => call . path . includes ( '/start-processing' )), false )
assert . equal ( uploads , 0 )
assert . ok ( context . calls . filter ( call => call . path . includes ( '/complete' )). every ( call => call . body . idempotencyKey === 'ORIGINAL-COMPLETE' ))
}
assert . equal ( context . createdResources . phase5OverseasFulfillment . returnReceiptAttempt . evidenceFileId , '91' )
}
})
test ( 'PROCESSING continuation without the original pallet and evidence remains blocked without creating replacements' , async () => {
const context = contextFor (() => ok ({ order : { status : 'PROCESSING' , exceptionType : 'RETURN' , outboundNo : 'OB-1' , version : 1 },
returnSources : [{ outboundPalletItemId : '51' , inventoryPositionId : '61' , maxReturnPackages : 1 }] }))
2026-09-30 13:50:13 +08:00
context . createdResources . phase5OverseasFulfillment = { marker : context . marker , returnExceptionNo : 'EX-1' , outboundNo : 'OB-1' , inventoryProof : { sourceBalanceIds : [ '1' ] } }
2026-09-30 12:58:15 +08:00
assert . equal ( await completeReturnedException ( context ,
{ customerId : '100' , warehouseId : 'WH-1' , exceptionNo : 'EX-1' , outboundNo : 'OB-1' }), null )
assert . equal ( context . calls . length , 1 )
assert . ok ( context . assertions . some ( row => ! row . passed ))
})
test ( 'failed same-exception completion still checks zero inventory drift and retains the original resume evidence' , async () => {
const context = contextFor (( method , path ) => {
2026-09-30 13:50:13 +08:00
if ( path . includes ( '/inventory/ledger' )) return ok ({ records : [], total : 0 })
if ( path . includes ( '/inventory/balances' )) {
const balance = { id : '1' , customerId : '100' , overseasWarehouseId : 'WH-1' , totalPackages : 1 , availablePackages : 1 ,
holdPackages : 0 , allocatedPackages : 0 , pickedPackages : 0 , receivingPackages : 0 , inTransitPackages : 0 , procurementPackages : 0 }
return ok ( path . includes ( '/positions' ) ? [{ ... balance , id : '61' , balanceId : '1' , inboundCode : 'IN-A' }]
: path . includes ( '/balances/1?' ) ? balance : { records : [ balance ], total : 1 })
}
2026-09-30 12:58:15 +08:00
if ( path . includes ( '/locations' )) return ok ({ records : [{ id : '72' , locationCode : 'L-1' }], total : 1 })
if ( path . endsWith ( '/pallets/71' )) return ok ({ id : '71' , warehouseId : 'WH-1' , palletCode : 'RET-TAIL-CURRENT' , locationId : '72' })
if ( path . includes ( '/complete' )) return { http : 200 , body : { code : 'A0400' , message : 'Source rejected' } }
return ok ({ order : { status : 'PROCESSING' , exceptionType : 'RETURN' , outboundNo : 'OB-1' , inboundCode : 'IN-A' , version : 1 },
returnSources : [{ outboundPalletItemId : '51' , inventoryPositionId : '61' , maxReturnPackages : 1 }] })
})
2026-09-30 13:50:13 +08:00
context . createdResources . phase5OverseasFulfillment = { marker : context . marker , returnExceptionNo : 'EX-1' , outboundNo : 'OB-1' , inventoryProof : { sourceBalanceIds : [ '1' ] } }
2026-09-30 12:58:15 +08:00
const resume = { targetPalletId : '71' , targetPalletNo : 'RET-TAIL-CURRENT' , evidenceFileId : '91' , completeIdempotencyKey : 'ORIGINAL-COMPLETE' }
assert . equal ( await completeReturnedException ( context ,
{ customerId : '100' , warehouseId : 'WH-1' , exceptionNo : 'EX-1' , outboundNo : 'OB-1' , resume }), null )
2026-09-30 13:50:13 +08:00
assert . equal ( context . calls . filter ( call => call . path . includes ( '/inventory/balances' )). length , 6 )
2026-09-30 12:58:15 +08:00
assert . equal ( context . calls . filter ( call => call . path . includes ( '/inventory/ledger' )). length , 2 )
assert . ok ( context . assertions . some ( row => row . name === '退回实收失败后库存及流水保持不变并保留原续验资料' && row . passed ))
assert . equal ( context . createdResources . phase5OverseasFulfillment . returnReceiptAttempt . evidenceFileId , '91' )
assert . equal ( context . createdResources . phase5OverseasFulfillment . returnReceiptAttempt . completeIdempotencyKey , 'ORIGINAL-COMPLETE' )
assert . equal ( context . calls . some ( call => call . method === 'POST' && ! call . path . includes ( '/complete' )), false )
})
test ( 'customer receipt acceptance downloads exact bytes and rejects a foreign customer without a platform fallback' , async () => {
const context = contextFor (( method , path , body , token ) => path . endsWith ( '/iam/tenant/profile' )
? ok ({ id : token === 'FOREIGN' ? '200' : '100' }) : token === 'FOREIGN'
? { http : 404 , body : { code : 'A0404' } }
: ok ({ deliveryNo : 'DEL-1' , files : [{ fileId : '91' }] }))
const previousFetch = globalThis . fetch
globalThis . fetch = async ( url , options ) => options . headers . Authorization === 'Bearer FOREIGN'
? new Response ( JSON . stringify ({ code : 'A0404' }), { status : 404 , headers : { 'content-type' : 'application/json' } })
: new Response ( 'CURRENT-RECEIPT' , { status : 200 , headers : { 'content-type' : 'application/octet-stream' } })
try {
assert . equal ( await verifyCustomerSignedDocuments ( context , 'OWN' ,
[{ deliveryNo : 'DEL-1' , fileId : '91' , content : 'CURRENT-RECEIPT' }], 'FOREIGN' ), true )
assert . deepEqual ( context . assertions . filter ( row => ! row . passed ), [])
assert . equal ( context . calls . some ( call => call . path . includes ( '/api/platform/' )), false )
} finally { globalThis . fetch = previousFetch }
})
test ( 'SIGNED-B fixture keeps primary options and credentials unchanged and records no password or token' , async () => {
const context = contextFor (( method , path , body , token ) => {
assert . equal ( path , '/api/auth/login' )
assert . equal ( token , '' )
assert . deepEqual ( body , { loginId : 'SECONDARY' , password : 'SECONDARY-IN-MEMORY' })
return ok ({ accessToken : 'SECONDARY-TOKEN' })
})
context . options . customerName = 'PRIMARY'
context . context = { merchantQualificationFixture : { tenantId : '100' , username : 'PRIMARY' , password : 'PRIMARY-IN-MEMORY' } }
context . createdResources . phase5OverseasFulfillment = { marker : context . marker }
const primary = context . context . merchantQualificationFixture
const options = context . options
const create = async ( secondary , flags ) => {
assert . equal ( flags . publishEnvironment , false )
assert . equal ( secondary . marker , ` ${ context . marker } -SIGNED-B` )
assert . notEqual ( secondary . options , context . options )
assert . notEqual ( secondary . context , context . context )
assert . notEqual ( secondary . createdResources , context . createdResources )
assert . equal ( secondary . options . customerName , '' )
secondary . context . merchantQualificationFixture = { tenantId : '200' , tenantName : 'SECONDARY' , username : 'SECONDARY' ,
password : 'SECONDARY-IN-MEMORY' , marker : secondary . marker }
// Even unexpected producer fields cannot enter the report's explicit metadata whitelist.
secondary . createdResources . merchantQualificationFixture = { ... secondary . context . merchantQualificationFixture , token : 'UNEXPECTED' }
}
assert . equal ( await createSignedDocumentIsolationCustomer ( context , { create }), 'SECONDARY-TOKEN' )
assert . equal ( context . options , options )
assert . equal ( context . options . customerName , 'PRIMARY' )
assert . equal ( context . context . merchantQualificationFixture , primary )
assert . equal ( context . context . phase5TailVerification . foreignMerchantToken , 'SECONDARY-TOKEN' )
const report = JSON . stringify ( context . createdResources )
assert . doesNotMatch ( report , /password|token|IN-MEMORY|UNEXPECTED|SECONDARY-TOKEN/ )
assert . equal ( context . createdResources . phase5OverseasFulfillment . signedDocumentIsolationCustomer . marker , 'TAIL-CURRENT-SIGNED-B' )
assert . deepEqual ( context . assertions . filter ( row => ! row . passed ), [])
})
test ( 'incomplete SIGNED-B producer remains a blocker and never logs in as the primary customer' , async () => {
const context = contextFor (() => { throw new Error ( 'must not log in' ) })
context . context = { merchantQualificationFixture : { tenantId : '100' , username : 'PRIMARY' , password : 'PRIMARY-IN-MEMORY' } }
context . createdResources . phase5OverseasFulfillment = { marker : context . marker }
const token = await createSignedDocumentIsolationCustomer ( context , { create : async () => {} })
assert . equal ( token , null )
assert . equal ( context . calls . length , 0 )
assert . ok ( context . assertions . some ( row => ! row . passed ))
assert . equal ( context . context . phase5TailVerification , undefined )
})
2026-09-30 13:15:20 +08:00
function inventoryFixture () {
const position = ( positionId , inboundCode , packages ) => ({ id : positionId , balanceId : '1' , customerId : '100' ,
overseasWarehouseId : 'WH-1' , inboundCode , inboundOrderId : `ORDER- ${ inboundCode } ` , palletId : `PALLET- ${ positionId } ` ,
palletNo : `P- ${ positionId } ` , batchNo : 'B-1' , warehouseLocationId : 'LOCATION-1' , warehouseLocationCode : 'L-1' ,
totalPackages : packages , availablePackages : packages , holdPackages : 0 , allocatedPackages : 0 , pickedPackages : 0 , receivingPackages : 0 })
return { balance : { id : '1' , customerId : '100' , overseasWarehouseId : 'WH-1' , skuCode : 'MIXED' ,
totalPackages : 9 , availablePackages : 9 , holdPackages : 0 , allocatedPackages : 0 , pickedPackages : 0 ,
receivingPackages : 0 , inTransitPackages : 4 , procurementPackages : 2 },
positions : [ position ( '11' , 'IN-A' , 3 ), position ( '12' , 'IN-A-1' , 2 ), position ( '13' , 'IN-B' , 4 )] }
}
function inventoryContext ( fixture ) {
return contextFor (( method , path ) => path . includes ( '/positions' ) ? ok ( fixture . positions )
2026-09-30 13:50:13 +08:00
: path . includes ( '/balances/1?' ) ? ok ( fixture . balance ) : ok ({ records : [ fixture . balance ], total : 1 }))
2026-09-30 13:15:20 +08:00
}
test ( 'inventory evidence resolves missing Balance inboundCode through exact positions and retains an independent shared balance' , async () => {
const fixture = inventoryFixture ()
const context = inventoryContext ( fixture )
2026-09-30 13:50:13 +08:00
const snapshot = await inventorySnapshot ( context , '100' , 'WH-1' , [ 'IN-A' , 'IN-A' , 'IN-B' ], 'stock' , [ '1' ])
2026-09-30 13:15:20 +08:00
assert . equal ( snapshot . length , 1 )
assert . equal ( snapshot [ 0 ]. id , '1' )
assert . equal ( snapshot [ 0 ]. totalPackages , 7 )
assert . deepEqual ( snapshot [ 0 ]. inboundCodes , [ 'IN-A' , 'IN-B' ])
assert . deepEqual ( snapshot [ 0 ]. matchingPositionIds , [ '11' , '13' ])
assert . equal ( snapshot [ 0 ]. balance . totalPackages , 9 )
assert . equal ( snapshot [ 0 ]. balance . inTransitPackages , 4 )
assert . equal ( snapshot [ 0 ]. balance . procurementPackages , 2 )
assert . equal ( snapshot [ 0 ]. positions . length , 3 )
assert . deepEqual ( context . assertions . filter ( row => ! row . passed ), [])
assert . equal ( context . calls . filter ( call => call . path . includes ( '/positions' )). length , 1 )
const childOnly = inventoryFixture ()
childOnly . positions = [ childOnly . positions [ 1 ]]
childOnly . balance . totalPackages = 2 ; childOnly . balance . availablePackages = 2
2026-09-30 13:50:13 +08:00
const childSnapshot = await inventorySnapshot ( inventoryContext ( childOnly ), '100' , 'WH-1' , [ 'IN-A' ], 'stock' , [ '1' ])
assert . equal ( childSnapshot [ 0 ]. totalPackages , 0 )
assert . deepEqual ( childSnapshot [ 0 ]. matchingPositionIds , [])
2026-09-30 13:15:20 +08:00
})
test ( 'inventory evidence rejects foreign balances and positions, mismatched balance IDs, duplicate identities, and broken bucket reconciliation' , async () => {
for ( const mutate of [
fixture => { fixture . balance . customerId = 'OTHER' },
fixture => { fixture . balance . overseasWarehouseId = 'OTHER' },
fixture => { fixture . positions [ 0 ]. customerId = 'OTHER' },
fixture => { fixture . positions [ 0 ]. overseasWarehouseId = 'OTHER' },
fixture => { fixture . positions [ 0 ]. balanceId = 'OTHER' },
fixture => { fixture . positions [ 0 ]. id = fixture . positions [ 1 ]. id },
fixture => { fixture . positions [ 0 ]. inboundCode = '' },
fixture => { fixture . positions [ 0 ]. receivingPackages = 1 },
fixture => { fixture . balance . inTransitPackages = null },
fixture => { delete fixture . positions [ 0 ]. receivingPackages },
fixture => { fixture . balance . availablePackages = 8 },
]) {
const fixture = inventoryFixture (); mutate ( fixture )
const context = inventoryContext ( fixture )
2026-09-30 13:50:13 +08:00
assert . equal ( await inventorySnapshot ( context , '100' , 'WH-1' , [ 'IN-A' ], 'stock' , [ '1' ]), null )
2026-09-30 13:15:20 +08:00
assert . ok ( context . assertions . some ( row => ! row . passed ))
}
})
test ( 'inventory evidence captures zero drift independently for every balance bucket, position identity, and unselected sibling position' , async () => {
const fixture = inventoryFixture ()
2026-09-30 13:50:13 +08:00
const original = await inventorySnapshot ( inventoryContext ( fixture ), '100' , 'WH-1' , [ 'IN-A' ], 'stock' , [ '1' ])
2026-09-30 13:15:20 +08:00
for ( const field of [ 'inTransitPackages' , 'procurementPackages' ]) {
const changed = inventoryFixture (); changed . balance [ field ] += 1
2026-09-30 13:50:13 +08:00
assert . notDeepEqual ( await inventorySnapshot ( inventoryContext ( changed ), '100' , 'WH-1' , [ 'IN-A' ], 'stock' , [ '1' ]), original )
2026-09-30 13:15:20 +08:00
}
for ( const field of [ 'palletId' , 'palletNo' , 'batchNo' , 'warehouseLocationId' , 'warehouseLocationCode' , 'inboundOrderId' ]) {
const changed = inventoryFixture (); changed . positions [ 2 ][ field ] = 'DIFFERENT'
2026-09-30 13:50:13 +08:00
assert . notDeepEqual ( await inventorySnapshot ( inventoryContext ( changed ), '100' , 'WH-1' , [ 'IN-A' ], 'stock' , [ '1' ]), original )
2026-09-30 13:15:20 +08:00
}
for ( const field of [ 'holdPackages' , 'allocatedPackages' , 'pickedPackages' , 'receivingPackages' ]) {
const changed = inventoryFixture (); changed . positions [ 2 ][ field ] += 1 ; changed . balance [ field ] += 1
2026-09-30 13:50:13 +08:00
assert . notDeepEqual ( await inventorySnapshot ( inventoryContext ( changed ), '100' , 'WH-1' , [ 'IN-A' ], 'stock' , [ '1' ]), original )
2026-09-30 13:15:20 +08:00
}
})
2026-09-30 13:50:13 +08:00
2026-10-20 10:35:52 +08:00
test ( 'departure requires independent matching native stage, shared version, reconciled picks and both action gates' , async () => {
const valid = { dispatchNo : 'DS-1' , status : 'ACTIVE' , stage : 'AFTER_LOADING' , recordVersion : '9007199254740993' ,
pickingReconciled : true , actions : { DEPART : { allowed : true } } }
for ( const change of [ null , { stage : 'LOADING' }, { stage : 'DELIVERING' }, { status : 'CANCELLED' },
{ dispatchNo : 'OTHER' }, { recordVersion : '9007199254740994' }, { pickingReconciled : false },
{ actions : { DEPART : { allowed : false } } }]) {
const context = contextFor (( method , path ) => ok ( path . startsWith ( '/api/pda/' ) ? valid : { ... valid , ... change }))
assert . equal ( Boolean ( await verifyDepartureReadiness ( context , 'PDA' , 'DS-1' )), change == null )
2026-09-30 13:50:13 +08:00
assert . equal ( context . calls . length , 2 )
assert . equal ( context . calls . some ( call => call . method !== 'GET' ), false )
}
})
test ( 'G05 freezes actual PDA balance IDs and measures raw sources independently from grouped representatives without inbound filters' , async () => {
const task = { dispatchNo : 'DS-1' , warehouseId : 'WH-1' , items : [
2026-10-20 10:35:52 +08:00
{ positions : [{ positionId : '11' , balanceId : '1' }, { positionId : '12' , balanceId : '2' }, { positionId : '11' , balanceId : '1' }] }] }
2026-09-30 13:50:13 +08:00
assert . deepEqual ( dispatchInventorySources ( task , 'DS-1' , 'WH-1' ), { sourceBalanceIds : [ '1' , '2' ], sourcePositionIds : [ '11' , '12' ],
sourcePositionBalances : [{ positionId : '11' , balanceId : '1' }, { positionId : '12' , balanceId : '2' }] })
assert . equal ( dispatchInventorySources ( task , 'OTHER' , 'WH-1' ), null )
assert . equal ( dispatchInventorySources ( task , 'DS-1' , 'OTHER' ), null )
2026-10-20 10:35:52 +08:00
assert . equal ( dispatchInventorySources ({ ... task , items : [{ positions : [{ positionId : '11' }] }] }, 'DS-1' , 'WH-1' ), null )
2026-09-30 13:50:13 +08:00
let shipped = false
const source = balanceId => ({ id : balanceId , customerId : '100' , overseasWarehouseId : 'WH-1' ,
destinationWarehouseCode : 'FBA' , skuCode : 'MIXED' , totalPackages : balanceId === '1' ? 3 : 6 ,
availablePackages : balanceId === '1' ? 3 : 6 , holdPackages : 0 , allocatedPackages : 0 , pickedPackages : 0 ,
receivingPackages : 0 , inTransitPackages : 0 , procurementPackages : 0 })
const context = contextFor (( method , path ) => {
assert . equal ( new URL ( `https://test.invalid ${ path } ` ). searchParams . has ( 'inboundCode' ), false )
const match = path . match ( /balances\/(1|2)(\/positions)?\?/ )
if ( ! match ) return ok ({ records : [{ ... source ( shipped ? '99' : '1' ), totalPackages : shipped ? 3 : 12 , availablePackages : shipped ? 3 : 12 }], total : 1 })
const balance = source ( match [ 1 ])
if ( match [ 2 ]) return ok ([{ ... balance , id : match [ 1 ] === '1' ? '11' : '12' , balanceId : match [ 1 ], inboundCode : 'IN-A' ,
totalPackages : shipped ? 0 : balance . totalPackages , availablePackages : shipped ? 0 : balance . availablePackages }])
return shipped ? { http : 404 , body : { code : 'A0404' } } : ok ( balance )
})
const frozenSources = dispatchInventorySources ( task , 'DS-1' , 'WH-1' )
const frozenIds = frozenSources . sourceBalanceIds
const before = await inventorySnapshot ( context , '100' , 'WH-1' , [ 'IN-A' ], 'before' , frozenIds )
assert . equal ( inventorySourcesPresent ( before , frozenSources . sourcePositionBalances ), true )
assert . equal ( inventorySourcesPresent ( before , [{ positionId : '11' , balanceId : '2' }]), false )
assert . equal ( inventorySourcesPresent ( before , [{ positionId : 'UNKNOWN' , balanceId : '1' }]), false )
assert . equal ( before . reduce (( sum , row ) => sum + row . totalPackages , 0 ), 9 )
assert . equal ( before . reduce (( sum , row ) => sum + row . balance . totalPackages , 0 ), 9 )
assert . equal ( before [ 0 ]. globalGroups [ 0 ]. totalPackages , 12 )
shipped = true
const after = await inventorySnapshot ( context , '100' , 'WH-1' , [ 'IN-A' ], 'after' , frozenIds )
assert . equal ( inventorySourcesPresent ( after , frozenSources . sourcePositionBalances ), true )
assert . equal ( after . reduce (( sum , row ) => sum + row . totalPackages , 0 ), 0 )
assert . equal ( after . reduce (( sum , row ) => sum + row . balance . totalPackages , 0 ), 0 )
assert . equal ( after [ 0 ]. globalGroups [ 0 ]. totalPackages , 3 )
assert . deepEqual ( after , await inventorySnapshot ( context , '100' , 'WH-1' , [ 'IN-A' ], 'replay' , frozenIds ))
assert . deepEqual ( context . assertions . filter ( row => ! row . passed ), [])
})
test ( 'source snapshot never treats unknown or incompletely proven raw 404 as zero inventory' , async () => {
const missing = { http : 404 , body : { code : 'A0404' } }
for ( const mode of [ 'unknown' , 'positions-failure' , 'position-nonzero' , 'group-not-decreased' ]) {
let absent = false
const fixture = inventoryFixture ()
fixture . balance . inTransitPackages = 0 ; fixture . balance . procurementPackages = 0
const context = contextFor (( method , path ) => {
if ( path . includes ( '/positions' )) {
if ( absent && mode === 'positions-failure' ) return missing
return ok ( fixture . positions . map ( row => absent && mode !== 'position-nonzero'
? { ... row , totalPackages : 0 , availablePackages : 0 } : row ))
}
if ( path . includes ( '/balances/1?' )) return absent ? missing : ok ( fixture . balance )
return ok ({ total : absent && mode !== 'group-not-decreased' ? 0 : 1 ,
records : absent && mode !== 'group-not-decreased' ? [] : [ fixture . balance ] })
})
if ( mode !== 'unknown' ) assert . ok ( await inventorySnapshot ( context , '100' , 'WH-1' , [ 'IN-A' ], 'before' , [ '1' ]))
absent = true
assert . equal ( await inventorySnapshot ( context , '100' , 'WH-1' , [ 'IN-A' ], 'after' , [ '1' ]), null )
assert . ok ( context . assertions . some ( row => ! row . passed ))
}
const context = contextFor (() => { throw new Error ( 'Missing fixed IDs cannot issue HTTP reads' ) })
assert . equal ( await inventorySnapshot ( context , '100' , 'WH-1' , [ 'IN-A' ], 'stock' ), null )
})
2026-09-30 14:27:45 +08:00
function representativePalletConservationFixture () {
const quantities = [ 1 , 3 , 1 , 3 , 1 ]
const codes = [ 'IN-A' , 'IN-A-OTHER' , 'IN-B' , 'IN-B-OTHER' , 'IN-C' ]
const references = quantities . map (( _ , index ) => ({ balanceId : String ( index + 1 ), positionId : String ( index + 11 ) }))
const groups = packages => [{ id : 'GROUP' , customerId : '100' , overseasWarehouseId : 'WH-1' , skuCode : 'MIXED' ,
totalPackages : packages , availablePackages : packages , holdPackages : 0 , allocatedPackages : 0 , pickedPackages : 0 ,
receivingPackages : 0 , inTransitPackages : 0 , procurementPackages : 0 }]
const snapshot = after => quantities . map (( quantity , index ) => {
const balanceId = String ( index + 1 )
const position = { id : String ( index + 11 ), balanceId , customerId : '100' , overseasWarehouseId : 'WH-1' ,
inboundCode : codes [ index ], palletNo : index < 2 ? 'P-A' : index < 4 ? 'P-B' : 'P-C' ,
totalPackages : after ? 0 : quantity , availablePackages : after ? 0 : quantity ,
holdPackages : 0 , allocatedPackages : 0 , pickedPackages : 0 , receivingPackages : 0 }
const leftover = { ... position , id : '99' , palletNo : 'UNSELECTED' , totalPackages : 3 , availablePackages : 3 }
const positions = index === 4 ? [ position , leftover ] : [ position ]
const exact = positions . filter ( row => [ 'IN-A' , 'IN-B' , 'IN-C' ]. includes ( row . inboundCode ))
const total = positions . reduce (( sum , row ) => sum + row . totalPackages , 0 )
return { id : balanceId , totalPackages : exact . reduce (( sum , row ) => sum + row . totalPackages , 0 ),
balance : { id : balanceId , totalPackages : total }, positions , globalGroups : groups ( after ? 3 : 12 ) }
})
const ledger = quantities . map (( quantity , index ) => ({ id : String ( index + 101 ), customerId : '100' ,
overseasWarehouseId : 'WH-1' , businessType : 'SHIP' , businessOrderNo : 'DS-1' , outboundOrderNo : 'DS-1' ,
inboundCode : codes [ index ], palletNo : index < 2 ? 'P-A' : index < 4 ? 'P-B' : 'P-C' ,
beforePackages : quantity , deltaPackages : - quantity , afterPackages : 0 }))
return { customerId : '100' , warehouseId : 'WH-1' , dispatchNo : 'DS-1' , expectedPackages : 9 ,
sourcePositionBalances : references , stockBefore : snapshot ( false ), stockAfter : snapshot ( true ),
ledgerBefore : [], ledgerAfter : ledger }
}
test ( 'G05 MIN inbound-code display does not filter real same-pallet sources: positions9→0/raw12→3/groups12→3/SHIP-9' , () => {
const fixture = representativePalletConservationFixture ()
const context = contextFor (() => { throw new Error ( 'Offline arithmetic cannot issue HTTP' ) })
context . createdResources . phase5OverseasFulfillment = { inventoryProof : {} }
assert . equal ( fixture . stockBefore . reduce (( sum , row ) => sum + row . totalPackages , 0 ), 6 )
assert . equal ( fixture . stockAfter . reduce (( sum , row ) => sum + row . totalPackages , 0 ), 3 )
const result = dispatchStockConservation ( context , fixture )
assert . equal ( result . passed , true )
assert . deepEqual ( result . proof . totals , { positionBefore : 9 , positionAfter : 0 , rawBefore : 12 , rawAfter : 3 ,
groupBefore : 12 , groupAfter : 3 , ledgerShipped : 9 , expectedPackages : 9 })
assert . equal ( result . proof . ledgerRowChecks . length , 5 )
assert . deepEqual ( context . assertions . filter ( row => ! row . passed ), [])
const saved = context . createdResources . phase5OverseasFulfillment . inventoryProof
assert . deepEqual ( saved . snapshots . beforePick , fixture . stockBefore )
assert . deepEqual ( saved . ledgers . afterPick , fixture . ledgerAfter )
assert . ok ( JSON . stringify ( saved ). includes ( 'IN-A-OTHER' ))
assert . doesNotMatch ( JSON . stringify ( saved ), /password|accessToken|Bearer|base64/ )
})
test ( 'G05 failures still independently review and preserve raw, group, each SHIP quantity/source, and unselected positions' , () => {
for ( const mutate of [
fixture => { fixture . stockAfter [ 0 ]. positions [ 0 ]. id = 'WRONG-POSITION' },
fixture => { fixture . stockAfter [ 0 ]. balance . totalPackages = 1 },
fixture => { for ( const row of fixture . stockAfter ) row . globalGroups [ 0 ]. totalPackages = 4 },
fixture => { fixture . ledgerAfter [ 0 ]. deltaPackages = - 2 },
fixture => { fixture . ledgerAfter [ 0 ]. customerId = 'OTHER' },
fixture => { fixture . ledgerAfter [ 0 ]. overseasWarehouseId = 'OTHER' },
fixture => { fixture . ledgerAfter [ 0 ]. outboundOrderNo = 'OTHER' },
fixture => { fixture . ledgerAfter [ 0 ]. palletNo = 'UNSELECTED' },
fixture => { fixture . stockAfter [ 4 ]. positions [ 1 ]. availablePackages = 2 },
]) {
const fixture = representativePalletConservationFixture (); mutate ( fixture )
const context = contextFor (() => { throw new Error ( 'Offline only' ) })
context . createdResources . phase5OverseasFulfillment = { inventoryProof : {} }
const result = dispatchStockConservation ( context , fixture )
assert . equal ( result . passed , false )
assert . equal ( context . assertions . length , 9 )
assert . equal ( Object . keys ( result . proof . checks ). length , 8 )
assert . equal ( result . proof . ledgerRowChecks . length , 5 )
assert . deepEqual ( context . createdResources . phase5OverseasFulfillment . inventoryProof . snapshots . afterPick , fixture . stockAfter )
assert . deepEqual ( context . createdResources . phase5OverseasFulfillment . inventoryProof . ledgers . afterPick , fixture . ledgerAfter )
}
})
2026-09-30 15:16:39 +08:00
function rootCompletionFixture ({ childStatus = 'PROCESSING' , rootStatus = 'PROCESSING' , rootDelivered = true ,
fullyLoaded = false , mainStatus = rootStatus === 'COMPLETED' ? 'COMPLETED' : 'DELIVERED' , sourceOrderId = '1001' } = {}) {
const root = { order : { id : '1001' , tenantId : '100' , customerId : '100' , orderRole : 'MASTER' , rootOrderId : '1001' ,
orderNo : 'FL1001' , status : rootStatus }, statusHistory : [
...( rootDelivered ? [{ action : 'OVERSEAS_DELIVERED' }] : []),
...( rootStatus === 'COMPLETED' ? [{ action : 'FULFILLMENT_COMPLETED' }] : [])] }
const child = { order : { id : '1002' , tenantId : '100' , customerId : '100' , orderRole : 'CHILD' ,
rootOrderId : '1001' , parentOrderId : '1001' , orderNo : 'FL1001-1' , status : childStatus } }
const tree = { parentOrderId : '1001' , parentOrderNo : 'FL1001' , originalPackageCount : 4 ,
cumulativeLoadedPackageCount : fullyLoaded ? 4 : 1 , currentRemainderPackageCount : fullyLoaded ? 0 : 3 ,
children : [{ orderId : '1001' , orderNo : 'FL1001' , splitRole : 'LOADED' , sourceOrderId : '1001' , packageCount : 1 },
{ orderId : '1002' , orderNo : 'FL1001-1' , splitRole : 'REMAINDER' , sourceOrderId : '1001' , packageCount : 3 },
...( fullyLoaded ? [{ orderId : '1002' , orderNo : 'FL1001-1' , splitRole : 'LOADED' , sourceOrderId : '1002' , packageCount : 3 }] : [])] }
const context = contextFor (( method , path ) => {
if ( path . includes ( '/fulfillment-tree' )) return ok ( tree )
if ( path . includes ( '/first-leg/1002' )) return ok ( child )
if ( path . includes ( '/first-leg/1001' )) return ok ( root )
return ok ({ summary : { orderId : '1001' , mainStatus } })
})
context . createdResources . phase5OverseasFulfillment = {}
return { root , child , tree , context ,
args : { sourceOrderId , customerId : '100' , merchantToken : 'ONLY-IN-MEMORY' , pollAttempts : 1 , pollIntervalMs : 0 } }
}
test ( 'real root1 signed plus effective remainder3 keeps raw PROCESSING and both platform/client DELIVERED' , async () => {
const fixture = rootCompletionFixture ()
const result = await verifyFulfillmentRootStatus ( fixture . context , fixture . args )
assert . equal ( result . passed , true )
assert . equal ( result . expectedCompleted , false )
assert . deepEqual ( result . pendingChildren . map ( row => row . orderId ), [ '1002' ])
assert . deepEqual ( fixture . context . assertions . filter ( row => ! row . passed ), [])
const proof = fixture . context . createdResources . phase5OverseasFulfillment . orderCompletionProof
assert . equal ( proof . tree . originalPackageCount , 4 )
assert . equal ( proof . tree . currentRemainderPackageCount , 3 )
assert . deepEqual ( proof . pendingChildOrderIds , [ '1002' ])
assert . doesNotMatch ( JSON . stringify ( proof ), /ONLY-IN-MEMORY|password|accessToken|Bearer/ )
})
test ( 'missing, foreign, unknown or omitted real child cannot be treated as all fulfillment completed' , async () => {
for ( const mutate of [
fixture => { fixture . child . order = null },
fixture => { fixture . child . order . customerId = 'FOREIGN' },
fixture => { fixture . child . order . rootOrderId = 'OTHER' },
fixture => { fixture . child . order . parentOrderId = 'OTHER' },
fixture => { fixture . child . order . orderNo = 'WRONG' },
fixture => { fixture . child . order . status = undefined },
fixture => { fixture . child . order . status = 'UNKNOWN' },
fixture => { fixture . tree . children . pop () },
fixture => { fixture . tree . children = undefined },
]) {
const fixture = rootCompletionFixture (); mutate ( fixture )
assert . equal ( await verifyFulfillmentRootStatus ( fixture . context , fixture . args ), null )
assert . ok ( fixture . context . assertions . some ( row => ! row . passed ))
assert . equal ( fixture . context . calls . some ( call => call . path . startsWith ( '/api/merchant/' )), false )
}
})
test ( 'draft, rejected and pending child stay effective, and a premature root COMPLETED still fails' , async () => {
for ( const childStatus of [ 'DRAFT' , 'SUBMITTED' , 'APPROVED' , 'ACCEPTED' , 'REJECTED' , 'PROCESSING' ]) {
const fixture = rootCompletionFixture ({ childStatus , rootStatus : 'COMPLETED' })
const result = await verifyFulfillmentRootStatus ( fixture . context , fixture . args )
assert . equal ( result . expectedCompleted , false )
assert . equal ( result . passed , false )
assert . equal ( result . pendingChildren . length , 1 )
assert . ok ( fixture . context . assertions . some ( row => ! row . passed ))
}
})
test ( 'actual completed child or explicit CANCELLED permits completion only with root own receipt and raw completion fact' , async () => {
for ( const childStatus of [ 'COMPLETED' , 'CANCELLED' ]) {
const fixture = rootCompletionFixture ({ childStatus , rootStatus : 'COMPLETED' , fullyLoaded : childStatus === 'COMPLETED' })
const result = await verifyFulfillmentRootStatus ( fixture . context , fixture . args )
assert . equal ( result . expectedCompleted , true )
assert . equal ( result . passed , true )
assert . deepEqual ( result . pendingChildren , [])
assert . deepEqual ( fixture . context . assertions . filter ( row => ! row . passed ), [])
}
const fixture = rootCompletionFixture ({ childStatus : 'COMPLETED' , fullyLoaded : true , rootDelivered : false })
const result = await verifyFulfillmentRootStatus ( fixture . context , fixture . args )
assert . equal ( result . expectedCompleted , false )
assert . equal ( result . passed , true )
})
test ( 'receipt of a real child resolves and checks its owning root instead of completing the child as the aggregate' , async () => {
const fixture = rootCompletionFixture ({ childStatus : 'COMPLETED' , rootStatus : 'COMPLETED' , fullyLoaded : true , sourceOrderId : '1002' })
const result = await verifyFulfillmentRootStatus ( fixture . context , fixture . args )
assert . equal ( result . rootOrderId , '1001' )
assert . equal ( result . passed , true )
assert . ok ( fixture . context . calls . some ( call => call . path === '/api/merchant/v1/orders/1001' ))
assert . equal ( fixture . context . calls . some ( call => call . path === '/api/merchant/v1/orders/1002' ), false )
})
test ( 'all fragments completed still requires raw aggregate history and matching platform/customer completion' , async () => {
const missingHistory = rootCompletionFixture ({ childStatus : 'COMPLETED' , rootStatus : 'COMPLETED' , fullyLoaded : true })
missingHistory . root . statusHistory = [{ action : 'OVERSEAS_DELIVERED' }]
assert . equal (( await verifyFulfillmentRootStatus ( missingHistory . context , missingHistory . args )). passed , false )
const notProjected = rootCompletionFixture ({ childStatus : 'COMPLETED' , rootStatus : 'COMPLETED' , fullyLoaded : true , mainStatus : 'DELIVERED' })
assert . equal (( await verifyFulfillmentRootStatus ( notProjected . context , notProjected . args )). passed , false )
const foreignProjection = rootCompletionFixture ({ childStatus : 'COMPLETED' , rootStatus : 'COMPLETED' , fullyLoaded : true })
const originalRequest = foreignProjection . context . request
foreignProjection . context . request = async (... args ) => args [ 1 ]. startsWith ( '/api/merchant/' )
? ok ({ summary : { orderId : '1002' , mainStatus : 'COMPLETED' } }) : originalRequest (... args )
assert . equal (( await verifyFulfillmentRootStatus ( foreignProjection . context , foreignProjection . args )). passed , false )
})
2026-10-20 10:35:52 +08:00
test ( 'native PDA scans use exact current versions including zero, immutable replay and stale-version rejection without implicit loading' , async () => {
const values = [ '0' , '9007199254740993' , '9007199254740994' ]
let currentVersion = values [ 0 ], picked = 0 , firstBody , firstResult
const context = contextFor (( method , path , body ) => {
if ( method === 'GET' ) return ok ({ dispatchNo : 'DS-1' , status : 'ACTIVE' , stage : 'LOADING' , recordVersion : currentVersion ,
pickingReconciled : picked === 2 , counts : { packageCount : 2 , pickedPackageCount : picked },
items : [{ dispatchItemId : '9007199254740995' , customerId : '100' , scheduledPackages : 2 , pickedPackages : picked ,
positions : [{ positionId : '9007199254740996' , balanceId : '9007199254740997' , availablePackages : 1 },
{ positionId : '9007199254740998' , balanceId : '9007199254740999' , availablePackages : 1 }] }] })
assert . match ( path , /items\/9007199254740995\/pick$/ )
assert . equal ( Object . hasOwn ( body , 'expectedVersion' ), false )
assert . equal ( typeof body . positionId , 'string' )
if ( body . idempotencyKey . endsWith ( '-STALE' )) {
assert . equal ( body . recordVersion , '0' ); return { http : 200 , body : { code : 'A0409' } }
}
if ( firstBody ? . idempotencyKey === body . idempotencyKey ) {
assert . deepEqual ( body , firstBody ); return ok ({ ... firstResult , replayed : true })
}
assert . equal ( body . recordVersion , currentVersion )
picked += 1 ; currentVersion = values [ picked ]
firstBody = structuredClone ( body )
firstResult = { dispatchNo : 'DS-1' , status : 'ACTIVE' , stage : 'LOADING' , recordVersion : currentVersion ,
result : { dispatchItemId : '9007199254740995' , pickedPackages : picked }, counts : { pickedPackageCount : picked } }
return ok ( firstResult )
})
assert . equal ( await pickAll ( context , 'PDA-IN-MEMORY' , 'DS-1' ), true )
assert . equal ( picked , 2 )
assert . equal ( context . calls . some ( call => / loading - complete | \ / complete | \ / depart / . test ( call . path )), false )
assert . deepEqual ( context . assertions . filter ( row => ! row . passed ), [])
})
function nativeArrangementPreview ( recordVersion = '0' ) {
return { dispatchNo : 'DS-1' , recordVersion , status : 'ACTIVE' , stage : 'AFTER_LOADING' , cargoHash : 'CARGO' ,
loadingCompletionHash : 'LOAD' , arrange : { allowed : true }, groups : [ '100' , '200' ]. map ( customerId => ({
groupKey : `GROUP- ${ customerId } ` , customerId , destination : { key : 'FBA:ONT8' , warehouseCode : 'ONT8' },
groupCargoHash : `GROUP-HASH- ${ customerId } ` , externalFreightHash : 'FREIGHT' , feeCoverageCargoHash : 'COVERAGE' ,
requiredServices : [ 'DELIVERY_FEE' ], feeSources : [], cargo : [{ customerId , packages : 1 }], blockReasons : [] })) }
}
test ( 'native arrangement carries frozen group and cost hashes, preserves all customer outbounds, and replays the exact original command' , async () => {
for ( const recordVersion of [ '0' , '9007199254740993' ]) {
const preview = nativeArrangementPreview ( recordVersion )
let original , result
const context = contextFor (( method , path , body ) => {
if ( method === 'GET' ) { assert . match ( path , /delivery-arrangement$/ ); return ok ( preview ) }
assert . match ( path , /transfer-delivery$/ )
if ( original ) { assert . deepEqual ( body , original ); return ok ({ ... result , replayed : true }) }
original = structuredClone ( body )
assert . equal ( body . recordVersion , recordVersion )
assert . equal ( body . cargoHash , 'CARGO' ); assert . equal ( body . loadingCompletionHash , 'LOAD' )
assert . deepEqual ( body . groups . map ( row => row . groupKey ), [ 'GROUP-100' , 'GROUP-200' ])
assert . ok ( body . groups . every ( row => row . externalFreightHash === 'FREIGHT' && row . feeCoverageCargoHash === 'COVERAGE' ))
result = { dispatchNo : 'DS-1' , status : 'ACTIVE' , stage : 'AFTER_LOADING' , recordVersion : '9007199254740994' ,
result : { dispatchNo : 'DS-1' , cargoHash : 'CARGO' , outbounds : [ '100' , '200' ]. map ( customerId => ({
customerId , outboundNo : `OB- ${ customerId } ` , status : 'WAIT_OUTBOUND' , packageCount : 1 })),
deliveries : [ '100' , '200' ]. map ( customerId => ({ customerId , outboundNo : `OB- ${ customerId } ` ,
deliveryNo : `DL- ${ customerId } ` , destination : { key : 'FBA:ONT8' , warehouseCode : 'ONT8' }, status : 'WAIT_DELIVERY' , packageCount : 1 })) } }
return ok ( result )
})
const arranged = await arrangeDispatchDelivery ( context , 'DS-1' )
assert . deepEqual ( arranged . outbounds . map ( row => row . outboundNo ), [ 'OB-100' , 'OB-200' ])
assert . equal ( context . calls . filter ( call => call . method === 'POST' ). length , 2 )
assert . deepEqual ( context . assertions . filter ( row => ! row . passed ), [])
}
})
test ( 'arrangement cannot run before loading or with missing hashes, groups or server gate' , async () => {
for ( const mutate of [ value => { value . stage = 'LOADING' }, value => { value . status = 'CANCELLED' },
value => { value . cargoHash = '' }, value => { value . loadingCompletionHash = '' },
value => { value . groups = [] }, value => { value . arrange . allowed = false },
value => { value . groups [ 0 ]. blockReasons = [ 'MISSING_FEE' ] }]) {
const preview = nativeArrangementPreview (); mutate ( preview )
const context = contextFor (( method ) => { assert . equal ( method , 'GET' ); return ok ( preview ) })
assert . equal ( await arrangeDispatchDelivery ( context , 'DS-1' ), null )
assert . ok ( context . assertions . some ( row => ! row . passed ))
}
})
for ( const [ name , outcome ] of [
[ 'transport' , { http : 0 , body : { code : '' } }],
[ 'infrastructure' , { http : 503 , body : { code : 'S0503' } }],
[ 'malformed success' , { http : 200 , body : { code : '200' , data : null } }],
[ 'missing business response' , { http : 200 , body : {} }],
]) test ( `write intent persists and ${ name } stops commands and checkpoint restarts` , async () => {
const dir = await mkdtemp ( join ( tmpdir (), 'phase5-contract-' ))
try {
const context = contextFor ( async ( method , path , body ) => {
const saved = JSON . parse ( await readFile ( context . createdResources . phase5OverseasFulfillment . checkpointPath , 'utf8' ))
assert . equal ( saved . requests . at ( - 1 ). status , 'SENDING' )
assert . equal ( saved . requests . at ( - 1 ). body . recordVersion , '0' )
assert . equal ( saved . requests . at ( - 1 ). body . idempotencyKey , body . idempotencyKey )
assert . equal ( JSON . stringify ( saved ). includes ( 'SECRET-CREDENTIAL' ), false )
return { ... outcome , requestId : 'REQ-UNKNOWN' , traceId : 'TRACE-UNKNOWN' }
})
context . options . output = join ( dir , 'report.json' )
context . createdResources . phase5OverseasFulfillment = {}
const scoped = await fulfillmentEvidenceContext ( context )
const body = { recordVersion : '0' , idempotencyKey : 'ORIGINAL-COMMAND' , password : 'SECRET-CREDENTIAL' }
await assert . rejects ( scoped . request ( 'POST' , '/api/platform/v1/last-leg/dispatches/DS-1/depart' , body ), /结果未知/ )
await assert . rejects ( scoped . request ( 'POST' , '/api/platform/v1/last-leg/dispatches/DS-1/depart' , { ... body , idempotencyKey : 'NEW-KEY' }), /未知写结果/ )
assert . equal ( context . calls . length , 1 )
const saved = JSON . parse ( await readFile ( context . createdResources . phase5OverseasFulfillment . checkpointPath , 'utf8' ))
assert . equal ( saved . status , 'UNKNOWN' ); assert . equal ( saved . requests [ 0 ]. status , 'UNKNOWN' )
assert . equal ( saved . requests [ 0 ]. requestId , 'REQ-UNKNOWN' )
await assert . rejects ( fulfillmentEvidenceContext ( context ), /已存在本轮履约检查点/ )
} finally { await rm ( dir , { recursive : true , force : true }) }
})
test ( 'default normal completion returns before exception writes; explicit legacy return stays after its original receipt guards and before closure' , () => {
const run = source . slice ( source . indexOf ( 'export async function run' ))
const start = run . indexOf ( 'if (context.context?.phase5TailVerification?.runReturnScenario !== true)' )
const exception = run . indexOf ( 'const manualExceptionBody' )
assert . ok ( start > run . indexOf ( "savedVisit.data?.visit?.status !== 'COMPLETED'" ))
const normalBranch = run . slice ( start , exception )
assert . ok ( normalBranch . includes ( "finalStatus = 'DELIVERED_WITH_COMPLETED_VISIT'" ))
assert . match ( normalBranch , /await finishFleetTrip/ )
assert . match ( normalBranch , /return\s*}/ )
assert . doesNotMatch ( normalBranch , /createDeliveryReturn|completeReturnedException|exception-orders|mark-return/ )
const explicitBranch = run . slice ( exception )
assert . ok ( explicitBranch . indexOf ( 'const returnReceipt = await completeReturnedException' ) < explicitBranch . indexOf ( 'await finishFleetTrip' ))
assert . match ( source , /const sourceBalanceIds = owned.inventoryProof\?.sourceBalanceIds/ )
assert . match ( source , /原returnSource位置必须存在于正式排车冻结真实余额中/ )
})