工作流 Flowable 流程模型, 流程定义 优化

This commit is contained in:
jason 2022-02-11 11:32:46 +08:00
parent b1d6baaad8
commit d64555697f
17 changed files with 466 additions and 261 deletions

View File

@ -1,10 +1,10 @@
package cn.iocoder.yudao.module.bpm.controller.admin.definition; 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.BpmTaskAssignRuleCreateReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO; 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.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService; 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.Api;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiImplicitParams;
@ -32,7 +32,7 @@ public class BpmTaskAssignRuleController {
@ApiOperation(value = "获得任务分配规则列表") @ApiOperation(value = "获得任务分配规则列表")
@ApiImplicitParams({ @ApiImplicitParams({
@ApiImplicitParam(name = "modelId", value = "模型编号", example = "1024", dataTypeClass = String.class), @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')") @PreAuthorize("@ss.hasPermission('bpm:task-assign-rule:query')")
public CommonResult<List<BpmTaskAssignRuleRespVO>> getTaskAssignRuleList( public CommonResult<List<BpmTaskAssignRuleRespVO>> getTaskAssignRuleList(

View File

@ -1,82 +0,0 @@
package cn.iocoder.yudao.module.bpm.service.definition;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
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.BpmModelMetaInfoRespDTO;
import java.util.List;
import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
/**
* 流程模型通用抽象类
* Activiti flowable 通用的流程模型抽象类 Activiti flowable 两边通用的方法
*
* @author yunlongn
* @author jason
*/
public abstract class BpmAbstractModelService {
protected final BpmFormService bpmFormService;
protected final BpmTaskAssignRuleService taskAssignRuleService;
public BpmAbstractModelService(BpmFormService bpmFormService,BpmTaskAssignRuleService taskAssignRuleService) {
this.bpmFormService = bpmFormService;
this.taskAssignRuleService = taskAssignRuleService;
}
/**
* 校验流程表单已配置
*
* @param metaInfoStr 流程模型 metaInfo 字段
* @return 流程表单
*/
protected 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;
}
/**
* 校验流程模型的任务分配规则全部都配置了
* 目的如果有规则未配置会导致流程任务找不到负责人进而流程无法进行下去
*
* @param id 流程模型编号
*/
protected 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());
}
});
}
protected void checkKeyNCName(String key) {
if (!ValidationUtils.isXmlNCName(key)) {
throw exception(MODEL_KEY_VALID);
}
}
}

View File

@ -88,4 +88,12 @@ public interface BpmFormService {
*/ */
PageResult<BpmFormDO> getFormPage(BpmFormPageReqVO pageReqVO); PageResult<BpmFormDO> getFormPage(BpmFormPageReqVO pageReqVO);
/**
* 校验流程表单已配置
*
* @param configStr configStr 字段
* @return 流程表单
*/
BpmFormDO checkFormConfig(String configStr);
} }

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.bpm.service.definition; package cn.iocoder.yudao.module.bpm.service.definition;
import cn.hutool.core.lang.Assert; 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.BpmFormCreateReqVO;
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.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.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.enums.ErrorCodeConstants; 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.module.bpm.service.definition.dto.BpmFormFieldRespDTO;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 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.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Collection; import java.util.*;
import java.util.HashMap;
import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import java.util.Map; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
/** /**
* 动态表单 Service 实现类 * 动态表单 Service 实现类
@ -87,6 +90,29 @@ public class BpmFormServiceImpl implements BpmFormService {
return formMapper.selectPage(pageReqVO); 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 重复 * 校验 Field避免 field 重复
* *

View File

@ -1,69 +0,0 @@
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 javax.validation.Valid;
/**
* 流程模型通用接口
* Activiti flowable 通用的流程模型接口
*
* @author yunlongn
* @author jason
*/
public interface BpmModelCommonService {
/**
* 获得流程模型分页
*
* @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);
}

View File

@ -1,69 +0,0 @@
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.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 javax.validation.Valid;
/**
* 流程定义通用接口
* Activiti flowable 通用的流程定义接口
*
* @author yunlong.li
* @author ZJQ
* @author 芋道源码
* @author jason
*/
public interface BpmProcessDefinitionCommonService {
/**
* 获得流程定义分页
*
* @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);
}

View File

@ -76,4 +76,12 @@ public interface BpmTaskAssignRuleService {
*/ */
void copyTaskAssignRules(String fromModelId, String toProcessDefinitionId); void copyTaskAssignRules(String fromModelId, String toProcessDefinitionId);
/**
* 校验流程模型的任务分配规则全部都配置了
* 目的如果有规则未配置会导致流程任务找不到负责人进而流程无法进行下去
*
* @param id 流程模型编号
*/
void checkTaskAssignRuleAllConfig(String id);
} }

View File

