Compare commits
5 Commits
master
...
feature/fl
Author | SHA1 | Date |
---|---|---|
jason | d692e553ea | |
jason | 9f46199479 | |
jason | 8bbf94705f | |
jason | 948503aabd | |
jason | f3d61216f4 |
|
@ -1,10 +1,10 @@
|
|||
package cn.iocoder.yudao.module.bpm.controller.admin.definition;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
|
@ -32,7 +32,7 @@ public class BpmTaskAssignRuleController {
|
|||
@ApiOperation(value = "获得任务分配规则列表")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "modelId", value = "模型编号", example = "1024", dataTypeClass = String.class),
|
||||
@ApiImplicitParam(name = "processDefinitionId", value = "刘晨定义的编号", example = "2048", dataTypeClass = String.class)
|
||||
@ApiImplicitParam(name = "processDefinitionId", value = "流程定义的编号", example = "2048", dataTypeClass = String.class)
|
||||
})
|
||||
@PreAuthorize("@ss.hasPermission('bpm:task-assign-rule:query')")
|
||||
public CommonResult<List<BpmTaskAssignRuleRespVO>> getTaskAssignRuleList(
|
|
@ -88,4 +88,12 @@ public interface BpmFormService {
|
|||
*/
|
||||
PageResult<BpmFormDO> getFormPage(BpmFormPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 校验流程表单已配置
|
||||
*
|
||||
* @param configStr configStr 字段
|
||||
* @return 流程表单
|
||||
*/
|
||||
BpmFormDO checkFormConfig(String configStr);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cn.iocoder.yudao.module.bpm.service.definition;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormPageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormUpdateReqVO;
|
||||
|
@ -8,18 +9,20 @@ import cn.iocoder.yudao.module.bpm.convert.definition.BpmFormConvert;
|
|||
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.enums.ErrorCodeConstants;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmFormFieldRespDTO;
|
||||
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* 动态表单 Service 实现类
|
||||
|
@ -87,6 +90,29 @@ public class BpmFormServiceImpl implements BpmFormService {
|
|||
return formMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BpmFormDO checkFormConfig(String configStr) {
|
||||
BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(configStr, BpmModelMetaInfoRespDTO.class);
|
||||
if (metaInfo == null || metaInfo.getFormType() == null) {
|
||||
throw exception(MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG);
|
||||
}
|
||||
// 校验表单存在
|
||||
if (Objects.equals(metaInfo.getFormType(), BpmModelFormTypeEnum.NORMAL.getType())) {
|
||||
BpmFormDO form = getForm(metaInfo.getFormId());
|
||||
if (form == null) {
|
||||
throw exception(FORM_NOT_EXISTS);
|
||||
}
|
||||
return form;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void checkKeyNCName(String key) {
|
||||
if (!ValidationUtils.isXmlNCName(key)) {
|
||||
throw exception(MODEL_KEY_VALID);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 校验 Field,避免 field 重复
|
||||
*
|
||||
|
|
|
@ -76,4 +76,12 @@ public interface BpmTaskAssignRuleService {
|
|||
*/
|
||||
void copyTaskAssignRules(String fromModelId, String toProcessDefinitionId);
|
||||
|
||||
/**
|
||||
* 校验流程模型的任务分配规则全部都配置了
|
||||
* 目的:如果有规则未配置,会导致流程任务找不到负责人,进而流程无法进行下去!
|
||||
*
|
||||
* @param id 流程模型编号
|
||||
*/
|
||||
void checkTaskAssignRuleAllConfig(String id);
|
||||
|
||||
}
|
|
@ -5,7 +5,7 @@ import lombok.Data;
|
|||
|
||||
/**
|
||||
* BPM 流程 MetaInfo Response DTO
|
||||
* 主要用于 {@link org.activiti.engine.repository.Model#setMetaInfo(String)} 的存储
|
||||
* 主要用于 { Model#setMetaInfo(String)} 的存储
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
|
@ -21,7 +21,7 @@ public class BpmMessageSendWhenTaskCreatedReqDTO {
|
|||
*/
|
||||
@NotEmpty(message = "流程实例的名字不能为空")
|
||||
private String processInstanceName;
|
||||
@NotEmpty(message = "发起人的用户编号")
|
||||
@NotNull(message = "发起人的用户编号")
|
||||
private Long startUserId;
|
||||
@NotEmpty(message = "发起人的昵称")
|
||||
private String startUserNickname;
|
||||
|
|
|
@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.bpm.convert.definition;
|
|||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
|
||||
import org.activiti.engine.impl.persistence.entity.SuspensionState;
|
||||
import org.activiti.engine.repository.Deployment;
|
||||
import org.activiti.engine.repository.Model;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package cn.iocoder.yudao.module.bpm.convert.definition;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import org.activiti.engine.impl.persistence.entity.SuspensionState;
|
||||
import org.activiti.engine.repository.Deployment;
|
||||
import org.activiti.engine.repository.ProcessDefinition;
|
||||
|
|
|
@ -12,7 +12,6 @@ import javax.validation.Valid;
|
|||
* @author yunlongn
|
||||
*/
|
||||
public interface BpmModelService {
|
||||
|
||||
/**
|
||||
* 获得流程模型分页
|
||||
*
|
||||
|
@ -21,14 +20,6 @@ public interface BpmModelService {
|
|||
*/
|
||||
PageResult<BpmModelPageItemRespVO> getModelPage(BpmModelPageReqVO pageVO);
|
||||
|
||||
/**
|
||||
* 获得流程模块
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 流程模型
|
||||
*/
|
||||
BpmModelRespVO getModel(String id);
|
||||
|
||||
/**
|
||||
* 创建流程模型
|
||||
*
|
||||
|
@ -38,6 +29,14 @@ public interface BpmModelService {
|
|||
*/
|
||||
String createModel(@Valid BpmModelCreateReqVO modelVO, String bpmnXml);
|
||||
|
||||
/**
|
||||
* 获得流程模块
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 流程模型
|
||||
*/
|
||||
BpmModelRespVO getModel(String id);
|
||||
|
||||
/**
|
||||
* 修改流程模型
|
||||
*
|
||||
|
@ -63,7 +62,7 @@ public interface BpmModelService {
|
|||
* 修改模型的状态,实际更新的部署的流程定义的状态
|
||||
*
|
||||
* @param id 编号
|
||||
* @param state 状态 {@link org.activiti.engine.impl.persistence.entity.SuspensionState}
|
||||
* @param state 状态
|
||||
*/
|
||||
void updateModelState(String id, Integer state);
|
||||
|
||||
|
|
|
@ -3,19 +3,19 @@ package cn.iocoder.yudao.module.bpm.service.definition;
|
|||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
|
||||
import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
|
||||
import cn.iocoder.yudao.framework.activiti.core.util.ActivitiUtils;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.PageUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.activiti.bpmn.model.BpmnModel;
|
||||
import org.activiti.engine.RepositoryService;
|
||||
|
@ -47,16 +47,15 @@ import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
|
|||
@Service
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class BpmModelServiceImpl implements BpmModelService {
|
||||
public class BpmModelServiceImpl implements BpmModelService {
|
||||
|
||||
@Resource
|
||||
private RepositoryService repositoryService;
|
||||
@Resource
|
||||
private BpmFormService bpmFormService;
|
||||
@Resource
|
||||
private BpmProcessDefinitionService processDefinitionService;
|
||||
@Resource
|
||||
@Lazy // 解决循环依赖
|
||||
private BpmFormService bpmFormService;
|
||||
@Resource
|
||||
private BpmTaskAssignRuleService taskAssignRuleService;
|
||||
|
||||
@Override
|
||||
|
@ -167,9 +166,9 @@ public class BpmModelServiceImpl implements BpmModelService {
|
|||
}
|
||||
// TODO 芋艿:校验流程图的有效性;例如说,是否有开始的元素,是否有结束的元素;
|
||||
// 校验表单已配
|
||||
BpmFormDO form = checkFormConfig(model);
|
||||
BpmFormDO form = checkFormConfig(model.getMetaInfo());
|
||||
// 校验任务分配规则已配置
|
||||
checkTaskAssignRuleAllConfig(id);
|
||||
taskAssignRuleService.checkTaskAssignRuleAllConfig(id);
|
||||
|
||||
// 校验模型是否发生修改。如果未修改,则不允许创建
|
||||
BpmProcessDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form).setBpmnBytes(bpmnBytes);
|
||||
|
@ -194,48 +193,6 @@ public class BpmModelServiceImpl implements BpmModelService {
|
|||
taskAssignRuleService.copyTaskAssignRules(id, definition.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验流程模型的任务分配规则全部都配置了
|
||||
* 目的:如果有规则未配置,会导致流程任务找不到负责人,进而流程无法进行下去!
|
||||
*
|
||||
* @param id 流程模型编号
|
||||
*/
|
||||
private void checkTaskAssignRuleAllConfig(String id) {
|
||||
// 一个用户任务都没配置,所以无需配置规则
|
||||
List<BpmTaskAssignRuleRespVO> taskAssignRules = taskAssignRuleService.getTaskAssignRuleList(id, null);
|
||||
if (CollUtil.isEmpty(taskAssignRules)) {
|
||||
return;
|
||||
}
|
||||
// 校验未配置规则的任务
|
||||
taskAssignRules.forEach(rule -> {
|
||||
if (CollUtil.isEmpty(rule.getOptions())) {
|
||||
throw exception(MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG, rule.getTaskDefinitionName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验流程表单已配置
|
||||
*
|
||||
* @param model 流程模型
|
||||
* @return 流程表单
|
||||
*/
|
||||
private BpmFormDO checkFormConfig(Model model) {
|
||||
BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
|
||||
if (metaInfo == null || metaInfo.getFormType() == null) {
|
||||
throw exception(MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG);
|
||||
}
|
||||
// 校验表单存在
|
||||
if (Objects.equals(metaInfo.getFormType(), BpmModelFormTypeEnum.NORMAL.getType())) {
|
||||
BpmFormDO form = bpmFormService.getForm(metaInfo.getFormId());
|
||||
if (form == null) {
|
||||
throw exception(FORM_NOT_EXISTS);
|
||||
}
|
||||
return form;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteModel(String id) {
|
||||
|
@ -297,4 +254,26 @@ public class BpmModelServiceImpl implements BpmModelService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验流程表单已配置
|
||||
*
|
||||
* @param metaInfoStr 流程模型 metaInfo 字段
|
||||
* @return 流程表单
|
||||
*/
|
||||
private BpmFormDO checkFormConfig(String metaInfoStr) {
|
||||
BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(metaInfoStr, BpmModelMetaInfoRespDTO.class);
|
||||
if (metaInfo == null || metaInfo.getFormType() == null) {
|
||||
throw exception(MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG);
|
||||
}
|
||||
// 校验表单存在
|
||||
if (Objects.equals(metaInfo.getFormType(), BpmModelFormTypeEnum.NORMAL.getType())) {
|
||||
BpmFormDO form = bpmFormService.getForm(metaInfo.getFormId());
|
||||
if (form == null) {
|
||||
throw exception(FORM_NOT_EXISTS);
|
||||
}
|
||||
return form;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmPro
|
|||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
|
||||
import org.activiti.bpmn.model.BpmnModel;
|
||||
import org.activiti.engine.repository.Deployment;
|
||||
import org.activiti.engine.repository.ProcessDefinition;
|
||||
|
@ -35,12 +35,20 @@ public interface BpmProcessDefinitionService {
|
|||
PageResult<BpmProcessDefinitionPageItemRespVO> getProcessDefinitionPage(BpmProcessDefinitionPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 获得流程定义列表
|
||||
* 创建流程定义
|
||||
*
|
||||
* @param listReqVO 列表入参
|
||||
* @return 流程定义列表
|
||||
* @param createReqDTO 创建信息
|
||||
* @return 流程编号
|
||||
*/
|
||||
List<BpmProcessDefinitionRespVO> getProcessDefinitionList(BpmProcessDefinitionListReqVO listReqVO);
|
||||
String createProcessDefinition(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
|
||||
|
||||
/**
|
||||
* 更新流程定义状态
|
||||
*
|
||||
* @param id 流程定义的编号
|
||||
* @param state 状态
|
||||
*/
|
||||
void updateProcessDefinitionState(String id, Integer state);
|
||||
|
||||
/**
|
||||
* 获得流程定义对应的 BPMN XML
|
||||
|
@ -50,6 +58,30 @@ public interface BpmProcessDefinitionService {
|
|||
*/
|
||||
String getProcessDefinitionBpmnXML(String id);
|
||||
|
||||
/**
|
||||
* 获得需要创建的流程定义,是否和当前激活的流程定义相等
|
||||
*
|
||||
* @param createReqDTO 创建信息
|
||||
* @return 是否相等
|
||||
*/
|
||||
boolean isProcessDefinitionEquals(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
|
||||
|
||||
/**
|
||||
* 获得编号对应的 BpmProcessDefinitionExtDO
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 流程定义拓展
|
||||
*/
|
||||
BpmProcessDefinitionExtDO getProcessDefinitionExt(String id);
|
||||
|
||||
/**
|
||||
* 获得流程定义列表
|
||||
*
|
||||
* @param listReqVO 列表入参
|
||||
* @return 流程定义列表
|
||||
*/
|
||||
List<BpmProcessDefinitionRespVO> getProcessDefinitionList(BpmProcessDefinitionListReqVO listReqVO);
|
||||
|
||||
/**
|
||||
* 获得 Bpmn 模型
|
||||
*
|
||||
|
@ -84,14 +116,6 @@ public interface BpmProcessDefinitionService {
|
|||
*/
|
||||
ProcessDefinition getActiveProcessDefinition(String key);
|
||||
|
||||
/**
|
||||
* 获得编号对应的 BpmProcessDefinitionExtDO
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 流程定义拓展
|
||||
*/
|
||||
BpmProcessDefinitionExtDO getProcessDefinitionExt(String id);
|
||||
|
||||
/**
|
||||
* 获得 id 对应的 Deployment
|
||||
*
|
||||
|
@ -134,28 +158,4 @@ public interface BpmProcessDefinitionService {
|
|||
*/
|
||||
List<ProcessDefinition> getProcessDefinitionListByDeploymentIds(Set<String> deploymentIds);
|
||||
|
||||
/**
|
||||
* 获得需要创建的流程定义,是否和当前激活的流程定义相等
|
||||
*
|
||||
* @param createReqDTO 创建信息
|
||||
* @return 是否相等
|
||||
*/
|
||||
boolean isProcessDefinitionEquals(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
|
||||
|
||||
/**
|
||||
* 创建流程定义
|
||||
*
|
||||
* @param createReqDTO 创建信息
|
||||
* @return 流程编号
|
||||
*/
|
||||
String createProcessDefinition(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
|
||||
|
||||
/**
|
||||
* 更新流程定义的挂起状态
|
||||
*
|
||||
* @param id 流程定义的编号
|
||||
* @param state 挂起状态 {@link org.activiti.engine.impl.persistence.entity.SuspensionState}
|
||||
*/
|
||||
void updateProcessDefinitionState(String id, Integer state);
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
|
|||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.module.bpm.convert.definition.BpmProcessDefinitionConvert;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
|
||||
import cn.iocoder.yudao.framework.activiti.core.util.ActivitiUtils;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.PageUtils;
|
||||
|
@ -15,6 +14,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.BpmProcessDefinitionExtDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmProcessDefinitionExtMapper;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.activiti.bpmn.model.BpmnModel;
|
||||
import org.activiti.engine.RepositoryService;
|
||||
|
|
|
@ -173,6 +173,21 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
|
|||
taskRuleMapper.insertBatch(newRules);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkTaskAssignRuleAllConfig(String id) {
|
||||
// 一个用户任务都没配置,所以无需配置规则
|
||||
List<BpmTaskAssignRuleRespVO> taskAssignRules = getTaskAssignRuleList(id, null);
|
||||
if (CollUtil.isEmpty(taskAssignRules)) {
|
||||
return;
|
||||
}
|
||||
// 校验未配置规则的任务
|
||||
taskAssignRules.forEach(rule -> {
|
||||
if (CollUtil.isEmpty(rule.getOptions())) {
|
||||
throw exception(MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG, rule.getTaskDefinitionName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void validTaskAssignRuleOptions(Integer type, Set<Long> options) {
|
||||
if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.ROLE.getType())) {
|
||||
roleApi.validRoles(options);
|
||||
|
|
|
@ -16,6 +16,11 @@
|
|||
</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-bpm-base</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<!-- 工作流相关 -->
|
||||
<dependency>
|
||||
<groupId>org.flowable</groupId>
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* bpm API 实现类,定义暴露给其它模块的 API
|
||||
*/
|
||||
package cn.iocoder.yudao.module.bpm.api;
|
|
@ -0,0 +1,24 @@
|
|||
package cn.iocoder.yudao.module.bpm.api.task;
|
||||
|
||||
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
/**
|
||||
* Flowable 流程实例 Api 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
* @author jason
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class FlowableProcessInstanceApiImpl implements BpmProcessInstanceApi {
|
||||
|
||||
@Override
|
||||
public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO reqDTO) {
|
||||
//TODO
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package cn.iocoder.yudao.module.bpm.controller.admin.definition;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.io.IoUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
|
||||
import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Api(tags = "管理后台 - 流程模型")
|
||||
@RestController
|
||||
@RequestMapping("/bpm/model")
|
||||
@Validated
|
||||
public class BpmModelController {
|
||||
|
||||
@Resource
|
||||
private BpmModelService modelService;
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation(value = "获得模型分页")
|
||||
public CommonResult<PageResult<BpmModelPageItemRespVO>> getModelPage(BpmModelPageReqVO pageVO) {
|
||||
return success(modelService.getModelPage(pageVO));
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@ApiOperation("获得模型")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = String.class)
|
||||
@PreAuthorize("@ss.hasPermission('bpm:model:query')")
|
||||
public CommonResult<BpmModelRespVO> getModel(@RequestParam("id") String id) {
|
||||
BpmModelRespVO model = modelService.getModel(id);
|
||||
return success(model);
|
||||
}
|
||||
|
||||
@PostMapping("/create")
|
||||
@ApiOperation(value = "新建模型")
|
||||
@PreAuthorize("@ss.hasPermission('bpm:model:create')")
|
||||
public CommonResult<String> createModel(@Valid @RequestBody BpmModelCreateReqVO createRetVO) {
|
||||
return success(modelService.createModel(createRetVO, null));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@ApiOperation(value = "修改模型")
|
||||
@PreAuthorize("@ss.hasPermission('bpm:model:update')")
|
||||
public CommonResult<Boolean> updateModel(@Valid @RequestBody BpmModelUpdateReqVO modelVO) {
|
||||
modelService.updateModel(modelVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PostMapping("/import")
|
||||
@ApiOperation(value = "导入模型")
|
||||
public CommonResult<String> importModel(@Valid BpmModeImportReqVO importReqVO) throws IOException {
|
||||
BpmModelCreateReqVO createReqVO = BpmModelConvert.INSTANCE.convert(importReqVO);
|
||||
// 读取文件
|
||||
String bpmnXml = IoUtils.readUtf8(importReqVO.getBpmnFile().getInputStream(), false);
|
||||
return success(modelService.createModel(createReqVO, bpmnXml));
|
||||
}
|
||||
|
||||
@PostMapping("/deploy")
|
||||
@ApiOperation(value = "部署模型")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = String.class)
|
||||
@PreAuthorize("@ss.hasPermission('bpm:model:deploy')")
|
||||
public CommonResult<Boolean> deployModel(@RequestParam("id") String id) {
|
||||
modelService.deployModel(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/update-state")
|
||||
@ApiOperation(value = "修改模型的状态", notes = "实际更新的部署的流程定义的状态")
|
||||
@PreAuthorize("@ss.hasPermission('bpm:model:update')")
|
||||
public CommonResult<Boolean> updateModelState(@Valid @RequestBody BpmModelUpdateStateReqVO reqVO) {
|
||||
modelService.updateModelState(reqVO.getId(), reqVO.getState());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@ApiOperation("删除模型")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = String.class)
|
||||
@PreAuthorize("@ss.hasPermission('bpm:model:delete')")
|
||||
public CommonResult<Boolean> deleteModel(@RequestParam("id") String id) {
|
||||
modelService.deleteModel(id);
|
||||
return success(true);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package cn.iocoder.yudao.module.bpm.controller.admin.definition;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Api(tags = "管理后台 - 流程定义")
|
||||
@RestController
|
||||
@RequestMapping("/bpm/process-definition")
|
||||
@Validated
|
||||
public class BpmProcessDefinitionController {
|
||||
|
||||
@Resource
|
||||
private BpmProcessDefinitionService bpmDefinitionService;
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation(value = "获得流程定义分页")
|
||||
@PreAuthorize("@ss.hasPermission('bpm:process-definition:query')")
|
||||
public CommonResult<PageResult<BpmProcessDefinitionPageItemRespVO>> getProcessDefinitionPage(
|
||||
BpmProcessDefinitionPageReqVO pageReqVO) {
|
||||
return success(bpmDefinitionService.getProcessDefinitionPage(pageReqVO));
|
||||
}
|
||||
|
||||
@GetMapping ("/get-bpmn-xml")
|
||||
@ApiOperation(value = "获得流程定义的 BPMN XML")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = String.class)
|
||||
@PreAuthorize("@ss.hasPermission('bpm:process-definition:query')")
|
||||
public CommonResult<String> getProcessDefinitionBpmnXML(@RequestParam("id") String id) {
|
||||
String bpmnXML = bpmDefinitionService.getProcessDefinitionBpmnXML(id);
|
||||
return success(bpmnXML);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* 占位
|
||||
*/
|
||||
package cn.iocoder.yudao.module.bpm.controller.app;
|
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* 提供 RESTful API 给前端:
|
||||
* 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目
|
||||
* 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分
|
||||
*/
|
||||
package cn.iocoder.yudao.module.bpm.controller;
|
|
@ -0,0 +1,140 @@
|
|||
package cn.iocoder.yudao.module.bpm.convert.definition;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
|
||||
import org.flowable.common.engine.impl.db.SuspensionState;
|
||||
import org.flowable.engine.repository.Deployment;
|
||||
import org.flowable.engine.repository.Model;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MappingTarget;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 流程模型 Convert
|
||||
*
|
||||
* @author yunlongn
|
||||
*/
|
||||
@Mapper
|
||||
public interface BpmModelConvert {
|
||||
|
||||
BpmModelConvert INSTANCE = Mappers.getMapper(BpmModelConvert.class);
|
||||
|
||||
default List<BpmModelPageItemRespVO> convertList(List<Model> list, Map<Long, BpmFormDO> formMap,
|
||||
Map<String, Deployment> deploymentMap,
|
||||
Map<String, ProcessDefinition> processDefinitionMap) {
|
||||
return CollectionUtils.convertList(list, model -> {
|
||||
BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
|
||||
BpmFormDO form = metaInfo != null ? formMap.get(metaInfo.getFormId()) : null;
|
||||
Deployment deployment = model.getDeploymentId() != null ? deploymentMap.get(model.getDeploymentId()) : null;
|
||||
ProcessDefinition processDefinition = model.getDeploymentId() != null ? processDefinitionMap.get(model.getDeploymentId()) : null;
|
||||
return convert(model, form, deployment, processDefinition);
|
||||
});
|
||||
}
|
||||
|
||||
default BpmModelPageItemRespVO convert(Model model, BpmFormDO form, Deployment deployment, ProcessDefinition processDefinition) {
|
||||
BpmModelPageItemRespVO modelRespVO = new BpmModelPageItemRespVO();
|
||||
modelRespVO.setId(model.getId());
|
||||
modelRespVO.setCreateTime(model.getCreateTime());
|
||||
// 通用 copy
|
||||
copyTo(model, modelRespVO);
|
||||
// Form
|
||||
if (form != null) {
|
||||
modelRespVO.setFormId(form.getId());
|
||||
modelRespVO.setFormName(form.getName());
|
||||
}
|
||||
// ProcessDefinition
|
||||
modelRespVO.setProcessDefinition(this.convert(processDefinition));
|
||||
if (modelRespVO.getProcessDefinition() != null) {
|
||||
modelRespVO.getProcessDefinition().setSuspensionState(processDefinition.isSuspended() ?
|
||||
SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode());
|
||||
modelRespVO.getProcessDefinition().setDeploymentTime(deployment.getDeploymentTime());
|
||||
}
|
||||
return modelRespVO;
|
||||
}
|
||||
|
||||
default BpmModelRespVO convert(Model model) {
|
||||
BpmModelRespVO modelRespVO = new BpmModelRespVO();
|
||||
modelRespVO.setId(model.getId());
|
||||
modelRespVO.setCreateTime(model.getCreateTime());
|
||||
// 通用 copy
|
||||
copyTo(model, modelRespVO);
|
||||
return modelRespVO;
|
||||
}
|
||||
|
||||
default void copyTo(Model model, BpmModelBaseVO to) {
|
||||
to.setName(model.getName());
|
||||
to.setKey(model.getKey());
|
||||
to.setCategory(model.getCategory());
|
||||
// metaInfo
|
||||
BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
|
||||
copyTo(metaInfo, to);
|
||||
}
|
||||
|
||||
BpmModelCreateReqVO convert(BpmModeImportReqVO bean);
|
||||
|
||||
default BpmProcessDefinitionCreateReqDTO convert2(Model model, BpmFormDO form) {
|
||||
BpmProcessDefinitionCreateReqDTO createReqDTO = new BpmProcessDefinitionCreateReqDTO();
|
||||
createReqDTO.setModelId(model.getId());
|
||||
createReqDTO.setName(model.getName());
|
||||
createReqDTO.setKey(model.getKey());
|
||||
createReqDTO.setCategory(model.getCategory());
|
||||
BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
|
||||
// metaInfo
|
||||
copyTo(metaInfo, createReqDTO);
|
||||
// form
|
||||
if (form != null) {
|
||||
createReqDTO.setFormConf(form.getConf());
|
||||
createReqDTO.setFormFields(form.getFields());
|
||||
}
|
||||
return createReqDTO;
|
||||
}
|
||||
|
||||
void copyTo(BpmModelMetaInfoRespDTO from, @MappingTarget BpmProcessDefinitionCreateReqDTO to);
|
||||
|
||||
void copyTo(BpmModelMetaInfoRespDTO from, @MappingTarget BpmModelBaseVO to);
|
||||
|
||||
BpmModelPageItemRespVO.ProcessDefinition convert(ProcessDefinition bean);
|
||||
|
||||
default void copy(Model model, BpmModelCreateReqVO bean) {
|
||||
model.setName(bean.getName());
|
||||
model.setKey(bean.getKey());
|
||||
model.setMetaInfo(buildMetaInfoStr(null, bean.getDescription(), null, null,
|
||||
null, null));
|
||||
}
|
||||
|
||||
default void copy(Model model, BpmModelUpdateReqVO bean) {
|
||||
model.setName(bean.getName());
|
||||
model.setCategory(bean.getCategory());
|
||||
model.setMetaInfo(buildMetaInfoStr(JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class),
|
||||
bean.getDescription(), bean.getFormType(), bean.getFormId(),
|
||||
bean.getFormCustomCreatePath(), bean.getFormCustomViewPath()));
|
||||
}
|
||||
|
||||
default String buildMetaInfoStr(BpmModelMetaInfoRespDTO metaInfo, String description, Integer formType,
|
||||
Long formId, String formCustomCreatePath, String formCustomViewPath) {
|
||||
if (metaInfo == null) {
|
||||
metaInfo = new BpmModelMetaInfoRespDTO();
|
||||
}
|
||||
// 只有非空,才进行设置,避免更新时的覆盖
|
||||
if (StrUtil.isNotEmpty(description)) {
|
||||
metaInfo.setDescription(description);
|
||||
}
|
||||
if (Objects.nonNull(formType)) {
|
||||
metaInfo.setFormType(formType);
|
||||
metaInfo.setFormId(formId);
|
||||
metaInfo.setFormCustomCreatePath(formCustomCreatePath);
|
||||
metaInfo.setFormCustomViewPath(formCustomViewPath);
|
||||
}
|
||||
return JsonUtils.toJsonString(metaInfo);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package cn.iocoder.yudao.module.bpm.convert.definition;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
|
||||
import org.flowable.common.engine.impl.db.SuspensionState;
|
||||
import org.flowable.engine.repository.Deployment;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.MappingTarget;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Bpm 流程定义的 Convert
|
||||
*
|
||||
* @author yunlong.li
|
||||
*/
|
||||
@Mapper
|
||||
public interface BpmProcessDefinitionConvert {
|
||||
|
||||
BpmProcessDefinitionConvert INSTANCE = Mappers.getMapper(BpmProcessDefinitionConvert.class);
|
||||
|
||||
BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean);
|
||||
|
||||
BpmProcessDefinitionExtDO convert2(BpmProcessDefinitionCreateReqDTO bean);
|
||||
|
||||
default List<BpmProcessDefinitionPageItemRespVO> convertList(List<ProcessDefinition> list, Map<String, Deployment> deploymentMap,
|
||||
Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap, Map<Long, BpmFormDO> formMap) {
|
||||
return CollectionUtils.convertList(list, definition -> {
|
||||
Deployment deployment = definition.getDeploymentId() != null ? deploymentMap.get(definition.getDeploymentId()) : null;
|
||||
BpmProcessDefinitionExtDO definitionDO = processDefinitionDOMap.get(definition.getId());
|
||||
BpmFormDO form = definitionDO != null ? formMap.get(definitionDO.getFormId()) : null;
|
||||
return convert(definition, deployment, definitionDO, form);
|
||||
});
|
||||
}
|
||||
|
||||
default BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean, Deployment deployment,
|
||||
BpmProcessDefinitionExtDO processDefinitionExtDO, BpmFormDO form) {
|
||||
BpmProcessDefinitionPageItemRespVO respVO = convert(bean);
|
||||
respVO.setSuspensionState(bean.isSuspended() ? SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode());
|
||||
if (deployment != null) {
|
||||
respVO.setDeploymentTime(deployment.getDeploymentTime());
|
||||
}
|
||||
if (form != null) {
|
||||
respVO.setFormName(form.getName());
|
||||
}
|
||||
// 复制通用属性
|
||||
copyTo(processDefinitionExtDO, respVO);
|
||||
return respVO;
|
||||
}
|
||||
|
||||
@Mapping(source = "from.id", target = "to.id", ignore = true)
|
||||
void copyTo(BpmProcessDefinitionExtDO from, @MappingTarget BpmProcessDefinitionRespVO to);
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package cn.iocoder.yudao.module.bpm.convert.definition;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
|
||||
import org.flowable.bpmn.model.UserTask;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
public interface BpmTaskAssignRuleConvert {
|
||||
BpmTaskAssignRuleConvert INSTANCE = Mappers.getMapper(BpmTaskAssignRuleConvert.class);
|
||||
|
||||
default List<BpmTaskAssignRuleRespVO> convertList(List<UserTask> tasks, List<BpmTaskAssignRuleDO> rules) {
|
||||
Map<String, BpmTaskAssignRuleDO> ruleMap = CollectionUtils.convertMap(rules, BpmTaskAssignRuleDO::getTaskDefinitionKey);
|
||||
// 以 UserTask 为主维度,原因是:流程图编辑后,一些规则实际就没用了。
|
||||
return CollectionUtils.convertList(tasks, task -> {
|
||||
BpmTaskAssignRuleRespVO respVO = convert(ruleMap.get(task.getId()));
|
||||
if (respVO == null) {
|
||||
respVO = new BpmTaskAssignRuleRespVO();
|
||||
respVO.setTaskDefinitionKey(task.getId());
|
||||
}
|
||||
respVO.setTaskDefinitionName(task.getName());
|
||||
return respVO;
|
||||
});
|
||||
}
|
||||
|
||||
BpmTaskAssignRuleRespVO convert(BpmTaskAssignRuleDO bean);
|
||||
|
||||
BpmTaskAssignRuleDO convert(BpmTaskAssignRuleCreateReqVO bean);
|
||||
|
||||
BpmTaskAssignRuleDO convert(BpmTaskAssignRuleUpdateReqVO bean);
|
||||
|
||||
List<BpmTaskAssignRuleDO> convertList2(List<BpmTaskAssignRuleRespVO> list);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* 提供 POJO 类的实体转换
|
||||
*
|
||||
* 目前使用 MapStruct 框架
|
||||
*/
|
||||
package cn.iocoder.yudao.module.bpm.convert;
|
|
@ -0,0 +1 @@
|
|||
<http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao>
|
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* bpm 包下,业务流程管理(Business Process Management),我们放工作流的功能,基于 activiti 7 版本实现。
|
||||
* 例如说:流程定义、表单配置、审核中心(我的申请、我的待办、我的已办)等等
|
||||
*
|
||||
* bpm 解释:https://baike.baidu.com/item/BPM/1933
|
||||
*
|
||||
* 1. Controller URL:以 /bpm/ 开头,避免和其它 Module 冲突
|
||||
* 2. DataObject 表名:以 bpm_ 开头,方便在数据库中区分
|
||||
*
|
||||
* 注意,由于 Bpm 模块下,容易和其它模块重名,所以类名都加载 Pay 的前缀~
|
||||
*/
|
||||
package cn.iocoder.yudao.module.bpm;
|
|
@ -0,0 +1,77 @@
|
|||
package cn.iocoder.yudao.module.bpm.service.definition;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* Flowable流程模型接口
|
||||
*
|
||||
* @author yunlongn
|
||||
*/
|
||||
public interface BpmModelService {
|
||||
/**
|
||||
* 获得流程模型分页
|
||||
*
|
||||
* @param pageVO 分页查询
|
||||
* @return 流程模型分页
|
||||
*/
|
||||
PageResult<BpmModelPageItemRespVO> getModelPage(BpmModelPageReqVO pageVO);
|
||||
|
||||
/**
|
||||
* 创建流程模型
|
||||
*
|
||||
* @param modelVO 创建信息
|
||||
* @param bpmnXml BPMN XML
|
||||
* @return 创建的流程模型的编号
|
||||
*/
|
||||
String createModel(@Valid BpmModelCreateReqVO modelVO, String bpmnXml);
|
||||
|
||||
/**
|
||||
* 获得流程模块
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 流程模型
|
||||
*/
|
||||
BpmModelRespVO getModel(String id);
|
||||
|
||||
/**
|
||||
* 修改流程模型
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateModel(@Valid BpmModelUpdateReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 将流程模型,部署成一个流程定义
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deployModel(String id);
|
||||
|
||||
/**
|
||||
* 删除模型
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteModel(String id);
|
||||
|
||||
/**
|
||||
* 修改模型的状态,实际更新的部署的流程定义的状态
|
||||
*
|
||||
* @param id 编号
|
||||
* @param state 状态
|
||||
*/
|
||||
void updateModelState(String id, Integer state);
|
||||
|
||||
/**
|
||||
* 获得流程模型编号对应的 BPMN Model
|
||||
*
|
||||
* @param id 流程模型编号
|
||||
* @return BPMN Model
|
||||
*/
|
||||
BpmnModel getBpmnModel(String id);
|
||||
|
||||
}
|
|
@ -0,0 +1,284 @@
|
|||
package cn.iocoder.yudao.module.bpm.service.definition;
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.PageUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
|
||||
import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
|
||||
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.common.engine.impl.util.io.BytesStreamSource;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.repository.Deployment;
|
||||
import org.flowable.engine.repository.Model;
|
||||
import org.flowable.engine.repository.ModelQuery;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* Flowable流程模型实现
|
||||
* 主要进行 Flowable {@link Model} 的维护
|
||||
*
|
||||
* @author yunlongn
|
||||
* @author 芋道源码
|
||||
* @author jason
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class BpmModelServiceImpl implements BpmModelService {
|
||||
|
||||
@Resource
|
||||
private RepositoryService repositoryService;
|
||||
@Resource
|
||||
private BpmProcessDefinitionService processDefinitionService;
|
||||
@Resource
|
||||
private BpmFormService bpmFormService;
|
||||
@Resource
|
||||
private BpmTaskAssignRuleService taskAssignRuleService;
|
||||
|
||||
@Override
|
||||
public PageResult<BpmModelPageItemRespVO> getModelPage(BpmModelPageReqVO pageVO) {
|
||||
ModelQuery modelQuery = repositoryService.createModelQuery();
|
||||
if (StrUtil.isNotBlank(pageVO.getKey())) {
|
||||
modelQuery.modelKey(pageVO.getKey());
|
||||
}
|
||||
if (StrUtil.isNotBlank(pageVO.getName())) {
|
||||
modelQuery.modelNameLike("%" + pageVO.getName() + "%"); // 模糊匹配
|
||||
}
|
||||
if (StrUtil.isNotBlank(pageVO.getCategory())) {
|
||||
modelQuery.modelCategory(pageVO.getCategory());
|
||||
}
|
||||
// 执行查询
|
||||
List<Model> models = modelQuery.orderByCreateTime().desc()
|
||||
.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
|
||||
|
||||
// 获得 Form Map
|
||||
Set<Long> formIds = CollectionUtils.convertSet(models, model -> {
|
||||
BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class);
|
||||
return metaInfo != null ? metaInfo.getFormId() : null;
|
||||
});
|
||||
Map<Long, BpmFormDO> formMap = bpmFormService.getFormMap(formIds);
|
||||
|
||||
// 获得 Deployment Map
|
||||
Set<String> deploymentIds = new HashSet<>();
|
||||
models.forEach(model -> CollectionUtils.addIfNotNull(deploymentIds, model.getDeploymentId()));
|
||||
Map<String, Deployment> deploymentMap = processDefinitionService.getDeploymentMap(deploymentIds);
|
||||
// 获得 ProcessDefinition Map
|
||||
List<ProcessDefinition> processDefinitions = processDefinitionService.getProcessDefinitionListByDeploymentIds(deploymentIds);
|
||||
Map<String, ProcessDefinition> processDefinitionMap = convertMap(processDefinitions, ProcessDefinition::getDeploymentId);
|
||||
|
||||
// 拼接结果
|
||||
long modelCount = modelQuery.count();
|
||||
return new PageResult<>(BpmModelConvert.INSTANCE.convertList(models, formMap, deploymentMap, processDefinitionMap), modelCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String createModel(@Valid BpmModelCreateReqVO createReqVO, String bpmnXml) {
|
||||
checkKeyNCName(createReqVO.getKey());
|
||||
// 校验流程标识已经存在
|
||||
Model keyModel = this.getModelByKey(createReqVO.getKey());
|
||||
if (keyModel != null) {
|
||||
throw exception(MODEL_KEY_EXISTS, createReqVO.getKey());
|
||||
}
|
||||
|
||||
// 创建流程定义
|
||||
Model model = repositoryService.newModel();
|
||||
BpmModelConvert.INSTANCE.copy(model, createReqVO);
|
||||
// 保存流程定义
|
||||
repositoryService.saveModel(model);
|
||||
// 保存 BPMN XML
|
||||
saveModelBpmnXml(model, bpmnXml);
|
||||
return model.getId();
|
||||
}
|
||||
|
||||
private Model getModelByKey(String key) {
|
||||
return repositoryService.createModelQuery().modelKey(key).singleResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BpmModelRespVO getModel(String id) {
|
||||
Model model = repositoryService.getModel(id);
|
||||
if (model == null) {
|
||||
return null;
|
||||
}
|
||||
BpmModelRespVO modelRespVO = BpmModelConvert.INSTANCE.convert(model);
|
||||
// 拼接 bpmn XML
|
||||
byte[] bpmnBytes = repositoryService.getModelEditorSource(id);
|
||||
modelRespVO.setBpmnXml(StrUtil.utf8Str(bpmnBytes));
|
||||
return modelRespVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateModel(@Valid BpmModelUpdateReqVO updateReqVO) {
|
||||
// 校验流程模型存在
|
||||
Model model = repositoryService.getModel(updateReqVO.getId());
|
||||
if (model == null) {
|
||||
throw exception(MODEL_NOT_EXISTS);
|
||||
}
|
||||
|
||||
// 修改流程定义
|
||||
BpmModelConvert.INSTANCE.copy(model, updateReqVO);
|
||||
// 更新模型
|
||||
repositoryService.saveModel(model);
|
||||
// 更新 BPMN XML
|
||||
saveModelBpmnXml(model, updateReqVO.getBpmnXml());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deployModel(String id) {
|
||||
// 校验流程模型存在
|
||||
Model model = repositoryService.getModel(id);
|
||||
if (ObjectUtils.isEmpty(model)) {
|
||||
throw exception(MODEL_NOT_EXISTS);
|
||||
}
|
||||
// 校验流程图
|
||||
byte[] bpmnBytes = repositoryService.getModelEditorSource(model.getId());
|
||||
if (bpmnBytes == null) {
|
||||
throw exception(MODEL_NOT_EXISTS);
|
||||
}
|
||||
// TODO 芋艿:校验流程图的有效性;例如说,是否有开始的元素,是否有结束的元素;
|
||||
// 校验表单已配
|
||||
BpmFormDO form = checkFormConfig(model.getMetaInfo());
|
||||
//校验任务分配规则已配置
|
||||
taskAssignRuleService.checkTaskAssignRuleAllConfig(id);
|
||||
|
||||
BpmProcessDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form).setBpmnBytes(bpmnBytes);
|
||||
//校验模型是否发生修改。如果未修改,则不允许创建
|
||||
if (processDefinitionService.isProcessDefinitionEquals(definitionCreateReqDTO)) { // 流程定义的信息相等
|
||||
ProcessDefinition oldProcessInstance = processDefinitionService.getProcessDefinitionByDeploymentId(model.getDeploymentId());
|
||||
if (oldProcessInstance != null && taskAssignRuleService.isTaskAssignRulesEquals(model.getId(), oldProcessInstance.getId())) {
|
||||
throw exception(MODEL_DEPLOY_FAIL_TASK_INFO_EQUALS);
|
||||
}
|
||||
}
|
||||
// 创建流程定义
|
||||
String definitionId = processDefinitionService.createProcessDefinition(definitionCreateReqDTO);
|
||||
|
||||
// 将老的流程定义进行挂起。也就是说,只有最新部署的流程定义,才可以发起任务。
|
||||
updateProcessDefinitionSuspended(model.getDeploymentId());
|
||||
|
||||
// 更新 model 的 deploymentId,进行关联
|
||||
ProcessDefinition definition = processDefinitionService.getProcessDefinition(definitionId);
|
||||
model.setDeploymentId(definition.getDeploymentId());
|
||||
repositoryService.saveModel(model);
|
||||
|
||||
//复制任务分配规则
|
||||
taskAssignRuleService.copyTaskAssignRules(id, definition.getId());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteModel(String id) {
|
||||
// 校验流程模型存在
|
||||
Model model = repositoryService.getModel(id);
|
||||
if (model == null) {
|
||||
throw exception(MODEL_NOT_EXISTS);
|
||||
}
|
||||
// 执行删除
|
||||
repositoryService.deleteModel(id);
|
||||
// 禁用流程实例
|
||||
updateProcessDefinitionSuspended(model.getDeploymentId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateModelState(String id, Integer state) {
|
||||
// 校验流程模型存在
|
||||
Model model = repositoryService.getModel(id);
|
||||
if (model == null) {
|
||||
throw exception(MODEL_NOT_EXISTS);
|
||||
}
|
||||
// 校验流程定义存在
|
||||
ProcessDefinition definition = processDefinitionService.getProcessDefinitionByDeploymentId(model.getDeploymentId());
|
||||
if (definition == null) {
|
||||
throw exception(PROCESS_DEFINITION_NOT_EXISTS);
|
||||
}
|
||||
|
||||
// 更新状态
|
||||
processDefinitionService.updateProcessDefinitionState(definition.getId(), state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BpmnModel getBpmnModel(String id) {
|
||||
byte[] bpmnBytes = repositoryService.getModelEditorSource(id);
|
||||
if (ArrayUtil.isEmpty(bpmnBytes)) {
|
||||
return null;
|
||||
}
|
||||
BpmnXMLConverter converter = new BpmnXMLConverter();
|
||||
return converter.convertToBpmnModel(new BytesStreamSource(bpmnBytes), true, true);
|
||||
}
|
||||
|
||||
private void checkKeyNCName(String key) {
|
||||
if (!ValidationUtils.isXmlNCName(key)) {
|
||||
throw exception(MODEL_KEY_VALID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验流程表单已配置
|
||||
*
|
||||
* @param metaInfoStr 流程模型 metaInfo 字段
|
||||
* @return 流程表单
|
||||
*/
|
||||
private BpmFormDO checkFormConfig(String metaInfoStr) {
|
||||
BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(metaInfoStr, BpmModelMetaInfoRespDTO.class);
|
||||
if (metaInfo == null || metaInfo.getFormType() == null) {
|
||||
throw exception(MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG);
|
||||
}
|
||||
// 校验表单存在
|
||||
if (Objects.equals(metaInfo.getFormType(), BpmModelFormTypeEnum.NORMAL.getType())) {
|
||||
BpmFormDO form = bpmFormService.getForm(metaInfo.getFormId());
|
||||
if (form == null) {
|
||||
throw exception(FORM_NOT_EXISTS);
|
||||
}
|
||||
return form;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void saveModelBpmnXml(Model model, String bpmnXml) {
|
||||
if (StrUtil.isEmpty(bpmnXml)) {
|
||||
return;
|
||||
}
|
||||
repositoryService.addModelEditorSource(model.getId(), StrUtil.utf8Bytes(bpmnXml));
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起 deploymentId 对应的流程定义。 这里一个deploymentId 只关联一个流程定义
|
||||
* @param deploymentId 流程发布Id.
|
||||
*/
|
||||
private void updateProcessDefinitionSuspended(String deploymentId) {
|
||||
if (StrUtil.isEmpty(deploymentId)) {
|
||||
return;
|
||||
}
|
||||
ProcessDefinition oldDefinition = processDefinitionService.getProcessDefinitionByDeploymentId(deploymentId);
|
||||
if (oldDefinition == null) {
|
||||
return;
|
||||
}
|
||||
processDefinitionService.updateProcessDefinitionState(oldDefinition.getId(), SuspensionState.SUSPENDED.getStateCode());
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
package cn.iocoder.yudao.module.bpm.service.definition;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
|
||||
import org.flowable.bpmn.model.BpmnModel;
|
||||
import org.flowable.engine.repository.Deployment;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
/**
|
||||
* Flowable流程定义接口
|
||||
*
|
||||
* @author yunlong.li
|
||||
* @author ZJQ
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface BpmProcessDefinitionService {
|
||||
|
||||
/**
|
||||
* 获得流程定义分页
|
||||
*
|
||||
* @param pageReqVO 分页入参
|
||||
* @return 流程定义 Page
|
||||
*/
|
||||
PageResult<BpmProcessDefinitionPageItemRespVO> getProcessDefinitionPage(BpmProcessDefinitionPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 创建流程定义
|
||||
*
|
||||
* @param createReqDTO 创建信息
|
||||
* @return 流程编号
|
||||
*/
|
||||
String createProcessDefinition(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
|
||||
|
||||
/**
|
||||
* 更新流程定义状态
|
||||
*
|
||||
* @param id 流程定义的编号
|
||||
* @param state 状态
|
||||
*/
|
||||
void updateProcessDefinitionState(String id, Integer state);
|
||||
|
||||
/**
|
||||
* 获得流程定义对应的 BPMN XML
|
||||
*
|
||||
* @param id 流程定义编号
|
||||
* @return BPMN XML
|
||||
*/
|
||||
String getProcessDefinitionBpmnXML(String id);
|
||||
|
||||
/**
|
||||
* 获得需要创建的流程定义,是否和当前激活的流程定义相等
|
||||
*
|
||||
* @param createReqDTO 创建信息
|
||||
* @return 是否相等
|
||||
*/
|
||||
boolean isProcessDefinitionEquals(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
|
||||
|
||||
/**
|
||||
* 获得编号对应的 BpmProcessDefinitionExtDO
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 流程定义拓展
|
||||
*/
|
||||
BpmProcessDefinitionExtDO getProcessDefinitionExt(String id);
|
||||
|
||||
/**
|
||||
* 获得编号对应的 ProcessDefinition
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 流程定义
|
||||
*/
|
||||
ProcessDefinition getProcessDefinition(String id);
|
||||
|
||||
/**
|
||||
* 获得 deploymentId 对应的 ProcessDefinition
|
||||
*
|
||||
* @param deploymentId 部署编号
|
||||
* @return 流程定义
|
||||
*/
|
||||
ProcessDefinition getProcessDefinitionByDeploymentId(String deploymentId);
|
||||
|
||||
/**
|
||||
* 获得 deploymentIds 对应的 ProcessDefinition 数组
|
||||
*
|
||||
* @param deploymentIds 部署编号的数组
|
||||
* @return 流程定义的数组
|
||||
*/
|
||||
List<ProcessDefinition> getProcessDefinitionListByDeploymentIds(Set<String> deploymentIds);
|
||||
|
||||
/**
|
||||
* 获得流程定义标识对应的激活的流程定义
|
||||
*
|
||||
* @param key 流程定义的标识
|
||||
* @return 流程定义
|
||||
*/
|
||||
ProcessDefinition getActiveProcessDefinition(String key);
|
||||
|
||||
/**
|
||||
* 获得 ids 对应的 Deployment Map
|
||||
*
|
||||
* @param ids 部署编号的数组
|
||||
* @return 流程部署 Map
|
||||
*/
|
||||
default Map<String, Deployment> getDeploymentMap(Set<String> ids) {
|
||||
return CollectionUtils.convertMap(getDeployments(ids), Deployment::getId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得 ids 对应的 Deployment 数组
|
||||
*
|
||||
* @param ids 部署编号的数组
|
||||
* @return 流程部署的数组
|
||||
*/
|
||||
List<Deployment> getDeployments(Set<String> ids);
|
||||
|
||||
/**
|
||||
* 获得 id 对应的 Deployment
|
||||
*
|
||||
* @param id 部署编号
|
||||
* @return 流程部署
|
||||
*/
|
||||
Deployment getDeployment(String id);
|
||||
|
||||
/**
|
||||
* 获得 Bpmn 模型
|
||||
*
|
||||
* @param processDefinitionId 流程定义的编号
|
||||
* @return Bpmn 模型
|
||||
*/
|
||||
BpmnModel getBpmnModel(String processDefinitionId);
|
||||
}
|
|
@ -0,0 +1,265 @@
|
|||
package cn.iocoder.yudao.module.bpm.service.definition;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.PageUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.convert.definition.BpmProcessDefinitionConvert;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmProcessDefinitionExtMapper;
|
||||
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
|
||||
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.common.engine.impl.util.io.BytesStreamSource;
|
||||
import org.flowable.engine.RepositoryService;
|
||||
import org.flowable.engine.repository.Deployment;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.flowable.engine.repository.ProcessDefinitionQuery;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_KEY_NOT_MATCH;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_NAME_NOT_MATCH;
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
/**
|
||||
* 流程定义实现
|
||||
* 主要进行 Flowable {@link ProcessDefinition} 和 {@link Deployment} 的维护
|
||||
*
|
||||
* @author yunlongn
|
||||
* @author ZJQ
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionService {
|
||||
|
||||
private static final String BPMN_FILE_SUFFIX = ".bpmn";
|
||||
|
||||
@Resource
|
||||
private RepositoryService repositoryService;
|
||||
|
||||
@Resource
|
||||
private BpmProcessDefinitionExtMapper processDefinitionMapper;
|
||||
|
||||
@Resource
|
||||
private BpmFormService formService;
|
||||
|
||||
@Override
|
||||
public ProcessDefinition getProcessDefinition(String id) {
|
||||
return repositoryService.getProcessDefinition(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessDefinition getProcessDefinitionByDeploymentId(String deploymentId) {
|
||||
if (StrUtil.isEmpty(deploymentId)) {
|
||||
return null;
|
||||
}
|
||||
return repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProcessDefinition> getProcessDefinitionListByDeploymentIds(Set<String> deploymentIds) {
|
||||
if (CollUtil.isEmpty(deploymentIds)) {
|
||||
return emptyList();
|
||||
}
|
||||
return repositoryService.createProcessDefinitionQuery().deploymentIds(deploymentIds).list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessDefinition getActiveProcessDefinition(String key) {
|
||||
return repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).active().singleResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Deployment> getDeployments(Set<String> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return emptyList();
|
||||
}
|
||||
List<Deployment> list = new ArrayList<>(ids.size());
|
||||
for (String id : ids) {
|
||||
addIfNotNull(list, getDeployment(id));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Deployment getDeployment(String id) {
|
||||
if (StrUtil.isEmpty(id)) {
|
||||
return null;
|
||||
}
|
||||
return repositoryService.createDeploymentQuery().deploymentId(id).singleResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BpmnModel getBpmnModel(String processDefinitionId) {
|
||||
return repositoryService.getBpmnModel(processDefinitionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createProcessDefinition(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO) {
|
||||
// 创建 Deployment 部署
|
||||
Deployment deploy = repositoryService.createDeployment()
|
||||
.key(createReqDTO.getKey()).name(createReqDTO.getName()).category(createReqDTO.getCategory())
|
||||
.addBytes(createReqDTO.getKey() + BPMN_FILE_SUFFIX, createReqDTO.getBpmnBytes())
|
||||
.deploy();
|
||||
|
||||
// 设置 ProcessDefinition 的 category 分类
|
||||
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();
|
||||
repositoryService.setProcessDefinitionCategory(definition.getId(), createReqDTO.getCategory());
|
||||
// 注意 1,ProcessDefinition 的 key 和 name 是通过 BPMN 中的 <bpmn2:process /> 的 id 和 name 决定
|
||||
// 注意 2,目前该项目的设计上,需要保证 Model、Deployment、ProcessDefinition 使用相同的 key,保证关联性。
|
||||
// 否则,会导致 ProcessDefinition 的分页无法查询到。
|
||||
if (!Objects.equals(definition.getKey(), createReqDTO.getKey())) {
|
||||
throw exception(PROCESS_DEFINITION_KEY_NOT_MATCH, createReqDTO.getKey(), definition.getKey());
|
||||
}
|
||||
if (!Objects.equals(definition.getName(), createReqDTO.getName())) {
|
||||
throw exception(PROCESS_DEFINITION_NAME_NOT_MATCH, createReqDTO.getName(), definition.getName());
|
||||
}
|
||||
|
||||
// 插入拓展表
|
||||
BpmProcessDefinitionExtDO definitionDO = BpmProcessDefinitionConvert.INSTANCE.convert2(createReqDTO)
|
||||
.setProcessDefinitionId(definition.getId());
|
||||
processDefinitionMapper.insert(definitionDO);
|
||||
return definition.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateProcessDefinitionState(String id, Integer state) {
|
||||
// 激活
|
||||
if (Objects.equals(SuspensionState.ACTIVE.getStateCode(), state)) {
|
||||
repositoryService.activateProcessDefinitionById(id, false, null);
|
||||
return;
|
||||
}
|
||||
// 挂起
|
||||
if (Objects.equals(SuspensionState.SUSPENDED.getStateCode(), state)) {
|
||||
// suspendProcessInstances = false,进行中的任务,不进行挂起。
|
||||
// 原因:只要新的流程不允许发起即可,老流程继续可以执行。
|
||||
repositoryService.suspendProcessDefinitionById(id, false, null);
|
||||
return;
|
||||
}
|
||||
log.error("[updateProcessDefinitionState][流程定义({}) 修改未知状态({})]", id, state);
|
||||
}
|
||||
|
||||
@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));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isProcessDefinitionEquals(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO) {
|
||||
// 校验 name、description 是否更新
|
||||
ProcessDefinition oldProcessDefinition = getActiveProcessDefinition(createReqDTO.getKey());
|
||||
if (oldProcessDefinition == null) {
|
||||
return false;
|
||||
}
|
||||
BpmProcessDefinitionExtDO oldProcessDefinitionExt = getProcessDefinitionExt(oldProcessDefinition.getId());
|
||||
if (!StrUtil.equals(createReqDTO.getName(), oldProcessDefinition.getName())
|
||||
|| !StrUtil.equals(createReqDTO.getDescription(), oldProcessDefinitionExt.getDescription())
|
||||
|| !StrUtil.equals(createReqDTO.getCategory(), oldProcessDefinition.getCategory())) {
|
||||
return false;
|
||||
}
|
||||
// 校验 form 信息是否更新
|
||||
if (!ObjectUtil.equal(createReqDTO.getFormType(), oldProcessDefinitionExt.getFormType())
|
||||
|| !ObjectUtil.equal(createReqDTO.getFormId(), oldProcessDefinitionExt.getFormId())
|
||||
|| !ObjectUtil.equal(createReqDTO.getFormConf(), oldProcessDefinitionExt.getFormConf())
|
||||
|| !ObjectUtil.equal(createReqDTO.getFormFields(), oldProcessDefinitionExt.getFormFields())
|
||||
|| !ObjectUtil.equal(createReqDTO.getFormCustomCreatePath(), oldProcessDefinitionExt.getFormCustomCreatePath())
|
||||
|| !ObjectUtil.equal(createReqDTO.getFormCustomViewPath(), oldProcessDefinitionExt.getFormCustomViewPath())) {
|
||||
return false;
|
||||
}
|
||||
// 校验 BPMN XML 信息
|
||||
BpmnModel newModel = buildBpmnModel(createReqDTO.getBpmnBytes());
|
||||
BpmnModel oldModel = getBpmnModel(oldProcessDefinition.getId());
|
||||
//TODO 貌似 flowable 不修改这个也不同。需要看看。 sourceSystemId 不同
|
||||
if (equals(oldModel, newModel)) {
|
||||
return false;
|
||||
}
|
||||
// 最终发现都一致,则返回 true
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建对应的 BPMN Model
|
||||
*
|
||||
* @param bpmnBytes 原始的 BPMN XML 字节数组
|
||||
* @return BPMN Model
|
||||
*/
|
||||
private BpmnModel buildBpmnModel(byte[] bpmnBytes) {
|
||||
// 转换成 BpmnModel 对象
|
||||
BpmnXMLConverter converter = new BpmnXMLConverter();
|
||||
return converter.convertToBpmnModel(new BytesStreamSource(bpmnBytes), true, true);
|
||||
}
|
||||
//TODO 移出去
|
||||
public boolean equals(BpmnModel oldModel, BpmnModel newModel) {
|
||||
// 由于 BpmnModel 未提供 equals 方法,所以只能转成字节数组,进行比较
|
||||
return Arrays.equals(getBpmnBytes(oldModel), getBpmnBytes(newModel));
|
||||
}
|
||||
//TODO 移出去
|
||||
public byte[] getBpmnBytes(BpmnModel model) {
|
||||
if (model == null) {
|
||||
return new byte[0];
|
||||
}
|
||||
BpmnXMLConverter converter = new BpmnXMLConverter();
|
||||
return converter.convertToXML(model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BpmProcessDefinitionExtDO getProcessDefinitionExt(String id) {
|
||||
return processDefinitionMapper.selectByProcessDefinitionId(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<BpmProcessDefinitionPageItemRespVO> getProcessDefinitionPage(BpmProcessDefinitionPageReqVO pageVO) {
|
||||
ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();
|
||||
if (StrUtil.isNotBlank(pageVO.getKey())) {
|
||||
definitionQuery.processDefinitionKey(pageVO.getKey());
|
||||
}
|
||||
|
||||
// 执行查询
|
||||
List<ProcessDefinition> processDefinitions = definitionQuery.orderByProcessDefinitionVersion().desc()
|
||||
.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
|
||||
|
||||
if (CollUtil.isEmpty(processDefinitions)) {
|
||||
return new PageResult<>(emptyList(), definitionQuery.count());
|
||||
}
|
||||
// 获得 Deployment Map
|
||||
Set<String> deploymentIds = new HashSet<>();
|
||||
processDefinitions.forEach(definition -> addIfNotNull(deploymentIds, definition.getDeploymentId()));
|
||||
Map<String, Deployment> deploymentMap = getDeploymentMap(deploymentIds);
|
||||
|
||||
// 获得 BpmProcessDefinitionDO Map
|
||||
List<BpmProcessDefinitionExtDO> processDefinitionDOs = processDefinitionMapper.selectListByProcessDefinitionIds(
|
||||
convertList(processDefinitions, ProcessDefinition::getId));
|
||||
Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap = convertMap(processDefinitionDOs,
|
||||
BpmProcessDefinitionExtDO::getProcessDefinitionId);
|
||||
|
||||
// 获得 Form Map
|
||||
Set<Long> formIds = convertSet(processDefinitionDOs, BpmProcessDefinitionExtDO::getFormId);
|
||||
Map<Long, BpmFormDO> formMap = formService.getFormMap(formIds);
|
||||
|
||||
// 拼接结果
|
||||
long definitionCount = definitionQuery.count();
|
||||
return new PageResult<>(BpmProcessDefinitionConvert.INSTANCE.convertList(processDefinitions, deploymentMap,
|
||||
processDefinitionDOMap, formMap), definitionCount);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,228 @@
|
|||
package cn.iocoder.yudao.module.bpm.service.definition;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.convert.definition.BpmTaskAssignRuleConvert;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper;
|
||||
import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
|
||||
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
||||
import cn.iocoder.yudao.module.system.api.dept.PostApi;
|
||||
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
|
||||
import cn.iocoder.yudao.module.system.api.permission.RoleApi;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
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.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* BPM 任务分配规则 Service 实现类
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService{
|
||||
|
||||
@Resource
|
||||
private BpmTaskAssignRuleMapper taskRuleMapper;
|
||||
@Resource
|
||||
@Lazy // 解决循环依赖
|
||||
private BpmModelService modelService;
|
||||
@Resource
|
||||
private BpmProcessDefinitionService processDefinitionService;
|
||||
@Resource
|
||||
private BpmUserGroupService userGroupService;
|
||||
@Resource
|
||||
private RoleApi roleApi;
|
||||
@Resource
|
||||
private DeptApi deptApi;
|
||||
@Resource
|
||||
private PostApi postApi;
|
||||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
@Resource
|
||||
private DictDataApi dictDataApi;
|
||||
|
||||
@Override
|
||||
public List<BpmTaskAssignRuleDO> getTaskAssignRuleListByProcessDefinitionId(String processDefinitionId, String taskDefinitionKey) {
|
||||
return taskRuleMapper.selectListByProcessDefinitionId(processDefinitionId, taskDefinitionKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BpmTaskAssignRuleDO> getTaskAssignRuleListByModelId(String modelId) {
|
||||
return taskRuleMapper.selectListByModelId(modelId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BpmTaskAssignRuleRespVO> getTaskAssignRuleList(String modelId, String processDefinitionId) {
|
||||
// 获得规则
|
||||
List<BpmTaskAssignRuleDO> rules = Collections.emptyList();
|
||||
BpmnModel model = null;
|
||||
if (StrUtil.isNotEmpty(modelId)) {
|
||||
rules = getTaskAssignRuleListByModelId(modelId);
|
||||
model = modelService.getBpmnModel(modelId);
|
||||
} else if (StrUtil.isNotEmpty(processDefinitionId)) {
|
||||
rules = getTaskAssignRuleListByProcessDefinitionId(processDefinitionId, null);
|
||||
model = processDefinitionService.getBpmnModel(processDefinitionId);
|
||||
}
|
||||
if (model == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 获得用户任务,只有用户任务才可以设置分配规则
|
||||
List<UserTask> userTasks = getBpmnModelElements(model, UserTask.class);
|
||||
if (CollUtil.isEmpty(userTasks)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 转换数据
|
||||
return BpmTaskAssignRuleConvert.INSTANCE.convertList(userTasks, rules);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO 需要移出去
|
||||
* 获得 BPMN 流程中,指定的元素们
|
||||
*
|
||||
* @param model
|
||||
* @param clazz 指定元素。例如说,{@link org.flowable.bpmn.model.UserTask}、{@link org.flowable.bpmn.model.Gateway} 等等
|
||||
* @return 元素们
|
||||
*/
|
||||
public static <T extends FlowElement> List<T> getBpmnModelElements(BpmnModel model, Class<T> clazz) {
|
||||
List<T> result = new ArrayList<>();
|
||||
model.getProcesses().forEach(process -> {
|
||||
process.getFlowElements().forEach(flowElement -> {
|
||||
if (flowElement.getClass().isAssignableFrom(clazz)) {
|
||||
result.add((T) flowElement);
|
||||
}
|
||||
});
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long createTaskAssignRule(@Valid BpmTaskAssignRuleCreateReqVO reqVO) {
|
||||
// 校验参数
|
||||
validTaskAssignRuleOptions(reqVO.getType(), reqVO.getOptions());
|
||||
// 校验是否已经配置
|
||||
BpmTaskAssignRuleDO existRule = taskRuleMapper.selectListByModelIdAndTaskDefinitionKey(
|
||||
reqVO.getModelId(), reqVO.getTaskDefinitionKey());
|
||||
if (existRule != null) {
|
||||
throw exception(TASK_ASSIGN_RULE_EXISTS, reqVO.getModelId(), reqVO.getTaskDefinitionKey());
|
||||
}
|
||||
|
||||
// 存储
|
||||
BpmTaskAssignRuleDO rule = BpmTaskAssignRuleConvert.INSTANCE.convert(reqVO)
|
||||
.setProcessDefinitionId(BpmTaskAssignRuleDO.PROCESS_DEFINITION_ID_NULL); // 只有流程模型,才允许新建
|
||||
taskRuleMapper.insert(rule);
|
||||
return rule.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTaskAssignRule(@Valid BpmTaskAssignRuleUpdateReqVO reqVO) {
|
||||
// 校验参数
|
||||
validTaskAssignRuleOptions(reqVO.getType(), reqVO.getOptions());
|
||||
// 校验是否存在
|
||||
BpmTaskAssignRuleDO existRule = taskRuleMapper.selectById(reqVO.getId());
|
||||
if (existRule == null) {
|
||||
throw exception(TASK_ASSIGN_RULE_NOT_EXISTS);
|
||||
}
|
||||
// 只允许修改流程模型的规则
|
||||
if (!Objects.equals(BpmTaskAssignRuleDO.PROCESS_DEFINITION_ID_NULL, existRule.getProcessDefinitionId())) {
|
||||
throw exception(TASK_UPDATE_FAIL_NOT_MODEL);
|
||||
}
|
||||
|
||||
// 执行更新
|
||||
taskRuleMapper.updateById(BpmTaskAssignRuleConvert.INSTANCE.convert(reqVO));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTaskAssignRulesEquals(String modelId, String processDefinitionId) {
|
||||
// 调用 VO 接口的原因是,过滤掉流程模型不需要的规则,保持和 copyTaskAssignRules 方法的一致性
|
||||
List<BpmTaskAssignRuleRespVO> modelRules = getTaskAssignRuleList(modelId, null);
|
||||
List<BpmTaskAssignRuleRespVO> processInstanceRules = getTaskAssignRuleList(null, processDefinitionId);
|
||||
if (modelRules.size() != processInstanceRules.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 遍历,匹配对应的规则
|
||||
Map<String, BpmTaskAssignRuleRespVO> processInstanceRuleMap = CollectionUtils.convertMap(processInstanceRules,
|
||||
BpmTaskAssignRuleRespVO::getTaskDefinitionKey);
|
||||
for (BpmTaskAssignRuleRespVO modelRule : modelRules) {
|
||||
BpmTaskAssignRuleRespVO processInstanceRule = processInstanceRuleMap.get(modelRule.getTaskDefinitionKey());
|
||||
if (processInstanceRule == null) {
|
||||
return false;
|
||||
}
|
||||
if (!ObjectUtil.equals(modelRule.getType(), processInstanceRule.getType())
|
||||
|| !ObjectUtil.equal(modelRule.getOptions(), processInstanceRule.getOptions())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyTaskAssignRules(String fromModelId, String toProcessDefinitionId) {
|
||||
List<BpmTaskAssignRuleRespVO> rules = getTaskAssignRuleList(fromModelId, null);
|
||||
if (CollUtil.isEmpty(rules)) {
|
||||
return;
|
||||
}
|
||||
// 开始复制
|
||||
List<BpmTaskAssignRuleDO> newRules = BpmTaskAssignRuleConvert.INSTANCE.convertList2(rules);
|
||||
newRules.forEach(rule -> rule.setProcessDefinitionId(toProcessDefinitionId).setId(null)
|
||||
.setCreateTime(null).setUpdateTime(null));
|
||||
taskRuleMapper.insertBatch(newRules);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkTaskAssignRuleAllConfig(String id) {
|
||||
// 一个用户任务都没配置,所以无需配置规则
|
||||
List<BpmTaskAssignRuleRespVO> taskAssignRules = getTaskAssignRuleList(id, null);
|
||||
if (CollUtil.isEmpty(taskAssignRules)) {
|
||||
return;
|
||||
}
|
||||
// 校验未配置规则的任务
|
||||
taskAssignRules.forEach(rule -> {
|
||||
if (CollUtil.isEmpty(rule.getOptions())) {
|
||||
throw exception(MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG, rule.getTaskDefinitionName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void validTaskAssignRuleOptions(Integer type, Set<Long> options) {
|
||||
if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.ROLE.getType())) {
|
||||
roleApi.validRoles(options);
|
||||
} else if (ObjectUtils.equalsAny(type, BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(),
|
||||
BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType())) {
|
||||
deptApi.validDepts(options);
|
||||
} else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.POST.getType())) {
|
||||
postApi.validPosts(options);
|
||||
} else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER.getType())) {
|
||||
adminUserApi.validUsers(options);
|
||||
} else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.USER_GROUP.getType())) {
|
||||
userGroupService.validUserGroups(options);
|
||||
} else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.SCRIPT.getType())) {
|
||||
dictDataApi.validDictDatas(DictTypeConstants.TASK_ASSIGN_SCRIPT,
|
||||
CollectionUtils.convertSet(options, String::valueOf));
|
||||
} else {
|
||||
throw new IllegalArgumentException(StrUtil.format("未知的规则类型({})", type));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue