Merge origin/release/test preserving asynchronous order funding and retry coverage

This commit is contained in:
2026-10-30 18:03:37 +08:00
18 changed files with 573 additions and 223 deletions
@@ -261,6 +261,61 @@ test('unchanged create retries reuse the idempotency key', async () => {
} finally { harness.dispose() }
})
test('a lost create response recovers the original order after review releases its budget', async () => {
for (const status of ['RELEASE_PENDING', 'RELEASED', 'RELEASE_FAILED']) {
const budgetCalls = [], createCalls = []
let boundOrder = null
const budgets = moduleFrom(readFileSync(new URL('./api/orderBudgets.ts', import.meta.url), 'utf8'), name => {
assert.equal(name, '@/api/http')
return { apiRequest: async request => {
budgetCalls.push(normalized(request))
return { status, usable: false, orderNo: boundOrder, message: '本次资金预占已释放' }
} }
})
const harness = viewHarness({ createPage: true, api: {
requireOrderBudget: async (...args) => { budgetCalls.push(args); throw new Error('创建订单不应调用旧资金预占接口') },
createProcurement: async payload => {
createCalls.push(normalized(payload))
if (!boundOrder) { boundOrder = 'CG-EXISTING'; throw new ApiError('timeout', 'TIMEOUT') }
assert.equal(payload.idempotencyKey, createCalls[0].idempotencyKey)
return { order: { orderNo: boundOrder, status: 'REJECTED' } }
},
} })
try {
Object.assign(harness.state.form, draft())
await harness.state.submit()
assert.equal(harness.state.submitError.value, 'timeout')
const funding = await budgets.readOrderFunding('procurement', boundOrder)
assert.equal(funding.status, status)
assert.equal(funding.usable, false)
await harness.state.submit()
assert.equal(createCalls.length, 2, status)
assert.deepEqual(budgetCalls, [{ method: 'GET', url: '/merchant/v1/last-leg/order-budgets/procurement/orders/CG-EXISTING' }])
assert.equal(harness.state.submitError.value, '')
assert.equal(harness.state.submittedOrder.value, 'CG-EXISTING')
assert.equal(harness.pushes[0].name, 'cross-border-procurement')
await harness.state.submit()
assert.equal(createCalls.length, 2)
} finally { harness.dispose() }
}
})
test('funding APIs preserve server results and retry the same order only when requested', async () => {
for (const kind of ['procurement', 'trucking']) for (const status of ['FREEZE_PENDING', 'FROZEN', 'RELEASE_PENDING', 'RELEASED', 'RELEASE_FAILED', 'FAILED']) {
const calls = []
const result = { status, usable: false, orderNo: 'CG/EXISTING', message: '资金校验失败' }
const budgets = moduleFrom(readFileSync(new URL('./api/orderBudgets.ts', import.meta.url), 'utf8'), name => {
assert.equal(name, '@/api/http')
return { apiRequest: async request => { calls.push(normalized(request)); return result } }
})
assert.deepEqual(await budgets.readOrderFunding(kind, result.orderNo), result)
assert.deepEqual(calls, [{ method: 'GET', url: `/merchant/v1/last-leg/order-budgets/${kind}/orders/CG%2FEXISTING` }])
await budgets.retryOrderFunding(kind, result.orderNo)
assert.deepEqual(calls[1], { method: 'POST', url: `/merchant/v1/last-leg/order-budgets/${kind}/orders/CG%2FEXISTING/retry` })
assert.equal(calls.length, 2)
}
})
test('bill-settled manual fees show review results without counting a balance debit', () => {
const bill = determination => ({ ...fee('OTHER', 'NOT_REQUIRED', '100'), determination })
assert.equal(presentation.feeStatus(bill('PENDING')), '账单结算 · 待审核')