回撤原理 :把原有出口连线 指向回撤的目标 节点,审批过后,再还原原有连线
代码:
/**
*撤回逻辑 就是把当前节点的 出口连线 指向 要撤回的目标节点(上一步,实际上可以一次回退多步,同时也可以跳转多步) 然后执行任务完成,完成后恢复此节点的出口原有连线
* @param prodId 实例ID
* @param taskId 任务ID
*/
void direction(String prodId,String taskId){
HistoryService historyService = this.processEngine.getHistoryService();
RepositoryService repositoryService = this.processEngine.getRepositoryService();
TaskService taskService = this.processEngine.getTaskService();
/**
* 第一步 获取回退目标节点(一般业务 都是回退到上一步)
*/
//获取未完成流程的 所有历史任务节点
HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery()
.processUnfinished();
//根据流程实例ID 获取 任务节点实例
List<HistoricTaskInstance> list = historicTaskInstanceQuery.processInstanceId(prodId)
//.unfinished()//未完成的任务实例 (查询 流程未结束 且 任务未结束的任务)
.finished()//已经结束的任务实例 (查询 流程未结束 但是 任务已经结束了的任务(历史任务))
.orderByTaskCreateTime()
.desc()
.list();
//获取第一任务实例 当前流程 目前 已完成的最后一个任务 也就是 目前需要回退到的目标节点)
HistoricTaskInstance historicTaskInstance=list.get(0);
//获取流程实例
ProcessInstance processInstance = this.processEngine.getRuntimeService().createProcessInstanceQuery().processInstanceId(prodId).singleResult();
// System.out.println(processInstance.getId()+" name "+processInstance.getName()+" getProcessDefinitionId"+processInstance.getProcessDefinitionId());
//获取流程定义对象
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity)repositoryService.getProcessDefinition(processInstance.getProcessDefinitionId());
/**
* 获取回退目标节点
*/
// 根据流程定义key 获得当前流程上一步活动节点(要撤回的目标节点)
ActivityImpl upActivity = processDefinition.findActivity(historicTaskInstance.getTaskDefinitionKey());
/**
* 第二步 获取当前活动节点
*/
//获取当前任务
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
// 根据流程定义key 获得当前活动节点
ActivityImpl currentActivity = processDefinition.findActivity(task.getTaskDefinitionKey());
// 获取当前活动节点的 出口(节点后面的所有连出去的线 每条线是一个出口 所以返回的是集合)
List<PvmTransition> currTransitionList = currentActivity.getOutgoingTransitions();
//把出口的线 存起来, 等转向过后需要还原的
List<PvmTransition> oldTransitionList=new ArrayList<>();
for (PvmTransition pvmTransition : currTransitionList) {
System.out.println("原始连线: "+pvmTransition.toString());
oldTransitionList.add(pvmTransition);
}
//清空原有的连线
currTransitionList.clear();
/**
* 第三步 为当前活动节点 创建新的连线, 并指向 撤回的目标节点
*/
List<TransitionImpl> newTransitions = new ArrayList<TransitionImpl>();
//当前流程节点创建一条新的连线
TransitionImpl newTransition = currentActivity.createOutgoingTransition();
//新的连线指向 上一步流程节点
newTransition.setDestination( upActivity );
newTransitions.add( newTransition );//如果多根线 就用集合存储
//设置后的连线
List<PvmTransition> outgoingTransitions1 = currentActivity.getOutgoingTransitions();
for (PvmTransition outgoingTransition : outgoingTransitions1) {
System.out.println("设置后的连线: "+outgoingTransition.toString());
}
/**
* 第四步 完成当前任务( 因为当前任务的连线指向了 撤回的目标节点,所以当任务完成后 就回到了 回撤的目标节点)
*/
// taskService.setAssignee(task.getId(),"任务执行人"); //任务执行人
taskService.addComment(taskId,prodId,"撤回操作");
taskService.complete(task.getId());//执行任务 执行完后 进入下一节点(也就是 回撤的目标节点)
historyService.deleteHistoricTaskInstance(task.getId());//删除历史任务实例 (必须要删除,不然回撤多步时会出现 逻辑异常)
/**
* 第五步 当前任节点删除新的连线 并且恢复'原来的连线' 这一步也是必须的
*/
//删除 新建的连线
currentActivity.getOutgoingTransitions().remove(newTransition);
//恢复原来的连线
currTransitionList.addAll(oldTransitionList);
//查看还原后的连线
List<PvmTransition> outgoingTransitions = currentActivity.getOutgoingTransitions();
for (PvmTransition outgoingTransition : outgoingTransitions) {
System.out.println("还原后的连线: "+outgoingTransition.toString());
}
}