BPM:流程任务的 status 状态实现,使用 Flowable 的 variables 存储,移除 bpm_task_ext

This commit is contained in:
YunaiV 2024-03-17 10:10:42 +08:00
parent 7967a2a195
commit d40fa0f929
15 changed files with 260 additions and 298 deletions

View File

@ -55,12 +55,8 @@ public interface ErrorCodeConstants {
ErrorCode TASK_ADD_SIGN_USER_REPEAT = new ErrorCode(1_009_005_011, "任务加签失败,加签人与现有审批人[{}]重复");
ErrorCode TASK_SUB_SIGN_NO_PARENT = new ErrorCode(1_009_005_011, "任务减签失败,被减签的任务必须是通过加签生成的任务");
// ========== 流程任务分配规则 1-009-006-000 ==========
ErrorCode TASK_ASSIGN_RULE_EXISTS = new ErrorCode(1_009_006_000, "流程({}) 的任务({}) 已经存在分配规则");
ErrorCode TASK_ASSIGN_RULE_NOT_EXISTS = new ErrorCode(1_009_006_001, "流程任务分配规则不存在");
ErrorCode TASK_UPDATE_FAIL_NOT_MODEL = new ErrorCode(1_009_006_002, "只有流程模型的任务分配规则,才允许被修改");
// ========== 流程任务分配规则 1-009-006-000 TODO 芋艿这里要改下 ==========
ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!");
ErrorCode TASK_ASSIGN_SCRIPT_NOT_EXISTS = new ErrorCode(1_009_006_004, "操作失败,原因:任务分配脚本({}) 不存在");
// ========== 动态表单模块 1-009-010-000 ==========
ErrorCode FORM_NOT_EXISTS = new ErrorCode(1_009_010_000, "动态表单不存在");

View File

@ -4,9 +4,6 @@ import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.List;
/**
* 流程实例的结果
*
@ -16,38 +13,34 @@ import java.util.List;
@AllArgsConstructor
public enum BpmProcessInstanceResultEnum {
PROCESS(1, "处理"),
APPROVE(2, "通过"),
REJECT(3, "不通过"),
RUNNING(1, "审批"),
APPROVE(2, "审批通过"),
REJECT(3, "审批不通过"),
CANCEL(4, "已取消"),
// ========== 流程任务独有的状态 ==========
BACK(5, "驳回"), // 退回
DELEGATE(6, "委派"),
BACK(5, "已驳回"), // 退回
DELEGATE(6, "委派中"),
/**
* 加签源任务已经审批完成但是它使用了后加签后加签的任务未完成源任务就会是这个状态
* 相当于是 通过 APPROVE 的特殊状态
* 例如A审批 A 后加签了 B并且审批通过了任务但是 B 还未审批则当前任务状态为待后加签任务完成
* 例如A 审批A 后加签了 B并且审批通过了任务但是 B 还未审批则当前任务状态为待后加签任务完成
*/
SIGN_AFTER(7, "待后加签任务完成"),
APPROVING(7, "审批通过中"),
/**
* 加签源任务未审批但是向前加签了所以源任务状态变为待前加签任务完成
* 相当于是 处理中 PROCESS 的特殊状态
* 例如A 审批 A 前加签了 BB 还未审核
* 例如A 审批A 前加签了 BB 还未审核
*/
SIGN_BEFORE(8, "待前加签任务完成"),
/**
* 加签后加签任务被创建时的初始状态
* 相当于是 处理中 PROCESS 的特殊状态
* 因为需要源任务先完成才能到后加签的人来审批所以加了一个状态区分
*/
WAIT_BEFORE_TASK(9, "待前置任务完成");
/**
* 能被减签的状态
*/
public static final List<Integer> CAN_SUB_SIGN_STATUS_LIST = Arrays.asList(PROCESS.result, WAIT_BEFORE_TASK.result);
WAIT(0, "待审批");
// /**
// * 加签后加签任务被创建时的初始状态
// * 相当于是 处理中 PROCESS 的特殊状态
// * 因为需要源任务先完成才能到后加签的人来审批所以加了一个状态区分
// */
// WAIT_BEFORE_TASK(9, "处理中【待前置任务完成】");
/**
* 结果
@ -69,9 +62,9 @@ public enum BpmProcessInstanceResultEnum {
* @return 是否
*/
public static boolean isEndResult(Integer result) {
return ObjectUtils.equalsAny(result, APPROVE.getResult(), REJECT.getResult(),
CANCEL.getResult(), BACK.getResult(),
SIGN_AFTER.getResult());
return ObjectUtils.equalsAny(result,
APPROVE.getResult(), REJECT.getResult(), CANCEL.getResult(),
BACK.getResult(), APPROVING.getResult());
}
}

View File

