mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-22 15:21:53 +08:00
【功能重构】工作流:重构流程不通过、取消的处理逻辑,完全转向 flowable 的 moveActivityIdsToSingleActivityId API
This commit is contained in:
parent
521cc3deb4
commit
32804d3e0b
@ -5,13 +5,13 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 流程实例/任务的删除原因枚举
|
||||
* 流程实例/任务的的处理原因枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum BpmDeleteReasonEnum {
|
||||
public enum BpmReasonEnum {
|
||||
|
||||
// ========== 流程实例的独有原因 ==========
|
||||
|
||||
@ -36,10 +36,4 @@ public enum BpmDeleteReasonEnum {
|
||||
return StrUtil.format(reason, args);
|
||||
}
|
||||
|
||||
// ========== 逻辑 ==========
|
||||
|
||||
public static boolean isRejectReason(String reason) {
|
||||
return StrUtil.startWith(reason, "审批不通过任务,原因:");
|
||||
}
|
||||
|
||||
}
|
@ -89,11 +89,6 @@ public interface BpmProcessInstanceConvert {
|
||||
@Mapping(source = "from.id", target = "to.id", ignore = true)
|
||||
void copyTo(BpmProcessDefinitionInfoDO from, @MappingTarget BpmProcessDefinitionRespVO to);
|
||||
|
||||
default BpmProcessInstanceStatusEvent buildProcessInstanceStatusEvent(Object source, HistoricProcessInstance instance, Integer status) {
|
||||
return new BpmProcessInstanceStatusEvent(source).setId(instance.getId()).setStatus(status)
|
||||
.setProcessDefinitionKey(instance.getProcessDefinitionKey()).setBusinessKey(instance.getBusinessKey());
|
||||
}
|
||||
|
||||
default BpmProcessInstanceStatusEvent buildProcessInstanceStatusEvent(Object source, ProcessInstance instance, Integer status) {;
|
||||
return new BpmProcessInstanceStatusEvent(source).setId(instance.getId()).setStatus(status)
|
||||
.setProcessDefinitionKey(instance.getProcessDefinitionKey()).setBusinessKey(instance.getBusinessKey());
|
||||
|
@ -15,6 +15,14 @@ public class BpmConstants {
|
||||
* @see ProcessInstance#getProcessVariables()
|
||||
*/
|
||||
public static final String PROCESS_INSTANCE_VARIABLE_STATUS = "PROCESS_STATUS";
|
||||
/**
|
||||
* 流程实例的变量 - 理由
|
||||
*
|
||||
* 例如说:审批不通过的理由(目前审核通过暂时不会记录)
|
||||
*
|
||||
* @see ProcessInstance#getProcessVariables()
|
||||
*/
|
||||
public static final String PROCESS_INSTANCE_VARIABLE_REASON = "PROCESS_REASON";
|
||||
/**
|
||||
* 流程实例的变量 - 发起用户选择的审批人 Map
|
||||
*
|
||||
|
@ -6,7 +6,6 @@ import jakarta.annotation.Resource;
|
||||
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.FlowableCancelledEvent;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -21,24 +20,18 @@ import java.util.Set;
|
||||
@Component
|
||||
public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEventListener {
|
||||
|
||||
@Resource
|
||||
@Lazy
|
||||
private BpmProcessInstanceService processInstanceService;
|
||||
|
||||
public static final Set<FlowableEngineEventType> PROCESS_INSTANCE_EVENTS = ImmutableSet.<FlowableEngineEventType>builder()
|
||||
.add(FlowableEngineEventType.PROCESS_CANCELLED)
|
||||
.add(FlowableEngineEventType.PROCESS_COMPLETED)
|
||||
.build();
|
||||
|
||||
@Resource
|
||||
@Lazy // 延迟加载,避免循环依赖
|
||||
private BpmProcessInstanceService processInstanceService;
|
||||
|
||||
public BpmProcessInstanceEventListener(){
|
||||
super(PROCESS_INSTANCE_EVENTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCancelled(FlowableCancelledEvent event) {
|
||||
processInstanceService.updateProcessInstanceWhenCancel(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCompleted(FlowableEngineEntityEvent event) {
|
||||
processInstanceService.updateProcessInstanceWhenCompleted((ProcessInstance)event.getEntity());
|
||||
|
@ -6,11 +6,9 @@ import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessI
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstancePageReqVO;
|
||||
import jakarta.validation.Valid;
|
||||
import org.flowable.engine.delegate.event.FlowableCancelledEvent;
|
||||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -120,32 +118,16 @@ public interface BpmProcessInstanceService {
|
||||
*/
|
||||
void cancelProcessInstanceByAdmin(Long userId, BpmProcessInstanceCancelReqVO cancelReqVO);
|
||||
|
||||
/**
|
||||
* 更新 ProcessInstance 拓展记录为取消
|
||||
*
|
||||
* @param event 流程取消事件
|
||||
*/
|
||||
void updateProcessInstanceWhenCancel(FlowableCancelledEvent event);
|
||||
|
||||
/**
|
||||
* 更新 ProcessInstance 为完成
|
||||
*
|
||||
* @param instance 流程任务
|
||||
*/
|
||||
void updateProcessInstanceWhenApprove(ProcessInstance instance);
|
||||
|
||||
/**
|
||||
* 更新 ProcessInstance 为不通过
|
||||
*
|
||||
* @param processInstance 流程实例
|
||||
* @param activityIds 当前未完成活动节点 Id
|
||||
* @param endId 结束节点 Id
|
||||
* @param reason 理由。例如说,审批不通过时,需要传递该值
|
||||
*/
|
||||
void updateProcessInstanceReject(ProcessInstance processInstance, Collection<String> activityIds, String endId, String reason);
|
||||
void updateProcessInstanceReject(ProcessInstance processInstance, String reason);
|
||||
|
||||
/**
|
||||
* 当流程结束时候,更新 ProcessInstance 为通过
|
||||
* 处理 ProcessInstance 完成(审批通过、不通过、取消)
|
||||
*
|
||||
* @param instance 流程任务
|
||||
*/
|
||||
|
File diff suppressed because one or more lines are too long
@ -90,8 +90,6 @@ public interface BpmTaskService {
|
||||
*/
|
||||
void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 将流程任务分配给指定用户
|
||||
*
|
||||
@ -100,6 +98,13 @@ public interface BpmTaskService {
|
||||
*/
|
||||
void transferTask(Long userId, BpmTaskTransferReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 将指定流程实例的、进行中的流程任务,移动到结束节点
|
||||
*
|
||||
* @param processInstanceId 流程编号
|
||||
*/
|
||||
void moveTaskToEnd(String processInstanceId);
|
||||
|
||||
/**
|
||||
* 更新 Task 状态,在创建时
|
||||
*
|
||||
|
@ -11,7 +11,7 @@ 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.task.BpmCommentTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmDeleteReasonEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskSignTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmConstants;
|
||||
@ -327,15 +327,12 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||
throw exception(PROCESS_INSTANCE_NOT_EXISTS);
|
||||
}
|
||||
|
||||
// 2. 处理当前任务
|
||||
// 2.1 更新流程任务为不通过
|
||||
updateTaskStatusAndReason(task.getId(), BpmTaskStatusEnum.REJECT.getStatus(), reqVO.getReason());
|
||||
// 2.2 添加评论
|
||||
// 2.2 添加流程评论
|
||||
taskService.addComment(task.getId(), task.getProcessInstanceId(), BpmCommentTypeEnum.REJECT.getType(),
|
||||
BpmCommentTypeEnum.REJECT.formatComment(reqVO.getReason()));
|
||||
|
||||
// 3. 处理其他进行中的任务
|
||||
// 3.1 如果当前任务时被加签的,则加它的根任务也标记成未通过
|
||||
// 2.3 如果当前任务时被加签的,则加它的根任务也标记成未通过
|
||||
// 疑问:为什么要标记未通过呢?
|
||||
// 回答:例如说 A 任务被向前加签除 B 任务时,B 任务被审批不通过,此时 A 会被取消。而 yudao-ui-admin-vue3 不展示“已取消”的任务,导致展示不出审批不通过的细节。
|
||||
if (task.getParentTaskId() != null) {
|
||||
@ -345,41 +342,22 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||
taskService.addComment(rootParentId, task.getProcessInstanceId(), BpmCommentTypeEnum.REJECT.getType(),
|
||||
BpmCommentTypeEnum.REJECT.formatComment("加签任务不通过"));
|
||||
}
|
||||
// 3.2 其它未结束的任务,直接取消
|
||||
// 疑问:为什么不通过 updateTaskStatusWhenCanceled 监听取消,而是直接提前调用呢?
|
||||
// 回答:详细见 updateTaskStatusWhenCanceled 的方法,加签的场景
|
||||
List<Task> taskList = getRunningTaskListByProcessInstanceId(instance.getProcessInstanceId(), null, null, null);
|
||||
taskList.forEach(otherTask -> {
|
||||
if (!otherTask.getId().equals(task.getId())) { // 不需要处理当前任务
|
||||
return;
|
||||
}
|
||||
Integer otherTaskStatus = (Integer) task.getTaskLocalVariables().get(BpmConstants.TASK_VARIABLE_STATUS);
|
||||
if (BpmTaskStatusEnum.isEndStatus(otherTaskStatus)) {
|
||||
return;
|
||||
}
|
||||
updateTaskStatusWhenCanceled(otherTask.getId());
|
||||
});
|
||||
taskList.stream().filter(otherTask -> !otherTask.getId().equals(task.getId())) // 需要排除当前任务
|
||||
.forEach(otherTask -> updateTaskStatusWhenCanceled(otherTask.getId()));
|
||||
|
||||
// 4.1 驳回到指定的任务节点
|
||||
// 3. 根据不同的 RejectHandler 处理策略
|
||||
BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(task.getProcessDefinitionId());
|
||||
FlowElement flowElement = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
|
||||
// 3.1 情况一:驳回到指定的任务节点
|
||||
BpmUserTaskRejectHandlerType userTaskRejectHandlerType = BpmnModelUtils.parseRejectHandlerType(flowElement);
|
||||
if (userTaskRejectHandlerType == BpmUserTaskRejectHandlerType.RETURN_USER_TASK) {
|
||||
String returnTaskId = BpmnModelUtils.parseReturnTaskId(flowElement);
|
||||
Assert.notNull(returnTaskId, "回退的节点不能为空");
|
||||
BpmTaskReturnReqVO returnReq = new BpmTaskReturnReqVO().setId(task.getId()).setTargetTaskDefinitionKey(returnTaskId)
|
||||
.setReason(reqVO.getReason());
|
||||
returnTask(userId, returnReq);
|
||||
returnTask(userId, new BpmTaskReturnReqVO().setId(task.getId())
|
||||
.setTargetTaskDefinitionKey(returnTaskId).setReason(reqVO.getReason()));
|
||||
return;
|
||||
}
|
||||
|
||||
// 4.2 终止流程
|
||||
Set<String> activityIds = convertSet(taskList, Task::getTaskDefinitionKey);
|
||||
EndEvent endEvent = BpmnModelUtils.getEndEvent(bpmnModel);
|
||||
Assert.notNull(endEvent, "结束节点不能未空");
|
||||
processInstanceService.updateProcessInstanceReject(instance, activityIds, endEvent.getId(), reqVO.getReason());
|
||||
// 3.2 情况二:直接结束,审批不通过
|
||||
processInstanceService.updateProcessInstanceReject(instance, reqVO.getReason()); // 标记不通过
|
||||
moveTaskToEnd(task.getProcessInstanceId()); // 结束流程
|
||||
}
|
||||
|
||||
/**
|
||||
@ -449,7 +427,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||
log.error("[updateTaskStatusWhenCanceled][taskId({}) 处于结果({}),无需进行更新]", taskId, status);
|
||||
return;
|
||||
}
|
||||
updateTaskStatusAndReason(taskId, BpmTaskStatusEnum.CANCEL.getStatus(), BpmDeleteReasonEnum.CANCEL_BY_SYSTEM.getReason());
|
||||
updateTaskStatusAndReason(taskId, BpmTaskStatusEnum.CANCEL.getStatus(), BpmReasonEnum.CANCEL_BY_SYSTEM.getReason());
|
||||
// 补充说明:由于 Task 被删除成 HistoricTask 后,无法通过 taskService.addComment 添加理由,所以无法存储具体的取消理由
|
||||
}
|
||||
|
||||
@ -665,6 +643,35 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
||||
taskService.setAssignee(taskId, reqVO.getAssigneeUserId().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveTaskToEnd(String processInstanceId) {
|
||||
List<Task> taskList = getRunningTaskListByProcessInstanceId(processInstanceId, null, null, null);
|
||||
if (CollUtil.isEmpty(taskList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 其它未结束的任务,直接取消
|
||||
// 疑问:为什么不通过 updateTaskStatusWhenCanceled 监听取消,而是直接提前调用呢?
|
||||
// 回答:详细见 updateTaskStatusWhenCanceled 的方法,加签的场景
|
||||
taskList.forEach(task -> {
|
||||
Integer otherTaskStatus = (Integer) task.getTaskLocalVariables().get(BpmConstants.TASK_VARIABLE_STATUS);
|
||||
if (BpmTaskStatusEnum.isEndStatus(otherTaskStatus)) {
|
||||
return;
|
||||
}
|
||||
updateTaskStatusWhenCanceled(task.getId());
|
||||
});
|
||||
|
||||
// 2. 终止流程
|
||||
BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(taskList.get(0).getProcessDefinitionId());
|
||||
List<String> activityIds = CollUtil.newArrayList(convertSet(taskList, Task::getTaskDefinitionKey));
|
||||
EndEvent endEvent = BpmnModelUtils.getEndEvent(bpmnModel);
|
||||
Assert.notNull(endEvent, "结束节点不能未空");
|
||||
runtimeService.createChangeActivityStateBuilder()
|
||||
.processInstanceId(processInstanceId)
|
||||
.moveActivityIdsToSingleActivityId(activityIds, endEvent.getId())
|
||||
.changeState();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void createSignTask(Long userId, BpmTaskSignCreateReqVO reqVO) {
|
||||
|
Loading…
Reference in New Issue
Block a user