@ -11,7 +11,60 @@ import javax.validation.Valid;
* *
* @author yunlongn * @author yunlongn
*/ */
public interface BpmModelService extends BpmModelCommonService { 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 * 获得流程模型编号对应的 BPMN Model

View File

@ -3,8 +3,10 @@ package cn.iocoder.yudao.module.bpm.service.definition;
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.hutool.core.util.StrUtil; 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.controller.admin.definition.vo.model.*;
import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert; 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.BpmModelMetaInfoRespDTO;
import cn.iocoder.yudao.framework.activiti.core.util.ActivitiUtils; import cn.iocoder.yudao.framework.activiti.core.util.ActivitiUtils;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
@ -45,17 +47,16 @@ import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
@Service @Service
@Validated @Validated
@Slf4j @Slf4j
public class BpmModelServiceImpl extends BpmAbstractModelService implements BpmModelService { public class BpmModelServiceImpl implements BpmModelService {
@Resource @Resource
private RepositoryService repositoryService; private RepositoryService repositoryService;
@Resource @Resource
private BpmProcessDefinitionService processDefinitionService; private BpmProcessDefinitionService processDefinitionService;
@Resource
public BpmModelServiceImpl(BpmFormService bpmFormService,BpmTaskAssignRuleService taskAssignRuleService) { private BpmFormService bpmFormService;
super(bpmFormService, taskAssignRuleService); @Resource
} private BpmTaskAssignRuleService taskAssignRuleService;
@Override @Override
public PageResult<BpmModelPageItemRespVO> getModelPage(BpmModelPageReqVO pageVO) { public PageResult<BpmModelPageItemRespVO> getModelPage(BpmModelPageReqVO pageVO) {
@ -167,7 +168,7 @@ public class BpmModelServiceImpl extends BpmAbstractModelService implements BpmM
// 校验表单已配 // 校验表单已配
BpmFormDO form = checkFormConfig(model.getMetaInfo()); BpmFormDO form = checkFormConfig(model.getMetaInfo());
// 校验任务分配规则已配置 // 校验任务分配规则已配置
checkTaskAssignRuleAllConfig(id); taskAssignRuleService.checkTaskAssignRuleAllConfig(id);
// 校验模型是否发生修改如果未修改则不允许创建 // 校验模型是否发生修改如果未修改则不允许创建
BpmProcessDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form).setBpmnBytes(bpmnBytes); BpmProcessDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form).setBpmnBytes(bpmnBytes);
@ -247,4 +248,32 @@ public class BpmModelServiceImpl extends BpmAbstractModelService implements BpmM
return repositoryService.createModelQuery().modelKey(key).singleResult(); return repositoryService.createModelQuery().modelKey(key).singleResult();
} }
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;
}
} }

View File

@ -24,7 +24,55 @@ import java.util.Set;
* @author ZJQ * @author ZJQ
* @author 芋道源码 * @author 芋道源码
*/ */
public interface BpmProcessDefinitionService extends BpmProcessDefinitionCommonService { 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);
/** /**
* 获得流程定义列表 * 获得流程定义列表

View File

@ -173,6 +173,21 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
taskRuleMapper.insertBatch(newRules); 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) { private void validTaskAssignRuleOptions(Integer type, Set<Long> options) {
if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.ROLE.getType())) { if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.ROLE.getType())) {
roleApi.validRoles(options); roleApi.validRoles(options);

View File

@ -1,7 +1,9 @@
package cn.iocoder.yudao.module.bpm.convert.definition; package cn.iocoder.yudao.module.bpm.convert.definition;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 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.BpmTaskAssignRuleRespVO;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
import org.flowable.bpmn.model.UserTask; import org.flowable.bpmn.model.UserTask;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
@ -29,4 +31,10 @@ public interface BpmTaskAssignRuleConvert {
} }
BpmTaskAssignRuleRespVO convert(BpmTaskAssignRuleDO bean); BpmTaskAssignRuleRespVO convert(BpmTaskAssignRuleDO bean);
BpmTaskAssignRuleDO convert(BpmTaskAssignRuleCreateReqVO bean);
BpmTaskAssignRuleDO convert(BpmTaskAssignRuleUpdateReqVO bean);
List<BpmTaskAssignRuleDO> convertList2(List<BpmTaskAssignRuleRespVO> list);
} }

View File

@ -1,13 +1,70 @@
package cn.iocoder.yudao.module.bpm.service.definition; 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 org.flowable.bpmn.model.BpmnModel;
import javax.validation.Valid;
/** /**
* Flowable流程模型接口 * Flowable流程模型接口
* *
* @author yunlongn * @author yunlongn
*/ */
public interface BpmModelService extends BpmModelCommonService { 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 * 获得流程模型编号对应的 BPMN Model

View File

@ -6,9 +6,11 @@ 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.json.JsonUtils; 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.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.controller.admin.definition.vo.model.*;
import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert; 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.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.BpmModelMetaInfoRespDTO;
import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -45,16 +47,16 @@ import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
@Service @Service
@Validated @Validated
@Slf4j @Slf4j
public class BpmModelServiceImpl extends BpmAbstractModelService implements BpmModelService { public class BpmModelServiceImpl implements BpmModelService {
@Resource @Resource
private RepositoryService repositoryService; private RepositoryService repositoryService;
@Resource @Resource
private BpmProcessDefinitionService processDefinitionService; private BpmProcessDefinitionService processDefinitionService;
@Resource
public BpmModelServiceImpl(BpmFormService bpmFormService, BpmTaskAssignRuleService taskAssignRuleService){ private BpmFormService bpmFormService;
super(bpmFormService, taskAssignRuleService); @Resource
} private BpmTaskAssignRuleService taskAssignRuleService;
@Override @Override
public PageResult<BpmModelPageItemRespVO> getModelPage(BpmModelPageReqVO pageVO) { public PageResult<BpmModelPageItemRespVO> getModelPage(BpmModelPageReqVO pageVO) {
@ -161,7 +163,7 @@ public class BpmModelServiceImpl extends BpmAbstractModelService implements BpmM
// 校验表单已配 // 校验表单已配
BpmFormDO form = checkFormConfig(model.getMetaInfo()); BpmFormDO form = checkFormConfig(model.getMetaInfo());
//校验任务分配规则已配置 //校验任务分配规则已配置
checkTaskAssignRuleAllConfig(id); taskAssignRuleService.checkTaskAssignRuleAllConfig(id);
BpmProcessDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form).setBpmnBytes(bpmnBytes); BpmProcessDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form).setBpmnBytes(bpmnBytes);
//校验模型是否发生修改如果未修改则不允许创建 //校验模型是否发生修改如果未修改则不允许创建
@ -182,8 +184,8 @@ public class BpmModelServiceImpl extends BpmAbstractModelService implements BpmM
model.setDeploymentId(definition.getDeploymentId()); model.setDeploymentId(definition.getDeploymentId());
repositoryService.saveModel(model); repositoryService.saveModel(model);
//TODO 复制任务分配规则 //复制任务分配规则
//taskAssignRuleService.copyTaskAssignRules(id, definition.getId()); taskAssignRuleService.copyTaskAssignRules(id, definition.getId());
} }
@ -218,6 +220,44 @@ public class BpmModelServiceImpl extends BpmAbstractModelService implements BpmM
processDefinitionService.updateProcessDefinitionState(definition.getId(), state); 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) { private void saveModelBpmnXml(Model model, String bpmnXml) {
if (StrUtil.isEmpty(bpmnXml)) { if (StrUtil.isEmpty(bpmnXml)) {
return; return;
@ -240,13 +280,5 @@ public class BpmModelServiceImpl extends BpmAbstractModelService implements BpmM
processDefinitionService.updateProcessDefinitionState(oldDefinition.getId(), SuspensionState.SUSPENDED.getStateCode()); processDefinitionService.updateProcessDefinitionState(oldDefinition.getId(), SuspensionState.SUSPENDED.getStateCode());
} }
@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);
}
} }

