Commit 6217d5acb1067142fe9f54994c4cdff5540c43cb

Authored by jason
2 parents da690a2b 56664ca0

Merge remote-tracking branch 'origin/feature/bpm' into feature/bpm

yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java
1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior; 1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.hutool.core.util.ObjectUtil;  
5 import cn.hutool.core.util.RandomUtil; 4 import cn.hutool.core.util.RandomUtil;
6 -import cn.hutool.extra.spring.SpringUtil;  
7 -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskApproveReqVO;  
8 -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRejectReqVO;  
9 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskApproveTypeEnum;  
10 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskAssignEmptyHandlerTypeEnum;  
11 -import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum;  
12 import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker; 5 import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
13 -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;  
14 -import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;  
15 import lombok.Setter; 6 import lombok.Setter;
16 import lombok.extern.slf4j.Slf4j; 7 import lombok.extern.slf4j.Slf4j;
17 import org.flowable.bpmn.model.UserTask; 8 import org.flowable.bpmn.model.UserTask;
@@ -22,8 +13,7 @@ import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; @@ -22,8 +13,7 @@ import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
22 import org.flowable.engine.impl.util.TaskHelper; 13 import org.flowable.engine.impl.util.TaskHelper;
23 import org.flowable.task.service.TaskService; 14 import org.flowable.task.service.TaskService;
24 import org.flowable.task.service.impl.persistence.entity.TaskEntity; 15 import org.flowable.task.service.impl.persistence.entity.TaskEntity;
25 -import org.springframework.transaction.support.TransactionSynchronization;  
26 -import org.springframework.transaction.support.TransactionSynchronizationManager; 16 +import org.springframework.transaction.annotation.Transactional;
27 17
28 import java.util.List; 18 import java.util.List;
29 import java.util.Set; 19 import java.util.Set;
@@ -46,6 +36,7 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior { @@ -46,6 +36,7 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
46 } 36 }
47 37
48 @Override 38 @Override
  39 + @Transactional(rollbackFor = Exception.class)
