fix(worker): 用户付款金额未变化时不再写审计日志
This commit is contained in:
@@ -31,6 +31,7 @@ import {
|
|||||||
updateAdminWorkOrderPaymentAmount,
|
updateAdminWorkOrderPaymentAmount,
|
||||||
updateAdminWorkOrderSharing,
|
updateAdminWorkOrderSharing,
|
||||||
} from '../../../services/worker-platform/index.js'
|
} from '../../../services/worker-platform/index.js'
|
||||||
|
import { buildWorkOrderPaymentAmountAuditData } from '../../../services/worker-platform/work-order-payment-amount.js'
|
||||||
import {
|
import {
|
||||||
createJsonHandler,
|
createJsonHandler,
|
||||||
requireAdminPermission,
|
requireAdminPermission,
|
||||||
@@ -251,20 +252,14 @@ router.put(
|
|||||||
errorMessage: '修改用户付款金额失败',
|
errorMessage: '修改用户付款金额失败',
|
||||||
scope: '[admin/worker-platform/orders/:workOrderId/payment-amount]',
|
scope: '[admin/worker-platform/orders/:workOrderId/payment-amount]',
|
||||||
audit: (req, data) => {
|
audit: (req, data) => {
|
||||||
const result = (data || {}) as {
|
// 金额未变化时服务层不会写工单事件,这里也不留下一条“已更新”的审计记录。
|
||||||
previousAmountFen?: number | null
|
const auditData = buildWorkOrderPaymentAmountAuditData(data)
|
||||||
amountFen?: number
|
if (!auditData) return null
|
||||||
reason?: string
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
action: 'work_order_payment_amount_updated',
|
action: 'work_order_payment_amount_updated',
|
||||||
targetType: 'work_order',
|
targetType: 'work_order',
|
||||||
targetId: String(req.params.workOrderId || ''),
|
targetId: String(req.params.workOrderId || ''),
|
||||||
data: {
|
data: auditData,
|
||||||
previousAmountFen: result.previousAmountFen ?? null,
|
|
||||||
amountFen: result.amountFen ?? null,
|
|
||||||
reason: result.reason || '',
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import assert from 'node:assert/strict'
|
|||||||
import test from 'node:test'
|
import test from 'node:test'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
buildWorkOrderPaymentAmountAuditData,
|
||||||
mergeUserPaymentAmountIntoMaterial,
|
mergeUserPaymentAmountIntoMaterial,
|
||||||
normalizeUserPaymentAmountFen,
|
normalizeUserPaymentAmountFen,
|
||||||
resolveDisplayedUserPaymentAmountFen,
|
resolveDisplayedUserPaymentAmountFen,
|
||||||
@@ -87,3 +88,38 @@ test('mergeUserPaymentAmountIntoMaterial:兼容 JSON 字符串与异常结构'
|
|||||||
source: { orderAmountFen: 1234 },
|
source: { orderAmountFen: 1234 },
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('buildWorkOrderPaymentAmountAuditData:未变化不写审计,变化时保留原值', () => {
|
||||||
|
assert.equal(
|
||||||
|
buildWorkOrderPaymentAmountAuditData({
|
||||||
|
unchanged: true,
|
||||||
|
previousAmountFen: 1000,
|
||||||
|
amountFen: 1000,
|
||||||
|
reason: '',
|
||||||
|
}),
|
||||||
|
null,
|
||||||
|
'未变化提交不能留下「已更新」审计',
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.deepEqual(
|
||||||
|
buildWorkOrderPaymentAmountAuditData({
|
||||||
|
unchanged: false,
|
||||||
|
previousAmountFen: 1000,
|
||||||
|
amountFen: 1234,
|
||||||
|
reason: ' 修正 ',
|
||||||
|
}),
|
||||||
|
{ previousAmountFen: 1000, amountFen: 1234, reason: '修正' },
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.deepEqual(
|
||||||
|
buildWorkOrderPaymentAmountAuditData({
|
||||||
|
unchanged: false,
|
||||||
|
previousAmountFen: null,
|
||||||
|
amountFen: 1234,
|
||||||
|
}),
|
||||||
|
{ previousAmountFen: null, amountFen: 1234, reason: '' },
|
||||||
|
'原标题金额缺失时保留 null,不能误写成 0',
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.equal(buildWorkOrderPaymentAmountAuditData(null), null)
|
||||||
|
})
|
||||||
|
|||||||
@@ -78,3 +78,39 @@ export function mergeUserPaymentAmountIntoMaterial(
|
|||||||
}
|
}
|
||||||
return { ...material, source: nextSource }
|
return { ...material, source: nextSource }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type WorkOrderPaymentAmountAuditData = {
|
||||||
|
previousAmountFen: number | null
|
||||||
|
amountFen: number | null
|
||||||
|
reason: string
|
||||||
|
}
|
||||||
|
|
||||||
|
function toAmountFenOrNull(value: unknown): number | null {
|
||||||
|
if (value === null || value === undefined || value === '') return null
|
||||||
|
const parsed = Number(value)
|
||||||
|
return Number.isFinite(parsed) ? parsed : null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 后台审计载荷:金额未变化时不写「已更新」审计。
|
||||||
|
*
|
||||||
|
* 前端已拦截未变化提交,但接口仍可能被直接调用或重放;此时服务层不会写
|
||||||
|
* payment_amount_updated 工单事件,审计也不能留下一条原金额等于新金额的修改记录。
|
||||||
|
*/
|
||||||
|
export function buildWorkOrderPaymentAmountAuditData(
|
||||||
|
data: unknown,
|
||||||
|
): WorkOrderPaymentAmountAuditData | null {
|
||||||
|
if (!data || typeof data !== 'object' || Array.isArray(data)) return null
|
||||||
|
const result = data as {
|
||||||
|
previousAmountFen?: unknown
|
||||||
|
amountFen?: unknown
|
||||||
|
reason?: unknown
|
||||||
|
unchanged?: unknown
|
||||||
|
}
|
||||||
|
if (result.unchanged === true) return null
|
||||||
|
return {
|
||||||
|
previousAmountFen: toAmountFenOrNull(result.previousAmountFen),
|
||||||
|
amountFen: toAmountFenOrNull(result.amountFen),
|
||||||
|
reason: String(result.reason || '').trim(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user