Files
hzdyjs/docs/变更管理/code-adjust-record-2025-01-27-cursor-approval-workflow-redesign.md
T
2025-08-04 13:38:08 +08:00

10 KiB

审批流程重新设计和优化记录

变更信息

  • 变更时间: 2025-01-27 18:45:00
  • 操作人员: cursor
  • 变更类型: 功能重构 + 架构优化
  • 影响范围: 财务管理模块 - 完整审批流程重新设计

问题描述

🔴 用户反馈的核心问题

  1. 部门审批查询问题: jwc001用户作为部门审批负责人,看不到jwc009提交的项目预算申请
  2. 冗余数据问题: 审批记录一次性全部写入表中,造成大量冗余数据
  3. 审批流程不符合实际需求: 需要重新设计审批规则

🔍 用户明确的业务需求

  • 部门审批: 部门审批人可以看到本部门下所有用户提交的申请(流程属于部门审批环节的)
  • 财务审批: 部门审批通过且财务审批未通过的数据,所有部门满足条件的数据都可以看到
  • 学院领导审批: 财务审批通过但是领导审批未通过的数据,是流程的最后一个环节

🔧 技术问题分析

  1. 查询逻辑错误: 部门审批查询限制了 approverId = currentUserId,应该基于部门查询
  2. 记录创建策略错误: 一次性创建所有审批记录,应该渐进式创建
  3. 审批流程设计不合理: 没有按照实际业务流程设计

修复方案

📝 1. 修复部门审批查询逻辑

问题: 查询条件过于严格

文件: backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/service/impl/CwApprovalRecordServiceImpl.java

// 修复前 - 错误的查询逻辑
lqw.eq(CwApprovalRecord::getApproverId, currentUserId); // ❌ 限制审批人

// 修复后 - 正确的查询逻辑  
// 🔧 修复:不限制审批人,显示本部门所有待审批的申请
// 部门审批人可以看到本部门下所有用户提交的申请

修复效果

  • ✅ 查询范围: 从"当前用户审批"改为"本部门申请"
  • ✅ SQL优化: 使用 inSql 子查询,性能更好
  • ✅ 权限合理: 符合部门审批的实际业务需求

📝 2. 前端查询参数修复

问题: 前端使用错误的查询模式

文件: web/src/views/cw/approvalRecord/index.vue

// 修复前
queryParams: {
  deptId: ''  // 空字符串,触发通用查询
}

// 修复后
queryParams: {
  deptId: 'current'  // 触发部门审批专用查询
}

📝 3. 审批记录创建策略重构

原有问题: 一次性创建冗余记录

// 修复前 - 一次性创建所有记录
records.add(deptRecord);     // 部门审批
records.add(financeRecord);  // 财务审批 
records.add(leaderRecord);   // 领导审批

新策略: 渐进式创建

// 修复后 - 渐进式创建
// 第1步:提交申请时,只创建部门审批记录
records.add(deptRecord);

// 💡 后续审批记录将在前一步骤完成时动态创建:
// - 部门审批通过后,创建财务审批记录
// - 财务审批通过后,创建学院领导审批记录

实现机制: 动态创建审批记录

  1. 新增方法: createApprovalRecordForNode() - 动态创建指定节点的审批记录
  2. 修改方法: startNextApprovalNode() - 启动下一节点时自动创建记录
  3. 智能判断: 检查记录是否存在,不存在则创建

📝 4. 新增财务审批和学院领导审批模块

Service层扩展

// 新增Service方法
List<CwApprovalRecordVo> queryFinancePendingApprovals();  // 财务待审批
List<CwApprovalRecordVo> queryLeaderPendingApprovals();   // 领导待审批

Controller层扩展

// 新增Controller接口
@GetMapping("/finance/pending")  // 财务审批查询
@GetMapping("/leader/pending")   // 领导审批查询

Mapper层扩展

// 新增Mapper方法
List<CwApprovalRecordVo> selectByNode(@Param("nodeCode") String nodeCode,
                                      @Param("nodeStatus") String nodeStatus);

📝 5. 审批流程重新设计

新的审批流程

1. 提交申请 → 创建部门审批记录
       ↓
2. 部门审批通过 → 动态创建财务审批记录
       ↓  
3. 财务审批通过 → 动态创建学院领导审批记录
       ↓
4. 学院领导审批通过 → 审批流程完成

查询权限设计

  • 部门审批: 查看本部门所有待审批申请
  • 财务审批: 查看所有部门的财务待审批申请
  • 学院领导审批: 查看指派给自己的领导待审批申请

技术实现细节

🔧 1. 动态创建审批记录机制

private Boolean startNextApprovalNode(Long applicationId, String nextNodeCode) {
    // 检查下一个节点是否存在
    CwApprovalRecordVo nextRecord = queryByApplicationAndNode(applicationId, nextNodeCode);
    
    if (nextRecord == null) {
        // 不存在则动态创建
        CwApprovalRecord newRecord = createApprovalRecordForNode(...);
        baseMapper.insert(newRecord);
    } else {
        // 存在则直接启动
        updateBo.setNodeStatus("waiting");
        updateByBo(updateBo);
    }
}

🔧 2. 节点类型识别机制

