自定义简易工作流

使用背景:

        如果你觉得使用activity工作流很繁琐,或者觉得接口对接很麻烦,那么你需要一套自定义的简易工作流,它能实现工作流已有的核心部分功能,自己数据库里面创建工作流表,可以横向扩展,你想审批就审批,想随时驳回就驳回,日志自己记录。。。。一切自己动手,那么直接上代码:这里的代码是部分代码,里面缺失的部分自行处理,但关注的还是这个实现逻辑,只有了解的实现逻辑用起来才会更顺手。

        简单说明一下:枚举控制流程模板,然后自己建表实现工作流相关的功能;

建表语句:

工作流程信息表flow_info:
flow_id:流程id
flow_name:流程名称
flow_node_code_path:流程路径(节点code集合,逗号拼接)
flow_status:当前流程状态[1.发起,2.审批中,3.审批结束,4.被驳回,5.挂起]
..........

工作流程信息表flow_node:
flow_node_id:流程节点id
flow_node_code:流程节点code
flow_node_name:流程节点名称
flow_info_id:工作流程id
flow_node_approve_users:流程节点审批人集合,逗号隔开
flow_approve_param:流程节点审批条件
flow_node_status:流程节点状态[1.开始,2.审批中,3.审批完成]
..........

工作流程信息表flow_record:
flow_record_id:流程日志id
flow_info_id:工作流程id
flow_node_code:流程节点code
flow_record_type:流程日志操作类型[1.发起流程类型,2.审批类型,3.驳回类型,4.流程挂起类型]
flow_record_content:流程日志内容
..........

模板类:这里是核心模板流程图,里面配置了你这个流程图所有的节点信息,和节点的信息和参数配置,并在自己的init方法中设置好网关(判断条件的节点条件参数);

@Slf4j
public enum ApproveFlowEnum implements IWfNodeBaseEnum {

    START("approve_01", "流程节点开始", null, "approve_02", null, "start"),
    HEAD_APPROVE("approve_02", "组长审批", 1, "approve_03", null, "node"),
    PERSONAL_APPROVE("approve_03", "人事审批", 1, "approve_04", null, "node"),
    PRESIDENT_APPROVE("approve_04", "总经理审批", 1, "approve_05", null, "node"),
    END("approve_05", "流程节点结束", 1, null, null, "end");

    private final ApproveFlowEnum[] approveFlowEnums = ApproveFlowEnum.values();
    private Map<String, ApproveFlowEnum> flowCodeEnumMap;
    /**
     * nodeCode:当前节点code(唯一)
     * nodeName:当前节点名称
     * nodeApproveParam:设置当前节点需要达到几个人审批才算通过
     * nextNodeCode:下一个节点的code
     * nextNodeMap:下一个节点的信息(这里是记录有判断条件的下一个节点信息,在PostConstruct中去配置,或者在构造方法中去设置)
     * nodeDesc:当前节点标识(主要表示用于起点和终点的判断,当然后期也可以维护成很多判断条件,但是终点的end标记很重要,用于判断该流程是否已经结束)
     */
    private String nodeCode;
    private String nodeName;
    private Integer nodeApproveParam;
    private String nextNodeCode;
    private Map<String, String> nextNodeMap;
    private String nodeDesc;

    ApproveFlowEnum(String nodeCode, String nodeName, Integer nodeApproveParam, String nextNodeCode, Map<String, String> nextNodeMap,
                    String nodeDesc) {
        this.nodeCode = nodeCode;
        this.nodeName = nodeName;
        this.nodeApproveParam = nodeApproveParam;
        this.nextNodeCode = nextNodeCode;
        this.nextNodeMap = nextNodeMap;
        this.nodeDesc = nodeDesc;
    }
/**
     * 核心配置(这块内容可以在PostConstruct配置,也可以在构造函数中设置)
     * 用于构建流程控制语句的流转规则
     * 如果是一条直线简单流程,那么这里不需要设置(这里只配置流程判断条件情况)
     * 某个节点的nextNodeMap的条件语句(类似于在画流程图的时候网关设置判断流转参数)
     */
    @PostConstruct
    public void init() {
        for (ApproveFlowEnum approveFlowEnum : approveFlowEnums) {
            //这里手动设置有需要判断的节点参数设置(类似于网关节点)
            if (ObjectUtils.isEmpty(approveFlowEnum.getNextNodeCode())) {
                if ("approve_02".equals(approveFlowEnum.getNodeCode())) {
                    Map<String, String> map = new HashMap<>();
                    map.put("1", "approve_02");
                    approveFlowEnum.setNextNodeMap(map);
                }
            }
        }
        flowCodeEnumMap = Arrays.stream(approveFlowEnums)
                .collect(Collectors.toMap(ApproveFlowEnum::getNodeCode, Function.identity()));
        log.info("审批工作流初始化完成++++++++++++++++++++++++++");
    }

