【代码优化】BPM:审批超时提醒的实现

This commit is contained in:
YunaiV 2024-08-16 23:28:59 +08:00
parent ae7dbd3c53
commit fe3ca8deba
17 changed files with 179 additions and 218 deletions

View File

@ -4,6 +4,7 @@ import cn.hutool.core.util.ArrayUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
// TODO @jason这个是不是可以去掉了哈
/**
* BPM 边界事件 (boundary event) 自定义类型枚举
*

View File

@ -20,6 +20,7 @@ public enum BpmUserTaskTimeoutHandlerType implements IntArrayValuable {
APPROVE(2, "自动同意"),
REJECT(3, "自动拒绝");
// TODO @jasontype 是不是更合适哈
private final Integer action;
private final String name;

View File

@ -14,7 +14,8 @@ public enum BpmMessageEnum {
PROCESS_INSTANCE_APPROVE("bpm_process_instance_approve"), // 流程任务被审批通过时发送给申请人
PROCESS_INSTANCE_REJECT("bpm_process_instance_reject"), // 流程任务被审批不通过时发送给申请人
TASK_ASSIGNED("bpm_task_assigned"); // 任务被分配时发送给审批人
TASK_ASSIGNED("bpm_task_assigned"), // 任务被分配时发送给审批人
TASK_TIMEOUT("bpm_task_timeout"); // 任务审批超时时发送给审批人
/**
* 短信模板的标识

View File

@ -96,6 +96,7 @@ public class BpmSimpleModelNodeVO {
private String returnNodeId;
}
// TODO @芋艿参数校验
@Data
@Schema(description = "审批节点超时处理策略")
public static class TimeoutHandler {
@ -103,6 +104,7 @@ public class BpmSimpleModelNodeVO {
@Schema(description = "是否开启超时处理", example = "false")
private Boolean enable;
// TODO @jasontype 是不是更合适哈
@Schema(description = "任务超时未处理的行为", example = "1")
@InEnum(BpmUserTaskTimeoutHandlerType.class)
private Integer action;
@ -112,6 +114,7 @@ public class BpmSimpleModelNodeVO {
@Schema(description = "最大提醒次数", example = "1")
private Integer maxRemindCount;
}
@Data

View File

@ -1,17 +1,27 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
import cn.iocoder.yudao.module.bpm.service.task.BpmActivityService;
import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
import com.google.common.collect.ImmutableSet;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BoundaryEvent;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
import org.flowable.engine.delegate.event.FlowableActivityCancelledEvent;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.job.api.Job;
import org.flowable.task.api.Task;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@ -28,6 +38,9 @@ import java.util.Set;
@Slf4j
public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
@Resource
@Lazy // 延迟加载避免循环依赖
private BpmModelService modelService;
@Resource
@Lazy // 解决循环依赖
private BpmTaskService taskService;
@ -40,6 +53,7 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
.add(FlowableEngineEventType.TASK_ASSIGNED)
// .add(FlowableEngineEventType.TASK_COMPLETED) // 由于审批通过时已经记录了 task status 为通过所以不需要监听了
.add(FlowableEngineEventType.ACTIVITY_CANCELLED)
.add(FlowableEngineEventType.TIMER_FIRED) // 监听审批超时
.build();
public BpmTaskEventListener() {
@ -72,4 +86,30 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
});
}
@Override
protected void timerFired(FlowableEngineEntityEvent event) {
// 1.1 只处理 BoundaryEvent 边界计时时间
String processDefinitionId = event.getProcessDefinitionId();
BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processDefinitionId);
Job entity = (Job) event.getEntity();
FlowElement element = BpmnModelUtils.getFlowElementById(bpmnModel, entity.getElementId());
if (!(element instanceof BoundaryEvent)) {
return;
}
// 1.2 判断是否为超时处理
BoundaryEvent boundaryEvent = (BoundaryEvent) element;
String boundaryEventType = BpmnModelUtils.parseBoundaryEventExtensionElement(boundaryEvent,
BpmnModelConstants.BOUNDARY_EVENT_TYPE);
BpmBoundaryEventType bpmTimerBoundaryEventType = BpmBoundaryEventType.typeOf(NumberUtils.parseInt(boundaryEventType));
if (ObjectUtil.notEqual(bpmTimerBoundaryEventType, BpmBoundaryEventType.USER_TASK_TIMEOUT)) {
return;
}
// 2. 处理超时
String timeoutAction = BpmnModelUtils.parseBoundaryEventExtensionElement(boundaryEvent,
BpmnModelConstants.USER_TASK_TIMEOUT_HANDLER_ACTION);
String taskKey = boundaryEvent.getAttachedToRefId();
taskService.processTaskTimeout(event.getProcessInstanceId(), taskKey, NumberUtils.parseInt(timeoutAction));
}
}

View File

@ -1,111 +0,0 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskApproveReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRejectReqVO;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventType;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskTimeoutHandlerType;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.mq.message.task.TodoTaskReminderMessage;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.mq.producer.task.TodoTaskReminderProducer;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
import com.google.common.collect.ImmutableSet;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BoundaryEvent;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
import org.flowable.job.api.Job;
import org.flowable.task.api.Task;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Set;
// TODO @芋艿这块需要仔细再瞅瞅
/**
* 监听定时器触发事件
*
* @author jason
*/
@Component
@Slf4j
public class BpmTimerFiredEventListener extends AbstractFlowableEngineEventListener {
@Resource
@Lazy // 延迟加载避免循环依赖
private BpmModelService bpmModelService;
@Resource
@Lazy // 延迟加载避免循环依赖
private BpmTaskService bpmTaskService;
@Resource
private TodoTaskReminderProducer todoTaskReminderProducer;
public static final Set<FlowableEngineEventType> TIME_EVENTS = ImmutableSet.<FlowableEngineEventType>builder()
.add(FlowableEngineEventType.TIMER_FIRED)
.build();
public BpmTimerFiredEventListener() {
super(TIME_EVENTS);
}
@Override
protected void timerFired(FlowableEngineEntityEvent event) {
String processDefinitionId = event.getProcessDefinitionId();
BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(processDefinitionId);
Job entity = (Job) event.getEntity();
FlowElement element = BpmnModelUtils.getFlowElementById(bpmnModel, entity.getElementId());
// 如果是定时器边界事件
if (element instanceof BoundaryEvent) {
BoundaryEvent boundaryEvent = (BoundaryEvent) element;
String boundaryEventType = BpmnModelUtils.parseBoundaryEventExtensionElement(boundaryEvent, BpmnModelConstants.BOUNDARY_EVENT_TYPE);
BpmBoundaryEventType bpmTimerBoundaryEventType = BpmBoundaryEventType.typeOf(NumberUtils.parseInt(boundaryEventType));
// 类型为用户任务超时未处理的情况
if (bpmTimerBoundaryEventType == BpmBoundaryEventType.USER_TASK_TIMEOUT) {
String timeoutAction = BpmnModelUtils.parseBoundaryEventExtensionElement(boundaryEvent, BpmnModelConstants.USER_TASK_TIMEOUT_HANDLER_ACTION);
userTaskTimeoutHandler(event.getProcessInstanceId(), boundaryEvent.getAttachedToRefId(), NumberUtils.parseInt(timeoutAction));
}
}
}
private void userTaskTimeoutHandler(String processInstanceId, String taskDefKey, Integer timeoutAction) {
BpmUserTaskTimeoutHandlerType userTaskTimeoutAction = BpmUserTaskTimeoutHandlerType.typeOf(timeoutAction);
if (userTaskTimeoutAction != null) {
// 查询超时未处理的任务 TODO 加签的情况会不会有问题 ???
List<Task> taskList = bpmTaskService.getRunningTaskListByProcessInstanceId(processInstanceId, true, taskDefKey);
taskList.forEach(task -> {
// 自动提醒
if (userTaskTimeoutAction == BpmUserTaskTimeoutHandlerType.REMINDER) {
TodoTaskReminderMessage message = new TodoTaskReminderMessage().setTenantId(Long.parseLong(task.getTenantId()))
.setUserId(Long.parseLong(task.getAssignee())).setTaskName(task.getName());
todoTaskReminderProducer.sendReminderMessage(message);
}
// 自动同意
if (userTaskTimeoutAction == BpmUserTaskTimeoutHandlerType.APPROVE) {
// TODO @芋艿 这个上下文如何清除呢 任务通过后, BpmProcessInstanceEventListener 会有回调
TenantContextHolder.setTenantId(Long.parseLong(task.getTenantId()));
TenantContextHolder.setIgnore(false);
BpmTaskApproveReqVO req = new BpmTaskApproveReqVO().setId(task.getId())
.setReason("超时系统自动同意");
bpmTaskService.approveTask(Long.parseLong(task.getAssignee()), req);
}
// 自动拒绝
if (userTaskTimeoutAction == BpmUserTaskTimeoutHandlerType.REJECT) {
// TODO @芋艿 这个上下文如何清除呢 任务拒绝后, BpmProcessInstanceEventListener 会有回调
TenantContextHolder.setTenantId(Long.parseLong(task.getTenantId()));
TenantContextHolder.setIgnore(false);
BpmTaskRejectReqVO req = new BpmTaskRejectReqVO().setId(task.getId()).setReason("超时系统自动拒绝");
bpmTaskService.rejectTask(Long.parseLong(task.getAssignee()), req);
}
});
}
}
}

