优化
This commit is contained in:
@@ -9,7 +9,9 @@ const write = (context, method, path, body, operation) => context.request(method
|
||||
const settlementId = (value) => id(value?.settlementId ?? value?.summary?.settlementId ?? value?.id)
|
||||
const statementId = (value) => id(value?.statementId ?? value?.reconciliationStatementId ?? value?.id)
|
||||
const outstanding = (value) => Number(value?.outstandingAmount ?? value?.summary?.outstandingAmount ?? 0)
|
||||
const paid = (value) => Number(value?.paidAmount ?? value?.summary?.paidAmount ?? 0)
|
||||
const version = (value) => Number(value?.version ?? value?.summary?.version ?? 0)
|
||||
const status = (value) => id(value?.status ?? value?.summary?.status ?? value?.paymentStatus)
|
||||
|
||||
export function values(value) {
|
||||
if (Array.isArray(value)) return value.filter(Boolean)
|
||||
@@ -34,6 +36,61 @@ async function detail(context, targetId) {
|
||||
return { response, value: data(response) }
|
||||
}
|
||||
|
||||
async function verifyVoidReopen(context, item) {
|
||||
const targetId = settlementId(item)
|
||||
const before = await detail(context, targetId)
|
||||
if (!ok(before.response) || status(before.value) !== 'ISSUED' || outstanding(before.value) <= 0 || paid(before.value) !== 0) {
|
||||
gap(context, '取得未收付款 ISSUED 结算单', 'settlement VOID/REOPEN',
|
||||
`本轮 settlementId=${targetId || 'missing'} 不满足 ISSUED 且 paidAmount=0;status=${status(before.value)}, paid=${paid(before.value)}`,
|
||||
'settlement-action-fixture-unavailable')
|
||||
return null
|
||||
}
|
||||
const path = `${BASE}/settlements/${targetId}/actions`
|
||||
const voidBody = { action: 'VOID', reason: context.marker, expectedVersion: version(before.value) }
|
||||
const voidedResponse = await write(context, 'POST', path, voidBody, 'settlement-void')
|
||||
const voided = data(voidedResponse)
|
||||
context.assert(MODULE, '未收付款结算单作废', voidedResponse, ok(voidedResponse)
|
||||
&& status(voided) === 'VOIDED' && version(voided) === version(before.value) + 1,
|
||||
`settlementId=${targetId}, status=${status(voided)}, version=${version(voided)}`, OPTIONS)
|
||||
|
||||
const replayResponse = await write(context, 'POST', path, voidBody, 'settlement-void')
|
||||
const replayed = data(replayResponse)
|
||||
context.assert(MODULE, '结算单作废同键同参幂等重放', replayResponse, ok(replayResponse)
|
||||
&& status(replayed) === 'VOIDED' && version(replayed) === version(voided),
|
||||
`settlementId=${targetId}, version=${version(replayed)}`, OPTIONS)
|
||||
|
||||
const conflictResponse = await write(context, 'POST', path,
|
||||
{ action: 'REOPEN', reason: `${context.marker}-conflict`, expectedVersion: version(voided) }, 'settlement-void')
|
||||
context.assert(MODULE, '结算单动作同键异参冲突', conflictResponse, !ok(conflictResponse),
|
||||
`HTTP=${conflictResponse.http}, code=${id(conflictResponse.body?.code)}`, OPTIONS)
|
||||
|
||||
const reopenBody = { action: 'REOPEN', reason: context.marker, expectedVersion: version(voided) }
|
||||
const reopenedResponse = await write(context, 'POST', path, reopenBody, 'settlement-reopen')
|
||||
const reopened = data(reopenedResponse)
|
||||
context.assert(MODULE, '已作废结算单重开', reopenedResponse, ok(reopenedResponse)
|
||||
&& status(reopened) === 'ISSUED' && version(reopened) === version(voided) + 1,
|
||||
`settlementId=${targetId}, status=${status(reopened)}, version=${version(reopened)}`, OPTIONS)
|
||||
return reopened
|
||||
}
|
||||
|
||||
async function verifyPaidVoidRejected(context, item) {
|
||||
const targetId = settlementId(item)
|
||||
const before = await detail(context, targetId)
|
||||
if (!ok(before.response) || paid(before.value) <= 0) {
|
||||
gap(context, '取得已发生收付款结算单', 'paid settlement VOID rejection',
|
||||
`本轮 settlementId=${targetId || 'missing'} 没有有效收付款;paid=${paid(before.value)}`,
|
||||
'paid-settlement-fixture-unavailable')
|
||||
return
|
||||
}
|
||||
const response = await write(context, 'POST', `${BASE}/settlements/${targetId}/actions`,
|
||||
{ action: 'VOID', reason: context.marker, expectedVersion: version(before.value) }, 'paid-settlement-void')
|
||||
const after = await detail(context, targetId)
|
||||
context.assert(MODULE, '已收付款结算单拒绝作废且状态金额不变', response, !ok(response) && ok(after.response)
|
||||
&& status(after.value) === status(before.value) && version(after.value) === version(before.value)
|
||||
&& paid(after.value) === paid(before.value) && outstanding(after.value) === outstanding(before.value),
|
||||
`settlementId=${targetId}, status=${status(after.value)}, paid=${paid(after.value)}, outstanding=${outstanding(after.value)}, version=${version(after.value)}`, OPTIONS)
|
||||
}
|
||||
|
||||
async function receive(context, fixtures, item, requestedAmount, operation, label) {
|
||||
const targetId = settlementId(item)
|
||||
const billId = statementId(item) || id(item.reconciliationStatementId)
|
||||
@@ -87,6 +144,11 @@ export async function run(context) {
|
||||
manualIds.length > 0 && manualIds.every((feeId) => usedIds.has(feeId)),
|
||||
`manual=${manualIds.length}, settled=${manualIds.filter((feeId) => usedIds.has(feeId)).length}`, OPTIONS)
|
||||
|
||||
const actionTarget = validReceivables.find((item) => item.status === 'ISSUED')
|
||||
?? validPayables.find((item) => item.status === 'ISSUED')
|
||||
if (!actionTarget) gap(context, '取得结算单动作 Fixture', 'settlement VOID/REOPEN', '本轮没有未收付款且状态 ISSUED 的 AR/AP,禁止借历史单据')
|
||||
else await verifyVoidReopen(context, actionTarget)
|
||||
|
||||
const multiTargets = validReceivables
|
||||
if (multiTargets.length < 3) gap(context, '取得三张应收结算单', 'multi receipt allocation', '本轮没有三张独占应收单,禁止借历史单据')
|
||||
else {
|
||||
@@ -111,6 +173,7 @@ export async function run(context) {
|
||||
const final = await receive(context, fixtures, primary, outstanding(partial.settlement), 'ar-final-receipt', '应收全额收款完结')
|
||||
fixtures.receipts = { ...(fixtures.receipts || {}), partial: partial.receipt, final: final.receipt }
|
||||
fixtures.settlementFinalStates = { ...(fixtures.settlementFinalStates || {}), receivable: final.settlement }
|
||||
await verifyPaidVoidRejected(context, primary)
|
||||
}
|
||||
|
||||
const payable = validPayables[0]
|
||||
|
||||
Reference in New Issue
Block a user