    @Override
    public IWfNodeBaseEnum getEnumByNodeCode(String nodeCode) {
        return flowCodeEnumMap.get(nodeCode);
    }

    @Override
    public List<IWfNodeBaseEnum> getAllEnumInfo() {
        ApproveFlowEnum[] approveFlowEnums = ApproveFlowEnum.values();
        return Arrays.asList(approveFlowEnums);
    }

    @Override
    public String getNodeCode() {
        return nodeCode;
    }

    public void setNodeCode(String nodeCode) {
        this.nodeCode = nodeCode;
    }

    @Override
    public String getNodeName() {
        return nodeName;
    }

    public void setNodeName(String nodeName) {
        this.nodeName = nodeName;
    }

    @Override
    public String getNodeDesc() {
        return nodeDesc;
    }

    @Override
    public Integer getNodeApproveParam() {
        return nodeApproveParam;
    }

    public void setNodeApproveParam(Integer nodeApproveParam) {
        this.nodeApproveParam = nodeApproveParam;
    }

    @Override
    public String getNextNodeCode(String nodeCode) {
        return flowCodeEnumMap.get(nodeCode).getNodeCode();
    }

    @Override
    public String getNextNodeCode() {
        return nextNodeCode;
    }

    public void setNextNodeCode(String nextNodeCode) {
        this.nextNodeCode = nextNodeCode;
    }

    @Override
    public Map<String, String> getNextNodeMap() {
        return nextNodeMap;
    }

    public void setNextNodeMap(Map<String, String> nextNodeMap) {
        this.nextNodeMap = nextNodeMap;
    }

    public void setNodeDesc(String nodeDesc) {
        this.nodeDesc = nodeDesc;
    }

}

父级模板模式的借口限定借口类:主要定义工作流中涉及到的方法,比如初始化、驳回、审批、挂起等等场景方法,其数据信息都在对应的子类中:

/**
 * 工作流包装类
 *
 * @author IT701820-tp
 */
public interface IWfNodeBaseEnum {

    /**
     * 获取初始化第一个节点信息
     *
     * @param nodeCode 节点code
     * @return 枚举信息
     */
    IWfNodeBaseEnum getEnumByNodeCode(String nodeCode);

    /**
     * 获取节点名称
     *
     * @return 节点值
     */
    String getNodeName();

    /**
     * 获取节点审批条件参数
     *
     * @return 参数值(满足几个人才算审批通过)
     */
    Integer getNodeApproveParam();

    /**
     * 获取下一节点code
     *
     * @param nodeCode 当前节点
     * @return 节点值
     */
    String getNextNodeCode(String nodeCode);

    /**
     * 获取下一节点枚举信息
     *
     * @param nodeCode 当前节点
     * @param param    有网关参数的时候的参数配置(可以为null)
     * @return 枚举信息值
     */
    default IWfNodeBaseEnum getNextNodeEnum(String nodeCode, String param) {
        List<IWfNodeBaseEnum> allEnumInfo = getAllEnumInfo();
        Map<String, IWfNodeBaseEnum> flowCodeEnumMap = allEnumInfo.stream()
                .collect(Collectors.toMap(IWfNodeBaseEnum::getNodeCode, Function.identity()));
        IWfNodeBaseEnum nextNodeEnum = getNextNodeEnum(nodeCode);
        if (!ObjectUtils.isEmpty(nextNodeEnum)) {
            return nextNodeEnum;
        }
        //获取当前节点信息
        IWfNodeBaseEnum approveFlowEnum = flowCodeEnumMap.get(nodeCode);
        Map<String, String> nextNodeMap = approveFlowEnum.getNextNodeMap();
        String nextNodeCode = nextNodeMap.get(param);
        return flowCodeEnumMap.get(nextNodeCode);
    }