View File

@ -1,42 +0,0 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.core.mq.consumer.task;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.mq.message.task.TodoTaskReminderMessage;
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* 待办任务提醒 - 站内信的消费者
*
* @author jason
*/
@Component
@Slf4j
public class SysNotifyTodoTaskReminderConsumer {
private static final String TASK_REMIND_TEMPLATE_CODE = "user_task_remind";
@Resource
private NotifyMessageSendApi notifyMessageSendApi;
@EventListener
@Async
public void onMessage(TodoTaskReminderMessage message) {
log.info("站内信消费者接收到消息 [消息内容({})] ", message);
TenantUtils.execute(message.getTenantId(), ()-> {
Map<String,Object> templateParams = MapUtil.newHashMap();
templateParams.put("name", message.getTaskName());
NotifySendSingleToUserReqDTO req = new NotifySendSingleToUserReqDTO().setUserId(message.getUserId())
.setTemplateCode(TASK_REMIND_TEMPLATE_CODE).setTemplateParams(templateParams);
notifyMessageSendApi.sendSingleMessageToAdmin(req);
});
}
}

View File

@ -1,34 +0,0 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.core.mq.message.task;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* 待办任务提醒消息
*
* @author jason
*/
@Data
public class TodoTaskReminderMessage {
/**
* 租户 Id
*/
@NotNull(message = "租户 Id 不能未空")
private Long tenantId;
/**
* 用户Id
*/
@NotNull(message = "用户 Id 不能未空")
private Long userId;
/**
* 任务名称
*/
@NotEmpty(message = "任务名称不能未空")
private String taskName;
// TODO 暂时只有站内信通知. 后面可以增加
}

