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

背景

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

设计思路

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

?

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

审核节点:流程审批人审批流程

?

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

流程审核

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

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

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

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

流程配置

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

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

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

审核记录

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

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

数据库表设计

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

流程配置表:as_config

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

流程审批人表:as_node

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

审批记录表:as_process

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

程序开发

接下来就是程序开发了。

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

提交功能

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

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

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

Pair<String, String> pair = validateParamAndReturn(createParam);

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

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

//初始化层级:1
process.initLevel();

设置审核轮次

//设置审核次数
byte currentTimes = validateConfigAndReturnCurrentTimes(code, sheetNo);
process.setTimes(currentTimes);

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

?

初次审核:审核轮次为1

二审及以后的审核:上一次审核轮次 + 1

?

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

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

接下来设置审批人:

//设置审核人
String currentApproveMan = getCurrentApproveMan(code, 1);
process.setApproveMan(currentApproveMan);

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

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

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

然后创建流程记录

processMapper.insert(process);

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

//策略-提交进入流程的策略操作
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()方法(如下代码)。这样我们既做到了按需扩展,又不修改流程主代码(开发人员无需查看提交审批代码,只需按照说明文档扩展即可),安全简便。

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

审核功能

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

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

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

//1.更新当前节点
updateLatestProcess(createParam, latestInfo, currentDate);

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

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

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

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

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

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

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

返回的节点信息如上图。

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

createNextProcess(createParam, latestInfo, currentDate, result);

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

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

Byte latestLevel = latestInfo.getLevel();
byte nextLevel = (byte) (latestLevel + 1);
createNext.setLevel(nextLevel);

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

createNext.setStatus(Byte.valueOf(ApproveStatusEnum.IN.getValue()));

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

//策略模式,下个审批人需要做的事情
processStrategyApplicationService.nextProcessOperation(result);

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

@Override
public void nextProcessOperation(ProcessResult result) {
    //策略模式,比如通知下一环节审批人等
    ...
}

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

整体流程如下图:

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

审批流程梳理

来看看工程的目录结构:

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

主要方法在ProcessService类中。

测试

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 cloud@ksuyun.com 举报,一经查实,本站将立刻删除。
如若转载,请注明出处:https://www.daxuejiayuan.com/4237.html