    /**
     * 获取所有枚举信息
     *
     * @return 枚举信息
     */
    List<IWfNodeBaseEnum> getAllEnumInfo();

    /**
     * 获取节点code
     *
     * @return 节点值
     */
    String getNodeCode();

    /**
     * 获取下一节点枚举信息(没有参数的获取方式,直接流转到下一个流程)
     *
     * @param nodeCode 当前节点
     * @return 枚举信息值
     */
    default IWfNodeBaseEnum getNextNodeEnum(String nodeCode) {
        List<IWfNodeBaseEnum> allEnumInfo = getAllEnumInfo();
        Map<String, IWfNodeBaseEnum> flowCodeEnumMap = allEnumInfo.stream()
                .collect(Collectors.toMap(IWfNodeBaseEnum::getNodeCode, Function.identity()));
        //获取当前节点信息
        IWfNodeBaseEnum approveFlowEnum = flowCodeEnumMap.get(nodeCode);
        String nextNodeCode = approveFlowEnum.getNextNodeCode();
        if (!ObjectUtils.isEmpty(nextNodeCode)) {
            return flowCodeEnumMap.get(nextNodeCode);
        }
        return null;
    }
/**
     * 获取当前枚举的下一个code(带有条件的)
     *
     * @return 节点值
     */
    Map<String, String> getNextNodeMap();

    /**
     * 获取当前枚举的下一个code
     *
     * @return 节点值
     */
    String getNextNodeCode();

    /**
     * 获取初始化第一个节点信息
     *
     * @return 枚举信息
     */
    default IWfNodeBaseEnum getInitEnum() {
        List<IWfNodeBaseEnum> allEnumInfo = getAllEnumInfo();
        for (IWfNodeBaseEnum iWfNodeBaseEnum : allEnumInfo) {
            if ("start".equals(iWfNodeBaseEnum.getNodeDesc())) {
                return iWfNodeBaseEnum;
            }
        }
        return null;
    }

    /**
     * 获取节点标志(开始节点,审批节点,结束节点)
     *
     * @return 节点标志值
     */
    String getNodeDesc();

}

具体的业务实现类:

/**
 * 工作流操作业务类
 *
 * @author IT701820-tp
 */
@Service
@Slf4j
public class FlowInfoService {

    @Resource
    FlowInfoMapper flowInfoMapper;

    @Resource
    FlowNodeMapper flowNodeMapper;

    @Resource
    FlowRecordMapper flowRecordMapper;

    @Resource
    PtlTodoTaskMapper ptlTodoTaskMapper;

    @Resource
    SysUserMapper sysUserMapper;

    @Resource
    SysYhtUserSyncMapper sysYhtUserSyncMapper;

    @Resource
    private ApiService apiService;

    @Value("${yht.sys.approve.schema}")
    private String schema;

