feat:添加流程审批时校验,是否为下一个流程审批的节点

This commit is contained in:
lizhixian 2025-02-26 17:45:35 +08:00
parent 37b2fd4789
commit 13c2d36eee
3 changed files with 38 additions and 8 deletions

View File

@ -57,6 +57,7 @@ public interface ErrorCodeConstants {
ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!");
ErrorCode TASK_SIGNATURE_NOT_EXISTS = new ErrorCode(1_009_005_015, "签名不能为空!");
ErrorCode TASK_REASON_REQUIRE = new ErrorCode(1_009_005_016, "审批意见不能为空!");
ErrorCode TASK_START_USER_SELECT_NODE_NOT_EXISTS = new ErrorCode(1_009_004_007, "({})不是下一个执行的流程节点!");
// ========== 动态表单模块 1-009-010-000 ==========
ErrorCode FORM_NOT_EXISTS = new ErrorCode(1_009_010_000, "动态表单不存在");

View File

@ -176,14 +176,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
// 如果流程变量不为空则用前端传递的新变量值覆盖历史的流程变量
Map<String, Object> historicVariables = historicProcessInstance.getProcessVariables();
if (null != processVariables) {
// 遍历新变量值仅更新历史变量中存在的键
for (Map.Entry<String, Object> entry : processVariables.entrySet()) {
String key = entry.getKey();
if (historicVariables.containsKey(key)) {
// 如果历史变量中存在该键则用新值覆盖
historicVariables.put(key, entry.getValue());
}
}
historicVariables.putAll(processVariables);
}
processVariables = historicVariables;
}

View File

@ -10,15 +10,19 @@ 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.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.bpm.enums.definition.*;
import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum;
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.BpmnVariableConstants;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
@ -56,6 +60,7 @@ import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@ -519,6 +524,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
// 其中variables 是存储动态表单到 local 任务级别过滤一下避免 ProcessInstance 系统级的变量被占用
if (CollUtil.isNotEmpty(reqVO.getVariables())) {
Map<String, Object> variables = FlowableUtils.filterTaskFormVariable(reqVO.getVariables());
// 校验传递的参数中是否存在不是下一个执行的节点
checkNextActivityNodes(userId, reqVO.getVariables(), task.getProcessInstanceId(), reqVO.getNextAssignees());
// 下个节点审批人如果不存在则由前端传递
if (CollUtil.isNotEmpty(reqVO.getNextAssignees())) {
// 获取实例中的全部节点数据避免后续节点的审批人被覆盖
@ -536,6 +543,35 @@ public class BpmTaskServiceImpl implements BpmTaskService {
handleParentTaskIfSign(task.getParentTaskId());
}
/**
* 校验传递的参数中是否存在不是下一个执行的节点
*
* @param loginUserId 流程发起人
* @param processInstanceId 流程实例id
* @param nextActivityNodes 下一个执行节点信息 {节点id : [审批人id,审批人id]}
*/
private void checkNextActivityNodes(Long loginUserId, Map<String, Object> variables,String processInstanceId,
Map<String, List<Long>> nextActivityNodes){
// 1查询流程预测的全部信息
BpmApprovalDetailRespVO approvalDetail = processInstanceService.getApprovalDetail(loginUserId,
new BpmApprovalDetailReqVO().setProcessVariables(variables).setProcessInstanceId(processInstanceId));
// 2获取预测节点的信息
List<BpmApprovalDetailRespVO.ActivityNode> activityNodes = approvalDetail.getActivityNodes();
if (CollUtil.isNotEmpty(activityNodes)) {
// 2.1获取节点中的审批人策略为发起人自选且状态为未执行的节点
List<BpmApprovalDetailRespVO.ActivityNode> notStartActivityNodes = activityNodes.stream().filter(node ->
BpmTaskCandidateStrategyEnum.START_USER_SELECT.getStrategy().equals(node.getCandidateStrategy())
&& BpmTaskStatusEnum.NOT_START.getStatus().equals(node.getStatus())).toList();
// 3校验传递的参数中是否存在不是下一节点的信息
for (Map.Entry<String, List<Long>> nextActivityNode : nextActivityNodes.entrySet()) {
if (notStartActivityNodes.stream().noneMatch(taskNode -> taskNode.getId().equals(nextActivityNode.getKey()))) {
log.error("[checkNextActivityNodes][ ({}) 不是下一个执行的流程节点!]", nextActivityNode.getKey());
throw exception(TASK_START_USER_SELECT_NODE_NOT_EXISTS, nextActivityNode.getKey());
}
}
}
}
/**
* 审批通过存在后加签的任务
* <p>