49 protected void handleAssignments(TaskService taskService, String assignee, String owner, 40 protected void handleAssignments(TaskService taskService, String assignee, String owner,
50 List<String> candidateUsers, List<String> candidateGroups, TaskEntity task, ExpressionManager expressionManager, 41 List<String> candidateUsers, List<String> candidateGroups, TaskEntity task, ExpressionManager expressionManager,
51 DelegateExecution execution, ProcessEngineConfigurationImpl processEngineConfiguration) { 42 DelegateExecution execution, ProcessEngineConfigurationImpl processEngineConfiguration) {
@@ -54,39 +45,7 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior { @@ -54,39 +45,7 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
54 // 第二步,设置作为负责人 45 // 第二步,设置作为负责人
55 if (assigneeUserId != null) { 46 if (assigneeUserId != null) {
56 TaskHelper.changeTaskAssignee(task, String.valueOf(assigneeUserId)); 47 TaskHelper.changeTaskAssignee(task, String.valueOf(assigneeUserId));
57 - return;  
58 } 48 }
59 -  
60 - // 特殊:处理需要自动通过、不通过的情况  
61 - Integer approveType = BpmnModelUtils.parseApproveType(userTask);  
62 - Integer assignEmptyHandlerType = BpmnModelUtils.parseAssignEmptyHandlerType(userTask);  
63 - TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {  
64 -  
65 - @Override  
66 - public void afterCommit() {  
67 - // 特殊情况一:【人工审核】审批人为空,根据配置是否要自动通过、自动拒绝  
68 - if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.USER.getType())) {  
69 - if (ObjectUtil.equal(assignEmptyHandlerType, BpmUserTaskAssignEmptyHandlerTypeEnum.APPROVE.getType())) {  
70 - SpringUtil.getBean(BpmTaskService.class).approveTask(null, new BpmTaskApproveReqVO()  
71 - .setId(task.getId()).setReason(BpmReasonEnum.ASSIGN_EMPTY_APPROVE.getReason()));  
72 - } else if (ObjectUtil.equal(assignEmptyHandlerType, BpmUserTaskAssignEmptyHandlerTypeEnum.REJECT.getType())) {  
73 - SpringUtil.getBean(BpmTaskService.class).rejectTask(null, new BpmTaskRejectReqVO()  
74 - .setId(task.getId()).setReason(BpmReasonEnum.ASSIGN_EMPTY_REJECT.getReason()));  
75 - }  
76 - // 特殊情况二:【自动审核】审批类型为自动通过、不通过  
77 - } else {  
78 - if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.AUTO_APPROVE.getType())) {  
79 - SpringUtil.getBean(BpmTaskService.class).approveTask(null, new BpmTaskApproveReqVO()  
80 - .setId(task.getId()).setReason(BpmReasonEnum.APPROVE_TYPE_AUTO_APPROVE.getReason()));  
81 - } else if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.AUTO_REJECT.getType())) {  
82 - SpringUtil.getBean(BpmTaskService.class).rejectTask(null, new BpmTaskRejectReqVO()  
83 - .setId(task.getId()).setReason(BpmReasonEnum.APPROVE_TYPE_AUTO_REJECT.getReason()));  
84 - }  
85 - }  
86 -  
87 - }  
88 -  
89 - });  
90 } 49 }
91 50
92 private Long calculateTaskCandidateUsers(DelegateExecution execution) { 51 private Long calculateTaskCandidateUsers(DelegateExecution execution) {
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnVariableConstants.java
@@ -30,10 +30,11 @@ public class BpmnVariableConstants { @@ -30,10 +30,11 @@ public class BpmnVariableConstants {
30 */ 30 */
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 - // TODO @芋艿:用于处理,驳回到发起人时,如果被自动通过的逻辑  
34 /** 33 /**
35 * 流程实例的变量 - 用于判断流程实例变量节点是否驳回. 格式 RETURN_FLAG_{节点 id} 34 * 流程实例的变量 - 用于判断流程实例变量节点是否驳回. 格式 RETURN_FLAG_{节点 id}
36 * 35 *
  36 + * 目的是:驳回到发起节点时,因为审批人与发起人相同,所以被自动通过。但是,此时还是希望不要自动通过
  37 + *
37 * @see ProcessInstance#getProcessVariables() 38 * @see ProcessInstance#getProcessVariables()
38 */ 39 */
39 public static final String PROCESS_INSTANCE_VARIABLE_RETURN_FLAG = "RETURN_FLAG_%s"; 40 public static final String PROCESS_INSTANCE_VARIABLE_RETURN_FLAG = "RETURN_FLAG_%s";
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java
@@ -196,7 +196,12 @@ public interface BpmTaskService { @@ -196,7 +196,12 @@ public interface BpmTaskService {
196 // ========== Event 事件相关方法 ========== 196 // ========== Event 事件相关方法 ==========
197 197
198 /** 198 /**
199 - * 处理 Task 创建事件,目前是更新它的状态为审批中 199 + * 处理 Task 创建事件,目前是
  200 + *
  201 + * 1. 更新它的状态为审批中
  202 + * 2. 处理自动通过的情况,例如说:1)无审批人时,是否自动通过、不通过;2)非【人工审核】时,是否自动通过、不通过
  203 + *
  204 + * 注意:它的触发时机,晚于 {@link #processTaskAssigned(Task)} 之后
200 * 205 *
201 * @param task 任务实体 206 * @param task 任务实体
202 */ 207 */
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
@@ -12,9 +12,7 @@ import cn.iocoder.yudao.framework.common.util.object.PageUtils; @@ -12,9 +12,7 @@ import cn.iocoder.yudao.framework.common.util.object.PageUtils;
12 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; 12 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
13 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; 13 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
14 import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; 14 import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
15 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskAssignStartUserHandlerTypeEnum;  
16 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskRejectHandlerType;  
17 -import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskTimeoutHandlerTypeEnum; 15 +import cn.iocoder.yudao.module.bpm.enums.definition.*;
18 import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum; 16 import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum;
19 import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum; 17 import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum;
20 import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskSignTypeEnum; 18 import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskSignTypeEnum;
@@ -620,10 +618,11 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -620,10 +618,11 @@ public class BpmTaskServiceImpl implements BpmTaskService {
620 updateTaskStatusAndReason(task.getId(), BpmTaskStatusEnum.RETURN.getStatus(), reqVO.getReason()); 618 updateTaskStatusAndReason(task.getId(), BpmTaskStatusEnum.RETURN.getStatus(), reqVO.getReason());
621 }); 619 });
622 620
623 - // 设置流程变量节点驳回标记。用于驳回到节点。不执行 BpmUserTaskAssignStartUserHandlerTypeEnum 策略 而自动通过 621 + // 3. 设置流程变量节点驳回标记:用于驳回到节点,不执行 BpmUserTaskAssignStartUserHandlerTypeEnum 策略。导致自动通过
624 runtimeService.setVariable(currentTask.getProcessInstanceId(), 622 runtimeService.setVariable(currentTask.getProcessInstanceId(),
625 String.format(PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, reqVO.getTargetTaskDefinitionKey()), Boolean.TRUE); 623 String.format(PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, reqVO.getTargetTaskDefinitionKey()), Boolean.TRUE);
626 - // 3. 执行驳回 624 +
  625 + // 4. 执行驳回
627 runtimeService.createChangeActivityStateBuilder() 626 runtimeService.createChangeActivityStateBuilder()
628 .processInstanceId(currentTask.getProcessInstanceId()) 627 .processInstanceId(currentTask.getProcessInstanceId())
629 .moveActivityIdsToSingleActivityId(returnTaskKeyList, // 当前要跳转的节点列表( 1 或多) 628 .moveActivityIdsToSingleActivityId(returnTaskKeyList, // 当前要跳转的节点列表( 1 或多)
@@ -889,12 +888,55 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -889,12 +888,55 @@ public class BpmTaskServiceImpl implements BpmTaskService {
889 888
890 @Override 889 @Override
891 public void processTaskCreated(Task task) { 890 public void processTaskCreated(Task task) {
  891 + // 1. 设置为待办中
892 Integer status = (Integer) task.getTaskLocalVariables().get(BpmnVariableConstants.TASK_VARIABLE_STATUS); 892 Integer status = (Integer) task.getTaskLocalVariables().get(BpmnVariableConstants.TASK_VARIABLE_STATUS);
893 if (status != null) { 893 if (status != null) {
894 log.error("[updateTaskStatusWhenCreated][taskId({}) 已经有状态({})]", task.getId(), status); 894 log.error("[updateTaskStatusWhenCreated][taskId({}) 已经有状态({})]", task.getId(), status);
895 return; 895 return;
896 } 896 }
897 updateTaskStatus(task.getId(), BpmTaskStatusEnum.RUNNING.getStatus()); 897 updateTaskStatus(task.getId(), BpmTaskStatusEnum.RUNNING.getStatus());
  898 +
  899 + // 2. 处理自动通过的情况,例如说:1)无审批人时,是否自动通过、不通过;2)非【人工审核】时,是否自动通过、不通过
  900 + ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
  901 + if (processInstance == null) {
  902 + log.error("[processTaskCreated][taskId({}) 没有找到流程实例]", task.getId());
  903 + return;
  904 + }
  905 + BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processInstance.getProcessDefinitionId());
  906 + FlowElement userTaskElement = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
  907 + Integer approveType = BpmnModelUtils.parseApproveType(userTaskElement);
  908 + Integer assignEmptyHandlerType = BpmnModelUtils.parseAssignEmptyHandlerType(userTaskElement);
  909 + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
  910 +
  911 + @Override
  912 + public void afterCompletion(int transactionStatus) {
  913 + // 特殊情况:部分情况下,TransactionSynchronizationManager 注册 afterCommit 监听时,不会被调用,但是 afterCompletion 可以
  914 + // 例如说:第一个 task 就是配置【自动通过】或者【自动拒绝】时
  915 + if (ObjectUtil.notEqual(transactionStatus, TransactionSynchronization.STATUS_COMMITTED)) {
  916 + return;
  917 + }
  918 + // 特殊情况一:【人工审核】审批人为空,根据配置是否要自动通过、自动拒绝
  919 + if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.USER.getType())) {
  920 + if (ObjectUtil.equal(assignEmptyHandlerType, BpmUserTaskAssignEmptyHandlerTypeEnum.APPROVE.getType())) {
  921 + SpringUtil.getBean(BpmTaskService.class).approveTask(null, new BpmTaskApproveReqVO()
  922 + .setId(task.getId()).setReason(BpmReasonEnum.ASSIGN_EMPTY_APPROVE.getReason()));
  923 + } else if (ObjectUtil.equal(assignEmptyHandlerType, BpmUserTaskAssignEmptyHandlerTypeEnum.REJECT.getType())) {
  924 + SpringUtil.getBean(BpmTaskService.class).rejectTask(null, new BpmTaskRejectReqVO()
  925 + .setId(task.getId()).setReason(BpmReasonEnum.ASSIGN_EMPTY_REJECT.getReason()));
  926 + }
  927 + // 特殊情况二:【自动审核】审批类型为自动通过、不通过
  928 + } else {
  929 + if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.AUTO_APPROVE.getType())) {
  930 + SpringUtil.getBean(BpmTaskService.class).approveTask(null, new BpmTaskApproveReqVO()
  931 + .setId(task.getId()).setReason(BpmReasonEnum.APPROVE_TYPE_AUTO_APPROVE.getReason()));
  932 + } else if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.AUTO_REJECT.getType())) {
  933 + SpringUtil.getBean(BpmTaskService.class).rejectTask(null, new BpmTaskRejectReqVO()
  934 + .setId(task.getId()).setReason(BpmReasonEnum.APPROVE_TYPE_AUTO_REJECT.getReason()));
  935 + }
  936 + }
  937 + }
  938 +
  939 + });
