import test from 'node:test' import assert from 'node:assert/strict' import { arrangeLooseboardPool } from './looseboard-pool-dispatch.mjs' function fixture(fault = '') { const tripProof = { tripNo: 'TR-1', dispatchNo: 'DP-1' } const pallet = { warehousePalletId: '72', palletNo: 'P-2', packages: 3 } const receipt = { status: 'RECEIVED_READY_FOR_DISPATCH', incomingNo: 'IN-1', pallets: [pallet], acceptedReceipt: { source: { receiptHash: 'hash', pallets: [{ ...pallet, weightKg: 80, volumeCbm: 1.8 }] } } } const demand = { marker: 'fixture', customerId: '101', receipt, poolBinding: { bookingNo: 'BK-1', tripNo: 'TR-1', createRequest: { cargo: { destinationKey: 'FBA:TEST' } } } } const oldRow = { dispatchItemId: '1', sourceKey: 'OLD', customerId: '101', warehousePalletId: '71', inboundCode: 'OLD', scheduledPackages: 2, pickedPackages: 0 } const newRow = { dispatchItemId: '2', sourceKey: 'NEW', customerId: '101', ...pallet, inboundCode: 'IN-1', scheduledPackages: 3, pickedPackages: 0 } const planPallet = { warehousePalletId: '71', palletSpaces: 1, weightKg: 100, volumeCbm: 1, deliveryIndex: 1 } const booking = { bookingNo: 'BK-1', tripNo: 'TR-1', customerId: '101', incomingNo: 'IN-1', status: 'RECEIVED', recordVersion: 2, receipt: receipt.acceptedReceipt } let stage = 'LOADING', arranged = false, arrangeCalls = 0, returnCalls = 0 const calls = [] const context = { marker: 'fixture', createdResources: { fleetTrips: [tripProof], phase4OverseasBusiness: { looseboard: demand } }, assert(_m, name, _r, ok) { assert.ok(ok, name) }, async checkpoint() {}, async request(method, path, body) { calls.push({ method, path, body }) let data if (path.endsWith('/dispatches/DP-1')) data = { dispatchNo: 'DP-1', status: 'ACTIVE', stage, recordVersion: 1, counts: { pickedPackageCount: fault === 'picked' ? 1 : 0, shippedPackageCount: 0 } } else if (path.endsWith('/items')) { data = { dispatchNo: 'DP-1', items: arranged ? [oldRow, newRow] : [oldRow] } data = structuredClone(data) if (arranged && fault === 'lost original') data.items.shift() if (arranged && fault === 'wrong boxes') data.items[1].scheduledPackages = 4 } else if (path.endsWith('/return-to-review')) { returnCalls += 1; stage = 'BEFORE_LOADING' data = { dispatchNo: 'DP-1', action: 'RETURN_TO_REVIEW', replayed: returnCalls > 1 } } else if (path.endsWith('/capacity-plan')) { data = { planValid: !arranged, recordVersion: 1, manifestHash: 'hash', capacityPlan: { pallets: [planPallet] }, cargo: [{ dispatchNo: 'DP-1' }] } if (method === 'POST') { assert.deepEqual(body.pallets[0], planPallet) assert.deepEqual(body.pallets[1], { warehousePalletId: '72', palletSpaces: 1, weightKg: 80, volumeCbm: 1.8, deliveryIndex: 1 }) data.planValid = true } } else if (path.endsWith('/bookings')) data = { tripRecordVersion: 2, records: [booking] } else if (path.endsWith('/arrange-dispatch')) { arrangeCalls += 1 assert.equal('dispatchNo' in body, false) if (fault === 'network') return { http: 0 } arranged = true data = { tripRecordVersion: 3, booking: { ...booking, status: 'BOUND', dispatchNo: fault === 'wrong main' ? 'OTHER' : 'DP-1' }, replayed: arrangeCalls > 1 } if (fault === 'replay' && arrangeCalls > 1) data.tripRecordVersion += 1 } else if (path.endsWith('/trips/TR-1')) data = { trip: { tripNo: 'TR-1', stops: [{ destinationKey: 'ORIGIN' }, { destinationKey: 'FBA:TEST' }] } } else throw Error(`Unexpected ${method} ${path}`) return { http: 200, body: { code: '200', data: structuredClone(data) }, requestId: 'req', traceId: 'trace' } } } return { context, args: { demand, tripProof }, calls, counts: () => arrangeCalls } } test('original looseboard receipt joins same main preserving existing rows and planning', async () => { const f = fixture() const result = await arrangeLooseboardPool(f.context, f.args) assert.equal(result.status, 'BOUND_AWAITING_REVIEW') assert.equal(f.counts(), 2) await assert.rejects(arrangeLooseboardPool(f.context, f.args)) assert.equal(f.counts(), 2) }) for (const fault of ['picked', 'network', 'wrong main', 'replay', 'lost original', 'wrong boxes']) { test(`join original main rejects ${fault} and preserves evidence`, async () => { const f = fixture(fault) await assert.rejects(arrangeLooseboardPool(f.context, f.args)) assert.equal(f.args.demand.receipt.dispatch.status, 'FAILED') assert.equal(f.calls.some(c => c.method === 'POST' && c.path.endsWith('/capacity-plan')), false) if (fault === 'network') { assert.equal(f.counts(), 1) assert.equal(f.context.createdResources.dispatchWriteBoundary.stopped, true) } }) }