test: use active suppliers for finance fixtures
This commit is contained in:
@@ -8,9 +8,10 @@ import { run } from './finance-reconciliation-full.mjs'
|
||||
const here = path.dirname(fileURLToPath(import.meta.url))
|
||||
const source = fs.readFileSync(path.join(here, 'finance-reconciliation-full.mjs'), 'utf8')
|
||||
|
||||
test('Finance pool keeps formal MANUAL_COST and maps container cost by stable container identity', () => {
|
||||
test('Finance AP consumes only published fin_fee_source rows and never substitutes MANUAL_COST IDs', () => {
|
||||
assert.doesNotMatch(source, /sourceType \?\? ''\) !== 'MANUAL_COST'/)
|
||||
assert.match(source, /\[raw\.containerBookingId, raw\.loadingPlanId\]\.map\(id\)\.includes\(id\(item\?\.containerId\)\)/)
|
||||
assert.doesNotMatch(source, /\[raw\.containerBookingId, raw\.loadingPlanId\]\.map\(id\)\.includes\(id\(item\?\.containerId\)\)/)
|
||||
assert.match(source, /const financeSource = poolBySource\.get\(sourceId\(raw\)\)/)
|
||||
assert.match(source, /!isUnboundContainerCost\(source\.raw\) \|\| hasContainerAllocations/)
|
||||
})
|
||||
const financePermissions = [
|
||||
@@ -26,7 +27,8 @@ function ok(data) {
|
||||
return { http: 200, body: { code: '200', data }, requestId: 'request-test', traceId: 'trace-test' }
|
||||
}
|
||||
|
||||
function fakeContext(withFixture = true, permissions = financePermissions, denyFinanceWrites = false, missingSubject = false) {
|
||||
function fakeContext(withFixture = true, permissions = financePermissions, denyFinanceWrites = false,
|
||||
missingSubject = false, omitPayableSource = false) {
|
||||
const marker = 'FIN-TEST-MARKER'
|
||||
const receivables = [
|
||||
{ feeSourceId: '101', orderId: '201', direction: 'RECEIVABLE', currency: 'CNY', businessDate: '2026-08-10' },
|
||||
@@ -84,7 +86,7 @@ function fakeContext(withFixture = true, permissions = financePermissions, denyF
|
||||
if (method === 'GET' && requestPath === '/api/platform/v1/iam/authorization/permissions') {
|
||||
return ok(permissions)
|
||||
}
|
||||
if (method === 'GET' && requestPath === '/api/platform/finance/v1/accounts?page=1&pageSize=20') {
|
||||
if (method === 'GET' && requestPath === '/api/platform/finance/v1/accounts?page=1&pageSize=20&customerId=11') {
|
||||
return ok({ records: [{ customerId: '11', accountName: 'Fixture Account' }] })
|
||||
}
|
||||
if (method === 'GET' && requestPath.startsWith('/api/platform/finance/v1/accounts/11/ledger?')) {
|
||||
@@ -98,7 +100,7 @@ function fakeContext(withFixture = true, permissions = financePermissions, denyF
|
||||
requestId: 'request-denied', traceId: 'trace-denied' }
|
||||
}
|
||||
if (method === 'GET' && requestPath.includes('/fee-pool')) {
|
||||
return ok(feeSources.filter((item) => item.feeSourceId).map((item, index) => {
|
||||
return ok(feeSources.filter((item) => item.feeSourceId && (!omitPayableSource || item.feeSourceId !== '105')).map((item, index) => {
|
||||
const { feeSourceId, ...rest } = item
|
||||
return { ...rest, poolItemId: `${item.direction}:${1001 + index}`, sourceId: feeSourceId,
|
||||
reviewStatus: 'APPROVED', settlementIncluded: true, sourceStatus: 'AVAILABLE' }
|
||||
@@ -219,7 +221,7 @@ test('静态契约覆盖日期、SELECTED、三 AR、AP、状态机和数组输
|
||||
assert.match(source, /platform:finance:settlement-ar:list/)
|
||||
assert.match(source, /platform:finance:settlement-ap:list/)
|
||||
assert.doesNotMatch(source, /platform:finance:settlement-(ar|ap):view/)
|
||||
assert.match(source, /\$\{BASE\}\/accounts\?page=1&pageSize=20/)
|
||||
assert.match(source, /accounts\?page=1&pageSize=20&customerId=/)
|
||||
assert.match(source, /\/accounts\/\$\{encodeURIComponent\(customerId\)\}\/ledger\?page=1&pageSize=200/)
|
||||
assert.match(source, /balance.*recharge.*prepayment/)
|
||||
assert.match(source, /accountReadback/)
|
||||
@@ -300,6 +302,17 @@ test('来源缺失逐条 customerId 时不得由 fixture 根字段静默补齐',
|
||||
assert.equal(context.calls.some((call) => call.method !== 'GET'), false)
|
||||
})
|
||||
|
||||
test('marker-owned PAYABLE 来源未入池时 fail-closed 且不使用 MANUAL_COST 替代', async () => {
|
||||
const context = fakeContext(true, financePermissions, false, false, true)
|
||||
|
||||
await run(context)
|
||||
|
||||
assert.equal(context.steps.some((step) => step.name === '本轮费用来源进入 Finance 池'
|
||||
&& !step.passed && step.deploymentBlocker), true)
|
||||
assert.equal(context.coverageGaps.some((gap) => gap.category === 'unpublished-marker-owned-finance-source'), true)
|
||||
assert.equal(context.calls.some((call) => call.method !== 'GET'), false)
|
||||
})
|
||||
|
||||
test('缺少 Finance 创建权限时 fail-closed 且不发送财务写请求', async () => {
|
||||
const context = fakeContext(true, financePermissions.filter((item) => item !== 'platform:finance:reconciliation:create'))
|
||||
await run(context)
|
||||
|
||||
Reference in New Issue
Block a user