工作流模块提交
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
package com.njcn.bpm.strategy;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.njcn.bpm.enums.BpmTaskCandidateStrategyEnum;
|
||||
import com.njcn.bpm.utils.BpmnModelUtils;
|
||||
import com.njcn.bpm.utils.CollectionUtils;
|
||||
import com.njcn.common.pojo.enums.common.DataStateEnum;
|
||||
import com.njcn.common.pojo.exception.BusinessException;
|
||||
import com.njcn.user.api.UserFeignClient;
|
||||
import com.njcn.user.pojo.po.User;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.bpmn.model.UserTask;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Slf4j
|
||||
public class BpmTaskCandidateInvoker {
|
||||
|
||||
private final Map<BpmTaskCandidateStrategyEnum, IBpmTaskCandidateStrategy> strategyMap = new HashMap<>();
|
||||
|
||||
private final UserFeignClient adminUserApi;
|
||||
|
||||
public BpmTaskCandidateInvoker(List<IBpmTaskCandidateStrategy> strategyList,
|
||||
UserFeignClient adminUserApi) {
|
||||
strategyList.forEach(strategy -> {
|
||||
IBpmTaskCandidateStrategy oldStrategy = strategyMap.put(strategy.getStrategy(), strategy);
|
||||
Assert.isNull(oldStrategy, "策略(%s) 重复", strategy.getStrategy());
|
||||
});
|
||||
this.adminUserApi = adminUserApi;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验流程模型的任务分配规则全部都配置了
|
||||
* 目的:如果有规则未配置,会导致流程任务找不到负责人,进而流程无法进行下去!
|
||||
*
|
||||
* @param bpmnBytes BPMN XML
|
||||
*/
|
||||
public void validateBpmnConfig(byte[] bpmnBytes) {
|
||||
BpmnModel bpmnModel = BpmnModelUtils.getBpmnModel(bpmnBytes);
|
||||
assert bpmnModel != null;
|
||||
List<UserTask> userTaskList = BpmnModelUtils.getBpmnModelElements(bpmnModel, UserTask.class);
|
||||
// 遍历所有的 UserTask,校验审批人配置
|
||||
userTaskList.forEach(userTask -> {
|
||||
// 1. 非空校验
|
||||
Integer strategy = BpmnModelUtils.parseCandidateStrategy(userTask);
|
||||
String param = BpmnModelUtils.parseCandidateParam(userTask);
|
||||
if (strategy == null) {
|
||||
throw new BusinessException("部署流程失败,原因:BPMN 流程图中,用户任务(" + userTask.getName() + ")的名字不存在");
|
||||
}
|
||||
IBpmTaskCandidateStrategy candidateStrategy = getCandidateStrategy(strategy);
|
||||
if (candidateStrategy.isParamRequired() && StrUtil.isBlank(param)) {
|
||||
throw new BusinessException("部署流程失败,原因:用户任务(" + userTask.getName() + ")未配置审批人,请点击【流程设计】按钮,选择该它的【任务(审批人)】进行配置");
|
||||
}
|
||||
// 2. 具体策略校验
|
||||
getCandidateStrategy(strategy).validateParam(param);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算任务的候选人
|
||||
*
|
||||
* @param execution 执行任务
|
||||
* @return 用户编号集合
|
||||
*/
|
||||
public List<String> calculateUsers(DelegateExecution execution) {
|
||||
Integer strategy = BpmnModelUtils.parseCandidateStrategy(execution.getCurrentFlowElement());
|
||||
String param = BpmnModelUtils.parseCandidateParam(execution.getCurrentFlowElement());
|
||||
// 1.1 计算任务的候选人
|
||||
List<String> userIds = getCandidateStrategy(strategy).calculateUsers(execution, param);
|
||||
// 1.2 移除被禁用的用户
|
||||
removeDisableUsers(userIds);
|
||||
|
||||
// 2. 校验是否有候选人
|
||||
if (CollUtil.isEmpty(userIds)) {
|
||||
log.error("[calculateUsers][流程任务({}/{}/{}) 任务规则({}/{}) 找不到候选人]", execution.getId(),
|
||||
execution.getProcessDefinitionId(), execution.getCurrentActivityId(), strategy, param);
|
||||
throw new BusinessException("操作失败,原因:找不到任务的审批人!");
|
||||
}
|
||||
return userIds;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void removeDisableUsers(List<String> assigneeUserIds) {
|
||||
if (CollUtil.isEmpty(assigneeUserIds)) {
|
||||
return;
|
||||
}
|
||||
List<User> users = adminUserApi.getUserByIdList(assigneeUserIds).getData();
|
||||
Map<String, User> userMap = CollectionUtils.convertMap(users, User::getId);
|
||||
assigneeUserIds.removeIf(id -> {
|
||||
User user = userMap.get(id);
|
||||
return user == null || !DataStateEnum.ENABLE.getCode().equals(user.getState());
|
||||
});
|
||||
}
|
||||
|
||||
private IBpmTaskCandidateStrategy getCandidateStrategy(Integer strategy) {
|
||||
BpmTaskCandidateStrategyEnum strategyEnum = BpmTaskCandidateStrategyEnum.valueOf(strategy);
|
||||
Assert.notNull(strategyEnum, "策略(%s) 不存在", strategy);
|
||||
IBpmTaskCandidateStrategy strategyObj = strategyMap.get(strategyEnum);
|
||||
Assert.notNull(strategyObj, "策略(%s) 不存在", strategy);
|
||||
return strategyObj;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.njcn.bpm.strategy;
|
||||
|
||||
import com.njcn.user.api.UserFeignClient;
|
||||
import com.njcn.bpm.utils.StrUtils;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
import com.njcn.bpm.enums.BpmTaskCandidateStrategyEnum;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 角色 {@link IBpmTaskCandidateStrategy} 实现类
|
||||
*
|
||||
* @author kyle
|
||||
*/
|
||||
@Component
|
||||
public class BpmTaskCandidateRoleStrategy implements IBpmTaskCandidateStrategy {
|
||||
|
||||
@Resource
|
||||
private UserFeignClient userFeignClient;
|
||||
|
||||
// @Resource
|
||||
// private PermissionApi permissionApi;
|
||||
|
||||
@Override
|
||||
public BpmTaskCandidateStrategyEnum getStrategy() {
|
||||
return BpmTaskCandidateStrategyEnum.ROLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateParam(String param) {
|
||||
// Set<Long> roleIds = StrUtils.splitToLongSet(param);
|
||||
// roleApi.validRoleList(roleIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> calculateUsers(DelegateExecution execution, String param) {
|
||||
List<String> roleIds = StrUtils.splitToStringList(param);
|
||||
return userFeignClient.getUserIdByRoleId(roleIds).getData();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.njcn.bpm.strategy;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import com.njcn.bpm.enums.BpmTaskCandidateStrategyEnum;
|
||||
import com.njcn.bpm.service.task.IBpmProcessInstanceService;
|
||||
import com.njcn.bpm.utils.BpmnModelUtils;
|
||||
import com.njcn.bpm.utils.FlowableUtils;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.bpmn.model.UserTask;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Component
|
||||
public class BpmTaskCandidateStartUserSelectStrategy implements IBpmTaskCandidateStrategy {
|
||||
|
||||
@Resource
|
||||
@Lazy // 延迟加载,避免循环依赖
|
||||
private IBpmProcessInstanceService processInstanceService;
|
||||
|
||||
@Override
|
||||
public BpmTaskCandidateStrategyEnum getStrategy() {
|
||||
return BpmTaskCandidateStrategyEnum.START_USER_SELECT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateParam(String param) {}
|
||||
|
||||
@Override
|
||||
public List<String> calculateUsers(DelegateExecution execution, String param) {
|
||||
ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getProcessInstanceId());
|
||||
Assert.notNull(processInstance, "流程实例({})不能为空", execution.getProcessInstanceId());
|
||||
Map<String, List<String>> startUserSelectAssignees = FlowableUtils.getStartUserSelectAssignees(processInstance);
|
||||
Assert.notNull(startUserSelectAssignees, "流程实例({}) 的发起人自选审批人不能为空",
|
||||
execution.getProcessInstanceId());
|
||||
// 获得审批人
|
||||
List<String> assignees = startUserSelectAssignees.get(execution.getCurrentActivityId());
|
||||
return new ArrayList<>(assignees);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isParamRequired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得发起人自选审批人的 UserTask 列表
|
||||
*
|
||||
* @param bpmnModel BPMN 模型
|
||||
* @return UserTask 列表
|
||||
*/
|
||||
public static List<UserTask> getStartUserSelectUserTaskList(BpmnModel bpmnModel) {
|
||||
if (bpmnModel == null) {
|
||||
return null;
|
||||
}
|
||||
List<UserTask> userTaskList = BpmnModelUtils.getBpmnModelElements(bpmnModel, UserTask.class);
|
||||
if (CollUtil.isEmpty(userTaskList)) {
|
||||
return null;
|
||||
}
|
||||
userTaskList.removeIf(userTask -> !Objects.equals(BpmnModelUtils.parseCandidateStrategy(userTask),
|
||||
BpmTaskCandidateStrategyEnum.START_USER_SELECT.getStrategy()));
|
||||
return userTaskList;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.njcn.bpm.strategy;
|
||||
|
||||
import com.njcn.bpm.enums.BpmTaskCandidateStrategyEnum;
|
||||
import com.njcn.bpm.utils.StrUtils;
|
||||
import com.njcn.user.api.UserFeignClient;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户 {@link IBpmTaskCandidateStrategy} 实现类
|
||||
*
|
||||
* @author kyle
|
||||
*/
|
||||
@Component
|
||||
public class BpmTaskCandidateUserStrategy implements IBpmTaskCandidateStrategy {
|
||||
|
||||
@Resource
|
||||
private UserFeignClient adminUserApi;
|
||||
|
||||
@Override
|
||||
public BpmTaskCandidateStrategyEnum getStrategy() {
|
||||
return BpmTaskCandidateStrategyEnum.USER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateParam(String param) {
|
||||
// adminUserApi.validateUserList(StrUtils.splitToLongSet(param));
|
||||
//暂时默认均有效,后期可以加强管理,todo...
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> calculateUsers(DelegateExecution execution, String param) {
|
||||
return StrUtils.splitToStringList(param);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.njcn.bpm.strategy;
|
||||
|
||||
import com.njcn.bpm.enums.BpmTaskCandidateStrategyEnum;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* BPM 任务的候选人的策略接口
|
||||
*
|
||||
* 例如说:分配审批人
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface IBpmTaskCandidateStrategy {
|
||||
|
||||
/**
|
||||
* 对应策略
|
||||
*
|
||||
* @return 策略
|
||||
*/
|
||||
BpmTaskCandidateStrategyEnum getStrategy();
|
||||
|
||||
/**
|
||||
* 校验参数
|
||||
*
|
||||
* @param param 参数
|
||||
*/
|
||||
void validateParam(String param);
|
||||
|
||||
/**
|
||||
* 基于执行任务,获得任务的候选用户们
|
||||
*
|
||||
* @param execution 执行任务
|
||||
* @return 用户编号集合
|
||||
*/
|
||||
List<String> calculateUsers(DelegateExecution execution, String param);
|
||||
|
||||
/**
|
||||
* 是否一定要输入参数
|
||||
*
|
||||
* @return 是否
|
||||
*/
|
||||
default boolean isParamRequired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user