当前位置: 首页 > news >正文

别再硬编码了!用两张表搞定OA多级审批(附加班申请完整SQL与事务处理)

通用审批引擎设计:用两张表实现企业级OA多级审批系统

当企业OA系统需要处理数十种不同类型的审批流程时,传统为每种表单单独开发审批逻辑的方式会带来巨大的维护成本。本文将介绍一种基于"审批主表+明细表"的通用审批引擎设计方案,通过松耦合的架构实现审批流程的复用,大幅降低开发复杂度。

1. 核心设计理念与表结构

1.1 为什么需要通用审批引擎

在传统OA系统中,每种审批表单(如请假、报销、采购等)通常都有自己独立的审批流程实现。这种方式会导致:

  • 代码重复:相似的审批逻辑在不同表单中重复实现
  • 维护困难:审批规则变更需要在多处修改
  • 扩展性差:新增审批类型需要从头开发

通用审批引擎通过将审批流程抽象为独立模块,实现与具体业务表单的解耦,提供统一的审批处理机制。

1.2 核心表结构设计

只需两张核心表即可支撑整个审批系统:

审批主表(AuditFlow)

字段名类型描述
FlowNoVARCHAR(50)审批编号(主键)
TitleNVARCHAR(50)审批标题
BusTypeVARCHAR(20)业务类型标识
AddUserNoVARCHAR(50)申请人
AddTimeDATETIME申请时间
ApproStatusINT审批状态

审批明细表(AuditFlowDetail)

字段名类型描述
IDINT自增主键
FlowNoVARCHAR(50)关联审批编号
AuditUserNoVARCHAR(50)审批人
AuditRemarkNVARCHAR(500)审批意见
AuditTimeDATETIME审批时间
AuditStatusINT审批状态

这种设计的关键在于:

  • 通过BusType字段区分不同业务类型
  • 通过FlowNo关联业务表与审批流程
  • 状态字段使用枚举值表示不同审批阶段

2. 审批流程的状态机设计

2.1 状态定义与流转

审批流程本质上是一个状态机,核心状态包括:

  • 待审:流程刚创建,等待第一级审批
  • 审批中:部分审批人已通过,流程继续
  • 通过:所有审批人同意
  • 驳回:任一审批人拒绝
  • 撤销:申请人主动撤回

状态流转规则:

stateDiagram-v2 [*] --> 待审 待审 --> 审批中: 第一级通过 审批中 --> 审批中: 中间级通过 审批中 --> 通过: 最后一级通过 待审 --> 驳回: 第一级拒绝 审批中 --> 驳回: 任一级拒绝 待审 --> 撤销: 申请人撤回 审批中 --> 撤销: 申请人撤回

2.2 多级审批的实现逻辑

明细表中的记录顺序决定了审批层级。处理逻辑如下:

  1. 创建审批流程时,按审批顺序插入明细记录
  2. 第一级审批人的状态设为"待我审批",后续设为"审核中"
  3. 当前审批人通过后:
    • 如果还有下一级,将下一级状态改为"待我审批"
    • 如果是最后一级,将主表状态改为"通过"
  4. 任一审批人拒绝时,立即终止流程,主表状态改为"驳回"

3. 与业务表的集成方案

3.1 松耦合设计模式

业务表只需包含FlowNo字段即可接入审批系统:

CREATE TABLE OverTimeAsk ( FlowNo VARCHAR(50) PRIMARY KEY, AddUserNo VARCHAR(20) NOT NULL, AddTime DATETIME NOT NULL, AskReason NVARCHAR(50) NOT NULL, -- 其他业务字段... FOREIGN KEY (FlowNo) REFERENCES AuditFlow(FlowNo) );

集成步骤:

  1. 业务表提交时生成唯一FlowNo
  2. AuditFlow插入主记录,BusType设为业务标识
  3. AuditFlowDetail插入审批人记录
  4. 业务表记录通过FlowNo关联审批流程

3.2 事务处理示例

以下是一个完整的加班申请提交事务处理SQL示例:

BEGIN TRANSACTION; DECLARE @FlowNo VARCHAR(50) = '2023050112300001'; DECLARE @BusType VARCHAR(20) = 'OverTimeAsk'; -- 插入业务表 INSERT INTO OverTimeAsk (FlowNo, AddUserNo, AddTime, AskReason, LeaveTimeFrom, LeaveTimeTo) VALUES (@FlowNo, 'U1001', GETDATE(), '项目紧急上线', '2023-05-01 19:00', '2023-05-01 22:00'); -- 插入审批主表 INSERT INTO AuditFlow (FlowNo, Title, BusType, AddUserNo, AddTime, ApproStatus) VALUES (@FlowNo, '张XX的加班申请', @BusType, 'U1001', GETDATE(), 1); -- 插入审批明细表(三级审批) INSERT INTO AuditFlowDetail (FlowNo, AuditUserNo, AuditStatus) VALUES (@FlowNo, 'U2001', 2), -- 主管(待我审批) (@FlowNo, 'U2002', 1), -- 部门经理(审核中) (@FlowNo, 'U2003', 1); -- 总监(审核中) COMMIT TRANSACTION;

注意:实际应用中应考虑添加异常处理和事务回滚逻辑。

4. 高级功能与优化建议

