Activiti60 驳回到任意节点(跳回驳回节点)

最近接手公司的crm系统,针对原先的工作流模块方面进行业务拓展
新增了转办、驳回到任意节点(跳回驳回节点)、跳过相同审批人等业务。

原系统activiti版本是6.0,之前只接触过5.x版本。acitviti6.x版本把pvm包都删了,执行计划的代码也进行了改造

参考了segmentfault.com/a/119000001… 大侠的博客

1:获取历史执行节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
scss复制代码/**
* 记录当前操作人为节点审批人 记录审批时长
* @Author: ruiwu
* @param param 转办他人参数
* @return 状态值
* @CreateDate: 2021/2/20 10:17
* @version: 1.0
* @status: done
*/
public List<HisNodeVo> getRunNodes(String procInstId) {
//procInstId 流程实例id
//查询流程运行到哪个节点了
Execution execution = runtimeService.createExecutionQuery()
.processInstanceId(procInstId)
.orderByProcessInstanceId()
.desc()
.list().get(0);
String activityId = execution.getActivityId();


Map<String,String> map= new LinkedHashMap<>();
// 获取流程历史中已执行节点,并按照节点在流程中执行先后顺序排序
List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(procInstId)
//用户任务
.activityType("userTask")
//已经执行的任务节点
.finished()
.orderByHistoricActivityInstanceEndTime()
.asc()
.list();

// 已执行的节点ID集合
if(CollUtil.isNotEmpty(historicActivityInstanceList)){
for (HistoricActivityInstance historicActivityInstance:historicActivityInstanceList){
String hisActId = historicActivityInstance.getActivityId();
if (hisActId.equals(activityId)){
break;
}
if(!map.containsKey(historicActivityInstance.getActivityId())){
map.put(historicActivityInstance.getActivityId(),historicActivityInstance.getActivityName());
}
}
}
if (CollUtil.isNotEmpty(map)){
return map.entrySet()
.stream()
.map(HisNodeVo::new)
.collect(Collectors.toList());
}
return Collections.emptyList();
}

此处引用了lombox

1
2
3
4
5
6
7
8
9
10
11
12
13
14
less复制代码@Data
@ApiModel("历史节点")
@NoArgsConstructor
public class HisNodeVo {
@ApiModelProperty("节点id")
private String activityId;
@ApiModelProperty("节点名")
private String activityName;

public HisNodeVo(Entry<String, String> node) {
this.activityId = node.getKey();
this.activityName = node.getValue();
}
}

实现效果

2:驳回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
scss复制代码public BaseResult<String> approve(ApproveParam param) {
// 办理人userId
String taskId = param.getTaskId();
// 审核意见
String opinion = param.getOpinion();
// 审批人的姓名+审批意见
Map<String, Object> map = new LinkedHashMap<>();
// 设置审批人
map.put(Constants.APPROVER_KEY,
Optional.ofNullable(SecurityUser.getUserId()).orElse(""));
// 审批 批准
if (param.getApproveStatus() == 0) {
//当前任务
Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult();
String executionId = currentTask.getExecutionId();
//获取流程定义
Object variable = runtimeService.getVariable(executionId,"turnDownNode");
if (variable != null){
String nodeAssign = runtimeService
.getVariable(executionId,"turnDownNodeAssign").toString();
map.put(Constants.COMMENTS_KEY, "【批准】" + opinion);
//设置流程变量
setVariablesByTaskIdAsMap(taskId, map);
//驳回重新提交
String targetNodeId = String.valueOf(variable);
managementService.executeCommand(new SetFlowNodeAndGoCmd(
currentTask.getId(), targetNodeId,nodeAssign));
runtimeService.removeVariable (executionId, "turnDownNode");
}else{
//审批结果
map.put(Constants.COMMENTS_KEY, "【批准】" + opinion);
map.put("approvalResult", "同意");
boolean mark = StringUtils.isNotBlank(param.getProcInstType()) &&
(param.getProcInstType().contains(Constants.KEY_NEWCLASS) ||
param.getProcInstType().contains(Constants.KEY_PRECLASS));
taskService.setAssignee(taskId,SecurityUser.getUserId());
// 设置流程变量
setVariablesByTaskIdAsMap(taskId, map);
setVariablesByTaskId(taskId, "批准");

//审批结果添加到缓存
cacheService.set(Constants.COMMENTS_KEY + param.getProcInstId(), Constant.ONE + "");
//完成任务
completeMyPersonalTask(taskId);
}
} else {
//驳回
map.put(Constants.COMMENTS_KEY, "【驳回】" + opinion);
map.put("approvalResult", "驳回");
//设置流程变量
setVariablesByTaskIdAsMap(taskId, map);
if (param.getApproveType() == Constant.FAIL){
setVariablesByTaskId(taskId, "驳回");
//审批结果添加到缓存
cacheService.set(Constants.COMMENTS_KEY + param.getProcInstId(), Constant.FAIL + "");
//完成任务
completeMyPersonalTask(taskId);
//记录流程状态-可忽略
this.updateProcessStatus(param.getProcInstId(),Constant.TWO);
}else{
//驳回到任意节点
//历史节点执行人
String targetNodeAssign = this.getRunNodes(param.getProcInstId(), param.getRunNodeId());
log.info("驳回 历史节点执行人= " + targetNodeAssign);
//当前任务
if (param.getTurnType() == Constant.ONE){
Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult();
String executionId = currentTask.getExecutionId();

//驳回到目标节点携带参数,标记当前节点,然后直接跳转
runtimeService.setVariable (executionId, "turnDownNode",
currentTask.getTaskDefinitionKey());
runtimeService.setVariable (executionId, "turnDownNodeAssign",
currentTask.getAssignee());
}
managementService.executeCommand(new SetFlowNodeAndGoCmd(
param.getTaskId(), param.getRunNodeId() ,targetNodeAssign));
}

//驳回推送钉钉消息-可忽略
ruTaskService.sendRejectProcessNotice(param.getProcInstId());
}

return new BaseResult<String>().ok();
}


