Commit 6217d5acb1067142fe9f54994c4cdff5540c43cb
Merge remote-tracking branch 'origin/feature/bpm' into feature/bpm
Showing
4 changed files
with
61 additions
and
53 deletions
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()); |