flowable 驳回
欢迎大家学习交流,如有不对的地方,请大家多多指教,我接下来会把flowable的所有的中国式API*都写出来,也希望对大家有帮助,程序员只要静下心来,其实可以产生巨大的能量,靠任何人都没有用,唯有靠自己。学习好一门技术,还是多看看源代码,多在实际工作中用,如果想走捷径,想通过一本书或者一些视频想学好,那永远是痴心说梦。*
网上搜索了很多关于activiti的驳回方法,flowable的驳回方法,发现一个问题,基本都是在扯淡,根本无法解决商业用途,为了把这块吃透,我最近研究了一下他们的源代码,已在我们公司使用,暂时没有发现问题。其实看flowable的源代码很简单的,就是一个命令模式,仿照他们的命令模式写自己的就可以了,没有太大的难度。不得不佩服flowable的作者,用命令模式规范了自己的代码,而且把这么好的东西开源出来,从来没有找我们要过钱,这是何等的伟大,像大神致敬。闲话不多说,直接来代码比较干脆。
由于我们公司的流程有规范,所以有写地方有点特殊,如果不懂的可以随时给我留言即可,来也网络,去也网络。
- 1. 判断该节点上一个节点是不是并行网关节点
- 2. 如果上一个节点是提交者的话要处理一下
- 3. 添加审批意见和修改流程状态
- 4. 删除现有的所有任务
- 5. 删除节点信息
- 6. 驳回到disk节点
- 6.1 如果当前节点是多实例节点 删除当前多实例 如果目标节点不是多实例我们就创建一个孩子实例
- 6.2 处理并行网关的多实例
具体代码
public ReturnVo backToStep(BackVo backVo) {
ReturnVo 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 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 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 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 {
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 executionEntities = executionEntityManager.findChildExecutionsByProcessInstanceId(processInstanceId);
executionEntities.forEach(executionEntity -> taskEntityManager.deleteTasksByExecutionId(executionEntity.getId()));
return null;
}
}
AddChildExecutionCmd 添加一个流程实例下面的执行实例
public class AddChildExecutionCmd implements Command {
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 {
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 {
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 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;
}