import test from 'node:test' import { relabelOutboundMarksMatch, inventoryQuantitySnapshot, inventorySnapshot, verifyPartialOrderCompletion, completeReturnedException, verifyCustomerSignedDocuments, createSignedDocumentIsolationCustomer } from './phase5-overseas-fulfillment.mjs' import assert from 'node:assert/strict' import { readFile } from 'node:fs/promises' 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') 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) } }) test('phase-five module covers dispatch edit, transfer, PDA pick/depart and delivery state', () => { for (const token of [ "const DISPATCH_BASE = '/api/platform/v1/last-leg/dispatches'", "const PDA_DISPATCH_BASE = '/api/pda/v1/last-leg/dispatches'", 'query(MERCHANT_DELIVERY_BASE, { dispatchNo })', '/items/${encodeURIComponent(id(item.dispatchItemId))}/pick', '/complete`', '/depart`', '/outbound-orders/${encodeURIComponent(outboundNo)}', '/delivery-orders/${encodeURIComponent(currentNo)}/status', ]) assert.ok(source.includes(token), token) assert.match(source, /WAIT_OUTBOUND/) assert.match(source, /WAIT_DELIVERY/) assert.match(source, /READY_TO_DEPART/) assert.match(source, /OUTBOUNDED/) assert.match(source, /DELIVERING/) assert.match(source, /expectedVersion: deliveryVersion/) assert.match(source, /transferDeliveries\(transferred\.data\)/) assert.match(source, /new Set\(destinationKeys\)\.size === deliveries\.length/) assert.match(source, /deliveries\.reduce\(\(sum, value\) => sum \+ Number\(value\?\.packageCount \|\| 0\), 0\)/) }) test('phase-five module proves the client delivery create, list and nested detail contract', () => { assert.match(source, /const MERCHANT_DELIVERY_BASE = '\/api\/merchant\/v1\/last-leg\/delivery-orders'/) assert.match(source, /loginMerchant\(context, customerId\)/) assert.match(source, /context\.options\?\.merchantUsername/) assert.match(source, /\/api\/merchant\/v1\/iam\/tenant\/profile/) assert.match(source, /id\(profile\?\.id\) === customerId/) assert.match(source, /客户创建派送并原子转出库单/) assert.match(source, /deliveryMethod: 'TRUCK_PALLET'/) assert.match(source, /fees: \[\{ feeType: 'DELIVERY_FEE', feeName: '派送费', direction: 'RECEIVABLE',\s*currency: 'USD', amount: 10/) assert.match(source, /客户分页回查自身派送单/) assert.match(source, /客户读取自身派送详情/) 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/) }) test('phase-five module proves receipt-save completion, cross-region convergence, customer visit, exception and return', () => { for (const token of [ '/documents/RECEIPT/files', 'requestMultipart', "category: 'RECEIPT'", 'SAVE-RECEIPT', 'RECEIPT_AUTO_COMPLETE', '/customer-visits/${encodeURIComponent(visitId)}', "visitResult: 'SATISFIED'", '/exception-orders', '/return-inbound-options', '/mark-return', "returnDirection: 'OVERSEAS_WAREHOUSE'", 'returnSources', 'outboundPalletItemId', 'inventoryPositionId', 'value.returnSources.some', 'returnInbound?.deliveryNo === deliveryNo', "idempotencyKey: key(context, 'DELIVERY-RETURN')", '派送退回同键同载荷重放', 'RETURN_PENDING_WITH_COMPLETED_VISIT', ]) assert.ok(source.includes(token), token) 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'/) assert.match(source, /\/api\/platform\/v1\/orders\/\$\{encodeURIComponent\(sourceOrderId\)\}/) assert.match(source, /mainStatus === 'COMPLETED'/) assert.doesNotMatch(source, /platform\(context, 'POST', '确认派送完成/) 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/) assert.doesNotMatch(source, /8\.163\.|password\s*:\s*['"`]/) }) test('phase-five writes carry idempotency and record deployment blockers instead of passing empty fixtures', () => { assert.match(source, /idempotencyKey: key\(context, 'TRANSFER'\)/) assert.match(source, /idempotencyKey: key\(context, 'DISPATCH-PICK'/) assert.match(source, /idempotencyKey: key\(context, 'DISPATCH-COMPLETE'\)/) assert.match(source, /idempotencyKey: key\(context, 'DISPATCH-DEPART'\)/) assert.match(source, /addCoverageGap\(MODULE, SCENARIO/) assert.match(source, /deploymentBlocker: true/) }) 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/) }) test('manual exception retries only a transport failure with the identical business body', () => { assert.match(source, /manualException\.response\.http === 0/) assert.match(source, /人工异常连接失败后使用同载荷重试/) assert.match(source, /manualExceptionBody/) }) 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 } }) 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) => { if (path.includes('/inventory/balances/1/positions')) return ok(path.includes('palletNo=') ? (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 }] : []) : [{ id: 'OLD', balanceId: '1', customerId: '100', overseasWarehouseId: 'WH-1', inboundCode: 'IN-A', 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 }] : [])]) if (path.includes('/inventory/balances')) return ok({ total: 1, records: [{ id: '1', customerId: '100', overseasWarehouseId: 'WH-1', totalPackages: completed ? 9 : 8, availablePackages: completed ? 9 : 8, holdPackages: 0, allocatedPackages: 0, pickedPackages: 0, receivingPackages: 0, inTransitPackages: 0, procurementPackages: 0 }] }) 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 }) } if (path.includes('/delivery-orders/')) return ok({ order: { status: 'RETURNED', outboundNo: 'OB-1' } }) return ok({ order: { status: completed ? 'COMPLETED' : initialStatus, exceptionType: 'RETURN', outboundNo: 'OB-1', inboundCode: 'IN-A', deliveryNo: 'DEL-1', version, evidenceFileIds: ['91'] }, returnSources: [source] }) }) context.requestMultipart = async () => { uploads += 1; return ok({ fileId: '91' }) } context.createdResources.phase5OverseasFulfillment = { marker: context.marker, returnExceptionNo: 'EX-1', outboundNo: 'OB-1' } 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 }] })) context.createdResources.phase5OverseasFulfillment = { marker: context.marker, returnExceptionNo: 'EX-1', outboundNo: 'OB-1' } 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) => { if (path.includes('/inventory/')) return ok({ records: [], total: 0 }) 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 }] }) }) context.createdResources.phase5OverseasFulfillment = { marker: context.marker, returnExceptionNo: 'EX-1', outboundNo: 'OB-1' } 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) assert.equal(context.calls.filter(call => call.path.includes('/inventory/balances')).length, 2) 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) }) 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) : ok({ records: [fixture.balance], total: 1 })) } test('inventory evidence resolves missing Balance inboundCode through exact positions and retains an independent shared balance', async () => { const fixture = inventoryFixture() const context = inventoryContext(fixture) const snapshot = await inventorySnapshot(context, '100', 'WH-1', ['IN-A', 'IN-A', 'IN-B'], 'stock') 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 assert.deepEqual(await inventorySnapshot(inventoryContext(childOnly), '100', 'WH-1', ['IN-A'], 'stock'), []) }) 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) assert.equal(await inventorySnapshot(context, '100', 'WH-1', ['IN-A'], 'stock'), null) 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() const original = await inventorySnapshot(inventoryContext(fixture), '100', 'WH-1', ['IN-A'], 'stock') for (const field of ['inTransitPackages', 'procurementPackages']) { const changed = inventoryFixture(); changed.balance[field] += 1 assert.notDeepEqual(await inventorySnapshot(inventoryContext(changed), '100', 'WH-1', ['IN-A'], 'stock'), original) } for (const field of ['palletId', 'palletNo', 'batchNo', 'warehouseLocationId', 'warehouseLocationCode', 'inboundOrderId']) { const changed = inventoryFixture(); changed.positions[2][field] = 'DIFFERENT' assert.notDeepEqual(await inventorySnapshot(inventoryContext(changed), '100', 'WH-1', ['IN-A'], 'stock'), original) } for (const field of ['holdPackages', 'allocatedPackages', 'pickedPackages', 'receivingPackages']) { const changed = inventoryFixture(); changed.positions[2][field] += 1; changed.balance[field] += 1 assert.notDeepEqual(await inventorySnapshot(inventoryContext(changed), '100', 'WH-1', ['IN-A'], 'stock'), original) } })