activiti&flowable任意驳回-获取可驳回节点信息

 我们经常需要工作流中退回上一步,或者退回历史某一个节点。但由于流程的场景是很复杂的,回退有以下一些场景:

1.串行路线上的退回:流程中没有任何网关(排他网关/并行网关)和会签多实例。

2.退回到并行网关分支中的某一个节点上。

3.并行网关中的某一个分支节点上发起退回,退回到并行网关前面的某一个节点上。

4.子流程中退回到主干流程中某一个节点/主干流程退回到子流程中某一个节点。
 

flowable版本:6.6.0

我们都知道驳回的api:

runtimeService.createChangeActivityStateBuilder().processInstanceId(proInstanceId)
     .moveActivityIdTo(currentActivityId, newActivityId).changeState();
或者
runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(        
     currentExecutionIds, newActivityId).changeState();

但是其实不好处理的是如何获取可驳回节点信息,task任务是没有驳回需要的activityId的,言归正传,下面提供下我的实现方案:

/**
     * 获取可驳回节点,排序规则-最近的节点在前面
     *
     * @param taskId            任务id
     * @param processInstanceId 流程实例id
     * @return
     */
public List<FlowNodeDto> getCanRejectedFlowNode(String taskId, String processInstanceId) {
        List<FlowNodeDto> backNodes = new ArrayList<>();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        String currActId = task.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_,t2.ACT_ID_, t.TASK_ID_, t.CALL_PROC_INST_ID_, t.ACT_NAME_, t.ACT_TYPE_, " +
                " t.ASSIGNEE_, t.START_TIME_, t2.END_TIME_, t.DURATION_, t.DELETE_REASON_, t.TENANT_ID_" +
                " FROM  ACT_RU_ACTINST t JOIN (SELECT ACT_ID_,max(END_TIME_) AS END_TIME_   FROM ACT_RU_ACTINST GROUP BY ACT_ID_) t2  WHERE t.ACT_TYPE_ = 'parallelGateway' AND t.PROC_INST_ID_ = #{processInstanceId} and t.END_TIME_ is not null" +
                " and t.ACT_ID_ <> #{actId}";
        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 = getApplyers(processInstanceId, userList, taskInstanceMap);
        if (CollectionUtils.isNotEmpty(userTasks)) {
            userTasks.forEach(activityInstance -> {
                FlowNodeDto node = new FlowNodeDto();
                node.setNodeId(activityInstance.getActivityId());
                node.setNodeName(activityInstance.getActivityName());
                node.setEndTime(activityInstance.getEndTime());
                node.setUserName(activityIdUserNames.get(activityInstance.getActivityId()));
                backNodes.add(node);
            });
        }
        //组装会签节点数据
        if (MapUtils.isNotEmpty(taskInstanceMap)) {
            parallelGatewayUserTasks.forEach((activity, activities) -> {
                FlowNodeDto node = new FlowNodeDto();
                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());
                    backNodes.add(node);
                }
            });
        }
        //去重合并
        List<FlowNodeDto> flowNodeDtos = backNodes.stream().collect(
                Collectors.collectingAndThen(Collectors.toCollection(() ->
                        new TreeSet<>(Comparator.comparing(FlowNodeDto::getNodeId))), ArrayList::new));

        //排序
        flowNodeDtos.sort(Comparator.comparing(FlowNodeDto::getEndTime).reversed());
        return flowNodeDtos;
    }

 

FlowNodeDto:
@Getter
@Setter
public class FlowNodeDto implements Serializable {
    private static final long serialVersionUID = 1L;

    private String nodeId;
    protected String nodeName;
    protected String activityType;
    protected Date endTime;
    protected String userName;
}

获取审批人getApplyers:

private Map<String, String> getApplyers(String processInstanceId, List<User> userList, Map<String, List<HistoricTaskInstance>> taskInstanceMap) {
        Map<String, User> userMap = userList.stream().collect(Collectors.toMap(User::getId, user -> user));
        Map<String, String> applyMap = new HashMap<>();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        taskInstanceMap.forEach((activityId, taskInstances) -> {
            StringBuilder applyers = new StringBuilder();
            StringBuffer finalApplyers = new StringBuffer();
            taskInstances.forEach(taskInstance -> {
                if (!taskInstance.getName().equals(FlowableConstants.FLOW_SUBMITTER)) {
                    User user = userMap.get(taskInstance.getAssignee());
                    if (user != null) {
                        if (StringUtils.indexOf(finalApplyers.toString(), user.getDisplayName()) == -1) {
                            finalApplyers.append(user.getDisplayName()).append(",");
                        }
                    }
                } else {
                    String startUserId = processInstance.getStartUserId();
                    User user = identityService.createUserQuery().userId(startUserId).singleResult();
                    if (user != null) {
                        finalApplyers.append(user.getDisplayName()).append(",");
                    }
                }
            });
            if (applyers.length() > 0) {
                applyers.deleteCharAt(applyers.length() - 1);
            }
            applyMap.put(activityId, applyers.toString());
        });
        return applyMap;
    }

这样就可以获取到了可驳回的节点信息,那我们就可以根据节点信息进行选择做驳回操作了

后续我们要做的就是驳回操作了:activiti&flowable节点驳回操作

refer:https://space.bilibili.com/485524575/

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值