    /**
     * 1.新增flowInfo表信息(开始状态);
     * 2.新增flowNodeInfo表信息,把该流程对应的所有节点信息初始化表中,并设置第一个节点的审批人信息和状态,和下一个节点发送代办信息;
     * 3.新增flowRecordInfo表信息,新增一条流程开始日志。
     *
     * @param approveFlowDto: flowName 流程名称
     *                        userList 下个节点的审批人集合
     *                        nextAction 一事通代办的跳转页面地址
     *                        recordContent 流程节点的日志信息
     */
    @Transactional(rollbackFor = Exception.class)
    public FlowInfoEntity initFlow(Class<IWfNodeBaseEnum> enumClass, ApproveFlowDto approveFlowDto)
            throws InstantiationException, IllegalAccessException {
        //保存流程信息
        IWfNodeBaseEnum iWfNodeBaseEnum = enumClass.newInstance();
        IWfNodeBaseEnum initEnum = iWfNodeBaseEnum.getInitEnum();
        FlowInfoEntity flowInfoEntity = new FlowInfoEntity();
        flowInfoEntity.setFlowId(UUIDUtil.getUUIDKey());
        flowInfoEntity.setFlowName(approveFlowDto.getFlowName());
        flowInfoEntity.setFlowNodeCodePath(initEnum.getNodeCode());
        flowInfoEntity.setFlowStatus(FlowConstants.FLOW_BEGIN);
        flowInfoEntity.setCreatorId("370124");
        flowInfoEntity.setCreatedTime(new Date());
        flowInfoMapper.insertSelective(flowInfoEntity);
        //保存流程节点信息
        List<FlowNodeEntity> nodeEntityList = new ArrayList<>();
        List<IWfNodeBaseEnum> wfNodeBaseEnumList = iWfNodeBaseEnum.getAllEnumInfo();
        String firstNodeCode = null;
        for (IWfNodeBaseEnum wfNodeBaseEnum : wfNodeBaseEnumList) {
            FlowNodeEntity flowNodeEntity = new FlowNodeEntity();
            flowNodeEntity.setFlowNodeId(UUIDUtil.getUUIDKey());
            flowNodeEntity.setFlowNodeCode(wfNodeBaseEnum.getNodeCode());
            flowNodeEntity.setFlowInfoId(flowInfoEntity.getFlowId());
            if (FlowConstants.FLOW_NODE_STATUS_START.equals(wfNodeBaseEnum.getNodeDesc())) {
                firstNodeCode = wfNodeBaseEnum.getNodeCode();
            }
//只针对下一个节点设置发起待办
            if (!ObjectUtils.isEmpty(firstNodeCode)) {
                String nextNodeCode = wfNodeBaseEnum.getNextNodeEnum(firstNodeCode).getNodeCode();
                if (nextNodeCode.equals(wfNodeBaseEnum.getNodeCode())) {
                    //仅限于初始化第一个节点的审批人
                    flowNodeEntity.setFlowNodeApproveUsers(StringUtils.join(approveFlowDto.getUserList(), ","));
                    //将这些审批人userList发送待办
                    executeTodoTask(approveFlowDto.getUserList(), flowInfoEntity, wfNodeBaseEnum, approveFlowDto.getNextAction());
                    firstNodeCode = null;
                }
            }
            flowNodeEntity.setFlowNodeName(wfNodeBaseEnum.getNodeName());
            flowNodeEntity.setFlowApproveParam(wfNodeBaseEnum.getNodeApproveParam());
            //只对开始的节点修改状态为已完成
            if (FlowConstants.FLOW_NODE_STATUS_START.equals(wfNodeBaseEnum.getNodeDesc())) {
                flowNodeEntity.setFlowNodeStatus(FlowConstants.FLOW_NODE_DONE);
            } else {
                flowNodeEntity.setFlowNodeStatus(FlowConstants.FLOW_NODE_APPROVE);
            }
            nodeEntityList.add(flowNodeEntity);
        }
        flowNodeMapper.insertList(nodeEntityList);
        //记录流程日志
        FlowRecordEntity flowRecord = new FlowRecordEntity();
        flowRecord.setFlowRecordId(UUIDUtil.getUUIDKey());
        flowRecord.setFlowInfoId(flowInfoEntity.getFlowId());
        List<IWfNodeBaseEnum> iWfNodeBaseEnumList = wfNodeBaseEnumList.stream()
                .filter(s -> FlowConstants.FLOW_NODE_STATUS_START.equals(s.getNodeDesc())).collect(Collectors.toList());
        flowRecord.setFlowNodeCode(iWfNodeBaseEnumList.get(0).getNodeCode());
        flowRecord.setFlowRecordType(FlowConstants.FLOW_RECORD_START);
        flowRecord.setFlowRecordContent(approveFlowDto.getRecordContent());
        flowRecord.setCreatorId("370124");
        flowRecord.setCreatedTime(new Date());
        flowRecordMapper.insert(flowRecord);
        return flowInfoEntity;
    }
/**
     * 发布代办信息
     */
    private void executeTodoTask(List<String> userList, FlowInfoEntity flowInfoEntity, IWfNodeBaseEnum wfNodeBaseEnum, String nextAction) {
        List<PtlTodoTaskEntity> ptlTodoTaskEntities = new ArrayList<>();
        List<YstTaskEntity> ystTaskEntityList = new ArrayList<>();
        for (String user : userList) {
            PtlTodoTaskEntity nextPtlTodoTaskEntity = new PtlTodoTaskEntity();
            nextPtlTodoTaskEntity.setTodoTaskId(UUIDUtil.getUUIDKey());
            nextPtlTodoTaskEntity.setNodeId(wfNodeBaseEnum.getNodeCode());
            nextPtlTodoTaskEntity.setBusModule(FlowConstants.FLOW_MODULE);
            nextPtlTodoTaskEntity.setBusId(flowInfoEntity.getFlowId());
            nextPtlTodoTaskEntity.setBusName(flowInfoEntity.getFlowName());
            nextPtlTodoTaskEntity.setHandleUserId(user);
            SysUserInfoDto userInfoDto = sysUserMapper.getUserInfoByUserId(user);
            if (!ObjectUtils.isEmpty(userInfoDto)) {
                nextPtlTodoTaskEntity.setHandleUserDeptId(userInfoDto.getOrgId());
            }
            nextPtlTodoTaskEntity.setCreatorId("370124");
            nextPtlTodoTaskEntity.setCreatedTime(new Date());
            ptlTodoTaskEntities.add(nextPtlTodoTaskEntity);
            //同步发送一号通代办
            YstTaskEntity ystTaskEntity = new YstTaskEntity();
            ystTaskEntity.setSysSchema(schema);
            ystTaskEntity.setNextAction(nextAction);
            ystTaskEntity.setRefKey(flowInfoEntity.getFlowId());
            ystTaskEntity.setTitle(flowInfoEntity.getFlowName() + "-");
            ystTaskEntity.setTaskType(wfNodeBaseEnum.getNodeCode());
            SysYhtUserSyncEntity sysYhtUserSyncEntity = sysYhtUserSyncMapper.selectOpenId(user);
            ystTaskEntity.setUserId(sysYhtUserSyncEntity.getOpenId());
            ystTaskEntity.setCreatorId(flowInfoEntity.getCreatorId());
            ystTaskEntityList.add(ystTaskEntity);
        }
        if (!CollectionUtils.isEmpty(ystTaskEntityList)) {
            List<List<YstTaskEntity>> device = com.cmbchina.itrisk.base.utils.CollectionUtils.device(ystTaskEntityList, 20);
            device.forEach(list -> apiService.syncYhtTodoTaskBatchCreat(list));
        }
        ptlTodoTaskMapper.insertBatch(ptlTodoTaskEntities);
    }

