mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2025-01-19 03:30:06 +08:00
BPM:增加「发起人自选」的任务审批人的分配策略
This commit is contained in:
parent
acea73c991
commit
528a321f0a
@ -32,14 +32,13 @@ public class BpmProcessInstanceCreateReqDTO {
|
|||||||
@NotEmpty(message = "业务的唯一标识")
|
@NotEmpty(message = "业务的唯一标识")
|
||||||
private String businessKey;
|
private String businessKey;
|
||||||
|
|
||||||
// TODO @hai:assignees 复数
|
|
||||||
/**
|
/**
|
||||||
* 提前指派的审批人
|
* 发起人自选审批人 Map
|
||||||
*
|
*
|
||||||
* key:taskKey 任务编码
|
* key:taskKey 任务编码
|
||||||
* value:审批人的数组
|
* 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_NAME_NOT_MATCH = new ErrorCode(1_009_003_001, "流程定义的名字期望是({}),当前是({}),请修改 BPMN 流程图");
|
||||||
ErrorCode PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1_009_003_002, "流程定义不存在");
|
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_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 ==========
|
// ========== 流程实例 1-009-004-000 ==========
|
||||||
ErrorCode PROCESS_INSTANCE_NOT_EXISTS = new ErrorCode(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_EXISTS = new ErrorCode(1_009_004_001, "流程取消失败,流程不处于运行中");
|
||||||
ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF = new ErrorCode(1_009_004_002, "流程取消失败,该流程不是你发起的");
|
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 ==========
|
// ========== 流程任务 1-009-005-000 ==========
|
||||||
ErrorCode TASK_OPERATE_FAIL_ASSIGN_NOT_SELF = new ErrorCode(1_009_005_001, "操作失败,原因:该任务的审批人不是你");
|
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_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_REPEAT = new ErrorCode(1_009_005_013, "任务转办失败,转办人和当前审批人为同一人");
|
||||||
ErrorCode TASK_TRANSFER_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_014, "任务转办失败,转办人不存在");
|
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, "操作失败,原因:找不到任务的审批人!");
|
ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!");
|
||||||
|
|
||||||
// ========== 动态表单模块 1-009-010-000 ==========
|
// ========== 动态表单模块 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.BpmCategoryDO;
|
||||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
|
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.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.BpmCategoryService;
|
||||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmFormService;
|
import cn.iocoder.yudao.module.bpm.service.definition.BpmFormService;
|
||||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
|
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.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.annotation.Resource;
|
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.Deployment;
|
||||||
import org.flowable.engine.repository.ProcessDefinition;
|
import org.flowable.engine.repository.ProcessDefinition;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
@ -89,13 +92,23 @@ public class BpmProcessDefinitionController {
|
|||||||
list, null, processDefinitionMap, null, null));
|
list, null, processDefinitionMap, null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping ("/get-bpmn-xml")
|
@GetMapping ("/get")
|
||||||
@Operation(summary = "获得流程定义的 BPMN XML")
|
@Operation(summary = "获得流程定义")
|
||||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
@Parameter(name = "id", description = "流程编号", required = true, example = "1024")
|
||||||
|
@Parameter(name = "key", description = "流程定义标识", required = true, example = "1024")
|
||||||
@PreAuthorize("@ss.hasPermission('bpm:process-definition:query')")
|
@PreAuthorize("@ss.hasPermission('bpm:process-definition:query')")
|
||||||
public CommonResult<String> getProcessDefinitionBpmnXML(@RequestParam("id") String id) {
|
public CommonResult<BpmProcessDefinitionRespVO> getProcessDefinition(
|
||||||
String bpmnXML = processDefinitionService.getProcessDefinitionBpmnXML(id);
|
@RequestParam(value = "id", required = false) String id,
|
||||||
return success(bpmnXML);
|
@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 = "分类名不能为空")
|
@NotEmpty(message = "分类名不能为空")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "分类描述", example = "你猜")
|
||||||
|
private String description;
|
||||||
|
|
||||||
@Schema(description = "分类标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "OA")
|
@Schema(description = "分类标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "OA")
|
||||||
@NotEmpty(message = "分类标志不能为空")
|
@NotEmpty(message = "分类标志不能为空")
|
||||||
private String code;
|
private String code;
|
||||||
|
@ -48,7 +48,7 @@ public class BpmProcessDefinitionRespVO {
|
|||||||
private String formCustomViewPath;
|
private String formCustomViewPath;
|
||||||
|
|
||||||
@Schema(description = "中断状态-参见 SuspensionState 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
@Schema(description = "中断状态-参见 SuspensionState 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
private Integer suspensionState;
|
private Integer suspensionState; // 参见 SuspensionState 枚举
|
||||||
|
|
||||||
@Schema(description = "部署时间")
|
@Schema(description = "部署时间")
|
||||||
private LocalDateTime deploymentTime; // 需要从对应的 Deployment 读取,非必须返回
|
private LocalDateTime deploymentTime; // 需要从对应的 Deployment 读取,非必须返回
|
||||||
@ -56,4 +56,19 @@ public class BpmProcessDefinitionRespVO {
|
|||||||
@Schema(description = "BPMN XML")
|
@Schema(description = "BPMN XML")
|
||||||
private String bpmnXml; // 需要从对应的 BpmnModel 读取,非必须返回
|
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 org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
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;
|
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 = "阅读芋道源码")
|
@Schema(description = "原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "阅读芋道源码")
|
||||||
private String reason;
|
private String reason;
|
||||||
|
|
||||||
|
@Schema(description = "发起人自选审批人 Map", example = "{taskKey1: [1, 2]}")
|
||||||
|
private Map<String, List<Long>> startUserSelectAssignees;
|
||||||
|
|
||||||
@AssertTrue(message = "结束时间,需要在开始时间之后")
|
@AssertTrue(message = "结束时间,需要在开始时间之后")
|
||||||
public boolean isEndTimeValid() {
|
public boolean isEndTimeValid() {
|
||||||
return !getEndTime().isBefore(getStartTime());
|
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.convert.task.BpmProcessInstanceConvert;
|
||||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
|
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.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.BpmCategoryService;
|
||||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
|
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
|
||||||
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
|
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
|
||||||
@ -130,7 +131,8 @@ public class BpmProcessInstanceController {
|
|||||||
processInstance.getProcessDefinitionId());
|
processInstance.getProcessDefinitionId());
|
||||||
BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.getProcessDefinitionInfo(
|
BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.getProcessDefinitionInfo(
|
||||||
processInstance.getProcessDefinitionId());
|
processInstance.getProcessDefinitionId());
|
||||||
String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId());
|
String bpmnXml = BpmnModelUtils.getBpmnXml(
|
||||||
|
processDefinitionService.getProcessDefinitionBpmnModel(processInstance.getProcessDefinitionId()));
|
||||||
AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId()));
|
AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId()));
|
||||||
DeptRespDTO dept = null;
|
DeptRespDTO dept = null;
|
||||||
if (startUser != null) {
|
if (startUser != null) {
|
||||||
|
@ -18,8 +18,7 @@ public class BpmProcessInstanceCreateReqVO {
|
|||||||
@Schema(description = "变量实例(动态表单)")
|
@Schema(description = "变量实例(动态表单)")
|
||||||
private Map<String, Object> variables;
|
private Map<String, Object> variables;
|
||||||
|
|
||||||
// TODO @hai:assignees 复数
|
@Schema(description = "发起人自选审批人 Map", example = "{taskKey1: [1, 2]}")
|
||||||
@Schema(description = "提前指派的审批人", requiredMode = Schema.RequiredMode.REQUIRED, example = "{taskKey1: [1, 2]}")
|
private Map<String, List<Long>> startUserSelectAssignees;
|
||||||
private Map<String, List<Long>> assignee;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,14 @@ import cn.hutool.core.date.LocalDateTimeUtil;
|
|||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
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.CollectionUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
|
||||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
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.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.BpmCategoryDO;
|
||||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
|
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.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.common.engine.impl.db.SuspensionState;
|
||||||
import org.flowable.engine.repository.Deployment;
|
import org.flowable.engine.repository.Deployment;
|
||||||
import org.flowable.engine.repository.ProcessDefinition;
|
import org.flowable.engine.repository.ProcessDefinition;
|
||||||
@ -47,27 +49,50 @@ public interface BpmProcessDefinitionConvert {
|
|||||||
Map<Long, BpmFormDO> formMap,
|
Map<Long, BpmFormDO> formMap,
|
||||||
Map<String, BpmCategoryDO> categoryMap) {
|
Map<String, BpmCategoryDO> categoryMap) {
|
||||||
return CollectionUtils.convertList(list, definition -> {
|
return CollectionUtils.convertList(list, definition -> {
|
||||||
BpmProcessDefinitionRespVO respVO = BeanUtils.toBean(definition, BpmProcessDefinitionRespVO.class);
|
Deployment deployment = MapUtil.get(deploymentMap, definition.getDeploymentId(), Deployment.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
|
|
||||||
BpmProcessDefinitionInfoDO processDefinitionInfo = MapUtil.get(processDefinitionInfoMap, definition.getId(), BpmProcessDefinitionInfoDO.class);
|
BpmProcessDefinitionInfoDO processDefinitionInfo = MapUtil.get(processDefinitionInfoMap, definition.getId(), BpmProcessDefinitionInfoDO.class);
|
||||||
|
BpmFormDO form = null;
|
||||||
if (processDefinitionInfo != null) {
|
if (processDefinitionInfo != null) {
|
||||||
copyTo(processDefinitionInfo, respVO);
|
form = MapUtil.get(formMap, processDefinitionInfo.getFormId(), BpmFormDO.class);
|
||||||
// Form
|
|
||||||
BpmFormDO form = MapUtil.get(formMap, processDefinitionInfo.getFormId(), BpmFormDO.class);
|
|
||||||
if (form != null) {
|
|
||||||
respVO.setFormName(form.getName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Category
|
BpmCategoryDO category = MapUtil.get(categoryMap, definition.getCategory(), BpmCategoryDO.class);
|
||||||
MapUtils.findAndThen(categoryMap, definition.getCategory(), category -> respVO.setCategoryName(category.getName()));
|
return buildProcessDefinition(definition, deployment, processDefinitionInfo, form, category, null, null);
|
||||||
return respVO;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
@Mapping(source = "from.id", target = "to.id", ignore = true)
|
||||||
void copyTo(BpmProcessDefinitionInfoDO from, @MappingTarget BpmProcessDefinitionRespVO to);
|
void copyTo(BpmProcessDefinitionInfoDO from, @MappingTarget BpmProcessDefinitionRespVO to);
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ public interface BpmProcessInstanceConvert {
|
|||||||
DeptRespDTO dept) {
|
DeptRespDTO dept) {
|
||||||
BpmProcessInstanceRespVO respVO = BeanUtils.toBean(processInstance, BpmProcessInstanceRespVO.class);
|
BpmProcessInstanceRespVO respVO = BeanUtils.toBean(processInstance, BpmProcessInstanceRespVO.class);
|
||||||
respVO.setStatus(FlowableUtils.getProcessInstanceStatus(processInstance));
|
respVO.setStatus(FlowableUtils.getProcessInstanceStatus(processInstance));
|
||||||
respVO.setFormVariables(FlowableUtils.filterProcessInstanceFormVariable(processInstance.getProcessVariables()));
|
respVO.setFormVariables(FlowableUtils.getProcessInstanceFormVariable(processInstance));
|
||||||
// definition
|
// definition
|
||||||
respVO.setProcessDefinition(BeanUtils.toBean(processDefinition, BpmProcessDefinitionRespVO.class));
|
respVO.setProcessDefinition(BeanUtils.toBean(processDefinition, BpmProcessDefinitionRespVO.class));
|
||||||
copyTo(processDefinitionExt, respVO.getProcessDefinition());
|
copyTo(processDefinitionExt, respVO.getProcessDefinition());
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
package cn.iocoder.yudao.module.bpm.dal.dataobject.definition;
|
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 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
|
* 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;
|
private Integer status;
|
||||||
/**
|
/**
|
||||||
|
@ -21,7 +21,7 @@ public interface BpmCategoryMapper extends BaseMapperX<BpmCategoryDO> {
|
|||||||
default PageResult<BpmCategoryDO> selectPage(BpmCategoryPageReqVO reqVO) {
|
default PageResult<BpmCategoryDO> selectPage(BpmCategoryPageReqVO reqVO) {
|
||||||
return selectPage(reqVO, new LambdaQueryWrapperX<BpmCategoryDO>()
|
return selectPage(reqVO, new LambdaQueryWrapperX<BpmCategoryDO>()
|
||||||
.likeIfPresent(BpmCategoryDO::getName, reqVO.getName())
|
.likeIfPresent(BpmCategoryDO::getName, reqVO.getName())
|
||||||
.eqIfPresent(BpmCategoryDO::getCode, reqVO.getCode())
|
.likeIfPresent(BpmCategoryDO::getCode, reqVO.getCode())
|
||||||
.eqIfPresent(BpmCategoryDO::getStatus, reqVO.getStatus())
|
.eqIfPresent(BpmCategoryDO::getStatus, reqVO.getStatus())
|
||||||
.betweenIfPresent(BpmCategoryDO::getCreateTime, reqVO.getCreateTime())
|
.betweenIfPresent(BpmCategoryDO::getCreateTime, reqVO.getCreateTime())
|
||||||
.orderByAsc(BpmCategoryDO::getSort));
|
.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.lang.Assert;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
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.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.AdminUserApi;
|
||||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.flowable.bpmn.model.BpmnModel;
|
import org.flowable.bpmn.model.BpmnModel;
|
||||||
import org.flowable.bpmn.model.FlowElement;
|
|
||||||
import org.flowable.bpmn.model.UserTask;
|
import org.flowable.bpmn.model.UserTask;
|
||||||
import org.flowable.engine.delegate.DelegateExecution;
|
import org.flowable.engine.delegate.DelegateExecution;
|
||||||
|
|
||||||
@ -60,9 +57,13 @@ public class BpmTaskCandidateInvoker {
|
|||||||
// 遍历所有的 UserTask,校验审批人配置
|
// 遍历所有的 UserTask,校验审批人配置
|
||||||
userTaskList.forEach(userTask -> {
|
userTaskList.forEach(userTask -> {
|
||||||
// 1. 非空校验
|
// 1. 非空校验
|
||||||
Integer strategy = parseCandidateStrategy(userTask);
|
Integer strategy = BpmnModelUtils.parseCandidateStrategy(userTask);
|
||||||
String param = parseCandidateParam(userTask);
|
String param = BpmnModelUtils.parseCandidateParam(userTask);
|
||||||
if (strategy == null || StrUtil.isBlank(param)) {
|
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());
|
throw exception(MODEL_DEPLOY_FAIL_TASK_CANDIDATE_NOT_CONFIG, userTask.getName());
|
||||||
}
|
}
|
||||||
// 2. 具体策略校验
|
// 2. 具体策略校验
|
||||||
@ -77,16 +78,8 @@ public class BpmTaskCandidateInvoker {
|
|||||||
* @return 用户编号集合
|
* @return 用户编号集合
|
||||||
*/
|
*/
|
||||||
public Set<Long> calculateUsers(DelegateExecution execution) {
|
public Set<Long> calculateUsers(DelegateExecution execution) {
|
||||||
// TODO 芋艿:这里需要重构
|
Integer strategy = BpmnModelUtils.parseCandidateStrategy(execution.getCurrentFlowElement());
|
||||||
// // 1. 先从提前选好的审批人中获取
|
String param = BpmnModelUtils.parseCandidateParam(execution.getCurrentFlowElement());
|
||||||
// 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());
|
|
||||||
// 1.1 计算任务的候选人
|
// 1.1 计算任务的候选人
|
||||||
Set<Long> userIds = getCandidateStrategy(strategy).calculateUsers(execution, param);
|
Set<Long> userIds = getCandidateStrategy(strategy).calculateUsers(execution, param);
|
||||||
// 1.2 移除被禁用的用户
|
// 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) {
|
private BpmTaskCandidateStrategy getCandidateStrategy(Integer strategy) {
|
||||||
BpmTaskCandidateStrategyEnum strategyEnum = BpmTaskCandidateStrategyEnum.valueOf(strategy);
|
BpmTaskCandidateStrategyEnum strategyEnum = BpmTaskCandidateStrategyEnum.valueOf(strategy);
|
||||||
Assert.notNull(strategyEnum, "策略(%s) 不存在", strategy);
|
Assert.notNull(strategyEnum, "策略(%s) 不存在", strategy);
|
||||||
|
@ -36,4 +36,13 @@ public interface BpmTaskCandidateStrategy {
|
|||||||
*/
|
*/
|
||||||
Set<Long> calculateUsers(DelegateExecution execution, String param);
|
Set<Long> calculateUsers(DelegateExecution execution, String param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否一定要输入参数
|
||||||
|
*
|
||||||
|
* @return 是否
|
||||||
|
*/
|
||||||
|
default boolean isParamRequired() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -32,12 +32,12 @@ public class BpmTaskAssignLeaderExpression {
|
|||||||
private DeptApi deptApi;
|
private DeptApi deptApi;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private BpmProcessInstanceService bpmProcessInstanceService;
|
private BpmProcessInstanceService processInstanceService;
|
||||||
|
|
||||||
protected Set<Long> calculateUsers(DelegateExecution execution, int level) {
|
protected Set<Long> calculateUsers(DelegateExecution execution, int level) {
|
||||||
Assert.isTrue(level > 0, "level 必须大于 0");
|
Assert.isTrue(level > 0, "level 必须大于 0");
|
||||||
// 获得发起人
|
// 获得发起人
|
||||||
ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(execution.getProcessInstanceId());
|
ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getProcessInstanceId());
|
||||||
Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
|
Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
|
||||||
// 获得对应 leve 的部门
|
// 获得对应 leve 的部门
|
||||||
DeptRespDTO dept = null;
|
DeptRespDTO dept = null;
|
||||||
|
@ -19,10 +19,10 @@ import java.util.Set;
|
|||||||
public class BpmTaskAssignStartUserExpression {
|
public class BpmTaskAssignStartUserExpression {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private BpmProcessInstanceService bpmProcessInstanceService;
|
private BpmProcessInstanceService processInstanceService;
|
||||||
|
|
||||||
public Set<Long> calculateUsers(DelegateExecution execution) {
|
public Set<Long> calculateUsers(DelegateExecution execution) {
|
||||||
ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(execution.getProcessInstanceId());
|
ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getProcessInstanceId());
|
||||||
Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
|
Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId());
|
||||||
return SetUtils.asSet(startUserId);
|
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()
|
* @see ProcessInstance#getProcessVariables()
|
||||||
*/
|
*/
|
||||||
public static final String PROCESS_INSTANCE_VARIABLE_STATUS = "PROCESS_STATUS";
|
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, "部门的负责人"),
|
DEPT_LEADER(21, "部门的负责人"),
|
||||||
POST(22, "岗位"),
|
POST(22, "岗位"),
|
||||||
USER(30, "用户"),
|
USER(30, "用户"),
|
||||||
|
START_USER_SELECT(35, "发起人自选"), // 申请人自己,可在提交申请时选择此节点的审批人
|
||||||
USER_GROUP(40, "用户组"),
|
USER_GROUP(40, "用户组"),
|
||||||
EXPRESSION(60, "流程表达式"), // 表达式 ExpressionManager
|
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.collection.CollUtil;
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
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.converter.BpmnXMLConverter;
|
||||||
import org.flowable.bpmn.model.Process;
|
import org.flowable.bpmn.model.Process;
|
||||||
import org.flowable.bpmn.model.*;
|
import org.flowable.bpmn.model.*;
|
||||||
@ -14,6 +16,16 @@ import java.util.*;
|
|||||||
*/
|
*/
|
||||||
public class BpmnModelUtils {
|
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);
|
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 org.flowable.task.api.TaskInfo;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -79,7 +80,7 @@ public class FlowableUtils {
|
|||||||
* @param processInstance 流程实例
|
* @param processInstance 流程实例
|
||||||
* @return 表单
|
* @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());
|
Map<String, Object> formVariables = new HashMap<>(processInstance.getProcessVariables());
|
||||||
filterProcessInstanceFormVariable(formVariables);
|
filterProcessInstanceFormVariable(formVariables);
|
||||||
return formVariables;
|
return formVariables;
|
||||||
@ -98,6 +99,18 @@ public class FlowableUtils {
|
|||||||
return processVariables;
|
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 相关的工具方法 ==========
|
// ========== Task 相关的工具方法 ==========
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,7 +33,7 @@ public class BpmFormServiceImpl implements BpmFormService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long createForm(BpmFormSaveReqVO createReqVO) {
|
public Long createForm(BpmFormSaveReqVO createReqVO) {
|
||||||
this.vadateFields(createReqVO.getFields());
|
this.validateFields(createReqVO.getFields());
|
||||||
// 插入
|
// 插入
|
||||||
BpmFormDO form = BeanUtils.toBean(createReqVO, BpmFormDO.class);
|
BpmFormDO form = BeanUtils.toBean(createReqVO, BpmFormDO.class);
|
||||||
formMapper.insert(form);
|
formMapper.insert(form);
|
||||||
@ -43,7 +43,7 @@ public class BpmFormServiceImpl implements BpmFormService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateForm(BpmFormSaveReqVO updateReqVO) {
|
public void updateForm(BpmFormSaveReqVO updateReqVO) {
|
||||||
vadateFields(updateReqVO.getFields());
|
validateFields(updateReqVO.getFields());
|
||||||
// 校验存在
|
// 校验存在
|
||||||
validateFormExists(updateReqVO.getId());
|
validateFormExists(updateReqVO.getId());
|
||||||
// 更新
|
// 更新
|
||||||
@ -93,7 +93,7 @@ public class BpmFormServiceImpl implements BpmFormService {
|
|||||||
*
|
*
|
||||||
* @param fields field 数组
|
* @param fields field 数组
|
||||||
*/
|
*/
|
||||||
private void vadateFields(List<String> fields) {
|
private void validateFields(List<String> fields) {
|
||||||
if (true) { // TODO 芋艿:兼容 Vue3 工作流:因为采用了新的表单设计器,所以暂时不校验
|
if (true) { // TODO 芋艿:兼容 Vue3 工作流:因为采用了新的表单设计器,所以暂时不校验
|
||||||
return;
|
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.BpmFormDO;
|
||||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
|
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
|
||||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
|
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.Deployment;
|
||||||
import org.flowable.engine.repository.Model;
|
import org.flowable.engine.repository.Model;
|
||||||
import org.flowable.engine.repository.ProcessDefinition;
|
import org.flowable.engine.repository.ProcessDefinition;
|
||||||
@ -61,12 +62,12 @@ public interface BpmProcessDefinitionService {
|
|||||||
void updateProcessDefinitionState(String id, Integer state);
|
void updateProcessDefinitionState(String id, Integer state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得流程定义对应的 BPMN XML
|
* 获得流程定义对应的 BPMN
|
||||||
*
|
*
|
||||||
* @param id 流程定义编号
|
* @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 流程定义
|
* @return 流程定义
|
||||||
*/
|
*/
|
||||||
ProcessDefinition getProcessDefinition(String id);
|
ProcessDefinition getProcessDefinition(String id);
|
||||||
@ -139,7 +140,7 @@ public interface BpmProcessDefinitionService {
|
|||||||
* @return 流程部署 Map
|
* @return 流程部署 Map
|
||||||
*/
|
*/
|
||||||
default Map<String, Deployment> getDeploymentMap(Set<String> ids) {
|
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 部署编号的数组
|
* @param ids 部署编号的数组
|
||||||
* @return 流程部署的数组
|
* @return 流程部署的数组
|
||||||
*/
|
*/
|
||||||
List<Deployment> getDeployments(Set<String> ids);
|
List<Deployment> getDeploymentList(Set<String> ids);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得 id 对应的 Deployment
|
* 获得 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 cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.flowable.bpmn.converter.BpmnXMLConverter;
|
|
||||||
import org.flowable.bpmn.model.BpmnModel;
|
import org.flowable.bpmn.model.BpmnModel;
|
||||||
import org.flowable.common.engine.impl.db.SuspensionState;
|
import org.flowable.common.engine.impl.db.SuspensionState;
|
||||||
import org.flowable.engine.RepositoryService;
|
import org.flowable.engine.RepositoryService;
|
||||||
@ -84,7 +83,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Deployment> getDeployments(Set<String> ids) {
|
public List<Deployment> getDeploymentList(Set<String> ids) {
|
||||||
if (CollUtil.isEmpty(ids)) {
|
if (CollUtil.isEmpty(ids)) {
|
||||||
return emptyList();
|
return emptyList();
|
||||||
}
|
}
|
||||||
@ -156,13 +155,8 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getProcessDefinitionBpmnXML(String id) {
|
public BpmnModel getProcessDefinitionBpmnModel(String id) {
|
||||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(id);
|
return repositoryService.getBpmnModel(id);
|
||||||
if (bpmnModel == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
BpmnXMLConverter converter = new BpmnXMLConverter();
|
|
||||||
return StrUtil.utf8Str(converter.convertToXML(bpmnModel));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -56,7 +56,8 @@ public class BpmOALeaveServiceImpl implements BpmOALeaveService {
|
|||||||
processInstanceVariables.put("day", day);
|
processInstanceVariables.put("day", day);
|
||||||
String processInstanceId = processInstanceApi.createProcessInstance(userId,
|
String processInstanceId = processInstanceApi.createProcessInstance(userId,
|
||||||
new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
|
new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
|
||||||
.setVariables(processInstanceVariables).setBusinessKey(String.valueOf(leave.getId())));
|
.setVariables(processInstanceVariables).setBusinessKey(String.valueOf(leave.getId()))
|
||||||
|
.setStartUserSelectAssignees(createReqVO.getStartUserSelectAssignees()));
|
||||||
|
|
||||||
// 将工作流的编号,更新到 OA 请假单中
|
// 将工作流的编号,更新到 OA 请假单中
|
||||||
leaveMapper.updateById(new BpmOALeaveDO().setId(leave.getId()).setProcessInstanceId(processInstanceId));
|
leaveMapper.updateById(new BpmOALeaveDO().setId(leave.getId()).setProcessInstanceId(processInstanceId));
|
||||||
|
@ -49,17 +49,6 @@ public interface BpmProcessInstanceService {
|
|||||||
return convertMap(getProcessInstances(ids), ProcessInstance::getProcessInstanceId);
|
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);
|
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;
|
private AdminUserApi adminUserApi;
|
||||||
@Mock
|
@Mock
|
||||||
private DeptApi deptApi;
|
private DeptApi deptApi;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private BpmProcessInstanceService bpmProcessInstanceService;
|
private BpmProcessInstanceService processInstanceService;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCalculateUsers_noDept() {
|
public void testCalculateUsers_noDept() {
|
||||||
@ -96,7 +97,7 @@ public class BpmTaskAssignLeaderExpressionTest extends BaseMockitoUnitTest {
|
|||||||
// mock 返回 startUserId
|
// mock 返回 startUserId
|
||||||
ExecutionEntityImpl processInstance = new ExecutionEntityImpl();
|
ExecutionEntityImpl processInstance = new ExecutionEntityImpl();
|
||||||
processInstance.setStartUserId(String.valueOf(startUserId));
|
processInstance.setStartUserId(String.valueOf(startUserId));
|
||||||
when(bpmProcessInstanceService.getProcessInstance(eq(execution.getProcessInstanceId())))
|
when(processInstanceService.getProcessInstance(eq(execution.getProcessInstanceId())))
|
||||||
.thenReturn(processInstance);
|
.thenReturn(processInstance);
|
||||||
return execution;
|
return execution;
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,24 @@
|
|||||||
package cn.iocoder.yudao.module.bpm.service.category;
|
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.BpmCategoryPageReqVO;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.category.BpmCategorySaveReqVO;
|
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.dataobject.definition.BpmCategoryDO;
|
||||||
import cn.iocoder.yudao.module.bpm.dal.mysql.category.BpmCategoryMapper;
|
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 org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
|
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
|
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.test.core.util.RandomUtils.*;
|
||||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
|
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.CATEGORY_NOT_EXISTS;
|
||||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,7 +38,8 @@ public class BpmCategoryServiceImplTest extends BaseDbUnitTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testCreateCategory_success() {
|
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);
|
Long categoryId = categoryService.createCategory(createReqVO);
|
||||||
@ -59,6 +58,7 @@ public class BpmCategoryServiceImplTest extends BaseDbUnitTest {
|
|||||||
// 准备参数
|
// 准备参数
|
||||||
BpmCategorySaveReqVO updateReqVO = randomPojo(BpmCategorySaveReqVO.class, o -> {
|
BpmCategorySaveReqVO updateReqVO = randomPojo(BpmCategorySaveReqVO.class, o -> {
|
||||||
o.setId(dbCategory.getId()); // 设置更新的 ID
|
o.setId(dbCategory.getId()); // 设置更新的 ID
|
||||||
|
o.setStatus(randomCommonStatus());
|
||||||
});
|
});
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
@ -101,29 +101,28 @@ public class BpmCategoryServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
|
|
||||||
public void testGetCategoryPage() {
|
public void testGetCategoryPage() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
BpmCategoryDO dbCategory = randomPojo(BpmCategoryDO.class, o -> { // 等会查询到
|
BpmCategoryDO dbCategory = randomPojo(BpmCategoryDO.class, o -> { // 等会查询到
|
||||||
o.setName(null);
|
o.setName("芋头");
|
||||||
o.setCode(null);
|
o.setCode("xiaodun");
|
||||||
o.setStatus(null);
|
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
o.setCreateTime(null);
|
o.setCreateTime(buildTime(2023, 2, 2));
|
||||||
});
|
});
|
||||||
categoryMapper.insert(dbCategory);
|
categoryMapper.insert(dbCategory);
|
||||||
// 测试 name 不匹配
|
// 测试 name 不匹配
|
||||||
categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setName(null)));
|
categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setName("小盾")));
|
||||||
// 测试 code 不匹配
|
// 测试 code 不匹配
|
||||||
categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setCode(null)));
|
categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setCode("tudou")));
|
||||||
// 测试 status 不匹配
|
// 测试 status 不匹配
|
||||||
categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setStatus(null)));
|
categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
|
||||||
// 测试 createTime 不匹配
|
// 测试 createTime 不匹配
|
||||||
categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setCreateTime(null)));
|
categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setCreateTime(buildTime(2024, 2, 2))));
|
||||||
// 准备参数
|
// 准备参数
|
||||||
BpmCategoryPageReqVO reqVO = new BpmCategoryPageReqVO();
|
BpmCategoryPageReqVO reqVO = new BpmCategoryPageReqVO();
|
||||||
reqVO.setName(null);
|
reqVO.setName("芋");
|
||||||
reqVO.setCode(null);
|
reqVO.setCode("xiao");
|
||||||
reqVO.setStatus(null);
|
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
|
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.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.BpmFormSaveReqVO;
|
||||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormPageReqVO;
|
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.dataobject.definition.BpmFormDO;
|
||||||
import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmFormMapper;
|
import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmFormMapper;
|
||||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmFormFieldRespDTO;
|
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmFormFieldRespDTO;
|
||||||
@ -66,7 +65,7 @@ public class BpmFormServiceTest extends BaseDbUnitTest {
|
|||||||
});
|
});
|
||||||
formMapper.insert(dbForm);// @Sql: 先插入出一条存在的数据
|
formMapper.insert(dbForm);// @Sql: 先插入出一条存在的数据
|
||||||
// 准备参数
|
// 准备参数
|
||||||
BpmFormUpdateReqVO reqVO = randomPojo(BpmFormUpdateReqVO.class, o -> {
|
BpmFormSaveReqVO reqVO = randomPojo(BpmFormSaveReqVO.class, o -> {
|
||||||
o.setId(dbForm.getId()); // 设置更新的 ID
|
o.setId(dbForm.getId()); // 设置更新的 ID
|
||||||
o.setConf("{'yudao': 'yuanma'}");
|
o.setConf("{'yudao': 'yuanma'}");
|
||||||
o.setFields(randomFields());
|
o.setFields(randomFields());
|
||||||
@ -82,7 +81,7 @@ public class BpmFormServiceTest extends BaseDbUnitTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testUpdateForm_notExists() {
|
public void testUpdateForm_notExists() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
BpmFormUpdateReqVO reqVO = randomPojo(BpmFormUpdateReqVO.class, o -> {
|
BpmFormSaveReqVO reqVO = randomPojo(BpmFormSaveReqVO.class, o -> {
|
||||||
o.setConf("{'yudao': 'yuanma'}");
|
o.setConf("{'yudao': 'yuanma'}");
|
||||||
o.setFields(randomFields());
|
o.setFields(randomFields());
|
||||||
});
|
});
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
DELETE FROM "bpm_form";
|
DELETE FROM "bpm_form";
|
||||||
DELETE FROM "bpm_user_group";
|
DELETE FROM "bpm_user_group";
|
||||||
|
DELETE FROM "bpm_category";
|
||||||
|
@ -12,6 +12,21 @@ CREATE TABLE IF NOT EXISTS "bpm_user_group" (
|
|||||||
PRIMARY KEY ("id")
|
PRIMARY KEY ("id")
|
||||||
) COMMENT '用户组';
|
) 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" (
|
CREATE TABLE IF NOT EXISTS "bpm_form" (
|
||||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||||
"name" varchar(63) NOT NULL,
|
"name" varchar(63) NOT NULL,
|
||||||
|
Loading…
Reference in New Issue
Block a user