优化
This commit is contained in:
@@ -1,119 +1,291 @@
|
||||
import fs from 'node:fs'
|
||||
import {createHash} from 'node:crypto'
|
||||
import {resolve} from 'node:path'
|
||||
import {pathToFileURL} from 'node:url'
|
||||
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'
|
||||
import {parseCrossCustomerArguments,runCrossCustomer} from './fleet-cross-customer-test-env.mjs'
|
||||
import {controlledPalletMeasurements} from './admin-test-env-modules/fleet-trip-fulfillment.mjs'
|
||||
import {fixtureContract} from './admin-test-env-modules/fleet-cross-customer-acceptance.mjs'
|
||||
import {version} from './admin-test-env-modules/grouped-dispatch-acceptance.mjs'
|
||||
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'
|
||||
const id=v=>String(v??''),demand=(value,message)=>{if(!value)throw Error(message)}
|
||||
const sorted=v=>Array.isArray(v)?v.map(sorted):v&&typeof v==='object'?Object.fromEntries(Object.keys(v).sort().map(k=>[k,sorted(v[k])])):v
|
||||
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
|
||||
const same=(a,b)=>JSON.stringify(sorted(a))===JSON.stringify(sorted(b))
|
||||
const cents=v=>{demand(/^\d+(?:\.\d{1,2})?$/.test(id(v)),'INVALID_MONEY');const [a,b='']=id(v).split('.');return BigInt(a)*100n+BigInt(b.padEnd(2,'0'))}
|
||||
const cents=value=>{const text=String(value);demand(/^\d+(?:\.\d{1,2})?$/.test(text),'INVALID_MONEY');const [whole,fraction='']=text.split('.');return BigInt(whole)*100n+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}
|
||||
}
|
||||
|
||||
export function assertSameRouteBasis(departure,shares) {
|
||||
const load=departure?.snapshot?.confirmedLoad,stops=departure?.snapshot?.trip?.stops
|
||||
demand(departure?.action==='DEPART'&&load?.manifestHash,'ACTUAL_DEPART_HISTORY_REQUIRED')
|
||||
demand(shares?.length===3&&shares.filter(x=>x.sourceType==='OWN').length===2&&shares.filter(x=>x.sourceType==='EXTERNAL').length===1,'THREE_EXACT_COST_SOURCES_REQUIRED')
|
||||
demand(new Set(shares.map(x=>x.businessNo)).size===3&&new Set(shares.map(x=>x.dispatchNo)).size===3&&shares.every(x=>x.palletSpaces===1&&x.warehousePalletIds?.length===1),'THREE_INDEPENDENT_STANDARD_PALLETS_REQUIRED')
|
||||
const ids=shares.flatMap(x=>x.warehousePalletIds).map(id)
|
||||
demand(new Set(ids).size===3&&load?.pallets?.length===3&&same([...ids].sort(),load.pallets.map(x=>id(x.warehousePalletId)).sort()),'COMPLETE_DEPART_PALLET_SCOPE_REQUIRED')
|
||||
demand(load.cargo?.length===3&&new Set(load.pallets.map(x=>x.deliveryIndex)).size===1&&load.pallets.every(x=>x.deliveryIndex>0&&stops?.[x.deliveryIndex]?.destinationKey),'SINGLE_REAL_UNLOADING_STOP_REQUIRED')
|
||||
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')
|
||||
for(const share of shares){
|
||||
const pallet=load.pallets.find(x=>id(x.warehousePalletId)===id(share.warehousePalletIds[0])),cargo=load.cargo.filter(x=>id(x.warehousePalletId)===id(pallet.warehousePalletId))
|
||||
demand(Number(pallet.palletSpaces)===1&&cargo.length===1&&cargo[0].dispatchNo===share.dispatchNo&&id(cargo[0].customerId)===share.customerId&&Number(cargo[0].packages)===1&&cargo[0].destinationKey===stops[pallet.deliveryIndex].destinationKey,'SOURCE_AND_DESTINATION_MISMATCH')
|
||||
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')
|
||||
}
|
||||
}
|
||||
const externals=(departure.snapshot.externalBookings||[]).filter(x=>!['DRAFT','CANCELLED'].includes(x.status)),external=shares.find(x=>x.sourceType==='EXTERNAL'),booking=externals[0]
|
||||
demand(externals.length===1&&booking?.status==='BOUND'&&booking.bookingNo===external.businessNo&&booking.dispatchNo===external.dispatchNo&&id(booking.customerId)===external.customerId&&Number(booking.receipt?.source?.receivedPackages)===1&&booking.receipt.source.pallets?.length===1&&Number(booking.receipt.source.pallets[0].packages)===1&&id(booking.receipt.source.pallets[0].warehousePalletId)===id(external.warehousePalletIds[0]),'ACTUAL_EXTERNAL_RECEIPT_REQUIRED')
|
||||
demand(shares.filter(x=>x.sourceType==='OWN').every(x=>x.businessNo===x.dispatchNo),'OWN_DISPATCH_IDENTITY_REQUIRED')
|
||||
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')
|
||||
return load
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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')
|
||||
const total=summary.totals[0],expected=expectedAllocations(amount,shares),actual=[...(total.allocations||[])].sort((a,b)=>a.businessNo.localeCompare(b.businessNo)).map(x=>({businessNo:x.businessNo,sourceType:x.sourceType,dispatchNo:x.dispatchNo,palletSpaces:Number(x.palletSpaces),cents:String(cents(x.amount))}))
|
||||
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))}))
|
||||
demand(cents(total.directCost)===cents(amount)&&same(actual,expected),'EXACT_LARGEST_REMAINDER_ALLOCATION_REQUIRED')
|
||||
demand(cents(total.ownCost)===expected.filter(x=>x.sourceType==='OWN').reduce((n,x)=>n+BigInt(x.cents),0n)&¢s(total.externalCost)===expected.filter(x=>x.sourceType==='EXTERNAL').reduce((n,x)=>n+BigInt(x.cents),0n)&¢s(total.ownCost)+cents(total.externalCost)===cents(amount),'OWN_EXTERNAL_CENT_CONSERVATION_REQUIRED')
|
||||
demand(cents(total.ownCost)===expected.filter(s=>s.sourceType==='OWN').reduce((sum,s)=>sum+BigInt(s.cents),0n)&¢s(total.externalCost)===expected.filter(s=>s.sourceType==='EXTERNAL').reduce((sum,s)=>sum+BigInt(s.cents),0n)&¢s(total.ownCost)+cents(total.externalCost)===cents(amount),'OWN_EXTERNAL_CENT_CONSERVATION_REQUIRED')
|
||||
return expected
|
||||
}
|
||||
|
||||
// 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)}
|
||||
}
|
||||
|
||||
export async function verifySameRouteCost(context,fixture,{execute=false,readInventory}={}) {
|
||||
if(!execute)return {scope:'SAME_ROUTE_COST_WITH_TWO_OWN_AND_ONE_EXTERNAL',businessSqlWrites:false}
|
||||
demand(context?.marker&&context.marker===fixture?.marker&&fixture?.pdaToken&&fixture?.members?.length===2
|
||||
&&context.createdResources?.fleetTrips?.some(x=>x.tripNo===fixture.tripNo)&&typeof readInventory==='function','CURRENT_TWO_CUSTOMER_FIXTURE_REQUIRED')
|
||||
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')
|
||||
demand(!context.createdResources.fleetSameRouteCost,'SAME_ROUTE_VERIFICATION_ALREADY_STARTED')
|
||||
const proof=context.createdResources.fleetSameRouteCost={status:'CHECKING',tripNo:fixture.tripNo,marker:context.marker,scope:'SAME_ROUTE_COST_WITH_TWO_OWN_AND_ONE_EXTERNAL',snapshots:{},requests:[]}
|
||||
const check=(name,condition)=>{context.assert(MODULE,name,null,Boolean(condition),'',{scenario:MODULE,deploymentBlocker:true});demand(condition,name)}
|
||||
const request=async(method,path,body,token=context.token)=>{const r=await context.request(method,path,body,token);proof.requests.push({method,path,http:r.http,code:r.body?.code,requestId:r.requestId,traceId:r.traceId});check(`${method} ${path}`,r.http===200&&id(r.body?.code)==='200'&&r.requestId&&r.traceId);return r.body.data}
|
||||
const trip=context.createdResources.fleetTrips.find(x=>x.tripNo===fixture.tripNo),base=`${ROOT}/fleet/trips/${fixture.tripNo}`,key=suffix=>`${context.marker}-SAME-${suffix}`
|
||||
const inventory=async label=>{const rows=[];for(const customerId of [...new Set(fixture.members.map(x=>x.customerId))])rows.push(await readInventory({marker:context.marker,customerId,warehouseId:fixture.warehouseId}));proof.snapshots[label]=rows;return rows}
|
||||
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
|
||||
}
|
||||
try{
|
||||
let detail=await request('GET',base),plan=await request('GET',`${base}/capacity-plan`)
|
||||
check('Two owned sources have one real FBA unloading destination',plan.cargo?.length===2&&new Set(plan.cargo.map(x=>x.destinationKey)).size===1&&plan.cargo.every(x=>x.destinationKey?.startsWith('FBA:')))
|
||||
await request('POST',`${base}/capacity-plan`,{recordVersion:plan.recordVersion,manifestHash:plan.manifestHash,pallets:controlledPalletMeasurements(plan.cargo,detail.trip.stops),reason:context.marker})
|
||||
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)
|
||||
await verifyFleetExternalReceipt(context,MODULE,trip,fixture.pdaToken)
|
||||
await verifyFleetExternalDispatch(context,MODULE,trip)
|
||||
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})
|
||||
const receipt=trip.externalReceipt,external=trip.externalDispatch
|
||||
const members=proof.members=[...fixture.members,{customerId:external.customerId,dispatchNo:external.dispatchNo,outboundNo:external.outboundNo,deliveryNo:external.deliveryNo,palletId:receipt.warehousePalletId,palletNo:receipt.palletNo,positionId:id(receipt.finalInventory.positions[0].id)}]
|
||||
check('Only three distinct current-run dispatches and pallets',new Set(members.map(x=>x.dispatchNo)).size===3&&new Set(members.map(x=>x.palletId)).size===3)
|
||||
for(const[index,m]of members.entries()){
|
||||
const task=await request('GET',`${PDA}/${m.dispatchNo}`,undefined,fixture.pdaToken),item=task.items?.[0]
|
||||
check('PDA item is the original one-box pallet and source position',task.tripNo===fixture.tripNo&&task.items.length===1&&item.palletNo===m.palletNo&&Number(item.scheduledPackages)===1&&Number(item.pickedPackages)===0&&item.positions?.some(x=>id(x.id)===m.positionId&&Number(x.availablePackages)===1))
|
||||
const pick={positionId:m.positionId,packages:1,productQuantity:1,idempotencyKey:key(`PICK-${index}`),remark:context.marker}
|
||||
await request('POST',`${PDA}/${m.dispatchNo}/items/${item.dispatchItemId}/pick`,pick,fixture.pdaToken)
|
||||
await request('POST',`${PDA}/${m.dispatchNo}/complete`,{idempotencyKey:key(`PICK-COMPLETE-${index}`)},fixture.pdaToken)
|
||||
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)
|
||||
}
|
||||
const stock=await inventory('PICKED'),positions=stock.flatMap(x=>x.positions)
|
||||
check('All three original physical positions remain with zero available stock',positions.length===3&&members.every(m=>positions.some(x=>id(x.id)===m.positionId&&Number(x.availablePackages)===0)))
|
||||
const loading=await request('GET',`${base}/loading`);detail=await request('GET',base)
|
||||
check('Three real pallets ready for loading',!loading.blockReason&&loading.cargo.length===3)
|
||||
const measured=await request('POST',`${base}/loading`,{recordVersion:loading.recordVersion,manifestHash:loading.manifestHash,pallets:controlledPalletMeasurements(loading.cargo,detail.trip.stops),reason:context.marker})
|
||||
const approved=await request('POST',`${base}/loading-review`,{recordVersion:measured.recordVersion,decision:'APPROVED'})
|
||||
const depart={recordVersion:approved.trip.recordVersion,idempotencyKey:key('DEPART'),remark:context.marker},departPath=`${PDA}/${members[0].dispatchNo}/depart`
|
||||
proof.departure=await request('POST',departPath,depart,fixture.pdaToken)
|
||||
check('Shared actual departure contains all three customer executions',proof.departure.tripNo===fixture.tripNo&&proof.departure.status==='IN_TRANSIT'&&Number(proof.departure.shippedPackages)===3&&same(proof.departure.dispatches.map(x=>x.dispatchNo).sort(),members.map(x=>x.dispatchNo).sort()))
|
||||
const departedTrip=proof.departedTrip=await request('GET',base),replay=await request('POST',departPath,depart,fixture.pdaToken)
|
||||
check('Departure replay is explicit and does not change complete trip or stock',replay.replayed===true&&same(departedTrip,await request('GET',base))&&same(stock,await inventory('DEPARTED')))
|
||||
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'&¤t.detail.stage==='AFTER_LOADING'&¤t.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&¤t.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')))
|
||||
const history=await request('GET',`${base}/history?page=1&size=200`)
|
||||
check('Complete trip history contains one actual departure',Number(history.total)===history.records.length&&history.records.filter(x=>x.action==='DEPART').length===1)
|
||||
const departure=proof.departureHistory=history.records.find(x=>x.action==='DEPART')
|
||||
const shares=proof.shares=members.map((m,i)=>({businessNo:i===2?receipt.bookingNo:m.dispatchNo,sourceType:i===2?'EXTERNAL':'OWN',dispatchNo:m.dispatchNo,customerId:m.customerId,palletSpaces:1,warehousePalletIds:[m.palletId]}))
|
||||
assertSameRouteBasis(departure,shares)
|
||||
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)
|
||||
const costPath=`${base}/costs`,before=await request('GET',`${costPath}?page=1&size=100`)
|
||||
check('Current trip has no prior cost entries',Number(before.page.total)===0&&before.page.records.length===0&&before.summary.totals.length===0)
|
||||
check('Empty cost query already uses exact original same-route departure',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} same-route synthetic cost`}}
|
||||
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`}}
|
||||
const cost=proof.cost=await request('POST',costPath,proof.costRequest),result=proof.costResult=await request('GET',`${costPath}?page=1&size=100`)
|
||||
check('Exactly one USD cost belongs to original trip',cost.tripNo===fixture.tripNo&&cost.costNo&&Number(cost.recordVersion)===0&&Number(result.page.total)===1&&result.page.records.length===1&&result.page.records[0].costNo===cost.costNo)
|
||||
check('Exactly one original-currency cost was created at legal zero version',cost.tripNo===fixture.tripNo&&cost.costNo&&BigInt(version(cost.recordVersion))===0n&&integer(result.page.total)===1&&result.page.records.length===1&&result.page.records[0].costNo===cost.costNo)
|
||||
proof.expectedAllocations=assertSameRouteCost(result.summary,departure,shares)
|
||||
check('Exact cost command replay returns same persisted cost and unchanged 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}/${cost.costNo}/history?page=1&size=100`)
|
||||
check('Only one immutable cost creation history',Number(costHistory.total)===1&&costHistory.records.length===1&&costHistory.records[0].action==='CREATE'&&costHistory.records[0].snapshot?.cost?.costNo===cost.costNo)
|
||||
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)
|
||||
assertSameRouteCost(costHistory.records[0].snapshot.summary,departure,shares)
|
||||
check('Cost writes preserve exact departure history and customer stock',same(history,await request('GET',`${base}/history?page=1&size=200`))&&same(stock,await inventory('COST_REPLAY')))
|
||||
for(const[index,m]of members.entries()){
|
||||
const path=`${ROOT}/delivery-orders/${m.deliveryNo}`,scope=`?customerId=${m.customerId}`,delivery=await request('GET',path+scope)
|
||||
await request('PUT',`${path}/status${scope}`,{status:'DELIVERING',expectedVersion:delivery.order.version,remark:context.marker})
|
||||
const docs=await request('GET',`${path}/documents${scope}`),upload=await context.requestMultipart('POST',`${path}/documents/RECEIPT/files${scope}`,{name:`${context.marker}-${index}-receipt.txt`,type:'text/plain',content:new TextEncoder().encode(`${context.marker} synthetic receipt ${m.deliveryNo}`)})
|
||||
check('Actual receipt upload belongs to delivery',upload.http===200&&id(upload.body?.code)==='200'&&upload.body.data?.fileId)
|
||||
const documents=(docs.categories||[]).filter(x=>x.category!=='RECEIPT').map(x=>({category:x.category,fileIds:(x.files||[]).map(f=>f.fileId)}));documents.push({category:'RECEIPT',fileIds:[id(upload.body.data.fileId)]})
|
||||
await request('PUT',`${path}/documents${scope}`,{expectedVersion:docs.version,idempotencyKey:key(`SIGN-${index}`),bolNo:docs.bolNo||null,documents})
|
||||
check('This actual delivery completed with saved receipt',(await request('GET',path+scope)).order.status==='DELIVERED')
|
||||
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()
|
||||
}
|
||||
const completed=await request('GET',path)
|
||||
check('All normal signatures aggregate current native main completion',completed.status==='ACTIVE'&&completed.stage==='DELIVERED')
|
||||
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`)))
|
||||
proof.status='VERIFIED';return proof
|
||||
}catch(error){proof.status='FAILED';proof.error=error.message;throw error}
|
||||
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}
|
||||
}
|
||||
|
||||
export async function runSameRouteCost(config,{env=process.env,...dependencies}={}) {
|
||||
if(!config.execute)return {...config,scope:'TWO_FRESH_OWN_RECEIPTS_PLUS_ONE_EXTERNAL_SAME_ROUTE',cost:'USD 1.00, three independently proven pallet sources, largest remainder by business number',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-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(path)).digest('hex')}))
|
||||
return runCrossCustomer(config,{...dependencies,env,verify:async(context,fixture,options)=>{
|
||||
fs.writeFileSync(resolve('reports',`fleet-cross-${config.runId}`,'same-route-source.json'),JSON.stringify({scope:'SAME_ROUTE_COST_WITH_TWO_OWN_AND_ONE_EXTERNAL',sources},null,2),{flag:'wx'})
|
||||
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'})
|
||||
return verifySameRouteCost(context,fixture,options)
|
||||
}})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user