This commit is contained in:
2026-08-19 09:42:07 +08:00
parent ff1d330c2d
commit b5864bfcda
56 changed files with 497 additions and 306 deletions
@@ -52,22 +52,21 @@ async function sourceDetail(context, feeSourceId) {
return { response, value: data(response) }
}
async function approveAndInclude(context, source, role) {
async function approveSource(context, source, role) {
let current = await sourceDetail(context, source.feeSourceId)
if (current.value?.reviewStatus === 'DRAFT' || current.value?.reviewStatus === 'REJECTED') {
const response = await write(context, 'POST', `${BASE}/fee-sources/${source.feeSourceId}/submit`,
{ reason: `${MARKER}-${role}`, expectedVersion: operationVersion(current.value) }, `source-${role}-${source.feeSourceId}-submit`)
current = { response, value: data(response) }
}
if (current.value?.reviewStatus === 'PENDING') {
const response = await write(context, 'POST', `${BASE}/fee-sources/${source.feeSourceId}/review`,
{ action: 'APPROVE', reason: `${MARKER}-${role}`, expectedVersion: operationVersion(current.value) }, `source-${role}-${source.feeSourceId}-approve`)
current = { response, value: data(response) }
}
if (current.value?.settlementIncluded !== true) {
const response = await write(context, 'PUT', `${BASE}/fee-sources/${source.feeSourceId}/settlement-inclusion`,
{ included: true, reason: `${MARKER}-${role}`, expectedVersion: operationVersion(current.value) }, `source-${role}-${source.feeSourceId}-include`)
current = { response, value: data(response) }
}
record(context, `${role} 来源已审核并纳入结算`, current.response,
current.value?.reviewStatus === 'APPROVED' && current.value?.settlementIncluded === true
&& current.value?.sourceStatus === 'AVAILABLE',
`feeSourceId=${source.feeSourceId}, review=${current.value?.reviewStatus}, included=${current.value?.settlementIncluded}`)
record(context, `${role} 来源已审核并自动进入结算候选`, current.response,
current.value?.reviewStatus === 'APPROVED' && current.value?.sourceStatus === 'AVAILABLE',
`feeSourceId=${source.feeSourceId}, review=${current.value?.reviewStatus}`)
return current.value
}
@@ -75,20 +74,20 @@ async function createExtraPayable(context, fixture, index) {
const itemResponse = await context.request('GET', '/api/platform/v1/fee-items?page=1&pageSize=200')
const feeItem = rows(data(itemResponse)).find((item) => item.status === 'ACTIVE' && item.warehousePayable === true)
const inboundId = id(fixture.orders.at(-1)?.inboundId)
const partnerId = id(fixture.supplier?.partnerId ?? fixture.supplier?.supplierId)
if (!feeItem || !inboundId || !partnerId) return null
const supplierId = id(fixture.supplier?.supplierId)
if (!feeItem || !inboundId || !supplierId) return null
const body = { feeItemId: Number(feeItem.id), direction: 'PAYABLE', businessDate: new Date().toISOString().slice(0, 10),
unitPrice: 90 + index * 10, amount: 90 + index * 10, currency: 'CNY', settlementIncluded: true,
partnerId, partnerName: fixture.supplier?.supplierName || null, remark: `${MARKER}-AP-${index}` }
unitPrice: 90 + index * 10, amount: 90 + index * 10, currency: 'CNY',
supplierId, remark: `${MARKER}-AP-${index}` }
const basePath = `/api/platform/v1/inbounds/${inboundId}/fee-details`
const createdResponse = await write(context, 'POST', `${basePath}?accountId=10001`, body, `extra-payable-${index}`)
const created = data(createdResponse)
if (!ok(createdResponse) || !created?.id) return null
const approveResponse = await write(context, 'POST', `${basePath}/${created.id}/approve?accountId=10001`, undefined, `extra-payable-${index}-approve`)
record(context, `创建第 ${index} 条额外应付来源`, approveResponse, ok(approveResponse),
`sourceFeeId=${created.id}, inboundId=${inboundId}, partnerId=${partnerId}`)
`sourceFeeId=${created.id}, inboundId=${inboundId}, supplierId=${supplierId}`)
return { sourceFeeId: id(created.id), direction: 'PAYABLE', businessDate: body.businessDate,
supplierId: partnerId, supplierName: body.partnerName }
supplierId, supplierName: fixture.supplier?.supplierName || null }
}
async function createStatement(context, source, role, targetStatus) {
@@ -206,7 +205,7 @@ async function recoverExistingDemo(context, reportPath) {
'invalid-finance-demo-recovery-source')
continue
}
const approved = await approveAndInclude(context, { feeSourceId: payableIds[index] }, role)
const approved = await approveSource(context, { feeSourceId: payableIds[index] }, role)
const existing = await recoverPayable(context, matrix.payableSettlements[role], payableIds[index])
const recoverySupplierId = role === 'apPartial'
? id(matrix.payableSettlements?.apPaid?.supplierId)
@@ -234,7 +233,7 @@ async function recoverExistingDemo(context, reportPath) {
matrix.receivableSettlements[role] = value
verifySettlementState(context, 'RECEIVABLE', role, response, value, expectedStatus)
}
matrix.feeSources.approvedUnbilled = await approveAndInclude(context, { feeSourceId: '300' }, 'approved-unbilled')
matrix.feeSources.approvedUnbilled = await approveSource(context, { feeSourceId: '300' }, 'approved-unbilled')
context.createdResources.financeFullFixtures = fixture
context.createdResources.financeDemo = matrix
}
@@ -294,7 +293,7 @@ export async function run(context) {
const poolBySource = new Map(pool.map((item) => [id(item.sourceId), item]))
const sources = produced.map((source) => ({ ...source,
feeSourceId: financeId(poolBySource.get(source.sourceFeeId)), marker: runMarker,
supplierId: id(source.supplierId ?? source.partnerId ?? fixture.supplier?.supplierId) }))
supplierId: id(source.supplierId ?? fixture.supplier?.supplierId) }))
.filter((source) => source.feeSourceId)
const receivables = sources.filter((source) => source.direction === 'RECEIVABLE')
const payables = sources.filter((source) => source.direction === 'PAYABLE' && source.supplierId)
@@ -311,10 +310,10 @@ export async function run(context) {
const pending = await sourceDetail(context, receivables[0].feeSourceId)
record(context, '保留费用待审核', pending.response,
pending.value?.reviewStatus === 'PENDING' && pending.value?.settlementIncluded === false,
pending.value?.reviewStatus === 'PENDING',
`feeSourceId=${receivables[0].feeSourceId}, review=${pending.value?.reviewStatus}`)
matrix.feeSources.pendingReview = pending.value
matrix.feeSources.approvedUnbilled = await approveAndInclude(context, receivables[1], 'approved-unbilled')
matrix.feeSources.approvedUnbilled = await approveSource(context, receivables[1], 'approved-unbilled')
const statementRoles = [
['draft', 'DRAFT'], ['pendingReview', 'PENDING_REVIEW'], ['arUnpaid', 'ISSUED'],
@@ -322,7 +321,7 @@ export async function run(context) {
]
for (let index = 0; index < statementRoles.length; index += 1) {
const [role, status] = statementRoles[index]
await approveAndInclude(context, receivables[index + 2], role)
await approveSource(context, receivables[index + 2], role)
const statement = await createStatement(context, receivables[index + 2], role, status)
if (statement.value) matrix.statements[role] = statement.value
}
@@ -344,7 +343,7 @@ export async function run(context) {
}
for (const [index, role] of ['apUnpaid', 'apPartial', 'apPaid'].entries()) {
await approveAndInclude(context, payables[index], role)
await approveSource(context, payables[index], role)
const settlement = await createAp(context, fixture, payables[index], role)
if (!settlement) continue
if (role === 'apUnpaid') matrix.payableSettlements[role] = settlement