@ -12,9 +12,9 @@ import lombok.Getter;
@AllArgsConstructor
public enum BpmProcessInstanceStatusEnum {
RUNNING(1, "进行"),
APPROVE(2, "通过"),
REJECT(3, "不通过"),
RUNNING(1, "审批"),
APPROVE(2, "审批通过"),
REJECT(3, "审批不通过"),
CANCEL(4, "已取消");
/**

View File

@ -17,15 +17,11 @@ public enum BpmTaskAddSignTypeEnum {
/**
* 向后加签需要后置任务全部审批完才会通过原审批人节点
*/
AFTER("after", "向后加签"),
/**
* 创建后置加签时的过度状态用于控制向后加签生成的任务状态
*/
AFTER_CHILDREN_TASK("afterChildrenTask", "向后加签生成的子任务");
AFTER("after", "向后加签");
private final String type;
private final String desc;
private final String desc; // TODO 芋艿desc
public static String formatDesc(String type) {
for (BpmTaskAddSignTypeEnum value : values()) {
@ -37,4 +33,3 @@ public enum BpmTaskAddSignTypeEnum {
}
}

View File

@ -18,8 +18,9 @@ public class BpmTaskDonePageItemRespVO extends BpmTaskTodoPageItemRespVO {
@Schema(description = "持续时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
private Long durationInMillis;
@Schema(description = "任务结果-参见 bpm_process_instance_result", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Integer result;
@Schema(description = "任务状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Integer status; // 参见 BpmProcessInstanceResultEnum 枚举
@Schema(description = "审批建议", requiredMode = Schema.RequiredMode.REQUIRED, example = "不请假了!")
private String reason;

View File

@ -6,10 +6,14 @@ import lombok.Data;
@Schema(description = "管理后台 - 减签流程任务的 Response VO")
@Data
public class BpmTaskSubSignRespVO {
@Schema(description = "审核的用户信息", requiredMode = Schema.RequiredMode.REQUIRED, example = "小李")
private BpmTaskRespVO.User assigneeUser;
@Schema(description = "任务 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "12312")
private String id;
@Schema(description = "任务名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "经理审批")
private String name;
}

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.bpm.convert.task;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
@ -8,7 +7,7 @@ import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmConstants;
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
@ -19,7 +18,10 @@ import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl;
import org.mapstruct.*;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;
import java.util.Date;
@ -62,12 +64,12 @@ public interface BpmTaskConvert {
}
default List<BpmTaskDonePageItemRespVO> convertList2(List<HistoricTaskInstance> tasks,
Map<String, BpmTaskExtDO> bpmTaskExtDOMap, Map<String, HistoricProcessInstance> historicProcessInstanceMap,
Map<String, HistoricProcessInstance> historicProcessInstanceMap,
Map<Long, AdminUserRespDTO> userMap) {
return CollectionUtils.convertList(tasks, task -> {
BpmTaskDonePageItemRespVO respVO = convert2(task);
BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId());
copyTo(taskExtDO, respVO);
respVO.setStatus((Integer) task.getTaskLocalVariables().get(BpmConstants.TASK_VARIABLE_STATUS));
// 流程实例
HistoricProcessInstance processInstance = historicProcessInstanceMap.get(task.getProcessInstanceId());
if (processInstance != null) {
AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId()));
@ -89,12 +91,12 @@ public interface BpmTaskConvert {
BpmTaskTodoPageItemRespVO.ProcessInstance convert(ProcessInstance processInstance, AdminUserRespDTO startUser);
default List<BpmTaskRespVO> convertList3(List<HistoricTaskInstance> tasks,
Map<String, BpmTaskExtDO> bpmTaskExtDOMap, HistoricProcessInstance processInstance,
HistoricProcessInstance processInstance,
Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) {
return CollectionUtils.convertList(tasks, task -> {
BpmTaskRespVO respVO = convert3(task);
BpmTaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId());
copyTo(taskExtDO, respVO);
respVO.setStatus((Integer) task.getTaskLocalVariables().get(BpmConstants.TASK_VARIABLE_STATUS));
// 流程实例
if (processInstance != null) {
AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId()));
respVO.setProcessInstance(convert(processInstance, startUser));
@ -116,9 +118,6 @@ public interface BpmTaskConvert {
BpmTaskRespVO.User convert3(AdminUserRespDTO bean);
@Mapping(target = "id", ignore = true)
void copyTo(BpmTaskExtDO from, @MappingTarget BpmTaskDonePageItemRespVO to);
@Mappings({@Mapping(source = "processInstance.id", target = "id"),
@Mapping(source = "processInstance.name", target = "name"),
@Mapping(source = "processInstance.startUserId", target = "startUserId"),
@ -127,14 +126,6 @@ public interface BpmTaskConvert {
BpmTaskTodoPageItemRespVO.ProcessInstance convert(HistoricProcessInstance processInstance,
AdminUserRespDTO startUser);
default BpmTaskExtDO convert2TaskExt(Task task) {
BpmTaskExtDO taskExtDO = new BpmTaskExtDO().setTaskId(task.getId())
.setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setName(task.getName())
.setProcessDefinitionId(task.getProcessDefinitionId()).setProcessInstanceId(task.getProcessInstanceId());
taskExtDO.setCreateTime(LocalDateTimeUtil.of(task.getCreateTime()));
return taskExtDO;
}
default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser,
Task task) {
BpmMessageSendWhenTaskCreatedReqDTO reqDTO = new BpmMessageSendWhenTaskCreatedReqDTO();
@ -161,6 +152,7 @@ public interface BpmTaskConvert {
task.setParentTaskId(parentTask.getId());
task.setProcessDefinitionId(parentTask.getProcessDefinitionId());
task.setProcessInstanceId(parentTask.getProcessInstanceId());
// task.setExecutionId(parentTask.getExecutionId()); // TODO 芋艿新加的不太确定尴尬不加时子任务不通过会失败报错加了子任务审批通过会失败报错
task.setTaskDefinitionKey(parentTask.getTaskDefinitionKey());
task.setTaskDefinitionId(parentTask.getTaskDefinitionId());
task.setPriority(parentTask.getPriority());
@ -168,15 +160,14 @@ public interface BpmTaskConvert {
return task;
}
default List<BpmTaskSubSignRespVO> convertList(List<BpmTaskExtDO> bpmTaskExtDOList,
Map<Long, AdminUserRespDTO> userMap,
Map<String, Task> idTaskMap){
default List<BpmTaskSubSignRespVO> convertList(List<Task> bpmTaskExtDOList,
Map<Long, AdminUserRespDTO> userMap){
return CollectionUtils.convertList(bpmTaskExtDOList, task -> {
BpmTaskSubSignRespVO bpmTaskSubSignRespVO = new BpmTaskSubSignRespVO()
.setId(task.getTaskId()).setName(task.getName());
.setId(task.getId()).setName(task.getName());
// 后加签任务不会直接设置 assignee ,所以不存在 assignee 的情况则去取 owner
Task sourceTask = idTaskMap.get(task.getTaskId());
String assignee = ObjectUtil.defaultIfBlank(sourceTask.getOwner(),sourceTask.getAssignee());
// Task sourceTask = idTaskMap.get(task.getTaskId());
String assignee = ObjectUtil.defaultIfBlank(task.getOwner(), task.getAssignee());
MapUtils.findAndThen(userMap,NumberUtils.parseLong(assignee),
assignUser-> bpmTaskSubSignRespVO.setAssigneeUser(convert3(assignUser)));
return bpmTaskSubSignRespVO;

View File

@ -20,6 +20,7 @@ import java.time.LocalDateTime;
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Deprecated
public class BpmTaskExtDO extends BaseDO {
/**
@ -61,6 +62,7 @@ public class BpmTaskExtDO extends BaseDO {
/**
* 审批建议
*/
@Deprecated
private String reason;
/**
* 任务的结束时间

View File

@ -1,39 +1,33 @@
package cn.iocoder.yudao.module.bpm.dal.mysql.task;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.List;
@Mapper
public interface BpmTaskExtMapper extends BaseMapperX<BpmTaskExtDO> {
default void updateByTaskId(BpmTaskExtDO entity) {
update(entity, new LambdaQueryWrapper<BpmTaskExtDO>().eq(BpmTaskExtDO::getTaskId, entity.getTaskId()));
}
// default void updateByTaskId(BpmTaskExtDO entity) {
// update(entity, new LambdaQueryWrapper<BpmTaskExtDO>().eq(BpmTaskExtDO::getTaskId, entity.getTaskId()));
// }
default List<BpmTaskExtDO> selectListByTaskIds(Collection<String> taskIds) {
return selectList(BpmTaskExtDO::getTaskId, taskIds);
}
// default List<BpmTaskExtDO> selectListByTaskIds(Collection<String> taskIds) {
// return selectList(BpmTaskExtDO::getTaskId, taskIds);
// }
// TODO @海BpmProcessInstanceResultEnum.CAN_SUB_SIGN_STATUS_LIST) 应该作为条件mapper 不要有业务
default List<BpmTaskExtDO> selectProcessListByTaskIds(Collection<String> taskIds) {
return selectList(new LambdaQueryWrapperX<BpmTaskExtDO>()
.in(BpmTaskExtDO::getTaskId, taskIds)
.in(BpmTaskExtDO::getResult, BpmProcessInstanceResultEnum.CAN_SUB_SIGN_STATUS_LIST));
}
// default List<BpmTaskExtDO> selectProcessListByTaskIds(Collection<String> taskIds) {
// return selectList(new LambdaQueryWrapperX<BpmTaskExtDO>()
// .in(BpmTaskExtDO::getTaskId, taskIds)
// .in(BpmTaskExtDO::getResult, BpmProcessInstanceResultEnum.CAN_SUB_SIGN_STATUS_LIST));
// }
default BpmTaskExtDO selectByTaskId(String taskId) {
return selectOne(BpmTaskExtDO::getTaskId, taskId);
}
// default BpmTaskExtDO selectByTaskId(String taskId) {
// return selectOne(BpmTaskExtDO::getTaskId, taskId);
// }
default void updateBatchByTaskIdList(List<String> taskIdList, BpmTaskExtDO updateObj) {
update(updateObj, new LambdaQueryWrapper<BpmTaskExtDO>().in(BpmTaskExtDO::getTaskId, taskIdList));
}
// default void updateBatchByTaskIdList(List<String> taskIdList, BpmTaskExtDO updateObj) {
// update(updateObj, new LambdaQueryWrapper<BpmTaskExtDO>().in(BpmTaskExtDO::getTaskId, taskIdList));
// }
}

View File

@ -16,4 +16,11 @@ public class BpmConstants {
*/
public static final String PROCESS_INSTANCE_VARIABLE_STATUS = "PROCESS_STATUS";
/**
* 任务的变量 - 状态
*
* @see org.flowable.task.api.Task#getTaskLocalVariables()
*/
public static final String TASK_VARIABLE_STATUS = "TASK_STATUS";
}

View File

@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
import cn.iocoder.yudao.module.bpm.service.task.BpmActivityService;
import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
import com.google.common.collect.ImmutableSet;
@ -21,7 +20,7 @@ import java.util.List;
import java.util.Set;
/**
* 监听 {@link org.flowable.task.api.Task} 的开始与完成创建与更新对应的 {@link BpmTaskExtDO} 记录
* 监听 {@link org.flowable.task.api.Task} 的开始与完成
*
* @author jason
*/

View File

@ -48,7 +48,7 @@ public class BpmOALeaveServiceImpl implements BpmOALeaveService {
// 插入 OA 请假单
long day = LocalDateTimeUtil.between(createReqVO.getStartTime(), createReqVO.getEndTime()).toDays();
BpmOALeaveDO leave = BpmOALeaveConvert.INSTANCE.convert(createReqVO).setUserId(userId).setDay(day)
.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
.setResult(BpmProcessInstanceResultEnum.RUNNING.getResult());
leaveMapper.insert(leave);
// 发起 BPM 流程

View File

@ -1,9 +1,11 @@
package cn.iocoder.yudao.module.bpm.service.task;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCancelReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCreateReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceMyPageReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO;
import jakarta.validation.Valid;
import org.flowable.engine.delegate.event.FlowableCancelledEvent;
import org.flowable.engine.history.HistoricProcessInstance;
@ -13,6 +15,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
/**
* 流程实例 Service 接口
*
@ -43,7 +47,7 @@ public interface BpmProcessInstanceService {
* @return 流程实例列表 Map
*/
default Map<String, ProcessInstance> getProcessInstanceMap(Set<String> ids) {
return CollectionUtils.convertMap(getProcessInstances(ids), ProcessInstance::getProcessInstanceId);
return convertMap(getProcessInstances(ids), ProcessInstance::getProcessInstanceId);
}
/**
@ -53,7 +57,7 @@ public interface BpmProcessInstanceService {
* @return 对应的映射关系
*/
default Map<String, String> getProcessInstanceNameMap(Set<String> ids) {
return CollectionUtils.convertMap(getProcessInstances(ids),
return convertMap(getProcessInstances(ids),
ProcessInstance::getProcessInstanceId, ProcessInstance::getName);
}
@ -80,7 +84,7 @@ public interface BpmProcessInstanceService {
* @return 历史的流程实例列表 Map
*/
default Map<String, HistoricProcessInstance> getHistoricProcessInstanceMap(Set<String> ids) {
return CollectionUtils.convertMap(getHistoricProcessInstances(ids), HistoricProcessInstance::getId);
return convertMap(getHistoricProcessInstances(ids), HistoricProcessInstance::getId);
}
/**

View File

@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.bpm.service.task;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
import jakarta.validation.Valid;
import org.flowable.task.api.Task;
@ -64,15 +63,6 @@ public interface BpmTaskService {
*/
List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId);
/**
* 通过任务 ID 集合获取任务扩展表信息集合
*
* @param taskIdList 任务 ID 集合
* @return 任务列表
*/
List<BpmTaskExtDO> getTaskListByTaskIdList(List<String> taskIdList);
/**
* 通过任务
*
@ -151,7 +141,6 @@ public interface BpmTaskService {
*/
void returnTask(Long userId, BpmTaskReturnReqVO reqVO);
/**
* 将指定任务委派给其他人处理等接收人处理后再回到原审批人手中审批
*

View File

@ -13,12 +13,11 @@ import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils;
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.dal.dataobject.task.BpmTaskExtDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper;
import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskAddSignTypeEnum;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmConstants;
import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
@ -39,7 +38,6 @@ import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskInfo;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
@ -51,7 +49,6 @@ import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Stream;
@ -115,8 +112,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
}
// 获得 ProcessInstance Map
Map<String, ProcessInstance> processInstanceMap =
processInstanceService.getProcessInstanceMap(convertSet(tasks, Task::getProcessInstanceId));
Map<String, ProcessInstance> processInstanceMap = processInstanceService.getProcessInstanceMap(
convertSet(tasks, Task::getProcessInstanceId));
// 获得 User Map
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
convertSet(processInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
@ -129,11 +126,13 @@ public class BpmTaskServiceImpl implements BpmTaskService {
public PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageVO) {
// 查询已办任务
HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery().finished() // 已完成
.includeTaskLocalVariables()
.taskAssignee(String.valueOf(userId)) // 分配给自己
.orderByHistoricTaskInstanceEndTime().desc(); // 审批时间倒序
if (StrUtil.isNotBlank(pageVO.getName())) {
taskQuery.taskNameLike("%" + pageVO.getName() + "%");
}
// TODO @芋艿传参风格统一
if (pageVO.getBeginCreateTime() != null) {
taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getBeginCreateTime()));
}
@ -146,20 +145,15 @@ public class BpmTaskServiceImpl implements BpmTaskService {
return PageResult.empty(taskQuery.count());
}
// 获得 TaskExtDO Map
List<BpmTaskExtDO> bpmTaskExtDOs =
taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
Map<String, BpmTaskExtDO> bpmTaskExtDOMap = convertMap(bpmTaskExtDOs, BpmTaskExtDO::getTaskId);
// 获得 ProcessInstance Map
Map<String, HistoricProcessInstance> historicProcessInstanceMap =
processInstanceService.getHistoricProcessInstanceMap(
convertSet(tasks, HistoricTaskInstance::getProcessInstanceId));
Map<String, HistoricProcessInstance> historicProcessInstanceMap = processInstanceService.getHistoricProcessInstanceMap(
convertSet(tasks, HistoricTaskInstance::getProcessInstanceId));
// 获得 User Map
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
convertSet(historicProcessInstanceMap.values(), instance -> Long.valueOf(instance.getStartUserId())));
// 拼接结果
return new PageResult<>(
BpmTaskConvert.INSTANCE.convertList2(tasks, bpmTaskExtDOMap, historicProcessInstanceMap, userMap),
BpmTaskConvert.INSTANCE.convertList2(tasks, historicProcessInstanceMap, userMap),
taskQuery.count());
}
@ -175,6 +169,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
public List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId) {
// 获得任务列表
List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery()
.includeTaskLocalVariables()
.processInstanceId(processInstanceId)
.orderByHistoricTaskInstanceStartTime().desc() // 创建时间倒序
.list();
@ -182,9 +177,6 @@ public class BpmTaskServiceImpl implements BpmTaskService {
return Collections.emptyList();
}
// 获得 TaskExtDO Map
List<BpmTaskExtDO> bpmTaskExtDOs = taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
Map<String, BpmTaskExtDO> bpmTaskExtDOMap = convertMap(bpmTaskExtDOs, BpmTaskExtDO::getTaskId);
// 获得 ProcessInstance Map
HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(processInstanceId);
// 获得 User Map
@ -195,15 +187,10 @@ public class BpmTaskServiceImpl implements BpmTaskService {
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
// 拼接数据
List<BpmTaskRespVO> result = BpmTaskConvert.INSTANCE.convertList3(tasks, bpmTaskExtDOMap, processInstance, userMap, deptMap);
List<BpmTaskRespVO> result = BpmTaskConvert.INSTANCE.convertList3(tasks, processInstance, userMap, deptMap);
return BpmTaskConvert.INSTANCE.convertChildrenList(result);
}
@Override
public List<BpmTaskExtDO> getTaskListByTaskIdList(List<String> taskIdList) {
return taskExtMapper.selectListByTaskIds(taskIdList);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void approveTask(Long userId, @Valid BpmTaskApproveReqVO reqVO) {
@ -230,16 +217,17 @@ public class BpmTaskServiceImpl implements BpmTaskService {
// 情况三自己审批的任务调用 complete 去完成任务
// 完成任务审批通过
updateTaskStatus(task.getId(), BpmProcessInstanceResultEnum.APPROVE.getResult());
taskService.complete(task.getId(), instance.getProcessVariables());
// 更新任务拓展表为通过
taskExtMapper.updateByTaskId(
new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.APPROVE.getResult())
.setReason(reqVO.getReason()));
// // 更新任务拓展表为通过
// taskExtMapper.updateByTaskId(
// new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.APPROVE.getResult())
// .setReason(reqVO.getReason()));
// 处理加签任务
handleParentTask(task);
// handleParentTask(task);
handleParentTaskNew(task.getParentTaskId());
}
/**
* 审批通过存在后加签的任务
* <p>
@ -250,133 +238,59 @@ public class BpmTaskServiceImpl implements BpmTaskService {
*/
private void approveAfterSignTask(Task task, BpmTaskApproveReqVO reqVO) {
// 1. 有向后加签则该任务状态临时设置为 ADD_SIGN_AFTER 状态
taskExtMapper.updateByTaskId(
new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.SIGN_AFTER.getResult())
.setReason(reqVO.getReason()).setEndTime(LocalDateTime.now()));
// taskExtMapper.updateByTaskId(
// new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.SIGN_AFTER.getResult())
// .setReason(reqVO.getReason()).setEndTime(LocalDateTime.now()));
// TODO @芋艿reqVO.reason
updateTaskStatus(task.getId(), BpmProcessInstanceResultEnum.APPROVING.getResult());
// 2. 激活子任务
List<String> childrenTaskIdList = getChildrenTaskIdList(task.getId());
for (String childrenTaskId : childrenTaskIdList) {
taskService.resolveTask(childrenTaskId);
// 更新任务扩展表中子任务为进行中
updateTaskStatus(childrenTaskId, BpmProcessInstanceResultEnum.RUNNING.getResult());
}
// 2.1 更新任务扩展表中子任务为进行中
taskExtMapper.updateBatchByTaskIdList(childrenTaskIdList,
new BpmTaskExtDO().setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()));
// taskExtMapper.updateBatchByTaskIdList(childrenTaskIdList,
// new BpmTaskExtDO().setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()));
}
/**
* 处理当前任务的父任务主要处理加签的情况
*
* @param task 当前任务
*/
private void handleParentTask(Task task) {
String parentTaskId = task.getParentTaskId();
// TODO 芋艿名字
private void handleParentTaskNew(String parentTaskId) {
if (StrUtil.isBlank(parentTaskId)) {
return;
}
// 1. 判断当前任务的父任务是否还有子任务
// 1.1 判断是否还有子任务如果没有就不处理
Long childrenTaskCount = getChildrenTaskCount(parentTaskId);
if (childrenTaskCount > 0) {
return;
}
// 2. 获取父任务
// 1.2 只处理加签的父任务
Task parentTask = validateTaskExist(parentTaskId);
// 3. 处理加签情况
String scopeType = parentTask.getScopeType();
if(!validateSignType(scopeType)){
if (!validateSignType(scopeType)){
return;
}
// 3.1 情况一处理向前加签
if (BpmTaskAddSignTypeEnum.BEFORE.getType().equals(scopeType)) {
// 3.1.1 如果是向前加签的任务则调用 resolveTask 指派父任务 owner 重新赋值给父任务的 assignee这样它就可以被审批
taskService.resolveTask(parentTaskId);
// 3.1.2 更新任务拓展表为处理中
taskExtMapper.updateByTaskId(
new BpmTaskExtDO().setTaskId(parentTask.getId()).setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()));
} else if (BpmTaskAddSignTypeEnum.AFTER.getType().equals(scopeType)) {
// 3.2 情况二处理向后加签
handleParentTaskForAfterSign(parentTask);
}
// 4. 子任务已处理完成清空 scopeType 字段修改 parentTask 信息方便后续可以继续向前后向后加签
// 再查询一次的原因是避免报错Task was updated by another transaction concurrently
// 因为前面处理后可能会导致 parentTask rev 字段被修改需要重新获取最新的
parentTask = getTask(parentTaskId);
if (parentTask == null) {
// 为空的情况是已经通过 handleAfterSign 方法将任务完成了所以 ru_task 表会查不到数据
return;
}
// 2. 子任务已处理完成清空 scopeType 字段修改 parentTask 信息方便后续可以继续向前后向后加签
clearTaskScopeTypeAndSave(parentTask);
}
/**
* 处理后加签任务
*
* @param parentTask 当前审批任务的父任务
*/
// TODO @海这个逻辑怎么感觉可以是 parentTask parent再去调用 handleParentTask 方法可以微信聊下
private void handleParentTaskForAfterSign(Task parentTask) {
String parentTaskId = parentTask.getId();
// 1. 更新 parentTask 的任务拓展表为通过并调用 complete 完成自己
BpmTaskExtDO currentTaskExt = taskExtMapper.selectByTaskId(parentTask.getId());
BpmTaskExtDO currentTaskExtUpdateObj = new BpmTaskExtDO().setTaskId(parentTask.getId())
.setResult(BpmProcessInstanceResultEnum.APPROVE.getResult());
if (currentTaskExt.getEndTime() == null) {
// 1.1 有这个判断是因为,以前没设置过结束时间才去设置
currentTaskExtUpdateObj.setEndTime(LocalDateTime.now());
}
taskExtMapper.updateByTaskId(currentTaskExtUpdateObj);
// 1.2 完成自己因为它已经没有子任务所以也可以完成
taskService.complete(parentTaskId);
// 2. 如果有父级递归查询上级任务是否都已经完成
if (StrUtil.isEmpty(parentTask.getParentTaskId())) {
return;
}
// 2.1 判断整条链路的任务是否完成
// 例如从 A 任务加签了一个 B 任务B 任务又加签了一个 C 任务C 任务加签了 D 任务
// 此时D 任务完成要一直往上找到祖先任务 A调用 complete 方法完成 A 任务
boolean allChildrenTaskFinish = true;
while (StrUtil.isNotBlank(parentTask.getParentTaskId())) {
parentTask = validateTaskExist(parentTask.getParentTaskId());
BpmTaskExtDO parentTaskExt = taskExtMapper.selectByTaskId(parentTask.getId());
if (parentTaskExt == null) {
break;
}
boolean currentTaskFinish = BpmProcessInstanceResultEnum.isEndResult(parentTaskExt.getResult());
// 2.2 如果 allChildrenTaskFinish 已经被赋值为 false则不会再赋值为 true因为整个链路没有完成
if (allChildrenTaskFinish) {
allChildrenTaskFinish = currentTaskFinish;
}
// 2.3 任务已完成则不处理
if (currentTaskFinish) {
continue;
}
// 3 处理非完成状态的任务
// 3.1 判断当前任务的父任务是否还有子任务
Long childrenTaskCount = getChildrenTaskCount(parentTaskExt.getTaskId());
if (childrenTaskCount > 0) {
continue;
}
// 3.2 没有子任务判断当前任务状态是否为 ADD_SIGN_BEFORE 待前加签任务完成
if (BpmProcessInstanceResultEnum.SIGN_BEFORE.getResult().equals(parentTaskExt.getResult())) {
// 3.3 需要修改该任务状态为处理中
taskService.resolveTask(parentTaskExt.getTaskId());
parentTaskExt.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
taskExtMapper.updateByTaskId(parentTaskExt);
}
// 3.4 清空 scopeType 字段用于任务没有子任务时使用该方法方便任务可以再次被不同的方式加签
parentTask = validateTaskExist(parentTaskExt.getTaskId());
clearTaskScopeTypeAndSave(parentTask);
// 3.1 情况一处理向向前加签
if (BpmTaskAddSignTypeEnum.BEFORE.getType().equals(scopeType)) {
// 3.1.1 owner 重新赋值给父任务的 assignee这样它就可以被审批
taskService.resolveTask(parentTaskId);
// 3.1.2 更新流程任务 status
updateTaskStatus(parentTaskId, BpmProcessInstanceResultEnum.RUNNING.getResult());
// 3.2 情况二处理向向后加签
} else if (BpmTaskAddSignTypeEnum.AFTER.getType().equals(scopeType)) {
// 3.2.1 完成自己因为它已经没有子任务所以也可以完成
updateTaskStatus(parentTaskId, BpmProcessInstanceResultEnum.APPROVE.getResult());
taskService.complete(parentTaskId);
}
// 4. 完成最后的顶级祖先任务
if (allChildrenTaskFinish) {
taskService.complete(parentTask.getId());
}
// 4. 递归处理父任务
handleParentTaskNew(parentTask.getParentTaskId());
}
/**
@ -422,9 +336,10 @@ public class BpmTaskServiceImpl implements BpmTaskService {
// 底层调用 TaskHelper.changeTaskAssignee(task, task.getOwner()) owner 设置为 assignee
taskService.resolveTask(task.getId());
// 2.2 更新任务拓展表为处理中
taskExtMapper.updateByTaskId(
new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.PROCESS.getResult())
.setReason(reqVO.getReason()));
// taskExtMapper.updateByTaskId(
// new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.RUNNING.getResult())
// .setReason(reqVO.getReason()));
updateTaskStatus(task.getId(), BpmProcessInstanceResultEnum.RUNNING.getResult());
}
@Override
@ -438,12 +353,13 @@ public class BpmTaskServiceImpl implements BpmTaskService {
}
// 更新流程实例为不通过
updateTaskStatus(task.getId(), BpmProcessInstanceResultEnum.REJECT.getResult());
processInstanceService.updateProcessInstanceExtReject(instance.getProcessInstanceId(), reqVO.getReason());
// 更新任务拓展表为不通过
taskExtMapper.updateByTaskId(
new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.REJECT.getResult())
.setEndTime(LocalDateTime.now()).setReason(reqVO.getReason()));
// // 更新任务拓展表为不通过
// taskExtMapper.updateByTaskId(
// new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.REJECT.getResult())
// .setEndTime(LocalDateTime.now()).setReason(reqVO.getReason()));
}
@Override
@ -459,6 +375,20 @@ public class BpmTaskServiceImpl implements BpmTaskService {
taskService.setAssignee(id, String.valueOf(userId));
}
/**
* 更新流程任务的 status 状态
*
* @param id 任务编号
* @param status 状态
*/
private void updateTaskStatus(String id, Integer status) {
// try {
// } catch (FlowableObjectNotFoundException exception) {
// historyService.
// }
taskService.setVariableLocal(id, BpmConstants.TASK_VARIABLE_STATUS, status);
}
/**
* 校验任务是否存在 并且是否是分配给自己的任务
*
@ -475,25 +405,56 @@ public class BpmTaskServiceImpl implements BpmTaskService {
@Override
public void createTaskExt(Task task) {
BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task)
.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
// BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task)
// .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
// // 向后加签生成的任务状态不能为进行中需要等前面父任务完成
// if (BpmTaskAddSignTypeEnum.AFTER_CHILDREN_TASK.getType().equals(task.getScopeType())) {
// taskExtDO.setResult(BpmProcessInstanceResultEnum.WAIT_BEFORE_TASK.getResult());
// }
// taskExtMapper.insert(taskExtDO);
// Integer status = (Integer) task.getTaskLocalVariables().get(BpmConstants.TASK_VARIABLE_STATUS);
// if (status != null) {
// return;
// }
//
// status = BpmProcessInstanceResultEnum.RUNNING.getResult();
// 向后加签生成的任务状态不能为进行中需要等前面父任务完成
if (BpmTaskAddSignTypeEnum.AFTER_CHILDREN_TASK.getType().equals(task.getScopeType())) {
taskExtDO.setResult(BpmProcessInstanceResultEnum.WAIT_BEFORE_TASK.getResult());
}
taskExtMapper.insert(taskExtDO);
// if (BpmTaskAddSignTypeEnum.AFTER_CHILDREN_TASK.getType().equals(task.getScopeType())) {
// status = BpmProcessInstanceResultEnum.WAIT_BEFORE_TASK.getResult();
// }
updateTaskStatus(task.getId(), BpmProcessInstanceResultEnum.RUNNING.getResult());
}
@Override
public void updateTaskExtComplete(Task task) {
BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task)
.setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()) // 不设置也问题不大因为 Complete 一般是审核通过已经设置
.setEndTime(LocalDateTime.now());
taskExtMapper.updateByTaskId(taskExtDO);
// BpmTaskExtDO taskExtDO = BpmTaskConvert.INSTANCE.convert2TaskExt(task)
// .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()) // 不设置也问题不大因为 Complete 一般是审核通过已经设置
// .setEndTime(LocalDateTime.now());
// taskExtMapper.updateByTaskId(taskExtDO);
updateTaskStatus(task.getId(), BpmProcessInstanceResultEnum.APPROVE.getResult());
}
@Override
public void updateTaskExtCancel(String taskId) {
Task task = getTask(taskId);
// 可能只是活动不是任务所以查询不到
if (task == null) {
log.error("[updateTaskExtCancel][taskId({}) 任务不存在]", taskId);
return;
}
Integer status = (Integer) task.getTaskLocalVariables().get(BpmConstants.TASK_VARIABLE_STATUS);
if (BpmProcessInstanceResultEnum.isEndResult(status)) {
log.error("[updateTaskExtCancel][taskId({}) 处于结果({}),无需进行更新]", taskId, status);
return;
}
updateTaskStatus(taskId, BpmProcessInstanceResultEnum.CANCEL.getResult());
if (true) {
return;
}
// 需要在事务提交后才进行查询不然查询不到历史的原因
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@ -505,21 +466,27 @@ public class BpmTaskServiceImpl implements BpmTaskService {
return;
}
// 如果任务拓展表已经是完成的状态则跳过
BpmTaskExtDO taskExt = taskExtMapper.selectByTaskId(taskId);
if (taskExt == null) {
log.error("[updateTaskExtCancel][taskId({}) 查找不到对应的记录,可能存在问题]", taskId);
return;
}
// 如果已经是最终的结果则跳过
if (BpmProcessInstanceResultEnum.isEndResult(taskExt.getResult())) {
log.error("[updateTaskExtCancel][taskId({}) 处于结果({}),无需进行更新]", taskId, taskExt.getResult());
// // 如果任务拓展表已经是完成的状态则跳过
// BpmTaskExtDO taskExt = taskExtMapper.selectByTaskId(taskId);
// if (taskExt == null) {
// log.error("[updateTaskExtCancel][taskId({}) 查找不到对应的记录,可能存在问题]", taskId);
// return;
// }
// // 如果已经是最终的结果则跳过
// if (BpmProcessInstanceResultEnum.isEndResult(taskExt.getResult())) {
// log.error("[updateTaskExtCancel][taskId({}) 处于结果({}),无需进行更新]", taskId, taskExt.getResult());
// return;
// }
Integer status = (Integer) task.getTaskLocalVariables().get(BpmConstants.TASK_VARIABLE_STATUS);
if (BpmProcessInstanceResultEnum.isEndResult(status)) {
log.error("[updateTaskExtCancel][taskId({}) 处于结果({}),无需进行更新]", taskId, status);
return;
}
// 更新任务
taskExtMapper.updateById(new BpmTaskExtDO().setId(taskExt.getId()).setResult(BpmProcessInstanceResultEnum.CANCEL.getResult())
.setEndTime(LocalDateTime.now()).setReason(BpmProcessInstanceDeleteReasonEnum.translateReason(task.getDeleteReason())));
// taskExtMapper.updateById(new BpmTaskExtDO().setId(taskExt.getId()).setResult(BpmProcessInstanceResultEnum.CANCEL.getResult())
// .setEndTime(LocalDateTime.now()).setReason(BpmProcessInstanceDeleteReasonEnum.translateReason(task.getDeleteReason())));
updateTaskStatus(taskId, BpmProcessInstanceResultEnum.CANCEL.getResult());
}
});
@ -527,9 +494,10 @@ public class BpmTaskServiceImpl implements BpmTaskService {
@Override
public void updateTaskExtAssign(Task task) {
BpmTaskExtDO taskExtDO =
new BpmTaskExtDO().setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setTaskId(task.getId());
taskExtMapper.updateByTaskId(taskExtDO);
// BpmTaskExtDO taskExtDO =
// new BpmTaskExtDO().setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())).setTaskId(task.getId());
// taskExtMapper.updateByTaskId(taskExtDO);
// 发送通知在事务提交时批量执行操作所以直接查询会无法查询到 ProcessInstance所以这里是通过监听事务的提交来实现
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
@ -555,11 +523,11 @@ public class BpmTaskServiceImpl implements BpmTaskService {
@Override
public Task getTask(String id) {
return taskService.createTaskQuery().taskId(id).singleResult();
return taskService.createTaskQuery().taskId(id).includeTaskLocalVariables().singleResult();
}
private HistoricTaskInstance getHistoricTask(String id) {
return historyService.createHistoricTaskInstanceQuery().taskId(id).singleResult();
return historyService.createHistoricTaskInstanceQuery().taskId(id).includeTaskLocalVariables().singleResult();
}
@Override
@ -594,13 +562,17 @@ public class BpmTaskServiceImpl implements BpmTaskService {
// 1.2 校验源头和目标节点的关系并返回目标元素
FlowElement targetElement = validateTargetTaskCanReturn(task.getTaskDefinitionKey(), reqVO.getTargetDefinitionKey(), task.getProcessDefinitionId());
// 3. 更新任务扩展表 TODO 芋艿需要提前搞
updateTaskStatus(task.getId(), BpmProcessInstanceResultEnum.BACK.getResult());
// 2. 调用 flowable 框架的回退逻辑
returnTask0(task, targetElement, reqVO);
// 3. 更新任务扩展表
taskExtMapper.updateByTaskId(new BpmTaskExtDO().setTaskId(task.getId())
.setResult(BpmProcessInstanceResultEnum.BACK.getResult())
.setEndTime(LocalDateTime.now()).setReason(reqVO.getReason()));
// updateTaskStatus(task.getId(), BpmProcessInstanceResultEnum.BACK.getResult());
// taskExtMapper.updateByTaskId(new BpmTaskExtDO().setTaskId(task.getId())
// .setResult(BpmProcessInstanceResultEnum.BACK.getResult())
// .setEndTime(LocalDateTime.now()).setReason(reqVO.getReason()));
}
/**
@ -654,6 +626,9 @@ public class BpmTaskServiceImpl implements BpmTaskService {
}
taskService.addComment(task.getId(), currentTask.getProcessInstanceId(),
BpmCommentTypeEnum.BACK.getType().toString(), reqVO.getReason());
// TODO 芋艿这里加下驳回的
updateTaskStatus(task.getId(), BpmProcessInstanceResultEnum.BACK.getResult());
});
// 3. 执行驳回
@ -688,9 +663,10 @@ public class BpmTaskServiceImpl implements BpmTaskService {
// 3.2 执行委派将任务委派给 receiveId
taskService.delegateTask(taskId, reqVO.getDelegateUserId().toString());
// 3.3 更新任务拓展表为委派
taskExtMapper.updateByTaskId(
new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.DELEGATE.getResult())
.setReason(reqVO.getReason()));
// taskExtMapper.updateByTaskId(
// new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.DELEGATE.getResult())
// .setReason(reqVO.getReason()));
updateTaskStatus(taskId, BpmProcessInstanceResultEnum.DELEGATE.getResult());
}
/**
@ -729,15 +705,20 @@ public class BpmTaskServiceImpl implements BpmTaskService {
taskEntity.setOwner(taskEntity.getAssignee());
taskEntity.setAssignee(null);
// 2.3 更新扩展表状态
taskExtMapper.updateByTaskId(
new BpmTaskExtDO().setTaskId(taskEntity.getId())
.setResult(BpmProcessInstanceResultEnum.SIGN_BEFORE.getResult())
.setReason(reqVO.getReason()));
// taskExtMapper.updateByTaskId(
// new BpmTaskExtDO().setTaskId(taskEntity.getId())
// .setResult(BpmProcessInstanceResultEnum.SIGN_BEFORE.getResult())
// .setReason(reqVO.getReason()));
// taskEntity.setTransientVariableLocal(BpmConstants.TASK_VARIABLE_STATUS, BpmProcessInstanceResultEnum.SIGN_BEFORE.getResult());
// updateTaskStatus(taskEntity.getId(), BpmProcessInstanceResultEnum.SIGN_BEFORE.getResult()); // TODO 芋艿貌似会有实物并发的问题所以不能用这个调用只能 set
}
// 2.4 记录加签方式完成任务时需要用到判断
taskEntity.setScopeType(reqVO.getType());
// 2.5 保存当前任务修改后的值
taskService.saveTask(taskEntity);
if (reqVO.getType().equals(BpmTaskAddSignTypeEnum.BEFORE.getType())) {
updateTaskStatus(taskEntity.getId(), BpmProcessInstanceResultEnum.WAIT.getResult()); // TODO 芋艿貌似只能放在这个地方不然会有并发修改的报错
}
// 3. 创建加签任务
createSignTask(convertList(reqVO.getUserIdList(), String::valueOf), taskEntity);
@ -764,12 +745,12 @@ public class BpmTaskServiceImpl implements BpmTaskService {
private TaskEntityImpl validateAddSign(Long userId, BpmTaskAddSignReqVO reqVO) {
TaskEntityImpl taskEntity = (TaskEntityImpl) validateTask(userId, reqVO.getId());
// 向前加签和向后加签不能同时存在
if (StrUtil.isNotBlank(taskEntity.getScopeType())
&& ObjectUtil.notEqual(BpmTaskAddSignTypeEnum.AFTER_CHILDREN_TASK.getType(), taskEntity.getScopeType())
if (taskEntity.getScopeType() != null
&& ObjectUtil.notEqual(taskEntity.getScopeType(), reqVO.getType())) {
throw exception(TASK_ADD_SIGN_TYPE_ERROR,
BpmTaskAddSignTypeEnum.formatDesc(taskEntity.getScopeType()), BpmTaskAddSignTypeEnum.formatDesc(reqVO.getType()));
}
// 同一个 key 的任务审批人不重复
List<Task> taskList = taskService.createTaskQuery().processInstanceId(taskEntity.getProcessInstanceId())
.taskDefinitionKey(taskEntity.getTaskDefinitionKey()).list();
@ -819,17 +800,23 @@ public class BpmTaskServiceImpl implements BpmTaskService {
// 2.2.1 设置 owner 不设置 assignee 是因为不能同时审批需要等父任务完成
task.setOwner(assignee);
// 2.2.2 设置向后加签任务的 scopeType afterChildrenTask用于设置任务扩展表的状态
task.setScopeType(BpmTaskAddSignTypeEnum.AFTER_CHILDREN_TASK.getType());
// task.setScopeType(BpmTaskAddSignTypeEnum.AFTER_CHILDREN_TASK.getType());
// task.setVariableLocal(BpmConstants.TASK_VARIABLE_STATUS, BpmProcessInstanceResultEnum.WAIT.getResult());
}
// 2. 保存子任务
taskService.saveTask(task);
// 3. TODO
if (BpmTaskAddSignTypeEnum.AFTER.getType().equals(parentTask.getScopeType())) {
updateTaskStatus(task.getId(), BpmProcessInstanceResultEnum.WAIT.getResult());
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteSignTask(Long userId, BpmTaskSubSignReqVO reqVO) {
// 1.1 校验 task 可以被减签
Task task = validateSubSign(reqVO.getId());
// Task task = validateSubSign(reqVO.getId()); // TODO 芋艿这个判断暂时有点问题在前置加签的时候
Task task = validateTaskExist(reqVO.getId());
// 1.2 校验取消人存在
AdminUserRespDTO cancelUser = null;
if (StrUtil.isNotBlank(task.getAssignee())) {
@ -846,17 +833,18 @@ public class BpmTaskServiceImpl implements BpmTaskService {
// 2.2 删除任务和所有子任务
taskService.deleteTasks(allTaskIdList);
// 2.3 修改扩展表状态为取消
AdminUserRespDTO user = adminUserApi.getUser(userId);
taskExtMapper.updateBatchByTaskIdList(allTaskIdList, new BpmTaskExtDO().setResult(BpmProcessInstanceResultEnum.CANCEL.getResult())
.setReason(StrUtil.format("由于{}操作[减签],任务被取消", user.getNickname())));
// taskExtMapper.updateBatchByTaskIdList(allTaskIdList, new BpmTaskExtDO().setResult(BpmProcessInstanceResultEnum.CANCEL.getResult())
// .setReason(StrUtil.format("由于{}操作[减签],任务被取消", user.getNickname())));
// allTaskIdList.forEach(taskId -> updateTaskStatus(taskId, BpmProcessInstanceResultEnum.CANCEL.getResult())); // TODO @芋艿交给取消考虑到理由可能不能直接给
// 3. 记录日志到父任务中先记录日志是因为通过 handleParentTask 方法之后任务可能被完成了并且不存在了会报异常所以先记录
AdminUserRespDTO user = adminUserApi.getUser(userId);
String comment = StrUtil.format(BpmCommentTypeEnum.SUB_SIGN.getComment(), user.getNickname(), cancelUser.getNickname());
taskService.addComment(task.getParentTaskId(), task.getProcessInstanceId(),
BpmCommentTypeEnum.SUB_SIGN.getType().toString(), comment);
// 4. 处理当前任务的父任务
handleParentTask(task);
handleParentTaskNew(task.getParentTaskId());
}
/**
@ -954,17 +942,16 @@ public class BpmTaskServiceImpl implements BpmTaskService {
if (CollUtil.isEmpty(taskList)) {
return Collections.emptyList();
}
List<String> childrenTaskIdList = convertList(taskList, Task::getId);
// 2.1 owner assignee 统一到一个集合中
List<Long> userIds = convertListByFlatMap(taskList, control ->
Stream.of(NumberUtils.parseLong(control.getAssignee()), NumberUtils.parseLong(control.getOwner()))
.filter(Objects::nonNull));
.filter(Objects::nonNull)); // TODO 芋艿这里可能可以优化下
// 2.2 组装数据
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
List<BpmTaskExtDO> taskExtList = taskExtMapper.selectProcessListByTaskIds(childrenTaskIdList);
Map<String, Task> idTaskMap = convertMap(taskList, TaskInfo::getId);
return BpmTaskConvert.INSTANCE.convertList(taskExtList, userMap, idTaskMap);
// List<BpmTaskExtDO> taskExtList = taskExtMapper.selectProcessListByTaskIds(childrenTaskIdList);
// Map<String, Task> idTaskMap = convertMap(taskList, TaskInfo::getId);
return BpmTaskConvert.INSTANCE.convertList(taskList, userMap);
}
@Override