4.1 动态审批人配置

可以通过额外表实现审批人的动态配置:

审批配置表(AuditConfig)

字段名类型描述
IDINT自增主键
BusTypeVARCHAR(20)业务类型
DeptNoVARCHAR(20)部门编号
RoleNoVARCHAR(20)角色编号
AuditLevelINT审批层级

获取审批人逻辑:

-- 根据业务类型和申请人部门获取审批流程 SELECT ac.AuditLevel, ur.UserNo FROM AuditConfig ac JOIN UserRole ur ON ac.RoleNo = ur.RoleNo AND ac.DeptNo = ur.DeptNo WHERE ac.BusType = 'OverTimeAsk' ORDER BY ac.AuditLevel;

4.2 性能优化策略

  1. 索引优化

    CREATE INDEX IX_AuditFlow_Status ON AuditFlow(ApproStatus); CREATE INDEX IX_AuditFlowDetail_FlowNo ON AuditFlowDetail(FlowNo); CREATE INDEX IX_AuditFlowDetail_UserStatus ON AuditFlowDetail(AuditUserNo, AuditStatus);
  2. 查询优化

    • 分页查询待审批列表
    • 使用JOIN替代子查询
    • 考虑使用视图简化常用查询
  3. 缓存策略

    • 缓存常用审批配置
    • 缓存审批人信息
    • 考虑使用Redis缓存进行状态跟踪

4.3 扩展性设计

  1. 审批委托

    • 添加委托关系表
    • 查询审批人时检查是否有委托
  2. 审批条件分支

    • 根据业务数据动态调整审批流程
    • 实现条件审批规则引擎
  3. 审批超时处理

    • 添加超时时间字段
    • 定时任务检查超时审批
    • 自动升级或提醒

5. 实战中的经验分享

在实际项目中实现这套方案时,有几个关键点值得注意:

  1. 审批编号生成:建议使用"年月日时分+序号"的格式,如2023050112300001,既保证唯一性又带有时间信息。

  2. 状态同步:业务表的状态应与审批主表保持同步,可以通过触发器或应用逻辑实现。

  3. 历史记录:考虑添加审批历史表,记录完整的审批轨迹,便于审计和查询。

  4. 消息通知:审批状态变更时应实时通知相关人,可以集成消息队列实现异步通知。

  5. 测试覆盖:特别注意测试边界条件,如:

    • 单级审批流程
    • 多级全部通过
    • 中间级驳回
    • 第一级驳回
    • 申请人撤销等场景

这套方案已经在多个项目中得到验证,最高支持过12级审批流程,日均处理超过5000条审批记录,表现出良好的稳定性和扩展性。

http://www.jsqmd.com/news/629899/

相关文章:

  • OpenCore Configurator:终极黑苹果引导配置完全指南
  • hadoop+Spark+django基于Hive的公共交通系统数据分析(源码+文档+调试+可视化大屏)
  • 利用HFSS仿真优化圆极化微带天线的耦合馈电设计
  • 我的黑金FPGA下载器坏了,自己动手修好了!分享FT232HL方案维修全记录(附开源固件下载)
  • 告别工业风!Ostrakon-VL像素终端在便利店智能巡检中的真实应用
  • DM数据库命令行利器:dlsql实战技巧与高效场景解析
  • Typora橙心主题安装与个性化配置指南(附base.user.css文件下载)
  • STC8G1K08A三路PWM输出与占空比平滑渐变实战指南
  • CosyVoice2-0.5B语音合成性能压测:QPS/延迟/错误率全维度压力测试
  • 万字干货 | OpenClaw 进阶玩法大全:技能 / 多 Agent / 省钱 / 安全,+ 实战技巧一次学会傲
  • VSCode+Mermaid插件避坑指南:手把手教你画带条件分支的智能流程图
  • GLM技术复盘:篇论文深度解读智谱模型家族冶
  • MRIcroGL医学影像可视化:从零开始的3D渲染终极指南
  • OpenClaw人人养虾:仪表盘(Dashboard)
  • II启动间隔概念
  • 代谢组学数据分析终极指南:5分钟掌握MetaboAnalystR完整解决方案
  • VSG多机并联并网系统小信号建模:从理论推导到稳定性分析
  • 电脑C盘又爆红了?试试这个开源工具,3步让Windows重获新生!
  • C语言基础与灵毓秀-牧神-造相Z-Turbo模型交互开发
  • Vue Router:三种重定向redirect的实战场景与选择指南
  • 【若依(ruoyi)】深度解析主题样式配置与优化实践
  • Go语言的sync.Map.CompareAndSwap原子操作实现原理与性能特性
  • Linux网络编程核心API速查手册糖
  • 基于深度学习的YOLO BEV视角车辆目标检测 俯视图投影算法 目标检测在简易鸟瞰图及跟踪中的应用
  • 从Scapy到pcap:在SEED Ubuntu 20.04中实践数据包嗅探与欺骗的攻防演练
  • 如何用Python实现Android设备实时控制:py-scrcpy-client终极指南
  • 2025届学术党必备的六大AI学术工具推荐榜单
  • JAVA-SSM学习5 SpringMVC
  • 模组管理的智能革命:Nexus Mods App如何重塑游戏体验
  • YOLO-Master 与 YOLO 开始碳