Commit fe7a68c41e0e1502483be2769c133be635ef4dad

Authored by YunaiV
1 parent c2db893f

bpm 增加流程定义的信息未发生变化时,部署不生效

Showing 13 changed files with 136 additions and 61 deletions
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/activity/BpmActivityRespVO.java
@@ -23,20 +23,4 @@ public class BpmActivityRespVO { @@ -23,20 +23,4 @@ public class BpmActivityRespVO {
23 @ApiModelProperty(value = "关联的流程任务的编号", example = "2048", notes = "关联的流程任务,只有 UserTask 等类型才有") 23 @ApiModelProperty(value = "关联的流程任务的编号", example = "2048", notes = "关联的流程任务,只有 UserTask 等类型才有")
24 private String taskId; 24 private String taskId;
25 25
26 - /**  
27 - * 关联的流程任务,只有 UserTask 类型才有  
28 - */  
29 - private Task task;  
30 -  
31 - @ApiModel(value = "流程任务")  
32 - @Data  
33 - public static class Task {  
34 -  
35 - @ApiModelProperty(value = "关联的流程任务的编号", required = true, example = "2048")  
36 - private String id;  
37 - @ApiModelProperty(value = "关联的流程任务的结果", required = true, example = "2", notes = "参见 bpm_process_instance_result 枚举")  
38 - private Integer result;  
39 -  
40 - }  
41 -  
42 } 26 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmModelConvert.java
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.adminserver.modules.bpm.convert.definition; @@ -3,7 +3,7 @@ package cn.iocoder.yudao.adminserver.modules.bpm.convert.definition;
3 import cn.hutool.core.util.StrUtil; 3 import cn.hutool.core.util.StrUtil;
4 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.model.*; 4 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.model.*;
5 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO; 5 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO;
6 -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO; 6 +import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
7 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmModelMetaInfoRespDTO; 7 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
8 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 8 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
9 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 9 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
@@ -83,8 +83,8 @@ public interface BpmModelConvert { @@ -83,8 +83,8 @@ public interface BpmModelConvert {
83 83
84 void copyTo(BpmModelMetaInfoRespDTO from, @MappingTarget BpmModelBaseVO to); 84 void copyTo(BpmModelMetaInfoRespDTO from, @MappingTarget BpmModelBaseVO to);
85 85
86 - default BpmDefinitionCreateReqDTO convert2(Model model, BpmFormDO form) {  
87 - BpmDefinitionCreateReqDTO createReqDTO = new BpmDefinitionCreateReqDTO(); 86 + default BpmProcessDefinitionCreateReqDTO convert2(Model model, BpmFormDO form) {
  87 + BpmProcessDefinitionCreateReqDTO createReqDTO = new BpmProcessDefinitionCreateReqDTO();
88 createReqDTO.setModelId(model.getId()); 88 createReqDTO.setModelId(model.getId());
89 createReqDTO.setName(model.getName()); 89 createReqDTO.setName(model.getName());
90 createReqDTO.setKey(model.getKey()); 90 createReqDTO.setKey(model.getKey());
@@ -100,7 +100,7 @@ public interface BpmModelConvert { @@ -100,7 +100,7 @@ public interface BpmModelConvert {
100 return createReqDTO; 100 return createReqDTO;
101 } 101 }
102 102
103 - void copyTo(BpmModelMetaInfoRespDTO from, @MappingTarget BpmDefinitionCreateReqDTO to); 103 + void copyTo(BpmModelMetaInfoRespDTO from, @MappingTarget BpmProcessDefinitionCreateReqDTO to);
104 104
105 default void copy(Model model, BpmModelCreateReqVO bean) { 105 default void copy(Model model, BpmModelCreateReqVO bean) {
106 model.setName(bean.getName()); 106 model.setName(bean.getName());
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/definition/BpmProcessDefinitionConvert.java
@@ -4,7 +4,7 @@ import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process @@ -4,7 +4,7 @@ import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process
4 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionRespVO; 4 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionRespVO;
5 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; 5 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
6 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO; 6 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO;
7 -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO; 7 +import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
8 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 8 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
9 import org.activiti.engine.impl.persistence.entity.SuspensionState; 9 import org.activiti.engine.impl.persistence.entity.SuspensionState;
10 import org.activiti.engine.repository.Deployment; 10 import org.activiti.engine.repository.Deployment;
@@ -55,7 +55,7 @@ public interface BpmProcessDefinitionConvert { @@ -55,7 +55,7 @@ public interface BpmProcessDefinitionConvert {
55 55
56 BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean); 56 BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean);
57 57
58 - BpmProcessDefinitionExtDO convert2(BpmDefinitionCreateReqDTO bean); 58 + BpmProcessDefinitionExtDO convert2(BpmProcessDefinitionCreateReqDTO bean);
59 59
60 default List<BpmProcessDefinitionRespVO> convertList3(List<ProcessDefinition> list, 60 default List<BpmProcessDefinitionRespVO> convertList3(List<ProcessDefinition> list,
61 Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap) { 61 Map<String, BpmProcessDefinitionExtDO> processDefinitionDOMap) {
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/convert/task/BpmActivityConvert.java
@@ -22,16 +22,7 @@ public interface BpmActivityConvert { @@ -22,16 +22,7 @@ public interface BpmActivityConvert {
22 22
23 BpmActivityConvert INSTANCE = Mappers.getMapper(BpmActivityConvert.class); 23 BpmActivityConvert INSTANCE = Mappers.getMapper(BpmActivityConvert.class);
24 24
25 - default List<BpmActivityRespVO> convertList(List<HistoricActivityInstance> list, Map<String, BpmTaskExtDO> taskExtMap) {  
26 - return CollectionUtils.convertList(list, bean -> {  
27 - BpmActivityRespVO respVO = convert(bean);  
28 - BpmTaskExtDO taskExt = taskExtMap.get(bean.getTaskId());  
29 - if (taskExt != null) {  
30 - respVO.setTask(new BpmActivityRespVO.Task().setId(taskExt.getTaskId()).setResult(taskExt.getResult()));  
31 - }  
32 - return respVO;  
33 - });  
34 - } 25 + List<BpmActivityRespVO> convertList(List<HistoricActivityInstance> list);
35 26
36 @Mappings({ 27 @Mappings({
37 @Mapping(source = "activityId", target = "key"), 28 @Mapping(source = "activityId", target = "key"),
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/BpmErrorCodeConstants.java
@@ -28,6 +28,7 @@ public interface BpmErrorCodeConstants { @@ -28,6 +28,7 @@ public interface BpmErrorCodeConstants {
28 ErrorCode MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG = new ErrorCode(1009002003, "部署流程失败,原因:流程表单未配置,请点击【修改流程】按钮进行配置"); 28 ErrorCode MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG = new ErrorCode(1009002003, "部署流程失败,原因:流程表单未配置,请点击【修改流程】按钮进行配置");
29 ErrorCode MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG = new ErrorCode(1009002004, "部署流程失败," + 29 ErrorCode MODEL_DEPLOY_FAIL_TASK_ASSIGN_RULE_NOT_CONFIG = new ErrorCode(1009002004, "部署流程失败," +
30 "原因:用户任务({})未配置分配规则,请点击【修改流程】按钮进行配置"); 30 "原因:用户任务({})未配置分配规则,请点击【修改流程】按钮进行配置");
  31 + ErrorCode MODEL_DEPLOY_FAIL_TASK_INFO_EQUALS = new ErrorCode(1009003005, "流程定义部署失败,原因:信息未发生变化");
31 32
32 // ========== 流程定义 1-009-003-000 ========== 33 // ========== 流程定义 1-009-003-000 ==========
33 ErrorCode PROCESS_DEFINITION_KEY_NOT_MATCH = new ErrorCode(1009003000, "流程定义的标识期望是({}),当前是({}),请修改 BPMN 流程图"); 34 ErrorCode PROCESS_DEFINITION_KEY_NOT_MATCH = new ErrorCode(1009003000, "流程定义的标识期望是({}),当前是({}),请修改 BPMN 流程图");
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmProcessDefinitionService.java
@@ -5,7 +5,7 @@ import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process @@ -5,7 +5,7 @@ import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process
5 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionPageReqVO; 5 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionPageReqVO;
6 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionRespVO; 6 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionRespVO;
7 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; 7 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
8 -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO; 8 +import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
9 import cn.iocoder.yudao.framework.common.pojo.PageResult; 9 import cn.iocoder.yudao.framework.common.pojo.PageResult;
10 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 10 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
11 import org.activiti.bpmn.model.BpmnModel; 11 import org.activiti.bpmn.model.BpmnModel;
@@ -126,12 +126,20 @@ public interface BpmProcessDefinitionService { @@ -126,12 +126,20 @@ public interface BpmProcessDefinitionService {
126 List<ProcessDefinition> getProcessDefinitionListByDeploymentIds(Set<String> deploymentIds); 126 List<ProcessDefinition> getProcessDefinitionListByDeploymentIds(Set<String> deploymentIds);
127 127
128 /** 128 /**
  129 + * 获得需要创建的流程定义,是否和当前激活的流程定义相等
  130 + *
  131 + * @param createReqDTO 创建信息
  132 + * @return 是否相等
  133 + */
  134 + boolean isProcessDefinitionEquals(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
  135 +
  136 + /**
129 * 创建流程定义 137 * 创建流程定义
130 * 138 *
131 * @param createReqDTO 创建信息 139 * @param createReqDTO 创建信息
132 * @return 流程编号 140 * @return 流程编号
133 */ 141 */
134 - String createProcessDefinition(@Valid BpmDefinitionCreateReqDTO createReqDTO); 142 + String createProcessDefinition(@Valid BpmProcessDefinitionCreateReqDTO createReqDTO);
135 143
136 /** 144 /**
137 * 更新流程定义的挂起状态 145 * 更新流程定义的挂起状态
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/BpmTaskAssignRuleService.java
@@ -60,6 +60,15 @@ public interface BpmTaskAssignRuleService { @@ -60,6 +60,15 @@ public interface BpmTaskAssignRuleService {
60 void updateTaskAssignRule(@Valid BpmTaskAssignRuleUpdateReqVO reqVO); 60 void updateTaskAssignRule(@Valid BpmTaskAssignRuleUpdateReqVO reqVO);
61 61
62 /** 62 /**
  63 + * 判断指定流程模型和流程定义的分配规则是否相等
  64 + *
  65 + * @param modelId 流程模型编号
  66 + * @param processDefinitionId 流程定义编号
  67 + * @return 是否相等
  68 + */
  69 + boolean isTaskAssignRulesEquals(String modelId, String processDefinitionId);
  70 +
  71 + /**
63 * 将流程流程模型的任务分配规则,复制一份给流程定义 72 * 将流程流程模型的任务分配规则,复制一份给流程定义
64 * 目的:每次流程模型部署时,都会生成一个新的流程定义,此时考虑到每次部署的流程不可变性,所以需要复制一份给该流程定义 73 * 目的:每次流程模型部署时,都会生成一个新的流程定义,此时考虑到每次部署的流程不可变性,所以需要复制一份给该流程定义
65 * 74 *
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/dto/BpmDefinitionCreateReqDTO.java renamed to yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java
@@ -18,7 +18,7 @@ import java.util.Objects; @@ -18,7 +18,7 @@ import java.util.Objects;
18 * 流程定义创建 Request DTO 18 * 流程定义创建 Request DTO
19 */ 19 */
20 @Data 20 @Data
21 -public class BpmDefinitionCreateReqDTO { 21 +public class BpmProcessDefinitionCreateReqDTO {
22 22
23 // ========== 模型相关 ========== 23 // ========== 模型相关 ==========
24 24
@@ -51,7 +51,7 @@ public class BpmDefinitionCreateReqDTO { @@ -51,7 +51,7 @@ public class BpmDefinitionCreateReqDTO {
51 * BPMN XML 51 * BPMN XML
52 */ 52 */
53 @NotEmpty(message = "BPMN XML 不能为空") 53 @NotEmpty(message = "BPMN XML 不能为空")
54 - private String bpmnXml; 54 + private byte[] bpmnBytes;
55 55
56 // ========== 表单相关 ========== 56 // ========== 表单相关 ==========
57 57
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmModelServiceImpl.java
@@ -10,7 +10,7 @@ import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFor @@ -10,7 +10,7 @@ import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFor
10 import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmModelFormTypeEnum; 10 import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmModelFormTypeEnum;
11 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService; 11 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService;
12 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmTaskAssignRuleService; 12 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmTaskAssignRuleService;
13 -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO; 13 +import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
14 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmFormService; 14 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmFormService;
15 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmModelService; 15 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmModelService;
16 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmModelMetaInfoRespDTO; 16 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmModelMetaInfoRespDTO;
@@ -21,11 +21,9 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -21,11 +21,9 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
21 import cn.iocoder.yudao.framework.common.util.object.PageUtils; 21 import cn.iocoder.yudao.framework.common.util.object.PageUtils;
22 import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; 22 import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
23 import lombok.extern.slf4j.Slf4j; 23 import lombok.extern.slf4j.Slf4j;
24 -import org.activiti.bpmn.converter.BpmnXMLConverter;  
25 import org.activiti.bpmn.model.BpmnModel; 24 import org.activiti.bpmn.model.BpmnModel;
26 import org.activiti.engine.RepositoryService; 25 import org.activiti.engine.RepositoryService;
27 import org.activiti.engine.impl.persistence.entity.SuspensionState; 26 import org.activiti.engine.impl.persistence.entity.SuspensionState;
28 -import org.activiti.engine.impl.util.io.StringStreamSource;  
29 import org.activiti.engine.repository.Deployment; 27 import org.activiti.engine.repository.Deployment;
30 import org.activiti.engine.repository.Model; 28 import org.activiti.engine.repository.Model;
31 import org.activiti.engine.repository.ModelQuery; 29 import org.activiti.engine.repository.ModelQuery;
@@ -38,7 +36,6 @@ import org.springframework.validation.annotation.Validated; @@ -38,7 +36,6 @@ import org.springframework.validation.annotation.Validated;
38 36
39 import javax.annotation.Resource; 37 import javax.annotation.Resource;
40 import java.util.*; 38 import java.util.*;
41 -import java.util.function.Consumer;  
42 39
43 import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*; 40 import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*;
44 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 41 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -175,14 +172,19 @@ public class BpmModelServiceImpl implements BpmModelService { @@ -175,14 +172,19 @@ public class BpmModelServiceImpl implements BpmModelService {
175 } 172 }
176 // TODO 芋艿:校验流程图的有效性;例如说,是否有开始的元素,是否有结束的元素; 173 // TODO 芋艿:校验流程图的有效性;例如说,是否有开始的元素,是否有结束的元素;
177 // 校验表单已配 174 // 校验表单已配
178 - // 校验表单存在  
179 BpmFormDO form = checkFormConfig(model); 175 BpmFormDO form = checkFormConfig(model);
180 // 校验任务分配规则已配置 176 // 校验任务分配规则已配置
181 checkTaskAssignRuleAllConfig(id); 177 checkTaskAssignRuleAllConfig(id);
182 178
  179 + // 校验模型是否发生修改。如果未修改,则不允许创建
  180 + BpmProcessDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form).setBpmnBytes(bpmnBytes);
  181 + if (processDefinitionService.isProcessDefinitionEquals(definitionCreateReqDTO)) { // 流程定义的信息相等
  182 + ProcessDefinition oldProcessInstance = processDefinitionService.getProcessDefinitionByDeploymentId(model.getDeploymentId());
  183 + if (oldProcessInstance != null && taskAssignRuleService.isTaskAssignRulesEquals(model.getId(), oldProcessInstance.getId())) {
  184 + throw exception(MODEL_DEPLOY_FAIL_TASK_INFO_EQUALS);
  185 + }
  186 + }
183 // 创建流程定义 187 // 创建流程定义
184 - BpmDefinitionCreateReqDTO definitionCreateReqDTO = BpmModelConvert.INSTANCE.convert2(model, form)  
185 - .setBpmnXml(StrUtil.utf8Str(bpmnBytes));  
186 String definitionId = processDefinitionService.createProcessDefinition(definitionCreateReqDTO); 188 String definitionId = processDefinitionService.createProcessDefinition(definitionCreateReqDTO);
187 189
188 // 将老的流程定义进行挂起。也就是说,只有最新部署的流程定义,才可以发起任务。 190 // 将老的流程定义进行挂起。也就是说,只有最新部署的流程定义,才可以发起任务。
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmProcessDefinitionServiceImpl.java
1 package cn.iocoder.yudao.adminserver.modules.bpm.service.definition.impl; 1 package cn.iocoder.yudao.adminserver.modules.bpm.service.definition.impl;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjectUtil;
4 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
5 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionListReqVO; 6 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionListReqVO;
6 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionPageItemRespVO; 7 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
7 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionPageReqVO; 8 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionPageReqVO;
8 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionRespVO; 9 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.process.BpmProcessDefinitionRespVO;
9 import cn.iocoder.yudao.adminserver.modules.bpm.convert.definition.BpmProcessDefinitionConvert; 10 import cn.iocoder.yudao.adminserver.modules.bpm.convert.definition.BpmProcessDefinitionConvert;
10 -import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;  
11 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO; 11 import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmFormDO;
  12 +import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
12 import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.definition.BpmProcessDefinitionExtMapper; 13 import cn.iocoder.yudao.adminserver.modules.bpm.dal.mysql.definition.BpmProcessDefinitionExtMapper;
13 -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService;  
14 -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmDefinitionCreateReqDTO;  
15 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmFormService; 14 import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmFormService;
  15 +import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService;
  16 +import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO;
16 import cn.iocoder.yudao.framework.activiti.core.util.ActivitiUtils; 17 import cn.iocoder.yudao.framework.activiti.core.util.ActivitiUtils;
17 import cn.iocoder.yudao.framework.common.pojo.PageResult; 18 import cn.iocoder.yudao.framework.common.pojo.PageResult;
18 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
19 import cn.iocoder.yudao.framework.common.util.object.PageUtils; 19 import cn.iocoder.yudao.framework.common.util.object.PageUtils;
20 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
21 -import org.activiti.bpmn.converter.BpmnXMLConverter;  
22 import org.activiti.bpmn.model.BpmnModel; 21 import org.activiti.bpmn.model.BpmnModel;
23 import org.activiti.engine.RepositoryService; 22 import org.activiti.engine.RepositoryService;
24 import org.activiti.engine.impl.persistence.entity.SuspensionState; 23 import org.activiti.engine.impl.persistence.entity.SuspensionState;
@@ -32,8 +31,7 @@ import org.springframework.validation.annotation.Validated; @@ -32,8 +31,7 @@ import org.springframework.validation.annotation.Validated;
32 import javax.annotation.Resource; 31 import javax.annotation.Resource;
33 import java.util.*; 32 import java.util.*;
34 33
35 -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.PROCESS_DEFINITION_KEY_NOT_MATCH;  
36 -import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.PROCESS_DEFINITION_NAME_NOT_MATCH; 34 +import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*;
37 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 35 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
38 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; 36 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
39 import static java.util.Collections.emptyList; 37 import static java.util.Collections.emptyList;
@@ -139,6 +137,16 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @@ -139,6 +137,16 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
139 return repositoryService.createProcessDefinitionQuery().processDefinitionId(id).singleResult(); 137 return repositoryService.createProcessDefinitionQuery().processDefinitionId(id).singleResult();
140 } 138 }
141 139
  140 + /**
  141 + * 获得流程定义标识对应的激活的流程定义
  142 + *
  143 + * @param processDefinitionKey 流程定义的标识
  144 + * @return 流程定义
  145 + */
  146 + private ProcessDefinition getActiveProcessDefinition(String processDefinitionKey) {
  147 + return repositoryService.createProcessDefinitionQuery().processDefinitionKey(processDefinitionKey).active().singleResult();
  148 + }
  149 +
142 @Override 150 @Override
143 public BpmProcessDefinitionExtDO getProcessDefinitionExt(String id) { 151 public BpmProcessDefinitionExtDO getProcessDefinitionExt(String id) {
144 return processDefinitionMapper.selectByProcessDefinitionId(id); 152 return processDefinitionMapper.selectByProcessDefinitionId(id);
@@ -166,6 +174,9 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @@ -166,6 +174,9 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
166 174
167 @Override 175 @Override
168 public ProcessDefinition getProcessDefinitionByDeploymentId(String deploymentId) { 176 public ProcessDefinition getProcessDefinitionByDeploymentId(String deploymentId) {
  177 + if (StrUtil.isEmpty(deploymentId)) {
  178 + return null;
  179 + }
169 return repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult(); 180 return repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
170 } 181 }
171 182
@@ -178,12 +189,44 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @@ -178,12 +189,44 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
178 } 189 }
179 190
180 @Override 191 @Override
  192 + public boolean isProcessDefinitionEquals(BpmProcessDefinitionCreateReqDTO createReqDTO) {
  193 + // 校验 name、description 是否更新
  194 + ProcessDefinition oldProcessDefinition = getActiveProcessDefinition(createReqDTO.getKey());
  195 + if (oldProcessDefinition == null) {
  196 + return false;
  197 + }
  198 + BpmProcessDefinitionExtDO oldProcessDefinitionExt = getProcessDefinitionExt(oldProcessDefinition.getId());
  199 + if (!StrUtil.equals(createReqDTO.getName(), oldProcessDefinition.getName())
  200 + || !StrUtil.equals(createReqDTO.getDescription(), oldProcessDefinitionExt.getDescription())
  201 + || !StrUtil.equals(createReqDTO.getCategory(), oldProcessDefinition.getCategory())) {
  202 + return false;
  203 + }
  204 + // 校验 form 信息是否更新
  205 + if (!ObjectUtil.equal(createReqDTO.getFormType(), oldProcessDefinitionExt.getFormType())
  206 + || !ObjectUtil.equal(createReqDTO.getFormId(), oldProcessDefinitionExt.getFormId())
  207 + || !ObjectUtil.equal(createReqDTO.getFormConf(), oldProcessDefinitionExt.getFormConf())
  208 + || !ObjectUtil.equal(createReqDTO.getFormFields(), oldProcessDefinitionExt.getFormFields())
  209 + || !ObjectUtil.equal(createReqDTO.getFormCustomCreatePath(), oldProcessDefinitionExt.getFormCustomCreatePath())
  210 + || !ObjectUtil.equal(createReqDTO.getFormCustomViewPath(), oldProcessDefinitionExt.getFormCustomViewPath())) {
  211 + return false;
  212 + }
  213 + // 校验 BPMN XML 信息
  214 + BpmnModel newModel = ActivitiUtils.buildBpmnModel(createReqDTO.getBpmnBytes());
  215 + BpmnModel oldModel = getBpmnModel(oldProcessDefinition.getId());
  216 + if (!ActivitiUtils.equals(oldModel, newModel)) {
  217 + return false;
  218 + }
  219 + // 最终发现都一致,则返回 true
  220 + return true;
  221 + }
  222 +
  223 + @Override
181 @Transactional(rollbackFor = Exception.class) // 因为进行多个 activiti 操作,所以开启事务 224 @Transactional(rollbackFor = Exception.class) // 因为进行多个 activiti 操作,所以开启事务
182 - public String createProcessDefinition(BpmDefinitionCreateReqDTO createReqDTO) { 225 + public String createProcessDefinition(BpmProcessDefinitionCreateReqDTO createReqDTO) {
183 // 创建 Deployment 部署 226 // 创建 Deployment 部署
184 Deployment deploy = repositoryService.createDeployment() 227 Deployment deploy = repositoryService.createDeployment()
185 .key(createReqDTO.getKey()).name(createReqDTO.getName()).category(createReqDTO.getCategory()) 228 .key(createReqDTO.getKey()).name(createReqDTO.getName()).category(createReqDTO.getCategory())
186 - .addString(createReqDTO.getKey() + BPMN_FILE_SUFFIX, createReqDTO.getBpmnXml()) 229 + .addBytes(createReqDTO.getKey() + BPMN_FILE_SUFFIX, createReqDTO.getBpmnBytes())
187 .deploy(); 230 .deploy();
188 231
189 // 设置 ProcessDefinition 的 category 分类 232 // 设置 ProcessDefinition 的 category 分类
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/definition/impl/BpmTaskAssignRuleServiceImpl.java
1 package cn.iocoder.yudao.adminserver.modules.bpm.service.definition.impl; 1 package cn.iocoder.yudao.adminserver.modules.bpm.service.definition.impl;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.collection.ListUtil;
  5 +import cn.hutool.core.util.ArrayUtil;
  6 +import cn.hutool.core.util.ObjectUtil;
4 import cn.hutool.core.util.StrUtil; 7 import cn.hutool.core.util.StrUtil;
5 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleCreateReqVO; 8 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleCreateReqVO;
6 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleRespVO; 9 import cn.iocoder.yudao.adminserver.modules.bpm.controller.definition.vo.rule.BpmTaskAssignRuleRespVO;
@@ -30,10 +33,7 @@ import org.springframework.stereotype.Service; @@ -30,10 +33,7 @@ import org.springframework.stereotype.Service;
30 import org.springframework.validation.annotation.Validated; 33 import org.springframework.validation.annotation.Validated;
31 34
32 import javax.annotation.Resource; 35 import javax.annotation.Resource;
33 -import java.util.Collections;  
34 -import java.util.List;  
35 -import java.util.Objects;  
36 -import java.util.Set; 36 +import java.util.*;
37 37
38 import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*; 38 import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.*;
39 import static cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants.BPM_TASK_ASSIGN_RULE_TYPE; 39 import static cn.iocoder.yudao.adminserver.modules.system.enums.SysDictTypeConstants.BPM_TASK_ASSIGN_RULE_TYPE;
@@ -143,6 +143,31 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService { @@ -143,6 +143,31 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
143 } 143 }
144 144
145 @Override 145 @Override
  146 + public boolean isTaskAssignRulesEquals(String modelId, String processDefinitionId) {
  147 + // 调用 VO 接口的原因是,过滤掉流程模型不需要的规则,保持和 copyTaskAssignRules 方法的一致性
  148 + List<BpmTaskAssignRuleRespVO> modelRules = getTaskAssignRuleList(modelId, null);
  149 + List<BpmTaskAssignRuleRespVO> processInstanceRules = getTaskAssignRuleList(null, processDefinitionId);
  150 + if (modelRules.size() != processInstanceRules.size()) {
  151 + return false;
  152 + }
  153 +
  154 + // 遍历,匹配对应的规则
  155 + Map<String, BpmTaskAssignRuleRespVO> processInstanceRuleMap = CollectionUtils.convertMap(processInstanceRules,
  156 + BpmTaskAssignRuleRespVO::getTaskDefinitionKey);
  157 + for (BpmTaskAssignRuleRespVO modelRule : modelRules) {
  158 + BpmTaskAssignRuleRespVO processInstanceRule = processInstanceRuleMap.get(modelRule.getTaskDefinitionKey());
  159 + if (processInstanceRule == null) {
  160 + return false;
  161 + }
  162 + if (!ObjectUtil.equals(modelRule.getType(), processInstanceRule.getType())
  163 + || !ObjectUtil.equal(modelRule.getOptions(), processInstanceRule.getOptions())) {
  164 + return false;
  165 + }
  166 + }
  167 + return true;
  168 + }
  169 +
  170 + @Override
146 public void copyTaskAssignRules(String fromModelId, String toProcessDefinitionId) { 171 public void copyTaskAssignRules(String fromModelId, String toProcessDefinitionId) {
147 List<BpmTaskAssignRuleRespVO> rules = getTaskAssignRuleList(fromModelId, null); 172 List<BpmTaskAssignRuleRespVO> rules = getTaskAssignRuleList(fromModelId, null);
148 if (CollUtil.isEmpty(rules)) { 173 if (CollUtil.isEmpty(rules)) {
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmActivityServiceImpl.java
@@ -60,10 +60,7 @@ public class BpmActivityServiceImpl implements BpmActivityService { @@ -60,10 +60,7 @@ public class BpmActivityServiceImpl implements BpmActivityService {
60 public List<BpmActivityRespVO> getActivityListByProcessInstanceId(String processInstanceId) { 60 public List<BpmActivityRespVO> getActivityListByProcessInstanceId(String processInstanceId) {
61 List<HistoricActivityInstance> activityList = historyService.createHistoricActivityInstanceQuery() 61 List<HistoricActivityInstance> activityList = historyService.createHistoricActivityInstanceQuery()
62 .processInstanceId(processInstanceId).list(); 62 .processInstanceId(processInstanceId).list();
63 - // 拼接数据  
64 - List<BpmTaskExtDO> taskExts = taskService.getTaskExtListByProcessInstanceId(processInstanceId);  
65 - Map<String, BpmTaskExtDO> taskExtMap = convertMap(taskExts, BpmTaskExtDO::getTaskId);  
66 - return BpmActivityConvert.INSTANCE.convertList(activityList, taskExtMap); 63 + return BpmActivityConvert.INSTANCE.convertList(activityList);
67 } 64 }
68 65
69 @Override 66 @Override
yudao-framework/yudao-spring-boot-starter-activiti/src/main/java/cn/iocoder/yudao/framework/activiti/core/util/ActivitiUtils.java
1 package cn.iocoder.yudao.framework.activiti.core.util; 1 package cn.iocoder.yudao.framework.activiti.core.util;
2 2
  3 +import cn.hutool.core.util.ArrayUtil;
  4 +import cn.hutool.core.util.ObjectUtil;
3 import cn.hutool.core.util.ReflectUtil; 5 import cn.hutool.core.util.ReflectUtil;
4 import cn.hutool.core.util.StrUtil; 6 import cn.hutool.core.util.StrUtil;
5 import cn.iocoder.yudao.framework.common.util.number.NumberUtils; 7 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
@@ -13,6 +15,7 @@ import org.activiti.engine.impl.util.io.BytesStreamSource; @@ -13,6 +15,7 @@ import org.activiti.engine.impl.util.io.BytesStreamSource;
13 15
14 import javax.xml.bind.Element; 16 import javax.xml.bind.Element;
15 import java.util.ArrayList; 17 import java.util.ArrayList;
  18 +import java.util.Arrays;
16 import java.util.List; 19 import java.util.List;
17 import java.util.Objects; 20 import java.util.Objects;
18 import java.util.function.Consumer; 21 import java.util.function.Consumer;
@@ -88,8 +91,20 @@ public class ActivitiUtils { @@ -88,8 +91,20 @@ public class ActivitiUtils {
88 if (model == null) { 91 if (model == null) {
89 return null; 92 return null;
90 } 93 }
  94 + return StrUtil.utf8Str(getBpmnBytes(model));
  95 + }
  96 +
  97 + public static byte[] getBpmnBytes(BpmnModel model) {
  98 + if (model == null) {
  99 + return new byte[0];
  100 + }
91 BpmnXMLConverter converter = new BpmnXMLConverter(); 101 BpmnXMLConverter converter = new BpmnXMLConverter();
92 - return StrUtil.utf8Str(converter.convertToXML(model)); 102 + return converter.convertToXML(model);
  103 + }
  104 +
  105 + public static boolean equals(BpmnModel oldModel, BpmnModel newModel) {
  106 + // 由于 BpmnModel 未提供 equals 方法,所以只能转成字节数组,进行比较
  107 + return Arrays.equals(getBpmnBytes(oldModel), getBpmnBytes(newModel));
93 } 108 }
94 109
95 } 110 }