test: use active suppliers for finance fixtures

This commit is contained in:
2026-08-15 17:52:46 +08:00
parent 5e1e49085d
commit 0e2a291e7a
4 changed files with 77 additions and 29 deletions
@@ -131,7 +131,8 @@ function hasWalletField(value) {
}
async function verifyCustomerAccountAndLedger(context, fixture) {
const customerId = id(fixture.customerId)
const accountResponse = await context.request('GET', `${BASE}/accounts?page=1&pageSize=20`)
const accountResponse = await context.request('GET',
`${BASE}/accounts?page=1&pageSize=20&customerId=${encodeURIComponent(customerId)}`)
const accounts = accountRows(accountResponse)
const account = accounts.find((item) => accountCustomerId(item) === customerId)
context.assert(MODULE, '客户账户列表包含本轮 marker 客户且不暴露钱包字段', accountResponse,
@@ -182,8 +183,6 @@ async function normalizeFixture(context) {
const poolBySource = new Map(pool.map((item) => [id(item?.sourceId), item]))
const attemptedSources = root.feeSources.map((raw) => {
const financeSource = poolBySource.get(sourceId(raw))
|| pool.find((item) => String(item?.direction || '').toUpperCase() === 'PAYABLE'
&& [raw.containerBookingId, raw.loadingPlanId].map(id).includes(id(item?.containerId)))
return {
raw, feeSourceId: financePoolId(financeSource), sourceFeeId: sourceId(raw), customerId: id(raw.customerId),
direction: String(raw.direction ?? ''), currency: String(raw.currency ?? raw.currencyCode ?? '').toUpperCase(),
@@ -346,22 +345,32 @@ export async function run(context) {
finish(context, start)
return
}
if (fixture.uncreatedSources.length > 0) {
const evidence = fixture.uncreatedSources.map((source) => {
const incompleteContainerSources = fixture.uncreatedSources.filter((source) => isUnboundContainerCost(source.raw))
if (incompleteContainerSources.length > 0) {
const evidence = incompleteContainerSources.map((source) => {
const raw = source.raw
return `sourceType=${raw.sourceType ?? 'missing'}, billingBasis=${raw.billingBasis ?? 'missing'}, feeSourceId=${source.feeSourceId || 'missing'}, containerBookingId=${id(raw.containerBookingId) || 'missing'}`
}).join('; ')
context.addCoverageGap(MODULE, SCENARIO, '忽略不完整的柜次成本尝试',
`Finance 未返回 feeSourceId 或逐订单/运单 allocation 关联,不得作为费用来源消费:${evidence}`,
'incomplete-container-cost-attempt', { marker: context.marker, count: fixture.uncreatedSources.length })
'incomplete-container-cost-attempt', { marker: context.marker, count: incompleteContainerSources.length })
}
const unpublishedSources = fixture.uncreatedSources.filter((source) => !isUnboundContainerCost(source.raw))
if (unpublishedSources.length > 0) {
blocker(context, '本轮费用来源进入 Finance 池',
`等待 Finance fee-pool 后仍有 ${unpublishedSources.length} 条 marker-owned 来源不可见;禁止忽略来源或改用 MANUAL_COST ID`,
'unpublished-marker-owned-finance-source')
finish(context, start)
return
}
const invalid = fixture.sources.filter((source) => !source.feeSourceId || !source.customerId
|| !source.businessDate || !source.waybillId || source.marker !== context.marker)
|| !source.businessDate || !source.waybillId || source.marker !== context.marker
|| (source.direction === 'PAYABLE' && (!source.supplierId || !source.supplierName)))
if (invalid.length > 0) {
fixture.root.reconciliationPrerequisite = { ready: false, category: 'finance-source-prerequisite',
invalidSourceCount: invalid.length }
blocker(context, 'Fixture 来源契约完整',
`存在 ${invalid.length} 条来源缺少 feeSourceId/customerId/businessDate/运单标识/marker`,
`存在 ${invalid.length} 条来源缺少 feeSourceId/customerId/businessDate/运单标识/marker/应付供应商快照`,
'invalid-finance-fixture-contract')
finish(context, start)
return