View File

@ -1,27 +0,0 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.core.mq.producer.task;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.mq.message.task.TodoTaskReminderMessage;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
// TODO @jason建议直接调用 BpmMessageService 更简化一点~
/**
* 待办任务提醒 Producer
*
* @author jason
*/
@Component
@Validated
public class TodoTaskReminderProducer {
@Resource
private ApplicationContext applicationContext;
public void sendReminderMessage(@Valid TodoTaskReminderMessage message) {
applicationContext.publishEvent(message);
}
}

View File

@ -1,6 +1,8 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.core.util;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmConstants;
import org.flowable.common.engine.api.delegate.Expression;
import org.flowable.common.engine.api.variable.VariableContainer;
@ -16,6 +18,7 @@ import org.flowable.task.api.TaskInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* Flowable 相关的工具方法
@ -39,6 +42,16 @@ public class FlowableUtils {
return tenantId != null ? String.valueOf(tenantId) : ProcessEngineConfiguration.NO_TENANT_ID;
}
public static void execute(String tenantIdStr, Runnable runnable) {
if (ObjectUtil.isEmpty(tenantIdStr)
|| Objects.equals(tenantIdStr, ProcessEngineConfiguration.NO_TENANT_ID)) {
runnable.run();
} else {
Long tenantId = Long.valueOf(tenantIdStr);
TenantUtils.execute(tenantId, runnable);
}
}
// ========== Execution 相关的工具方法 ==========
/**

View File

@ -59,7 +59,6 @@ public class SimpleModelUtils {
*/
public static final String APPROVE_BY_RATIO_COMPLETE_EXPRESSION = "${ nrOfCompletedInstances/nrOfInstances >= %s}";
// TODO-DONE @jason建议方法名改成 buildBpmnModel
// TODO @yunai注释需要完善下
/**
@ -347,6 +346,13 @@ public class SimpleModelUtils {
return flowElements;
}
/**
* 添加 UserTask 用户审批的 BoundaryEvent 超时事件
*
* @param userTask 审批任务
* @param timeoutHandler 超时处理器
* @return
*/
private static BoundaryEvent buildUserTaskTimerBoundaryEvent(UserTask userTask, TimeoutHandler timeoutHandler) {
// 定时器边界事件
BoundaryEvent boundaryEvent = new BoundaryEvent();
@ -362,6 +368,7 @@ public class SimpleModelUtils {
eventDefinition.setTimeCycle(String.format("R%d/%s", timeoutHandler.getMaxRemindCount(), timeoutHandler.getTimeDuration()));
}
boundaryEvent.addEventDefinition(eventDefinition);
// 添加定时器边界事件类型
addExtensionElement(boundaryEvent, BOUNDARY_EVENT_TYPE, USER_TASK_TIMEOUT.getType().toString());
// 添加超时执行动作元素

View File

@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.bpm.service.message;
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO;
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO;
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskTimeoutReqDTO;
import jakarta.validation.Valid;
/**
@ -36,4 +36,11 @@ public interface BpmMessageService {
*/
void sendMessageWhenTaskAssigned(@Valid BpmMessageSendWhenTaskCreatedReqDTO reqDTO);
/**
* 发送任务审批超时的消息
*
* @param reqDTO 发送信息
*/
void sendMessageWhenTaskTimeout(@Valid BpmMessageSendWhenTaskTimeoutReqDTO reqDTO);
}

