fix:【BPM 工作流】子流程支持流程 title 自定义标题
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener;
|
||||
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
|
||||
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import jakarta.annotation.Resource;
|
||||
@@ -37,18 +38,26 @@ public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEvent
|
||||
|
||||
@Override
|
||||
protected void processCreated(FlowableEngineEntityEvent event) {
|
||||
processInstanceService.processProcessInstanceCreated((ProcessInstance)event.getEntity());
|
||||
ProcessInstance processInstance = (ProcessInstance) event.getEntity();
|
||||
FlowableUtils.execute(processInstance.getTenantId(),
|
||||
() -> processInstanceService.processProcessInstanceCreated(processInstance));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCompleted(FlowableEngineEntityEvent event) {
|
||||
processInstanceService.processProcessInstanceCompleted((ProcessInstance)event.getEntity());
|
||||
ProcessInstance processInstance = (ProcessInstance) event.getEntity();
|
||||
FlowableUtils.execute(processInstance.getTenantId(),
|
||||
() -> processInstanceService.processProcessInstanceCompleted(processInstance));
|
||||
}
|
||||
|
||||
@Override // 特殊情况:当跳转到 EndEvent 流程实例未结束, 会执行 deleteProcessInstance 方法
|
||||
@Override
|
||||
protected void processCancelled(FlowableCancelledEvent event) {
|
||||
// 特殊情况:当跳转到 EndEvent 流程实例未结束, 会执行 deleteProcessInstance 方法
|
||||
ProcessInstance processInstance = processInstanceService.getProcessInstance(event.getProcessInstanceId());
|
||||
processInstanceService.processProcessInstanceCompleted(processInstance);
|
||||
if (processInstance != null) {
|
||||
FlowableUtils.execute(processInstance.getTenantId(),
|
||||
() -> processInstanceService.processProcessInstanceCompleted(processInstance));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,10 +4,7 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.*;
|
||||
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;
|
||||
@@ -61,6 +58,8 @@ import org.flowable.task.api.history.HistoricTaskInstance;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionSynchronization;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.*;
|
||||
@@ -244,7 +243,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||
if (historicProcessInstance == null) {
|
||||
throw exception(ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS);
|
||||
}
|
||||
// 1.3 校验 BpmnModel
|
||||
// 1.3 校验BpmnModel
|
||||
BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(task.getProcessDefinitionId());
|
||||
if (bpmnModel == null) {
|
||||
return null;
|
||||
@@ -449,7 +448,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||
.setNodeType(BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType()).setStatus(processInstanceStatus)
|
||||
.setStartTime(DateUtils.of(activity.getStartTime()))
|
||||
.setEndTime(DateUtils.of(activity.getEndTime()))
|
||||
.setProcessInstanceId(activity.getCalledProcessInstanceId());
|
||||
.setProcessInstanceId(activity.getProcessInstanceId());
|
||||
approvalNodes.add(callActivity);
|
||||
}
|
||||
});
|
||||
@@ -521,7 +520,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||
activityNode.setCandidateUserIds(CollUtil.sub(candidateUserIds, index + 1, candidateUserIds.size()));
|
||||
}
|
||||
if (BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType().equals(activityNode.getNodeType())) {
|
||||
activityNode.setProcessInstanceId(firstActivity.getCalledProcessInstanceId());
|
||||
activityNode.setProcessInstanceId(firstActivity.getProcessInstanceId());
|
||||
}
|
||||
return activityNode;
|
||||
});
|
||||
@@ -771,17 +770,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||
processInstanceBuilder.predefineProcessInstanceId(processIdRedisDAO.generate(processIdRule));
|
||||
}
|
||||
// 3.2 流程名称
|
||||
BpmModelMetaInfoVO.TitleSetting titleSetting = processDefinitionInfo.getTitleSetting();
|
||||
if (titleSetting != null && Boolean.TRUE.equals(titleSetting.getEnable())) {
|
||||
AdminUserRespDTO user = adminUserApi.getUser(userId);
|
||||
Map<String, Object> cloneVariables = new HashMap<>(variables);
|
||||
cloneVariables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, user.getNickname());
|
||||
cloneVariables.put(BpmnVariableConstants.PROCESS_START_TIME, DateUtil.now());
|
||||
cloneVariables.put(BpmnVariableConstants.PROCESS_DEFINITION_NAME, definition.getName().trim());
|
||||
processInstanceBuilder.name(StrUtil.format(titleSetting.getTitle(), cloneVariables));
|
||||
} else {
|
||||
processInstanceBuilder.name(definition.getName().trim());
|
||||
}
|
||||
processInstanceBuilder.name(generateProcessInstanceName(userId, definition, processDefinitionInfo, variables));
|
||||
// 3.3 发起流程实例
|
||||
ProcessInstance instance = processInstanceBuilder.start();
|
||||
return instance.getId();
|
||||
@@ -817,6 +806,25 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||
});
|
||||
}
|
||||
|
||||
private String generateProcessInstanceName(Long userId,
|
||||
ProcessDefinition definition,
|
||||
BpmProcessDefinitionInfoDO definitionInfo,
|
||||
Map<String, Object> variables) {
|
||||
if (definition == null || definitionInfo == null) {
|
||||
return null;
|
||||
}
|
||||
BpmModelMetaInfoVO.TitleSetting titleSetting = definitionInfo.getTitleSetting();
|
||||
if (titleSetting == null || !BooleanUtil.isTrue(titleSetting.getEnable())) {
|
||||
return definition.getName();
|
||||
}
|
||||
AdminUserRespDTO user = adminUserApi.getUser(userId);
|
||||
Map<String, Object> cloneVariables = new HashMap<>(variables);
|
||||
cloneVariables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, user.getNickname());
|
||||
cloneVariables.put(BpmnVariableConstants.PROCESS_START_TIME, DateUtil.now());
|
||||
cloneVariables.put(BpmnVariableConstants.PROCESS_DEFINITION_NAME, definition.getName().trim());
|
||||
return StrUtil.format(definitionInfo.getTitleSetting().getTitle(), cloneVariables);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelProcessInstanceByStartUser(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) {
|
||||
// 1.1 校验流程实例存在
|
||||
@@ -833,7 +841,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||
.getProcessDefinitionInfo(instance.getProcessDefinitionId());
|
||||
Assert.notNull(processDefinitionInfo, "流程定义({})不存在", processDefinitionInfo);
|
||||
if (processDefinitionInfo.getAllowCancelRunningProcess() != null // 防止未配置 AllowCancelRunningProcess , 默认为可取消
|
||||
&& Boolean.FALSE.equals(processDefinitionInfo.getAllowCancelRunningProcess())) {
|
||||
&& BooleanUtil.isFalse(processDefinitionInfo.getAllowCancelRunningProcess())) {
|
||||
throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW);
|
||||
}
|
||||
// 1.4 子流程不允许取消
|
||||
@@ -900,64 +908,77 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
||||
|
||||
@Override
|
||||
public void processProcessInstanceCompleted(ProcessInstance instance) {
|
||||
// 注意:需要基于 instance 设置租户编号,避免 Flowable 内部异步时,丢失租户编号
|
||||
FlowableUtils.execute(instance.getTenantId(), () -> {
|
||||
// 1.1 获取当前状态
|
||||
Integer status = (Integer) instance.getProcessVariables()
|
||||
.get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS);
|
||||
String reason = (String) instance.getProcessVariables()
|
||||
.get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON);
|
||||
// 1.2 当流程状态还是审批状态中,说明审批通过了,则变更下它的状态
|
||||
// 为什么这么处理?因为流程完成,并且完成了,说明审批通过了
|
||||
if (Objects.equals(status, BpmProcessInstanceStatusEnum.RUNNING.getStatus())) {
|
||||
status = BpmProcessInstanceStatusEnum.APPROVE.getStatus();
|
||||
runtimeService.setVariable(instance.getId(), BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS,
|
||||
status);
|
||||
// 1.1 获取当前状态
|
||||
Integer status = (Integer) instance.getProcessVariables()
|
||||
.get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS);
|
||||
String reason = (String) instance.getProcessVariables()
|
||||
.get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON);
|
||||
// 1.2 当流程状态还是审批状态中,说明审批通过了,则变更下它的状态
|
||||
// 为什么这么处理?因为流程完成,并且完成了,说明审批通过了
|
||||
if (Objects.equals(status, BpmProcessInstanceStatusEnum.RUNNING.getStatus())) {
|
||||
status = BpmProcessInstanceStatusEnum.APPROVE.getStatus();
|
||||
runtimeService.setVariable(instance.getId(), BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS,
|
||||
status);
|
||||
}
|
||||
|
||||
// 2. 发送对应的消息通知
|
||||
if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) {
|
||||
messageService.sendMessageWhenProcessInstanceApprove(
|
||||
BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceApproveMessage(instance));
|
||||
} else if (Objects.equals(status, BpmProcessInstanceStatusEnum.REJECT.getStatus())) {
|
||||
messageService.sendMessageWhenProcessInstanceReject(
|
||||
BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceRejectMessage(instance, reason));
|
||||
}
|
||||
|
||||
// 3. 发送流程实例的状态事件
|
||||
processInstanceEventPublisher.sendProcessInstanceResultEvent(
|
||||
BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceStatusEvent(this, instance, status));
|
||||
|
||||
// 4. 流程后置通知
|
||||
if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) {
|
||||
BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.
|
||||
getProcessDefinitionInfo(instance.getProcessDefinitionId());
|
||||
if (ObjUtil.isNotNull(processDefinitionInfo) &&
|
||||
ObjUtil.isNotNull(processDefinitionInfo.getProcessAfterTriggerSetting())) {
|
||||
BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessAfterTriggerSetting();
|
||||
|
||||
BpmHttpRequestUtils.executeBpmHttpRequest(instance,
|
||||
setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse());
|
||||
}
|
||||
|
||||
// 2. 发送对应的消息通知
|
||||
if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) {
|
||||
messageService.sendMessageWhenProcessInstanceApprove(
|
||||
BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceApproveMessage(instance));
|
||||
} else if (Objects.equals(status, BpmProcessInstanceStatusEnum.REJECT.getStatus())) {
|
||||
messageService.sendMessageWhenProcessInstanceReject(
|
||||
BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceRejectMessage(instance, reason));
|
||||
}
|
||||
|
||||
// 3. 发送流程实例的状态事件
|
||||
processInstanceEventPublisher.sendProcessInstanceResultEvent(
|
||||
BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceStatusEvent(this, instance, status));
|
||||
|
||||
// 4. 流程后置通知
|
||||
if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) {
|
||||
BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.
|
||||
getProcessDefinitionInfo(instance.getProcessDefinitionId());
|
||||
if (ObjUtil.isNotNull(processDefinitionInfo) &&
|
||||
ObjUtil.isNotNull(processDefinitionInfo.getProcessAfterTriggerSetting())) {
|
||||
BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessAfterTriggerSetting();
|
||||
|
||||
BpmHttpRequestUtils.executeBpmHttpRequest(instance,
|
||||
setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processProcessInstanceCreated(ProcessInstance instance) {
|
||||
// 注意:需要基于 instance 设置租户编号,避免 Flowable 内部异步时,丢失租户编号
|
||||
FlowableUtils.execute(instance.getTenantId(), () -> {
|
||||
// 流程前置通知
|
||||
BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.
|
||||
getProcessDefinitionInfo(instance.getProcessDefinitionId());
|
||||
if (ObjUtil.isNull(processDefinitionInfo) ||
|
||||
ObjUtil.isNull(processDefinitionInfo.getProcessBeforeTriggerSetting())) {
|
||||
return;
|
||||
BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.
|
||||
getProcessDefinitionInfo(instance.getProcessDefinitionId());
|
||||
ProcessDefinition processDefinition = processDefinitionService.getProcessDefinition(instance.getProcessDefinitionId());
|
||||
if (processDefinition == null || processDefinitionInfo == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 自定义标题。目的:主要处理子流程的标题无法处理
|
||||
// 注意:必须使用 TransactionSynchronizationManager 事务提交后,否则不生效!!!
|
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
||||
|
||||
@Override
|
||||
public void afterCommit() {
|
||||
String name = generateProcessInstanceName(Long.valueOf(instance.getStartUserId()),
|
||||
processDefinition, processDefinitionInfo, instance.getProcessVariables());
|
||||
if (ObjUtil.notEqual(instance.getName(), name)) {
|
||||
runtimeService.setProcessInstanceName(instance.getProcessInstanceId(), name);
|
||||
}
|
||||
}
|
||||
BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessBeforeTriggerSetting();
|
||||
BpmHttpRequestUtils.executeBpmHttpRequest(instance,
|
||||
setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse());
|
||||
|
||||
});
|
||||
|
||||
// 流程前置通知
|
||||
if (ObjUtil.isNull(processDefinitionInfo.getProcessBeforeTriggerSetting())) {
|
||||
return;
|
||||
}
|
||||
BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessBeforeTriggerSetting();
|
||||
BpmHttpRequestUtils.executeBpmHttpRequest(instance,
|
||||
setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user