优化
This commit is contained in:
@@ -86,6 +86,72 @@ export function approvedInboundReady(orderDetail, taskResponse, tenantId, orderI
|
||||
&& id(task?.orderId) === id(orderId)
|
||||
&& id(task?.tenantId) === id(tenantId)
|
||||
}
|
||||
|
||||
export function approvalReplayDigest(snapshot) {
|
||||
return createHash('sha256').update(JSON.stringify(snapshot)).digest('hex')
|
||||
}
|
||||
|
||||
export async function verifyOrderApprovalReplay(context, { tenantId, orderId, inboundId, inboundCode }) {
|
||||
const scope = `tenantId=${encodeURIComponent(tenantId)}`
|
||||
const orderPath = `/api/platform/v1/orders/first-leg/${encodeURIComponent(orderId)}?${scope}`
|
||||
const taskPath = `/api/platform/v1/first-leg/tasks/by-order/${encodeURIComponent(orderId)}?${scope}`
|
||||
const inboundPath = `/api/platform/inbounds/${encodeURIComponent(inboundId)}?${scope}`
|
||||
async function read(name) {
|
||||
const orderResponse = await context.request('GET', orderPath)
|
||||
const detail = context.apiSuccess(MODULE, `${name}订单及状态历史`, orderResponse, '', CONTRACT_OPTIONS)
|
||||
const taskResponse = await context.request('GET', taskPath)
|
||||
const task = context.apiSuccess(MODULE, `${name}原履约任务`, taskResponse, '', CONTRACT_OPTIONS)
|
||||
const inboundResponse = await context.request('GET', inboundPath)
|
||||
const inbound = context.apiSuccess(MODULE, `${name}原入库单及历史`, inboundResponse, '', CONTRACT_OPTIONS)
|
||||
const rows = []; let total = null; let page = 1
|
||||
while (total == null || rows.length < total) {
|
||||
const response = await context.request('GET', `/api/platform/inbounds?${scope}`
|
||||
+ `&inboundCode=${encodeURIComponent(inboundCode)}&page=${page}&size=100`)
|
||||
const data = context.apiSuccess(MODULE, `${name}入仓码来源入库列表第${page}页`, response, '', CONTRACT_OPTIONS)
|
||||
const valid = pageOk(data) && Number.isInteger(Number(data.total)) && Number(data.total) >= 0
|
||||
&& (total == null || total === Number(data.total))
|
||||
&& (data.records.length > 0 || Number(data.total) === 0)
|
||||
context.assert(MODULE, `${name}入库分页计数完整`, response, valid,
|
||||
`page=${page}, total=${data?.total ?? 'missing'}`, CONTRACT_OPTIONS)
|
||||
if (!valid) throw new Error('审核重放核验缺少完整入库分页事实')
|
||||
total = Number(data.total); rows.push(...data.records); page += 1
|
||||
}
|
||||
const exact = rows.filter(row => id(row.inboundCode) === inboundCode)
|
||||
const valid = detail?.order?.status === 'APPROVED' && id(detail.order.id) === orderId
|
||||
&& id(detail.order.inboundCode) === inboundCode && Array.isArray(detail.statusHistory)
|
||||
&& id(task?.orderId) === orderId && id(task?.tenantId) === tenantId && Boolean(id(task?.id))
|
||||
&& id(inbound?.summary?.id) === inboundId && id(inbound?.summary?.tenantId) === tenantId
|
||||
&& id(inbound?.summary?.inboundCode) === inboundCode && Array.isArray(inbound?.statusHistory)
|
||||
&& rows.length === total && new Set(rows.map(row => id(row.id))).size === total
|
||||
&& exact.length === 1 && id(exact[0].id) === inboundId
|
||||
context.assert(MODULE, `${name}审核态原身份与唯一入库事实有效`, inboundResponse, valid,
|
||||
`exactInbounds=${exact.length}, taskId=${id(task?.id)}, inboundId=${id(inbound?.summary?.id)}`, CONTRACT_OPTIONS)
|
||||
if (!valid) throw new Error('审核重放核验的订单任务或唯一入库身份不一致')
|
||||
return { response: inboundResponse, facts: {
|
||||
order: JSON.parse(orderPersistenceFacts(detail)), task, inbound, exactInbounds: exact,
|
||||
} }
|
||||
}
|
||||
const before = await read('审核重放前')
|
||||
const response = await context.request('POST',
|
||||
`/api/platform/v1/orders/first-leg/${encodeURIComponent(orderId)}/approve?${scope}`)
|
||||
const rejected = response?.http === 200 && String(response.body?.code) === 'A0409'
|
||||
context.assert(MODULE, '已审核订单再次审核明确A0409', response, rejected,
|
||||
`HTTP=${response?.http}, code=${response?.body?.code ?? 'missing'}`, CONTRACT_OPTIONS)
|
||||
const after = await read('审核重放后')
|
||||
const beforeDigest = approvalReplayDigest(before.facts)
|
||||
const afterDigest = approvalReplayDigest(after.facts)
|
||||
const unchanged = beforeDigest === afterDigest
|
||||
context.assert(MODULE, '审核重复拒绝后订单入仓码历史任务及唯一入库事实零漂移', after.response,
|
||||
unchanged, `inboundCount=1, orderHistories=${after.facts.order.statusHistory.length}`
|
||||
+ `, inboundHistories=${after.facts.inbound.statusHistory.length}`, CONTRACT_OPTIONS)
|
||||
const evidence = { marker: context.marker, tenantId, orderId, inboundId, inboundCode,
|
||||
taskId: id(after.facts.task.id), inboundCount: after.facts.exactInbounds.length,
|
||||
orderHistoryCount: after.facts.order.statusHistory.length,
|
||||
inboundHistoryCount: after.facts.inbound.statusHistory.length,
|
||||
beforeDigest, afterDigest, rejected, unchanged }
|
||||
context.createdResources.orders.approvalReplay = evidence
|
||||
return evidence
|
||||
}
|
||||
function tomorrow(days = 30) {
|
||||
const date = new Date(); date.setUTCDate(date.getUTCDate() + days)
|
||||
return date.toISOString().slice(0, 10)
|
||||
@@ -742,6 +808,9 @@ export async function run(context) {
|
||||
throw new Error('订单审核后的入库单与履约任务未在30秒内收敛,无法修改申报并向 OCR/墨家模块交接')
|
||||
}
|
||||
|
||||
await verifyOrderApprovalReplay(context, { tenantId, orderId, inboundId,
|
||||
inboundCode: id(inboundResult.detail?.summary?.inboundCode) })
|
||||
|
||||
const editableDetailResponse = await context.request('GET', firstLegDetailPath)
|
||||
const editableDetail = context.apiSuccess(MODULE, 'Admin 读取审核后客户申报资料', editableDetailResponse)
|
||||
const declarationDetail = editableDetail?.order?.order ? editableDetail.order : editableDetail
|
||||
|
||||
Reference in New Issue
Block a user