/**
* 根据提供节点和执行对象id,进行跳转命令
* @author yzyx
*/
@Slf4j
public class SetFlowNodeAndGoCmd implements Command<Void> {

/**
* 任务id
*/
private String taskId;
/**
* 目标节点
*/
private String runNodeId;
/**
* 目标节点审批人
*/
private String targetNodeAssign;


public SetFlowNodeAndGoCmd(String taskId,String runNodeId,String targetNodeAssign){
this.taskId = taskId;
this.runNodeId = runNodeId;
this.targetNodeAssign = targetNodeAssign;
}

@Override
public Void execute(CommandContext commandContext){
ActivitiEngineAgenda agenda = commandContext.getAgenda();
TaskEntityManager taskEntityManager = commandContext.getTaskEntityManager();
TaskEntity taskEntity = taskEntityManager.findById(taskId);
// 执行实例 id
String executionId = taskEntity.getExecutionId();
log.info("executionId = " + executionId);
String processDefinitionId = taskEntity.getProcessDefinitionId();
ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager();
HistoryManager historyManager = commandContext.getHistoryManager();
// 执行实例对象
ExecutionEntity executionEntity = executionEntityManager.findById(executionId);
Process process = ProcessDefinitionUtil.getProcess(processDefinitionId);
FlowElement flowElement = process.getFlowElement(runNodeId);
if (flowElement == null) {
throw new RuntimeException("目标节点不存在");
}
executionEntity.setVariable("USER_ID",targetNodeAssign);
//去掉无用的变量,不去掉,会导致很多莫名奇妙的问题
executionEntity.removeVariable("loopCounter");
//去掉多实例的变量,如果变量不知道是啥,自己从节点定义里查
executionEntity.removeVariable("cdp_atuser");
//要激活交路径
executionEntity.setActive(true);
// 将历史活动表更新
historyManager.recordActivityEnd(executionEntity, "jump");
// 设置当前流程
executionEntity.setCurrentFlowElement(flowElement);
// 跳转, 触发执行实例运转
agenda.planContinueProcessInCompensation(executionEntity);

// 从runtime 表中删除当前任务
taskEntityManager.delete(taskId);
// 将历史任务表更新, 历史任务标记为完成
historyManager.recordTaskEnd(taskId, "jump");
return null;
}

}

/***
* 查询历史节点执行人
* @param procInstId procInstId
* @param targetNodeId 目标节点
* @return 执行人
*/
private String getRunNodes(String procInstId, String targetNodeId) {
String assignee =SecurityUser.getUserId();

// 获取流程历史中已执行节点,并按照节点在流程中执行先后顺序排序
List<HistoricActivityInstance> instanceList = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(procInstId)
//用户任务
.activityId(targetNodeId)
//已经执行的任务节点
.finished()
.orderByHistoricActivityInstanceEndTime()
.asc()
.list();
if (CollUtil.isNotEmpty(instanceList)){
assignee = instanceList.get(0).getAssignee();
}
Date endTime = instanceList.get(0).getEndTime();
if (CollUtil.isNotEmpty(instanceList)){
for (HistoricActivityInstance activityInstance : instanceList) {
if (activityInstance.getActivityType().equals("olduserTask")){
assignee = activityInstance.getAssignee();
break;
}else{
if (endTime.getTime() < activityInstance.getEndTime().getTime()){
endTime = activityInstance.getEndTime();
assignee = activityInstance.getAssignee();
}
}
}
}

return assignee;
}

@Data
@ApiModel("审批参数")
public class ApproveParam {

@ApiModelProperty("任务Id")
private String taskId;

@ApiModelProperty("流程实例id")
private String procInstId;

@ApiModelProperty("通过-0,拒绝-1")
private int approveStatus;

@ApiModelProperty("0 驳回到发起节点 即原先的驳回重新提交 1 驳回到非发起节点")
private int approveType = 0;

@ApiModelProperty("审核意见")
private String opinion;

@ApiModelProperty(value = "流程类型")
private String procInstType;

@ApiModelProperty("开班申请需-传教师Id")
private String teacherId;

@ApiModelProperty("驳回 指定的运行节点id")
private String runNodeId;

@ApiModelProperty("0 驳回重新流转 1驳回审批通过后返回本节点")
private int turnType;

}

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%