From b1d6baaad8a92c6de7364c2dffbe29ccd5392031 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Fri, 11 Feb 2022 00:01:46 +0800 Subject: [PATCH] 工作流 Flowable 发布流程, 删除模型 的实现 --- yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmAbstractModelService.java | 28 +++++++++++++++++++++++++++- yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionCommonService.java | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java | 28 ++-------------------------- yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java | 50 +------------------------------------------------- yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java | 79 ------------------------------------------------------------------------------- yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java | 47 +++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/FlowableModelController.java | 79 ------------------------------------------------------------------------------- yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java | 43 +++++++++++++++++++++++++++++++++++++++++++ yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmTaskAssignRuleConvert.java | 32 ++++++++++++++++++++++++++++++++ yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/ModelConvert.java | 140 -------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java | 20 ++++++++++++++++++++ yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java | 252 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java | 265 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableModelService.java | 10 ---------- yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableModelServiceImpl.java | 215 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableProcessDefinitionService.java | 86 -------------------------------------------------------------------------------------- yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableProcessDefinitionServiceImpl.java | 136 ---------------------------------------------------------------------------------------------------------------------------------------- 22 files changed, 1299 insertions(+), 821 deletions(-) create mode 100644 yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionCommonService.java create mode 100644 yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java delete mode 100644 yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java create mode 100644 yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java create mode 100644 yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java delete mode 100644 yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/FlowableModelController.java create mode 100644 yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java create mode 100644 yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmTaskAssignRuleConvert.java delete mode 100644 yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/ModelConvert.java create mode 100644 yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java create mode 100644 yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java create mode 100644 yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java create mode 100644 yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java create mode 100644 yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java delete mode 100644 yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableModelService.java delete mode 100644 yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableModelServiceImpl.java delete mode 100644 yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableProcessDefinitionService.java delete mode 100644 yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableProcessDefinitionServiceImpl.java diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmAbstractModelService.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmAbstractModelService.java index d790189..caa8e13 100644 --- a/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmAbstractModelService.java +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmAbstractModelService.java @@ -1,11 +1,14 @@ 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; @@ -21,8 +24,11 @@ public abstract class BpmAbstractModelService { protected final BpmFormService bpmFormService; - public BpmAbstractModelService(BpmFormService bpmFormService) { + protected final BpmTaskAssignRuleService taskAssignRuleService; + + public BpmAbstractModelService(BpmFormService bpmFormService,BpmTaskAssignRuleService taskAssignRuleService) { this.bpmFormService = bpmFormService; + this.taskAssignRuleService = taskAssignRuleService; } /** @@ -47,6 +53,26 @@ public abstract class BpmAbstractModelService { return null; } + /** + * 校验流程模型的任务分配规则全部都配置了 + * 目的:如果有规则未配置,会导致流程任务找不到负责人,进而流程无法进行下去! + * + * @param id 流程模型编号 + */ + protected void checkTaskAssignRuleAllConfig(String id) { + // 一个用户任务都没配置,所以无需配置规则 + List 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)) { diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionCommonService.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionCommonService.java new file mode 100644 index 0000000..51a2ee4 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionCommonService.java @@ -0,0 +1,69 @@ +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 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); +} diff --git a/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java new file mode 100644 index 0000000..19e7f96 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java @@ -0,0 +1,79 @@ +package cn.iocoder.yudao.module.bpm.service.definition; + +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.springframework.lang.Nullable; + +import javax.validation.Valid; +import java.util.List; + +/** + * BPM 任务分配规则 Service 接口 + * + * @author 芋道源码 + */ +public interface BpmTaskAssignRuleService { + + /** + * 获得流程定义的任务分配规则数组 + * + * @param processDefinitionId 流程定义的编号 + * @param taskDefinitionKey 流程任务定义的 Key。允许空 + * @return 任务规则数组 + */ + List getTaskAssignRuleListByProcessDefinitionId(String processDefinitionId, + @Nullable String taskDefinitionKey); + + /** + * 获得流程模型的任务规则数组 + * + * @param modelId 流程模型的编号 + * @return 任务规则数组 + */ + List getTaskAssignRuleListByModelId(String modelId); + + /** + * 获得流程定义的任务分配规则数组 + * + * @param modelId 流程模型的编号 + * @param processDefinitionId 流程定义的编号 + * @return 任务规则数组 + */ + List getTaskAssignRuleList(String modelId, String processDefinitionId); + + /** + * 创建任务分配规则 + * + * @param reqVO 创建信息 + * @return 规则编号 + */ + Long createTaskAssignRule(@Valid BpmTaskAssignRuleCreateReqVO reqVO); + + /** + * 更新任务分配规则 + * + * @param reqVO 创建信息 + */ + void updateTaskAssignRule(@Valid BpmTaskAssignRuleUpdateReqVO reqVO); + + /** + * 判断指定流程模型和流程定义的分配规则是否相等 + * + * @param modelId 流程模型编号 + * @param processDefinitionId 流程定义编号 + * @return 是否相等 + */ + boolean isTaskAssignRulesEquals(String modelId, String processDefinitionId); + + /** + * 将流程流程模型的任务分配规则,复制一份给流程定义 + * 目的:每次流程模型部署时,都会生成一个新的流程定义,此时考虑到每次部署的流程不可变性,所以需要复制一份给该流程定义 + * + * @param fromModelId 流程模型编号 + * @param toProcessDefinitionId 流程定义编号 + */ + void copyTaskAssignRules(String fromModelId, String toProcessDefinitionId); + +} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java index abda72e..4387199 100644 --- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java @@ -52,13 +52,9 @@ public class BpmModelServiceImpl extends BpmAbstractModelService implements BpmM @Resource private BpmProcessDefinitionService processDefinitionService; - @Resource - @Lazy // 解决循环依赖 - private BpmTaskAssignRuleService taskAssignRuleService; - - public BpmModelServiceImpl(BpmFormService bpmFormService) { - super(bpmFormService); + public BpmModelServiceImpl(BpmFormService bpmFormService,BpmTaskAssignRuleService taskAssignRuleService) { + super(bpmFormService, taskAssignRuleService); } @Override @@ -196,26 +192,6 @@ public class BpmModelServiceImpl extends BpmAbstractModelService implements BpmM taskAssignRuleService.copyTaskAssignRules(id, definition.getId()); } - /** - * 校验流程模型的任务分配规则全部都配置了 - * 目的:如果有规则未配置,会导致流程任务找不到负责人,进而流程无法进行下去! - * - * @param id 流程模型编号 - */ - private void checkTaskAssignRuleAllConfig(String id) { - // 一个用户任务都没配置,所以无需配置规则 - List 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()); - } - }); - } - @Override @Transactional(rollbackFor = Exception.class) public void deleteModel(String id) { diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java index afa1e9d..58bba1f 100644 --- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java @@ -24,15 +24,7 @@ import java.util.Set; * @author ZJQ * @author 芋道源码 */ -public interface BpmProcessDefinitionService { - - /** - * 获得流程定义分页 - * - * @param pageReqVO 分页入参 - * @return 流程定义 Page - */ - PageResult getProcessDefinitionPage(BpmProcessDefinitionPageReqVO pageReqVO); +public interface BpmProcessDefinitionService extends BpmProcessDefinitionCommonService { /** * 获得流程定义列表 @@ -43,14 +35,6 @@ public interface BpmProcessDefinitionService { List getProcessDefinitionList(BpmProcessDefinitionListReqVO listReqVO); /** - * 获得流程定义对应的 BPMN XML - * - * @param id 流程定义编号 - * @return BPMN XML - */ - String getProcessDefinitionBpmnXML(String id); - - /** * 获得 Bpmn 模型 * * @param processDefinitionId 流程定义的编号 @@ -85,14 +69,6 @@ public interface BpmProcessDefinitionService { ProcessDefinition getActiveProcessDefinition(String key); /** - * 获得编号对应的 BpmProcessDefinitionExtDO - * - * @param id 编号 - * @return 流程定义拓展 - */ - BpmProcessDefinitionExtDO getProcessDefinitionExt(String id); - - /** * 获得 id 对应的 Deployment * * @param id 部署编号 @@ -134,28 +110,4 @@ public interface BpmProcessDefinitionService { */ List getProcessDefinitionListByDeploymentIds(Set 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); - } diff --git a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java b/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java deleted file mode 100644 index 19e7f96..0000000 --- a/yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java +++ /dev/null @@ -1,79 +0,0 @@ -package cn.iocoder.yudao.module.bpm.service.definition; - -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.springframework.lang.Nullable; - -import javax.validation.Valid; -import java.util.List; - -/** - * BPM 任务分配规则 Service 接口 - * - * @author 芋道源码 - */ -public interface BpmTaskAssignRuleService { - - /** - * 获得流程定义的任务分配规则数组 - * - * @param processDefinitionId 流程定义的编号 - * @param taskDefinitionKey 流程任务定义的 Key。允许空 - * @return 任务规则数组 - */ - List getTaskAssignRuleListByProcessDefinitionId(String processDefinitionId, - @Nullable String taskDefinitionKey); - - /** - * 获得流程模型的任务规则数组 - * - * @param modelId 流程模型的编号 - * @return 任务规则数组 - */ - List getTaskAssignRuleListByModelId(String modelId); - - /** - * 获得流程定义的任务分配规则数组 - * - * @param modelId 流程模型的编号 - * @param processDefinitionId 流程定义的编号 - * @return 任务规则数组 - */ - List getTaskAssignRuleList(String modelId, String processDefinitionId); - - /** - * 创建任务分配规则 - * - * @param reqVO 创建信息 - * @return 规则编号 - */ - Long createTaskAssignRule(@Valid BpmTaskAssignRuleCreateReqVO reqVO); - - /** - * 更新任务分配规则 - * - * @param reqVO 创建信息 - */ - void updateTaskAssignRule(@Valid BpmTaskAssignRuleUpdateReqVO reqVO); - - /** - * 判断指定流程模型和流程定义的分配规则是否相等 - * - * @param modelId 流程模型编号 - * @param processDefinitionId 流程定义编号 - * @return 是否相等 - */ - boolean isTaskAssignRulesEquals(String modelId, String processDefinitionId); - - /** - * 将流程流程模型的任务分配规则,复制一份给流程定义 - * 目的:每次流程模型部署时,都会生成一个新的流程定义,此时考虑到每次部署的流程不可变性,所以需要复制一份给该流程定义 - * - * @param fromModelId 流程模型编号 - * @param toProcessDefinitionId 流程定义编号 - */ - void copyTaskAssignRules(String fromModelId, String toProcessDefinitionId); - -} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java new file mode 100644 index 0000000..1bac188 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java @@ -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> 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 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 createModel(@Valid @RequestBody BpmModelCreateReqVO createRetVO) { + return success(modelService.createModel(createRetVO, null)); + } + + @PutMapping("/update") + @ApiOperation(value = "修改模型") + @PreAuthorize("@ss.hasPermission('bpm:model:update')") + public CommonResult updateModel(@Valid @RequestBody BpmModelUpdateReqVO modelVO) { + modelService.updateModel(modelVO); + return success(true); + } + + @PostMapping("/import") + @ApiOperation(value = "导入模型") + public CommonResult 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 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 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 deleteModel(@RequestParam("id") String id) { + modelService.deleteModel(id); + return success(true); + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java new file mode 100644 index 0000000..2d6ddc0 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java @@ -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> 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 getProcessDefinitionBpmnXML(@RequestParam("id") String id) { + String bpmnXML = bpmDefinitionService.getProcessDefinitionBpmnXML(id); + return success(bpmnXML); + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/FlowableModelController.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/FlowableModelController.java deleted file mode 100644 index 2a51688..0000000 --- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/FlowableModelController.java +++ /dev/null @@ -1,79 +0,0 @@ -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.ModelConvert; -import cn.iocoder.yudao.module.bpm.service.definition.FlowableModelService; -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 FlowableModelController { - - @Resource - private FlowableModelService modelService; - - @GetMapping("/page") - @ApiOperation(value = "获得模型分页") - public CommonResult> 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 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 createModel(@Valid @RequestBody BpmModelCreateReqVO createRetVO) { - return success(modelService.createModel(createRetVO, null)); - } - - @PutMapping("/update") - @ApiOperation(value = "修改模型") - @PreAuthorize("@ss.hasPermission('bpm:model:update')") - public CommonResult updateModel(@Valid @RequestBody BpmModelUpdateReqVO modelVO) { - modelService.updateModel(modelVO); - return success(true); - } - - @PostMapping("/import") - @ApiOperation(value = "导入模型") - public CommonResult importModel(@Valid BpmModeImportReqVO importReqVO) throws IOException { - BpmModelCreateReqVO createReqVO = ModelConvert.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 deployModel(@RequestParam("id") String id) { - modelService.deployModel(id); - return success(true); - } -} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java new file mode 100644 index 0000000..4d1b2a0 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java @@ -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 convertList(List list, Map formMap, + Map deploymentMap, + Map 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); + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java index 4b15ffb..5e81683 100644 --- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java @@ -1,10 +1,22 @@ 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 * @@ -12,7 +24,38 @@ import org.mapstruct.factory.Mappers; */ @Mapper public interface BpmProcessDefinitionConvert { + BpmProcessDefinitionConvert INSTANCE = Mappers.getMapper(BpmProcessDefinitionConvert.class); + BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean); + BpmProcessDefinitionExtDO convert2(BpmProcessDefinitionCreateReqDTO bean); + + default List convertList(List list, Map deploymentMap, + Map processDefinitionDOMap, Map 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); } diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmTaskAssignRuleConvert.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmTaskAssignRuleConvert.java new file mode 100644 index 0000000..992fa0b --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmTaskAssignRuleConvert.java @@ -0,0 +1,32 @@ +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.BpmTaskAssignRuleRespVO; +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 convertList(List tasks, List rules) { + Map 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); +} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/ModelConvert.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/ModelConvert.java deleted file mode 100644 index 4c7cd01..0000000 --- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/ModelConvert.java +++ /dev/null @@ -1,140 +0,0 @@ -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 ModelConvert { - - ModelConvert INSTANCE = Mappers.getMapper(ModelConvert.class); - - default List convertList(List list, Map formMap, - Map deploymentMap, - Map 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); - } -} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java new file mode 100644 index 0000000..9bd4551 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.bpm.service.definition; + +import org.flowable.bpmn.model.BpmnModel; + +/** + * Flowable流程模型接口 + * + * @author yunlongn + */ +public interface BpmModelService extends BpmModelCommonService { + + /** + * 获得流程模型编号对应的 BPMN Model + * + * @param id 流程模型编号 + * @return BPMN Model + */ + BpmnModel getBpmnModel(String id); + +} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java new file mode 100644 index 0000000..a1558d6 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java @@ -0,0 +1,252 @@ +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.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.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 extends BpmAbstractModelService implements BpmModelService { + + @Resource + private RepositoryService repositoryService; + @Resource + private BpmProcessDefinitionService processDefinitionService; + + public BpmModelServiceImpl(BpmFormService bpmFormService, BpmTaskAssignRuleService taskAssignRuleService){ + super(bpmFormService, taskAssignRuleService); + } + + @Override + public PageResult 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 models = modelQuery.orderByCreateTime().desc() + .listPage(PageUtils.getStart(pageVO), pageVO.getPageSize()); + + // 获得 Form Map + Set formIds = CollectionUtils.convertSet(models, model -> { + BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class); + return metaInfo != null ? metaInfo.getFormId() : null; + }); + Map formMap = bpmFormService.getFormMap(formIds); + + // 获得 Deployment Map + Set deploymentIds = new HashSet<>(); + models.forEach(model -> CollectionUtils.addIfNotNull(deploymentIds, model.getDeploymentId())); + Map deploymentMap = processDefinitionService.getDeploymentMap(deploymentIds); + // 获得 ProcessDefinition Map + List processDefinitions = processDefinitionService.getProcessDefinitionListByDeploymentIds(deploymentIds); + Map 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()); + //校验任务分配规则已配置 + 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); + + //TODO 复制任务分配规则 + //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); + } + + 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()); + } + + @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); + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java new file mode 100644 index 0000000..121bdc2 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.bpm.service.definition; + +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import org.flowable.bpmn.model.BpmnModel; +import org.flowable.engine.repository.Deployment; +import org.flowable.engine.repository.ProcessDefinition; + +import java.util.List; +import java.util.Map; +import java.util.Set; +/** + * Flowable流程定义接口 + * + * @author yunlong.li + * @author ZJQ + * @author 芋道源码 + */ +public interface BpmProcessDefinitionService extends BpmProcessDefinitionCommonService { + + /** + * 获得编号对应的 ProcessDefinition + * + * @param id 编号 + * @return 流程定义 + */ + ProcessDefinition getProcessDefinition(String id); + + /** + * 获得 deploymentId 对应的 ProcessDefinition + * + * @param deploymentId 部署编号 + * @return 流程定义 + */ + ProcessDefinition getProcessDefinitionByDeploymentId(String deploymentId); + + /** + * 获得 deploymentIds 对应的 ProcessDefinition 数组 + * + * @param deploymentIds 部署编号的数组 + * @return 流程定义的数组 + */ + List getProcessDefinitionListByDeploymentIds(Set deploymentIds); + + /** + * 获得流程定义标识对应的激活的流程定义 + * + * @param key 流程定义的标识 + * @return 流程定义 + */ + ProcessDefinition getActiveProcessDefinition(String key); + + /** + * 获得 ids 对应的 Deployment Map + * + * @param ids 部署编号的数组 + * @return 流程部署 Map + */ + default Map getDeploymentMap(Set ids) { + return CollectionUtils.convertMap(getDeployments(ids), Deployment::getId); + } + + /** + * 获得 ids 对应的 Deployment 数组 + * + * @param ids 部署编号的数组 + * @return 流程部署的数组 + */ + List getDeployments(Set ids); + + /** + * 获得 id 对应的 Deployment + * + * @param id 部署编号 + * @return 流程部署 + */ + Deployment getDeployment(String id); + + /** + * 获得 Bpmn 模型 + * + * @param processDefinitionId 流程定义的编号 + * @return Bpmn 模型 + */ + BpmnModel getBpmnModel(String processDefinitionId); +} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java new file mode 100644 index 0000000..cb34194 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java @@ -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 getProcessDefinitionListByDeploymentIds(Set 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 getDeployments(Set ids) { + if (CollUtil.isEmpty(ids)) { + return emptyList(); + } + List 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 中的 的 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 getProcessDefinitionPage(BpmProcessDefinitionPageReqVO pageVO) { + ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery(); + if (StrUtil.isNotBlank(pageVO.getKey())) { + definitionQuery.processDefinitionKey(pageVO.getKey()); + } + + // 执行查询 + List processDefinitions = definitionQuery.orderByProcessDefinitionVersion().desc() + .listPage(PageUtils.getStart(pageVO), pageVO.getPageSize()); + + if (CollUtil.isEmpty(processDefinitions)) { + return new PageResult<>(emptyList(), definitionQuery.count()); + } + // 获得 Deployment Map + Set deploymentIds = new HashSet<>(); + processDefinitions.forEach(definition -> addIfNotNull(deploymentIds, definition.getDeploymentId())); + Map deploymentMap = getDeploymentMap(deploymentIds); + + // 获得 BpmProcessDefinitionDO Map + List processDefinitionDOs = processDefinitionMapper.selectListByProcessDefinitionIds( + convertList(processDefinitions, ProcessDefinition::getId)); + Map processDefinitionDOMap = convertMap(processDefinitionDOs, + BpmProcessDefinitionExtDO::getProcessDefinitionId); + + // 获得 Form Map + Set formIds = convertSet(processDefinitionDOs, BpmProcessDefinitionExtDO::getFormId); + Map formMap = formService.getFormMap(formIds); + + // 拼接结果 + long definitionCount = definitionQuery.count(); + return new PageResult<>(BpmProcessDefinitionConvert.INSTANCE.convertList(processDefinitions, deploymentMap, + processDefinitionDOMap, formMap), definitionCount); + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java new file mode 100644 index 0000000..26cf938 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java @@ -0,0 +1,141 @@ +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.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 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.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * BPM 任务分配规则 Service 实现类 + */ +@Service +@Validated +@Slf4j +public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService{ + + @Resource + private BpmTaskAssignRuleMapper taskRuleMapper; + + @Resource + @Lazy // 解决循环依赖 + private BpmModelService modelService; + + @Resource + private BpmProcessDefinitionService processDefinitionService; + + @Override + public List getTaskAssignRuleListByProcessDefinitionId(String processDefinitionId, String taskDefinitionKey) { + return taskRuleMapper.selectListByProcessDefinitionId(processDefinitionId, taskDefinitionKey); + } + + @Override + public List getTaskAssignRuleListByModelId(String modelId) { + return taskRuleMapper.selectListByModelId(modelId); + } + + @Override + public List getTaskAssignRuleList(String modelId, String processDefinitionId) { + // 获得规则 + List 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 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 List getBpmnModelElements(BpmnModel model, Class clazz) { + List 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) { + return null; + } + + @Override + public void updateTaskAssignRule(@Valid BpmTaskAssignRuleUpdateReqVO reqVO) { + + } + + @Override + public boolean isTaskAssignRulesEquals(String modelId, String processDefinitionId) { + // 调用 VO 接口的原因是,过滤掉流程模型不需要的规则,保持和 copyTaskAssignRules 方法的一致性 + List modelRules = getTaskAssignRuleList(modelId, null); + List processInstanceRules = getTaskAssignRuleList(null, processDefinitionId); + if (modelRules.size() != processInstanceRules.size()) { + return false; + } + + // 遍历,匹配对应的规则 + Map 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) { + + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableModelService.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableModelService.java deleted file mode 100644 index bbc304d..0000000 --- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableModelService.java +++ /dev/null @@ -1,10 +0,0 @@ -package cn.iocoder.yudao.module.bpm.service.definition; - -/** - * Flowable流程模型接口 - * - * @author yunlongn - */ -public interface FlowableModelService extends BpmModelCommonService { - -} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableModelServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableModelServiceImpl.java deleted file mode 100644 index 12354db..0000000 --- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableModelServiceImpl.java +++ /dev/null @@ -1,215 +0,0 @@ -package cn.iocoder.yudao.module.bpm.service.definition; - -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.module.bpm.controller.admin.definition.vo.model.*; -import cn.iocoder.yudao.module.bpm.convert.definition.ModelConvert; -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 lombok.extern.slf4j.Slf4j; -import org.flowable.common.engine.impl.db.SuspensionState; -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 FlowableModelServiceImpl extends BpmAbstractModelService implements FlowableModelService { - - @Resource - private RepositoryService repositoryService; - @Resource - private FlowableProcessDefinitionService processDefinitionService; - - public FlowableModelServiceImpl(BpmFormService bpmFormService){ - super(bpmFormService); - } - - @Override - public PageResult 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 models = modelQuery.orderByCreateTime().desc() - .listPage(PageUtils.getStart(pageVO), pageVO.getPageSize()); - - // 获得 Form Map - Set formIds = CollectionUtils.convertSet(models, model -> { - BpmModelMetaInfoRespDTO metaInfo = JsonUtils.parseObject(model.getMetaInfo(), BpmModelMetaInfoRespDTO.class); - return metaInfo != null ? metaInfo.getFormId() : null; - }); - Map formMap = bpmFormService.getFormMap(formIds); - - // 获得 Deployment Map - Set deploymentIds = new HashSet<>(); - models.forEach(model -> CollectionUtils.addIfNotNull(deploymentIds, model.getDeploymentId())); - Map deploymentMap = processDefinitionService.getDeploymentMap(deploymentIds); - // 获得 ProcessDefinition Map - List processDefinitions = processDefinitionService.getProcessDefinitionListByDeploymentIds(deploymentIds); - Map processDefinitionMap = convertMap(processDefinitions, ProcessDefinition::getDeploymentId); - - // 拼接结果 - long modelCount = modelQuery.count(); - return new PageResult<>(ModelConvert.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(); - ModelConvert.INSTANCE.copy(model, createReqVO); - // 保存流程定义 - repositoryService.saveModel(model); - // 保存 BPMN XML - saveModelBpmnXml(model, bpmnXml); - return model.getId(); - } - - @Override - public BpmModelRespVO getModel(String id) { - Model model = repositoryService.getModel(id); - if (model == null) { - return null; - } - BpmModelRespVO modelRespVO = ModelConvert.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); - } - - // 修改流程定义 - ModelConvert.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()); - //TODO 校验任务分配规则已配置 - //checkTaskAssignRuleAllConfig(id); - - BpmProcessDefinitionCreateReqDTO definitionCreateReqDTO = ModelConvert.INSTANCE.convert2(model, form).setBpmnBytes(bpmnBytes); - // TODO 校验模型是否发生修改。如果未修改,则不允许创建 -// 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); - - //TODO 复制任务分配规则 - //taskAssignRuleService.copyTaskAssignRules(id, definition.getId()); - } - - @Override - public void deleteModel(String id) { - - } - - @Override - public void updateModelState(String id, Integer state) { - - } - - - - private Model getModelByKey(String key) { - return repositoryService.createModelQuery().modelKey(key).singleResult(); - } - - - private void saveModelBpmnXml(Model model, String bpmnXml) { - if (StrUtil.isEmpty(bpmnXml)) { - return; - } - repositoryService.addModelEditorSource(model.getId(), StrUtil.utf8Bytes(bpmnXml)); - } - - 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()); - } -} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableProcessDefinitionService.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableProcessDefinitionService.java deleted file mode 100644 index c7643c1..0000000 --- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableProcessDefinitionService.java +++ /dev/null @@ -1,86 +0,0 @@ -package cn.iocoder.yudao.module.bpm.service.definition; - -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; -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 FlowableProcessDefinitionService { - - /** - * 获得编号对应的 ProcessDefinition - * - * @param id 编号 - * @return 流程定义 - */ - ProcessDefinition getProcessDefinition(String id); - - /** - * 获得 deploymentId 对应的 ProcessDefinition - * - * @param deploymentId 部署编号 - * @return 流程定义 - */ - ProcessDefinition getProcessDefinitionByDeploymentId(String deploymentId); - - /** - * 获得 deploymentIds 对应的 ProcessDefinition 数组 - * - * @param deploymentIds 部署编号的数组 - * @return 流程定义的数组 - */ - List getProcessDefinitionListByDeploymentIds(Set deploymentIds); - - /** - * 获得 ids 对应的 Deployment Map - * - * @param ids 部署编号的数组 - * @return 流程部署 Map - */ - default Map getDeploymentMap(Set ids) { - return CollectionUtils.convertMap(getDeployments(ids), Deployment::getId); - } - - /** - * 获得 ids 对应的 Deployment 数组 - * - * @param ids 部署编号的数组 - * @return 流程部署的数组 - */ - List getDeployments(Set ids); - - /** - * 获得 id 对应的 Deployment - * - * @param id 部署编号 - * @return 流程部署 - */ - Deployment getDeployment(String id); - - /** - * 创建流程定义 - * - * @param createReqDTO 创建信息 - * @return 流程编号 - */ - String createProcessDefinition(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO); - - /** - * 更新流程定义状态 - * - * @param id 流程定义的编号 - * @param state 状态 - */ - void updateProcessDefinitionState(String id, Integer state); -} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableProcessDefinitionServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableProcessDefinitionServiceImpl.java deleted file mode 100644 index f205d32..0000000 --- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/FlowableProcessDefinitionServiceImpl.java +++ /dev/null @@ -1,136 +0,0 @@ -package cn.iocoder.yudao.module.bpm.service.definition; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.module.bpm.convert.definition.BpmProcessDefinitionConvert; -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.common.engine.impl.db.SuspensionState; -import org.flowable.engine.RepositoryService; -import org.flowable.engine.repository.Deployment; -import org.flowable.engine.repository.ProcessDefinition; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; -import javax.validation.Valid; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Set; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.addIfNotNull; -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 FlowableProcessDefinitionServiceImpl implements FlowableProcessDefinitionService { - - private static final String BPMN_FILE_SUFFIX = ".bpmn"; - - @Resource - private RepositoryService repositoryService; - - @Resource - private BpmProcessDefinitionExtMapper processDefinitionMapper; - - @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 getProcessDefinitionListByDeploymentIds(Set deploymentIds) { - if (CollUtil.isEmpty(deploymentIds)) { - return emptyList(); - } - return repositoryService.createProcessDefinitionQuery().deploymentIds(deploymentIds).list(); - } - - @Override - public List getDeployments(Set ids) { - if (CollUtil.isEmpty(ids)) { - return emptyList(); - } - List 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 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 中的 的 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); - } -} -- libgit2 0.21.4