提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
公司业务要求需要加个向前加签 向后加签的功能,可难为死我小时了,只听过说加签转签 还有向前加签。
一、解决思路
向前加签:向前加一个节点 把当前节点数据删除 将新生成的节点置换到当前实例中
向后加签:向后加一个节点
既然是加节点 flowable 有动态修改节点的功能 参考 flowable 中的 InjectUserTaskInProcessInstanceCmd
二、代码
package com.process.commnd; /**
* Created by Administrator on 2020/4/8.
*/
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.BpmnAutoLayout;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.impl.cmd.AbstractDynamicInjectionCmd;
import org.flowable.engine.impl.context.Context;
import org.flowable.engine.impl.dynamic.BaseDynamicSubProcessInjectUtil;
import org.flowable.engine.impl.dynamic.DynamicUserTaskBuilder;
import org.flowable.engine.impl.persistence.entity.*;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.flowable.job.service.JobService;
import org.flowable.task.service.HistoricTaskService;
import org.flowable.task.service.impl.persistence.entity.HistoricTaskInstanceEntity;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.flowable.variable.service.VariableService;
import org.springframework.beans.BeanUtils;
import java.util.*;
/**
* 加签根据flag 区分是向前加 还是向后加
* @author : shiyushan
* @date : 2020/10/18 14:46
*/
public class CustomInjectUserTaskInProcessInstanceCmd extends AbstractDynamicInjectionCmd implements Command<Void> {
protected String processInstanceId;
protected DynamicUserTaskBuilder dynamicUserTaskBuilder;
protected Boolean flag;
protected String currentActivityId;
protected String formKey;
protected FlowElement currentFlowElement;
public CustomInjectUserTaskInProcessInstanceCmd(String processInstanceId, Boolean flag, DynamicUserTaskBuilder dynamicUserTaskBuilder,
String currentActivityId,String formKey) {
this.processInstanceId = processInstanceId;
this.dynamicUserTaskBuilder = dynamicUserTaskBuilder;
this.currentActivityId = currentActivityId;
this.flag = flag;
this.formKey = formKey;
}
@Override
public Void execute(CommandContext commandContext) {
createDerivedProcessDefinitionForProcessInstance(commandContext, processInstanceId);
return null;
}
@Override
protected void updateBpmnProcess(CommandContext commandContext, Process process,
BpmnModel bpmnModel, ProcessDefinitionEntity originalProcessDefinitionEntity, DeploymentEntity newDeploymentEntity) {
this.currentFlowElement = process.getFlowElement(currentActivityId);
StartEvent initialStartEvent = getStartEvent(process);
if (currentFlowElement != null) {
UserTask userTask = getUserTask(process);
if (flag) {
addAfter(userTask, process);
} else {
addBefore(userTask, process);
}
addPoint(bpmnModel, initialStartEvent);
}
BaseDynamicSubProcessInjectUtil.processFlowElements(commandContext, process, bpmnModel, originalProcessDefinitionEntity, newDeploymentEntity);
}
/**
* 根据当前节点获取一个新的节点
* 并设置新节点的处理人为被加签人
* @param process
* @return
*/
private UserTask getUserTask(Process process) {
UserTask userTask = new UserTask();
BeanUtils.copyProperties(this.currentFlowElement, userTask);
if (dynamicUserTaskBuilder.getId() != null) {
userTask.setId(dynamicUserTaskBuilder.getId());
} else {
userTask.setId(dynamicUserTaskBuilder.nextTaskId(process.getFlowElementMap()));
}
dynamicUserTaskBuilder.setDynamicTaskId(userTask.getId());
userTask.setFormKey(formKey);
userTask.setName(dynamicUserTaskBuilder.getName());
userTask.setAssignee(dynamicUserTaskBuilder.getAssignee());
userTask.setCandidateUsers(new ArrayList<>());
userTask.setCandidateGroups(new ArrayList<>());
return userTask;
}
/**
* 向前加签
* 当前节点向前加线
* 给新任务节点设置出口跟入口
* @param userTask
* @param process
*/
private void addBefore(UserTask userTask, Process process) {
UserTask currentFlowElement = (UserTask) this.currentFlowElement;
List<SequenceFlow> outgoingFlows = new ArrayList<>();
SequenceFlow outgoingFlow = new SequenceFlow(userTask.getId(), currentFlowElement.getId());
outgoingFlow.setId("seq_" + UUID.randomUUID());
outgoingFlows.add(outgoingFlow);
process.addFlowElement(outgoingFlow);
List<SequenceFlow> incomingFlows = new ArrayList<>();
for (SequenceFlow sequenceFlow1 : currentFlowElement.getIncomingFlows()) {
SequenceFlow sequenceFlow = new SequenceFlow(sequenceFlow1.getSourceRef(),userTask.getId());
incomingFlows.add(getSequence(sequenceFlow, incomingFlows, sequenceFlow1));
//删除原先节点的入线
process.removeFlowElement(sequenceFlow1.getId());
process.addFlowElement(sequenceFlow);
}
userTask.setOutgoingFlows(outgoingFlows);
userTask.setIncomingFlows(incomingFlows);
process.addFlowElement(userTask);
}
/**
* 向后加签
* 当前节点向后加线
* 给新任务节点设置出口跟入口
* @param userTask
* @param process
*/
private void addAfter(UserTask userTask, Process process) {
UserTask currentFlowElement = (UserTask) this.currentFlowElement;
List<SequenceFlow> outgoingFlows = new ArrayList<>();
for (SequenceFlow sequenceFlow1 : currentFlowElement.getOutgoingFlows()) {
SequenceFlow sequenceFlow = new SequenceFlow( userTask.getId(),sequenceFlow1.getTargetRef());
outgoingFlows.add(getSequence(sequenceFlow, outgoingFlows, sequenceFlow1));
//删除原先节点的出线
process.removeFlowElement(sequenceFlow1.getId());
process.addFlowElement(sequenceFlow);
}
List<SequenceFlow> incomingFlows = new ArrayList<>();
SequenceFlow incomingFlow = new SequenceFlow(currentFlowElement.getId(), userTask.getId());
incomingFlow.setId("seq_" + UUID.randomUUID());
incomingFlows.add(incomingFlow);
process.addFlowElement(incomingFlow);
userTask.setOutgoingFlows(outgoingFlows);
userTask.setIncomingFlows(incomingFlows);
process.addFlowElement(userTask);
}
/**
* 组装新连线
*
* @param sequenceFlow
* @param incomingFlows
* @param sequenceFlow1
*/
private SequenceFlow getSequence(SequenceFlow sequenceFlow, List<SequenceFlow> incomingFlows, SequenceFlow sequenceFlow1) {
sequenceFlow.setSkipExpression(sequenceFlow1.getSkipExpression());
sequenceFlow.setConditionExpression(sequenceFlow1.getConditionExpression());
sequenceFlow.setExtensionElements(sequenceFlow1.getExtensionElements());
sequenceFlow.setExecutionListeners(sequenceFlow1.getExecutionListeners());
sequenceFlow.setName(sequenceFlow1.getName());
sequenceFlow.setId("seq_" + UUID.randomUUID());
return sequenceFlow;
}
/**
* 新增坐标点
*
* @param bpmnModel
* @param initialStartEvent
*/
private void addPoint(BpmnModel bpmnModel, StartEvent initialStartEvent) {
GraphicInfo elementGraphicInfo = bpmnModel.getGraphicInfo(currentFlowElement.getId());
if (elementGraphicInfo != null) {
double yDiff = 0;
double xDiff = 80;
if (elementGraphicInfo.getY() < 173) {
yDiff = 173 - elementGraphicInfo.getY();
elementGraphicInfo.setY(173);
}
Map<String, GraphicInfo> locationMap = bpmnModel.getLocationMap();
for (String locationId : locationMap.keySet()) {
if (initialStartEvent.getId().equals(locationId)) {
continue;
}
GraphicInfo locationGraphicInfo = locationMap.get(locationId);
locationGraphicInfo.setX(locationGraphicInfo.getX() + xDiff);
locationGraphicInfo.setY(locationGraphicInfo.getY() + yDiff);
}
Map<String, List<GraphicInfo>> flowLocationMap = bpmnModel.getFlowLocationMap();
for (String flowId : flowLocationMap.keySet()) {
List<GraphicInfo> flowGraphicInfoList = flowLocationMap.get(flowId);
for (GraphicInfo flowGraphicInfo : flowGraphicInfoList) {
flowGraphicInfo.setX(flowGraphicInfo.getX() + xDiff);
flowGraphicInfo.setY(flowGraphicInfo.getY() + yDiff);
}
}
new BpmnAutoLayout(bpmnModel).execute();
}
}
/**
* 得到开始节点
* @param process
* @return
* @author: shiyushan
* @version: 1.0.0
* @date: 2023/1/2 6:57 下午
*/
private StartEvent getStartEvent(Process process) {
List<StartEvent> startEvents = process.findFlowElementsOfType(StartEvent.class);
StartEvent initialStartEvent = null;
for (StartEvent startEvent : startEvents) {
if (startEvent.getEventDefinitions().size() == 0) {
initialStartEvent = startEvent;
break;
} else if (initialStartEvent == null) {
initialStartEvent = startEvent;
}
}
return initialStartEvent;
}
@Override
protected void updateExecutions(CommandContext commandContext, ProcessDefinitionEntity processDefinitionEntity,
ExecutionEntity processInstance, List<ExecutionEntity> childExecutions) {
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext);
VariableService variableService = CommandContextUtil.getVariableService(commandContext);
JobService jobService = CommandContextUtil.getJobService(commandContext);
BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processDefinitionEntity.getId());
ActivityInstanceEntityManager manager = CommandContextUtil.getActivityInstanceEntityManager();
org.flowable.task.service.TaskService taskService = CommandContextUtil.getTaskService(commandContext);
HistoricTaskService historicTaskService = CommandContextUtil.getHistoricTaskService(commandContext);
List<TaskEntity> taskEntities = taskService.findTasksByProcessInstanceId(processInstanceId);
if (!flag) {
ExecutionEntity execution = executionEntityManager.createChildExecution(processInstance);
execution.setVariable("assigneeList_"+dynamicUserTaskBuilder.getId(), Arrays.asList(dynamicUserTaskBuilder.getAssignee()));
ActivityInstanceEntity activityInstance = manager.findUnfinishedActivityInstance(execution);
// 删除当前活动任务
String parentId ="";
for (TaskEntity taskEntity : taskEntities) {
taskEntity.getIdentityLinks().stream().forEach(identityLinkEntity -> {
taskEntity.deleteUserIdentityLink(identityLinkEntity.getUserId(), "candidate");
taskEntity.deleteUserIdentityLink(identityLinkEntity.getUserId(), "participant");
});
if (taskEntity.getTaskDefinitionKey().equals(currentFlowElement.getId())) {
taskService.deleteTask(taskEntity, true);
}
//得到父级实例
ExecutionEntity executionEntity = executionEntityManager.findById(taskEntity.getExecutionId());
parentId = executionEntity.getParentId();
}
//删除相关联的实例 特别注意如果是会签另一个实例已同意所以进程未删除
if (StringUtils.isNotBlank(parentId)) {
ExecutionEntity parentExecution = executionEntityManager.findById(parentId);
List<ExecutionEntity> executions = executionEntityManager.findChildExecutionsByParentExecutionId(parentId);
for (ExecutionEntity childExecution : executions) {
if (!childExecution.getId().equals(execution.getId())) {
jobService.deleteJobsByExecutionId(childExecution.getId());
variableService.deleteVariablesByExecutionId(childExecution.getId());
executionEntityManager.delete(childExecution);
}
}
if (StringUtils.isNotBlank(parentExecution.getActivityId())) {
jobService.deleteJobsByExecutionId(parentExecution.getId());
variableService.deleteVariablesByExecutionId(parentExecution.getId());
executionEntityManager.delete(parentExecution);
System.out.println("删除父实例");
}
}
List<HistoricTaskInstanceEntity> historyList = historicTaskService.findHistoricTasksByProcessInstanceId(execution.getProcessInstanceId());
for (HistoricTaskInstanceEntity history : historyList) {
if (history.getTaskDefinitionKey().equals(currentFlowElement.getId())) {
history.setDeleteReason("加签被删除");
history.setEndTime(new Date());
historicTaskService.updateHistoricTask(history,false);
}
}
//任务节点结束
if (activityInstance!=null) {
activityInstance.setEndTime(new Date());
manager.update(activityInstance);
}
//设置活动后的节点
UserTask userTask = (UserTask) bpmnModel.getProcessById(processDefinitionEntity.getKey()).getFlowElement(dynamicUserTaskBuilder.getId());
execution.setCurrentFlowElement(userTask);
Context.getAgenda().planContinueProcessOperation(execution);
}else {
processInstance.setVariable("assigneeList_"+dynamicUserTaskBuilder.getId(), Arrays.asList(dynamicUserTaskBuilder.getAssignee()));
}
}
}
测试
@Autowired
protected ManagementService managementService;
private void addSign(WfSignPo vo,FlowEnum type) {
managementService.executeCommand(new CustomInjectUserTaskInProcessInstanceCmd(task.getProcessInstanceId(), flag, dynamicUserTaskBuilder, task.getTaskDefinitionKey()));
}