mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2025-01-18 19:20:05 +08:00
BPM:增加「发起人自选」的任务审批人的分配策略
This commit is contained in:
parent
acea73c991
commit
528a321f0a
@ -32,14 +32,13 @@ public class BpmProcessInstanceCreateReqDTO {
|
||||
@NotEmpty(message = "业务的唯一标识")
|
||||
private String businessKey;
|
||||
|
||||
// TODO @hai:assignees 复数
|
||||
/**
|
||||
* 提前指派的审批人
|
||||
* 发起人自选审批人 Map
|
||||
*
|
||||
* key:taskKey 任务编码
|
||||
* value:审批人的数组
|
||||
* 例如: { taskKey1 :[1, 2] },则表示 taskKey1 这个任务,提前设定了,由 userId 为 1,2 的用户进行审批
|
||||
* 例如:{ taskKey1 :[1, 2] },则表示 taskKey1 这个任务,提前设定了,由 userId 为 1,2 的用户进行审批
|
||||
*/
|
||||
private Map<String, List<Long>> assignee;
|
||||
private Map<String, List<Long>> startUserSelectAssignees;
|
||||
|
||||
}
|
||||
|
@ -29,12 +29,13 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode PROCESS_DEFINITION_NAME_NOT_MATCH = new ErrorCode(1_009_003_001, "流程定义的名字期望是({}),当前是({}),请修改 BPMN 流程图");
|
||||
ErrorCode PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1_009_003_002, "流程定义不存在");
|
||||
ErrorCode PROCESS_DEFINITION_IS_SUSPENDED = new ErrorCode(1_009_003_003, "流程定义处于挂起状态");
|
||||
ErrorCode PROCESS_DEFINITION_BPMN_MODEL_NOT_EXISTS = new ErrorCode(1_009_003_004, "流程定义的模型不存在");
|
||||
|
||||
// ========== 流程实例 1-009-004-000 ==========
|
||||
ErrorCode PROCESS_INSTANCE_NOT_EXISTS = new ErrorCode(1_009_004_000, "流程实例不存在");
|
||||
ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS = new ErrorCode(1_009_004_001, "流程取消失败,流程不处于运行中");
|
||||
ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF = new ErrorCode(1_009_004_002, "流程取消失败,该流程不是你发起的");
|
||||
ErrorCode PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIG = new ErrorCode(1_009_004_003, "审批任务({})的审批人未配置");
|
||||
ErrorCode PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_EXISTS = new ErrorCode(1_009_004_004, "审批任务({})的审批人({})不存在");
|
||||
|
||||
// ========== 流程任务 1-009-005-000 ==========
|
||||
ErrorCode TASK_OPERATE_FAIL_ASSIGN_NOT_SELF = new ErrorCode(1_009_005_001, "操作失败,原因:该任务的审批人不是你");
|
||||
@ -50,8 +51,6 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode TASK_SIGN_DELETE_NO_PARENT = new ErrorCode(1_009_005_012, "任务减签失败,被减签的任务必须是通过加签生成的任务");
|
||||
ErrorCode TASK_TRANSFER_FAIL_USER_REPEAT = new ErrorCode(1_009_005_013, "任务转办失败,转办人和当前审批人为同一人");
|
||||
ErrorCode TASK_TRANSFER_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_014, "任务转办失败,转办人不存在");
|
||||
|
||||
// ========== 流程任务分配规则 1-009-006-000 TODO 芋艿:这里要改下 ==========
|
||||
ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!");
|
||||
|
||||
// ========== 动态表单模块 1-009-010-000 ==========
|
||||
|
@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.bpm.convert.definition.BpmProcessDefinitionConver
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.BpmTaskCandidateStartUserSelectStrategy;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryService;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmFormService;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
|
||||
@ -16,6 +17,8 @@ import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.bpmn.model.UserTask;
|
||||
import org.flowable.engine.repository.Deployment;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@ -89,13 +92,23 @@ public class BpmProcessDefinitionController {
|
||||
list, null, processDefinitionMap, null, null));
|
||||
}
|
||||
|
||||
@GetMapping ("/get-bpmn-xml")
|
||||
@Operation(summary = "获得流程定义的 BPMN XML")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@GetMapping ("/get")
|
||||
@Operation(summary = "获得流程定义")
|
||||
@Parameter(name = "id", description = "流程编号", required = true, example = "1024")
|
||||
@Parameter(name = "key", description = "流程定义标识", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('bpm:process-definition:query')")
|
||||
public CommonResult<String> getProcessDefinitionBpmnXML(@RequestParam("id") String id) {
|
||||
String bpmnXML = processDefinitionService.getProcessDefinitionBpmnXML(id);
|
||||
return success(bpmnXML);
|
||||
public CommonResult<BpmProcessDefinitionRespVO> getProcessDefinition(
|
||||
@RequestParam(value = "id", required = false) String id,
|
||||
@RequestParam(value = "key", required = false) String key) {
|
||||
ProcessDefinition processDefinition = id != null ? processDefinitionService.getProcessDefinition(id)
|
||||
: processDefinitionService.getActiveProcessDefinition(key);
|
||||
if (processDefinition == null) {
|
||||
return success(null);
|
||||
}
|
||||
BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(processDefinition.getId());
|
||||
List<UserTask> userTaskList = BpmTaskCandidateStartUserSelectStrategy.getStartUserSelectUserTaskList(bpmnModel);
|
||||
return success(BpmProcessDefinitionConvert.INSTANCE.buildProcessDefinition(
|
||||
processDefinition, null, null, null, null, bpmnModel, userTaskList));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,6 +18,9 @@ public class BpmCategorySaveReqVO {
|
||||
@NotEmpty(message = "分类名不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "分类描述", example = "你猜")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "分类标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "OA")
|
||||
@NotEmpty(message = "分类标志不能为空")
|
||||
private String code;
|
||||
|
@ -48,7 +48,7 @@ public class BpmProcessDefinitionRespVO {
|
||||
private String formCustomViewPath;
|
||||
|
||||
@Schema(description = "中断状态-参见 SuspensionState 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer suspensionState;
|
||||
private Integer suspensionState; // 参见 SuspensionState 枚举
|
||||
|
||||
@Schema(description = "部署时间")
|
||||
private LocalDateTime deploymentTime; // 需要从对应的 Deployment 读取,非必须返回
|
||||
@ -56,4 +56,19 @@ public class BpmProcessDefinitionRespVO {
|
||||
@Schema(description = "BPMN XML")
|
||||
private String bpmnXml; // 需要从对应的 BpmnModel 读取,非必须返回
|
||||
|
||||
@Schema(description = "发起用户需要选择审批人的任务数组")
|
||||
private List<UserTask> startUserSelectTasks; // 需要从对应的 BpmnModel 读取,非必须返回
|
||||
|
||||
@Schema(description = "BPMN UserTask 用户任务")
|
||||
@Data
|
||||
public static class UserTask {
|
||||
|
||||
@Schema(description = "任务标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "sudo")
|
||||
private String id;
|
||||
|
||||
@Schema(description = "任务名", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
|
||||
private String name;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@ -30,6 +32,9 @@ public class BpmOALeaveCreateReqVO {
|
||||
@Schema(description = "原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "阅读芋道源码")
|
||||
private String reason;
|
||||
|
||||
@Schema(description = "发起人自选审批人 Map", example = "{taskKey1: [1, 2]}")
|
||||
private Map<String, List<Long>> startUserSelectAssignees;
|
||||
|
||||
@AssertTrue(message = "结束时间,需要在开始时间之后")
|
||||
public boolean isEndTimeValid() {
|
||||
return !getEndTime().isBefore(getStartTime());
|
||||
|
@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessI
|
||||
import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryService;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
|
||||
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
|
||||
@ -130,7 +131,8 @@ public class BpmProcessInstanceController {
|
||||
processInstance.getProcessDefinitionId());
|
||||
BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.getProcessDefinitionInfo(
|
||||
processInstance.getProcessDefinitionId());
|
||||
String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId());
|
||||
String bpmnXml = BpmnModelUtils.getBpmnXml(
|
||||
processDefinitionService.getProcessDefinitionBpmnModel(processInstance.getProcessDefinitionId()));
|
||||
AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId()));
|
||||
DeptRespDTO dept = null;
|
||||
if (startUser != null) {
|
||||
|
@ -18,8 +18,7 @@ public class BpmProcessInstanceCreateReqVO {
|
||||
@Schema(description = "变量实例(动态表单)")
|
||||
private Map<String, Object> variables;
|
||||
|
||||
// TODO @hai:assignees 复数
|
||||
@Schema(description = "提前指派的审批人", requiredMode = Schema.RequiredMode.REQUIRED, example = "{taskKey1: [1, 2]}")
|
||||
private Map<String, List<Long>> assignee;
|
||||
@Schema(description = "发起人自选审批人 Map", example = "{taskKey1: [1, 2]}")
|
||||
private Map<String, List<Long>> startUserSelectAssignees;
|
||||
|
||||
}
|
||||
|
@ -4,12 +4,14 @@ import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.bpmn.model.UserTask;
|
||||
import org.flowable.common.engine.impl.db.SuspensionState;
|
||||
import org.flowable.engine.repository.Deployment;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
@ -47,27 +49,50 @@ public interface BpmProcessDefinitionConvert {
|
||||
Map<Long, BpmFormDO> formMap,
|
||||
Map<String, BpmCategoryDO> categoryMap) {
|
||||
return CollectionUtils.convertList(list, definition -> {
|
||||
BpmProcessDefinitionRespVO respVO = BeanUtils.toBean(definition, BpmProcessDefinitionRespVO.class);
|
||||
respVO.setSuspensionState(definition.isSuspended() ? SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode());
|
||||
// Deployment
|
||||
MapUtils.findAndThen(deploymentMap, definition.getDeploymentId(),
|
||||
deployment -> respVO.setDeploymentTime(LocalDateTimeUtil.of(deployment.getDeploymentTime())));
|
||||
// BpmProcessDefinitionInfoDO
|
||||
Deployment deployment = MapUtil.get(deploymentMap, definition.getDeploymentId(), Deployment.class);
|
||||
BpmProcessDefinitionInfoDO processDefinitionInfo = MapUtil.get(processDefinitionInfoMap, definition.getId(), BpmProcessDefinitionInfoDO.class);
|
||||
BpmFormDO form = null;
|
||||
if (processDefinitionInfo != null) {
|
||||
copyTo(processDefinitionInfo, respVO);
|
||||
// Form
|
||||
BpmFormDO form = MapUtil.get(formMap, processDefinitionInfo.getFormId(), BpmFormDO.class);
|
||||
if (form != null) {
|
||||
respVO.setFormName(form.getName());
|
||||
}
|
||||
form = MapUtil.get(formMap, processDefinitionInfo.getFormId(), BpmFormDO.class);
|
||||
}
|
||||
// Category
|
||||
MapUtils.findAndThen(categoryMap, definition.getCategory(), category -> respVO.setCategoryName(category.getName()));
|
||||
return respVO;
|
||||
BpmCategoryDO category = MapUtil.get(categoryMap, definition.getCategory(), BpmCategoryDO.class);
|
||||
return buildProcessDefinition(definition, deployment, processDefinitionInfo, form, category, null, null);
|
||||
});
|
||||
}
|
||||
|
||||
default BpmProcessDefinitionRespVO buildProcessDefinition(ProcessDefinition definition,
|
||||
Deployment deployment,
|
||||
BpmProcessDefinitionInfoDO processDefinitionInfo,
|
||||
BpmFormDO form,
|
||||
BpmCategoryDO category,
|
||||
BpmnModel bpmnModel,
|
||||
List<UserTask> startUserSelectUserTaskList) {
|
||||
BpmProcessDefinitionRespVO respVO = BeanUtils.toBean(definition, BpmProcessDefinitionRespVO.class);
|
||||
respVO.setSuspensionState(definition.isSuspended() ? SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode());
|
||||
// Deployment
|
||||
if (deployment != null) {
|
||||
respVO.setDeploymentTime(LocalDateTimeUtil.of(deployment.getDeploymentTime()));
|
||||
}
|
||||
// BpmProcessDefinitionInfoDO
|
||||
if (processDefinitionInfo != null) {
|
||||
copyTo(processDefinitionInfo, respVO);
|
||||
// Form
|
||||
if (form != null) {
|
||||
respVO.setFormName(form.getName());
|
||||
}
|
||||
}
|
||||
// Category
|
||||
if (category != null) {
|
||||
respVO.setCategoryName(category.getName());
|
||||
}
|
||||
// BpmnModel
|
||||
if (bpmnModel != null) {
|
||||
respVO.setBpmnXml(BpmnModelUtils.getBpmnXml(bpmnModel));
|
||||
respVO.setStartUserSelectTasks(BeanUtils.toBean(startUserSelectUserTaskList, BpmProcessDefinitionRespVO.UserTask.class));
|
||||
}
|
||||
return respVO;
|
||||
}
|
||||
|
||||
@Mapping(source = "from.id", target = "to.id", ignore = true)
|
||||
void copyTo(BpmProcessDefinitionInfoDO from, @MappingTarget BpmProcessDefinitionRespVO to);
|
||||
|
||||
|
@ -68,7 +68,7 @@ public interface BpmProcessInstanceConvert {
|
||||
DeptRespDTO dept) {
|
||||
BpmProcessInstanceRespVO respVO = BeanUtils.toBean(processInstance, BpmProcessInstanceRespVO.class);
|
||||
respVO.setStatus(FlowableUtils.getProcessInstanceStatus(processInstance));
|
||||
respVO.setFormVariables(FlowableUtils.filterProcessInstanceFormVariable(processInstance.getProcessVariables()));
|
||||
respVO.setFormVariables(FlowableUtils.getProcessInstanceFormVariable(processInstance));
|
||||
// definition
|
||||
respVO.setProcessDefinition(BeanUtils.toBean(processDefinition, BpmProcessDefinitionRespVO.class));
|
||||
copyTo(processDefinitionExt, respVO.getProcessDefinition());
|
||||
|
@ -1,11 +1,10 @@
|
||||
package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* BPM 流程分类 DO
|
||||
@ -42,7 +41,7 @@ public class BpmCategoryDO extends BaseDO {
|
||||
/**
|
||||
* 分类状态
|
||||
*
|
||||
* 枚举 {@link TODO common_status 对应的类}
|
||||
* 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
|
@ -21,7 +21,7 @@ public interface BpmCategoryMapper extends BaseMapperX<BpmCategoryDO> {
|
||||
default PageResult<BpmCategoryDO> selectPage(BpmCategoryPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<BpmCategoryDO>()
|
||||
.likeIfPresent(BpmCategoryDO::getName, reqVO.getName())
|
||||
.eqIfPresent(BpmCategoryDO::getCode, reqVO.getCode())
|
||||
.likeIfPresent(BpmCategoryDO::getCode, reqVO.getCode())
|
||||
.eqIfPresent(BpmCategoryDO::getStatus, reqVO.getStatus())
|
||||
.betweenIfPresent(BpmCategoryDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByAsc(BpmCategoryDO::getSort));
|
||||
|
@ -1,41 +0,0 @@
|
||||
package cn.iocoder.yudao.module.bpm.framework;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.alibaba.ttl.TransmittableThreadLocal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 工作流--用户用到的上下文相关信息
|
||||
*/
|
||||
@Deprecated // TODO 芋艿:找个方式,去掉这个上下文
|
||||
public class FlowableContextHolder {
|
||||
|
||||
private static final ThreadLocal<Map<String, List<Long>>> ASSIGNEE = new TransmittableThreadLocal<>();
|
||||
|
||||
/**
|
||||
* 通过流程任务的定义 key ,拿到提前选好的审批人
|
||||
* 此方法目的:首次创建流程实例时,数据库中还查询不到 assignee 字段,所以存入上下文中获取
|
||||
*
|
||||
* @param taskDefinitionKey 流程任务 key
|
||||
* @return 审批人 ID 集合
|
||||
*/
|
||||
public static List<Long> getAssigneeByTaskDefinitionKey(String taskDefinitionKey) {
|
||||
if (CollUtil.isNotEmpty(ASSIGNEE.get())) {
|
||||
return ASSIGNEE.get().get(taskDefinitionKey);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 存入提前选好的审批人到上下文线程变量中
|
||||
*
|
||||
* @param assignee 流程任务 key -> 审批人 ID 炅和
|
||||
*/
|
||||
public static void setAssignee(Map<String, List<Long>> assignee) {
|
||||
ASSIGNEE.set(assignee);
|
||||
}
|
||||
|
||||
}
|
@ -4,16 +4,13 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
|
||||
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.system.api.user.AdminUserApi;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.bpmn.model.FlowElement;
|
||||
import org.flowable.bpmn.model.UserTask;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
|
||||
@ -60,9 +57,13 @@ public class BpmTaskCandidateInvoker {
|
||||
// 遍历所有的 UserTask,校验审批人配置
|
||||
userTaskList.forEach(userTask -> {
|
||||
// 1. 非空校验
|
||||
Integer strategy = parseCandidateStrategy(userTask);
|
||||
String param = parseCandidateParam(userTask);
|
||||
if (strategy == null || StrUtil.isBlank(param)) {
|
||||
Integer strategy = BpmnModelUtils.parseCandidateStrategy(userTask);
|
||||
String param = BpmnModelUtils.parseCandidateParam(userTask);
|
||||
if (strategy == null) {
|
||||
throw exception(MODEL_DEPLOY_FAIL_TASK_CANDIDATE_NOT_CONFIG, userTask.getName());
|
||||
}
|
||||
BpmTaskCandidateStrategy candidateStrategy = getCandidateStrategy(strategy);
|
||||
if (candidateStrategy.isParamRequired() && StrUtil.isBlank(param)) {
|
||||
throw exception(MODEL_DEPLOY_FAIL_TASK_CANDIDATE_NOT_CONFIG, userTask.getName());
|
||||
}
|
||||
// 2. 具体策略校验
|
||||
@ -77,16 +78,8 @@ public class BpmTaskCandidateInvoker {
|
||||
* @return 用户编号集合
|
||||
*/
|
||||
public Set<Long> calculateUsers(DelegateExecution execution) {
|
||||
// TODO 芋艿:这里需要重构
|
||||
// // 1. 先从提前选好的审批人中获取
|
||||
// List<Long> assignee = processInstanceService.getAssigneeByProcessInstanceIdAndTaskDefinitionKey(
|
||||
// execution.getProcessInstanceId(), execution.getCurrentActivityId());
|
||||
// if (CollUtil.isNotEmpty(assignee)) {
|
||||
// // TODO @hai:new HashSet 即可
|
||||
// return convertSet(assignee, Function.identity());
|
||||
// }
|
||||
Integer strategy = parseCandidateStrategy(execution.getCurrentFlowElement());
|
||||
String param = parseCandidateParam(execution.getCurrentFlowElement());
|
||||
Integer strategy = BpmnModelUtils.parseCandidateStrategy(execution.getCurrentFlowElement());
|
||||
String param = BpmnModelUtils.parseCandidateParam(execution.getCurrentFlowElement());
|
||||
// 1.1 计算任务的候选人
|
||||
Set<Long> userIds = getCandidateStrategy(strategy).calculateUsers(execution, param);
|
||||
// 1.2 移除被禁用的用户
|
||||
@ -113,16 +106,6 @@ public class BpmTaskCandidateInvoker {
|
||||
});
|
||||
}
|
||||
|
||||
private static Integer parseCandidateStrategy(FlowElement userTask) {
|
||||
return NumberUtils.parseInt(userTask.getAttributeValue(
|
||||
BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY));
|
||||
}
|
||||
|
||||
private static String parseCandidateParam(FlowElement userTask) {
|
||||
return userTask.getAttributeValue(
|
||||
BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_PARAM);
|
||||
}
|
||||
|
||||
private BpmTaskCandidateStrategy getCandidateStrategy(Integer strategy) {
|
||||
BpmTaskCandidateStrategyEnum strategyEnum = BpmTaskCandidateStrategyEnum.valueOf(strategy);
|
||||
Assert.notNull(strategyEnum, "策略(%s) 不存在", strategy);
|
||||
|
@ -36,4 +36,13 @@ public interface BpmTaskCandidateStrategy {
|
||||
*/
|
||||
Set<Long> calculateUsers(DelegateExecution execution, String param);
|
||||
|
||||
/**
|
||||
* 是否一定要输入参数
|
||||
*
|
||||
* @return 是否
|
||||
*/
|
||||
default boolean isParamRequired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -32,12 +32,12 @@ public class BpmTaskAssignLeaderExpression {
|
||||
private DeptApi deptApi;
|
||||
|
||||
@Resource
|
||||
private BpmProcessInstanceService bpmProcessInstanceService;
|
||||
private BpmProcessInstanceService processInstanceService;
|
||||
|
||||
protected Set<Long> calculateUsers(DelegateExecution execution, int level) {
|
||||
Assert.isTrue(level > 0, "level 必须大于 0");
|
||||
// 获得发起人
|
||||
ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(execution.getProcessInstanceId());
|
||||
ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getProcessInstanceId());
|
||||
Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
|
||||
// 获得对应 leve 的部门
|
||||
DeptRespDTO dept = null;
|
||||
|
@ -19,10 +19,10 @@ import java.util.Set;
|
||||
public class BpmTaskAssignStartUserExpression {
|
||||
|
||||
@Resource
|
||||
private BpmProcessInstanceService bpmProcessInstanceService;
|
||||
private BpmProcessInstanceService processInstanceService;
|
||||
|
||||
public Set<Long> calculateUsers(DelegateExecution execution) {
|
||||
ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(execution.getProcessInstanceId());
|
||||
ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getProcessInstanceId());
|
||||
Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
|
||||
return SetUtils.asSet(startUserId);
|
||||
}
|
||||
|
@ -0,0 +1,76 @@
|
||||
package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
|
||||
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.task.BpmProcessInstanceService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.bpmn.model.UserTask;
|
||||
import org.flowable.engine.delegate.DelegateExecution;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 发起人自选 {@link BpmTaskCandidateUserStrategy} 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Component
|
||||
public class BpmTaskCandidateStartUserSelectStrategy implements BpmTaskCandidateStrategy {
|
||||
|
||||
@Resource
|
||||
@Lazy // 延迟加载,避免循环依赖
|
||||
private BpmProcessInstanceService processInstanceService;
|
||||
|
||||
@Override
|
||||
public BpmTaskCandidateStrategyEnum getStrategy() {
|
||||
return BpmTaskCandidateStrategyEnum.START_USER_SELECT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateParam(String param) {}
|
||||
|
||||
@Override
|
||||
public Set<Long> calculateUsers(DelegateExecution execution, String param) {
|
||||
ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getProcessInstanceId());
|
||||
Assert.notNull(processInstance, "流程实例({})不能为空", execution.getProcessInstanceId());
|
||||
Map<String, List<Long>> startUserSelectAssignees = FlowableUtils.getStartUserSelectAssignees(processInstance);
|
||||
Assert.notNull(startUserSelectAssignees, "流程实例({}) 的发起人自选审批人不能为空",
|
||||
execution.getProcessInstanceId());
|
||||
// 获得审批人
|
||||
List<Long> assignees = startUserSelectAssignees.get(execution.getCurrentActivityId());
|
||||
return new LinkedHashSet<>(assignees);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isParamRequired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得发起人自选审批人的 UserTask 列表
|
||||
*
|
||||
* @param bpmnModel BPMN 模型
|
||||
* @return UserTask 列表
|
||||
*/
|
||||
public static List<UserTask> getStartUserSelectUserTaskList(BpmnModel bpmnModel) {
|
||||
if (bpmnModel == null) {
|
||||
return null;
|
||||
}
|
||||
List<UserTask> userTaskList = BpmnModelUtils.getBpmnModelElements(bpmnModel, UserTask.class);
|
||||
if (CollUtil.isEmpty(userTaskList)) {
|
||||
return null;
|
||||
}
|
||||
userTaskList.removeIf(userTask -> !Objects.equals(BpmnModelUtils.parseCandidateStrategy(userTask),
|
||||
BpmTaskCandidateStrategyEnum.START_USER_SELECT.getStrategy()));
|
||||
return userTaskList;
|
||||
}
|
||||
|
||||
}
|
@ -15,6 +15,12 @@ public class BpmConstants {
|
||||
* @see ProcessInstance#getProcessVariables()
|
||||
*/
|
||||
public static final String PROCESS_INSTANCE_VARIABLE_STATUS = "PROCESS_STATUS";
|
||||
/**
|
||||
* 流程实例的变量 - 发起用户选择的审批人 Map
|
||||
*
|
||||
* @see ProcessInstance#getProcessVariables()
|
||||
*/
|
||||
public static final String PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES = "PROCESS_START_USER_SELECT_ASSIGNEES";
|
||||
|
||||
/**
|
||||
* 任务的变量 - 状态
|
||||
|
@ -20,6 +20,7 @@ public enum BpmTaskCandidateStrategyEnum {
|
||||
DEPT_LEADER(21, "部门的负责人"),
|
||||
POST(22, "岗位"),
|
||||
USER(30, "用户"),
|
||||
START_USER_SELECT(35, "发起人自选"), // 申请人自己,可在提交申请时选择此节点的审批人
|
||||
USER_GROUP(40, "用户组"),
|
||||
EXPRESSION(60, "流程表达式"), // 表达式 ExpressionManager
|
||||
;
|
||||
|
@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.util;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
|
||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
|
||||
import org.flowable.bpmn.converter.BpmnXMLConverter;
|
||||
import org.flowable.bpmn.model.Process;
|
||||
import org.flowable.bpmn.model.*;
|
||||
@ -14,6 +16,16 @@ import java.util.*;
|
||||
*/
|
||||
public class BpmnModelUtils {
|
||||
|
||||
public static Integer parseCandidateStrategy(FlowElement userTask) {
|
||||
return NumberUtils.parseInt(userTask.getAttributeValue(
|
||||
BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY));
|
||||
}
|
||||
|
||||
public static String parseCandidateParam(FlowElement userTask) {
|
||||
return userTask.getAttributeValue(
|
||||
BpmnModelConstants.NAMESPACE, BpmnModelConstants.USER_TASK_CANDIDATE_PARAM);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据节点,获取入口连线
|
||||
*
|
||||
@ -91,6 +103,14 @@ public class BpmnModelUtils {
|
||||
return converter.convertToBpmnModel(new BytesStreamSource(bpmnBytes), false, false);
|
||||
}
|
||||
|
||||
public static String getBpmnXml(BpmnModel model) {
|
||||
if (model == null) {
|
||||
return null;
|
||||
}
|
||||
BpmnXMLConverter converter = new BpmnXMLConverter();
|
||||
return new String(converter.convertToXML(model));
|
||||
}
|
||||
|
||||
// ========== 遍历相关的方法 ==========
|
||||
|
||||
/**
|
||||
|
@ -12,6 +12,7 @@ import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.flowable.task.api.TaskInfo;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@ -79,7 +80,7 @@ public class FlowableUtils {
|
||||
* @param processInstance 流程实例
|
||||
* @return 表单
|
||||
*/
|
||||
public static Map<String, Object> getProcessInstanceFormVariable(ProcessInstance processInstance) {
|
||||
public static Map<String, Object> getProcessInstanceFormVariable(HistoricProcessInstance processInstance) {
|
||||
Map<String, Object> formVariables = new HashMap<>(processInstance.getProcessVariables());
|
||||
filterProcessInstanceFormVariable(formVariables);
|
||||
return formVariables;
|
||||
@ -98,6 +99,18 @@ public class FlowableUtils {
|
||||
return processVariables;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得流程实例的发起用户选择的审批人 Map
|
||||
*
|
||||
* @param processInstance 流程实例
|
||||
* @return 发起用户选择的审批人 Map
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Map<String, List<Long>> getStartUserSelectAssignees(ProcessInstance processInstance) {
|
||||
return (Map<String, List<Long>>) processInstance.getProcessVariables().get(
|
||||
BpmConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES);
|
||||
}
|
||||
|
||||
// ========== Task 相关的工具方法 ==========
|
||||
|
||||
/**
|
||||
|
@ -33,7 +33,7 @@ public class BpmFormServiceImpl implements BpmFormService {
|
||||
|
||||
@Override
|
||||
public Long createForm(BpmFormSaveReqVO createReqVO) {
|
||||
this.vadateFields(createReqVO.getFields());
|
||||
this.validateFields(createReqVO.getFields());
|
||||
// 插入
|
||||
BpmFormDO form = BeanUtils.toBean(createReqVO, BpmFormDO.class);
|
||||
formMapper.insert(form);
|
||||
@ -43,7 +43,7 @@ public class BpmFormServiceImpl implements BpmFormService {
|
||||
|
||||
@Override
|
||||
public void updateForm(BpmFormSaveReqVO updateReqVO) {
|
||||
vadateFields(updateReqVO.getFields());
|
||||
validateFields(updateReqVO.getFields());
|
||||
// 校验存在
|
||||
validateFormExists(updateReqVO.getId());
|
||||
// 更新
|
||||
@ -93,7 +93,7 @@ public class BpmFormServiceImpl implements BpmFormService {
|
||||
*
|
||||
* @param fields field 数组
|
||||
*/
|
||||
private void vadateFields(List<String> fields) {
|
||||
private void validateFields(List<String> fields) {
|
||||
if (true) { // TODO 芋艿:兼容 Vue3 工作流:因为采用了新的表单设计器,所以暂时不校验
|
||||
return;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmPro
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.engine.repository.Deployment;
|
||||
import org.flowable.engine.repository.Model;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
@ -61,12 +62,12 @@ public interface BpmProcessDefinitionService {
|
||||
void updateProcessDefinitionState(String id, Integer state);
|
||||
|
||||
/**
|
||||
* 获得流程定义对应的 BPMN XML
|
||||
* 获得流程定义对应的 BPMN
|
||||
*
|
||||
* @param id 流程定义编号
|
||||
* @return BPMN XML
|
||||
* @return BPMN
|
||||
*/
|
||||
String getProcessDefinitionBpmnXML(String id);
|
||||
BpmnModel getProcessDefinitionBpmnModel(String id);
|
||||
|
||||
/**
|
||||
* 获得流程定义的信息
|
||||
@ -89,9 +90,9 @@ public interface BpmProcessDefinitionService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得编号对应的 ProcessDefinition
|
||||
* 获得流程定义编号对应的 ProcessDefinition
|
||||
*
|
||||
* @param id 编号
|
||||
* @param id 流程定义编号
|
||||
* @return 流程定义
|
||||
*/
|
||||
ProcessDefinition getProcessDefinition(String id);
|
||||
@ -139,7 +140,7 @@ public interface BpmProcessDefinitionService {
|
||||
* @return 流程部署 Map
|
||||
*/
|
||||
default Map<String, Deployment> getDeploymentMap(Set<String> ids) {
|
||||
return convertMap(getDeployments(ids), Deployment::getId);
|
||||
return convertMap(getDeploymentList(ids), Deployment::getId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -148,7 +149,7 @@ public interface BpmProcessDefinitionService {
|
||||
* @param ids 部署编号的数组
|
||||
* @return 流程部署的数组
|
||||
*/
|
||||
List<Deployment> getDeployments(Set<String> ids);
|
||||
List<Deployment> getDeploymentList(Set<String> ids);
|
||||
|
||||
/**
|
||||
* 获得 id 对应的 Deployment
|
||||
|
@ -14,7 +14,6 @@ import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConsta
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.bpmn.converter.BpmnXMLConverter;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.common.engine.impl.db.SuspensionState;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
@ -84,7 +83,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Deployment> getDeployments(Set<String> ids) {
|
||||
public List<Deployment> getDeploymentList(Set<String> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return emptyList();
|
||||
}
|
||||
@ -156,13 +155,8 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProcessDefinitionBpmnXML(String id) {
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(id);
|
||||
if (bpmnModel == null) {
|
||||
return null;
|
||||
}
|
||||
BpmnXMLConverter converter = new BpmnXMLConverter();
|
||||
return StrUtil.utf8Str(converter.convertToXML(bpmnModel));
|
||||
public BpmnModel getProcessDefinitionBpmnModel(String id) {
|
||||
return repositoryService.getBpmnModel(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -56,7 +56,8 @@ public class BpmOALeaveServiceImpl implements BpmOALeaveService {
|
||||
processInstanceVariables.put("day", day);
|
||||
String processInstanceId = processInstanceApi.createProcessInstance(userId,
|
||||
new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
|
||||
.setVariables(processInstanceVariables).setBusinessKey(String.valueOf(leave.getId())));
|
||||
.setVariables(processInstanceVariables).setBusinessKey(String.valueOf(leave.getId()))
|
||||
.setStartUserSelectAssignees(createReqVO.getStartUserSelectAssignees()));
|
||||
|
||||
// 将工作流的编号,更新到 OA 请假单中
|
||||
leaveMapper.updateById(new BpmOALeaveDO().setId(leave.getId()).setProcessInstanceId(processInstanceId));
|
||||
|
@ -49,17 +49,6 @@ public interface BpmProcessInstanceService {
|
||||
return convertMap(getProcessInstances(ids), ProcessInstance::getProcessInstanceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得流程实例名字 Map
|
||||
*
|
||||
* @param ids 流程实例的编号集合
|
||||
* @return 对应的映射关系
|
||||
*/
|
||||
default Map<String, String> getProcessInstanceNameMap(Set<String> ids) {
|
||||
return convertMap(getProcessInstances(ids),
|
||||
ProcessInstance::getProcessInstanceId, ProcessInstance::getName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得历史的流程实例
|
||||
*
|
||||
@ -152,14 +141,4 @@ public interface BpmProcessInstanceService {
|
||||
*/
|
||||
void updateProcessInstanceReject(String id, String reason);
|
||||
|
||||
// TODO @hai:改成 getProcessInstanceAssigneesByTaskDefinitionKey(String id, String taskDefinitionKey)
|
||||
/**
|
||||
* 获取流程实例中,取出指定流程任务提前指定的审批人
|
||||
*
|
||||
* @param processInstanceId 流程实例的编号
|
||||
* @param taskDefinitionKey 流程任务定义的 key
|
||||
* @return 审批人集合
|
||||
*/
|
||||
List<Long> getAssigneeByProcessInstanceIdAndTaskDefinitionKey(String processInstanceId, String taskDefinitionKey);
|
||||
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
@ -30,8 +30,9 @@ public class BpmTaskAssignLeaderExpressionTest extends BaseMockitoUnitTest {
|
||||
private AdminUserApi adminUserApi;
|
||||
@Mock
|
||||
private DeptApi deptApi;
|
||||
|
||||
@Mock
|
||||
private BpmProcessInstanceService bpmProcessInstanceService;
|
||||
private BpmProcessInstanceService processInstanceService;
|
||||
|
||||
@Test
|
||||
public void testCalculateUsers_noDept() {
|
||||
@ -96,7 +97,7 @@ public class BpmTaskAssignLeaderExpressionTest extends BaseMockitoUnitTest {
|
||||
// mock 返回 startUserId
|
||||
ExecutionEntityImpl processInstance = new ExecutionEntityImpl();
|
||||
processInstance.setStartUserId(String.valueOf(startUserId));
|
||||
when(bpmProcessInstanceService.getProcessInstance(eq(execution.getProcessInstanceId())))
|
||||
when(processInstanceService.getProcessInstance(eq(execution.getProcessInstanceId())))
|
||||
.thenReturn(processInstance);
|
||||
return execution;
|
||||
}
|
||||
|
@ -1,26 +1,24 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.category;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.category.BpmCategoryPageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.category.BpmCategorySaveReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryServiceImpl;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.mysql.category.BpmCategoryMapper;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryServiceImpl;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
|
||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
|
||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.CATEGORY_NOT_EXISTS;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
@ -40,7 +38,8 @@ public class BpmCategoryServiceImplTest extends BaseDbUnitTest {
|
||||
@Test
|
||||
public void testCreateCategory_success() {
|
||||
// 准备参数
|
||||
BpmCategorySaveReqVO createReqVO = randomPojo(BpmCategorySaveReqVO.class).setId(null);
|
||||
BpmCategorySaveReqVO createReqVO = randomPojo(BpmCategorySaveReqVO.class).setId(null)
|
||||
.setStatus(randomCommonStatus());
|
||||
|
||||
// 调用
|
||||
Long categoryId = categoryService.createCategory(createReqVO);
|
||||
@ -59,6 +58,7 @@ public class BpmCategoryServiceImplTest extends BaseDbUnitTest {
|
||||
// 准备参数
|
||||
BpmCategorySaveReqVO updateReqVO = randomPojo(BpmCategorySaveReqVO.class, o -> {
|
||||
o.setId(dbCategory.getId()); // 设置更新的 ID
|
||||
o.setStatus(randomCommonStatus());
|
||||
});
|
||||
|
||||
// 调用
|
||||
@ -101,29 +101,28 @@ public class BpmCategoryServiceImplTest extends BaseDbUnitTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
|
||||
public void testGetCategoryPage() {
|
||||
// mock 数据
|
||||
BpmCategoryDO dbCategory = randomPojo(BpmCategoryDO.class, o -> { // 等会查询到
|
||||
o.setName(null);
|
||||
o.setCode(null);
|
||||
o.setStatus(null);
|
||||
o.setCreateTime(null);
|
||||
o.setName("芋头");
|
||||
o.setCode("xiaodun");
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setCreateTime(buildTime(2023, 2, 2));
|
||||
});
|
||||
categoryMapper.insert(dbCategory);
|
||||
// 测试 name 不匹配
|
||||
categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setName(null)));
|
||||
categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setName("小盾")));
|
||||
// 测试 code 不匹配
|
||||
categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setCode(null)));
|
||||
categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setCode("tudou")));
|
||||
// 测试 status 不匹配
|
||||
categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setStatus(null)));
|
||||
categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
|
||||
// 测试 createTime 不匹配
|
||||
categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setCreateTime(null)));
|
||||
categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setCreateTime(buildTime(2024, 2, 2))));
|
||||
// 准备参数
|
||||
BpmCategoryPageReqVO reqVO = new BpmCategoryPageReqVO();
|
||||
reqVO.setName(null);
|
||||
reqVO.setCode(null);
|
||||
reqVO.setStatus(null);
|
||||
reqVO.setName("芋");
|
||||
reqVO.setCode("xiao");
|
||||
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
|
||||
|
||||
// 调用
|
||||
|
@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormSaveReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormPageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmFormMapper;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmFormFieldRespDTO;
|
||||
@ -66,7 +65,7 @@ public class BpmFormServiceTest extends BaseDbUnitTest {
|
||||
});
|
||||
formMapper.insert(dbForm);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
BpmFormUpdateReqVO reqVO = randomPojo(BpmFormUpdateReqVO.class, o -> {
|
||||
BpmFormSaveReqVO reqVO = randomPojo(BpmFormSaveReqVO.class, o -> {
|
||||
o.setId(dbForm.getId()); // 设置更新的 ID
|
||||
o.setConf("{'yudao': 'yuanma'}");
|
||||
o.setFields(randomFields());
|
||||
@ -82,7 +81,7 @@ public class BpmFormServiceTest extends BaseDbUnitTest {
|
||||
@Test
|
||||
public void testUpdateForm_notExists() {
|
||||
// 准备参数
|
||||
BpmFormUpdateReqVO reqVO = randomPojo(BpmFormUpdateReqVO.class, o -> {
|
||||
BpmFormSaveReqVO reqVO = randomPojo(BpmFormSaveReqVO.class, o -> {
|
||||
o.setConf("{'yudao': 'yuanma'}");
|
||||
o.setFields(randomFields());
|
||||
});
|
||||
|
@ -1,2 +1,3 @@
|
||||
DELETE FROM "bpm_form";
|
||||
DELETE FROM "bpm_user_group";
|
||||
DELETE FROM "bpm_category";
|
||||
|
@ -12,6 +12,21 @@ CREATE TABLE IF NOT EXISTS "bpm_user_group" (
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT '用户组';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "bpm_category" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"name" varchar(63) NOT NULL,
|
||||
"code" varchar(63) NOT NULL,
|
||||
"description" varchar(255) NOT NULL,
|
||||
"status" tinyint NOT NULL,
|
||||
"sort" int NOT NULL,
|
||||
"creator" varchar(64) DEFAULT '',
|
||||
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updater" varchar(64) DEFAULT '',
|
||||
"update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"deleted" bit NOT NULL DEFAULT FALSE,
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT '分类';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "bpm_form" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"name" varchar(63) NOT NULL,
|
||||
|
Loading…
Reference in New Issue
Block a user