Commit 692daf900bd01a6052eca5f115c4cf56298c1ed0
1 parent
39e89bd3
优化 BpmParallelMultiInstanceBehavior 逻辑,实现会签、或签的任务分配
Showing
26 changed files
with
149 additions
and
223 deletions
yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/FlowableUtils.java
| ... | ... | @@ -9,8 +9,15 @@ import java.util.ArrayList; |
| 9 | 9 | import java.util.Arrays; |
| 10 | 10 | import java.util.List; |
| 11 | 11 | |
| 12 | +/** | |
| 13 | + * Flowable 相关的工具方法 | |
| 14 | + * | |
| 15 | + * @author 芋道源码 | |
| 16 | + */ | |
| 12 | 17 | public class FlowableUtils { |
| 13 | 18 | |
| 19 | + // ========== User 相关的工具方法 ========== | |
| 20 | + | |
| 14 | 21 | public static void setAuthenticatedUserId(Long userId) { |
| 15 | 22 | Authentication.setAuthenticatedUserId(String.valueOf(userId)); |
| 16 | 23 | } |
| ... | ... | @@ -19,6 +26,8 @@ public class FlowableUtils { |
| 19 | 26 | Authentication.setAuthenticatedUserId(null); |
| 20 | 27 | } |
| 21 | 28 | |
| 29 | + // ========== BPMN 相关的工具方法 ========== | |
| 30 | + | |
| 22 | 31 | /** |
| 23 | 32 | * 获得 BPMN 流程中,指定的元素们 |
| 24 | 33 | * |
| ... | ... | @@ -59,4 +68,15 @@ public class FlowableUtils { |
| 59 | 68 | BpmnXMLConverter converter = new BpmnXMLConverter(); |
| 60 | 69 | return converter.convertToXML(model); |
| 61 | 70 | } |
| 71 | + | |
| 72 | + // ========== Execution 相关的工具方法 ========== | |
| 73 | + | |
| 74 | + public static String formatCollectionVariable(String activityId) { | |
| 75 | + return activityId + "_assignees"; | |
| 76 | + } | |
| 77 | + | |
| 78 | + public static String formatCollectionElementVariable(String activityId) { | |
| 79 | + return activityId + "_assignee"; | |
| 80 | + } | |
| 81 | + | |
| 62 | 82 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/package-info.java deleted
| 1 | -package cn.iocoder.yudao.module.bpm.controller.admin.task; |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskApproveReqVO.java
| ... | ... | @@ -3,12 +3,8 @@ package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; |
| 3 | 3 | import io.swagger.annotations.ApiModel; |
| 4 | 4 | import io.swagger.annotations.ApiModelProperty; |
| 5 | 5 | import lombok.Data; |
| 6 | -import lombok.EqualsAndHashCode; | |
| 7 | -import lombok.ToString; | |
| 8 | 6 | |
| 9 | 7 | import javax.validation.constraints.NotEmpty; |
| 10 | -import javax.validation.constraints.NotNull; | |
| 11 | -import java.util.Map; | |
| 12 | 8 | |
| 13 | 9 | @ApiModel("管理后台 - 通过流程任务的 Request VO") |
| 14 | 10 | @Data |
| ... | ... | @@ -20,6 +16,6 @@ public class BpmTaskApproveReqVO { |
| 20 | 16 | |
| 21 | 17 | @ApiModelProperty(value = "审批意见", required = true, example = "不错不错!") |
| 22 | 18 | @NotEmpty(message = "审批意见不能为空") |
| 23 | - private String comment; | |
| 19 | + private String reason; | |
| 24 | 20 | |
| 25 | 21 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskBackReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDonePageItemRespVO.java
| ... | ... | @@ -22,6 +22,6 @@ public class BpmTaskDonePageItemRespVO extends BpmTaskTodoPageItemRespVO { |
| 22 | 22 | @ApiModelProperty(value = "任务结果", required = true, notes = "参见 bpm_process_instance_result", example = "2") |
| 23 | 23 | private Integer result; |
| 24 | 24 | @ApiModelProperty(value = "审批建议", required = true, example = "不请假了!") |
| 25 | - private String comment; | |
| 25 | + private String reason; | |
| 26 | 26 | |
| 27 | 27 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskRejectReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java
| ... | ... | @@ -18,12 +18,10 @@ import org.flowable.task.api.Task; |
| 18 | 18 | import org.mapstruct.Mapper; |
| 19 | 19 | import org.mapstruct.Mapping; |
| 20 | 20 | import org.mapstruct.MappingTarget; |
| 21 | -import org.mapstruct.Mappings; | |
| 22 | 21 | import org.mapstruct.factory.Mappers; |
| 23 | 22 | |
| 24 | 23 | import java.util.List; |
| 25 | 24 | import java.util.Map; |
| 26 | -import java.util.Optional; | |
| 27 | 25 | |
| 28 | 26 | /** |
| 29 | 27 | * 流程实例 Convert |
| ... | ... | @@ -105,11 +103,11 @@ public interface BpmProcessInstanceConvert { |
| 105 | 103 | .setProcessInstanceName(instance.getName()); |
| 106 | 104 | } |
| 107 | 105 | |
| 108 | - default BpmMessageSendWhenProcessInstanceRejectReqDTO convert2RejectReq(ProcessInstance instance, String comment) { | |
| 106 | + default BpmMessageSendWhenProcessInstanceRejectReqDTO convert2RejectReq(ProcessInstance instance, String reason) { | |
| 109 | 107 | return new BpmMessageSendWhenProcessInstanceRejectReqDTO() |
| 110 | 108 | .setProcessInstanceName(instance.getName()) |
| 111 | 109 | .setProcessInstanceId(instance.getId()) |
| 112 | - .setComment(comment) | |
| 110 | + .setReason(reason) | |
| 113 | 111 | .setStartUserId(NumberUtils.parseLong(instance.getStartUserId())); |
| 114 | 112 | } |
| 115 | 113 | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmTaskExtDO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmTaskExtMapper.java
| 1 | 1 | package cn.iocoder.yudao.module.bpm.dal.mysql.task; |
| 2 | 2 | |
| 3 | -import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; | |
| 4 | -import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; | |
| 5 | 3 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 4 | +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; | |
| 6 | 5 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| 7 | 6 | import org.apache.ibatis.annotations.Mapper; |
| 8 | 7 | import org.apache.ibatis.annotations.Param; |
| ... | ... | @@ -21,28 +20,8 @@ public interface BpmTaskExtMapper extends BaseMapperX<BpmTaskExtDO> { |
| 21 | 20 | return selectList(BpmTaskExtDO::getTaskId, taskIds); |
| 22 | 21 | } |
| 23 | 22 | |
| 24 | - /** | |
| 25 | - * 查询全部任务 | |
| 26 | - * | |
| 27 | - * @return 返回任务 | |
| 28 | - */ | |
| 29 | - @TenantIgnore | |
| 30 | - default List<BpmTaskExtDO> listAll() { | |
| 31 | - return selectList(); | |
| 32 | - } | |
| 33 | - | |
| 34 | - /** | |
| 35 | - * 查询任务 | |
| 36 | - * | |
| 37 | - * @param procInstId 流程id | |
| 38 | - * | |
| 39 | - * @return 返回任务列表 | |
| 40 | - */ | |
| 41 | - @TenantIgnore | |
| 42 | - List<BpmTaskExtDO> listByProcInstId(@Param("procInstId") String procInstId); | |
| 43 | - | |
| 44 | 23 | default List<BpmTaskExtDO> selectListByProcessInstanceId(String processInstanceId) { |
| 45 | - return selectList("process_instance_id", processInstanceId); | |
| 24 | + return selectList(BpmTaskExtDO::getProcessInstanceId, processInstanceId); | |
| 46 | 25 | } |
| 47 | 26 | |
| 48 | 27 | /** |
| ... | ... | @@ -56,11 +35,11 @@ public interface BpmTaskExtMapper extends BaseMapperX<BpmTaskExtDO> { |
| 56 | 35 | * 任务驳回 |
| 57 | 36 | * |
| 58 | 37 | * @param taskId 任务列表 |
| 59 | - * @param comment 驳回理由 | |
| 38 | + * @param reason 驳回理由 | |
| 60 | 39 | * |
| 61 | 40 | * @return 返回驳回结果,是否成功 |
| 62 | 41 | */ |
| 63 | - Boolean backByTaskId(@Param("taskId") String taskId, @Param("comment") String comment); | |
| 42 | + Boolean backByTaskId(@Param("taskId") String taskId, @Param("reason") String reason); | |
| 64 | 43 | |
| 65 | 44 | /** |
| 66 | 45 | * 逻辑删除任务 | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmParallelMultiInstanceBehavior.java
| 1 | 1 | package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior; |
| 2 | 2 | |
| 3 | -import cn.hutool.core.collection.CollUtil; | |
| 4 | -import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | |
| 5 | -import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; | |
| 3 | +import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils; | |
| 6 | 4 | import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService; |
| 7 | 5 | import lombok.Setter; |
| 8 | 6 | import lombok.extern.slf4j.Slf4j; |
| ... | ... | @@ -10,26 +8,20 @@ import org.flowable.bpmn.model.Activity; |
| 10 | 8 | import org.flowable.engine.delegate.DelegateExecution; |
| 11 | 9 | import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior; |
| 12 | 10 | import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior; |
| 13 | -import org.flowable.engine.impl.util.CommandContextUtil; | |
| 14 | 11 | |
| 15 | 12 | import java.util.Set; |
| 16 | 13 | |
| 17 | -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 18 | -import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; | |
| 19 | -import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_CREATE_FAIL_NO_CANDIDATE_USER; | |
| 20 | - | |
| 21 | 14 | /** |
| 15 | + * 自定义的【并行】的【多个】流程任务的 assignee 负责人的分配 | |
| 16 | + * 第一步,基于分配规则,计算出分配任务的【多个】候选人们。 | |
| 17 | + * 第二步,将【多个】任务候选人们,设置到 DelegateExecution 的 collectionVariable 变量中,以便 BpmUserTaskActivityBehavior 使用它 | |
| 18 | + * | |
| 22 | 19 | * @author kemengkai |
| 23 | - * @create 2022-04-21 16:57 | |
| 20 | + * @date 2022-04-21 16:57 | |
| 24 | 21 | */ |
| 25 | 22 | @Slf4j |
| 26 | 23 | public class BpmParallelMultiInstanceBehavior extends ParallelMultiInstanceBehavior { |
| 27 | 24 | |
| 28 | - /** | |
| 29 | - * EL表达式集合模板 | |
| 30 | - */ | |
| 31 | - private final static String EXPRESSION_TEXT_TEMPLATE = "${coll_userList}"; | |
| 32 | - | |
| 33 | 25 | @Setter |
| 34 | 26 | private BpmTaskAssignRuleService bpmTaskRuleService; |
| 35 | 27 | |
| ... | ... | @@ -39,78 +31,28 @@ public class BpmParallelMultiInstanceBehavior extends ParallelMultiInstanceBehav |
| 39 | 31 | } |
| 40 | 32 | |
| 41 | 33 | /** |
| 42 | - * 创建并行任务 | |
| 34 | + * 重写该方法,主要实现两个功能: | |
| 35 | + * 1. 忽略原有的 collectionVariable、collectionElementVariable 表达式,而是采用自己定义的 | |
| 36 | + * 2. 获得任务的处理人,并设置到 collectionVariable 中,用于 BpmUserTaskActivityBehavior 从中可以获取任务的处理人 | |
| 43 | 37 | * |
| 44 | - * @param multiInstanceRootExecution 并行任务入参 | |
| 38 | + * 注意,多个任务实例,每个任务实例对应一个处理人,所以返回的数量就是任务处理人的数量 | |
| 45 | 39 | * |
| 46 | - * @return 返回结果 | |
| 40 | + * @param execution 执行任务 | |
| 41 | + * @return 数量 | |
| 47 | 42 | */ |
| 48 | 43 | @Override |
| 49 | - protected int createInstances(DelegateExecution multiInstanceRootExecution) { | |
| 50 | - // 查找任务信息 | |
| 51 | -// BpmTaskAssignRuleDO taskRule = getTaskRule(multiInstanceRootExecution); | |
| 52 | - BpmTaskAssignRuleDO taskRule = null; | |
| 53 | - // 获取任务用户 | |
| 54 | - Set<Long> assigneeUserIds = calculateTaskCandidateUsers(multiInstanceRootExecution, taskRule); | |
| 55 | - // 设置任务集合变量 | |
| 56 | - String expressionText = String.format("%s_userList", taskRule.getTaskDefinitionKey()); | |
| 57 | - // 设置任务集合变量与任务关系 | |
| 58 | - multiInstanceRootExecution.setVariable(expressionText, assigneeUserIds); | |
| 59 | - // 设置任务集合EL表达式 | |
| 60 | - this.collectionExpression = CommandContextUtil.getProcessEngineConfiguration().getExpressionManager() | |
| 61 | - .createExpression(String.format("${%s}", expressionText)); | |
| 62 | - // 根据会签,或签类型,设置会签,或签条件 | |
| 63 | -// if (BpmTaskAssignRuleTypeEnum.USER_SIGN.getType().equals(taskRule.getType())) { | |
| 64 | -// // 会签 | |
| 65 | -// this.completionCondition = "${ nrOfInstances == nrOfCompletedInstances }"; | |
| 66 | -// } else { | |
| 67 | -// // 或签 | |
| 68 | -// this.completionCondition = "${ nrOfCompletedInstances == 1 }"; | |
| 69 | -// } | |
| 70 | - // 设置取出集合变量 | |
| 71 | - this.collectionElementVariable = "user"; | |
| 72 | - return super.createInstances(multiInstanceRootExecution); | |
| 73 | - } | |
| 74 | - | |
| 75 | - @Override | |
| 76 | - protected Object resolveCollection(DelegateExecution execution) { | |
| 77 | - Object collection = null; | |
| 78 | - if (EXPRESSION_TEXT_TEMPLATE.equals(this.collectionExpression.getExpressionText())) { | |
| 79 | - // 查找任务信息 | |
| 80 | -// BpmTaskAssignRuleDO taskRule = getTaskRule(execution); | |
| 81 | - BpmTaskAssignRuleDO taskRule = null; | |
| 82 | - // 设置任务集合变量 | |
| 83 | - String expressionText = String.format("%s_userList", execution.getCurrentActivityId()); | |
| 84 | - // 获取任务用户 | |
| 85 | - Set<Long> assigneeUserIds = calculateTaskCandidateUsers(execution, taskRule); | |
| 86 | - // 设置任务集合变量与任务关系 | |
| 87 | - execution.setVariable(expressionText, assigneeUserIds); | |
| 88 | - // 设置任务集合EL表达式 | |
| 89 | - this.collectionExpression = CommandContextUtil.getProcessEngineConfiguration().getExpressionManager() | |
| 90 | - .createExpression(String.format("${%s}", expressionText)); | |
| 91 | - } | |
| 92 | - if (this.collectionExpression != null) { | |
| 93 | - collection = this.collectionExpression.getValue(execution); | |
| 94 | - } else if (this.collectionVariable != null) { | |
| 95 | - collection = execution.getVariable(this.collectionVariable); | |
| 96 | - } else if (this.collectionString != null) { | |
| 97 | - collection = this.collectionString; | |
| 98 | - } | |
| 99 | - | |
| 100 | - return collection; | |
| 101 | - } | |
| 102 | - | |
| 103 | - Set<Long> calculateTaskCandidateUsers(DelegateExecution task, BpmTaskAssignRuleDO rule) { | |
| 104 | - Set<Long> assigneeUserIds = SetUtils.asSet(1L, 104L); | |
| 105 | - | |
| 106 | - // 移除被禁用的用户 | |
| 107 | - // 如果候选人为空,抛出异常 TODO 芋艿:没候选人的策略选择。1 - 挂起;2 - 直接结束;3 - 强制一个兜底人 | |
| 108 | - if (CollUtil.isEmpty(assigneeUserIds)) { | |
| 109 | - log.error("[calculateTaskCandidateUsers][流程任务({}/{}/{}) 任务规则({}) 找不到候选人]", task.getId(), | |
| 110 | - task.getProcessDefinitionId(), task.getCurrentActivityId(), toJsonString(rule)); | |
| 111 | - throw exception(TASK_CREATE_FAIL_NO_CANDIDATE_USER); | |
| 112 | - } | |
| 113 | - return assigneeUserIds; | |
| 44 | + protected int resolveNrOfInstances(DelegateExecution execution) { | |
| 45 | + // 第一步,设置 collectionVariable 和 CollectionVariable | |
| 46 | + // 从 execution.getVariable() 读取所有任务处理人的 key | |
| 47 | + super.collectionExpression = null; // collectionExpression 和 collectionVariable 是互斥的 | |
| 48 | + super.collectionVariable = FlowableUtils.formatCollectionVariable(execution.getCurrentActivityId()); | |
| 49 | + // 从 execution.getVariable() 读取当前所有任务处理的人的 key | |
| 50 | + super.collectionElementVariable = FlowableUtils.formatCollectionElementVariable(execution.getCurrentActivityId()); | |
| 51 | + | |
| 52 | + // 第二步,获取任务的所有处理人 | |
| 53 | + Set<Long> assigneeUserIds = bpmTaskRuleService.calculateTaskCandidateUsers(execution); | |
| 54 | + execution.setVariable(super.collectionVariable, assigneeUserIds); | |
| 55 | + return assigneeUserIds.size(); | |
| 114 | 56 | } |
| 115 | 57 | |
| 116 | 58 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java
| 1 | 1 | package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | +import cn.hutool.core.lang.Assert; | |
| 4 | 5 | import cn.hutool.core.util.RandomUtil; |
| 5 | -import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; | |
| 6 | 6 | import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService; |
| 7 | 7 | import lombok.Setter; |
| 8 | 8 | import lombok.extern.slf4j.Slf4j; |
| ... | ... | @@ -16,14 +16,12 @@ import org.flowable.task.service.TaskService; |
| 16 | 16 | import org.flowable.task.service.impl.persistence.entity.TaskEntity; |
| 17 | 17 | |
| 18 | 18 | import java.util.List; |
| 19 | -import java.util.Map; | |
| 20 | 19 | import java.util.Set; |
| 21 | 20 | |
| 22 | 21 | /** |
| 23 | - * 自定义的流程任务的 assignee 负责人的分配 | |
| 24 | - * 第一步,获得对应的分配规则; | |
| 25 | - * 第二步,根据分配规则,计算出分配任务的候选人。如果找不到,则直接报业务异常,不继续执行后续的流程; | |
| 26 | - * 第三步,随机选择一个候选人,则选择作为 assignee 负责人。 | |
| 22 | + * 自定义的【单个】流程任务的 assignee 负责人的分配 | |
| 23 | + * 第一步,基于分配规则,计算出分配任务的【单个】候选人。如果找不到,则直接报业务异常,不继续执行后续的流程; | |
| 24 | + * 第二步,随机选择一个候选人,则选择作为 assignee 负责人。 | |
| 27 | 25 | * |
| 28 | 26 | * @author 芋道源码 |
| 29 | 27 | */ |
| ... | ... | @@ -38,30 +36,28 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior { |
| 38 | 36 | } |
| 39 | 37 | |
| 40 | 38 | @Override |
| 41 | - @DataPermission(enable = false) // 不需要处理数据权限, 不然会有问题,查询不到数据 | |
| 42 | 39 | protected void handleAssignments(TaskService taskService, String assignee, String owner, |
| 43 | 40 | List<String> candidateUsers, List<String> candidateGroups, TaskEntity task, ExpressionManager expressionManager, |
| 44 | 41 | DelegateExecution execution, ProcessEngineConfigurationImpl processEngineConfiguration) { |
| 45 | - // 第一步,获得任务的候选用户们 | |
| 46 | - Set<Long> candidateUserIds = bpmTaskRuleService.calculateTaskCandidateUsers(task); | |
| 47 | - // 第二步,选择一个作为候选人 | |
| 48 | - Long assigneeUserId = chooseTaskAssignee(execution, candidateUserIds); | |
| 49 | - // 第三步,设置作为负责人 | |
| 42 | + // 第一步,获得任务的候选用户 | |
| 43 | + Long assigneeUserId = calculateTaskCandidateUsers(execution); | |
| 44 | + Assert.notNull(assigneeUserId, "任务处理人不能为空"); | |
| 45 | + // 第二步,设置作为负责人 | |
| 50 | 46 | TaskHelper.changeTaskAssignee(task, String.valueOf(assigneeUserId)); |
| 51 | 47 | } |
| 52 | 48 | |
| 53 | - private Long chooseTaskAssignee(DelegateExecution execution, Set<Long> candidateUserIds) { | |
| 54 | - // 获取任务变量 | |
| 55 | - Map<String, Object> variables = execution.getVariables(); | |
| 56 | - // 设置任务集合变量key | |
| 57 | - String expressionText = String.format("%s_userList", execution.getCurrentActivityId()); | |
| 58 | - // 判断当前任务是否为并行任务, 是的话获取任务变量 | |
| 59 | - if (variables.containsKey(expressionText)) { | |
| 60 | - String user = variables.get("user").toString(); | |
| 61 | - return Long.valueOf(user); | |
| 49 | + private Long calculateTaskCandidateUsers(DelegateExecution execution) { | |
| 50 | + // 情况一,如果是多实例的任务,例如说会签、或签等情况,则从 Variable 中获取。它的任务处理人在 BpmParallelMultiInstanceBehavior 中已经被分配了 | |
| 51 | + if (super.multiInstanceActivityBehavior != null) { | |
| 52 | + return execution.getVariable(super.multiInstanceActivityBehavior.getCollectionElementVariable(), Long.class); | |
| 62 | 53 | } |
| 63 | 54 | |
| 64 | - // TODO 芋艿:未来可以优化下,改成轮询的策略 | |
| 55 | + // 情况二,如果非多实例的任务,则计算任务处理人 | |
| 56 | + // 第一步,先计算可处理该任务的处理人们 | |
| 57 | + Set<Long> candidateUserIds = bpmTaskRuleService.calculateTaskCandidateUsers(execution); | |
| 58 | + // 第二步,后随机选择一个任务的处理人 | |
| 59 | + // 疑问:为什么一定要选择一个任务处理人? | |
| 60 | + // 解答:项目对 bpm 的任务是责任到人,所以每个任务有且仅有一个处理人。如果希望一个任务可以同时被多个人处理,可以考虑使用 BpmParallelMultiInstanceBehavior 实现的会签 or 或签。 | |
| 65 | 61 | int index = RandomUtil.randomInt(candidateUserIds.size()); |
| 66 | 62 | return CollUtil.get(candidateUserIds, index); |
| 67 | 63 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java
| 1 | 1 | package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum; |
| 4 | -import org.flowable.task.service.impl.persistence.entity.TaskEntity; | |
| 4 | +import org.flowable.engine.delegate.DelegateExecution; | |
| 5 | 5 | |
| 6 | 6 | import java.util.Set; |
| 7 | 7 | |
| 8 | +// TODO @芋艿:迁移到 bpm 的 core 下 | |
| 8 | 9 | /** |
| 9 | 10 | * Bpm 任务分配的自定义 Script 脚本 |
| 10 | 11 | * 使用场景: |
| ... | ... | @@ -17,12 +18,12 @@ import java.util.Set; |
| 17 | 18 | public interface BpmTaskAssignScript { |
| 18 | 19 | |
| 19 | 20 | /** |
| 20 | - * 基于流程任务,获得任务的候选用户们 | |
| 21 | + * 基于执行任务,获得任务的候选用户们 | |
| 21 | 22 | * |
| 22 | - * @param task 任务 | |
| 23 | + * @param execution 执行任务 | |
| 23 | 24 | * @return 候选人用户的编号数组 |
| 24 | 25 | */ |
| 25 | - Set<Long> calculateTaskCandidateUsers(TaskEntity task); | |
| 26 | + Set<Long> calculateTaskCandidateUsers(DelegateExecution execution); | |
| 26 | 27 | |
| 27 | 28 | /** |
| 28 | 29 | * 获得枚举值 | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java
| ... | ... | @@ -7,9 +7,8 @@ import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| 7 | 7 | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; |
| 8 | 8 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 9 | 9 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 10 | - | |
| 10 | +import org.flowable.engine.delegate.DelegateExecution; | |
| 11 | 11 | import org.flowable.engine.runtime.ProcessInstance; |
| 12 | -import org.flowable.task.service.impl.persistence.entity.TaskEntity; | |
| 13 | 12 | import org.springframework.context.annotation.Lazy; |
| 14 | 13 | import org.springframework.util.Assert; |
| 15 | 14 | |
| ... | ... | @@ -35,10 +34,10 @@ public abstract class BpmTaskAssignLeaderAbstractScript implements BpmTaskAssign |
| 35 | 34 | @Lazy // 解决循环依赖 |
| 36 | 35 | private BpmProcessInstanceService bpmProcessInstanceService; |
| 37 | 36 | |
| 38 | - protected Set<Long> calculateTaskCandidateUsers(TaskEntity task, int level) { | |
| 37 | + protected Set<Long> calculateTaskCandidateUsers(DelegateExecution execution, int level) { | |
| 39 | 38 | Assert.isTrue(level > 0, "level 必须大于 0"); |
| 40 | 39 | // 获得发起人 |
| 41 | - ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(task.getProcessInstanceId()); | |
| 40 | + ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(execution.getProcessInstanceId()); | |
| 42 | 41 | Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId()); |
| 43 | 42 | // 获得对应 leve 的部门 |
| 44 | 43 | DeptRespDTO dept = null; | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java
| 1 | 1 | package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl; |
| 2 | 2 | |
| 3 | -import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; | |
| 4 | 3 | import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum; |
| 5 | -import org.flowable.task.service.impl.persistence.entity.TaskEntity; | |
| 4 | +import org.flowable.engine.delegate.DelegateExecution; | |
| 6 | 5 | import org.springframework.stereotype.Component; |
| 7 | 6 | |
| 8 | 7 | import java.util.Set; |
| ... | ... | @@ -16,9 +15,8 @@ import java.util.Set; |
| 16 | 15 | public class BpmTaskAssignLeaderX1Script extends BpmTaskAssignLeaderAbstractScript { |
| 17 | 16 | |
| 18 | 17 | @Override |
| 19 | - @DataPermission(enable = false) // 不需要处理数据权限, 不然会有问题,查询不到数据 | |
| 20 | - public Set<Long> calculateTaskCandidateUsers(TaskEntity task) { | |
| 21 | - return calculateTaskCandidateUsers(task, 1); | |
| 18 | + public Set<Long> calculateTaskCandidateUsers(DelegateExecution execution) { | |
| 19 | + return calculateTaskCandidateUsers(execution, 1); | |
| 22 | 20 | } |
| 23 | 21 | |
| 24 | 22 | @Override | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java
| 1 | 1 | package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl; |
| 2 | 2 | |
| 3 | -import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; | |
| 4 | 3 | import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum; |
| 5 | -import org.flowable.task.service.impl.persistence.entity.TaskEntity; | |
| 4 | +import org.flowable.engine.delegate.DelegateExecution; | |
| 6 | 5 | import org.springframework.stereotype.Component; |
| 7 | 6 | |
| 8 | 7 | import java.util.Set; |
| ... | ... | @@ -16,9 +15,8 @@ import java.util.Set; |
| 16 | 15 | public class BpmTaskAssignLeaderX2Script extends BpmTaskAssignLeaderAbstractScript { |
| 17 | 16 | |
| 18 | 17 | @Override |
| 19 | - @DataPermission(enable = false) // 不需要处理数据权限, 不然会有问题,查询不到数据 | |
| 20 | - public Set<Long> calculateTaskCandidateUsers(TaskEntity task) { | |
| 21 | - return calculateTaskCandidateUsers(task, 2); | |
| 18 | + public Set<Long> calculateTaskCandidateUsers(DelegateExecution execution) { | |
| 19 | + return calculateTaskCandidateUsers(execution, 2); | |
| 22 | 20 | } |
| 23 | 21 | |
| 24 | 22 | @Override | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignStartUserScript.java
| ... | ... | @@ -3,11 +3,10 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl |
| 3 | 3 | import cn.iocoder.yudao.framework.common.util.collection.SetUtils; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.util.number.NumberUtils; |
| 5 | 5 | import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskRuleScriptEnum; |
| 6 | - | |
| 7 | 6 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript; |
| 8 | 7 | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; |
| 8 | +import org.flowable.engine.delegate.DelegateExecution; | |
| 9 | 9 | import org.flowable.engine.runtime.ProcessInstance; |
| 10 | -import org.flowable.task.service.impl.persistence.entity.TaskEntity; | |
| 11 | 10 | import org.springframework.context.annotation.Lazy; |
| 12 | 11 | import org.springframework.stereotype.Component; |
| 13 | 12 | |
| ... | ... | @@ -27,8 +26,8 @@ public class BpmTaskAssignStartUserScript implements BpmTaskAssignScript { |
| 27 | 26 | private BpmProcessInstanceService bpmProcessInstanceService; |
| 28 | 27 | |
| 29 | 28 | @Override |
| 30 | - public Set<Long> calculateTaskCandidateUsers(TaskEntity task) { | |
| 31 | - ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(task.getProcessInstanceId()); | |
| 29 | + public Set<Long> calculateTaskCandidateUsers(DelegateExecution execution) { | |
| 30 | + ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(execution.getProcessInstanceId()); | |
| 32 | 31 | Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId()); |
| 33 | 32 | return SetUtils.asSet(startUserId); |
| 34 | 33 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/package-info.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java
| ... | ... | @@ -4,7 +4,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAs |
| 4 | 4 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO; |
| 5 | 5 | import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO; |
| 6 | 6 | import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; |
| 7 | -import org.flowable.task.service.impl.persistence.entity.TaskEntity; | |
| 7 | +import org.flowable.engine.delegate.DelegateExecution; | |
| 8 | 8 | import org.springframework.lang.Nullable; |
| 9 | 9 | |
| 10 | 10 | import javax.validation.Valid; |
| ... | ... | @@ -86,6 +86,12 @@ public interface BpmTaskAssignRuleService { |
| 86 | 86 | */ |
| 87 | 87 | void checkTaskAssignRuleAllConfig(String id); |
| 88 | 88 | |
| 89 | - Set<Long> calculateTaskCandidateUsers(TaskEntity task); | |
| 89 | + /** | |
| 90 | + * 计算当前执行任务的处理人 | |
| 91 | + * | |
| 92 | + * @param execution 执行任务 | |
| 93 | + * @return 处理人的编号数组 | |
| 94 | + */ | |
| 95 | + Set<Long> calculateTaskCandidateUsers(DelegateExecution execution); | |
| 90 | 96 | |
| 91 | 97 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
| ... | ... | @@ -31,7 +31,7 @@ import lombok.extern.slf4j.Slf4j; |
| 31 | 31 | import org.flowable.bpmn.model.BpmnModel; |
| 32 | 32 | import org.flowable.bpmn.model.UserTask; |
| 33 | 33 | import org.flowable.common.engine.api.FlowableException; |
| 34 | -import org.flowable.task.service.impl.persistence.entity.TaskEntity; | |
| 34 | +import org.flowable.engine.delegate.DelegateExecution; | |
| 35 | 35 | import org.springframework.context.annotation.Lazy; |
| 36 | 36 | import org.springframework.stereotype.Service; |
| 37 | 37 | import org.springframework.validation.annotation.Validated; |
| ... | ... | @@ -40,6 +40,7 @@ import javax.annotation.Resource; |
| 40 | 40 | import javax.validation.Valid; |
| 41 | 41 | import java.util.*; |
| 42 | 42 | |
| 43 | +import static cn.hutool.core.text.CharSequenceUtil.format; | |
| 43 | 44 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 44 | 45 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; |
| 45 | 46 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| ... | ... | @@ -226,95 +227,93 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService { |
| 226 | 227 | dictDataApi.validDictDatas(DictTypeConstants.TASK_ASSIGN_SCRIPT, |
| 227 | 228 | CollectionUtils.convertSet(options, String::valueOf)); |
| 228 | 229 | } else { |
| 229 | - throw new IllegalArgumentException(StrUtil.format("未知的规则类型({})", type)); | |
| 230 | + throw new IllegalArgumentException(format("未知的规则类型({})", type)); | |
| 230 | 231 | } |
| 231 | 232 | } |
| 232 | 233 | |
| 233 | 234 | @Override |
| 234 | 235 | @DataPermission(enable = false) // 忽略数据权限,不然分配会存在问题 |
| 235 | - public Set<Long> calculateTaskCandidateUsers(TaskEntity task) { | |
| 236 | - BpmTaskAssignRuleDO rule = getTaskRule(task); | |
| 237 | - return calculateTaskCandidateUsers(task, rule); | |
| 236 | + public Set<Long> calculateTaskCandidateUsers(DelegateExecution execution) { | |
| 237 | + BpmTaskAssignRuleDO rule = getTaskRule(execution); | |
| 238 | + return calculateTaskCandidateUsers(execution, rule); | |
| 238 | 239 | } |
| 239 | 240 | |
| 240 | 241 | @VisibleForTesting |
| 241 | - BpmTaskAssignRuleDO getTaskRule(TaskEntity task) { | |
| 242 | + BpmTaskAssignRuleDO getTaskRule(DelegateExecution execution) { | |
| 242 | 243 | List<BpmTaskAssignRuleDO> taskRules = getTaskAssignRuleListByProcessDefinitionId( |
| 243 | - task.getProcessDefinitionId(), task.getTaskDefinitionKey()); | |
| 244 | + execution.getProcessDefinitionId(), execution.getCurrentActivityId()); | |
| 244 | 245 | if (CollUtil.isEmpty(taskRules)) { |
| 245 | - throw new FlowableException( | |
| 246 | - StrUtil.format("流程任务({}/{}/{}) 找不到符合的任务规则", task.getId(), task.getProcessDefinitionId(), | |
| 247 | - task.getTaskDefinitionKey())); | |
| 246 | + throw new FlowableException(format("流程任务({}/{}/{}) 找不到符合的任务规则", | |
| 247 | + execution.getId(), execution.getProcessDefinitionId(), execution.getCurrentActivityId())); | |
| 248 | 248 | } |
| 249 | 249 | if (taskRules.size() > 1) { |
| 250 | - throw new FlowableException( | |
| 251 | - StrUtil.format("流程任务({}/{}/{}) 找到过多任务规则({})", task.getId(), task.getProcessDefinitionId(), | |
| 252 | - task.getTaskDefinitionKey(), taskRules.size())); | |
| 250 | + throw new FlowableException(format("流程任务({}/{}/{}) 找到过多任务规则({})", | |
| 251 | + execution.getId(), execution.getProcessDefinitionId(), execution.getCurrentActivityId())); | |
| 253 | 252 | } |
| 254 | 253 | return taskRules.get(0); |
| 255 | 254 | } |
| 256 | 255 | |
| 257 | 256 | @VisibleForTesting |
| 258 | - Set<Long> calculateTaskCandidateUsers(TaskEntity task, BpmTaskAssignRuleDO rule) { | |
| 257 | + Set<Long> calculateTaskCandidateUsers(DelegateExecution execution, BpmTaskAssignRuleDO rule) { | |
| 259 | 258 | Set<Long> assigneeUserIds = null; |
| 260 | 259 | if (Objects.equals(BpmTaskAssignRuleTypeEnum.ROLE.getType(), rule.getType())) { |
| 261 | - assigneeUserIds = calculateTaskCandidateUsersByRole(task, rule); | |
| 260 | + assigneeUserIds = calculateTaskCandidateUsersByRole(rule); | |
| 262 | 261 | } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(), rule.getType())) { |
| 263 | - assigneeUserIds = calculateTaskCandidateUsersByDeptMember(task, rule); | |
| 262 | + assigneeUserIds = calculateTaskCandidateUsersByDeptMember(rule); | |
| 264 | 263 | } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType(), rule.getType())) { |
| 265 | - assigneeUserIds = calculateTaskCandidateUsersByDeptLeader(task, rule); | |
| 264 | + assigneeUserIds = calculateTaskCandidateUsersByDeptLeader(rule); | |
| 266 | 265 | } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.POST.getType(), rule.getType())) { |
| 267 | - assigneeUserIds = calculateTaskCandidateUsersByPost(task, rule); | |
| 266 | + assigneeUserIds = calculateTaskCandidateUsersByPost(rule); | |
| 268 | 267 | } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER.getType(), rule.getType())) { |
| 269 | - assigneeUserIds = calculateTaskCandidateUsersByUser(task, rule); | |
| 268 | + assigneeUserIds = calculateTaskCandidateUsersByUser(rule); | |
| 270 | 269 | } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType(), rule.getType())) { |
| 271 | - assigneeUserIds = calculateTaskCandidateUsersByUserGroup(task, rule); | |
| 270 | + assigneeUserIds = calculateTaskCandidateUsersByUserGroup(rule); | |
| 272 | 271 | } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), rule.getType())) { |
| 273 | - assigneeUserIds = calculateTaskCandidateUsersByScript(task, rule); | |
| 272 | + assigneeUserIds = calculateTaskCandidateUsersByScript(execution, rule); | |
| 274 | 273 | } |
| 275 | 274 | |
| 276 | 275 | // 移除被禁用的用户 |
| 277 | 276 | removeDisableUsers(assigneeUserIds); |
| 278 | 277 | // 如果候选人为空,抛出异常 TODO 芋艿:没候选人的策略选择。1 - 挂起;2 - 直接结束;3 - 强制一个兜底人 |
| 279 | 278 | if (CollUtil.isEmpty(assigneeUserIds)) { |
| 280 | - log.error("[calculateTaskCandidateUsers][流程任务({}/{}/{}) 任务规则({}) 找不到候选人]", task.getId(), | |
| 281 | - task.getProcessDefinitionId(), task.getTaskDefinitionKey(), toJsonString(rule)); | |
| 279 | + log.error("[calculateTaskCandidateUsers][流程任务({}/{}/{}) 任务规则({}) 找不到候选人]", execution.getId(), | |
| 280 | + execution.getProcessDefinitionId(), execution.getCurrentActivityId(), toJsonString(rule)); | |
| 282 | 281 | throw exception(TASK_CREATE_FAIL_NO_CANDIDATE_USER); |
| 283 | 282 | } |
| 284 | 283 | return assigneeUserIds; |
| 285 | 284 | } |
| 286 | 285 | |
| 287 | - private Set<Long> calculateTaskCandidateUsersByRole(TaskEntity task, BpmTaskAssignRuleDO rule) { | |
| 286 | + private Set<Long> calculateTaskCandidateUsersByRole(BpmTaskAssignRuleDO rule) { | |
| 288 | 287 | return permissionApi.getUserRoleIdListByRoleIds(rule.getOptions()); |
| 289 | 288 | } |
| 290 | 289 | |
| 291 | - private Set<Long> calculateTaskCandidateUsersByDeptMember(TaskEntity task, BpmTaskAssignRuleDO rule) { | |
| 290 | + private Set<Long> calculateTaskCandidateUsersByDeptMember(BpmTaskAssignRuleDO rule) { | |
| 292 | 291 | List<AdminUserRespDTO> users = adminUserApi.getUsersByDeptIds(rule.getOptions()); |
| 293 | 292 | return convertSet(users, AdminUserRespDTO::getId); |
| 294 | 293 | } |
| 295 | 294 | |
| 296 | - private Set<Long> calculateTaskCandidateUsersByDeptLeader(TaskEntity task, BpmTaskAssignRuleDO rule) { | |
| 295 | + private Set<Long> calculateTaskCandidateUsersByDeptLeader(BpmTaskAssignRuleDO rule) { | |
| 297 | 296 | List<DeptRespDTO> depts = deptApi.getDepts(rule.getOptions()); |
| 298 | 297 | return convertSet(depts, DeptRespDTO::getLeaderUserId); |
| 299 | 298 | } |
| 300 | 299 | |
| 301 | - private Set<Long> calculateTaskCandidateUsersByPost(TaskEntity task, BpmTaskAssignRuleDO rule) { | |
| 300 | + private Set<Long> calculateTaskCandidateUsersByPost(BpmTaskAssignRuleDO rule) { | |
| 302 | 301 | List<AdminUserRespDTO> users = adminUserApi.getUsersByPostIds(rule.getOptions()); |
| 303 | 302 | return convertSet(users, AdminUserRespDTO::getId); |
| 304 | 303 | } |
| 305 | 304 | |
| 306 | - private Set<Long> calculateTaskCandidateUsersByUser(TaskEntity task, BpmTaskAssignRuleDO rule) { | |
| 305 | + private Set<Long> calculateTaskCandidateUsersByUser(BpmTaskAssignRuleDO rule) { | |
| 307 | 306 | return rule.getOptions(); |
| 308 | 307 | } |
| 309 | 308 | |
| 310 | - private Set<Long> calculateTaskCandidateUsersByUserGroup(TaskEntity task, BpmTaskAssignRuleDO rule) { | |
| 309 | + private Set<Long> calculateTaskCandidateUsersByUserGroup(BpmTaskAssignRuleDO rule) { | |
| 311 | 310 | List<BpmUserGroupDO> userGroups = userGroupService.getUserGroupList(rule.getOptions()); |
| 312 | 311 | Set<Long> userIds = new HashSet<>(); |
| 313 | 312 | userGroups.forEach(group -> userIds.addAll(group.getMemberUserIds())); |
| 314 | 313 | return userIds; |
| 315 | 314 | } |
| 316 | 315 | |
| 317 | - private Set<Long> calculateTaskCandidateUsersByScript(TaskEntity task, BpmTaskAssignRuleDO rule) { | |
| 316 | + private Set<Long> calculateTaskCandidateUsersByScript(DelegateExecution execution, BpmTaskAssignRuleDO rule) { | |
| 318 | 317 | // 获得对应的脚本 |
| 319 | 318 | List<BpmTaskAssignScript> scripts = new ArrayList<>(rule.getOptions().size()); |
| 320 | 319 | rule.getOptions().forEach(id -> { |
| ... | ... | @@ -326,7 +325,7 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService { |
| 326 | 325 | }); |
| 327 | 326 | // 逐个计算任务 |
| 328 | 327 | Set<Long> userIds = new HashSet<>(); |
| 329 | - scripts.forEach(script -> CollUtil.addAll(userIds, script.calculateTaskCandidateUsers(task))); | |
| 328 | + scripts.forEach(script -> CollUtil.addAll(userIds, script.calculateTaskCandidateUsers(execution))); | |
| 330 | 329 | return userIds; |
| 331 | 330 | } |
| 332 | 331 | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageServiceImpl.java
| ... | ... | @@ -44,7 +44,7 @@ public class BpmMessageServiceImpl implements BpmMessageService { |
| 44 | 44 | public void sendMessageWhenProcessInstanceReject(BpmMessageSendWhenProcessInstanceRejectReqDTO reqDTO) { |
| 45 | 45 | Map<String, Object> templateParams = new HashMap<>(); |
| 46 | 46 | templateParams.put("processInstanceName", reqDTO.getProcessInstanceName()); |
| 47 | - templateParams.put("comment", reqDTO.getComment()); | |
| 47 | + templateParams.put("reason", reqDTO.getReason()); | |
| 48 | 48 | templateParams.put("detailUrl", getProcessInstanceDetailUrl(reqDTO.getProcessInstanceId())); |
| 49 | 49 | smsSendApi.sendSingleSmsToAdmin(BpmMessageConvert.INSTANCE.convert(reqDTO.getStartUserId(), |
| 50 | 50 | BpmMessageEnum.PROCESS_INSTANCE_REJECT.getSmsTemplateCode(), templateParams)); | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenProcessInstanceRejectReqDTO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java
| ... | ... | @@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 5 | 5 | import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; |
| 6 | 6 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; |
| 7 | -import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent; | |
| 8 | 7 | import org.flowable.engine.delegate.event.FlowableCancelledEvent; |
| 9 | 8 | import org.flowable.engine.history.HistoricProcessInstance; |
| 10 | 9 | import org.flowable.engine.runtime.ProcessInstance; |
| ... | ... | @@ -141,9 +140,9 @@ public interface BpmProcessInstanceService { |
| 141 | 140 | * 更新 ProcessInstance 拓展记录为不通过 |
| 142 | 141 | * |
| 143 | 142 | * @param id 流程编号 |
| 144 | - * @param comment 理由。例如说,审批不通过时,需要传递该值 | |
| 143 | + * @param reason 理由。例如说,审批不通过时,需要传递该值 | |
| 145 | 144 | */ |
| 146 | - void updateProcessInstanceExtReject(String id, String comment); | |
| 145 | + void updateProcessInstanceExtReject(String id, String reason); | |
| 147 | 146 | |
| 148 | 147 | |
| 149 | 148 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
| ... | ... | @@ -251,11 +251,11 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 251 | 251 | } |
| 252 | 252 | |
| 253 | 253 | @Transactional(rollbackFor = Exception.class) |
| 254 | - public void updateProcessInstanceExtReject(String id, String comment) { | |
| 254 | + public void updateProcessInstanceExtReject(String id, String reason) { | |
| 255 | 255 | // 需要主动查询,因为 instance 只有 id 属性 |
| 256 | 256 | ProcessInstance processInstance = getProcessInstance(id); |
| 257 | 257 | // 删除流程实例,以实现驳回任务时,取消整个审批流程 |
| 258 | - deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(comment))); | |
| 258 | + deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); | |
| 259 | 259 | |
| 260 | 260 | // 更新 status + result |
| 261 | 261 | // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法, |
| ... | ... | @@ -266,7 +266,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 266 | 266 | processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); |
| 267 | 267 | |
| 268 | 268 | // 发送流程被不通过的消息 |
| 269 | - messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, comment)); | |
| 269 | + messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); | |
| 270 | 270 | |
| 271 | 271 | // 发送流程实例的状态事件 |
| 272 | 272 | processInstanceResultEventPublisher.sendProcessInstanceResultEvent( | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
| ... | ... | @@ -186,7 +186,9 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 186 | 186 | Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));*/ |
| 187 | 187 | |
| 188 | 188 | // 拼接数据 |
| 189 | - List<BpmTaskExtDO> tmpBpmTaskExtDOList = taskExtMapper.listByProcInstId(processInstanceId); | |
| 189 | +// List<BpmTaskExtDO> tmpBpmTaskExtDOList = taskExtMapper.listByProcInstId(processInstanceId); | |
| 190 | + List<BpmTaskExtDO> tmpBpmTaskExtDOList = taskExtMapper.selectListByProcessInstanceId(processInstanceId); | |
| 191 | + tmpBpmTaskExtDOList.sort(Comparator.comparing(BpmTaskExtDO::getCreateTime)); | |
| 190 | 192 | return hiTaskInstService.taskGetComment(tmpBpmTaskExtDOList, ""); |
| 191 | 193 | } |
| 192 | 194 | |
| ... | ... | @@ -207,13 +209,13 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 207 | 209 | // 更新任务拓展表为通过 |
| 208 | 210 | taskExtMapper.updateByTaskId( |
| 209 | 211 | new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()) |
| 210 | - .setComment(reqVO.getComment())); | |
| 212 | + .setReason(reqVO.getReason())); | |
| 211 | 213 | // 判断任务是否为或签,或签时删除其余不用审批的任务 |
| 212 | 214 | List<BpmTaskAssignRuleDO> bpmTaskAssignRuleList = |
| 213 | 215 | taskAssignRuleMapper.selectListByProcessDefinitionId(task.getProcessDefinitionId(), |
| 214 | 216 | task.getTaskDefinitionKey()); |
| 215 | 217 | if (CollUtil.isNotEmpty(bpmTaskAssignRuleList) && bpmTaskAssignRuleList.size() > 0) { |
| 216 | - // edit by 芋艿 | |
| 218 | + // edit by 芋艿 TODO | |
| 217 | 219 | // if (BpmTaskAssignRuleTypeEnum.USER_OR_SIGN.getType().equals(bpmTaskAssignRuleList.get(0).getType())) { |
| 218 | 220 | // taskExtMapper.delTaskByProcInstIdAndTaskIdAndTaskDefKey( |
| 219 | 221 | // new BpmTaskExtDO().setTaskId(task.getId()).setTaskDefKey(task.getTaskDefinitionKey()) |
| ... | ... | @@ -233,12 +235,12 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 233 | 235 | } |
| 234 | 236 | |
| 235 | 237 | // 更新流程实例为不通过 |
| 236 | - processInstanceService.updateProcessInstanceExtReject(instance.getProcessInstanceId(), reqVO.getComment()); | |
| 238 | + processInstanceService.updateProcessInstanceExtReject(instance.getProcessInstanceId(), reqVO.getReason()); | |
| 237 | 239 | |
| 238 | 240 | // 更新任务拓展表为不通过 |
| 239 | 241 | taskExtMapper.updateByTaskId( |
| 240 | 242 | new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.REJECT.getResult()) |
| 241 | - .setComment(reqVO.getComment())); | |
| 243 | + .setReason(reqVO.getReason())); | |
| 242 | 244 | } |
| 243 | 245 | |
| 244 | 246 | @Override |
| ... | ... | @@ -269,7 +271,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 269 | 271 | // 逻辑删除hiTaskInst表任务 |
| 270 | 272 | Boolean delHiTaskInstResult = bpmActivityMapper.delHiTaskInstByTaskId(taskIdList); |
| 271 | 273 | // 更新任务拓展表 |
| 272 | - Boolean backResult = taskExtMapper.backByTaskId(reqVO.getTaskId(), reqVO.getComment()); | |
| 274 | + Boolean backResult = taskExtMapper.backByTaskId(reqVO.getTaskId(), reqVO.getReason()); | |
| 273 | 275 | Boolean delTaskResult = taskExtMapper.delByTaskIds(taskIdList); |
| 274 | 276 | if (!delHiActInstResult && !delHiTaskInstResult && !backResult && !delTaskResult) { |
| 275 | 277 | throw new RuntimeException("任务驳回失败!!!"); | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/business/hi/task/inst/service/HiTaskInstService.java
| ... | ... | @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.business.hi.task.inst.service; |
| 3 | 3 | import cn.hutool.core.bean.BeanUtil; |
| 4 | 4 | import cn.hutool.core.collection.CollUtil; |
| 5 | 5 | import cn.hutool.core.util.ObjectUtil; |
| 6 | +import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; | |
| 6 | 7 | import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; |
| 7 | 8 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO; |
| 8 | 9 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskTodoPageItemRespVO; |
| ... | ... | @@ -67,6 +68,7 @@ public class HiTaskInstService { |
| 67 | 68 | * @return 返回流程信息 |
| 68 | 69 | */ |
| 69 | 70 | @TenantIgnore |
| 71 | + @DataPermission(enable = false) // TODO 芋艿:先临时去掉 | |
| 70 | 72 | public List<BpmTaskRespVO> taskGetComment(List<BpmTaskExtDO> taskList, Object approved) { |
| 71 | 73 | BpmTaskExtDO task = taskList.get(taskList.size() - 1); |
| 72 | 74 | Map<String, BpmTaskExtDO> bpmTaskMap = |
| ... | ... | @@ -262,7 +264,7 @@ public class HiTaskInstService { |
| 262 | 264 | DeptDO deptDO = deptMap.get(adminUserDO.getDeptId()); |
| 263 | 265 | bpmTaskRespVO.setAssigneeUser(setUser(adminUserDO)); |
| 264 | 266 | bpmTaskRespVO.getAssigneeUser().setDeptName(deptDO.getName()); |
| 265 | - // edit by 芋艿 | |
| 267 | + // edit by 芋艿 TODO | |
| 266 | 268 | // if (!bpmTaskAssignRuleDO.getType().equals(BpmTaskAssignRuleTypeEnum.USER_OR_SIGN.getType()) |
| 267 | 269 | // && !bpmTaskAssignRuleDO.getType().equals(BpmTaskAssignRuleTypeEnum.USER_SIGN.getType())) { |
| 268 | 270 | // break; | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/BpmTaskExtMapper.xml
| ... | ... | @@ -13,7 +13,7 @@ |
| 13 | 13 | <update id="backByTaskId"> |
| 14 | 14 | UPDATE bpm_task_ext |
| 15 | 15 | SET result=2, |
| 16 | - `comment`=#{comment} | |
| 16 | + `reason`=#{reason} | |
| 17 | 17 | WHERE task_id = #{taskId} |
| 18 | 18 | </update> |
| 19 | 19 | <update id="delByTaskIds"> |
| ... | ... | @@ -26,12 +26,5 @@ |
| 26 | 26 | </foreach> |
| 27 | 27 | </update> |
| 28 | 28 | |
| 29 | - <select id="listByProcInstId" resultType="cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO"> | |
| 30 | - SELECT * | |
| 31 | - FROM bpm_task_ext | |
| 32 | - WHERE `process_instance_id` = #{procInstId} | |
| 33 | - AND `deleted` = FALSE | |
| 34 | - ORDER BY create_time | |
| 35 | - LIMIT 500 | |
| 36 | - </select> | |
| 29 | + | |
| 37 | 30 | </mapper> | ... | ... |