Activiti7实现驳回功能

  • 5
  • 浏览量:10,805 次
  • A+
所属分类:工作流引擎

所谓驳回,其实就是返回到上个执行节点,但是这个里面又分两种情况

单个执行人assignee的情况

第一种情况比较简单,直接在流程图里用一个变量控制,比如audit为true时代表审核通过,走下一个节点,audit为false时代表驳回,返回上一个节点,这时直接连线到上一个节点,然后设置条件为${audit == false}即可。

多个候选人candidate user的情况

第二种情况就比较麻烦。用第一种情况的方法是不行的。为什么不行?有人说用上面的方法不是可以回到上次执行的节点吗?是的,虽然可以回到上次的节点,但是状态还是初始状态,即assignee为空的状态,我们知道,candidate需要先拾取任务,然后才能完成任务。举个例子,candidate user为张三和李四两个人,张三拾取任务后完成任务,到下一步后被驳回,这时上面的方法回到上一步时,为任务未拾取的状态,这时李四还可以拾取任务并完成。这样显然是不对的,驳回时应该打回到张三,也就是返回上一个节点时应该指定assignee为张三才对。

要实现上述效果,就要进行一些底层的操作了。大概思路如下:

  • 取得当前节点的信息
  • 取得当前节点的上一个节点的信息
  • 保存当前节点的流向
  • 新建流向,由当前节点指向上一个节点
  • 将当前节点的流向设置为上面新建的流向
  • 当前节点完成任务
  • 将当前节点的流向还原
  • 取得之前上个节点的执行人
  • 设置上个节点的assignee为之前的执行人

 

好了,talk is cheap, show me the code,下面直接上代码(已测试通过)

如有问题,欢迎指正!

/**
 *
 * 退回到上一节点
 *
 * @param task 当前任务
 */
public void backProcess(Task task) throws Exception {

    String processInstanceId = task.getProcessInstanceId();

    // 取得所有历史任务按时间降序排序
    List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
            .processInstanceId(processInstanceId)
            .orderByTaskCreateTime()
            .desc()
            .list();

    if (ObjectUtils.isEmpty(htiList) || htiList.size() < 2) {
        return;
    }

    // list里的第二条代表上一个任务
    HistoricTaskInstance lastTask = htiList.get(1);

    // list里第二条代表当前任务
    HistoricTaskInstance curTask = htiList.get(0);

    // 当前节点的executionId
    String curExecutionId = curTask.getExecutionId();


    // 上个节点的taskId
    String lastTaskId = lastTask.getId();
    // 上个节点的executionId
    String lastExecutionId = lastTask.getExecutionId();

    if (null == lastTaskId) {
        throw new Exception("LAST TASK IS NULL");
    }

    String processDefinitionId = lastTask.getProcessDefinitionId();
    BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);

    String lastActivityId = null;
    List<HistoricActivityInstance> haiFinishedList = historyService.createHistoricActivityInstanceQuery()
            .executionId(lastExecutionId).finished().list();

    for (HistoricActivityInstance hai : haiFinishedList) {
        if (lastTaskId.equals(hai.getTaskId())) {
            // 得到ActivityId,只有HistoricActivityInstance对象里才有此方法
            lastActivityId = hai.getActivityId();
            break;
        }
    }

    // 得到上个节点的信息
    FlowNode lastFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(lastActivityId);


    // 取得当前节点的信息
    Execution execution = runtimeService.createExecutionQuery().executionId(curExecutionId).singleResult();
    String curActivityId = execution.getActivityId();
    FlowNode curFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(curActivityId);

    //记录当前节点的原活动方向
    List<SequenceFlow> oriSequenceFlows = new ArrayList<>();
    oriSequenceFlows.addAll(curFlowNode.getOutgoingFlows());

    //清理活动方向
    curFlowNode.getOutgoingFlows().clear();

    //建立新方向
    List<SequenceFlow> newSequenceFlowList = new ArrayList<>();
    SequenceFlow newSequenceFlow = new SequenceFlow();
    newSequenceFlow.setId("newSequenceFlowId");
    newSequenceFlow.setSourceFlowElement(curFlowNode);
    newSequenceFlow.setTargetFlowElement(lastFlowNode);
    newSequenceFlowList.add(newSequenceFlow);
    curFlowNode.setOutgoingFlows(newSequenceFlowList);

    // 完成任务
    taskService.complete(task.getId());

    //恢复原方向
    curFlowNode.setOutgoingFlows(oriSequenceFlows);

    org.activiti.engine.task.Task nextTask = taskService
            .createTaskQuery().processInstanceId(processInstanceId).singleResult();

    // 设置执行人
    if(nextTask!=null) {
        taskService.setAssignee(nextTask.getId(), lastTask.getAssignee());
    }
}

 

ZPY

发表评论取消回复

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

目前评论:5   其中:访客  4   博主  1

    • avatar 程序员 0

      如果上一个是会签节点是不是就有毛病了?

        • avatar ZPY Admin

          @程序员 上一个节点是会签节点的话,驳回到上一个节点这块是没问题的,但是assignee可能会有多人,所以assgine的设置会有点问题,这种情况代码需要改造下,要取得会签节点所有的assginee后再设置。

            • avatar 码农 0

              @ZPY 如果是多实例, act_hi_actinst里面拿到数据是多个, 取上一个任务的activity应该是有问题的

              • avatar 哈哈 0

                @ZPY 可以的根据 输入连线 获取历史用户

            • avatar 郑生 0

              楼主,能加下微信聊吗,驳回功能不知道怎么操作
              15875959285 微信号