test: extend eight-business acceptance flows and offline contracts

This commit is contained in:
2026-10-22 15:41:50 +08:00
parent 86889d7e0e
commit 080ca600e6
33 changed files with 1285 additions and 101 deletions
@@ -1,7 +1,7 @@
import test from 'node:test'
import { relabelOutboundMarksMatch, inventoryQuantitySnapshot, inventorySnapshot, dispatchInventorySources, inventorySourcesPresent, dispatchStockConservation, verifyAutomaticDeparture, verifyPartialOrderCompletion, verifyFulfillmentRootStatus,
createDeliveryReturn, completeReturnedException, returnedExceptionFactsMatch, verifyCustomerSignedDocuments, createSignedDocumentIsolationCustomer,
dispatchDestinationConservation, pickAll, readAutomaticDispatchDelivery, fulfillmentEvidenceContext } from './phase5-overseas-fulfillment.mjs'
dispatchDestinationConservation, pickAll, readAutomaticDispatchDelivery, fulfillmentEvidenceContext, verifyRelabelDispatchOutbound, verifyClientRelabelSettlement } from './phase5-overseas-fulfillment.mjs'
import assert from 'node:assert/strict'
import { readFile, mkdtemp, rm } from 'node:fs/promises'
import { tmpdir } from 'node:os'
@@ -10,6 +10,80 @@ 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')
for (const fault of ['', 'foreign customer', 'old marks', 'sign failure', 'resource held', 'settlement failed']) {
test(`client original relabel delivery includes receipt and resource release: ${fault || 'normal'}`, async () => {
const relabel = { marker: 'batch', relabelNo: 'RL-CLIENT', dispatchNo: 'DP-CLIENT', warehouseId: '42', customerId: '101',
sourceCartonMarks: ['OLD'], relabelCartonMarks: ['NEW'] }
const calls = []
const context = { marker: 'batch', createdResources: { phase4OverseasClientServices: { relabelFulfillment: relabel } },
checkpoint: async () => {}, assert(_m, name, _r, ok) { assert.ok(ok, name) },
apiSuccess(_m, _name, response) { return response.body.data },
async request(method, path) {
calls.push('outbound')
assert.equal(method, 'GET'); assert.ok(path.endsWith('/outbound-orders/OUT-1'))
return { http: 200, body: { code: '200', data: { outbound: { outboundNo: 'OUT-1', dispatchNo: 'DP-CLIENT', customerId: '101',
status: 'OUTBOUNDED', packageCount: 1 }, pallets: [{ cartonMarks: fault === 'old marks' ? 'OLD' : 'NEW' }] } } }
} }
const helpers = {
async prepare(_c, _m, dispatch, warehouse) { calls.push('prepare'); assert.equal(dispatch, relabel.dispatchNo); assert.equal(warehouse, '42'); return { tripNo: 'TR-1' } },
async pick() { calls.push('pick'); return true }, async load() { calls.push('load') },
async read() { calls.push('read'); return { outbounds: [{ customerId: '101', outboundNo: 'OUT-1' }],
deliveries: [{ customerId: fault === 'foreign customer' ? '102' : '101', outboundNo: 'OUT-1', deliveryNo: 'DE-1', packageCount: 1 }] } },
async sign() { calls.push('sign'); return { order: { status: fault === 'sign failure' ? 'DELIVERING' : 'DELIVERED',
deliveryNo: 'DE-1', customerId: '101', outboundNo: 'OUT-1' } } },
async finish() { calls.push('finish'); return { status: fault === 'resource held' ? 'CHECKING' : 'CARGO_COMPLETED_AND_RESOURCES_RELEASED' } },
async settle() { calls.push('settle'); return { status: fault === 'settlement failed' ? 'FAILED' : 'SETTLED_HTTP_VERIFIED' } },
}
if (fault) {
await assert.rejects(verifyRelabelDispatchOutbound(context, relabel, 'pda', '42', helpers))
assert.equal(relabel.deliveryExecution.status, 'FAILED')
if (['foreign customer', 'old marks'].includes(fault)) assert.equal(calls.includes('sign'), false)
if (fault === 'sign failure') assert.equal(calls.includes('finish'), false)
} else {
await verifyRelabelDispatchOutbound(context, relabel, 'pda', '42', helpers)
assert.equal(relabel.deliveryExecution.status, 'DELIVERED_HTTP_VERIFIED')
assert.deepEqual(calls, ['prepare', 'pick', 'load', 'read', 'outbound', 'sign', 'finish', 'settle'])
}
const count = calls.length
await assert.rejects(verifyRelabelDispatchOutbound(context, relabel, 'pda', '42', helpers))
assert.equal(calls.length, count)
})
}
for (const fault of ['', 'foreign order', 'wrong amount', 'pending', 'rejected']) {
test(`原贴标结算只读回查: ${fault || 'settled'}`, async () => {
const relabel = { marker: 'batch', relabelNo: 'RL-1', sourceOrderNo: 'WC-1', customerId: '101', warehouseId: '42', outboundNo: 'OUT-1',
deliveryExecution: { closure: { status: 'CARGO_COMPLETED_AND_RESOURCES_RELEASED' } } }
let calls = 0
const context = { marker: 'batch', context: { merchantQualificationFixture: { tenantId: '101' } },
createdResources: { phase4OverseasClientServices: { relabelFulfillment: relabel } }, checkpoint: async () => {}, assert() {},
apiSuccess(_m, _n, response) { return response.body.data },
async request(method, path) {
assert.equal(method, 'GET'); assert.ok(path.endsWith('/relabel-applications/RL-1')); calls++
return { http: 200, body: { code: '200', data: { application: { relabelNo: 'RL-1',
customerOrderNo: fault === 'foreign order' ? 'OTHER' : 'WC-1', overseasWarehouseId: '42',
chargeAmount: fault === 'wrong amount' ? 1 : 0.01, chargeCurrency: 'USD', customerConfirmedAt: '2026-10-22T01:00:00',
walletStatus: fault === 'pending' ? 'SETTLE_PENDING' : fault === 'rejected' ? 'SETTLE_FAILED' : calls === 1 ? 'SETTLE_PENDING' : 'SETTLED' } } } }
} }
if (fault) {
await assert.rejects(verifyClientRelabelSettlement(context, relabel, async () => {}))
assert.equal(relabel.settlement.status, 'FAILED')
assert.equal(calls, fault === 'pending' ? 31 : 1)
} else {
await verifyClientRelabelSettlement(context, relabel, async () => {})
assert.equal(relabel.settlement.status, 'SETTLED_HTTP_VERIFIED'); assert.equal(calls, 2)
}
})
}
test('relabel fleets run after main resource release and retain both original proofs in checkpoints', () => {
const start = source.indexOf('export async function run(context)')
const run = source.slice(start)
assert.ok(run.indexOf('await finishRelabelDeliveries(') > run.indexOf('await finishFleetTrip('))
assert.equal(run.includes('await verifyRelabelDispatchOutbound('), false)
assert.match(source, /clientRelabel: context.createdResources.phase4OverseasClientServices\?\.relabelFulfillment/)
})
const entry = await readFile(fileURLToPath(new URL('../admin-test-env-acceptance.mjs', import.meta.url)), 'utf8')
test('一箱实收从四箱派送退回仅保持RETURN_PENDING,全部实收才RETURNED,缺失收货或来源证据仍拒绝', () => {