import assert from 'node:assert/strict' import test from 'node:test' import { readFileSync } from 'node:fs' import { fulfillmentHistorySnapshot, validTwoFragmentTree, validSignatureGate, completionCounts, exactCompletionOutboxProof, resolveF40MerchantCredentials, f40TransferBody, f40LocalDateTime, validFragmentCabinetIdentity, run } from './phase5-root-fulfillment.mjs' import { loadOneFragment } from './phase3-order-splitting.mjs' import { verifyPalletLabels } from './phase3-loading-finalize.mjs' import { awaitProducerConsumption, convertReceivingContainers, runReceiving, resolveSharedWarehouse } from './phase4-overseas-pda.mjs' const source = readFileSync(new URL('./phase5-root-fulfillment.mjs', import.meta.url),'utf8') const history = (...actions) => actions.map((action,index) => ({id:String(index+1),action})) const tree = () => ({parentOrderId:'100',originalPackageCount:2,cumulativeLoadedPackageCount:2, currentRemainderPackageCount:0,children:[ {orderId:'100',sourceOrderId:'100',splitRole:'LOADED',packageCount:1}, {orderId:'101',sourceOrderId:'100',splitRole:'REMAINDER',packageCount:1}, {orderId:'101',sourceOrderId:'101',splitRole:'LOADED',packageCount:1}, ]}) const signed = () => ({root:{status:'COMPLETED',histories:history('OVERSEAS_DELIVERED','FULFILLMENT_COMPLETED')}, child:{status:'COMPLETED',histories:history('OVERSEAS_DELIVERED')}, rootInbound:{processStatus:'DELIVERED',orderStatusSnapshot:'COMPLETED'}}) const outbox = () => ({readOnly:true,customerId:'90',rootOrderId:'100',orders:['100','101'].map(orderId => ({ orderId,customerId:'90',rootOrderId:'100',eventType:'FIRST_LEG_ORDER_FULFILLMENT_COMPLETED', count:1,publishedCount:1,pendingCount:0,failedCount:0, }))}) const fixture = () => ({steps:[],token:'offline',marker:'offline-only',createdResources:{}, addStep(_module,_label,_response,passed){this.steps.push({passed})}, assert(_module,_label,_response,passed){this.steps.push({passed})}, addCoverageGap(){},apiSuccess(_module,_label,response){return response?.body?.data}, }) test('F40 transfer uses the current formal Transfer DTO including required positive fee and same LocalDateTime tool',() => { const dto=readFileSync(new URL('../../lastleg-service/src/main/java/com/baiyue/lastleg/delivery/dto/DeliveryRequests.java',import.meta.url),'utf8') const vehicle={carrierName:'offline-fleet',vehiclePlate:'offline-plate',driverName:'offline-driver',driverPhone:'19900000000'} const now=new Date('2026-09-30T01:02:03.456Z'),body=f40TransferBody('offline',1,vehicle,now) for(const field of ['idempotencyKey','plannedDeliveryAt','deliveryMethod','pickupMethod','loadingType','fees']) { assert.match(dto,new RegExp(`\\b${field}\\b`));assert.ok(body[field]) } assert.equal(body.plannedDeliveryAt,'2026-10-02T01:02:03') assert.equal(f40LocalDateTime(now),'2026-09-30T01:02:03') assert.equal(body.deliveryMethod,'TRUCK_PALLET');assert.equal(body.pickupMethod,'WAREHOUSE_PICKUP') assert.equal(body.loadingType,'PALLET');assert.equal(body.vehicleSize,'15托') for(const field of Object.keys(vehicle))assert.equal(body[field],vehicle[field]) assert.equal(body.fees.length,1) assert.deepEqual(Object.fromEntries(['feeType','feeName','direction','currency','amount'].map(field=>[field,body.fees[0][field]])), {feeType:'DELIVERY_FEE',feeName:'派送费',direction:'RECEIVABLE',currency:'USD',amount:10}) assert.match(source,/f40TransferBody\(context.marker,index,vehicle\)/) assert.match(source,/estimatedArrivalAt: f40LocalDateTime\(/) }) test('F40 credentials prefer a complete current fixture pair and never combine fixture with configured customer',() => { const options={username:'offline-admin',password:'offline-admin-secret',merchantUsername:'configured-customer',merchantPassword:'configured-secret'} const current={username:'fixture-customer',password:'fixture-secret',tenantId:'90'} assert.deepEqual(resolveF40MerchantCredentials({options,context:{merchantQualificationFixture:current}}), {username:'fixture-customer',password:'fixture-secret',customerId:'90'}) assert.deepEqual(resolveF40MerchantCredentials({options,context:{}}), {username:'configured-customer',password:'configured-secret',customerId:null}) for(const incomplete of [{username:'fixture-only',tenantId:'90'},{password:'fixture-only',tenantId:'90'}, {username:'fixture-customer',password:'fixture-secret'}]) assert.equal(resolveF40MerchantCredentials({options,context:{merchantQualificationFixture:incomplete}}),null) assert.equal(resolveF40MerchantCredentials({options:{merchantUsername:'incomplete'},context:{}}),null) assert.ok(source.indexOf("'F40 正式订单创建客户与本轮登录客户一致'") < source.indexOf("await stage(scope, 'inbound-measurement')")) }) test('F40 reads formal nested domestic cabinet workbench and compares booking/plan/task identity instead of inventing GET containers/id',() => { const controller=readFileSync(new URL('../../firstleg/src/main/java/com/baiyue/firstleg/controller/PlatformContainerController.java',import.meta.url),'utf8') const dto=readFileSync(new URL('../../firstleg/src/main/java/com/baiyue/firstleg/terminaldrayage/dto/ContainerWorkbenchDtos.java',import.meta.url),'utf8') assert.match(controller,/@GetMapping\("\/domestic\/\{id\}"\)/) assert.doesNotMatch(controller,/@GetMapping\("\/\{id\}"\)/) assert.match(dto,/record WorkbenchItem\(ContainerBookingEntity container, String workbenchStage/) assert.match(source,/`\/api\/platform\/v1\/containers\/domestic\/\$\{result.containerId\}`/) assert.doesNotMatch(source,/`\/api\/platform\/v1\/containers\/\$\{result.containerId\}`/) const fragment={containerId:'20',planId:'30',taskId:'40',oceanBookingId:'50'},task={id:'40',containerBookingId:'20',loadingPlanId:'30'} const workbench={container:{id:'20',cabinetNo:'D0001',containerNo:'OFFLINE',oceanBookingId:'50'}} assert.equal(validFragmentCabinetIdentity(workbench,fragment,task),true) assert.equal(validFragmentCabinetIdentity(workbench,{...fragment,containerId:'21'},task),false) assert.equal(validFragmentCabinetIdentity(workbench,fragment,{...task,containerBookingId:'21'}),false) assert.equal(validFragmentCabinetIdentity(workbench,fragment,{...task,loadingPlanId:'31'}),false) assert.equal(validFragmentCabinetIdentity(workbench,fragment,{...task,id:'41'}),false) assert.equal(validFragmentCabinetIdentity(workbench,{...fragment,oceanBookingId:'51'},task),false) assert.equal(validFragmentCabinetIdentity(workbench.container,fragment,task),false) }) test('formal tree requires one root physical source plus its exact real remainder child and conserves two boxes',() => { assert.equal(validTwoFragmentTree(tree(),'100','101'),true) for (const change of [ value => value.parentOrderId='999', value => value.currentRemainderPackageCount=1, value => value.children[2].sourceOrderId='999', value => value.children[1].sourceOrderId='999', value => value.children[2].packageCount=2, value => value.children.push({splitRole:'UNKNOWN',orderId:'999'}), ]) {const value=tree();change(value);assert.equal(validTwoFragmentTree(value,'100','101'),false)} }) test('F40 separates immutable physical task cartons from current actual FBA receiving prefix scans',() => { assert.match(source,/cartonMarks: stableLoadedCartonMarks\(task.items\)/) assert.match(source,/receivingCartonMarks:\[`\$\{current.summary.inboundCode\}#PDA-CONTRACT-1`\]/) assert.doesNotMatch(source,/cartonMarks:\s*\[`\$\{current.summary.inboundCode\}#PDA-CONTRACT/) }) test('raw Order and original status history remain in evidence including operator, reason and timestamp',() => { const detail={order:{id:'100',orderRole:'MASTER',version:3,status:'TRANSPORTING'},statusHistory:[ {id:'11',orderId:'100',action:'OVERSEAS_DELIVERED',operatorName:'OVERSEAS_DELIVERY_EVENT', reason:'signed actual delivery',occurredAt:'2026-09-30T01:00:00',fromStatus:'TRANSPORTING',toStatus:'TRANSPORTING'}, ]} const snapshot=fulfillmentHistorySnapshot(detail) assert.deepEqual(snapshot.rawOrder,detail.order) assert.deepEqual(snapshot.histories,detail.statusHistory) assert.deepEqual(completionCounts(snapshot),{own:1,final:0}) }) test('root shipment signed first preserves unfinished root while effective child remains pending',() => { const snapshot=signed();snapshot.root.status='TRANSPORTING' snapshot.root.histories=history('OVERSEAS_DELIVERED');snapshot.child={status:'TRANSPORTING',histories:[]} snapshot.rootInbound.orderStatusSnapshot='TRANSPORTING' assert.equal(validSignatureGate(snapshot,'MASTER'),true) snapshot.root.status='COMPLETED' assert.equal(validSignatureGate(snapshot,'MASTER'),false) }) test('child signed before root remains an independent completed child and cannot finish unsigned root',() => { const snapshot=signed();snapshot.root={status:'TRANSPORTING',histories:[]} snapshot.rootInbound={processStatus:'IN_TRANSIT',orderStatusSnapshot:'TRANSPORTING'} assert.equal(validSignatureGate(snapshot,'CHILD'),true) assert.equal(validSignatureGate(snapshot,'MASTER'),false) snapshot.root.histories=history('OVERSEAS_DELIVERED') assert.equal(validSignatureGate(snapshot,'CHILD'),false) }) test('all signed requires root own fact, exactly one aggregate final history and real Firstleg delivered completion',() => { assert.equal(validSignatureGate(signed(),'MASTER',true),true) for(const change of [ value => value.root.histories=history('FULFILLMENT_COMPLETED'), value => value.root.histories.push({action:'FULFILLMENT_COMPLETED'}), value => value.child.histories.push({action:'OVERSEAS_DELIVERED'}), value => value.child.status='CANCELLED', value => value.rootInbound.orderStatusSnapshot='TRANSPORTING', value => value.rootInbound.processStatus='RECEIVED', ]) {const value=signed();change(value);assert.equal(validSignatureGate(value,'MASTER',true),false)} }) test('Outbox requires exact customer/root/source aggregate membership, unique completion and PUBLISHED',() => { assert.equal(exactCompletionOutboxProof(outbox(),'90','100',['101','100']),true) for(const change of [ value => value.readOnly=false, value => value.customerId='91', value => value.rootOrderId='999', value => value.orders[0].rootOrderId='999', value => value.orders[0].customerId='91', value => value.orders[1].orderId='100', value => value.orders[0].count=2, value => value.orders[1].publishedCount=0, value => value.orders[1].pendingCount=1, value => value.orders[0].failedCount=1, value => value.orders[0].eventType='OVERSEAS_DELIVERED', value => value.orders.pop(), ]) {const value=outbox();change(value);assert.equal(exactCompletionOutboxProof(value,'90','100',['100','101']),false)} }) test('exported fragment producer preserves fail closed supplier precondition and never writes without actual source master',async() => { const context=fixture(),calls=[] context.request=async(method,path) => {calls.push([method,path]);return {http:200,body:{code:200,data:{records:[]}}}} assert.equal(await loadOneFragment(context,{sourceOrderNo:'offline-only'}),null) assert.equal(calls.length,1) assert.equal(calls[0][0],'GET') assert.match(calls[0][1],/category=BOOKING&status=ACTIVE/) }) test('exported pallet label helper preserves FBA eligibility without introducing writes for other destinations',async() => { const context=fixture();context.request=async() => {throw new Error('unexpected HTTP')} assert.equal(await verifyPalletLabels(context,{destinationType:'OVERSEAS'},'1'),null) assert.equal(await verifyPalletLabels(context,{destinationType:'FBA',fulfillmentType:'ONE_CLICK_DROPSHIP'},'1'),null) }) test('exported consumer polling and conversion fail closed when real producer consumption is absent',async() => { const context=fixture(),calls=[] context.request=async(method,path) => {calls.push([method,path]);return {http:200,body:{code:200,data:{records:[]}}}} assert.equal(await awaitProducerConsumption(context,[]),true) assert.equal(await convertReceivingContainers(context,[{containerNo:'OFFLINE'}]),false) assert.equal(calls.every(([method]) => method==='GET'),true) assert.equal(context.steps.at(-1).passed,false) }) test('exported receiving rejects unmatched current producer instead of borrowing any history container',async() => { const context=fixture();context.request=async(_method,path) => ({http:200,body:{code:200,data: path.endsWith('/candidates')?[{containerNo:'ANOTHER',sourceContainerBookingId:'999',totalPackages:1}]:null}}) await runReceiving(context,'offline-pda',null,null,{containerNo:'EXPECTED',containerBookingId:'100'},false) assert.equal(context.steps.some(step => step.passed === false),true) }) test('exported receiving warehouse resolver continues to choose only configured active official warehouse',async() => { const context=fixture();context.request=async() => ({http:200,body:{code:200,data:{records:[ {id:'193000000000200003',warehouseType:'OVERSEAS',status:'ACTIVE',warehouseName:'offline'}, ]}}}) assert.deepEqual(await resolveSharedWarehouse(context),{id:'193000000000200003',name:'offline'}) }) test('complete orchestrator calls actual source chain and blocks missing Outbox evidence; no fake callback, SQL or cancellation substitute',() => { assert.equal(typeof run,'function') for(const name of ['orders','inbound-measurement','phase3-customs','phase3-outbound-dispatch', 'phase3-carrier-schedule-queries'])assert.ok(source.includes(`'${name}'`)) for(const name of ['loadOneFragment','verifyPalletLabels','awaitProducerConsumption', 'convertReceivingContainers','prepareTerminalDrayage','runReceiving','pickAll','saveReceiptAndComplete']) assert.match(source,new RegExp(`await ${name}\\(`)) assert.match(source,/rootOrderId, sourceOrderIds:\[rootOrderId,childOrderId\]/) assert.match(source,/HTTP_VERIFIED_OUTBOX_PENDING/) assert.match(source,/finally \{ proof.currentStage = 'PDA_IDENTITY_CLEANUP'; await disablePicker/) assert.doesNotMatch(source,/['"`]\/internal\/|UPDATE\s+ord_|INSERT\s+INTO|\/cancel|\/complete-delivery/) }) test('early F40 failures become FAILED with only a safe stage and preserve the original exception',async() => { const context=fixture();context.context={};context.options={} await assert.rejects(run(context),/F40 本轮客户完整凭据有效/) assert.equal(context.createdResources.phase5RootFulfillment.finalStatus,'FAILED') assert.equal(context.createdResources.phase5RootFulfillment.failedStage,'CUSTOMER_IDENTITY') assert.equal('error' in context.createdResources.phase5RootFulfillment,false) const secretError=new Error('offline-secret-body-not-recorded') const withLogin=fixture();withLogin.context={};withLogin.options={merchantUsername:'offline',merchantPassword:'offline'} withLogin.request=async()=>{throw secretError} await assert.rejects(run(withLogin),error=>error === secretError) assert.equal(withLogin.createdResources.phase5RootFulfillment.finalStatus,'FAILED') assert.equal(JSON.stringify(withLogin.createdResources.phase5RootFulfillment).includes(secretError.message),false) })