    /**
     * 审批一个流程
     * 1.根据当前流程,添加流程的节点路径,修改流程的状态;
     * 2.如果该节点审批完成,设置流程节点的关联人信息
     * 3.记录流程日志
     * 1.如果查询到审批通过人数达到节点审批条件值
     * 1>修改当前节点的审批状态;
     * 2>发送下一批人的代办任务
     * 4.如果流程审批结束,修改该工作流为已删除(成为历史数据),当前节点所有待办任务删除,并给下个节点发布待办任务
     *
     * @param approveFlowDto: nextAction:待办的跳转地址信息
     *                        flowInfoId:该流程信息id
     *                        flowNodeCode:当前审批的节点
     *                        param:审批的节点参数(可以为null,null的情况就是没有条件参数,直接往下走)
     *                        userList:下一次审批的人员列表集合
     * @return Integer 1:审批完成;2:还在审批中
     */
    @Transactional(rollbackFor = Exception.class)
    public Integer executeFlow(Class<IWfNodeBaseEnum> enumClass, ApproveFlowDto approveFlowDto)
            throws InstantiationException, IllegalAccessException {
        String flowInfoId = approveFlowDto.getFlowId();
        String flowNodeCode = approveFlowDto.getFlowNodeCode();
        List<String> userList = approveFlowDto.getUserList();
        if (ObjectUtils.isEmpty(flowInfoId)) {
            throw new BusinessException("审批流程id不能为空!!!");
        }
        if (ObjectUtils.isEmpty(flowNodeCode)) {
            throw new BusinessException("审批流程节点code不能为空!!!");
        }
        if (CollectionUtils.isEmpty(approveFlowDto.getUserList())) {
            throw new BusinessException("审批人不能为空!!!");
        }
        FlowInfoEntity flowInfoEntity = flowInfoMapper.selectByPrimaryKey(flowInfoId);
        if (FlowConstants.FLOW_PENDING.equals(flowInfoEntity.getFlowStatus())) {
            throw new BusinessException("该流程已处于挂起状态,请解除挂起之后再发起审批");
        }
        //1.根据当前流程,添加流程的节点路径,修改流程的状态;
        IWfNodeBaseEnum iWfNodeBaseEnum = enumClass.newInstance();
        //记录流程日志(先记日志,后续需要计算日志的值)
        FlowRecordEntity flowRecord = new FlowRecordEntity();
        flowRecord.setFlowRecordId(UUIDUtil.getUUIDKey());
        flowRecord.setFlowInfoId(flowInfoEntity.getFlowId());
        flowRecord.setFlowNodeCode(flowNodeCode);
        flowRecord.setFlowRecordType(FlowConstants.FLOW_RECORD_START);
        flowRecord.setFlowRecordContent(approveFlowDto.getRecordContent());
        flowRecord.setCreatorId("370124");
        flowRecord.setCreatedTime(new Date());
        flowRecordMapper.insert(flowRecord);

        //判断当前节点是否有审批人数量限制(用该参数和审批日志中的数量进行对比)
        IWfNodeBaseEnum nodeEnum = iWfNodeBaseEnum.getEnumByNodeCode(flowNodeCode);
        Integer nodeApproveParam = nodeEnum.getNodeApproveParam();
        //表示当前节点还在审批阶段,直接返回不需要后续操作,参数从日志中查询同意审批个数
        //获取下一个节点信息
        IWfNodeBaseEnum nextNodeEnum = iWfNodeBaseEnum.getNextNodeEnum(flowNodeCode, approveFlowDto.getParam());
        FlowRecordEntity record = new FlowRecordEntity();
        record.setFlowInfoId(flowInfoId);
        record.setFlowNodeCode(flowNodeCode);
        List<FlowRecordEntity> flowRecordList = flowRecordMapper.selectByParam(record);
if (nodeApproveParam > flowRecordList.size()) {
            String flowNodeCodePath = flowInfoEntity.getFlowNodeCodePath();
            List<String> nodeCodePathList = Arrays.asList(flowNodeCodePath.split(","));
            if (!nodeCodePathList.contains(flowNodeCode)) {
                flowInfoEntity.setFlowNodeCodePath(flowNodeCodePath + "," + flowNodeCode);
                //该情况表示流程还未结束(不需要发待办)
                if (!FlowConstants.FLOW_NODE_STATUS_END.equals(nextNodeEnum.getNodeDesc())) {
                    flowInfoEntity.setFlowStatus(FlowConstants.FLOW_APPROVE);
                }
                flowInfoMapper.updateByPrimaryKeySelective(flowInfoEntity);
            }
            return 2;
        }
        //2.当前节点已经审批完成,设置流程节点的关联人信息
        IWfNodeBaseEnum enumByNodeCode = iWfNodeBaseEnum.getEnumByNodeCode(flowNodeCode);
        FlowNodeEntity flowNodeEntity = new FlowNodeEntity();
        flowNodeEntity.setFlowInfoId(flowInfoEntity.getFlowId());
        flowNodeEntity.setFlowNodeCode(enumByNodeCode.getNodeCode());
        FlowNodeEntity nodeEntity = flowNodeMapper.selectByEntity(flowNodeEntity);
        nodeEntity.setFlowNodeStatus(FlowConstants.FLOW_NODE_DONE);
        nodeEntity.setLastModifierId("370124");
        nodeEntity.setLastModifiedTime(new Date());
        flowNodeMapper.updateByPrimaryKey(nodeEntity);
        //如果当前节点审批都完成,删除当前节点所有的待办任务(待办转已办)
        ptlTodoTaskMapper.batchDeleteByBusIds(Collections.singletonList(nodeEntity.getFlowNodeId()));

        //判断该流程是否结束(下一个节点是否是end标记)
        //重新获取该流程
        FlowInfoEntity flowInfo = flowInfoMapper.selectByPrimaryKey(flowInfoId);
        String flowNodeCodePath = flowInfo.getFlowNodeCodePath();
        if (FlowConstants.FLOW_NODE_STATUS_END.equals(nextNodeEnum.getNodeDesc())) {
            if (FlowConstants.FLOW_NODE_STATUS_END.equals(nextNodeEnum.getNodeDesc())) {
                flowInfo.setFlowStatus(FlowConstants.FLOW_END);
                flowInfo.setFlowNodeCodePath(flowNodeCodePath + "," + nextNodeEnum.getNodeCode());
                flowInfoMapper.updateByPrimaryKeySelective(flowInfo);
                return 1;
            }
        }
//如果流程还未结束,设置下一个节点的状态和发送代办
        FlowNodeEntity flowNode = new FlowNodeEntity();
        flowNode.setFlowInfoId(flowInfoEntity.getFlowId());
        flowNode.setFlowNodeCode(nextNodeEnum.getNodeCode());
        FlowNodeEntity nextNodeEntity = flowNodeMapper.selectByEntity(flowNodeEntity);
        nextNodeEntity.setFlowNodeApproveUsers(StringUtils.join(userList, ","));
        nextNodeEntity.setFlowNodeStatus(FlowConstants.FLOW_NODE_APPROVE);
        nextNodeEntity.setLastModifierId("370124");
        nextNodeEntity.setLastModifiedTime(new Date());
        flowNodeMapper.updateByPrimaryKey(nextNodeEntity);
        //将这些审批人userList发送代办
        if (!CollectionUtils.isEmpty(userList)) {
            executeTodoTask(userList, flowInfoEntity, nodeEnum, approveFlowDto.getNextAction());
        }
        return 2;
    }