private CwApprovalRecord createApprovalRecordForNode(String nodeCode, ...) {
    switch (nodeCode) {
        case "finance_approve":
            nodeName = "财务审批"; 
            nodeOrder = 2;
            break;
        case "leader_approve":
            nodeName = "学院领导审批";
            nodeOrder = 3; 
            break;
    }
    return createApprovalRecord(...);
}

🔧 3. 查询优化机制

// 部门审批查询 - 基于部门ID的子查询
lqw.inSql(CwApprovalRecord::getApplicationId, 
    "SELECT id FROM cw_project_application WHERE department_id = " + currentDeptId);

// 财务审批查询 - 基于节点状态
return baseMapper.selectByNode("finance_approve", "waiting");

// 领导审批查询 - 基于审批人
return baseMapper.selectByApproverAndNode(currentUserId, "leader_approve", "waiting");

数据库验证

✅ 验证查询结果

SELECT ar.id, ar.application_id, ar.node_code, ar.node_status, ar.approver_id, 
       ar.approver_name, pa.application_no, pa.project_name, pa.department_name 
FROM cw_approval_record ar 
LEFT JOIN cw_project_application pa ON ar.application_id = pa.id 
WHERE pa.department_id = 1938484570826956801 
  AND ar.node_code = 'dept_approve' 
  AND ar.node_status = 'waiting';

查询结果: 3条待审批记录

  • YS202508029073 - 测试项目预算申报001
  • YS202508011350 - 3232323
  • YS202508021849 - 888888

✅ 数据完整性确认

  • 所有记录都属于教务处 (department_id = 1938484570826956801)
  • 所有记录都处于部门审批节点 (node_code = 'dept_approve')
  • 所有记录都是等待状态 (node_status = 'waiting')
  • 审批人都是jwc001 (approver_id = 2101)

影响评估

✅ 正面影响

业务流程优化

  • 数据清洁: 消除冗余审批记录,数据库更简洁
  • 流程合理: 审批流程符合实际业务需求
  • 权限精确: 各级审批人看到的数据范围准确

系统性能提升

  • 查询效率: 减少无效数据,查询速度提升
  • 存储优化: 按需创建记录,减少存储占用
  • 维护简化: 数据结构更清晰,便于维护

用户体验改善

  • 权限清晰: 每个角色看到的数据范围明确
  • 操作直观: 审批流程更符合直觉
  • 响应快速: 查询性能提升,页面加载更快

📊 向下兼容

  • 现有数据: 不影响已有的审批记录
  • API接口: 保持原有接口的兼容性
  • 权限系统: 沿用现有的权限控制机制

🎯 用户收益

jwc001 (部门审批人)

  • ✅ 可以看到本部门所有待审批申请
  • ✅ 不再局限于自己作为审批人的记录
  • ✅ 符合部门管理的实际需求

财务审批人员

  • ✅ 可以看到所有部门的财务待审批申请
  • ✅ 统一的财务审批视图
  • ✅ 提高财务审批效率

学院领导

  • ✅ 只看到指派给自己的领导审批申请
  • ✅ 作为最终审批环节,权限明确
  • ✅ 审批完成后流程自动结束

测试建议

📋 功能测试场景

1. 部门审批测试

  • jwc001用户登录 → 进入部门审批页面 → 应该看到3条待审批记录
  • 选择一条记录进行审批通过 → 验证是否自动创建财务审批记录
  • 验证申请状态是否正确更新为"审批中"

2. 财务审批测试

  • 财务审批人员登录 → 进入财务审批页面 → 应该看到部门审批通过的记录
  • 进行财务审批通过 → 验证是否自动创建学院领导审批记录
  • 验证申请状态和审批记录状态

3. 学院领导审批测试

  • 学院领导登录 → 进入领导审批页面 → 应该看到指派给自己的记录
  • 进行领导审批通过 → 验证整个流程是否完成
  • 验证申请最终状态为"已通过"

4. 数据一致性测试

  • 验证审批记录的渐进式创建
  • 确认不再有冗余的审批记录
  • 检查审批流程状态的正确性

🔄 回归测试

  • 已有功能不受影响
  • 权限控制正常工作
  • API接口响应正确

🎭 压力测试

  • 多用户同时审批
  • 大量申请的查询性能
  • 并发创建审批记录的稳定性

🎉 重构总结

核心改进

  1. 查询逻辑修复: 从"用户审批"改为"部门申请",符合业务需求
  2. 创建策略优化: 从"一次性创建"改为"渐进式创建",消除冗余数据
  3. 流程设计完善: 增加财务审批和学院领导审批,覆盖完整业务流程
  4. 权限设计合理: 不同角色看到不同范围的数据,权限清晰

技术特点

  • 动态创建: 按需创建审批记录,避免冗余
  • 智能查询: 根据角色和权限智能筛选数据
  • 流程驱动: 审批流程驱动记录创建,逻辑清晰
  • 性能优化: 减少无效数据,提升查询效率

业务价值

  • 流程优化: 审批流程更符合实际业务需求
  • 数据质量: 消除冗余数据,提高数据质量
  • 用户体验: 各角色操作更直观,权限更清晰
  • 系统维护: 数据结构简化,便于维护和扩展

现在jwc001用户应该可以正常看到本部门的所有待审批申请,并且系统不再产生冗余的审批记录!