test(acceptance): reuse fixed customers and align native fulfillment flows
This commit is contained in:
@@ -7,6 +7,8 @@ function harness(fault = '', transfer = false) {
|
||||
const proof = { marker: 'RELABEL-TEST', relabelNo: 'TB202610220001', customerId: '101', warehouseId: '201',
|
||||
sourcePositionId: '301', sourcePalletNo: 'SOURCE', sourceOrderNo: 'WC202610220001' }
|
||||
let status = 'PENDING_REVIEW', moved = false, scanned = false, version = 0, taskStatus = 'AVAILABLE'
|
||||
const palletMeasurements = ['SOURCE', 'TARGET'].map((palletCode, index) => ({ palletId: String(500 + index), palletCode,
|
||||
packages: index ? 1 : 2, stockVersion: `CURRENT-${palletCode}`, cartonAggregated: false }))
|
||||
const item = { itemId: '401', expectedPackages: 1, cartonMark: 'BOX-TEST', fbaCartonMark: 'FBA-TEST',
|
||||
operationType: 'CARTON_AND_SKU', skuItems: [{ skuCode: 'SKU', newSkuCode: 'NEW', quantity: 1 }] }
|
||||
const detail = () => ({ application: { relabelNo: proof.relabelNo, customerOrderNo: proof.sourceOrderNo,
|
||||
@@ -35,6 +37,13 @@ function harness(fault = '', transfer = false) {
|
||||
if (fault === 'unknown scan') throw new Error('unknown scan response')
|
||||
scanned = true; if (!repeated) version++; data = task()
|
||||
if (fault === 'scan replay drift' && repeated) data.relabelledPackages = 2
|
||||
} else if (path.endsWith('/relabel-pallet-measurements')) data = structuredClone(palletMeasurements)
|
||||
else if (path.endsWith('/relabel-pallet-measure')) {
|
||||
const row = palletMeasurements.find(value => value.palletCode === body.palletCode)
|
||||
assert.equal(body.stockVersion, row.stockVersion)
|
||||
if (fault !== 'measurement not saved') Object.assign(row, { lengthCm: body.lengthCm, widthCm: body.widthCm,
|
||||
heightCm: body.heightCm, grossWeightKg: body.grossWeightKg, volumeCbm: 0.96 })
|
||||
data = structuredClone(palletMeasurements)
|
||||
} else if (path.endsWith('/relabel-pallet-label')) data = { palletId: '501', palletCode: 'TARGET' }
|
||||
else if (path.endsWith('/pallets/resolve')) {
|
||||
const source = body.code === 'SOURCE'
|
||||
@@ -79,6 +88,23 @@ test('original customer relabel reaches ready for dispatch through real command
|
||||
await assert.rejects(verifyClientRelabelFulfillment(h.context, h.inputs), /不自动重跑/)
|
||||
})
|
||||
|
||||
test('same operator and batch can execute customer and transfer applications without sharing operation keys', async () => {
|
||||
const first = harness(), second = harness('', true)
|
||||
second.inputs.proof.relabelNo = 'TB202610220002'
|
||||
second.inputs.transferProof.relabelNo = second.inputs.proof.relabelNo
|
||||
await verifyClientRelabelFulfillment(first.context, first.inputs)
|
||||
const used = new Map(first.calls.filter(call => call.body?.idempotencyKey).map(call => [call.body.idempotencyKey, call.path]))
|
||||
const request = second.context.request
|
||||
second.context.request = async (method, path, body, token) => {
|
||||
if (body?.idempotencyKey && used.has(body.idempotencyKey) && used.get(body.idempotencyKey) !== path)
|
||||
return { http: 200, body: { code: 'A0404' } }
|
||||
return request(method, path, body, token)
|
||||
}
|
||||
const result = await verifyClientRelabelFulfillment(second.context, second.inputs)
|
||||
assert.equal(result.execution.status, 'HTTP_VERIFIED_READY_FOR_TRANSFER_OUTBOUND')
|
||||
assert.ok(second.calls.filter(call => call.body?.idempotencyKey).every(call => !used.has(call.body.idempotencyKey)))
|
||||
})
|
||||
|
||||
for (const fault of ['wrong customer', 'wrong warehouse', 'no funds', 'unknown scan', 'scan replay drift', 'no source deduction', 'disk']) {
|
||||
test(`relabel stops before completion on ${fault}`, async () => {
|
||||
const h = harness(fault)
|
||||
@@ -109,6 +135,13 @@ test('已有库存转运原关联换标完成后回到原转运新SKU预留', as
|
||||
assert.equal(h.inputs.transferProof.outboundAllocations[0].palletId, '501')
|
||||
})
|
||||
|
||||
test('转运拆合托补测未保存时禁止完工和客户确认', async () => {
|
||||
const h = harness('measurement not saved', true)
|
||||
await assert.rejects(verifyClientRelabelFulfillment(h.context, h.inputs), /补测回执/)
|
||||
assert.equal(h.inputs.proof.execution.status, 'FAILED')
|
||||
assert.equal(h.calls.some(call => call.path.endsWith('/complete') || call.path.endsWith('/confirm-completion')), false)
|
||||
})
|
||||
|
||||
for (const fault of ['wrong fulfillment', 'wrong target']) {
|
||||
test(`转运关联换标拒绝 ${fault}`, async () => {
|
||||
const h = harness(fault, true)
|
||||
|
||||
Reference in New Issue
Block a user