    /**
     * 驳回工作流信息(flowNodeCode为空相当于是默认设置第一个start节点,不为空是跳转到具体的节点中)
     * 1.修改工作流的流程状态为已驳回(任何时候都可以驳回)
     * 2.添加流程工作日志
     * 3.驳回的时候将该流程节点的审批人全部重置到第一个节点(并给第一个节点的人发送代办)
     */
    @Transactional(rollbackFor = Exception.class)
    public void rejectFlow(Class<IWfNodeBaseEnum> enumClass, ApproveFlowDto approveFlowDto)
            throws InstantiationException, IllegalAccessException {
        //更新该流程的状态和链路路径
        IWfNodeBaseEnum iWfNodeBaseEnum = enumClass.newInstance();
        FlowInfoEntity flowInfoEntity = flowInfoMapper.selectByPrimaryKey(approveFlowDto.getFlowId());
        if (FlowConstants.FLOW_PENDING.equals(flowInfoEntity.getFlowStatus())) {
            throw new BusinessException("该流程已处于挂起状态,请解除挂起之后再发起审批");
        }
        flowInfoEntity.setFlowStatus(FlowConstants.FLOW_REJECT);
        String flowNodeCodePath = flowInfoEntity.getFlowNodeCodePath();
        String flowNodeCode = approveFlowDto.getFlowNodeCode();
        String startCode;
        if (ObjectUtils.isEmpty(flowNodeCode)) {
            startCode = flowNodeCodePath.split(",")[0];
            flowInfoEntity.setFlowNodeCodePath(startCode);
        } else {
    //校验跳回的节点是否在该流程中
            List<String> nodeCodeList = Arrays.asList(flowNodeCodePath.split(","));
            if (!nodeCodeList.contains(flowNodeCode)) {
                throw new BusinessException("跳转的节点code不在该流程的工作节点中,跳转失败");
            }
            startCode = flowNodeCodePath.split(flowNodeCode)[0];
            flowInfoEntity.setFlowNodeCodePath(startCode + "," + flowNodeCode);
            startCode = flowNodeCode;
        }
        flowInfoEntity.setLastModifierId("370124");
        flowInfoEntity.setLastModifiedTime(new Date());
        flowInfoMapper.updateByPrimaryKeySelective(flowInfoEntity);
        //记录流程日志
        FlowRecordEntity flowRecord = new FlowRecordEntity();
        flowRecord.setFlowRecordId(UUIDUtil.getUUIDKey());
        flowRecord.setFlowInfoId(flowInfoEntity.getFlowId());
        flowRecord.setFlowRecordType(FlowConstants.FLOW_RECORD_REJECT);
        flowRecord.setFlowRecordContent(approveFlowDto.getRecordContent());
        flowRecord.setCreatorId("370124");
        flowRecord.setCreatedTime(new Date());
        flowRecordMapper.insert(flowRecord);
        //修改流程节点的信息
        List<FlowNodeEntity> flowNodeEntityList = flowNodeMapper.selectByFlowInfoId(approveFlowDto.getFlowId());
        List<FlowNodeEntity> entityList = flowNodeEntityList.stream()
                .filter(s -> !ObjectUtils.isEmpty(s.getFlowNodeApproveUsers())).collect(Collectors.toList());
        String flowPath = flowNodeCodePath.split(flowNodeCode)[0];
        String approveNodeCode = startCode + flowPath.split(startCode)[1];
        //获取需要修改的节点信息
        List<String> updateNodeCodeLost = Arrays.asList(approveNodeCode.split(","));
        List<FlowNodeEntity> nodeEntityList = entityList.stream()
                .filter(s -> updateNodeCodeLost.contains(s.getFlowNodeCode())).collect(Collectors.toList());
        for (FlowNodeEntity flowNodeEntity : nodeEntityList) {
            flowNodeEntity.setFlowNodeApproveUsers("");
            flowNodeEntity.setFlowNodeStatus(FlowConstants.FLOW_NODE_APPROVE);
            flowNodeEntity.setLastModifierId("370124");
            flowNodeEntity.setLastModifiedTime(new Date());
        }
        flowNodeMapper.updateBatch(nodeEntityList);
        //删除往后节点的代办信息
        List<String> flowNodeIdList = nodeEntityList.stream().map(FlowNodeEntity::getFlowNodeId).collect(Collectors.toList());
        ptlTodoTaskMapper.batchDeleteByBusIds(flowNodeIdList);
        //重新发送下一节点代办,将这些审批人userList发送代办
        executeTodoTask(approveFlowDto.getUserList(), flowInfoEntity, iWfNodeBaseEnum.getNextNodeEnum(startCode), approveFlowDto.getNextAction());
    }
/**
     * 获取整条链路直接从流程数据中获取(在每次执行审批流程之后都会更新当前链路code字段)
     */
    public List<IWfNodeBaseEnum> getLinkNode(Class<IWfNodeBaseEnum> enumClass, String flowId)
            throws InstantiationException, IllegalAccessException {
        IWfNodeBaseEnum iWfNodeBaseEnum = enumClass.newInstance();
        FlowInfoEntity flowInfoEntity = flowInfoMapper.selectByPrimaryKey(flowId);
        String flowNodeCodePath = flowInfoEntity.getFlowNodeCodePath();
        if (ObjectUtils.isEmpty(flowNodeCodePath)) {
            throw new BusinessException("异常数据,流程路径不能为空");
        }
        String[] nodeCodeList = flowNodeCodePath.split(",");
        List<IWfNodeBaseEnum> list = new ArrayList<>();
        for (String nodeCode : nodeCodeList) {
            IWfNodeBaseEnum wfNodeEnum = iWfNodeBaseEnum.getEnumByNodeCode(nodeCode);
            list.add(wfNodeEnum);
        }
        return list;
    }

    /**
     * 任务挂起
     * 1.修改该流程为挂起状态;
     * 2.在提交的时候校验该流程是否挂起,挂起的流程不能提交流程
     *
     * @param flowId  流程id
     * @param pending 是否挂起,true的时候是设置为挂起,false取消挂起
     */
    public void executeFlow(String flowId, Boolean pending) {
        FlowInfoEntity flowInfoEntity = flowInfoMapper.selectByPrimaryKey(flowId);
        if (pending) {
            flowInfoEntity.setFlowStatus(FlowConstants.FLOW_PENDING);
            flowInfoMapper.updateByPrimaryKey(flowInfoEntity);
        } else {
            flowInfoEntity.setFlowStatus(FlowConstants.FLOW_APPROVE);
            flowInfoMapper.updateByPrimaryKey(flowInfoEntity);
        }
    }

}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值