Commit 5679b4ef95b8a62ceeeef3256353239c04ef9e78

Authored by jason
1 parent 3a433e82

仿钉钉流程设计- 新增发起人节点

yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeType.java
@@ -19,18 +19,20 @@ public enum BpmSimpleModelNodeType implements IntArrayValuable { @@ -19,18 +19,20 @@ public enum BpmSimpleModelNodeType implements IntArrayValuable {
19 19
20 // TODO @jaosn:-1、0、1、4、-2 是前端已经定义好的么?感觉未来可以考虑搞成和 BPMN 尽量一致的单词哈;类似 usertask 用户审批; 20 // TODO @jaosn:-1、0、1、4、-2 是前端已经定义好的么?感觉未来可以考虑搞成和 BPMN 尽量一致的单词哈;类似 usertask 用户审批;
21 // @芋艿 感觉还是用 START_NODE . END_NODE 比较好. 21 // @芋艿 感觉还是用 START_NODE . END_NODE 比较好.
  22 + // 0 1 开始和结束
22 START_NODE(0, "开始节点"), 23 START_NODE(0, "开始节点"),
23 - END_NODE(-2, "结束节点"), // TODO @jaosn:挪到 START_EVENT_NODE 后; 24 + END_NODE(1, "结束节点"), // TODO @jaosn:挪到 START_EVENT_NODE 后;
24 25
25 - APPROVE_NODE(1, "审批人节点"), // TODO @jaosn:是不是这里从 10 开始好点;相当于说,0-9 给开始和结束;10-19 给各种节点;20-29 给各种条件; TODO 后面改改  
26 - COPY_NODE(2, "抄送人节点"), 26 + // 10 ~ 49 各种节点
  27 + START_USER_NODE(10, "发起人节点"), // 发起人节点。前端的开始节点,Id 固定
  28 + APPROVE_NODE(11, "审批人节点"), // TODO @jaosn:是不是这里从 10 开始好点;相当于说,0-9 给开始和结束;10-19 给各种节点;20-29 给各种条件; TODO 后面改改
  29 + COPY_NODE(12, "抄送人节点"),
27 30
28 - CONDITION_NODE(3, "条件节点"), // 用于构建流转条件的表达式  
29 - CONDITION_BRANCH_NODE(4, "条件分支节点"), // TODO @jason:是不是改成叫 条件分支?  
30 - PARALLEL_BRANCH_NODE(5, "并行分支节点"), // TODO @jason:是不是一个 并行分支 ?就可以啦? 后面是否去掉并行网关。只用包容网关  
31 -// PARALLEL_BRANCH_JOIN_NODE(6, "并行分支聚合节点"),  
32 - INCLUSIVE_BRANCH_FORK_NODE(7, "包容网关分叉节点"),  
33 - INCLUSIVE_BRANCH_JOIN_NODE(8, "包容网关聚合节点"), 31 + // 50 ~ 条件分支
  32 + CONDITION_NODE(50, "条件节点"), // 用于构建流转条件的表达式
  33 + CONDITION_BRANCH_NODE(51, "条件分支节点"), // TODO @jason:是不是改成叫 条件分支?
  34 + PARALLEL_BRANCH_NODE(52, "并行分支节点"), // TODO @jason:是不是一个 并行分支 ?就可以啦? 后面是否去掉并行网关。只用包容网关
  35 + INCLUSIVE_BRANCH_NODE(53, "包容分叉节点"),
34 // TODO @jason:建议整合 join,最终只有 条件分支、并行分支、包容分支,三种~ 36 // TODO @jason:建议整合 join,最终只有 条件分支、并行分支、包容分支,三种~
35 // TODO @芋艿。 感觉还是分开好理解一点,也好处理一点。前端结构中把聚合节点显示并传过来。 37 // TODO @芋艿。 感觉还是分开好理解一点,也好处理一点。前端结构中把聚合节点显示并传过来。
36 ; 38 ;
@@ -48,7 +50,7 @@ public enum BpmSimpleModelNodeType implements IntArrayValuable { @@ -48,7 +50,7 @@ public enum BpmSimpleModelNodeType implements IntArrayValuable {
48 public static boolean isBranchNode(Integer type) { 50 public static boolean isBranchNode(Integer type) {
49 return Objects.equals(CONDITION_BRANCH_NODE.getType(), type) 51 return Objects.equals(CONDITION_BRANCH_NODE.getType(), type)
50 || Objects.equals(PARALLEL_BRANCH_NODE.getType(), type) 52 || Objects.equals(PARALLEL_BRANCH_NODE.getType(), type)
51 - || Objects.equals(INCLUSIVE_BRANCH_FORK_NODE.getType(), type) ; 53 + || Objects.equals(INCLUSIVE_BRANCH_NODE.getType(), type) ;
52 } 54 }
53 55
54 public static BpmSimpleModelNodeType valueOf(Integer type) { 56 public static BpmSimpleModelNodeType valueOf(Integer type) {
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/BpmTaskCandidateDeptLeaderMultiStrategy.java
1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy; 1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
2 2
3 -import cn.hutool.core.collection.CollUtil;  
4 import cn.hutool.core.lang.Assert; 3 import cn.hutool.core.lang.Assert;
5 import cn.iocoder.yudao.framework.common.util.string.StrUtils; 4 import cn.iocoder.yudao.framework.common.util.string.StrUtils;
6 import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy; 5 import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
@@ -9,7 +8,6 @@ import cn.iocoder.yudao.module.system.api.dept.DeptApi; @@ -9,7 +8,6 @@ import cn.iocoder.yudao.module.system.api.dept.DeptApi;
9 import org.flowable.engine.delegate.DelegateExecution; 8 import org.flowable.engine.delegate.DelegateExecution;
10 import org.springframework.stereotype.Component; 9 import org.springframework.stereotype.Component;
11 10
12 -import java.util.List;  
13 import java.util.Set; 11 import java.util.Set;
14 12
15 /** 13 /**
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnModelConstants.java
@@ -99,4 +99,14 @@ public interface BpmnModelConstants { @@ -99,4 +99,14 @@ public interface BpmnModelConstants {
99 */ 99 */
100 String BUTTON_SETTING_ELEMENT_ENABLE_ATTRIBUTE = "enable"; 100 String BUTTON_SETTING_ELEMENT_ENABLE_ATTRIBUTE = "enable";
101 101
  102 + /**
  103 + * BPMN Start Event Node Id
  104 + */
  105 + String START_EVENT_NODE_ID = "StartEvent";
  106 +
  107 + /**
  108 + * BPMN Start Event Node Name
  109 + */
  110 + String START_EVENT_NODE_NAME = "开始";
  111 +
102 } 112 }
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnVariableConstants.java
@@ -31,6 +31,12 @@ public class BpmnVariableConstants { @@ -31,6 +31,12 @@ public class BpmnVariableConstants {
31 public static final String PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES = "PROCESS_START_USER_SELECT_ASSIGNEES"; 31 public static final String PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES = "PROCESS_START_USER_SELECT_ASSIGNEES";
32 32
33 /** 33 /**
  34 + * 流程实例的变量 - 用于判断流程实例变量节点是否驳回. 格式 RETURN_FLAG_{节点 id}
  35 + *
  36 + * @see ProcessInstance#getProcessVariables()
  37 + */
  38 + public static final String PROCESS_INSTANCE_VARIABLE_RETURN_FLAG = "RETURN_FLAG_%s";
  39 + /**
34 * 任务的变量 - 状态 40 * 任务的变量 - 状态
35 * 41 *
36 * @see org.flowable.task.api.Task#getTaskLocalVariables() 42 * @see org.flowable.task.api.Task#getTaskLocalVariables()
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
@@ -9,7 +9,10 @@ import cn.hutool.core.util.*; @@ -9,7 +9,10 @@ import cn.hutool.core.util.*;
9 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 9 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
10 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; 10 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
11 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.RejectHandler; 11 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.RejectHandler;
12 -import cn.iocoder.yudao.module.bpm.enums.definition.*; 12 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType;
  13 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModeConditionType;
  14 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType;
  15 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskApproveMethodEnum;
13 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants; 16 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
14 import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmCopyTaskDelegate; 17 import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmCopyTaskDelegate;
15 import cn.iocoder.yudao.module.bpm.framework.flowable.core.simplemodel.SimpleModelConditionGroups; 18 import cn.iocoder.yudao.module.bpm.framework.flowable.core.simplemodel.SimpleModelConditionGroups;
@@ -17,12 +20,18 @@ import org.flowable.bpmn.BpmnAutoLayout; @@ -17,12 +20,18 @@ import org.flowable.bpmn.BpmnAutoLayout;
17 import org.flowable.bpmn.model.Process; 20 import org.flowable.bpmn.model.Process;
18 import org.flowable.bpmn.model.*; 21 import org.flowable.bpmn.model.*;
19 22
20 -import java.util.*; 23 +import java.util.ArrayList;
  24 +import java.util.List;
  25 +import java.util.Map;
  26 +import java.util.Objects;
21 27
22 import static cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.OperationButtonSetting; 28 import static cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.OperationButtonSetting;
23 import static cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.TimeoutHandler; 29 import static cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.TimeoutHandler;
24 import static cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType.*; 30 import static cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeType.*;
  31 +import static cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskApproveTypeEnum.USER;
  32 +import static cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskAssignStartUserHandlerTypeEnum.SKIP;
25 import static cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskTimeoutHandlerTypeEnum.REMINDER; 33 import static cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskTimeoutHandlerTypeEnum.REMINDER;
  34 +import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum.START_USER;
26 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*; 35 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*;
27 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.SimpleModelConstants.*; 36 import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.SimpleModelConstants.*;
28 import static org.flowable.bpmn.constants.BpmnXMLConstants.*; 37 import static org.flowable.bpmn.constants.BpmnXMLConstants.*;
@@ -76,19 +85,29 @@ public class SimpleModelUtils { @@ -76,19 +85,29 @@ public class SimpleModelUtils {
76 process.setExecutable(Boolean.TRUE); // TODO @jason:这个是必须设置的么? 85 process.setExecutable(Boolean.TRUE); // TODO @jason:这个是必须设置的么?
77 bpmnModel.addProcess(process); 86 bpmnModel.addProcess(process);
78 87
79 - // 前端模型数据结构  
80 - // 从 SimpleModel 构建 FlowNode 并添加到 Main Process  
81 - traverseNodeToBuildFlowNode(simpleModelNode, process); 88 + // 目前前端的第一个节点是 发起人节点。这里构建一个StartNode. 用于创建 Bpmn 的 StartEvent 节点
  89 + BpmSimpleModelNodeVO startNode = buildStartSimpleModelNode();
  90 + startNode.setChildNode(simpleModelNode);
  91 + // 从 前端模型数据结构 SimpleModel 构建 FlowNode 并添加到 Main Process
  92 + traverseNodeToBuildFlowNode(startNode, process);
82 // 找到 end event 93 // 找到 end event
83 EndEvent endEvent = (EndEvent) CollUtil.findOne(process.getFlowElements(), item -> item instanceof EndEvent); 94 EndEvent endEvent = (EndEvent) CollUtil.findOne(process.getFlowElements(), item -> item instanceof EndEvent);
84 95
85 // 构建并添加节点之间的连线 Sequence Flow 96 // 构建并添加节点之间的连线 Sequence Flow
86 - traverseNodeToBuildSequenceFlow(process, simpleModelNode, endEvent.getId()); 97 + traverseNodeToBuildSequenceFlow(process, startNode, endEvent.getId());
87 // 自动布局 98 // 自动布局
88 new BpmnAutoLayout(bpmnModel).execute(); 99 new BpmnAutoLayout(bpmnModel).execute();
89 return bpmnModel; 100 return bpmnModel;
90 } 101 }
91 102
  103 + private static BpmSimpleModelNodeVO buildStartSimpleModelNode() {
  104 + BpmSimpleModelNodeVO startNode = new BpmSimpleModelNodeVO();
  105 + startNode.setId(START_EVENT_NODE_ID);
  106 + startNode.setName(START_EVENT_NODE_NAME);
  107 + startNode.setType(START_NODE.getType());
  108 + return startNode;
  109 + }
  110 +
92 // TODO @芋艿:在优化下这个注释 111 // TODO @芋艿:在优化下这个注释
93 private static void traverseNodeToBuildSequenceFlow(Process process, BpmSimpleModelNodeVO node, String targetNodeId) { 112 private static void traverseNodeToBuildSequenceFlow(Process process, BpmSimpleModelNodeVO node, String targetNodeId) {
94 // 1.1 无效节点返回 113 // 1.1 无效节点返回
@@ -288,6 +307,11 @@ public class SimpleModelUtils { @@ -288,6 +307,11 @@ public class SimpleModelUtils {
288 list.add(endEvent); 307 list.add(endEvent);
289 break; 308 break;
290 } 309 }
  310 + case START_USER_NODE: { // 发起人节点
  311 + UserTask userTask = convertStartUserNode(node);
  312 + list.add(userTask);
  313 + break;
  314 + }
291 case APPROVE_NODE: { // 审批节点 315 case APPROVE_NODE: { // 审批节点
292 List<FlowElement> flowElements = convertApproveNode(node); 316 List<FlowElement> flowElements = convertApproveNode(node);
293 list.addAll(flowElements); 317 list.addAll(flowElements);
@@ -309,14 +333,8 @@ public class SimpleModelUtils { @@ -309,14 +333,8 @@ public class SimpleModelUtils {
309 break; 333 break;
310 } 334 }
311 335
312 - case INCLUSIVE_BRANCH_FORK_NODE: {  
313 - InclusiveGateway inclusiveGateway = convertInclusiveBranchNode(node, Boolean.TRUE);  
314 - list.add(inclusiveGateway);  
315 - break;  
316 - }  
317 - case INCLUSIVE_BRANCH_JOIN_NODE: {  
318 - InclusiveGateway inclusiveGateway = convertInclusiveBranchNode(node, Boolean.FALSE);  
319 - list.add(inclusiveGateway); 336 + case INCLUSIVE_BRANCH_NODE: {
  337 + // TODO jason 待实现
320 break; 338 break;
321 } 339 }
322 default: { 340 default: {
@@ -326,6 +344,11 @@ public class SimpleModelUtils { @@ -326,6 +344,11 @@ public class SimpleModelUtils {
326 return list; 344 return list;
327 } 345 }
328 346
  347 + private static UserTask convertStartUserNode(BpmSimpleModelNodeVO node) {
  348 + return buildBpmnStartUserTask(node);
  349 + }
  350 +
  351 +
329 private static List<FlowElement> convertApproveNode(BpmSimpleModelNodeVO node) { 352 private static List<FlowElement> convertApproveNode(BpmSimpleModelNodeVO node) {
330 List<FlowElement> flowElements = new ArrayList<>(); 353 List<FlowElement> flowElements = new ArrayList<>();
331 UserTask userTask = buildBpmnUserTask(node); 354 UserTask userTask = buildBpmnUserTask(node);
@@ -444,7 +467,7 @@ public class SimpleModelUtils { @@ -444,7 +467,7 @@ public class SimpleModelUtils {
444 467
445 // 如果不是审批人节点,则直接返回 468 // 如果不是审批人节点,则直接返回
446 addExtensionElement(userTask, USER_TASK_APPROVE_TYPE, StrUtil.toStringOrNull(node.getApproveType())); 469 addExtensionElement(userTask, USER_TASK_APPROVE_TYPE, StrUtil.toStringOrNull(node.getApproveType()));
447 - if (ObjectUtil.notEqual(node.getApproveType(), BpmUserTaskApproveTypeEnum.USER.getType())) { 470 + if (ObjectUtil.notEqual(node.getApproveType(), USER.getType())) {
448 return userTask; 471 return userTask;
449 } 472 }
450 473
@@ -576,17 +599,32 @@ public class SimpleModelUtils { @@ -576,17 +599,32 @@ public class SimpleModelUtils {
576 599
577 // ========== 各种 build 节点的方法 ========== 600 // ========== 各种 build 节点的方法 ==========
578 601
579 - private static StartEvent convertStartNode(BpmSimpleModelNodeVO node) { 602 + private static StartEvent convertStartNode(BpmSimpleModelNodeVO node) {
580 StartEvent startEvent = new StartEvent(); 603 StartEvent startEvent = new StartEvent();
581 startEvent.setId(node.getId()); 604 startEvent.setId(node.getId());
582 startEvent.setName(node.getName()); 605 startEvent.setName(node.getName());
583 -  
584 // TODO 芋艿 + jason:要不要在开启节点后面,加一个“发起人”任务节点,然后自动审批通过 606 // TODO 芋艿 + jason:要不要在开启节点后面,加一个“发起人”任务节点,然后自动审批通过
585 // @芋艿 这个是不是由前端来实现。 默认开始节点后面跟一个 “发起人”的审批节点(审批人是发起人自己)。 607 // @芋艿 这个是不是由前端来实现。 默认开始节点后面跟一个 “发起人”的审批节点(审批人是发起人自己)。
586 - // 我看有些平台这个审批节点允许删除,有些不允许。由用户决定  
587 return startEvent; 608 return startEvent;
588 } 609 }
589 610
  611 + private static UserTask buildBpmnStartUserTask(BpmSimpleModelNodeVO node) {
  612 + UserTask userTask = new UserTask();
  613 + userTask.setId(node.getId());
  614 + userTask.setName(node.getName());
  615 + // 人工审批
  616 + addExtensionElement(userTask, USER_TASK_APPROVE_TYPE, USER.getType().toString());
  617 + // 候选人策略为发起人自己
  618 + addCandidateElements(START_USER.getStrategy(),null, userTask);
  619 + // 添加表单字段权限属性元素
  620 + addFormFieldsPermission(node.getFieldsPermission(), userTask);
  621 + // 添加操作按钮配置属性元素.
  622 + addButtonsSetting(node.getButtonsSetting(), userTask);
  623 + // 使用自动通过策略。TODO @芋艿 复用了SKIP, 是否需要新加一个策略
  624 + addAssignStartUserHandlerType(SKIP.getType(), userTask);
  625 +
  626 + return userTask;
  627 + }
590 private static EndEvent convertEndNode(BpmSimpleModelNodeVO node) { 628 private static EndEvent convertEndNode(BpmSimpleModelNodeVO node) {
591 EndEvent endEvent = new EndEvent(); 629 EndEvent endEvent = new EndEvent();
592 endEvent.setId(node.getId()); 630 endEvent.setId(node.getId());
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
@@ -59,6 +59,7 @@ import java.util.stream.Stream; @@ -59,6 +59,7 @@ import java.util.stream.Stream;
59 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 59 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
60 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; 60 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
61 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; 61 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
  62 +import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_RETURN_FLAG;
62 63
63 /** 64 /**
64 * 流程任务实例 Service 实现类 65 * 流程任务实例 Service 实现类
@@ -194,7 +195,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -194,7 +195,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
194 // 为什么判断 assignee 非空的情况下? 195 // 为什么判断 assignee 非空的情况下?
195 // 例如说:在审批人为空时,我们会有“自动审批通过”的策略,此时 userId 为 null,允许通过 196 // 例如说:在审批人为空时,我们会有“自动审批通过”的策略,此时 userId 为 null,允许通过
196 if (StrUtil.isNotBlank(task.getAssignee()) 197 if (StrUtil.isNotBlank(task.getAssignee())
197 - && ObjectUtil.notEqual(userId, NumberUtils.parseLong(task.getAssignee()))) { 198 + && ObjectUtil.notEqual(userId, NumberUtils.parseLong(task.getAssignee()))) {
198 throw exception(TASK_OPERATE_FAIL_ASSIGN_NOT_SELF); 199 throw exception(TASK_OPERATE_FAIL_ASSIGN_NOT_SELF);
199 } 200 }
200 return task; 201 return task;
@@ -618,6 +619,9 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -618,6 +619,9 @@ public class BpmTaskServiceImpl implements BpmTaskService {
618 updateTaskStatusAndReason(task.getId(), BpmTaskStatusEnum.RETURN.getStatus(), reqVO.getReason()); 619 updateTaskStatusAndReason(task.getId(), BpmTaskStatusEnum.RETURN.getStatus(), reqVO.getReason());
619 }); 620 });
620 621
  622 + // 设置流程变量节点驳回标记。用于驳回到节点。不执行 BpmUserTaskAssignStartUserHandlerTypeEnum 策略 而自动通过
  623 + runtimeService.setVariable(currentTask.getProcessInstanceId(),
  624 + String.format(PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, reqVO.getTargetTaskDefinitionKey()), Boolean.TRUE);
621 // 3. 执行驳回 625 // 3. 执行驳回
622 runtimeService.createChangeActivityStateBuilder() 626 runtimeService.createChangeActivityStateBuilder()
623 .processInstanceId(currentTask.getProcessInstanceId()) 627 .processInstanceId(currentTask.getProcessInstanceId())
@@ -894,7 +898,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -894,7 +898,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
894 898
895 /** 899 /**
896 * 重要补充说明:该方法目前主要有两个情况会调用到: 900 * 重要补充说明:该方法目前主要有两个情况会调用到:
897 - * 901 + * <p>
898 * 1. 或签场景 + 审批通过:一个或签有多个审批时,如果 A 审批通过,其它或签 B、C 等任务会被 Flowable 自动删除,此时需要通过该方法更新状态为已取消 902 * 1. 或签场景 + 审批通过:一个或签有多个审批时,如果 A 审批通过,其它或签 B、C 等任务会被 Flowable 自动删除,此时需要通过该方法更新状态为已取消
899 * 2. 审批不通过:在 {@link #rejectTask(Long, BpmTaskRejectReqVO)} 不通过时,对于加签的任务,不会被 Flowable 删除,此时需要通过该方法更新状态为已取消 903 * 2. 审批不通过:在 {@link #rejectTask(Long, BpmTaskRejectReqVO)} 不通过时,对于加签的任务,不会被 Flowable 删除,此时需要通过该方法更新状态为已取消
900 */ 904 */
@@ -933,46 +937,50 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -933,46 +937,50 @@ public class BpmTaskServiceImpl implements BpmTaskService {
933 log.error("[processTaskAssigned][taskId({}) 没有找到流程实例]", task.getId()); 937 log.error("[processTaskAssigned][taskId({}) 没有找到流程实例]", task.getId());
934 return; 938 return;
935 } 939 }
936 -  
937 // 审批人与提交人为同一人时,根据策略进行处理 940 // 审批人与提交人为同一人时,根据策略进行处理
938 if (StrUtil.equals(task.getAssignee(), processInstance.getStartUserId())) { 941 if (StrUtil.equals(task.getAssignee(), processInstance.getStartUserId())) {
939 - BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processInstance.getProcessDefinitionId());  
940 - if (bpmnModel == null) {  
941 - log.error("[processTaskAssigned][taskId({}) 没有找到流程模型]", task.getId());  
942 - return;  
943 - }  
944 - FlowElement userTaskElement = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());  
945 - Integer assignStartUserHandlerType = BpmnModelUtils.parseAssignStartUserHandlerType(userTaskElement);  
946 -  
947 - // 情况一:自动跳过  
948 - if (ObjectUtils.equalsAny(assignStartUserHandlerType,  
949 - BpmUserTaskAssignStartUserHandlerTypeEnum.SKIP.getType())) {  
950 - getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())  
951 - .setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_SKIP.getReason()));  
952 - return;  
953 - }  
954 - // 情况二:转交给部门负责人审批  
955 - if (ObjectUtils.equalsAny(assignStartUserHandlerType,  
956 - BpmUserTaskAssignStartUserHandlerTypeEnum.TRANSFER_DEPT_LEADER.getType())) {  
957 - AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));  
958 - Assert.notNull(startUser, "提交人({})信息为空", processInstance.getStartUserId());  
959 - DeptRespDTO dept = startUser.getDeptId() != null ? deptApi.getDept(startUser.getDeptId()) : null;  
960 - Assert.notNull(dept, "提交人({})部门({})信息为空", processInstance.getStartUserId(), startUser.getDeptId());  
961 - // 找不到部门负责人的情况下,自动审批通过  
962 - // noinspection DataFlowIssue  
963 - if (dept.getLeaderUserId() == null) {  
964 - getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())  
965 - .setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_DEPT_LEADER_NOT_FOUND.getReason())); 942 + // 判断是否为回退或者驳回
  943 + Boolean returnTaskFlag = runtimeService.getVariable(processInstance.getProcessInstanceId(),
  944 + String.format(PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, task.getTaskDefinitionKey()), Boolean.class);
  945 + if (!BooleanUtil.isTrue(returnTaskFlag)) { // 如果是回退或者驳回不走这个策略
  946 + BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processInstance.getProcessDefinitionId());
  947 + if (bpmnModel == null) {
  948 + log.error("[processTaskAssigned][taskId({}) 没有找到流程模型]", task.getId());
966 return; 949 return;
967 } 950 }
968 - // 找得到部门负责人的情况下,修改负责人  
969 - if (ObjectUtil.notEqual(dept.getLeaderUserId(), startUser.getId())) {  
970 - getSelf().transferTask(Long.valueOf(task.getAssignee()), new BpmTaskTransferReqVO()  
971 - .setId(task.getId()).setAssigneeUserId(dept.getLeaderUserId())  
972 - .setReason(BpmReasonEnum.ASSIGN_START_USER_TRANSFER_DEPT_LEADER.getReason())); 951 + FlowElement userTaskElement = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
  952 + Integer assignStartUserHandlerType = BpmnModelUtils.parseAssignStartUserHandlerType(userTaskElement);
  953 +
  954 + // 情况一:自动跳过
  955 + if (ObjectUtils.equalsAny(assignStartUserHandlerType,
  956 + BpmUserTaskAssignStartUserHandlerTypeEnum.SKIP.getType())) {
  957 + getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())
  958 + .setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_SKIP.getReason()));
