• (企业内部)工作流实战_22_flowable 驳回/回退 并行网关驳回 多实例驳回 子流程驳回


    (企业内部)工作流实战_22_flowable 驳回/回退 并行网关驳回 多实例驳回 子流程驳回

    项目地址https://gitee.com/lwj/flowable.git
    代码分支 flowable-base
    视频讲解地址 https://www.bilibili.com/video/av78779999/
    用户名密码
    0000001 test
    0000002 test
    0000003 test
    0000004 test

    1. 场景

    驳回:当前处理人可以驳回历史走过的任何一个节点
    1、驳回任意普通节点
    2、驳回多实例节点
    3、驳回并行网关节点
    4、驳回子流程节点
    5、子流程节点驳回主流程节点

    实际情况中,为了获取可驳回的节点列表,我们做了一些规定,比方说并行网关节点,要求必须成对出现,也只能驳回到并行网关节点的 fork节点

    2. 演示

    由于情况很多,截图反而不能重点讲述驳回的事情,这里只截一张图,如果想看详情请查看视频里面的讲解
    在这里插入图片描述

    3. 代码分享

    3.1. 获取可驳回节点

    public List<FlowNodeVo> getBackNodesByProcessInstanceId(String taskId,String processInstanceId) {
            List<FlowNodeVo> backNods = new ArrayList<>();
            TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery().taskId(taskId).singleResult();
            String currActId = taskEntity.getTaskDefinitionKey();
            //获取运行节点表中usertask
            String sql = "select t.* from act_ru_actinst t where t.ACT_TYPE_ = 'userTask' " +
                    " and t.PROC_INST_ID_=#{processInstanceId} and t.END_TIME_ is not null ";
            List<ActivityInstance> activityInstances = runtimeService.createNativeActivityInstanceQuery().sql(sql)
                    .parameter("processInstanceId", processInstanceId)
                    .list();
            //获取运行节点表的parallelGateway节点并出重
            sql = "SELECT t.ID_, t.REV_,t.PROC_DEF_ID_,t.PROC_INST_ID_,t.EXECUTION_ID_,t.ACT_ID_, t.TASK_ID_, t.CALL_PROC_INST_ID_, t.ACT_NAME_, t.ACT_TYPE_, " +
                    " t.ASSIGNEE_, t.START_TIME_, max(t.END_TIME_) as END_TIME_, t.DURATION_, t.DELETE_REASON_, t.TENANT_ID_" +
                    " FROM  act_ru_actinst t WHERE t.ACT_TYPE_ = 'parallelGateway' AND t.PROC_INST_ID_ = #{processInstanceId} and t.END_TIME_ is not null" +
                    " and t.ACT_ID_ <> #{actId} GROUP BY t.act_id_";
            List<ActivityInstance> parallelGatewaies = runtimeService.createNativeActivityInstanceQuery().sql(sql)
                    .parameter("processInstanceId", processInstanceId)
                    .parameter("actId", currActId)
                    .list();
            //排序
            if (CollectionUtils.isNotEmpty(parallelGatewaies)) {
                activityInstances.addAll(parallelGatewaies);
                activityInstances.sort(Comparator.comparing(ActivityInstance::getEndTime));
            }
            //分组节点
            int count = 0;
            Map<ActivityInstance, List<ActivityInstance>> parallelGatewayUserTasks = new HashMap<>();
            List<ActivityInstance> userTasks = new ArrayList<>();
            ActivityInstance currActivityInstance = null;
            for (ActivityInstance activityInstance : activityInstances) {
                if (BpmnXMLConstants.ELEMENT_GATEWAY_PARALLEL.equals(activityInstance.getActivityType())) {
                    count++;
                    if (count % 2 != 0) {
                        List<ActivityInstance> datas = new ArrayList<>();
                        currActivityInstance = activityInstance;
                        parallelGatewayUserTasks.put(currActivityInstance, datas);
                    }
                }
                if (BpmnXMLConstants.ELEMENT_TASK_USER.equals(activityInstance.getActivityType())) {
                    if (count % 2 == 0) {
                        userTasks.add(activityInstance);
                    } else {
                        if (parallelGatewayUserTasks.containsKey(currActivityInstance)) {
                            parallelGatewayUserTasks.get(currActivityInstance).add(activityInstance);
                        }
                    }
                }
            }
            //组装人员名称
            List<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery()
                    .processInstanceId(processInstanceId).finished().list();
            Map<String, List<HistoricTaskInstance>> taskInstanceMap = new HashMap<>();
            List<String> userCodes = new ArrayList<>();
            historicTaskInstances.forEach(historicTaskInstance -> {
                userCodes.add(historicTaskInstance.getAssignee());
                String taskDefinitionKey = historicTaskInstance.getTaskDefinitionKey();
                if (taskInstanceMap.containsKey(historicTaskInstance.getTaskDefinitionKey())) {
                    taskInstanceMap.get(taskDefinitionKey).add(historicTaskInstance);
                } else {
                    List<HistoricTaskInstance> tasks = new ArrayList<>();
                    tasks.add(historicTaskInstance);
                    taskInstanceMap.put(taskDefinitionKey, tasks);
                }
            });
            //组装usertask的数据
            List<User> userList = identityService.createUserQuery().userIds(userCodes).list();
            Map<String, String> activityIdUserNames = this.getApplyers(processInstanceId, userList, taskInstanceMap);
            if (CollectionUtils.isNotEmpty(userTasks)) {
                userTasks.forEach(activityInstance -> {
                    FlowNodeVo node = new FlowNodeVo();
                    node.setNodeId(activityInstance.getActivityId());
                    node.setNodeName(activityInstance.getActivityName());
                    node.setEndTime(activityInstance.getEndTime());
                    node.setUserName(activityIdUserNames.get(activityInstance.getActivityId()));
                    backNods.add(node);
                });
            }
            //组装会签节点数据
            if (MapUtils.isNotEmpty(taskInstanceMap)) {
                parallelGatewayUserTasks.forEach((activity, activities) -> {
                    FlowNodeVo node = new FlowNodeVo();
                    node.setNodeId(activity.getActivityId());
                    node.setEndTime(activity.getEndTime());
                    StringBuffer nodeNames = new StringBuffer("会签:");
                    StringBuffer userNames = new StringBuffer("审批人员:");
                    if (CollectionUtils.isNotEmpty(activities)){
                        activities.forEach(activityInstance -> {
                            nodeNames.append(activityInstance.getActivityName()).append(",");
                            userNames.append(activityIdUserNames.get(activityInstance.getActivityId())).append(",");
                        });
                        node.setNodeName(nodeNames.toString());
                        node.setUserName(userNames.toString());
                        backNods.add(node);
                    }
                });
            }
            //去重合并
            List<FlowNodeVo> datas = backNods.stream().collect(
                    Collectors.collectingAndThen(Collectors.toCollection(() ->
                            new TreeSet<>(Comparator.comparing(nodeVo -> nodeVo.getNodeId()))), ArrayList::new));
    
            //排序
            datas.sort(Comparator.comparing(FlowNodeVo::getEndTime));
            return datas;
        }
    

    3.2. 驳回代码分享

    public ReturnVo<String> backToStepTask(BackTaskVo backTaskVo) {
            ReturnVo<String> returnVo = null;
            TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery().taskId(backTaskVo.getTaskId()).singleResult();
            //1.把当前的节点设置为空
            if (taskEntity != null) {
                //2.设置审批人
                taskEntity.setAssignee(backTaskVo.getUserCode());
                taskService.saveTask(taskEntity);
                //3.添加驳回意见
                this.addComment(backTaskVo.getTaskId(), backTaskVo.getUserCode(), backTaskVo.getProcessInstanceId(),
                        CommentTypeEnum.BH.toString(), backTaskVo.getMessage());
                //4.处理提交人节点
                FlowNode distActivity = flowableBpmnModelService.findFlowNodeByActivityId(taskEntity.getProcessDefinitionId(), backTaskVo.getDistFlowElementId());
                if (distActivity != null) {
                    if (FlowConstant.FLOW_SUBMITTER.equals(distActivity.getName())) {
                        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(taskEntity.getProcessInstanceId()).singleResult();
                        runtimeService.setVariable(backTaskVo.getProcessInstanceId(), FlowConstant.FLOW_SUBMITTER_VAR, processInstance.getStartUserId());
                    }
                }
                //5.删除节点
                this.deleteActivity(backTaskVo.getDistFlowElementId(), taskEntity.getProcessInstanceId());
                List<String> executionIds = new ArrayList<>();
                //6.判断节点是不是子流程内部的节点
                if (flowableBpmnModelService.checkActivitySubprocessByActivityId(taskEntity.getProcessDefinitionId(),
                        backTaskVo.getDistFlowElementId())
                        && flowableBpmnModelService.checkActivitySubprocessByActivityId(taskEntity.getProcessDefinitionId(),
                        taskEntity.getTaskDefinitionKey())){
                    //6.1 子流程内部驳回
                    Execution executionTask = runtimeService.createExecutionQuery().executionId(taskEntity.getExecutionId()).singleResult();
                    String parentId = executionTask.getParentId();
                    List<Execution> executions = runtimeService.createExecutionQuery().parentId(parentId).list();
                    executions.forEach(execution -> executionIds.add(execution.getId()));
                    this.moveExecutionsToSingleActivityId(executionIds,backTaskVo.getDistFlowElementId());
                }else {
                    //6.2 普通驳回
                    List<Execution> executions = runtimeService.createExecutionQuery().parentId(taskEntity.getProcessInstanceId()).list();
                    executions.forEach(execution -> executionIds.add(execution.getId()));
                    this.moveExecutionsToSingleActivityId(executionIds,backTaskVo.getDistFlowElementId());
                }
                returnVo = new ReturnVo<>(ReturnCode.SUCCESS, "驳回成功!");
            } else {
                returnVo = new ReturnVo<>(ReturnCode.FAIL, "不存在任务实例,请确认!");
            }
            return returnVo;
        }
    
     
  • 相关阅读:
    1.7 this关键字
    1.6 作用域练习题
    1.5 关于内存释放和作用域销毁的研究
    php 类与对象
    Yii2 数据操作Query Builder查询数据
    Mac 下配置Nginx安装环境配置详细说明
    PHP 面向对象
    php中static静态关键字的使用方法和应用场景
    http协议(五)web服务器
    http协议(四)http常用状态码
  • 原文地址:https://www.cnblogs.com/xianz666/p/14693432.html
Copyright © 2020-2023  润新知