前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >我开发了一套简单易用的审批流程引擎

我开发了一套简单易用的审批流程引擎

作者头像
Lvshen
发布2022-08-31 10:43:48
4.2K1
发布2022-08-31 10:43:48
举报

背景

最近的项目有涉及审批流程业务,为了不增加系统的复杂度,不想引入开源的流程引擎(市面上开源流程引擎功能都比较齐全,本项目的流程审批功能没有那么复杂),于是自己决定设计一套简单易用的审批流程来。

设计思路

审批流程相信大家都有了解。比如请假流程审批,办公物品领取申请流程审批,员工转正流程审批等等。无论是何种场景的审批流程,我们都可以抽象为「提交节点」「审批节点」

❝提交节点:流程提交人提交进入审批流程 审核节点:流程审批人审批流程 ❞

流程审核

因此我们需要写两个方法来执行审批流程。

但是在执行审批流程之前,需要配置审批流程。

由于审批结束时,如果审批不通过,还有可能从头开始进行审批。那么需要设置可重复审批次数。所以在审批流程配置时可增加字段可审批轮次times

流程配置

如上图,设计了一个流程配置主表,一个流程节点分表。它们是一对多的关系。

流程配置后就是流程执行后的审批记录了。

审核记录

审批记录主要存储审批信息,主要字段见上图。

以上的流程设计比较简单,没有考虑驳回上一环节,指定审批人等情况。有兴趣的童鞋可以思考思考。

数据库表设计

理清流程审批的思路,接下来就是创建数据库表了,这里主要创建3张表。

流程配置表:as_config

流程审批人表:as_node

审批记录表:as_process

程序开发

接下来就是程序开发了。

由于流程的配置就是简单的增删改查,这里就不作详细的介绍了。我们主要来说说「提交功能」「审批功能」

提交功能

在提交审批前需要提交哪些参数呢?如上图,流程编号,业务单据号,审批意见,审批状态,审批的业务模块,这些都是需要提交的参数。

提交审批时要做的第一件事就是参数的校验:

代码语言:javascript
复制
Pair<String, String> pair = validateParamAndReturn(createParam);

这里主要校验参数不能为空,然后我们返回重要的参数流程编号,业务单据号。

接下来需要将审核层级数初始化:

代码语言:javascript
复制
//初始化层级:1
process.initLevel();

设置审核轮次:

代码语言:javascript
复制
//设置审核次数
byte currentTimes = validateConfigAndReturnCurrentTimes(code, sheetNo);
process.setTimes(currentTimes);

validateConfigAndReturnCurrentTimes()会获取当前审核的轮次,这里的审核轮次计算逻辑为:

❝初次审核:审核轮次为1 二审及以后的审核:上一次审核轮次 + 1 ❞

当然还要校验审核配置是否已配置,审核轮次是否已用完:

接下来设置审批人:

代码语言:javascript
复制
//设置审核人
String currentApproveMan = getCurrentApproveMan(code, 1);
process.setApproveMan(currentApproveMan);

审批人从as_node表中获取,因为是提交节点,所以这里的层级为1,及获取的第一层级的审批人。

初始化流程状态为:审批中

代码语言:javascript
复制
//进入审核流程之前,创建的流程单状态默认为:审核中
process.setStatus(Byte.valueOf(ApproveStatusEnum.IN.getValue()));

然后创建流程记录

代码语言:javascript
复制
processMapper.insert(process);

到这里提交进入审批流程的功能已经结束,但是有的业务场景提交之后可能做一些额外的操作,比如通知给审批人,修改业务单据状态等。这里我用策略模式做了一个扩展,即提交后的功能。

代码语言:javascript
复制
//策略-提交进入流程的策略操作
ProcessResult result = new ProcessResult();
result.setCode(code);
result.setSheetNo(sheetNo);
result.setNextProcessId(String.valueOf(process.getId()));
result.setApproveMan(getCurrentAccount());
result.setNextApproveMan(currentApproveMan);
result.setModuleCode(createParam.getModuleCode());
processStrategyApplicationService.nextProcessOperation(result);

