【代码评审】BPM:下一个审批人

This commit is contained in:
YunaiV 2025-03-06 07:51:20 +08:00
parent 8a5638bdea
commit 9ff56403d6
9 changed files with 73 additions and 79 deletions

View File

@ -24,7 +24,7 @@ public interface ErrorCodeConstants {
ErrorCode MODEL_DEPLOY_FAIL_BPMN_START_EVENT_NOT_EXISTS = new ErrorCode(1_009_002_005, "部署流程失败原因BPMN 流程图中,没有开始事件");
ErrorCode MODEL_DEPLOY_FAIL_BPMN_USER_TASK_NAME_NOT_EXISTS = new ErrorCode(1_009_002_006, "部署流程失败原因BPMN 流程图中,用户任务({})的名字不存在");
ErrorCode MODEL_UPDATE_FAIL_NOT_MANAGER = new ErrorCode(1_009_002_007, "操作流程失败,原因:你不是该流程({})的管理员");
ErrorCode MODEL_DEPLOY_FAIL_BPMN_USER_TASK_RULE_TYPE_NOT_APPROVE_USER_SELECT = new ErrorCode(1_009_002_008, "部署流程失败,原因:BPMN 流程图中,用户任务({})的规则类型不能是【审批人自选】");
ErrorCode MODEL_DEPLOY_FAIL_FIRST_USER_TASK_CANDIDATE_STRATEGY_ERROR = new ErrorCode(1_009_002_008, "部署流程失败,原因:首个任务({})的审批人不能是【审批人自选】");
// ========== 流程定义 1-009-003-000 ==========
ErrorCode PROCESS_DEFINITION_KEY_NOT_MATCH = new ErrorCode(1_009_003_000, "流程定义的标识期望是({}),当前是({}),请修改 BPMN 流程图");
@ -41,7 +41,7 @@ public interface ErrorCodeConstants {
ErrorCode PROCESS_INSTANCE_START_USER_CAN_START = new ErrorCode(1_009_004_005, "发起流程失败,你没有权限发起该流程");
ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW = new ErrorCode(1_009_004_005, "流程取消失败,该流程不允许取消");
ErrorCode PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR = new ErrorCode(1_009_004_006, "流程 Http 触发器请求调用失败");
ErrorCode PROCESS_INSTANCE_APPROVE_USER_SELECT_ASSIGNEES_NOT_CONFIG = new ErrorCode(1_009_004_007, "任务({})的下一个执行节点审批人未配置");
ErrorCode PROCESS_INSTANCE_APPROVE_USER_SELECT_ASSIGNEES_NOT_CONFIG = new ErrorCode(1_009_004_007, "下一个任务({})的审批人未配置");
// ========== 流程任务 1-009-005-000 ==========
ErrorCode TASK_OPERATE_FAIL_ASSIGN_NOT_SELF = new ErrorCode(1_009_005_001, "操作失败,原因:该任务的审批人不是你");

View File

@ -24,8 +24,8 @@ public enum BpmTaskCandidateStrategyEnum implements ArrayValuable<Integer> {
MULTI_DEPT_LEADER_MULTI(23, "连续多级部门的负责人"),
POST(22, "岗位"),
USER(30, "用户"),
APPROVE_USER_SELECT(34, "审批人,在审批时选择下一个节点的审批人"), // 审批人在审批时选择下一个节点的审批人
START_USER_SELECT(35, "发起人自选"), // 申请人自己可在提交申请时选择此节点的审批人
APPROVE_USER_SELECT(34, "审批人自身"), // 当前审批人在审批时选择下一个节点的审批人
START_USER_SELECT(35, "发起人自选"), // 申请人自己可在提交申请时选择此节点的审批人
START_USER(36, "发起人自己"), // 申请人自己, 一般紧挨开始节点常用于发起人信息审核场景
START_USER_DEPT_LEADER(37, "发起人部门负责人"),
START_USER_DEPT_LEADER_MULTI(38, "发起人连续多级部门的负责人"),

View File

@ -27,12 +27,14 @@ public class BpmnVariableConstants {
* 流程实例的变量 - 发起用户选择的审批人 Map
*
* @see ProcessInstance#getProcessVariables()
* @see BpmTaskCandidateStrategyEnum#START_USER_SELECT
*/
public static final String PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES = "PROCESS_START_USER_SELECT_ASSIGNEES";
/**
* 流程实例的变量 - 审批人选择的审批人 Map
*
* @see ProcessInstance#getProcessVariables()
* @see BpmTaskCandidateStrategyEnum#APPROVE_USER_SELECT
*/
public static final String PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES = "PROCESS_APPROVE_USER_SELECT_ASSIGNEES";
/**

View File

@ -808,16 +808,16 @@ public class BpmnModelUtils {
// 情况ExclusiveGateway 排它只有一个满足条件的如果没有就走默认的
if (currentElement instanceof ExclusiveGateway) {
// 查找满足条件的 SequenceFlow 路径
SequenceFlow matchSequenceFlow = findMatchSequenceFlow((Gateway) currentElement, variables);
SequenceFlow matchSequenceFlow = findMatchSequenceFlowByExclusiveGateway((Gateway) currentElement, variables);
// 遍历满足条件的 SequenceFlow 路径
if (matchSequenceFlow != null) {
simulateNextFlowElements(matchSequenceFlow.getTargetFlowElement(), variables, resultElements, visitElements);
}
}
// 情况InclusiveGateway 包容多个满足条件的如果没有就走默认的
else if (currentElement instanceof InclusiveGateway) {
else if (currentElement instanceof InclusiveGateway) {
// 查找满足条件的 SequenceFlow 路径
Collection<SequenceFlow> matchSequenceFlows = findMatchSequenceFlows((Gateway) currentElement, variables);
Collection<SequenceFlow> matchSequenceFlows = findMatchSequenceFlowsByInclusiveGateway((Gateway) currentElement, variables);
// 遍历满足条件的 SequenceFlow 路径
matchSequenceFlows.forEach(
flow -> simulateNextFlowElements(flow.getTargetFlowElement(), variables, resultElements, visitElements));
@ -889,7 +889,7 @@ public class BpmnModelUtils {
private static void handleExclusiveGateway(Gateway gateway, BpmnModel bpmnModel,
Map<String, Object> variables, List<FlowNode> nextFlowNodes) {
// 查找满足条件的 SequenceFlow 路径
SequenceFlow matchSequenceFlow = findMatchSequenceFlow(gateway, variables);
SequenceFlow matchSequenceFlow = findMatchSequenceFlowByExclusiveGateway(gateway, variables);
// 遍历满足条件的 SequenceFlow 路径
if (matchSequenceFlow != null) {
FlowElement targetElement = bpmnModel.getFlowElement(matchSequenceFlow.getTargetRef());
@ -906,7 +906,7 @@ public class BpmnModelUtils {
* @param variables 流程变量
* @return 符合条件的路径
*/
private static SequenceFlow findMatchSequenceFlow(Gateway gateway, Map<String, Object> variables){
private static SequenceFlow findMatchSequenceFlowByExclusiveGateway(Gateway gateway, Map<String, Object> variables) {
SequenceFlow matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(),
flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId())
&& (evalConditionExpress(variables, flow.getConditionExpression())));
@ -932,7 +932,7 @@ public class BpmnModelUtils {
private static void handleInclusiveGateway(Gateway gateway, BpmnModel bpmnModel,
Map<String, Object> variables, List<FlowNode> nextFlowNodes) {
// 查找满足条件的 SequenceFlow 路径集合
Collection<SequenceFlow> matchSequenceFlows = findMatchSequenceFlows(gateway, variables);
Collection<SequenceFlow> matchSequenceFlows = findMatchSequenceFlowsByInclusiveGateway(gateway, variables);
// 遍历满足条件的 SequenceFlow 路径获取目标节点
matchSequenceFlows.forEach(flow -> {
FlowElement targetElement = bpmnModel.getFlowElement(flow.getTargetRef());
@ -949,7 +949,7 @@ public class BpmnModelUtils {
* @param variables 流程变量
* @return 符合条件的路径
*/
private static Collection<SequenceFlow> findMatchSequenceFlows(Gateway gateway, Map<String, Object> variables) {
private static Collection<SequenceFlow> findMatchSequenceFlowsByInclusiveGateway(Gateway gateway, Map<String, Object> variables) {
// 查找满足条件的 SequenceFlow 路径
Collection<SequenceFlow> matchSequenceFlows = CollUtil.filterNew(gateway.getOutgoingFlows(),
flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId())

View File

@ -243,15 +243,15 @@ public class BpmModelServiceImpl implements BpmModelService {
if (startEvent == null) {
throw exception(MODEL_DEPLOY_FAIL_BPMN_START_EVENT_NOT_EXISTS);
}
// 2. 校验第一个用户任务的规则类型是否为 审批人自选如果是则抛出异常第一个用户任务的规则类型不允许是审批人自选因为会出现无审批人的情况
// 2. 校验第一个用户任务的规则类型是否为审批人自选如果是则抛出异常原因是流程发起后直接进入第一个用户任务会出现无审批人的情况
List<SequenceFlow> outgoingFlows = startEvent.getOutgoingFlows();
if (CollUtil.isNotEmpty(outgoingFlows)){
// 2.1 获取第一个用户任务节点
// TODO @小北可能极端情况下startEvent 后面接了个 serviceTask接着才是 userTask
// TODO @小北simple 因为第一个任务是发起人可能要找第二个任务
if (CollUtil.isNotEmpty(outgoingFlows)) {
FlowElement targetFlowElement = outgoingFlows.get(0).getTargetFlowElement();
// 2.2 获取审批人策略
Integer candidateStrategy = parseCandidateStrategy(targetFlowElement);
if (ObjUtil.equals(candidateStrategy, BpmTaskCandidateStrategyEnum.APPROVE_USER_SELECT.getStrategy())){
throw exception(MODEL_DEPLOY_FAIL_BPMN_USER_TASK_RULE_TYPE_NOT_APPROVE_USER_SELECT, targetFlowElement.getName());
if (Objects.equals(candidateStrategy, BpmTaskCandidateStrategyEnum.APPROVE_USER_SELECT.getStrategy())) {
throw exception(MODEL_DEPLOY_FAIL_FIRST_USER_TASK_CANDIDATE_STRATEGY_ERROR, targetFlowElement.getName());
}
}
// 3. 校验 UserTask name 都配置了

View File

@ -97,7 +97,7 @@ public interface BpmProcessInstanceService {
BpmApprovalDetailRespVO getApprovalDetail(Long loginUserId, @Valid BpmApprovalDetailReqVO reqVO);
/**
* 获取下一个执行节点信息
* 获取下一个执行节点信息
*
* @param loginUserId 登录人的用户编号
* @param reqVO 请求信息

View File

@ -11,7 +11,6 @@ import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.common.util.object.PageUtils;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
@ -179,9 +178,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
startUserId = Long.valueOf(historicProcessInstance.getStartUserId());
processInstanceStatus = FlowableUtils.getProcessInstanceStatus(historicProcessInstance);
// 合并 DB 和前端传递的流量变量以前端的为主
Map<String, Object> historicVariables = historicProcessInstance.getProcessVariables();
if (CollUtil.isNotEmpty(historicVariables)) {
processVariables.putAll(historicVariables);
if (CollUtil.isNotEmpty(historicProcessInstance.getProcessVariables())) {
processVariables.putAll(historicProcessInstance.getProcessVariables());
}
}
if (CollUtil.isNotEmpty(reqVO.getProcessVariables())) {
@ -222,9 +220,11 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
List<ActivityNode> simulateActivityNodes = getSimulateApproveNodeList(startUserId, bpmnModel,
processDefinitionInfo,
processVariables, activities);
// 3.3 如果是发起动作,activityId为开始节点不校验审批人自选节点
if (ObjUtil.isNotNull(reqVO.getActivityId()) && ObjUtil.equals(reqVO.getActivityId(),BpmnModelConstants.START_USER_NODE_ID)){
simulateActivityNodes.removeIf(node -> BpmTaskCandidateStrategyEnum.APPROVE_USER_SELECT.getStrategy().equals(node.getCandidateStrategy()));
// 3.3 如果是发起动作activityId 为开始节点不校验审批人自选节点
// TODO @小北ObjUtil.equals(reqVO.getActivityId(), BpmnModelConstants.START_USER_NODE_ID) 够啦不用判空
if (ObjUtil.isNotNull(reqVO.getActivityId()) && ObjUtil.equals(reqVO.getActivityId(), BpmnModelConstants.START_USER_NODE_ID)) {
simulateActivityNodes.removeIf(node ->
BpmTaskCandidateStrategyEnum.APPROVE_USER_SELECT.getStrategy().equals(node.getCandidateStrategy()));
}
// 4. 拼接最终数据
@ -234,46 +234,37 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
@Override
public List<ActivityNode> getNextApprovalNodes(Long loginUserId, BpmApprovalDetailReqVO reqVO) {
// 1.1 校验任务存在
Task task = taskService.getTask(reqVO.getTaskId());
if (task == null) {
throw exception(TASK_NOT_EXISTS);
}
// 1.2 校验任务是否由当前用户审批
if (StrUtil.isNotBlank(task.getAssignee())
&& ObjectUtil.notEqual(loginUserId, NumberUtils.parseLong(task.getAssignee()))) {
throw exception(TASK_OPERATE_FAIL_ASSIGN_NOT_SELF);
}
// 1.3 校验流程实例存在
// 1.1 校验任务存在且是当前用户的
Task task = taskService.validateTask(loginUserId, reqVO.getTaskId());
// 1.2 校验流程实例存在
ProcessInstance instance = getProcessInstance(task.getProcessInstanceId());
if (instance == null) {
throw exception(PROCESS_INSTANCE_NOT_EXISTS);
}
// 1.4 校验BpmnModel
BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(task.getProcessDefinitionId());
if (bpmnModel == null) {
return null;
}
//1.5 流程实例是否存在
HistoricProcessInstance historicProcessInstance = getHistoricProcessInstance(task.getProcessInstanceId());
if (historicProcessInstance == null) {
throw exception(ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS);
}
// 1.3 校验BpmnModel
BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(task.getProcessDefinitionId());
if (bpmnModel == null) {
return null;
}
// 2 设置流程变量
// 2. 设置流程变量
Map<String, Object> processVariables = new HashMap<>();
// 2.1 获取历史中流程变量
Map<String, Object> historicVariables = historicProcessInstance.getProcessVariables();
if (CollUtil.isNotEmpty(historicVariables)) {
processVariables.putAll(historicVariables);
if (CollUtil.isNotEmpty(historicProcessInstance.getProcessVariables())) {
processVariables.putAll(historicProcessInstance.getProcessVariables());
}
// 2.2 合并前端传递的流程变量以前端为准
if (CollUtil.isNotEmpty(reqVO.getProcessVariables())) {
processVariables.putAll(reqVO.getProcessVariables());
}
// 3 获取当前任务节点的信息
FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey());
// 3.1 获取下一个将要执行的节点集合
FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey());
List<FlowNode> nextFlowNodes = BpmnModelUtils.getNextFlowNodes(flowElement, bpmnModel, processVariables);
return convertList(nextFlowNodes, node -> {
List<Long> candidateUserIds = getTaskCandidateUserList(bpmnModel, node.getId(),
@ -290,6 +281,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
.setName(node.getName())
.setStatus(BpmTaskStatusEnum.RUNNING.getStatus())
.setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(node))
// TODO @小北先把 candidateUserIds 设置完然后最后拼接 candidateUsers 信息这样如果有多个节点就不用重复查询啦类似 buildApprovalDetail 思路
// TODO 先拼接处 List ActivityNode
// TODO 接着再起一段处理 adminUserApi.getUserMap(candidateUserIds)deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId))
.setCandidateUsers(candidateUsers);
});
}
@ -745,16 +739,11 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, userId); // 设置流程变量发起人 ID
variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, // 流程实例状态审批中
BpmProcessInstanceStatusEnum.RUNNING.getStatus());
variables.put(BpmnVariableConstants.PROCESS_INSTANCE_SKIP_EXPRESSION_ENABLED, true); // 跳过表达式需要添加此变量为
// true不影响没配置
// skipExpression 的节点
variables.put(BpmnVariableConstants.PROCESS_INSTANCE_SKIP_EXPRESSION_ENABLED, true); // 跳过表达式需要添加此变量为 true不影响没配置 skipExpression 的节点
if (CollUtil.isNotEmpty(startUserSelectAssignees)) {
// 设置流程变量发起人自选审批人
variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES,
startUserSelectAssignees);
// // 设置流程变量审批人自选审批人
// variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES,
// startUserSelectAssignees);
}
// 3. 创建流程
@ -796,7 +785,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
return;
}
// 2.1 移除掉不是发起人或者审批人自选审批人节点
// 2.1 移除掉不是发起人自选审批人节点
activityNodes.removeIf(task ->
ObjectUtil.notEqual(BpmTaskCandidateStrategyEnum.START_USER_SELECT.getStrategy(), task.getCandidateStrategy()));
// 2.2 流程发起时要先获取当前流程的预测走向节点发起时只校验预测的节点发起人自选审批人的审批人和抄送人是否都配置了

View File

@ -92,6 +92,14 @@ public interface BpmTaskService {
*/
List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId, Boolean asc);
/**
* 校验任务是否存在并且是否是分配给自己的任务
*
* @param userId 用户 id
* @param taskId task id
*/
Task validateTask(Long userId, String taskId);
/**
* 获取任务
*

View File

@ -21,7 +21,6 @@ import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskSignTypeEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
@ -277,13 +276,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
return query.list();
}
/**
* 校验任务是否存在并且是否是分配给自己的任务
*
* @param userId 用户 id
* @param taskId task id
*/
private Task validateTask(Long userId, String taskId) {
@Override
public Task validateTask(Long userId, String taskId) {
Task task = validateTaskExist(taskId);
// 为什么判断 assignee 非空的情况下
// 例如说在审批人为空时我们会有自动审批通过的策略此时 userId null允许通过
@ -552,12 +546,14 @@ public class BpmTaskServiceImpl implements BpmTaskService {
// 2.3 调用 BPM complete 去完成任务
// 其中variables 是存储动态表单到 local 任务级别过滤一下避免 ProcessInstance 系统级的变量被占用
if (CollUtil.isNotEmpty(reqVO.getVariables())) {
// 校验传递的参数中是否为下一个将要执行的任务节点
// 校验并处理 APPROVE_USER_SELECT 当前审批人选择下一节点审批人的逻辑
Map<String, Object> variables = validateAndSetNextAssignees(task.getTaskDefinitionKey(), reqVO.getVariables(),
bpmnModel, reqVO.getNextAssignees(), instance);
// 完成任务
runtimeService.setVariables(task.getProcessInstanceId(), variables);
taskService.complete(task.getId(), variables, true);
} else {
// 完成任务
taskService.complete(task.getId());
}
@ -579,54 +575,52 @@ public class BpmTaskServiceImpl implements BpmTaskService {
* @param processInstance 流程实例
*/
private Map<String, Object> validateAndSetNextAssignees(String taskDefinitionKey, Map<String, Object> variables, BpmnModel bpmnModel,
Map<String, List<Long>> nextAssignees, ProcessInstance processInstance) {
Map<String, List<Long>> nextAssignees, ProcessInstance processInstance) {
// 下一个节点参数为空不做处理表示流程正常流转无需选择下一个节点的审判人
if (CollUtil.isEmpty(nextAssignees)){
// TODO @小北会出现漏选其实需要的情况哇
if (CollUtil.isEmpty(nextAssignees)) {
return variables;
}
// 1. 获取当前任务节点的信息
// 1. 获取下一个将要执行的节点集合
FlowElement flowElement = bpmnModel.getFlowElement(taskDefinitionKey);
// 2. 获取下一个将要执行的节点集合
List<FlowNode> nextFlowNodes = getNextFlowNodes(flowElement, bpmnModel, variables);
// 2. 循环下一个将要执行的节点集合
Map<String, List<Long>> processVariables = new HashMap<>();
// 3. 循环下一个将要执行的节点集合
for (FlowNode nextFlowNode : nextFlowNodes) {
// 3.1 获取下一个将要执行节点中的审批人策略
Integer candidateStrategy = parseCandidateStrategy(nextFlowNode);
// 3.2 判断节点是否为执行节点仅校验节点
if (!nextAssignees.containsKey(nextFlowNode.getId())) {
throw exception(TASK_TARGET_NODE_NOT_EXISTS, nextFlowNode.getName());
}
// 3.3 获取节点中的审批人
List<Long> assignees = nextAssignees.get(nextFlowNode.getId());
// 3.4 流程变量
// 3.5 如果节点中的审批人策略为 发起人自选
// 2.1 情况一如果节点中的审批人策略为 发起人自选
Integer candidateStrategy = parseCandidateStrategy(nextFlowNode);
if (ObjUtil.equals(candidateStrategy, BpmTaskCandidateStrategyEnum.START_USER_SELECT.getStrategy())) {
processVariables = FlowableUtils.getStartUserSelectAssignees(processInstance.getProcessVariables());
if(processVariables == null){
if (processVariables == null) {
processVariables = new HashMap<>();
}
List<Long> startUserSelectAssignee = processVariables.get(nextFlowNode.getId());
// 如果当前节点已经存在审批人则不允许覆盖
// 特殊如果当前节点已经存在审批人则不允许覆盖
if (CollUtil.isNotEmpty(startUserSelectAssignee)) {
continue;
}
// 如果节点存在但未配置审批人
if (CollUtil.isEmpty(assignees)){
if (CollUtil.isEmpty(assignees)) {
throw exception(PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIG, nextFlowNode.getName());
}
// 校验通过的全部节点和审批人
processVariables.put(nextFlowNode.getId(), assignees);
variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES, processVariables);
}
// 3.6 如果节点中的审批人策略为 审批人在审批时选择下一个节点的审批人并且该节点的审批人为空
if (ObjUtil.equals(candidateStrategy, BpmTaskCandidateStrategyEnum.APPROVE_USER_SELECT.getStrategy())){
// 2.2 情况二如果节点中的审批人策略为 审批人在审批时选择下一个节点的审批人并且该节点的审批人为空
if (ObjUtil.equals(candidateStrategy, BpmTaskCandidateStrategyEnum.APPROVE_USER_SELECT.getStrategy())) {
// 如果节点存在但未配置审批人
if (CollUtil.isEmpty(assignees)) {
throw exception(PROCESS_INSTANCE_APPROVE_USER_SELECT_ASSIGNEES_NOT_CONFIG, nextFlowNode.getName());
}
// 校验通过的全部节点和审批人
processVariables.put(nextFlowNode.getId(), assignees);
// TODO @小北是不是要类似情况一的做法通过 PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES 拿一下因为如果 task1 是审批人自选task2 是审批人自选看着会覆盖
variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES, processVariables);
}
}
@ -1094,6 +1088,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
@Override
@Transactional(rollbackFor = Exception.class)
@SuppressWarnings("DataFlowIssue")
public void deleteSignTask(Long userId, BpmTaskSignDeleteReqVO reqVO) {
// 1.1 校验 task 可以被减签
Task task = validateTaskCanSignDelete(reqVO.getId());