feat: 新增风险图谱算法与系统仪表盘及操作反馈体系
后端新增风险图谱算法模块、风险观察与反馈服务、规则 DSL 校验器和可解释性引擎,完善系统仪表盘和财务仪表盘统计, 优化 agent 运行和编排执行链路,清理旧开发文档,前端新增 系统趋势、负载热力图等多种仪表盘图表组件,完善操作反馈 对话框和工作台日期选择器,优化报销创建和审批详情交互, 补充单元测试覆盖。
This commit is contained in:
@@ -9,6 +9,9 @@ const BUDGET_MANAGER_APPROVAL = '\u9884\u7b97\u7ba1\u7406\u8005\u5ba1\u6279'
|
||||
const APPROVAL_COMPLETED = '\u5ba1\u6279\u5b8c\u6210'
|
||||
const RETURNED = '\u9000\u56de'
|
||||
const WAIT_SUBMIT = '\u5f85\u63d0\u4ea4'
|
||||
const LINKED_APPLICATION = '\u5173\u8054\u5355\u636e'
|
||||
const PAID = '\u5df2\u4ed8\u6b3e'
|
||||
const ARCHIVED = '\u5df2\u5f52\u6863'
|
||||
const WAIT_LEADER_LI_APPROVAL = '\u7b49\u5f85 Leader Li \u6279\u590d'
|
||||
const WAIT_BUDGET_ZHAO_APPROVAL = '\u7b49\u5f85 \u8d75\u9884\u7b97 \u6279\u590d'
|
||||
const LEADER_RETURNED_STATUS = '\u9886\u5bfc\u5df2\u9000\u56de\uff0c\u5f85\u91cd\u65b0\u63d0\u4ea4'
|
||||
@@ -191,6 +194,47 @@ test('approved application claims complete after budget approval', () => {
|
||||
assert.equal(request.progressSteps.find((step) => step.label === '预算管理者审批')?.time, '赵预算通过')
|
||||
})
|
||||
|
||||
test('application claims hide budget step when leader approval also covers budget approval', () => {
|
||||
const request = mapExpenseClaimToRequest({
|
||||
id: 'claim-application-merged-budget',
|
||||
claim_no: 'APP-20260525-MERGED',
|
||||
employee_name: '张三',
|
||||
department_name: '交付部',
|
||||
manager_name: '李预算经理',
|
||||
expense_type: 'travel_application',
|
||||
reason: '支撑国网服务器上线部署',
|
||||
location: '上海',
|
||||
amount: 12000,
|
||||
invoice_count: 0,
|
||||
occurred_at: '2026-05-25T00:00:00.000Z',
|
||||
submitted_at: '2026-05-25T02:00:00.000Z',
|
||||
created_at: '2026-05-25T01:30:00.000Z',
|
||||
updated_at: '2026-05-25T03:00:00.000Z',
|
||||
status: 'approved',
|
||||
approval_stage: APPROVAL_COMPLETED,
|
||||
risk_flags_json: [
|
||||
{
|
||||
source: 'manual_approval',
|
||||
event_type: 'expense_application_approval',
|
||||
operator: '李预算经理',
|
||||
previous_approval_stage: DIRECT_MANAGER_APPROVAL,
|
||||
next_approval_stage: APPROVAL_COMPLETED,
|
||||
budget_approval_merged: true,
|
||||
created_at: '2026-05-25T03:00:00.000Z'
|
||||
}
|
||||
],
|
||||
items: []
|
||||
})
|
||||
|
||||
assert.deepEqual(
|
||||
request.progressSteps.map((step) => step.label),
|
||||
[CREATE_APPLICATION, DIRECT_MANAGER_APPROVAL, APPROVAL_COMPLETED]
|
||||
)
|
||||
assert.equal(request.progressSteps.every((step) => step.done), true)
|
||||
assert.equal(request.progressSteps.some((step) => step.label === BUDGET_MANAGER_APPROVAL), false)
|
||||
assert.equal(request.progressSteps.find((step) => step.label === DIRECT_MANAGER_APPROVAL)?.time, '李预算经理通过')
|
||||
})
|
||||
|
||||
test('progress steps show approval operator time and current stay duration', () => {
|
||||
const originalNow = Date.now
|
||||
Date.now = () => new Date('2026-05-20T05:00:00.000Z').getTime()
|
||||
@@ -230,7 +274,7 @@ test('progress steps show approval operator time and current stay duration', ()
|
||||
const firstStep = request.progressSteps[0]
|
||||
|
||||
assert.equal(request.riskSummary, '无')
|
||||
assert.equal(firstStep.label, '创建单据')
|
||||
assert.equal(firstStep.label, LINKED_APPLICATION)
|
||||
assert.equal(leaderStep.time, '李经理通过')
|
||||
assert.match(leaderStep.detail, /2026-05-20/)
|
||||
assert.match(leaderStep.title, /李经理审批通过/)
|
||||
@@ -479,19 +523,48 @@ test('paid reimbursement marks payment progress step as complete', () => {
|
||||
previous_approval_stage: '待付款',
|
||||
next_approval_stage: '已付款',
|
||||
created_at: '2026-05-20T05:00:00.000Z'
|
||||
},
|
||||
{
|
||||
source: 'application_handoff',
|
||||
event_type: 'expense_application_to_reimbursement_draft',
|
||||
application_claim_id: 'application-1',
|
||||
application_claim_no: 'APP-20260520-001',
|
||||
application_detail: {
|
||||
application_type: '差旅费用申请',
|
||||
application_content: '差旅费用申请 / 北京',
|
||||
application_reason: '支撑国网仿生产环境部署',
|
||||
application_days: '3 天',
|
||||
application_location: '北京',
|
||||
application_amount: '3000',
|
||||
application_time: '2026-05-20T00:00:00.000Z',
|
||||
application_transport_mode: '高铁'
|
||||
}
|
||||
}
|
||||
],
|
||||
items: []
|
||||
})
|
||||
|
||||
const paymentStep = request.progressSteps.find((step) => step.label === '待付款')
|
||||
const paidStep = request.progressSteps.find((step) => step.label === '已付款')
|
||||
const paidStep = request.progressSteps.find((step) => step.label === PAID)
|
||||
const archivedStep = request.progressSteps.find((step) => step.label === ARCHIVED)
|
||||
const linkedStep = request.progressSteps.find((step) => step.label === LINKED_APPLICATION)
|
||||
|
||||
assert.equal(request.workflowNode, '已付款')
|
||||
assert.equal(request.approvalStatus, '已付款')
|
||||
assert.deepEqual(
|
||||
request.progressSteps.map((step) => step.label),
|
||||
[LINKED_APPLICATION, '待提交', 'AI预审', '直属领导审批', '财务审批', '待付款', PAID, ARCHIVED]
|
||||
)
|
||||
assert.equal(paymentStep.time, '待付款')
|
||||
assert.equal(paidStep.time, '已付款')
|
||||
assert.equal(paidStep.done, true)
|
||||
assert.equal(archivedStep.time, ARCHIVED)
|
||||
assert.equal(archivedStep.done, true)
|
||||
assert.equal(linkedStep.time, '已关联 APP-20260520-001')
|
||||
assert.equal(request.relatedApplication.claimNo, 'APP-20260520-001')
|
||||
assert.equal(request.relatedApplication.reason, '支撑国网仿生产环境部署')
|
||||
assert.equal(request.relatedApplication.days, '3 天')
|
||||
assert.equal(request.relatedApplication.amountLabel, '¥3,000')
|
||||
})
|
||||
|
||||
test('current direct manager step shows how long the claim has stayed there', () => {
|
||||
|
||||
Reference in New Issue
Block a user