这里的代码是固定的,如果你是请假模块的流程,可能需要OA内部通知给审批人,这里你只需要写一个请假流程策略类去实现ProcessStrategy接口。然后实现nextProcessOperation()getModuleTypeStr()方法(如下代码)。这样我们既做到了按需扩展,又不修改流程主代码(开发人员无需查看提交审批代码,只需按照说明文档扩展即可),安全简便。

代码语言:javascript
复制
@Component
@Slf4j
public class HolidayProcessStrategy implements ProcessStrategy {
 @Override
    public void nextProcessOperation(ProcessResult result) {
        //策略模式,比如OA通知下一环节审批人等
    }
    
    @Override
    public String getModuleTypeStr() {
        //请假模块
        return HOLIDAY.getValue();
    }
}

审核功能

接下来就是审核功能了,和提交一样,需要校验流程编码和业务单号,然后就要获取最后一次审核记录:

通过获取到的最新已审批节点,我们就可以更新当前待审批的节点了。

代码语言:javascript
复制
//1.更新当前节点
updateLatestProcess(createParam, latestInfo, currentDate);

更新待审批节点是要注意必要的参数校验:

这里需要判断当前登录人是不是待审批环节的审批人,该节点是不是待审批节点。

更新了当前审批节点之后,就要创建下一环节待审批节点了。

在审批方法中同样可以返回节点信息,用于后续的操作。来看ProcessResult里面的信息:

返回的节点信息如上图。

我们来看看生成下一个待审批节点的方法:

代码语言:javascript
复制
createNextProcess(createParam, latestInfo, currentDate, result);

这里要注意,如果审批节点不通过,或者该审批节点为最后一个节点。则不应该创建节点。

创建节点中,需要增加审核层级

代码语言:javascript
复制
Byte latestLevel = latestInfo.getLevel();
byte nextLevel = (byte) (latestLevel + 1);
createNext.setLevel(nextLevel);

新创建的审核节点审核状态为审核中

代码语言:javascript
复制
createNext.setStatus(Byte.valueOf(ApproveStatusEnum.IN.getValue()));

同样我们在创建节点中,使用策略模式用于创建节点后的扩展。

代码语言:javascript
复制
//策略模式,下个审批人需要做的事情
processStrategyApplicationService.nextProcessOperation(result);

如果需要对下一个审核人发通知,可以写一个类实现ProcessStrategy,然后实现nextProcessOperation()方法。

代码语言:javascript
复制
@Override
public void nextProcessOperation(ProcessResult result) {
    //策略模式,比如通知下一环节审批人等
    ...
}

这样我们的审核功能完成了。

整体流程如下图:

审批流程梳理

来看看工程的目录结构:

主要方法在ProcessService类中。

测试

功能完成,就是紧张刺激的测试环节了,先测试submitProcess()方法,测试代码下:

提交审核功能中,只需要填入3个参数:流程编号,业务单据号,业务模块。流程编号一般可以通过业务模块查询,具体查询逻辑不在这里体现。

查询数据库发现新增一条待审批的节点。

如上图,可以看到当前环节审批人为:lvshen1,审批状态:0(待审批)。

接下来测试审批功能,测试代码如下:

如上代码,入参需要填入审批编码,业务单据号,审批意见,审批结果。代码中审批结果设置为审批通过。

来查询数据库,发现上一条数据已经审批,审批状态更改为1(审批通过),并填入了审批时间。

同时创建了一条新的待审批节点。

我们多模拟几条审批,数据库记录如下:

当然,如果当前登录人不是审批人,会报出如下异常。

如果当前节点是最后一个节点,则不会创建新的节点了。

这里做了控制,已审批的节点不能重新审批。

测试到这里,我们的功能已经实现,可满足一般业务需求了。

如果你对本文的功能感兴趣,欢迎和我探讨交流

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Lvshen的技术小屋 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 设计思路
  • 数据库表设计
  • 程序开发
    • 提交功能
      • 审核功能
      • 测试
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档