973 return; 959 return;
974 } 960 }
975 - // 如果部门负责人是自己,还是自己审批吧~ 961 + // 情况二:转交给部门负责人审批
  962 + if (ObjectUtils.equalsAny(assignStartUserHandlerType,
  963 + BpmUserTaskAssignStartUserHandlerTypeEnum.TRANSFER_DEPT_LEADER.getType())) {
  964 + AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));
  965 + Assert.notNull(startUser, "提交人({})信息为空", processInstance.getStartUserId());
  966 + DeptRespDTO dept = startUser.getDeptId() != null ? deptApi.getDept(startUser.getDeptId()) : null;
  967 + Assert.notNull(dept, "提交人({})部门({})信息为空", processInstance.getStartUserId(), startUser.getDeptId());
  968 + // 找不到部门负责人的情况下,自动审批通过
  969 + // noinspection DataFlowIssue
  970 + if (dept.getLeaderUserId() == null) {
  971 + getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())
  972 + .setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_DEPT_LEADER_NOT_FOUND.getReason()));
  973 + return;
  974 + }
  975 + // 找得到部门负责人的情况下,修改负责人
  976 + if (ObjectUtil.notEqual(dept.getLeaderUserId(), startUser.getId())) {
  977 + getSelf().transferTask(Long.valueOf(task.getAssignee()), new BpmTaskTransferReqVO()
  978 + .setId(task.getId()).setAssigneeUserId(dept.getLeaderUserId())
  979 + .setReason(BpmReasonEnum.ASSIGN_START_USER_TRANSFER_DEPT_LEADER.getReason()));
  980 + return;
  981 + }
  982 + // 如果部门负责人是自己,还是自己审批吧~
  983 + }
976 } 984 }
977 } 985 }
978 986