feat: 新增预算费控模型与报销审批流引擎
后端新增预算费控服务和报销单审批流模块,引入申请人费用画像 算法,优化知识库 RAG 运行时和同步逻辑,完善报销单工作流常 量和明细同步,更新差旅报销规则电子表格,前端新增预算分析 组件和数字员工模型,完善审批对话框和洞察面板交互,优化侧 边栏和顶栏样式,补充单元测试。
This commit is contained in:
@@ -57,6 +57,7 @@ const REIMBURSEMENT_PROGRESS_LABELS = [
|
||||
const APPLICATION_PROGRESS_LABELS = [
|
||||
'创建申请',
|
||||
'直属领导审批',
|
||||
'预算管理者审批',
|
||||
'审批完成'
|
||||
]
|
||||
|
||||
@@ -386,10 +387,13 @@ function resolveApplicationProgressCurrentIndex(approvalMeta, workflowNode) {
|
||||
const normalizedNode = String(workflowNode || '').trim()
|
||||
|
||||
if (approvalMeta.key === 'completed') {
|
||||
return 2
|
||||
return 3
|
||||
}
|
||||
|
||||
if (normalizedNode.includes('审批完成') || normalizedNode.includes('申请完成')) {
|
||||
return 3
|
||||
}
|
||||
if (normalizedNode.includes('预算')) {
|
||||
return 2
|
||||
}
|
||||
if (
|
||||
@@ -437,15 +441,42 @@ function resolveApplicationApproverName(claim) {
|
||||
) || '直属领导'
|
||||
}
|
||||
|
||||
function resolveApplicationBudgetApproverName(claim) {
|
||||
const routeEvent = findApprovalEventForStep(claim, '直属领导审批')
|
||||
return resolveDisplayName(
|
||||
routeEvent?.next_approver_name,
|
||||
routeEvent?.nextApproverName,
|
||||
routeEvent?.budget_approver_name,
|
||||
routeEvent?.budgetApproverName
|
||||
) || 'P8预算监控者'
|
||||
}
|
||||
|
||||
function resolveProgressDisplayLabel(label, documentTypeCode, claim, approvalMeta) {
|
||||
const normalizedLabel = normalizeText(label)
|
||||
const workflowNode = normalizeText(claim?.approval_stage || claim?.workflowNode)
|
||||
if (
|
||||
documentTypeCode === DOCUMENT_TYPE_APPLICATION
|
||||
&& approvalMeta.key !== 'completed'
|
||||
&& normalizeText(label) === '直属领导审批'
|
||||
&& normalizedLabel === '直属领导审批'
|
||||
&& (
|
||||
workflowNode.includes('直属领导')
|
||||
|| workflowNode.includes('领导审批')
|
||||
|| workflowNode.includes('部门负责人')
|
||||
|| workflowNode.includes('负责人审批')
|
||||
)
|
||||
) {
|
||||
return `等待 ${resolveApplicationApproverName(claim)} 批复`
|
||||
}
|
||||
|
||||
if (
|
||||
documentTypeCode === DOCUMENT_TYPE_APPLICATION
|
||||
&& approvalMeta.key !== 'completed'
|
||||
&& normalizedLabel === '预算管理者审批'
|
||||
&& workflowNode.includes('预算')
|
||||
) {
|
||||
return `等待 ${resolveApplicationBudgetApproverName(claim)} 批复`
|
||||
}
|
||||
|
||||
return label
|
||||
}
|
||||
|
||||
@@ -471,7 +502,7 @@ function findApprovalEventForStep(claim, label) {
|
||||
}
|
||||
|
||||
const source = normalizeText(flag.source)
|
||||
if (!['manual_approval', 'finance_approval'].includes(source)) {
|
||||
if (!['manual_approval', 'budget_approval', 'finance_approval'].includes(source)) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -482,10 +513,19 @@ function findApprovalEventForStep(claim, label) {
|
||||
return (
|
||||
previousStage.includes('直属领导')
|
||||
|| previousStage.includes('领导审批')
|
||||
|| nextStage.includes('预算')
|
||||
|| nextStage.includes('财务')
|
||||
)
|
||||
}
|
||||
|
||||
if (stepLabel === '预算管理者审批') {
|
||||
return (
|
||||
source === 'budget_approval'
|
||||
|| previousStage.includes('预算')
|
||||
|| nextStage.includes('审批完成')
|
||||
)
|
||||
}
|
||||
|
||||
if (stepLabel === '财务审批') {
|
||||
return (
|
||||
previousStage.includes('财务')
|
||||
@@ -557,15 +597,16 @@ function buildCompletedStepMeta(claim, label) {
|
||||
return buildProgressStepMeta('AI预审通过', reviewedAt)
|
||||
}
|
||||
|
||||
if (stepLabel === '直属领导审批' || stepLabel === '财务审批') {
|
||||
if (stepLabel === '直属领导审批' || stepLabel === '预算管理者审批' || stepLabel === '财务审批') {
|
||||
const approvalEvent = findApprovalEventForStep(claim, stepLabel)
|
||||
if (approvalEvent) {
|
||||
const operator = resolveDisplayName(
|
||||
approvalEvent.operator,
|
||||
approvalEvent.operator_name,
|
||||
approvalEvent.operatorName,
|
||||
stepLabel === '直属领导审批' ? claim?.manager_name : ''
|
||||
) || (stepLabel === '财务审批' ? '财务' : '直属领导')
|
||||
stepLabel === '直属领导审批' ? claim?.manager_name : '',
|
||||
stepLabel === '预算管理者审批' ? approvalEvent.next_approver_name : ''
|
||||
) || (stepLabel === '财务审批' ? '财务' : stepLabel === '预算管理者审批' ? '预算监控者' : '直属领导')
|
||||
const approvedAt = formatDateTime(approvalEvent.created_at || approvalEvent.createdAt)
|
||||
return buildProgressStepMeta(`${operator}通过`, approvedAt, `${operator}审批通过 ${approvedAt}`.trim())
|
||||
}
|
||||
@@ -626,6 +667,10 @@ function resolveCurrentStepStartedAt(claim, label) {
|
||||
if (stepLabel === '直属领导审批') {
|
||||
return claim?.submitted_at || claim?.updated_at || claim?.created_at
|
||||
}
|
||||
if (stepLabel === '预算管理者审批') {
|
||||
const leaderApprovalEvent = findApprovalEventForStep(claim, '直属领导审批')
|
||||
return leaderApprovalEvent?.created_at || leaderApprovalEvent?.createdAt || claim?.updated_at || claim?.submitted_at
|
||||
}
|
||||
if (stepLabel === '财务审批') {
|
||||
const leaderApprovalEvent = findApprovalEventForStep(claim, '直属领导审批')
|
||||
return leaderApprovalEvent?.created_at || leaderApprovalEvent?.createdAt || claim?.updated_at || claim?.submitted_at
|
||||
|
||||
Reference in New Issue
Block a user