898 } 940 }
899 941
900 /** 942 /**
@@ -938,12 +980,13 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -938,12 +980,13 @@ public class BpmTaskServiceImpl implements BpmTaskService {
938 log.error("[processTaskAssigned][taskId({}) 没有找到流程实例]", task.getId()); 980 log.error("[processTaskAssigned][taskId({}) 没有找到流程实例]", task.getId());
939 return; 981 return;
940 } 982 }
941 - // 审批人与提交人为同一人时,根据策略进行处理 983 + // 审批人与提交人为同一人时,根据 BpmUserTaskAssignStartUserHandlerTypeEnum 策略进行处理
942 if (StrUtil.equals(task.getAssignee(), processInstance.getStartUserId())) { 984 if (StrUtil.equals(task.getAssignee(), processInstance.getStartUserId())) {
943 - // 判断是否为回退或者驳回 985 + // 判断是否为回退或者驳回:如果是回退或者驳回不走这个策略
  986 + // TODO 芋艿:【优化】未来有没更好的判断方式?!另外,还要考虑清理机制。就是说,下次处理了之后,就移除这个标识
944 Boolean returnTaskFlag = runtimeService.getVariable(processInstance.getProcessInstanceId(), 987 Boolean returnTaskFlag = runtimeService.getVariable(processInstance.getProcessInstanceId(),
945 String.format(PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, task.getTaskDefinitionKey()), Boolean.class); 988 String.format(PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, task.getTaskDefinitionKey()), Boolean.class);
946 - if (!BooleanUtil.isTrue(returnTaskFlag)) { // 如果是回退或者驳回不走这个策略 989 + if (ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE)) {
947 BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processInstance.getProcessDefinitionId()); 990 BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processInstance.getProcessDefinitionId());
948 if (bpmnModel == null) { 991 if (bpmnModel == null) {
949 log.error("[processTaskAssigned][taskId({}) 没有找到流程模型]", task.getId()); 992 log.error("[processTaskAssigned][taskId({}) 没有找到流程模型]", task.getId());