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

Posted liuwenjun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
    }

  

以上是关于flowable 之驳回 多实例驳回 并行网关驳回 普通节点驳回到多实例的主要内容,如果未能解决你的问题,请参考以下文章

ctiviti7工作流引擎:进阶篇 驳回(拒绝)

Activiti 5.22.0 之自由驳回任务实现(亲测)

工作流引擎驳回设计

Activiti7工作流引擎:进阶篇 驳回(拒绝)

Activiti工作流几种驳回方式的实现与比较

商标驳回和不予受理区别是啥?