View File

@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.bpm.enums.message.BpmMessageEnum;
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO;
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceRejectReqDTO;
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskTimeoutReqDTO;
import cn.iocoder.yudao.module.system.api.sms.SmsSendApi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@ -61,6 +62,16 @@ public class BpmMessageServiceImpl implements BpmMessageService {
BpmMessageEnum.TASK_ASSIGNED.getSmsTemplateCode(), templateParams));
}
@Override
public void sendMessageWhenTaskTimeout(BpmMessageSendWhenTaskTimeoutReqDTO reqDTO) {
Map<String, Object> templateParams = new HashMap<>();
templateParams.put("processInstanceName", reqDTO.getProcessInstanceName());
templateParams.put("taskName", reqDTO.getTaskName());
templateParams.put("detailUrl", getProcessInstanceDetailUrl(reqDTO.getProcessInstanceId()));
smsSendApi.sendSingleSmsToAdmin(BpmMessageConvert.INSTANCE.convert(reqDTO.getAssigneeUserId(),
BpmMessageEnum.TASK_TIMEOUT.getSmsTemplateCode(), templateParams));
}
private String getProcessInstanceDetailUrl(String taskId) {
return webProperties.getAdminUi().getUrl() + "/bpm/process-instance/detail?id=" + taskId;
}

