• flowable 之驳回 多实例驳回 并行网关驳回 普通节点驳回到多实例


    flowable 驳回

    欢迎大家学习交流,如有不对的地方,请大家多多指教,我接下来会把flowable的所有的中国式API*都写出来,也希望对大家有帮助,程序员只要静下心来,其实可以产生巨大的能量,靠任何人都没有用,唯有靠自己。学习好一门技术,还是多看看源代码,多在实际工作中用,如果想走捷径,想通过一本书或者一些视频想学好,那永远是痴心说梦。*

    网上搜索了很多关于activiti的驳回方法,flowable的驳回方法,发现一个问题,基本都是在扯淡,根本无法解决商业用途,为了把这块吃透,我最近研究了一下他们的源代码,已在我们公司使用,暂时没有发现问题。其实看flowable的源代码很简单的,就是一个命令模式,仿照他们的命令模式写自己的就可以了,没有太大的难度。不得不佩服flowable的作者,用命令模式规范了自己的代码,而且把这么好的东西开源出来,从来没有找我们要过钱,这是何等的伟大,像大神致敬。闲话不多说,直接来代码比较干脆。

    由于我们公司的流程有规范,所以有写地方有点特殊,如果不懂的可以随时给我留言即可,来也网络,去也网络。

    • 1. 判断该节点上一个节点是不是并行网关节点
    • 2. 如果上一个节点是提交者的话要处理一下
    • 3. 添加审批意见和修改流程状态
    • 4. 删除现有的所有任务
    • 5. 删除节点信息
    • 6. 驳回到disk节点
    • 6.1 如果当前节点是多实例节点 删除当前多实例 如果目标节点不是多实例我们就创建一个孩子实例
    • 6.2 处理并行网关的多实例

        具体代码

     public ReturnVo<String> backToStep(BackVo backVo) {
            ReturnVo<String> returnVo = new ReturnVo<>(ReturnCode.SUCCESS, "OK");
            if (backVo != null && StringUtils.isNotBlank(backVo.getTaskId())) {
                TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery().taskId(backVo.getTaskId()).singleResult();
                if (taskEntity != null){
                    Activity distActivity = processDefinitionUtils.findFlowElementById(taskEntity.getProcessDefinitionId(), backVo.getDistFlowElementId());
                    if (taskEntity != null && distActivity != null) {
                        //1. 判断该节点上一个节点是不是并行网关节点
                        List<SequenceFlow> incomingFlows = distActivity.getIncomingFlows();
                        if (CollectionUtils.isNotEmpty(incomingFlows)) {
                            for (SequenceFlow sequenceFlow : incomingFlows) {
                                FlowElement upNode = sequenceFlow.getSourceFlowElement();
                                if (upNode != null && (upNode instanceof ParallelGateway || upNode instanceof InclusiveGateway)) {
                                    returnVo = new ReturnVo<>(ReturnCode.FAIL, "并行节点无法驳回,请选择其他节点!");
                                    return returnVo;
                                }
                            }
                        }
                        //2. 如果上一个节点是提交者的话要处理一下
                        if (FlowConstant.FLOW_SUBMITTER.equals(distActivity.getName())) {
                            //查找发起人
                            ExtendHisprocinst extendHisprocinst = this.extendHisprocinstService.findExtendHisprocinstByProcessInstanceId(taskEntity.getProcessInstanceId());
                            if (extendHisprocinst != null) {
                                runtimeService.setVariable(taskEntity.getProcessInstanceId(), FlowConstant.FLOW_SUBMITTER, extendHisprocinst.getCreator());
                            }
                        }
                        //3. 添加审批意见和修改流程状态
                        this.addCommentAndUpdateProcessStatus(backVo);
                        //4. 删除现有的所有任务
                        managementService.executeCommand(new DeleteTaskCmd(taskEntity.getProcessInstanceId()));
                        //5. 删除节点信息
                        this.deleteHisActivities(distActivity, taskEntity.getProcessInstanceId());
                        //6. 驳回到disk节点
                        Activity currActivity = processDefinitionUtils.findFlowElementById(taskEntity.getProcessDefinitionId(), taskEntity.getTaskDefinitionKey());
                        //6.1 如果当前节点是多实例节点 删除当前多实例 如果目标节点不是多实例我们就创建一个孩子实例
                        boolean flag = false;
                        if (currActivity.getBehavior() instanceof MultiInstanceActivityBehavior){
                            ExecutionEntity executionEntity = (ExecutionEntity)runtimeService.createExecutionQuery().executionId(taskEntity.getExecutionId()).singleResult();
                            managementService.executeCommand(new DeleteMultiInstanceExecutionCmd(executionEntity.getParentId(),false));
                            flag = true;
                        }
                        //6.2 处理并行网关的多实例
                        List<Execution> executions = runtimeService.createExecutionQuery().parentId(taskEntity.getProcessInstanceId()).list();
                        if (CollectionUtils.isNotEmpty(executions) && executions.size() >1){
                            executions.forEach(execution -> {
                                ExecutionEntity e = (ExecutionEntity)execution;
                                managementService.executeCommand(new DeleteChildExecutionCmd(e));
                            });
                            flag = true;
                        }
                        if (flag) {
                            ExecutionEntity parentExecutionEntity = (ExecutionEntity)runtimeService.createExecutionQuery().executionId(taskEntity.getProcessInstanceId()).singleResult();
                            managementService.executeCommand(new AddChildExecutionCmd(parentExecutionEntity));
                        }
                        managementService.executeCommand(new JumpActivityCmd(taskEntity.getProcessInstanceId(),distActivity.getId()));
                        //TODO 7. 处理加签的数据0
                    }
                }else {
                    returnVo = new ReturnVo<>(ReturnCode.FAIL, "当前任务不存在!");
                }
            } else {
                returnVo = new ReturnVo<>(ReturnCode.FAIL, "请设置相关参数!");
            }
            return returnVo;
        }
    

      

    • ProcessDefinitionUtils
    @Component
    public class ProcessDefinitionUtils {
    
        @Autowired
        private RepositoryService repositoryService;
    
        /**
         * 获取end节点
         *
         * @param processDefId
         * @return FlowElement
         */
        public FlowElement findEndFlowElement(String processDefId) {
            Process process = repositoryService.getBpmnModel(processDefId).getMainProcess();
            Collection<FlowElement> list = process.getFlowElements();
            for (FlowElement f : list) {
                if (f instanceof EndEvent) {
                    return f;
                }
            }
            return null;
        }
    
        /**
         * 获取指定节点的节点信息
         *
         * @param processDefId
         * @param flowElementId
         * @return FlowElement
         */
        public Activity findFlowElementById(String processDefId, String flowElementId) {
            Process process = repositoryService.getBpmnModel(processDefId).getMainProcess();
            return (Activity) process.getFlowElement(flowElementId);
        }
    
    }
    

      

    addCommentAndUpdateProcessStatus 这个方法是添加审批意见和更新流程状态,由于流程状态没有,我这里扩展了一张表,状态主要有审批中,驳回,暂存,转办,撤回,终止等等状态

    /**
         * 添加审批意见和修改流程状态
         * @param baseProcessVo 基本流程任务参数
         */
        protected void addCommentAndUpdateProcessStatus(BaseProcessVo baseProcessVo) {
            //兼容处理
            if (StringUtils.isBlank(baseProcessVo.getProcessInstanceId())){
                Task task = taskService.createTaskQuery().taskId(baseProcessVo.getTaskId()).singleResult();
                if (task != null) {
                    baseProcessVo.setProcessInstanceId(task.getProcessInstanceId());
                }
            }
            //1.添加审批意见
            FlowCommentVo flowCommentVo = new FlowCommentVo(baseProcessVo.getTaskId(), baseProcessVo.getUserCode(),
                    baseProcessVo.getProcessInstanceId(), baseProcessVo.getMessage(), baseProcessVo.getCommentTypeEnum().toString());
            this.addFlowComment(flowCommentVo);
            //2.修改流程实例的状态
            ExtendHisprocinst extendHisprocinst = new ExtendHisprocinst(baseProcessVo.getProcessInstanceId(), baseProcessVo.getProcessStatusEnum().toString());
            extendHisprocinstService.updateStatusByProcessInstanceId(extendHisprocinst);
            //3.TODO 生成索引
        }
    
        /**
         * 添加审批意见
         * @param flowCommentVo
         */
        private void addFlowComment(FlowCommentVo flowCommentVo) {
            FlowCommentCmd cmd = new FlowCommentCmd(flowCommentVo.getTaskId(), flowCommentVo.getUserId(),
                    flowCommentVo.getProcessInstanceId(), flowCommentVo.getType(), flowCommentVo.getMessage());
            managementService.executeCommand(cmd);
        }
    

     DeleteTaskCmd 删除任务命令

    public class DeleteTaskCmd implements Command<Void> {
    
        private String processInstanceId;
    
        public DeleteTaskCmd(String processInstanceId) {
            this.processInstanceId = processInstanceId;
        }
    
        @Override
        public Void execute(CommandContext commandContext) {
            TaskEntityManager taskEntityManager = CommandContextUtil.getTaskEntityManager(commandContext);
            ExecutionEntityManager executionEntityManager = org.flowable.engine.impl.util.CommandContextUtil.getExecutionEntityManager(commandContext);
            List<ExecutionEntity> executionEntities = executionEntityManager.findChildExecutionsByProcessInstanceId(processInstanceId);
            executionEntities.forEach(executionEntity -> taskEntityManager.deleteTasksByExecutionId(executionEntity.getId()));
            return null;
        }
    }
    

     AddChildExecutionCmd 添加一个流程实例下面的执行实例

    public class AddChildExecutionCmd implements Command<Void> {
    
        private ExecutionEntity parentExecutionEntity;
    
        public AddChildExecutionCmd(ExecutionEntity parentExecutionEntity) {
            this.parentExecutionEntity = parentExecutionEntity;
        }
    
        @Override
        public Void execute(CommandContext commandContext) {
            ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext);
            executionEntityManager.createChildExecution(parentExecutionEntity);
            return null;
        }
    }
    

      DeleteChildExecutionCmd 删除执行实例

    public class DeleteChildExecutionCmd implements Command<Void> {
    
        private ExecutionEntity child;
    
        public DeleteChildExecutionCmd(ExecutionEntity child) {
            this.child = child;
        }
    
        @Override
        public Void execute(CommandContext commandContext) {
            ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext);
            executionEntityManager.delete(child,true);
            return null;
        }
    }
    

      JumpActivityCmd 执行跳转

    public class JumpActivityCmd implements Command<Void> {
    
        private String target;
        private String processInstanceId;
    
        public JumpActivityCmd(String processInstanceId, String target) {
            this.processInstanceId = processInstanceId;
            this.target = target;
        }
    
        @Override
        public Void execute(CommandContext commandContext) {
            ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext);
            List<ExecutionEntity> executionEntities = executionEntityManager.findChildExecutionsByParentExecutionId(processInstanceId);
            Process process = ProcessDefinitionUtil.getProcess(executionEntities.get(0).getProcessDefinitionId());
            FlowNode targetFlowElement = (FlowNode) process.getFlowElement(target);
            FlowableEngineAgenda agenda = CommandContextUtil.getAgenda();
            executionEntities.forEach(execution -> {
                execution.setCurrentFlowElement(targetFlowElement);
                agenda.planContinueProcessInCompensation(execution);
            });
            return null;
        }
    

      

  • 相关阅读:
    骨场经历
    聚财与聚人
    腾讯正式开始了QQForMAC的测试
    fiddler
    soap协议基本结构
    js小判断
    控制器
    resharper快捷键
    如何让datetime类型数据接受并且产出long或string类型?
    AES加密,解密方法
  • 原文地址:https://www.cnblogs.com/liuwenjun/p/9611063.html
Copyright © 2020-2023  润新知