Commit 9e151b396676f82f5cd8e8ba07998a6d60f44b7c
1 parent
4e57bd15
review: 278 281行
Showing
1 changed file
with
60 additions
and
55 deletions
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
| ... | ... | @@ -149,7 +149,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 149 | 149 | } |
| 150 | 150 | |
| 151 | 151 | private Map<String, String> getFormFieldsPermission(BpmnModel bpmnModel, |
| 152 | - String activityId, String taskId) { | |
| 152 | + String activityId, String taskId) { | |
| 153 | 153 | // 1. 获取流程活动编号。流程活动 Id 为空事,从流程任务中获取流程活动 Id |
| 154 | 154 | if (StrUtil.isEmpty(activityId) && StrUtil.isNotEmpty(taskId)) { |
| 155 | 155 | activityId = Optional.ofNullable(taskService.getHistoricTask(taskId)) |
| ... | ... | @@ -232,57 +232,62 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 232 | 232 | |
| 233 | 233 | @Override |
| 234 | 234 | public List<ActivityNode> getNextFlowNodes(Long loginUserId, BpmApprovalDetailReqVO reqVO) { |
| 235 | - // 1 校验任务存在 | |
| 235 | + // 1.1 校验任务存在 | |
| 236 | 236 | Task task = taskService.getTask(reqVO.getTaskId()); |
| 237 | 237 | if (task == null) { |
| 238 | 238 | throw exception(TASK_NOT_EXISTS); |
| 239 | 239 | } |
| 240 | - // 2 校验任务是否由当前用户审批 | |
| 240 | + // 1.2 校验任务是否由当前用户审批 | |
| 241 | 241 | if (StrUtil.isNotBlank(task.getAssignee()) |
| 242 | 242 | && ObjectUtil.notEqual(loginUserId, NumberUtils.parseLong(task.getAssignee()))) { |
| 243 | 243 | throw exception(TASK_OPERATE_FAIL_ASSIGN_NOT_SELF); |
| 244 | 244 | } |
| 245 | - // 3 校验流程实例存在 | |
| 245 | + // 1.3 校验流程实例存在 | |
| 246 | 246 | ProcessInstance instance = getProcessInstance(task.getProcessInstanceId()); |
| 247 | 247 | if (instance == null) { |
| 248 | 248 | throw exception(PROCESS_INSTANCE_NOT_EXISTS); |
| 249 | 249 | } |
| 250 | - // 4 获取 BpmnModel | |
| 250 | + // 1.4 校验BpmnModel | |
| 251 | 251 | BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(task.getProcessDefinitionId()); |
| 252 | 252 | if (bpmnModel == null) { |
| 253 | 253 | return null; |
| 254 | 254 | } |
| 255 | + //1.5 流程实例是否存在 | |
| 255 | 256 | HistoricProcessInstance historicProcessInstance = getHistoricProcessInstance(task.getProcessInstanceId()); |
| 256 | 257 | if (historicProcessInstance == null) { |
| 257 | 258 | throw exception(ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS); |
| 258 | 259 | } |
| 260 | + | |
| 261 | + // 2 设置流程变量 | |
| 259 | 262 | Map<String, Object> processVariables = new HashMap<>(); |
| 260 | - // 获取历史中流程变量 | |
| 263 | + // 2.1 获取历史中流程变量 | |
| 261 | 264 | Map<String, Object> historicVariables = historicProcessInstance.getProcessVariables(); |
| 262 | 265 | if (CollUtil.isNotEmpty(historicVariables)) { |
| 263 | 266 | processVariables.putAll(historicVariables); |
| 264 | 267 | } |
| 265 | - // 合并前端传递的流程变量,以前端为准 | |
| 266 | - if (CollUtil.isNotEmpty(reqVO.getProcessVariables())){ | |
| 268 | + // 2.2 合并前端传递的流程变量,以前端为准 | |
| 269 | + if (CollUtil.isNotEmpty(reqVO.getProcessVariables())) { | |
| 267 | 270 | processVariables.putAll(reqVO.getProcessVariables()); |
| 268 | 271 | } |
| 269 | - // 获取流程定义信息 | |
| 270 | - BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService | |
| 271 | - .getProcessDefinitionInfo(task.getProcessDefinitionId()); | |
| 272 | - // 获取当前任务节点的信息 | |
| 272 | + // 3 获取当前任务节点的信息 | |
| 273 | 273 | FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey()); |
| 274 | - // 获取下一个将要执行的节点集合 | |
| 274 | + // 3.1 获取下一个将要执行的节点集合 | |
| 275 | 275 | List<FlowNode> nextFlowNodes = BpmnModelUtils.getNextFlowNodes(flowElement, bpmnModel, processVariables); |
| 276 | 276 | return convertList(nextFlowNodes, node -> { |
| 277 | 277 | List<Long> candidateUserIds = getTaskCandidateUserList(bpmnModel, node.getId(), |
| 278 | - loginUserId, processDefinitionInfo.getProcessDefinitionId(), processVariables); | |
| 279 | - //存在一个节点多人审批的情况 | |
| 280 | - List<UserSimpleBaseVO> candidateUsers = new ArrayList<>(); | |
| 281 | - for (Long candidateUserId : candidateUserIds) { | |
| 282 | - Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(candidateUserIds); | |
| 283 | - Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); | |
| 284 | - candidateUsers.add(BpmProcessInstanceConvert.INSTANCE.buildUser(candidateUserId, userMap, deptMap)); | |
| 278 | + loginUserId, historicProcessInstance.getProcessDefinitionId(), processVariables); | |
| 279 | + // 3.2 获取节点的审批人信息 | |
| 280 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(candidateUserIds); | |
| 281 | + if (CollUtil.isEmpty(userMap)) { | |
| 282 | + return null; | |
| 285 | 283 | } |
| 284 | + // 3.3 获取节点的审批人部门信息 | |
| 285 | + Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); | |
| 286 | + // 3.4 存在一个节点多人审批的情况,组装审批人信息 | |
| 287 | + List<UserSimpleBaseVO> candidateUsers = new ArrayList<>(); | |
| 288 | + userMap.forEach((key, value) -> { | |
| 289 | + candidateUsers.add(BpmProcessInstanceConvert.INSTANCE.buildUser(key, userMap, deptMap)); | |
| 290 | + }); | |
| 286 | 291 | return new ActivityNode().setNodeType(BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()) |
| 287 | 292 | .setId(node.getId()) |
| 288 | 293 | .setName(node.getName()) |
| ... | ... | @@ -356,15 +361,15 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 356 | 361 | * 主要是,拼接审批人的用户信息、部门信息 |
| 357 | 362 | */ |
| 358 | 363 | private BpmApprovalDetailRespVO buildApprovalDetail(BpmApprovalDetailReqVO reqVO, |
| 359 | - BpmnModel bpmnModel, | |
| 360 | - ProcessDefinition processDefinition, | |
| 361 | - BpmProcessDefinitionInfoDO processDefinitionInfo, | |
| 362 | - HistoricProcessInstance processInstance, | |
| 363 | - Integer processInstanceStatus, | |
| 364 | - List<ActivityNode> endApprovalNodeInfos, | |
| 365 | - List<ActivityNode> runningApprovalNodeInfos, | |
| 366 | - List<ActivityNode> simulateApprovalNodeInfos, | |
| 367 | - BpmTaskRespVO todoTask) { | |
| 364 | + BpmnModel bpmnModel, | |
| 365 | + ProcessDefinition processDefinition, | |
| 366 | + BpmProcessDefinitionInfoDO processDefinitionInfo, | |
| 367 | + HistoricProcessInstance processInstance, | |
| 368 | + Integer processInstanceStatus, | |
| 369 | + List<ActivityNode> endApprovalNodeInfos, | |
| 370 | + List<ActivityNode> runningApprovalNodeInfos, | |
| 371 | + List<ActivityNode> simulateApprovalNodeInfos, | |
| 372 | + BpmTaskRespVO todoTask) { | |
| 368 | 373 | // 1. 获取所有需要读取用户信息的 userIds |
| 369 | 374 | List<ActivityNode> approveNodes = newArrayList( |
| 370 | 375 | asList(endApprovalNodeInfos, runningApprovalNodeInfos, simulateApprovalNodeInfos)); |
| ... | ... | @@ -386,9 +391,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 386 | 391 | * 获得【已结束】的活动节点们 |
| 387 | 392 | */ |
| 388 | 393 | private List<ActivityNode> getEndActivityNodeList(Long startUserId, BpmnModel bpmnModel, |
| 389 | - BpmProcessDefinitionInfoDO processDefinitionInfo, | |
| 390 | - HistoricProcessInstance historicProcessInstance, Integer processInstanceStatus, | |
| 391 | - List<HistoricActivityInstance> activities, List<HistoricTaskInstance> tasks) { | |
| 394 | + BpmProcessDefinitionInfoDO processDefinitionInfo, | |
| 395 | + HistoricProcessInstance historicProcessInstance, Integer processInstanceStatus, | |
| 396 | + List<HistoricActivityInstance> activities, List<HistoricTaskInstance> tasks) { | |
| 392 | 397 | // 遍历 tasks 列表,只处理已结束的 UserTask |
| 393 | 398 | // 为什么不通过 activities 呢?因为,加签场景下,它只存在于 tasks,没有 activities,导致如果遍历 activities |
| 394 | 399 | // 的话,它无法成为一个节点 |
| ... | ... | @@ -400,7 +405,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 400 | 405 | .setNodeType(START_USER_NODE_ID.equals(task.getTaskDefinitionKey()) |
| 401 | 406 | ? BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType() |
| 402 | 407 | : ObjUtil.defaultIfNull(parseNodeType(flowNode), // 目的:解决“办理节点”的识别 |
| 403 | - BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType())) | |
| 408 | + BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType())) | |
| 404 | 409 | .setStatus(FlowableUtils.getTaskStatus(task)) |
| 405 | 410 | .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode)) |
| 406 | 411 | .setStartTime(DateUtils.of(task.getCreateTime())).setEndTime(DateUtils.of(task.getEndTime())) |
| ... | ... | @@ -456,11 +461,11 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 456 | 461 | * 获得【进行中】的活动节点们 |
| 457 | 462 | */ |
| 458 | 463 | private List<ActivityNode> getRunApproveNodeList(Long startUserId, |
| 459 | - BpmnModel bpmnModel, | |
| 460 | - ProcessDefinition processDefinition, | |
| 461 | - Map<String, Object> processVariables, | |
| 462 | - List<HistoricActivityInstance> activities, | |
| 463 | - List<HistoricTaskInstance> tasks) { | |
| 464 | + BpmnModel bpmnModel, | |
| 465 | + ProcessDefinition processDefinition, | |
| 466 | + Map<String, Object> processVariables, | |
| 467 | + List<HistoricActivityInstance> activities, | |
| 468 | + List<HistoricTaskInstance> tasks) { | |
| 464 | 469 | // 构建运行中的任务、子流程,基于 activityId 分组 |
| 465 | 470 | List<HistoricActivityInstance> runActivities = filterList(activities, activity -> activity.getEndTime() == null |
| 466 | 471 | && (StrUtil.equalsAny(activity.getActivityType(), ELEMENT_TASK_USER, ELEMENT_CALL_ACTIVITY))); |
| ... | ... | @@ -521,9 +526,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 521 | 526 | * 获得【预测(未来)】的活动节点们 |
| 522 | 527 | */ |
| 523 | 528 | private List<ActivityNode> getSimulateApproveNodeList(Long startUserId, BpmnModel bpmnModel, |
| 524 | - BpmProcessDefinitionInfoDO processDefinitionInfo, | |
| 525 | - Map<String, Object> processVariables, | |
| 526 | - List<HistoricActivityInstance> activities) { | |
| 529 | + BpmProcessDefinitionInfoDO processDefinitionInfo, | |
| 530 | + Map<String, Object> processVariables, | |
| 531 | + List<HistoricActivityInstance> activities) { | |
| 527 | 532 | // TODO @芋艿:【可优化】在驳回场景下,未来的预测准确性不高。原因是,驳回后,HistoricActivityInstance |
| 528 | 533 | // 包括了历史的操作,不是只有 startEvent 到当前节点的记录 |
| 529 | 534 | Set<String> runActivityIds = convertSet(activities, HistoricActivityInstance::getActivityId); |
| ... | ... | @@ -545,8 +550,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 545 | 550 | } |
| 546 | 551 | |
| 547 | 552 | private ActivityNode buildNotRunApproveNodeForSimple(Long startUserId, BpmnModel bpmnModel, |
| 548 | - BpmProcessDefinitionInfoDO processDefinitionInfo, Map<String, Object> processVariables, | |
| 549 | - BpmSimpleModelNodeVO node, Set<String> runActivityIds) { | |
| 553 | + BpmProcessDefinitionInfoDO processDefinitionInfo, Map<String, Object> processVariables, | |
| 554 | + BpmSimpleModelNodeVO node, Set<String> runActivityIds) { | |
| 550 | 555 | // TODO @芋艿:【可优化】在驳回场景下,未来的预测准确性不高。原因是,驳回后,HistoricActivityInstance |
| 551 | 556 | // 包括了历史的操作,不是只有 startEvent 到当前节点的记录 |
| 552 | 557 | if (runActivityIds.contains(node.getId())) { |
| ... | ... | @@ -590,8 +595,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 590 | 595 | } |
| 591 | 596 | |
| 592 | 597 | private ActivityNode buildNotRunApproveNodeForBpmn(Long startUserId, BpmnModel bpmnModel, |
| 593 | - BpmProcessDefinitionInfoDO processDefinitionInfo, Map<String, Object> processVariables, | |
| 594 | - FlowElement node, Set<String> runActivityIds) { | |
| 598 | + BpmProcessDefinitionInfoDO processDefinitionInfo, Map<String, Object> processVariables, | |
| 599 | + FlowElement node, Set<String> runActivityIds) { | |
| 595 | 600 | if (runActivityIds.contains(node.getId())) { |
| 596 | 601 | return null; |
| 597 | 602 | } |
| ... | ... | @@ -622,7 +627,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 622 | 627 | } |
| 623 | 628 | |
| 624 | 629 | private List<Long> getTaskCandidateUserList(BpmnModel bpmnModel, String activityId, |
| 625 | - Long startUserId, String processDefinitionId, Map<String, Object> processVariables) { | |
| 630 | + Long startUserId, String processDefinitionId, Map<String, Object> processVariables) { | |
| 626 | 631 | Set<Long> userIds = taskCandidateInvoker.calculateUsersByActivity(bpmnModel, activityId, |
| 627 | 632 | startUserId, processDefinitionId, processVariables); |
| 628 | 633 | return new ArrayList<>(userIds); |
| ... | ... | @@ -658,11 +663,11 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 658 | 663 | Set<String> finishedTaskActivityIds = convertSet(activities, HistoricActivityInstance::getActivityId, |
| 659 | 664 | activityInstance -> activityInstance.getEndTime() != null |
| 660 | 665 | && ObjectUtil.notEqual(activityInstance.getActivityType(), |
| 661 | - BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW)); | |
| 666 | + BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW)); | |
| 662 | 667 | Set<String> finishedSequenceFlowActivityIds = convertSet(activities, HistoricActivityInstance::getActivityId, |
| 663 | 668 | activityInstance -> activityInstance.getEndTime() != null |
| 664 | 669 | && ObjectUtil.equals(activityInstance.getActivityType(), |
| 665 | - BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW)); | |
| 670 | + BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW)); | |
| 666 | 671 | // 特殊:会签情况下,会有部分已完成(审批)、部分未完成(待审批),此时需要 finishedTaskActivityIds 移除掉 |
| 667 | 672 | finishedTaskActivityIds.removeAll(unfinishedTaskActivityIds); |
| 668 | 673 | // 特殊:如果流程实例被拒绝,则需要计算是哪个活动节点。 |
| ... | ... | @@ -714,8 +719,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 714 | 719 | } |
| 715 | 720 | |
| 716 | 721 | private String createProcessInstance0(Long userId, ProcessDefinition definition, |
| 717 | - Map<String, Object> variables, String businessKey, | |
| 718 | - Map<String, List<Long>> startUserSelectAssignees) { | |
| 722 | + Map<String, Object> variables, String businessKey, | |
| 723 | + Map<String, List<Long>> startUserSelectAssignees) { | |
| 719 | 724 | // 1.1 校验流程定义 |
| 720 | 725 | if (definition == null) { |
| 721 | 726 | throw exception(PROCESS_DEFINITION_NOT_EXISTS); |
| ... | ... | @@ -744,8 +749,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 744 | 749 | variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, // 流程实例状态:审批中 |
| 745 | 750 | BpmProcessInstanceStatusEnum.RUNNING.getStatus()); |
| 746 | 751 | variables.put(BpmnVariableConstants.PROCESS_INSTANCE_SKIP_EXPRESSION_ENABLED, true); // 跳过表达式需要添加此变量为 |
| 747 | - // true,不影响没配置 | |
| 748 | - // skipExpression 的节点 | |
| 752 | + // true,不影响没配置 | |
| 753 | + // skipExpression 的节点 | |
| 749 | 754 | if (CollUtil.isNotEmpty(startUserSelectAssignees)) { |
| 750 | 755 | // 设置流程变量,发起人自选审批人 |
| 751 | 756 | variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES, |
| ... | ... | @@ -784,20 +789,20 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService |
| 784 | 789 | |
| 785 | 790 | private void validateStartUserSelectAssignees(Long userId, ProcessDefinition definition, |
| 786 | 791 | Map<String, List<Long>> startUserSelectAssignees, |
| 787 | - Map<String,Object> variables) { | |
| 792 | + Map<String, Object> variables) { | |
| 788 | 793 | // 1. 获取预测的节点信息 |
| 789 | 794 | BpmApprovalDetailRespVO detailRespVO = getApprovalDetail(userId, new BpmApprovalDetailReqVO() |
| 790 | 795 | .setProcessDefinitionId(definition.getId()) |
| 791 | 796 | .setProcessVariables(variables)); |
| 792 | 797 | List<ActivityNode> activityNodes = detailRespVO.getActivityNodes(); |
| 793 | - if (CollUtil.isEmpty(activityNodes)){ | |
| 798 | + if (CollUtil.isEmpty(activityNodes)) { | |
| 794 | 799 | return; |
| 795 | 800 | } |
| 796 | 801 | |
| 797 | 802 | // 2.1 移除掉不是发起人或者审批人自选审批人节点 |
| 798 | 803 | activityNodes.removeIf(task -> |
| 799 | 804 | ObjectUtil.notEqual(BpmTaskCandidateStrategyEnum.START_USER_SELECT.getStrategy(), task.getCandidateStrategy()) |
| 800 | - && ObjectUtil.notEqual(BpmTaskCandidateStrategyEnum.APPROVE_USER_SELECT.getStrategy(), task.getCandidateStrategy())); | |
| 805 | + && ObjectUtil.notEqual(BpmTaskCandidateStrategyEnum.APPROVE_USER_SELECT.getStrategy(), task.getCandidateStrategy())); | |
| 801 | 806 | // 2.2 流程发起时要先获取当前流程的预测走向节点,发起时只校验预测的节点发起人自选审批人的审批人和抄送人是否都配置了 |
| 802 | 807 | activityNodes.forEach(task -> { |
| 803 | 808 | List<Long> assignees = startUserSelectAssignees != null ? startUserSelectAssignees.get(task.getId()) : null; | ... | ... |