fix finance reconciliation fee pool ids

This commit is contained in:
2026-08-12 14:21:25 +08:00
parent aaa38f825a
commit 60895e3bf5
2 changed files with 25 additions and 11 deletions
@@ -80,8 +80,11 @@ function fakeContext(withFixture = true, permissions = financePermissions, denyF
requestId: 'request-denied', traceId: 'trace-denied' }
}
if (method === 'GET' && requestPath.includes('/fee-pool')) {
return ok(receivables.map((item) => ({ ...item, reviewStatus: 'APPROVED',
settlementIncluded: true, sourceStatus: 'AVAILABLE' })))
return ok(feeSources.filter((item) => item.feeSourceId).map((item, index) => {
const { feeSourceId, ...rest } = item
return { ...rest, poolItemId: `${item.direction}:${1001 + index}`, sourceId: feeSourceId,
reviewStatus: 'APPROVED', settlementIncluded: true, sourceStatus: 'AVAILABLE' }
}))
}
if (method === 'POST' && requestPath.endsWith('/statements')) {
if (body.currency !== 'CNY') return { http: 200, body: { code: 'FIN_400' } }
@@ -89,12 +92,12 @@ function fakeContext(withFixture = true, permissions = financePermissions, denyF
requestId: 'request-subject', traceId: 'trace-subject' }
const selected = body.generationMode === 'BY_CUTOFF'
? receivables.filter((item) => item.businessDate >= body.periodStart && item.businessDate <= body.periodEnd)
: feeSources.filter((item) => body.feeSourceIds.includes(item.feeSourceId))
: feeSources.filter((item, index) => body.feeSourceIds.includes(String(1001 + index)))
if (selected.some((item) => item.direction !== 'RECEIVABLE')) return { http: 200, body: { code: 'FIN_409' } }
const statementId = String(++statementSequence)
const statement = { statementId, status: 'DRAFT', version: 0, revisions: [],
lines: selected.map((item, index) => ({ statementLineId: `${statementId}${index + 1}`,
feeSourceId: item.feeSourceId, statementAmount: 100 + index, adjustmentReason: null })) }
feeSourceId: String(1001 + feeSources.indexOf(item)), statementAmount: 100 + index, adjustmentReason: null })) }
statements.set(statementId, statement)
if (idem) idempotency.set(idem, responseForStatement(statement))
return ok(responseForStatement(statement))
@@ -156,7 +159,7 @@ test('静态契约覆盖日期、SELECTED、三 AR、AP、状态机和数组输
assert.match(source, /fixture\.root\.statements = statementRows/)
assert.match(source, /fixture\.root\.receivableSettlements = arRows/)
assert.doesNotMatch(source, /generationMode:\s*['"]BY_CUTOFF['"]/)
assert.doesNotMatch(source, /\/fee-pool/)
assert.match(source, /\/fee-pool/)
assert.match(source, /http: response\?\.http \?\? null/)
assert.match(source, /requestId: response\?\.requestId \?\? null/)
assert.match(source, /traceId: response\?\.traceId \?\? null/)
@@ -184,9 +187,10 @@ test('run 发布一条日期链、三张独立已出账单、三张 AR 和一张
&& gap.reason.includes('containerBookingId=CB-COST-RESPONSE')), true)
assert.equal(context.calls.some((call) => call.body?.feeSourceIds?.includes(null)), false)
assert.equal(context.calls.some((call) => call.body?.feeSourceIds?.includes('106')), false)
assert.equal(context.calls.some((call) => call.path.includes('/fee-pool')
|| call.body?.generationMode === 'BY_CUTOFF'), false)
assert.equal(context.steps.filter((step) => !step.passed).length, 0)
assert.equal(context.calls.some((call) => call.path.includes('/fee-pool')), true)
assert.equal(context.calls.some((call) => call.body?.generationMode === 'BY_CUTOFF'), false)
const failedSteps = context.steps.filter((step) => !step.passed)
assert.equal(failedSteps.length, 0, JSON.stringify(failedSteps, null, 2))
})
test('run 在 fixture 缺失时记录 blocker 且不发送 HTTP 请求', async () => {