mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-30 03:01:53 +08:00
工作流 Flowable 任务自定义 Script 脚本 相关实现
This commit is contained in:
parent
41e4283f99
commit
e01acfb18e
@ -1,7 +1,14 @@
|
|||||||
package cn.iocoder.yudao.framework.flowable.core.util;
|
package cn.iocoder.yudao.framework.flowable.core.util;
|
||||||
|
|
||||||
|
import org.flowable.bpmn.converter.BpmnXMLConverter;
|
||||||
|
import org.flowable.bpmn.model.BpmnModel;
|
||||||
|
import org.flowable.bpmn.model.FlowElement;
|
||||||
import org.flowable.common.engine.impl.identity.Authentication;
|
import org.flowable.common.engine.impl.identity.Authentication;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class FlowableUtils {
|
public class FlowableUtils {
|
||||||
|
|
||||||
public static void setAuthenticatedUserId(Long userId) {
|
public static void setAuthenticatedUserId(Long userId) {
|
||||||
@ -11,4 +18,45 @@ public class FlowableUtils {
|
|||||||
public static void clearAuthenticatedUserId() {
|
public static void clearAuthenticatedUserId() {
|
||||||
Authentication.setAuthenticatedUserId(null);
|
Authentication.setAuthenticatedUserId(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得 BPMN 流程中,指定的元素们
|
||||||
|
*
|
||||||
|
* @param model
|
||||||
|
* @param clazz 指定元素。例如说,{@link org.flowable.bpmn.model.UserTask}、{@link org.flowable.bpmn.model.Gateway} 等等
|
||||||
|
* @return 元素们
|
||||||
|
*/
|
||||||
|
public static <T extends FlowElement> List<T> getBpmnModelElements(BpmnModel model, Class<T> clazz) {
|
||||||
|
List<T> result = new ArrayList<>();
|
||||||
|
model.getProcesses().forEach(process -> {
|
||||||
|
process.getFlowElements().forEach(flowElement -> {
|
||||||
|
if (flowElement.getClass().isAssignableFrom(clazz)) {
|
||||||
|
result.add((T) flowElement);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 比较 两个bpmnModel 是否相同
|
||||||
|
* @param oldModel 老的bpmn model
|
||||||
|
* @param newModel 新的bpmn model
|
||||||
|
*/
|
||||||
|
public static boolean equals(BpmnModel oldModel, BpmnModel newModel) {
|
||||||
|
// 由于 BpmnModel 未提供 equals 方法,所以只能转成字节数组,进行比较
|
||||||
|
return Arrays.equals(getBpmnBytes(oldModel), getBpmnBytes(newModel));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 把 bpmnModel 转换成 byte[]
|
||||||
|
* @param model bpmnModel
|
||||||
|
*/
|
||||||
|
public static byte[] getBpmnBytes(BpmnModel model) {
|
||||||
|
if (model == null) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
BpmnXMLConverter converter = new BpmnXMLConverter();
|
||||||
|
return converter.convertToXML(model);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package cn.iocoder.yudao.module.bpm.framework.flowable.config;
|
package cn.iocoder.yudao.module.bpm.framework.flowable.config;
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.BpmActivityBehaviorFactory;
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.BpmActivityBehaviorFactory;
|
||||||
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
|
||||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmProcessInstanceEventListener;
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmProcessInstanceEventListener;
|
||||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
|
import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
|
||||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
|
import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
|
||||||
@ -27,8 +28,9 @@ import java.util.List;
|
|||||||
public class BpmFlowableConfiguration {
|
public class BpmFlowableConfiguration {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将自定义 listener 加入全局listener
|
* Flowable engines 自定义的配置
|
||||||
* @param listeners 自定义 listener
|
* @param listeners 自定义 listener
|
||||||
|
* @param bpmActivityBehaviorFactory 自定义的 ActivityBehaviorFactory 实现
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public EngineConfigurationConfigurer<SpringProcessEngineConfiguration> addCustomerListenerConfigurer (ObjectProvider<FlowableEventListener> listeners,
|
public EngineConfigurationConfigurer<SpringProcessEngineConfiguration> addCustomerListenerConfigurer (ObjectProvider<FlowableEventListener> listeners,
|
||||||
@ -51,14 +53,15 @@ public class BpmFlowableConfiguration {
|
|||||||
BpmUserGroupService userGroupService,
|
BpmUserGroupService userGroupService,
|
||||||
PermissionApi permissionApi,
|
PermissionApi permissionApi,
|
||||||
DeptApi deptApi,
|
DeptApi deptApi,
|
||||||
AdminUserApi adminUserApi) {
|
AdminUserApi adminUserApi,
|
||||||
|
List<BpmTaskAssignScript> scripts) {
|
||||||
BpmActivityBehaviorFactory bpmActivityBehaviorFactory = new BpmActivityBehaviorFactory();
|
BpmActivityBehaviorFactory bpmActivityBehaviorFactory = new BpmActivityBehaviorFactory();
|
||||||
bpmActivityBehaviorFactory.setBpmTaskRuleService(taskRuleService);
|
bpmActivityBehaviorFactory.setBpmTaskRuleService(taskRuleService);
|
||||||
bpmActivityBehaviorFactory.setUserGroupService(userGroupService);
|
bpmActivityBehaviorFactory.setUserGroupService(userGroupService);
|
||||||
bpmActivityBehaviorFactory.setAdminUserApi(adminUserApi);
|
bpmActivityBehaviorFactory.setAdminUserApi(adminUserApi);
|
||||||
bpmActivityBehaviorFactory.setPermissionApi(permissionApi);
|
bpmActivityBehaviorFactory.setPermissionApi(permissionApi);
|
||||||
bpmActivityBehaviorFactory.setDeptApi(deptApi);
|
bpmActivityBehaviorFactory.setDeptApi(deptApi);
|
||||||
// bpmActivityBehaviorFactory.setScripts(scripts);
|
bpmActivityBehaviorFactory.setScripts(scripts);
|
||||||
return bpmActivityBehaviorFactory;
|
return bpmActivityBehaviorFactory;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior;
|
package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
|
||||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
|
import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
|
||||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
|
import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
|
||||||
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
||||||
@ -13,6 +14,8 @@ import org.flowable.bpmn.model.UserTask;
|
|||||||
import org.flowable.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
|
import org.flowable.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
|
||||||
import org.flowable.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFactory;
|
import org.flowable.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFactory;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义的 ActivityBehaviorFactory 实现类,目的如下:
|
* 自定义的 ActivityBehaviorFactory 实现类,目的如下:
|
||||||
* 1. 自定义 {@link #createUserTaskActivityBehavior(UserTask)}:实现自定义的流程任务的 assignee 负责人的分配
|
* 1. 自定义 {@link #createUserTaskActivityBehavior(UserTask)}:实现自定义的流程任务的 assignee 负责人的分配
|
||||||
@ -35,6 +38,8 @@ public class BpmActivityBehaviorFactory extends DefaultActivityBehaviorFactory {
|
|||||||
private DeptApi deptApi;
|
private DeptApi deptApi;
|
||||||
@Setter
|
@Setter
|
||||||
private AdminUserApi adminUserApi;
|
private AdminUserApi adminUserApi;
|
||||||
|
@Setter
|
||||||
|
private List<BpmTaskAssignScript> scripts;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserTaskActivityBehavior createUserTaskActivityBehavior(UserTask userTask) {
|
public UserTaskActivityBehavior createUserTaskActivityBehavior(UserTask userTask) {
|
||||||
@ -44,8 +49,7 @@ public class BpmActivityBehaviorFactory extends DefaultActivityBehaviorFactory {
|
|||||||
userTaskActivityBehavior.setDeptApi(deptApi);
|
userTaskActivityBehavior.setDeptApi(deptApi);
|
||||||
userTaskActivityBehavior.setUserGroupService(userGroupService);
|
userTaskActivityBehavior.setUserGroupService(userGroupService);
|
||||||
userTaskActivityBehavior.setAdminUserApi(adminUserApi);
|
userTaskActivityBehavior.setAdminUserApi(adminUserApi);
|
||||||
//TODO
|
userTaskActivityBehavior.setScripts(scripts);
|
||||||
//userTaskActivityBehavior.setScripts(scripts);
|
|
||||||
return userTaskActivityBehavior;
|
return userTaskActivityBehavior;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
|||||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
|
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
|
||||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
|
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
|
||||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
|
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
|
||||||
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
|
||||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
|
import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
|
||||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
|
import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
|
||||||
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
||||||
@ -30,8 +31,10 @@ import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||||
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
|
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
|
||||||
|
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_ASSIGN_SCRIPT_NOT_EXISTS;
|
||||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_CREATE_FAIL_NO_CANDIDATE_USER;
|
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_CREATE_FAIL_NO_CANDIDATE_USER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,9 +59,17 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
|
|||||||
@Setter
|
@Setter
|
||||||
private PermissionApi permissionApi;
|
private PermissionApi permissionApi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务分配脚本
|
||||||
|
*/
|
||||||
|
private Map<Long, BpmTaskAssignScript> scriptMap = Collections.emptyMap();
|
||||||
|
|
||||||
public BpmUserTaskActivityBehavior(UserTask userTask) {
|
public BpmUserTaskActivityBehavior(UserTask userTask) {
|
||||||
super(userTask);
|
super(userTask);
|
||||||
}
|
}
|
||||||
|
public void setScripts(List<BpmTaskAssignScript> scripts) {
|
||||||
|
this.scriptMap = convertMap(scripts, script -> script.getEnum().getId());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleAssignments(TaskService taskService, String assignee, String owner, List<String> candidateUsers, List<String> candidateGroups, TaskEntity task, ExpressionManager expressionManager, DelegateExecution execution, ProcessEngineConfigurationImpl processEngineConfiguration) {
|
protected void handleAssignments(TaskService taskService, String assignee, String owner, List<String> candidateUsers, List<String> candidateGroups, TaskEntity task, ExpressionManager expressionManager, DelegateExecution execution, ProcessEngineConfigurationImpl processEngineConfiguration) {
|
||||||
@ -100,10 +111,9 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
|
|||||||
assigneeUserIds = calculateTaskCandidateUsersByUser(task, rule);
|
assigneeUserIds = calculateTaskCandidateUsersByUser(task, rule);
|
||||||
} else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType(), rule.getType())) {
|
} else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType(), rule.getType())) {
|
||||||
assigneeUserIds = calculateTaskCandidateUsersByUserGroup(task, rule);
|
assigneeUserIds = calculateTaskCandidateUsersByUserGroup(task, rule);
|
||||||
|
} else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), rule.getType())) {
|
||||||
|
assigneeUserIds = calculateTaskCandidateUsersByScript(task, rule);
|
||||||
}
|
}
|
||||||
// else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), rule.getType())) {
|
|
||||||
// assigneeUserIds = calculateTaskCandidateUsersByScript(task, rule);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 移除被禁用的用户
|
// 移除被禁用的用户
|
||||||
removeDisableUsers(assigneeUserIds);
|
removeDisableUsers(assigneeUserIds);
|
||||||
@ -146,6 +156,22 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {
|
|||||||
return userIds;
|
return userIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Set<Long> calculateTaskCandidateUsersByScript(TaskEntity task, BpmTaskAssignRuleDO rule) {
|
||||||
|
// 获得对应的脚本
|
||||||
|
List<BpmTaskAssignScript> scripts = new ArrayList<>(rule.getOptions().size());
|
||||||
|
rule.getOptions().forEach(id -> {
|
||||||
|
BpmTaskAssignScript script = scriptMap.get(id);
|
||||||
|
if (script == null) {
|
||||||
|
throw exception(TASK_ASSIGN_SCRIPT_NOT_EXISTS, id);
|
||||||
|
}
|
||||||
|
scripts.add(script);
|
||||||
|
});
|
||||||
|
// 逐个计算任务
|
||||||
|
Set<Long> userIds = new HashSet<>();
|
||||||
|
scripts.forEach(script -> CollUtil.addAll(userIds, script.calculateTaskCandidateUsers(task)));
|
||||||
|
return userIds;
|
||||||
|
}
|
||||||
|
|
||||||
private Long chooseTaskAssignee(Set<Long> candidateUserIds) {
|
private Long chooseTaskAssignee(Set<Long> candidateUserIds) {
|
||||||
// TODO 芋艿:未来可以优化下,改成轮询的策略
|
// TODO 芋艿:未来可以优化下,改成轮询的策略
|
||||||
int index = RandomUtil.randomInt(candidateUserIds.size());
|
int index = RandomUtil.randomInt(candidateUserIds.size());
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
|
||||||
|
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bpm 任务分配的自定义 Script 脚本
|
||||||
|
* 使用场景:
|
||||||
|
* 1. 设置审批人为发起人
|
||||||
|
* 2. 设置审批人为发起人的 Leader
|
||||||
|
* 3. 甚至审批人为发起人的 Leader 的 Leader
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public interface BpmTaskAssignScript {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基于流程任务,获得任务的候选用户们
|
||||||
|
*
|
||||||
|
* @param task 任务
|
||||||
|
* @return 候选人用户的编号数组
|
||||||
|
*/
|
||||||
|
Set<Long> calculateTaskCandidateUsers(TaskEntity task);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得枚举值
|
||||||
|
*
|
||||||
|
* @return 枚举值
|
||||||
|
*/
|
||||||
|
BpmTaskRuleScriptEnum getEnum();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,71 @@
|
|||||||
|
package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
||||||
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
|
||||||
|
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
|
||||||
|
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
||||||
|
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
||||||
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||||
|
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||||
|
|
||||||
|
import org.flowable.engine.runtime.ProcessInstance;
|
||||||
|
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
|
||||||
|
import static java.util.Collections.emptySet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分配给发起人的 Leader 审批的 Script 实现类
|
||||||
|
* 目前 Leader 的定义是,
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public abstract class BpmTaskAssignLeaderAbstractScript implements BpmTaskAssignScript {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AdminUserApi adminUserApi;
|
||||||
|
@Resource
|
||||||
|
private DeptApi deptApi;
|
||||||
|
@Resource
|
||||||
|
@Lazy // 解决循环依赖
|
||||||
|
private BpmProcessInstanceService bpmProcessInstanceService;
|
||||||
|
|
||||||
|
protected Set<Long> calculateTaskCandidateUsers(TaskEntity task, int level) {
|
||||||
|
Assert.isTrue(level > 0, "level 必须大于 0");
|
||||||
|
// 获得发起人
|
||||||
|
ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(task.getProcessInstanceId());
|
||||||
|
Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
|
||||||
|
// 获得对应 leve 的部门
|
||||||
|
DeptRespDTO dept = null;
|
||||||
|
for (int i = 0; i < level; i++) {
|
||||||
|
// 获得 level 对应的部门
|
||||||
|
if (dept == null) {
|
||||||
|
dept = getStartUserDept(startUserId);
|
||||||
|
if (dept == null) { // 找不到发起人的部门,所以无法使用该规则
|
||||||
|
return emptySet();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DeptRespDTO parentDept = deptApi.getDept(dept.getParentId());
|
||||||
|
if (parentDept == null) { // 找不到父级部门,所以只好结束寻找。原因是:例如说,级别比较高的人,所在部门层级比较少
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dept = parentDept;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dept.getLeaderUserId() != null ? asSet(dept.getLeaderUserId()) : emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
private DeptRespDTO getStartUserDept(Long startUserId) {
|
||||||
|
AdminUserRespDTO startUser = adminUserApi.getUser(startUserId);
|
||||||
|
if (startUser.getDeptId() == null) { // 找不到部门,所以无法使用该规则
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return deptApi.getDept(startUser.getDeptId());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
|
||||||
|
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分配给发起人的一级 Leader 审批的 Script 实现类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BpmTaskAssignLeaderX1Script extends BpmTaskAssignLeaderAbstractScript {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Long> calculateTaskCandidateUsers(TaskEntity task) {
|
||||||
|
return calculateTaskCandidateUsers(task, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BpmTaskRuleScriptEnum getEnum() {
|
||||||
|
return BpmTaskRuleScriptEnum.LEADER_X1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
|
||||||
|
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分配给发起人的二级 Leader 审批的 Script 实现类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BpmTaskAssignLeaderX2Script extends BpmTaskAssignLeaderAbstractScript {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Long> calculateTaskCandidateUsers(TaskEntity task) {
|
||||||
|
return calculateTaskCandidateUsers(task, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BpmTaskRuleScriptEnum getEnum() {
|
||||||
|
return BpmTaskRuleScriptEnum.LEADER_X2;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
||||||
|
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
|
||||||
|
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
|
||||||
|
import org.flowable.engine.runtime.ProcessInstance;
|
||||||
|
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分配给发起人审批的 Script 实现类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BpmTaskAssignStartUserScript implements BpmTaskAssignScript {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Lazy // 解决循环依赖
|
||||||
|
private BpmProcessInstanceService bpmProcessInstanceService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Long> calculateTaskCandidateUsers(TaskEntity task) {
|
||||||
|
ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(task.getProcessInstanceId());
|
||||||
|
Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
|
||||||
|
return SetUtils.asSet(startUserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BpmTaskRuleScriptEnum getEnum() {
|
||||||
|
return BpmTaskRuleScriptEnum.START_USER;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -5,6 +5,7 @@ import cn.hutool.core.util.ObjectUtil;
|
|||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.PageUtils;
|
import cn.iocoder.yudao.framework.common.util.object.PageUtils;
|
||||||
|
import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO;
|
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
|
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
|
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
|
||||||
@ -198,7 +199,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
|
|||||||
BpmnModel newModel = buildBpmnModel(createReqDTO.getBpmnBytes());
|
BpmnModel newModel = buildBpmnModel(createReqDTO.getBpmnBytes());
|
||||||
BpmnModel oldModel = getBpmnModel(oldProcessDefinition.getId());
|
BpmnModel oldModel = getBpmnModel(oldProcessDefinition.getId());
|
||||||
//TODO 貌似 flowable 不修改这个也不同。需要看看。 sourceSystemId 不同
|
//TODO 貌似 flowable 不修改这个也不同。需要看看。 sourceSystemId 不同
|
||||||
if (equals(oldModel, newModel)) {
|
if (FlowableUtils.equals(oldModel, newModel)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 最终发现都一致,则返回 true
|
// 最终发现都一致,则返回 true
|
||||||
@ -216,19 +217,8 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
|
|||||||
BpmnXMLConverter converter = new BpmnXMLConverter();
|
BpmnXMLConverter converter = new BpmnXMLConverter();
|
||||||
return converter.convertToBpmnModel(new BytesStreamSource(bpmnBytes), true, true);
|
return converter.convertToBpmnModel(new BytesStreamSource(bpmnBytes), true, true);
|
||||||
}
|
}
|
||||||
//TODO 移出去
|
|
||||||
public boolean equals(BpmnModel oldModel, BpmnModel newModel) {
|
|
||||||
// 由于 BpmnModel 未提供 equals 方法,所以只能转成字节数组,进行比较
|
|
||||||
return Arrays.equals(getBpmnBytes(oldModel), getBpmnBytes(newModel));
|
|
||||||
}
|
|
||||||
//TODO 移出去
|
|
||||||
public byte[] getBpmnBytes(BpmnModel model) {
|
|
||||||
if (model == null) {
|
|
||||||
return new byte[0];
|
|
||||||
}
|
|
||||||
BpmnXMLConverter converter = new BpmnXMLConverter();
|
|
||||||
return converter.convertToXML(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BpmProcessDefinitionExtDO getProcessDefinitionExt(String id) {
|
public BpmProcessDefinitionExtDO getProcessDefinitionExt(String id) {
|
||||||
|
@ -5,6 +5,7 @@ import cn.hutool.core.util.ObjectUtil;
|
|||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||||
|
import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
|
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
|
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
|
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
|
||||||
@ -87,37 +88,15 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService{
|
|||||||
if (model == null) {
|
if (model == null) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获得用户任务,只有用户任务才可以设置分配规则
|
// 获得用户任务,只有用户任务才可以设置分配规则
|
||||||
List<UserTask> userTasks = getBpmnModelElements(model, UserTask.class);
|
List<UserTask> userTasks = FlowableUtils.getBpmnModelElements(model, UserTask.class);
|
||||||
if (CollUtil.isEmpty(userTasks)) {
|
if (CollUtil.isEmpty(userTasks)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 转换数据
|
// 转换数据
|
||||||
return BpmTaskAssignRuleConvert.INSTANCE.convertList(userTasks, rules);
|
return BpmTaskAssignRuleConvert.INSTANCE.convertList(userTasks, rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO 需要移出去
|
|
||||||
* 获得 BPMN 流程中,指定的元素们
|
|
||||||
*
|
|
||||||
* @param model
|
|
||||||
* @param clazz 指定元素。例如说,{@link org.flowable.bpmn.model.UserTask}、{@link org.flowable.bpmn.model.Gateway} 等等
|
|
||||||
* @return 元素们
|
|
||||||
*/
|
|
||||||
public static <T extends FlowElement> List<T> getBpmnModelElements(BpmnModel model, Class<T> clazz) {
|
|
||||||
List<T> result = new ArrayList<>();
|
|
||||||
model.getProcesses().forEach(process -> {
|
|
||||||
process.getFlowElements().forEach(flowElement -> {
|
|
||||||
if (flowElement.getClass().isAssignableFrom(clazz)) {
|
|
||||||
result.add((T) flowElement);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long createTaskAssignRule(@Valid BpmTaskAssignRuleCreateReqVO reqVO) {
|
public Long createTaskAssignRule(@Valid BpmTaskAssignRuleCreateReqVO reqVO) {
|
||||||
// 校验参数
|
// 校验参数
|
||||||
|
@ -106,6 +106,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) {
|
public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) {
|
||||||
// 获得流程定义
|
// 获得流程定义
|
||||||
ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId());
|
ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId());
|
||||||
|
@ -25,6 +25,7 @@ import org.flowable.task.api.TaskQuery;
|
|||||||
import org.flowable.task.api.history.HistoricTaskInstance;
|
import org.flowable.task.api.history.HistoricTaskInstance;
|
||||||
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
|
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.transaction.support.TransactionSynchronization;
|
import org.springframework.transaction.support.TransactionSynchronization;
|
||||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||||
|
|
||||||
@ -167,6 +168,7 @@ public class BpmTaskServiceImpl implements BpmTaskService{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void approveTask(Long userId, @Valid BpmTaskApproveReqVO reqVO) {
|
public void approveTask(Long userId, @Valid BpmTaskApproveReqVO reqVO) {
|
||||||
// 校验任务存在
|
// 校验任务存在
|
||||||
Task task = checkTask(userId, reqVO.getId());
|
Task task = checkTask(userId, reqVO.getId());
|
||||||
@ -184,6 +186,7 @@ public class BpmTaskServiceImpl implements BpmTaskService{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO) {
|
public void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO) {
|
||||||
Task task = checkTask(userId, reqVO.getId());
|
Task task = checkTask(userId, reqVO.getId());
|
||||||
// 校验流程实例存在
|
// 校验流程实例存在
|
||||||
@ -234,16 +237,15 @@ public class BpmTaskServiceImpl implements BpmTaskService{
|
|||||||
.setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()))
|
.setAssigneeUserId(NumberUtils.parseLong(task.getAssignee()))
|
||||||
.setTaskId(task.getId());
|
.setTaskId(task.getId());
|
||||||
taskExtMapper.updateByTaskId(taskExtDO);
|
taskExtMapper.updateByTaskId(taskExtDO);
|
||||||
//TODO 创建任务时候 也会调用 updateTaskExtAssign, processInstance 名称为空 校验不通过
|
|
||||||
// 发送通知。在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。
|
// 发送通知。在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。
|
||||||
// TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
||||||
// @Override
|
@Override
|
||||||
// public void afterCommit() {
|
public void afterCommit() {
|
||||||
// ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
|
ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId());
|
||||||
// AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));
|
AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));
|
||||||
// messageService.sendMessageWhenTaskAssigned(BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task));
|
messageService.sendMessageWhenTaskAssigned(BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task));
|
||||||
// }
|
}
|
||||||
// });
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user