View File

@ -1,10 +1,16 @@
package cn.iocoder.yudao.module.bpm.service.definition; 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.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.bpmn.model.BpmnModel;
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 javax.validation.Valid;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -15,7 +21,55 @@ import java.util.Set;
* @author ZJQ * @author ZJQ
* @author 芋道源码 * @author 芋道源码
*/ */
public interface BpmProcessDefinitionService extends BpmProcessDefinitionCommonService { 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 * 获得编号对应的 ProcessDefinition

View File

@ -4,12 +4,20 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
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.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.BpmTaskAssignRuleCreateReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleRespVO; 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.controller.admin.definition.vo.rule.BpmTaskAssignRuleUpdateReqVO;
import cn.iocoder.yudao.module.bpm.convert.definition.BpmTaskAssignRuleConvert; 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.dataobject.definition.BpmTaskAssignRuleDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper; 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 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.FlowElement;
@ -20,10 +28,10 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.validation.Valid; import javax.validation.Valid;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import java.util.Map; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
/** /**
* BPM 任务分配规则 Service 实现类 * BPM 任务分配规则 Service 实现类
@ -35,13 +43,23 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService{
@Resource @Resource
private BpmTaskAssignRuleMapper taskRuleMapper; private BpmTaskAssignRuleMapper taskRuleMapper;
@Resource @Resource
@Lazy // 解决循环依赖 @Lazy // 解决循环依赖
private BpmModelService modelService; private BpmModelService modelService;
@Resource @Resource
private BpmProcessDefinitionService processDefinitionService; 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 @Override
public List<BpmTaskAssignRuleDO> getTaskAssignRuleListByProcessDefinitionId(String processDefinitionId, String taskDefinitionKey) { public List<BpmTaskAssignRuleDO> getTaskAssignRuleListByProcessDefinitionId(String processDefinitionId, String taskDefinitionKey) {
@ -101,12 +119,38 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService{
@Override @Override
public Long createTaskAssignRule(@Valid BpmTaskAssignRuleCreateReqVO reqVO) { public Long createTaskAssignRule(@Valid BpmTaskAssignRuleCreateReqVO reqVO) {
return null; // 校验参数
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 @Override
public void updateTaskAssignRule(@Valid BpmTaskAssignRuleUpdateReqVO reqVO) { 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 @Override
@ -136,6 +180,49 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService{
@Override @Override
public void copyTaskAssignRules(String fromModelId, String toProcessDefinitionId) { 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));
}
} }
} }