Commit 13c2d36eeea6455d65c4b1262fccfdf816e0558c
1 parent
37b2fd47
feat:添加流程审批时校验,是否为下一个流程审批的节点
Showing
3 changed files
with
38 additions
and
8 deletions
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java
| @@ -57,6 +57,7 @@ public interface ErrorCodeConstants { | @@ -57,6 +57,7 @@ public interface ErrorCodeConstants { | ||
| 57 | ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!"); | 57 | ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!"); |
| 58 | ErrorCode TASK_SIGNATURE_NOT_EXISTS = new ErrorCode(1_009_005_015, "签名不能为空!"); | 58 | ErrorCode TASK_SIGNATURE_NOT_EXISTS = new ErrorCode(1_009_005_015, "签名不能为空!"); |
| 59 | ErrorCode TASK_REASON_REQUIRE = new ErrorCode(1_009_005_016, "审批意见不能为空!"); | 59 | ErrorCode TASK_REASON_REQUIRE = new ErrorCode(1_009_005_016, "审批意见不能为空!"); |
| 60 | + ErrorCode TASK_START_USER_SELECT_NODE_NOT_EXISTS = new ErrorCode(1_009_004_007, "({})不是下一个执行的流程节点!"); | ||
| 60 | 61 | ||
| 61 | // ========== 动态表单模块 1-009-010-000 ========== | 62 | // ========== 动态表单模块 1-009-010-000 ========== |
| 62 | ErrorCode FORM_NOT_EXISTS = new ErrorCode(1_009_010_000, "动态表单不存在"); | 63 | ErrorCode FORM_NOT_EXISTS = new ErrorCode(1_009_010_000, "动态表单不存在"); |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
| @@ -176,14 +176,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -176,14 +176,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 176 | // 如果流程变量不为空,则用前端传递的新变量值覆盖历史的流程变量 | 176 | // 如果流程变量不为空,则用前端传递的新变量值覆盖历史的流程变量 |
| 177 | Map<String, Object> historicVariables = historicProcessInstance.getProcessVariables(); | 177 | Map<String, Object> historicVariables = historicProcessInstance.getProcessVariables(); |
| 178 | if (null != processVariables) { | 178 | if (null != processVariables) { |
| 179 | - // 遍历新变量值,仅更新历史变量中存在的键 | ||
| 180 | - for (Map.Entry<String, Object> entry : processVariables.entrySet()) { | ||
| 181 | - String key = entry.getKey(); | ||
| 182 | - if (historicVariables.containsKey(key)) { | ||
| 183 | - // 如果历史变量中存在该键,则用新值覆盖 | ||
| 184 | - historicVariables.put(key, entry.getValue()); | ||
| 185 | - } | ||
| 186 | - } | 179 | + historicVariables.putAll(processVariables); |
| 187 | } | 180 | } |
| 188 | processVariables = historicVariables; | 181 | processVariables = historicVariables; |
| 189 | } | 182 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
| @@ -10,15 +10,19 @@ import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | @@ -10,15 +10,19 @@ import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | ||
| 10 | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; | 10 | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; |
| 11 | import cn.iocoder.yudao.framework.common.util.object.PageUtils; | 11 | import cn.iocoder.yudao.framework.common.util.object.PageUtils; |
| 12 | import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; | 12 | import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; |
| 13 | +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailReqVO; | ||
| 14 | +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO; | ||
| 13 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; | 15 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; |
| 14 | import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; | 16 | import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; |
| 15 | import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; | 17 | import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; |
| 16 | import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO; | 18 | import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO; |
| 19 | +import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants; | ||
| 17 | import cn.iocoder.yudao.module.bpm.enums.definition.*; | 20 | import cn.iocoder.yudao.module.bpm.enums.definition.*; |
| 18 | import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum; | 21 | import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum; |
| 19 | import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum; | 22 | import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum; |
| 20 | import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskSignTypeEnum; | 23 | import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskSignTypeEnum; |
| 21 | import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum; | 24 | import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum; |
| 25 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum; | ||
| 22 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants; | 26 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants; |
| 23 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; | 27 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; |
| 24 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; | 28 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; |
| @@ -56,6 +60,7 @@ import org.springframework.transaction.support.TransactionSynchronization; | @@ -56,6 +60,7 @@ import org.springframework.transaction.support.TransactionSynchronization; | ||
| 56 | import org.springframework.transaction.support.TransactionSynchronizationManager; | 60 | import org.springframework.transaction.support.TransactionSynchronizationManager; |
| 57 | 61 | ||
| 58 | import java.util.*; | 62 | import java.util.*; |
| 63 | +import java.util.stream.Collectors; | ||
| 59 | import java.util.stream.Stream; | 64 | import java.util.stream.Stream; |
| 60 | 65 | ||
| 61 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 66 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| @@ -519,6 +524,8 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -519,6 +524,8 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 519 | // 其中,variables 是存储动态表单到 local 任务级别。过滤一下,避免 ProcessInstance 系统级的变量被占用 | 524 | // 其中,variables 是存储动态表单到 local 任务级别。过滤一下,避免 ProcessInstance 系统级的变量被占用 |
| 520 | if (CollUtil.isNotEmpty(reqVO.getVariables())) { | 525 | if (CollUtil.isNotEmpty(reqVO.getVariables())) { |
| 521 | Map<String, Object> variables = FlowableUtils.filterTaskFormVariable(reqVO.getVariables()); | 526 | Map<String, Object> variables = FlowableUtils.filterTaskFormVariable(reqVO.getVariables()); |
| 527 | + // 校验传递的参数中是否存在不是下一个执行的节点 | ||
| 528 | + checkNextActivityNodes(userId, reqVO.getVariables(), task.getProcessInstanceId(), reqVO.getNextAssignees()); | ||
| 522 | // 下个节点审批人如果不存在,则由前端传递 | 529 | // 下个节点审批人如果不存在,则由前端传递 |
| 523 | if (CollUtil.isNotEmpty(reqVO.getNextAssignees())) { | 530 | if (CollUtil.isNotEmpty(reqVO.getNextAssignees())) { |
| 524 | // 获取实例中的全部节点数据,避免后续节点的审批人被覆盖 | 531 | // 获取实例中的全部节点数据,避免后续节点的审批人被覆盖 |
| @@ -537,6 +544,35 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -537,6 +544,35 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 537 | } | 544 | } |
| 538 | 545 | ||
| 539 | /** | 546 | /** |
| 547 | + * 校验传递的参数中是否存在不是下一个执行的节点 | ||
| 548 | + * | ||
| 549 | + * @param loginUserId 流程发起人 | ||
| 550 | + * @param processInstanceId 流程实例id | ||
| 551 | + * @param nextActivityNodes 下一个执行节点信息 {节点id : [审批人id,审批人id]} | ||
| 552 | + */ | ||
| 553 | + private void checkNextActivityNodes(Long loginUserId, Map<String, Object> variables,String processInstanceId, | ||
| 554 | + Map<String, List<Long>> nextActivityNodes){ | ||
| 555 | + // 1、查询流程【预测】的全部信息 | ||
| 556 | + BpmApprovalDetailRespVO approvalDetail = processInstanceService.getApprovalDetail(loginUserId, | ||
| 557 | + new BpmApprovalDetailReqVO().setProcessVariables(variables).setProcessInstanceId(processInstanceId)); | ||
| 558 | + // 2、获取预测节点的信息 | ||
| 559 | + List<BpmApprovalDetailRespVO.ActivityNode> activityNodes = approvalDetail.getActivityNodes(); | ||
| 560 | + if (CollUtil.isNotEmpty(activityNodes)) { | ||
| 561 | + // 2.1、获取节点中的审批人策略为【发起人自选】且状态为【未执行】的节点 | ||
| 562 | + List<BpmApprovalDetailRespVO.ActivityNode> notStartActivityNodes = activityNodes.stream().filter(node -> | ||
| 563 | + BpmTaskCandidateStrategyEnum.START_USER_SELECT.getStrategy().equals(node.getCandidateStrategy()) | ||
| 564 | + && BpmTaskStatusEnum.NOT_START.getStatus().equals(node.getStatus())).toList(); | ||
| 565 | + // 3、校验传递的参数中是否存在不是下一节点的信息 | ||
| 566 | + for (Map.Entry<String, List<Long>> nextActivityNode : nextActivityNodes.entrySet()) { | ||
| 567 | + if (notStartActivityNodes.stream().noneMatch(taskNode -> taskNode.getId().equals(nextActivityNode.getKey()))) { | ||
| 568 | + log.error("[checkNextActivityNodes][ ({}) 不是下一个执行的流程节点!]", nextActivityNode.getKey()); | ||
| 569 | + throw exception(TASK_START_USER_SELECT_NODE_NOT_EXISTS, nextActivityNode.getKey()); | ||
| 570 | + } | ||
| 571 | + } | ||
| 572 | + } | ||
| 573 | + } | ||
| 574 | + | ||
| 575 | + /** | ||
| 540 | * 审批通过存在“后加签”的任务。 | 576 | * 审批通过存在“后加签”的任务。 |
| 541 | * <p> | 577 | * <p> |
| 542 | * 注意:该任务不能马上完成,需要一个中间状态(APPROVING),并激活剩余所有子任务(PROCESS)为可审批处理 | 578 | * 注意:该任务不能马上完成,需要一个中间状态(APPROVING),并激活剩余所有子任务(PROCESS)为可审批处理 |