diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/FlowableUtils.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/FlowableUtils.java index 641c699c9..3621d9d99 100644 --- a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/FlowableUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/util/FlowableUtils.java @@ -1,7 +1,14 @@ package cn.iocoder.yudao.framework.flowable.core.util; +import org.flowable.bpmn.converter.BpmnXMLConverter; +import org.flowable.bpmn.model.BpmnModel; +import org.flowable.bpmn.model.FlowElement; import org.flowable.common.engine.impl.identity.Authentication; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + public class FlowableUtils { public static void setAuthenticatedUserId(Long userId) { @@ -11,4 +18,45 @@ public class FlowableUtils { public static void clearAuthenticatedUserId() { Authentication.setAuthenticatedUserId(null); } + + /** + * 获得 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; + } + + /** + * 比较 两个bpmnModel 是否相同 + * @param oldModel 老的bpmn model + * @param newModel 新的bpmn model + */ + public static boolean equals(BpmnModel oldModel, BpmnModel newModel) { + // 由于 BpmnModel 未提供 equals 方法,所以只能转成字节数组,进行比较 + return Arrays.equals(getBpmnBytes(oldModel), getBpmnBytes(newModel)); + } + + /** + * 把 bpmnModel 转换成 byte[] + * @param model bpmnModel + */ + public static byte[] getBpmnBytes(BpmnModel model) { + if (model == null) { + return new byte[0]; + } + BpmnXMLConverter converter = new BpmnXMLConverter(); + return converter.convertToXML(model); + } } diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java index 874df456d..f22dcb04a 100644 --- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.config; import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.BpmActivityBehaviorFactory; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript; import cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.BpmProcessInstanceEventListener; import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService; import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService; @@ -27,8 +28,9 @@ import java.util.List; public class BpmFlowableConfiguration { /** - * 将自定义 listener 加入全局listener + * Flowable engines 自定义的配置 * @param listeners 自定义 listener + * @param bpmActivityBehaviorFactory 自定义的 ActivityBehaviorFactory 实现 */ @Bean public EngineConfigurationConfigurer addCustomerListenerConfigurer (ObjectProvider listeners, @@ -51,14 +53,15 @@ public class BpmFlowableConfiguration { BpmUserGroupService userGroupService, PermissionApi permissionApi, DeptApi deptApi, - AdminUserApi adminUserApi) { + AdminUserApi adminUserApi, + List scripts) { BpmActivityBehaviorFactory bpmActivityBehaviorFactory = new BpmActivityBehaviorFactory(); bpmActivityBehaviorFactory.setBpmTaskRuleService(taskRuleService); bpmActivityBehaviorFactory.setUserGroupService(userGroupService); bpmActivityBehaviorFactory.setAdminUserApi(adminUserApi); bpmActivityBehaviorFactory.setPermissionApi(permissionApi); bpmActivityBehaviorFactory.setDeptApi(deptApi); -// bpmActivityBehaviorFactory.setScripts(scripts); + bpmActivityBehaviorFactory.setScripts(scripts); return bpmActivityBehaviorFactory; } } diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmActivityBehaviorFactory.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmActivityBehaviorFactory.java index 784cd4f69..0d8de4f62 100644 --- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmActivityBehaviorFactory.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmActivityBehaviorFactory.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript; import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService; import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; @@ -13,6 +14,8 @@ import org.flowable.bpmn.model.UserTask; import org.flowable.engine.impl.bpmn.behavior.UserTaskActivityBehavior; import org.flowable.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFactory; +import java.util.List; + /** * 自定义的 ActivityBehaviorFactory 实现类,目的如下: * 1. 自定义 {@link #createUserTaskActivityBehavior(UserTask)}:实现自定义的流程任务的 assignee 负责人的分配 @@ -35,6 +38,8 @@ public class BpmActivityBehaviorFactory extends DefaultActivityBehaviorFactory { private DeptApi deptApi; @Setter private AdminUserApi adminUserApi; + @Setter + private List scripts; @Override public UserTaskActivityBehavior createUserTaskActivityBehavior(UserTask userTask) { @@ -44,8 +49,7 @@ public class BpmActivityBehaviorFactory extends DefaultActivityBehaviorFactory { userTaskActivityBehavior.setDeptApi(deptApi); userTaskActivityBehavior.setUserGroupService(userGroupService); userTaskActivityBehavior.setAdminUserApi(adminUserApi); - //TODO - //userTaskActivityBehavior.setScripts(scripts); + userTaskActivityBehavior.setScripts(scripts); return userTaskActivityBehavior; } } diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java index 202ef09fc..e364b3199 100644 --- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO; import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript; import cn.iocoder.yudao.module.bpm.service.definition.BpmTaskAssignRuleService; import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; @@ -30,8 +31,10 @@ import org.flowable.task.service.impl.persistence.entity.TaskEntity; 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.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_ASSIGN_SCRIPT_NOT_EXISTS; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_CREATE_FAIL_NO_CANDIDATE_USER; /** @@ -56,9 +59,17 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior { @Setter private PermissionApi permissionApi; + /** + * 任务分配脚本 + */ + private Map scriptMap = Collections.emptyMap(); + public BpmUserTaskActivityBehavior(UserTask userTask) { super(userTask); } + public void setScripts(List scripts) { + this.scriptMap = convertMap(scripts, script -> script.getEnum().getId()); + } @Override protected void handleAssignments(TaskService taskService, String assignee, String owner, List candidateUsers, List candidateGroups, TaskEntity task, ExpressionManager expressionManager, DelegateExecution execution, ProcessEngineConfigurationImpl processEngineConfiguration) { @@ -100,10 +111,9 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior { assigneeUserIds = calculateTaskCandidateUsersByUser(task, rule); } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType(), rule.getType())) { assigneeUserIds = calculateTaskCandidateUsersByUserGroup(task, rule); + } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), rule.getType())) { + assigneeUserIds = calculateTaskCandidateUsersByScript(task, rule); } -// else if (Objects.equals(BpmTaskAssignRuleTypeEnum.SCRIPT.getType(), rule.getType())) { -// assigneeUserIds = calculateTaskCandidateUsersByScript(task, rule); -// } // 移除被禁用的用户 removeDisableUsers(assigneeUserIds); @@ -146,6 +156,22 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior { return userIds; } + private Set calculateTaskCandidateUsersByScript(TaskEntity task, BpmTaskAssignRuleDO rule) { + // 获得对应的脚本 + List scripts = new ArrayList<>(rule.getOptions().size()); + rule.getOptions().forEach(id -> { + BpmTaskAssignScript script = scriptMap.get(id); + if (script == null) { + throw exception(TASK_ASSIGN_SCRIPT_NOT_EXISTS, id); + } + scripts.add(script); + }); + // 逐个计算任务 + Set userIds = new HashSet<>(); + scripts.forEach(script -> CollUtil.addAll(userIds, script.calculateTaskCandidateUsers(task))); + return userIds; + } + private Long chooseTaskAssignee(Set candidateUserIds) { // TODO 芋艿:未来可以优化下,改成轮询的策略 int index = RandomUtil.randomInt(candidateUserIds.size()); diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java new file mode 100644 index 000000000..10392c714 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/BpmTaskAssignScript.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script; + +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum; +import org.flowable.task.service.impl.persistence.entity.TaskEntity; + +import java.util.Set; + +/** + * Bpm 任务分配的自定义 Script 脚本 + * 使用场景: + * 1. 设置审批人为发起人 + * 2. 设置审批人为发起人的 Leader + * 3. 甚至审批人为发起人的 Leader 的 Leader + * + * @author 芋道源码 + */ +public interface BpmTaskAssignScript { + + /** + * 基于流程任务,获得任务的候选用户们 + * + * @param task 任务 + * @return 候选人用户的编号数组 + */ + Set calculateTaskCandidateUsers(TaskEntity task); + + /** + * 获得枚举值 + * + * @return 枚举值 + */ + BpmTaskRuleScriptEnum getEnum(); +} + diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java new file mode 100644 index 000000000..06b8c52f0 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl; + +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript; +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; + +import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.service.impl.persistence.entity.TaskEntity; +import org.springframework.context.annotation.Lazy; +import org.springframework.util.Assert; + +import javax.annotation.Resource; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; +import static java.util.Collections.emptySet; + +/** + * 分配给发起人的 Leader 审批的 Script 实现类 + * 目前 Leader 的定义是, + * + * @author 芋道源码 + */ +public abstract class BpmTaskAssignLeaderAbstractScript implements BpmTaskAssignScript { + + @Resource + private AdminUserApi adminUserApi; + @Resource + private DeptApi deptApi; + @Resource + @Lazy // 解决循环依赖 + private BpmProcessInstanceService bpmProcessInstanceService; + + protected Set calculateTaskCandidateUsers(TaskEntity task, int level) { + Assert.isTrue(level > 0, "level 必须大于 0"); + // 获得发起人 + ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(task.getProcessInstanceId()); + Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId()); + // 获得对应 leve 的部门 + DeptRespDTO dept = null; + for (int i = 0; i < level; i++) { + // 获得 level 对应的部门 + if (dept == null) { + dept = getStartUserDept(startUserId); + if (dept == null) { // 找不到发起人的部门,所以无法使用该规则 + return emptySet(); + } + } else { + DeptRespDTO parentDept = deptApi.getDept(dept.getParentId()); + if (parentDept == null) { // 找不到父级部门,所以只好结束寻找。原因是:例如说,级别比较高的人,所在部门层级比较少 + break; + } + dept = parentDept; + } + } + return dept.getLeaderUserId() != null ? asSet(dept.getLeaderUserId()) : emptySet(); + } + + private DeptRespDTO getStartUserDept(Long startUserId) { + AdminUserRespDTO startUser = adminUserApi.getUser(startUserId); + if (startUser.getDeptId() == null) { // 找不到部门,所以无法使用该规则 + return null; + } + return deptApi.getDept(startUser.getDeptId()); + } + +} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java new file mode 100644 index 000000000..55e7df7b8 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl; + +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum; +import org.flowable.task.service.impl.persistence.entity.TaskEntity; +import org.springframework.stereotype.Component; + +import java.util.Set; + +/** + * 分配给发起人的一级 Leader 审批的 Script 实现类 + * + * @author 芋道源码 + */ +@Component +public class BpmTaskAssignLeaderX1Script extends BpmTaskAssignLeaderAbstractScript { + + @Override + public Set calculateTaskCandidateUsers(TaskEntity task) { + return calculateTaskCandidateUsers(task, 1); + } + + @Override + public BpmTaskRuleScriptEnum getEnum() { + return BpmTaskRuleScriptEnum.LEADER_X1; + } + +} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java new file mode 100644 index 000000000..a4455ea40 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl; + +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum; +import org.flowable.task.service.impl.persistence.entity.TaskEntity; +import org.springframework.stereotype.Component; + +import java.util.Set; + +/** + * 分配给发起人的二级 Leader 审批的 Script 实现类 + * + * @author 芋道源码 + */ +@Component +public class BpmTaskAssignLeaderX2Script extends BpmTaskAssignLeaderAbstractScript { + + @Override + public Set calculateTaskCandidateUsers(TaskEntity task) { + return calculateTaskCandidateUsers(task, 2); + } + + @Override + public BpmTaskRuleScriptEnum getEnum() { + return BpmTaskRuleScriptEnum.LEADER_X2; + } + +} diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignStartUserScript.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignStartUserScript.java new file mode 100644 index 000000000..653918b0b --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/script/impl/BpmTaskAssignStartUserScript.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl; + +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum; + +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript; +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; +import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.service.impl.persistence.entity.TaskEntity; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.Set; + +/** + * 分配给发起人审批的 Script 实现类 + * + * @author 芋道源码 + */ +@Component +public class BpmTaskAssignStartUserScript implements BpmTaskAssignScript { + + @Resource + @Lazy // 解决循环依赖 + private BpmProcessInstanceService bpmProcessInstanceService; + + @Override + public Set calculateTaskCandidateUsers(TaskEntity task) { + ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(task.getProcessInstanceId()); + Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId()); + return SetUtils.asSet(startUserId); + } + + @Override + public BpmTaskRuleScriptEnum getEnum() { + return BpmTaskRuleScriptEnum.START_USER; + } + +} 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 index d75a1bd68..694da78d4 100644 --- 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 @@ -5,6 +5,7 @@ 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.framework.flowable.core.util.FlowableUtils; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO; @@ -198,7 +199,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ BpmnModel newModel = buildBpmnModel(createReqDTO.getBpmnBytes()); BpmnModel oldModel = getBpmnModel(oldProcessDefinition.getId()); //TODO 貌似 flowable 不修改这个也不同。需要看看。 sourceSystemId 不同 - if (equals(oldModel, newModel)) { + if (FlowableUtils.equals(oldModel, newModel)) { return false; } // 最终发现都一致,则返回 true @@ -216,19 +217,8 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ 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) { 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 index b1a12e71c..6d6430da8 100644 --- 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 @@ -5,6 +5,7 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils; 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; @@ -87,37 +88,15 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService{ if (model == null) { return Collections.emptyList(); } - // 获得用户任务,只有用户任务才可以设置分配规则 - List userTasks = getBpmnModelElements(model, UserTask.class); + List userTasks = FlowableUtils.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) { // 校验参数 diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 440ecd916..9c21bd8a9 100644 --- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -106,6 +106,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService } @Override + @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); diff --git a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index 4028679e0..5c004977c 100644 --- a/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -25,6 +25,7 @@ import org.flowable.task.api.TaskQuery; import org.flowable.task.api.history.HistoricTaskInstance; import org.flowable.task.api.history.HistoricTaskInstanceQuery; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; @@ -167,6 +168,7 @@ public class BpmTaskServiceImpl implements BpmTaskService{ } @Override + @Transactional(rollbackFor = Exception.class) public void approveTask(Long userId, @Valid BpmTaskApproveReqVO reqVO) { // 校验任务存在 Task task = checkTask(userId, reqVO.getId()); @@ -184,6 +186,7 @@ public class BpmTaskServiceImpl implements BpmTaskService{ } @Override + @Transactional(rollbackFor = Exception.class) public void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO) { Task task = checkTask(userId, reqVO.getId()); // 校验流程实例存在 @@ -234,16 +237,15 @@ public class BpmTaskServiceImpl implements BpmTaskService{ .setAssigneeUserId(NumberUtils.parseLong(task.getAssignee())) .setTaskId(task.getId()); taskExtMapper.updateByTaskId(taskExtDO); - //TODO 创建任务时候 也会调用 updateTaskExtAssign, processInstance 名称为空 校验不通过 // 发送通知。在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。 -// TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { -// @Override -// public void afterCommit() { -// ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId()); -// AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId())); -// messageService.sendMessageWhenTaskAssigned(BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task)); -// } -// }); + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { + @Override + public void afterCommit() { + ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId()); + AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId())); + messageService.sendMessageWhenTaskAssigned(BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task)); + } + }); } /**