feat: 完善审批退回流程与报销申请关联
后端优化报销单访问策略和常量定义,增强退回原因和审批状态 流转,前端完善退回对话框和审批交互组件,新增报销申请关联 模型,优化文档中心行数据和审批收件箱工具函数,增强引导 流程和会话模型,补充单元测试覆盖。
This commit is contained in:
@@ -426,6 +426,29 @@ function resolveDisplayName(...values) {
|
||||
return ''
|
||||
}
|
||||
|
||||
function resolveApplicationApproverName(claim) {
|
||||
return resolveDisplayName(
|
||||
claim?.manager_name,
|
||||
claim?.managerName,
|
||||
claim?.profile_manager,
|
||||
claim?.profileManager,
|
||||
claim?.direct_manager_name,
|
||||
claim?.directManagerName
|
||||
) || '直属领导'
|
||||
}
|
||||
|
||||
function resolveProgressDisplayLabel(label, documentTypeCode, claim, approvalMeta) {
|
||||
if (
|
||||
documentTypeCode === DOCUMENT_TYPE_APPLICATION
|
||||
&& approvalMeta.key !== 'completed'
|
||||
&& normalizeText(label) === '直属领导审批'
|
||||
) {
|
||||
return `等待 ${resolveApplicationApproverName(claim)} 批复`
|
||||
}
|
||||
|
||||
return label
|
||||
}
|
||||
|
||||
function getRiskFlags(claim) {
|
||||
return Array.isArray(claim?.risk_flags_json) ? claim.risk_flags_json : []
|
||||
}
|
||||
@@ -488,6 +511,25 @@ function findLatestReturnEvent(claim) {
|
||||
)
|
||||
}
|
||||
|
||||
function findLatestApplicationReturnEvent(claim) {
|
||||
return getLatestEvent(
|
||||
getRiskFlags(claim).filter((flag) => {
|
||||
if (!flag || typeof flag !== 'object' || normalizeText(flag.source) !== 'manual_return') {
|
||||
return false
|
||||
}
|
||||
const eventType = normalizeText(flag.event_type || flag.eventType)
|
||||
const returnStage = normalizeText(flag.return_stage || flag.returnStage || flag.previous_approval_stage)
|
||||
const stageKey = normalizeText(flag.return_stage_key || flag.returnStageKey)
|
||||
return (
|
||||
eventType === 'expense_application_return'
|
||||
|| stageKey === 'direct_manager'
|
||||
|| returnStage.includes('直属领导')
|
||||
|| returnStage.includes('领导审批')
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
function buildProgressStepMeta(time, detail = '', title = '') {
|
||||
return {
|
||||
time,
|
||||
@@ -532,6 +574,28 @@ function buildCompletedStepMeta(claim, label) {
|
||||
const updatedAt = formatDateTime(claim?.updated_at)
|
||||
return buildProgressStepMeta('财务通过', updatedAt, `财务审批通过 ${updatedAt}`.trim())
|
||||
}
|
||||
|
||||
if (stepLabel === '直属领导审批') {
|
||||
const returnEvent = findLatestApplicationReturnEvent(claim)
|
||||
if (returnEvent) {
|
||||
const handledAt = formatDateTime(returnEvent.created_at || returnEvent.createdAt)
|
||||
return buildProgressStepMeta('已处理', handledAt, `直属领导已处理 ${handledAt}`.trim())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stepLabel === '退回') {
|
||||
const returnEvent = findLatestApplicationReturnEvent(claim) || findLatestReturnEvent(claim)
|
||||
if (returnEvent) {
|
||||
const operator = resolveDisplayName(
|
||||
returnEvent.operator,
|
||||
returnEvent.operator_name,
|
||||
returnEvent.operatorName,
|
||||
claim?.manager_name
|
||||
) || '直属领导'
|
||||
const returnedAt = formatDateTime(returnEvent.created_at || returnEvent.createdAt)
|
||||
return buildProgressStepMeta(`${operator}退回`, returnedAt, `${operator}退回 ${returnedAt}`.trim())
|
||||
}
|
||||
}
|
||||
|
||||
if (stepLabel === '归档入账') {
|
||||
@@ -574,13 +638,22 @@ function resolveCurrentStepStartedAt(claim, label) {
|
||||
|
||||
function buildProgressSteps(approvalMeta, workflowNode, claim = {}, options = {}) {
|
||||
const documentTypeCode = String(options.documentTypeCode || '').trim()
|
||||
const hasApplicationReturnStep = (
|
||||
documentTypeCode === DOCUMENT_TYPE_APPLICATION
|
||||
&& Boolean(findLatestApplicationReturnEvent(claim))
|
||||
&& approvalMeta.key === 'supplement'
|
||||
)
|
||||
const progressLabels =
|
||||
documentTypeCode === DOCUMENT_TYPE_APPLICATION
|
||||
? APPLICATION_PROGRESS_LABELS
|
||||
? hasApplicationReturnStep
|
||||
? ['创建申请', '直属领导审批', '退回', '待提交']
|
||||
: APPLICATION_PROGRESS_LABELS
|
||||
: REIMBURSEMENT_PROGRESS_LABELS
|
||||
const currentIndex =
|
||||
documentTypeCode === DOCUMENT_TYPE_APPLICATION
|
||||
? resolveApplicationProgressCurrentIndex(approvalMeta, workflowNode)
|
||||
? hasApplicationReturnStep
|
||||
? 3
|
||||
: resolveApplicationProgressCurrentIndex(approvalMeta, workflowNode)
|
||||
: resolveProgressCurrentIndex(approvalMeta, workflowNode)
|
||||
const currentTime =
|
||||
approvalMeta.key === 'completed'
|
||||
@@ -592,11 +665,13 @@ function buildProgressSteps(approvalMeta, workflowNode, claim = {}, options = {}
|
||||
: '进行中'
|
||||
|
||||
return progressLabels.map((label, index) => {
|
||||
const displayLabel = resolveProgressDisplayLabel(label, documentTypeCode, claim, approvalMeta)
|
||||
if (approvalMeta.key === 'completed') {
|
||||
const stepMeta = buildCompletedStepMeta(claim, label)
|
||||
return {
|
||||
index: index + 1,
|
||||
label,
|
||||
label: displayLabel,
|
||||
rawLabel: label,
|
||||
time: stepMeta.time,
|
||||
detail: stepMeta.detail,
|
||||
title: stepMeta.title,
|
||||
@@ -610,7 +685,8 @@ function buildProgressSteps(approvalMeta, workflowNode, claim = {}, options = {}
|
||||
const stepMeta = buildCompletedStepMeta(claim, label)
|
||||
return {
|
||||
index: index + 1,
|
||||
label,
|
||||
label: displayLabel,
|
||||
rawLabel: label,
|
||||
time: stepMeta.time,
|
||||
detail: stepMeta.detail,
|
||||
title: stepMeta.title,
|
||||
@@ -624,10 +700,11 @@ function buildProgressSteps(approvalMeta, workflowNode, claim = {}, options = {}
|
||||
const stayDuration = formatDurationFrom(resolveCurrentStepStartedAt(claim, label))
|
||||
return {
|
||||
index: index + 1,
|
||||
label,
|
||||
label: displayLabel,
|
||||
rawLabel: label,
|
||||
time: stayDuration ? `停留 ${stayDuration}` : currentTime,
|
||||
detail: '',
|
||||
title: stayDuration ? `当前${label}已停留 ${stayDuration}` : currentTime,
|
||||
title: stayDuration ? `当前${displayLabel}已停留 ${stayDuration}` : currentTime,
|
||||
done: false,
|
||||
active: true,
|
||||
current: true
|
||||
@@ -636,7 +713,8 @@ function buildProgressSteps(approvalMeta, workflowNode, claim = {}, options = {}
|
||||
|
||||
return {
|
||||
index: index + 1,
|
||||
label,
|
||||
label: displayLabel,
|
||||
rawLabel: label,
|
||||
time: '待处理',
|
||||
detail: '',
|
||||
title: '待处理',
|
||||
@@ -758,9 +836,13 @@ export function mapExpenseClaimToRequest(claim) {
|
||||
approvalTone: approvalMeta.tone,
|
||||
secondaryStatusLabel: isApplicationDocument ? '申请材料' : (typeCode === 'travel' ? '行程状态' : '票据状态'),
|
||||
secondaryStatusValue: isApplicationDocument
|
||||
? '已进入审批流程'
|
||||
? approvalMeta.key === 'supplement'
|
||||
? '领导已退回,待重新提交'
|
||||
: '已进入审批流程'
|
||||
: (invoiceCount > 0 ? `已关联 ${invoiceCount} 张票据` : '待上传票据'),
|
||||
secondaryStatusTone: isApplicationDocument ? 'success' : (invoiceCount > 0 ? 'success' : 'warning'),
|
||||
secondaryStatusTone: isApplicationDocument
|
||||
? approvalMeta.key === 'supplement' ? 'warning' : 'success'
|
||||
: (invoiceCount > 0 ? 'success' : 'warning'),
|
||||
riskSummary,
|
||||
attachmentSummary: isApplicationDocument ? '申请单' : (invoiceCount > 0 ? `${invoiceCount} 张票据` : '无'),
|
||||
expenseTableSummary: isApplicationDocument
|
||||
|
||||
Reference in New Issue
Block a user