View File

@ -0,0 +1,41 @@
package cn.iocoder.yudao.module.bpm.service.message.dto;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* BPM 发送任务审批超时 Request DTO
*/
@Data
public class BpmMessageSendWhenTaskTimeoutReqDTO {
/**
* 流程实例的编号
*/
@NotEmpty(message = "流程实例的编号不能为空")
private String processInstanceId;
/**
* 流程实例的名字
*/
@NotEmpty(message = "流程实例的名字不能为空")
private String processInstanceName;
/**
* 流程任务的编号
*/
@NotEmpty(message = "流程任务的编号不能为空")
private String taskId;
/**
* 流程任务的名字
*/
@NotEmpty(message = "流程任务的名字不能为空")
private String taskName;
/**
* 审批人的用户编号
*/
@NotNull(message = "审批人的用户编号不能为空")
private Long assigneeUserId;
}

View File

@ -207,4 +207,13 @@ public interface BpmTaskService {
*/
void processTaskAssigned(Task task);
/**
* 处理 Task 审批超时事件可能会处理多个当前审批中的任务
*
* @param processInstanceId 流程示例编号
* @param taskDefineKey 任务 Key
* @param taskAction 处理类型
*/
void processTaskTimeout(String processInstanceId, String taskDefineKey, Integer taskAction);
}

View File

@ -10,6 +10,7 @@ import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
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.enums.definition.BpmUserTaskRejectHandlerType;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskTimeoutHandlerType;
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;
@ -19,6 +20,7 @@ import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskTimeoutReqDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import jakarta.annotation.Resource;
@ -925,4 +927,43 @@ public class BpmTaskServiceImpl implements BpmTaskService {
});
}
@Override
@Transactional(rollbackFor = Exception.class)
public void processTaskTimeout(String processInstanceId, String taskDefineKey, Integer taskAction) {
ProcessInstance processInstance = processInstanceService.getProcessInstance(processInstanceId);
if (processInstance == null) {
log.error("[processTaskTimeout][processInstanceId({}) 没有找到流程实例]", processInstanceId);
return;
}
List<Task> taskList = getRunningTaskListByProcessInstanceId(processInstanceId, true, taskDefineKey);
// TODO 优化未来需要考虑加签的情况
if (CollUtil.isEmpty(taskList)) {
log.error("[processTaskTimeout][processInstanceId({}) 定义Key({}) 没有找到任务]", processInstanceId, taskDefineKey);
return;
}
taskList.forEach(task -> FlowableUtils.execute(task.getTenantId(), () -> {
// 情况一自动提醒
if (Objects.equals(taskAction, BpmUserTaskTimeoutHandlerType.REMINDER.getAction())) {
messageService.sendMessageWhenTaskTimeout(new BpmMessageSendWhenTaskTimeoutReqDTO()
.setProcessInstanceId(processInstanceId).setProcessInstanceName(processInstance.getName())
.setTaskId(task.getId()).setTaskName(task.getName()).setAssigneeUserId(Long.parseLong(task.getAssignee())));
return;
}
// 情况二自动同意
if (Objects.equals(taskAction, BpmUserTaskTimeoutHandlerType.APPROVE.getAction())) {
approveTask(Long.parseLong(task.getAssignee()),
new BpmTaskApproveReqVO().setId(task.getId()).setReason("超时系统自动同意"));
return;
}
// 情况三自动拒绝
if (Objects.equals(taskAction, BpmUserTaskTimeoutHandlerType.REJECT.getAction())) {
rejectTask(Long.parseLong(task.getAssignee()),
new BpmTaskRejectReqVO().setId(task.getId()).setReason("超时系统自动拒绝"));
}
}));
}
}