| | |
| | | import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; |
| | | import cn.iocoder.yudao.module.bpm.service.definition.BpmFormService; |
| | | import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService; |
| | | import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessAutoApproveService; |
| | | import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; |
| | | import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; |
| | | import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskTimeoutReqDTO; |
| | |
| | | /** |
| | | * 流程任务实例 Service 实现类 |
| | | * |
| | | * @author 芋道源码 |
| | | * @author 超级管理员 |
| | | * @author jason |
| | | */ |
| | | @Slf4j |
| | |
| | | private BpmMessageService messageService; |
| | | @Resource |
| | | private BpmFormService formService; |
| | | @Resource |
| | | private BpmProcessAutoApproveService processAutoApproveService; |
| | | |
| | | @Resource |
| | | private AdminUserApi adminUserApi; |
| | |
| | | // 改成 moveExecutionsToSingleActivityId 好像并没有遇到 ② 提到的超时提醒失效的问题。暂时先改回 moveExecutionsToSingleActivityId |
| | | // ④ moveExecutionsToSingleActivityId 回退多实例的时候不会去删除多实例根, 应改成 moveActivityIdsToSingleActivityId |
| | | // flowable 8.0.0 修复上面相关问题, 还修复了并行分支回退的问题 https://t.zsxq.com/z4d9i。 |
| | | // ⑤ 使用 moveExecutionsToSingleActivityId 方法进行回退操作时,如果是多实例的用户任务【芋道用户任务默认为多实例】,不会删除多实例任务的根数据 ACT_RU_EXECUTION |
| | | // ⑤ 使用 moveExecutionsToSingleActivityId 方法进行回退操作时,如果是多实例的用户任务【超级管理员用户任务默认为多实例】,不会删除多实例任务的根数据 ACT_RU_EXECUTION |
| | | // 会导致有一些问题,所以使用 moveActivityIdsToSingleActivityId。 但是该方法在 flowable 6.8.1 ~ 7.1.0 的版本会有 bug 阻塞回退功能 |
| | | // 相关 issue: https://github.com/flowable/flowable-engine/issues/3944 |
| | | runtimeService.createChangeActivityStateBuilder() |
| | |
| | | FlowElement userTaskElement = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); |
| | | Integer approveType = BpmnModelUtils.parseApproveType(userTaskElement); |
| | | Integer assignEmptyHandlerType = BpmnModelUtils.parseAssignEmptyHandlerType(userTaskElement); |
| | | // 流程级【免审批】开关:仅对【人工审核】节点生效。 |
| | | // 非人工审核的节点(AUTO_APPROVE / AUTO_REJECT)有其自身的设计器配置,不受本开关影响,避免两处配置互相干扰。 |
| | | boolean autoApproveEnabled = ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.USER.getType()) |
| | | && processAutoApproveService.isAutoApprove(processInstance.getProcessDefinitionKey()); |
| | | TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { |
| | | |
| | | /** |
| | |
| | | && getTask(task.getId()) == null) { |
| | | return; |
| | | } |
| | | // 特殊情况零:流程开启了【免审批】开关,人工审核节点直接自动通过 |
| | | // 说明:不改动业务侧任何逻辑——业务照常把单据置为「审批中」,随后走与正常审批通过 |
| | | // 完全相同的 approveTask 流程,因此业务监听器、审批留痕、以及下游动作 |
| | | // (生成采购订单 / MPS / 供应商档案 / 报工产出等)全部照常执行。 |
| | | if (autoApproveEnabled) { |
| | | // 幂等保护:任务可能已被推进(例如「发起人节点」由引擎自带的策略先行自动通过), |
| | | // 此时任务已不存在,直接跳过,避免重复审批报错 |
| | | Task autoApproveTask = getTask(task.getId()); |
| | | if (autoApproveTask == null) { |
| | | return; |
| | | } |
| | | // 必须传入任务的实际审批人:approveTask 会校验「操作人必须是该任务的审批人」, |
| | | // 传 null 仅对「审批人为空」的任务放行,否则会抛「该任务的审批人不是你」 |
| | | Long assigneeUserId = StrUtil.isNotBlank(autoApproveTask.getAssignee()) |
| | | ? NumberUtils.parseLong(autoApproveTask.getAssignee()) : null; |
| | | getSelf().approveTask(assigneeUserId, new BpmTaskApproveReqVO() |
| | | .setId(autoApproveTask.getId()) |
| | | .setReason(BpmReasonEnum.PROCESS_AUTO_APPROVE.getReason())); |
| | | return; |
| | | } |
| | | // 特殊情况一:【人工审核】审批人为空,根据配置是否要自动通过、自动拒绝 |
| | | if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.USER.getType())) { |
| | | // 如果有审批人、或者拥有人,则说明不满足情况一,不自动通过、不自动拒绝 |