Commit 13da7eba6fcf2589b0ad589d61a06fa1fa13b3e3

Authored by YunaiV
1 parent ef19efb2

reactor:移除 bpm 的 api 包

Showing 267 changed files with 2552 additions and 2615 deletions
yudao-module-bpm/pom.xml
... ... @@ -8,12 +8,8 @@
8 8 <version>${revision}</version>
9 9 </parent>
10 10 <modelVersion>4.0.0</modelVersion>
11   - <modules>
12   - <module>yudao-module-bpm-api</module>
13   - <module>yudao-module-bpm-biz</module>
14   - </modules>
15 11 <artifactId>yudao-module-bpm</artifactId>
16   - <packaging>pom</packaging>
  12 + <packaging>jar</packaging>
17 13  
18 14 <name>${project.artifactId}</name>
19 15 <description>
... ... @@ -24,4 +20,60 @@
24 20 工作流基于 Flowable 6 实现,分成流程定义、流程表单、流程实例、流程任务等功能模块。
25 21 </description>
26 22  
  23 + <dependencies>
  24 + <dependency>
  25 + <groupId>cn.iocoder.boot</groupId>
  26 + <artifactId>yudao-module-system</artifactId>
  27 + <version>${revision}</version>
  28 + </dependency>
  29 +
  30 + <!-- 业务组件 -->
  31 + <dependency>
  32 + <groupId>cn.iocoder.boot</groupId>
  33 + <artifactId>yudao-spring-boot-starter-biz-data-permission</artifactId>
  34 + </dependency>
  35 + <dependency>
  36 + <groupId>cn.iocoder.boot</groupId>
  37 + <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
  38 + </dependency>
  39 +
  40 + <!-- Web 相关 -->
  41 + <dependency>
  42 + <groupId>cn.iocoder.boot</groupId>
  43 + <artifactId>yudao-spring-boot-starter-web</artifactId>
  44 + </dependency>
  45 +
  46 + <dependency>
  47 + <groupId>cn.iocoder.boot</groupId>
  48 + <artifactId>yudao-spring-boot-starter-security</artifactId>
  49 + </dependency>
  50 +
  51 + <!-- DB 相关 -->
  52 + <dependency>
  53 + <groupId>cn.iocoder.boot</groupId>
  54 + <artifactId>yudao-spring-boot-starter-mybatis</artifactId>
  55 + </dependency>
  56 +
  57 + <!-- Test 测试相关 -->
  58 + <dependency>
  59 + <groupId>cn.iocoder.boot</groupId>
  60 + <artifactId>yudao-spring-boot-starter-test</artifactId>
  61 + </dependency>
  62 +
  63 + <!-- 工具类相关 -->
  64 + <dependency>
  65 + <groupId>cn.iocoder.boot</groupId>
  66 + <artifactId>yudao-spring-boot-starter-excel</artifactId>
  67 + </dependency>
  68 +
  69 + <!-- Flowable 工作流相关 -->
  70 + <dependency>
  71 + <groupId>org.flowable</groupId>
  72 + <artifactId>flowable-spring-boot-starter-process</artifactId>
  73 + </dependency>
  74 + <dependency>
  75 + <groupId>org.flowable</groupId>
  76 + <artifactId>flowable-spring-boot-starter-actuator</artifactId>
  77 + </dependency>
  78 + </dependencies>
27 79 </project>
... ...
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/event/BpmProcessInstanceStatusEvent.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/api/event/BpmProcessInstanceStatusEvent.java
1   -package cn.iocoder.yudao.module.bpm.event;
  1 +package cn.iocoder.yudao.module.bpm.api.event;
2 2  
3 3 import jakarta.validation.constraints.NotNull;
4 4 import lombok.Data;
... ...
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/event/BpmProcessInstanceStatusEventListener.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/api/event/BpmProcessInstanceStatusEventListener.java
1   -package cn.iocoder.yudao.module.bpm.event;
  1 +package cn.iocoder.yudao.module.bpm.api.event;
2 2  
3 3 import cn.hutool.core.util.StrUtil;
4 4 import org.springframework.context.ApplicationListener;
... ...
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/package-info.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/api/package-info.java
1 1 /**
2   - * bpm API 包,定义暴露给其它模块的 API
  2 + * bpm API 包,定义并实现提供给其它模块的 API
3 3 */
4 4 package cn.iocoder.yudao.module.bpm.api;
... ...
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApi.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApi.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessTaskApi.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessTaskApi.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessTaskApiImpl.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessTaskApiImpl.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/dto/BpmProcessInstanceCreateReqDTO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/api/task/dto/BpmProcessInstanceCreateReqDTO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/dept/DeptSimpleBaseVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/dept/DeptSimpleBaseVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/package-info.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/package-info.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/user/UserSimpleBaseVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/base/user/UserSimpleBaseVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmCategoryController.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmCategoryController.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmFormController.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmFormController.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessExpressionController.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessExpressionController.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessListenerController.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessListenerController.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmUserGroupController.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmUserGroupController.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/category/BpmCategoryPageReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/category/BpmCategoryPageReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/category/BpmCategoryRespVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/category/BpmCategoryRespVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/category/BpmCategorySaveReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/category/BpmCategorySaveReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionPageReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionPageReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionRespVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionRespVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionSaveReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionSaveReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormFieldVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormFieldVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormPageReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormPageReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormRespVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormRespVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormSaveReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/form/BpmFormSaveReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupPageReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupPageReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupRespVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupRespVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupSaveReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/group/BpmUserGroupSaveReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/listener/BpmProcessListenerPageReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/listener/BpmProcessListenerPageReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/listener/BpmProcessListenerRespVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/listener/BpmProcessListenerRespVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/listener/BpmProcessListenerSaveReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/listener/BpmProcessListenerSaveReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModeUpdateBpmnReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModeUpdateBpmnReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelRespVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelSaveReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelSaveReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelUpdateStateReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelUpdateStateReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelUpdateReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelUpdateReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionPageReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionPageReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionRespVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/process/BpmProcessDefinitionRespVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOALeaveController.http renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOALeaveController.http
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOALeaveController.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOALeaveController.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/package-info.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/package-info.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveCreateReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveCreateReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeavePageReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeavePageReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveRespVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/BpmOALeaveRespVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.http renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.http
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/activity/BpmActivityRespVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/activity/BpmActivityRespVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/cc/BpmProcessInstanceCopyRespVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/cc/BpmProcessInstanceCopyRespVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmApprovalDetailReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmApprovalDetailReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmApprovalDetailRespVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmApprovalDetailRespVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceBpmnModelViewRespVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceBpmnModelViewRespVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCancelReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCancelReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyPageReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyPageReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCreateReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCreateReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstancePageReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstancePageReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceRespVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceRespVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskApproveReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskApproveReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskCopyReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskCopyReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDelegateReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskDelegateReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskPageReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskPageReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskRejectReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskRejectReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskRespVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskRespVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskReturnReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskReturnReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskSignCreateReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskSignCreateReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskSignDeleteReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskSignDeleteReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskTransferReqVO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskTransferReqVO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/app/package-info.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/app/package-info.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/package-info.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/package-info.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/message/BpmMessageConvert.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/convert/message/BpmMessageConvert.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/package-info.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/convert/package-info.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java
... ... @@ -17,7 +17,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
17 17 import cn.iocoder.yudao.module.bpm.convert.definition.BpmProcessDefinitionConvert;
18 18 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
19 19 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
20   -import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceStatusEvent;
  20 +import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent;
21 21 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
22 22 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
23 23 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenProcessInstanceApproveReqDTO;
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmCategoryDO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmCategoryDO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmFormDO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmFormDO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessExpressionDO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessExpressionDO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessListenerDO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessListenerDO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmUserGroupDO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmUserGroupDO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOALeaveDO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOALeaveDO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmProcessInstanceCopyDO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/task/BpmProcessInstanceCopyDO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/category/BpmCategoryMapper.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/category/BpmCategoryMapper.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmFormMapper.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmFormMapper.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmProcessDefinitionInfoMapper.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmProcessDefinitionInfoMapper.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmProcessExpressionMapper.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmProcessExpressionMapper.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmProcessListenerMapper.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmProcessListenerMapper.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmUserGroupMapper.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmUserGroupMapper.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOALeaveMapper.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOALeaveMapper.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmProcessInstanceCopyMapper.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/task/BpmProcessInstanceCopyMapper.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/redis/BpmProcessIdRedisDAO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/redis/BpmProcessIdRedisDAO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/redis/RedisKeyConstants.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/dal/redis/RedisKeyConstants.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/DictTypeConstants.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/DictTypeConstants.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmAutoApproveTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmAutoApproveTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmBoundaryEventTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmBoundaryEventTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessMultiInstanceSourceTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessMultiInstanceSourceTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessStartUserEmptyTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessStartUserEmptyTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessStartUserTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmChildProcessStartUserTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmDelayTimerTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmDelayTimerTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmFieldPermissionEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmFieldPermissionEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmHttpRequestParamTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmHttpRequestParamTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmModelFormTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmModelFormTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmModelTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmModelTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmProcessListenerTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmProcessListenerTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmProcessListenerValueTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmProcessListenerValueTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModeConditionTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModeConditionTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTriggerTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTriggerTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskApproveMethodEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskApproveMethodEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskApproveTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskApproveTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskAssignEmptyHandlerTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskAssignEmptyHandlerTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskAssignStartUserHandlerTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskAssignStartUserHandlerTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskRejectHandlerTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskRejectHandlerTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskTimeoutHandlerTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmUserTaskTimeoutHandlerTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/message/BpmMessageEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/message/BpmMessageEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmCommentTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmCommentTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceStatusEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmProcessInstanceStatusEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmReasonEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskSignTypeEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskSignTypeEnum.java
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskStatusEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskStatusEnum.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/config/BpmFlowableConfiguration.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmActivityBehaviorFactory.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmActivityBehaviorFactory.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmParallelMultiInstanceBehavior.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmParallelMultiInstanceBehavior.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmSequentialMultiInstanceBehavior.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmSequentialMultiInstanceBehavior.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvoker.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvoker.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateStrategy.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateStrategy.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignLeaderExpression.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignLeaderExpression.java
... ... @@ -14,6 +14,7 @@ import org.springframework.util.Assert;
14 14 import jakarta.annotation.Resource;
15 15 import java.util.Set;
16 16  
  17 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
17 18 import static java.util.Collections.emptySet;
18 19  
19 20 /**
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignStartUserExpression.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignStartUserExpression.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/AbstractBpmTaskCandidateDeptLeaderStrategy.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/AbstractBpmTaskCandidateDeptLeaderStrategy.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateApproveUserSelectStrategy.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateApproveUserSelectStrategy.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateDeptLeaderMultiStrategy.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateDeptLeaderMultiStrategy.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateDeptLeaderStrategy.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateDeptLeaderStrategy.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateDeptMemberStrategy.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateDeptMemberStrategy.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderMultiStrategy.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderMultiStrategy.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderStrategy.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderStrategy.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserSelectStrategy.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserSelectStrategy.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/form/BpmTaskCandidateFormDeptLeaderStrategy.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/form/BpmTaskCandidateFormDeptLeaderStrategy.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/form/BpmTaskCandidateFormUserStrategy.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/form/BpmTaskCandidateFormUserStrategy.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/other/BpmTaskCandidateAssignEmptyStrategy.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/other/BpmTaskCandidateAssignEmptyStrategy.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/other/BpmTaskCandidateExpressionStrategy.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/other/BpmTaskCandidateExpressionStrategy.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidateGroupStrategy.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidateGroupStrategy.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidatePostStrategy.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidatePostStrategy.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidateRoleStrategy.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidateRoleStrategy.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidateStartUserStrategy.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidateStartUserStrategy.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidateUserStrategy.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidateUserStrategy.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/el/VariableConvertByTypeExpressionFunction.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/el/VariableConvertByTypeExpressionFunction.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmTaskCandidateStrategyEnum.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmTaskCandidateStrategyEnum.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnModelConstants.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnModelConstants.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnVariableConstants.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnVariableConstants.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/event/BpmProcessInstanceEventPublisher.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/event/BpmProcessInstanceEventPublisher.java
1 1 package cn.iocoder.yudao.module.bpm.framework.flowable.core.event;
2 2  
3   -import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceStatusEvent;
  3 +import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent;
4 4 import lombok.AllArgsConstructor;
5 5 import org.springframework.context.ApplicationEventPublisher;
6 6 import org.springframework.validation.annotation.Validated;
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmCopyTaskDelegate.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmCopyTaskDelegate.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTriggerTaskDelegate.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTriggerTaskDelegate.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/demo/exection/DemoDelegateClassExecutionListener.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/demo/exection/DemoDelegateClassExecutionListener.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/demo/exection/DemoDelegateExpressionExecutionListener.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/demo/exection/DemoDelegateExpressionExecutionListener.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/demo/exection/DemoSpringExpressionExecutionListener.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/demo/exection/DemoSpringExpressionExecutionListener.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/demo/task/DemoDelegateClassTaskListener.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/demo/task/DemoDelegateClassTaskListener.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/demo/task/DemoDelegateExpressionTaskListener.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/demo/task/DemoDelegateExpressionTaskListener.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/demo/task/DemoSpringExpressionTaskListener.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/demo/task/DemoSpringExpressionTaskListener.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/package-info.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/package-info.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/web/config/BpmWebConfiguration.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/web/config/BpmWebConfiguration.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/web/core/FlowableWebFilter.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/web/core/FlowableWebFilter.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/web/package-info.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/web/package-info.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/package-info.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/package-info.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmCategoryService.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmCategoryService.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmCategoryServiceImpl.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmCategoryServiceImpl.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormService.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormService.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormServiceImpl.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormServiceImpl.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessExpressionService.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessExpressionService.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessExpressionServiceImpl.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessExpressionServiceImpl.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessListenerService.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessListenerService.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessListenerServiceImpl.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessListenerServiceImpl.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupService.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupService.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceImpl.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceImpl.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmFormFieldRespDTO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmFormFieldRespDTO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/dto/BpmProcessDefinitionCreateReqDTO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageService.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageService.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageServiceImpl.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageServiceImpl.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenProcessInstanceApproveReqDTO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenProcessInstanceApproveReqDTO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenProcessInstanceRejectReqDTO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenProcessInstanceRejectReqDTO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenTaskCreatedReqDTO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenTaskCreatedReqDTO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenTaskTimeoutReqDTO.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/message/dto/BpmMessageSendWhenTaskTimeoutReqDTO.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveService.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveService.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOALeaveStatusListener.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/listener/BpmOALeaveStatusListener.java
1 1 package cn.iocoder.yudao.module.bpm.service.oa.listener;
2 2  
3   -import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceStatusEvent;
4   -import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceStatusEventListener;
  3 +import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent;
  4 +import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEventListener;
5 5 import cn.iocoder.yudao.module.bpm.service.oa.BpmOALeaveService;
6 6 import cn.iocoder.yudao.module.bpm.service.oa.BpmOALeaveServiceImpl;
7 7 import org.springframework.stereotype.Component;
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceCopyService.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceCopyService.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceCopyServiceImpl.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceCopyServiceImpl.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
1   -package cn.iocoder.yudao.module.bpm.service.task;
2   -
3   -import cn.hutool.core.collection.CollUtil;
4   -import cn.hutool.core.collection.ListUtil;
5   -import cn.hutool.core.date.DateUtil;
6   -import cn.hutool.core.lang.Assert;
7   -import cn.hutool.core.util.ArrayUtil;
8   -import cn.hutool.core.util.ObjUtil;
9   -import cn.hutool.core.util.ObjectUtil;
10   -import cn.hutool.core.util.StrUtil;
11   -import cn.iocoder.yudao.framework.common.pojo.PageResult;
12   -import cn.iocoder.yudao.framework.common.util.date.DateUtils;
13   -import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
14   -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
15   -import cn.iocoder.yudao.framework.common.util.object.PageUtils;
16   -import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
17   -import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModelMetaInfoVO;
18   -import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
19   -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
20   -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO.ActivityNodeTask;
21   -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
22   -import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;
23   -import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
24   -import cn.iocoder.yudao.module.bpm.dal.redis.BpmProcessIdRedisDAO;
25   -import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants;
26   -import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelTypeEnum;
27   -import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeTypeEnum;
28   -import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
29   -import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum;
30   -import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
31   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
32   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
33   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
34   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants;
35   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.event.BpmProcessInstanceEventPublisher;
36   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmHttpRequestUtils;
37   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
38   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
39   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils;
40   -import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
41   -import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
42   -import cn.iocoder.yudao.module.system.api.dept.DeptApi;
43   -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
44   -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
45   -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
46   -import jakarta.annotation.Resource;
47   -import jakarta.validation.Valid;
48   -import lombok.extern.slf4j.Slf4j;
49   -import org.flowable.bpmn.constants.BpmnXMLConstants;
50   -import org.flowable.bpmn.model.*;
51   -import org.flowable.engine.HistoryService;
52   -import org.flowable.engine.RuntimeService;
53   -import org.flowable.engine.history.HistoricActivityInstance;
54   -import org.flowable.engine.history.HistoricProcessInstance;
55   -import org.flowable.engine.history.HistoricProcessInstanceQuery;
56   -import org.flowable.engine.repository.ProcessDefinition;
57   -import org.flowable.engine.runtime.ProcessInstance;
58   -import org.flowable.engine.runtime.ProcessInstanceBuilder;
59   -import org.flowable.task.api.Task;
60   -import org.flowable.task.api.history.HistoricTaskInstance;
61   -import org.springframework.context.annotation.Lazy;
62   -import org.springframework.stereotype.Service;
63   -import org.springframework.transaction.annotation.Transactional;
64   -import org.springframework.validation.annotation.Validated;
65   -
66   -import java.util.*;
67   -
68   -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
69   -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
70   -import static cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO.ActivityNode;
71   -import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
72   -import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.START_USER_NODE_ID;
73   -import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseNodeType;
74   -import static java.util.Arrays.asList;
75   -import static java.util.Collections.singletonList;
76   -import static org.flowable.bpmn.constants.BpmnXMLConstants.*;
77   -
78   -/**
79   - * 流程实例 Service 实现类
80   - * <p>
81   - * ProcessDefinition & ProcessInstance & Execution & Task 的关系:
82   - * 1. <a href="https://blog.csdn.net/bobozai86/article/details/105210414" />
83   - * <p>
84   - * HistoricProcessInstance & ProcessInstance 的关系:
85   - * 1. <a href=" https://my.oschina.net/843294669/blog/71902" />
86   - * <p>
87   - * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例
88   - *
89   - * @author 芋道源码
90   - */
91   -@Service
92   -@Validated
93   -@Slf4j
94   -public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService {
95   -
96   - @Resource
97   - private RuntimeService runtimeService;
98   - @Resource
99   - private HistoryService historyService;
100   -
101   - @Resource
102   - private BpmProcessDefinitionService processDefinitionService;
103   - @Resource
104   - @Lazy // 避免循环依赖
105   - private BpmTaskService taskService;
106   - @Resource
107   - private BpmMessageService messageService;
108   -
109   - @Resource
110   - private AdminUserApi adminUserApi;
111   - @Resource
112   - private DeptApi deptApi;
113   -
114   - @Resource
115   - private BpmProcessInstanceEventPublisher processInstanceEventPublisher;
116   -
117   - @Resource
118   - private BpmTaskCandidateInvoker taskCandidateInvoker;
119   -
120   - @Resource
121   - private BpmProcessIdRedisDAO processIdRedisDAO;
122   -
123   - // ========== Query 查询相关方法 ==========
124   -
125   - @Override
126   - public ProcessInstance getProcessInstance(String id) {
127   - return runtimeService.createProcessInstanceQuery()
128   - .includeProcessVariables()
129   - .processInstanceId(id)
130   - .singleResult();
131   - }
132   -
133   - @Override
134   - public List<ProcessInstance> getProcessInstances(Set<String> ids) {
135   - return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).includeProcessVariables().list();
136   - }
137   -
138   - @Override
139   - public HistoricProcessInstance getHistoricProcessInstance(String id) {
140   - return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).includeProcessVariables()
141   - .singleResult();
142   - }
143   -
144   - @Override
145   - public List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids) {
146   - return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).includeProcessVariables()
147   - .list();
148   - }
149   -
150   - private Map<String, String> getFormFieldsPermission(BpmnModel bpmnModel,
151   - String activityId, String taskId) {
152   - // 1. 获取流程活动编号。流程活动 Id 为空事,从流程任务中获取流程活动 Id
153   - if (StrUtil.isEmpty(activityId) && StrUtil.isNotEmpty(taskId)) {
154   - activityId = Optional.ofNullable(taskService.getHistoricTask(taskId))
155   - .map(HistoricTaskInstance::getTaskDefinitionKey).orElse(null);
156   - }
157   - if (StrUtil.isEmpty(activityId)) {
158   - return null;
159   - }
160   -
161   - // 2. 从 BpmnModel 中解析表单字段权限
162   - return BpmnModelUtils.parseFormFieldsPermission(bpmnModel, activityId);
163   - }
164   -
165   - @Override
166   - public BpmApprovalDetailRespVO getApprovalDetail(Long loginUserId, BpmApprovalDetailReqVO reqVO) {
167   - // 1.1 从 reqVO 中,读取公共变量
168   - Long startUserId = loginUserId; // 流程发起人
169   - HistoricProcessInstance historicProcessInstance = null; // 流程实例
170   - Integer processInstanceStatus = BpmProcessInstanceStatusEnum.NOT_START.getStatus(); // 流程状态
171   - Map<String, Object> processVariables = new HashMap<>(); // 流程变量
172   - // 1.2 如果是流程已发起的场景,则使用流程实例的数据
173   - if (reqVO.getProcessInstanceId() != null) {
174   - historicProcessInstance = getHistoricProcessInstance(reqVO.getProcessInstanceId());
175   - if (historicProcessInstance == null) {
176   - throw exception(ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS);
177   - }
178   - startUserId = Long.valueOf(historicProcessInstance.getStartUserId());
179   - processInstanceStatus = FlowableUtils.getProcessInstanceStatus(historicProcessInstance);
180   - // 合并 DB 和前端传递的流量变量,以前端的为主
181   - if (CollUtil.isNotEmpty(historicProcessInstance.getProcessVariables())) {
182   - processVariables.putAll(historicProcessInstance.getProcessVariables());
183   - }
184   - }
185   - if (CollUtil.isNotEmpty(reqVO.getProcessVariables())) {
186   - processVariables.putAll(reqVO.getProcessVariables());
187   - }
188   - // 1.3 读取其它相关数据
189   - ProcessDefinition processDefinition = processDefinitionService.getProcessDefinition(
190   - historicProcessInstance != null ? historicProcessInstance.getProcessDefinitionId()
191   - : reqVO.getProcessDefinitionId());
192   - BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService
193   - .getProcessDefinitionInfo(processDefinition.getId());
194   - BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(processDefinition.getId());
195   -
196   - // 2.1 已结束 + 进行中的活动节点
197   - List<ActivityNode> endActivityNodes = null; // 已结束的审批信息
198   - List<ActivityNode> runActivityNodes = null; // 进行中的审批信息
199   - List<HistoricActivityInstance> activities = null; // 流程实例列表
200   - if (reqVO.getProcessInstanceId() != null) {
201   - activities = taskService.getActivityListByProcessInstanceId(reqVO.getProcessInstanceId());
202   - List<HistoricTaskInstance> tasks = taskService.getTaskListByProcessInstanceId(reqVO.getProcessInstanceId(),
203   - true);
204   - endActivityNodes = getEndActivityNodeList(startUserId, bpmnModel, processDefinitionInfo,
205   - historicProcessInstance, processInstanceStatus, activities, tasks);
206   - runActivityNodes = getRunApproveNodeList(startUserId, bpmnModel, processDefinition, processVariables,
207   - activities, tasks);
208   - }
209   -
210   - // 2.2 流程已经结束,直接 return,无需预测
211   - if (BpmProcessInstanceStatusEnum.isProcessEndStatus(processInstanceStatus)) {
212   - return buildApprovalDetail(reqVO, bpmnModel, processDefinition, processDefinitionInfo,
213   - historicProcessInstance,
214   - processInstanceStatus, endActivityNodes, runActivityNodes, null, null);
215   - }
216   -
217   - // 3.1 计算当前登录用户的待办任务
218   - BpmTaskRespVO todoTask = taskService.getTodoTask(loginUserId, reqVO.getTaskId(), reqVO.getProcessInstanceId());
219   - // 3.2 预测未运行节点的审批信息
220   - List<ActivityNode> simulateActivityNodes = getSimulateApproveNodeList(startUserId, bpmnModel,
221   - processDefinitionInfo,
222   - processVariables, activities);
223   - // 3.3 如果是发起动作,activityId 为开始节点,不校验审批人自选节点
224   - if (ObjUtil.equals(reqVO.getActivityId(), BpmnModelConstants.START_USER_NODE_ID)) {
225   - simulateActivityNodes.removeIf(node ->
226   - BpmTaskCandidateStrategyEnum.APPROVE_USER_SELECT.getStrategy().equals(node.getCandidateStrategy()));
227   - }
228   -
229   - // 4. 拼接最终数据
230   - return buildApprovalDetail(reqVO, bpmnModel, processDefinition, processDefinitionInfo, historicProcessInstance,
231   - processInstanceStatus, endActivityNodes, runActivityNodes, simulateActivityNodes, todoTask);
232   - }
233   -
234   - @Override
235   - public List<ActivityNode> getNextApprovalNodes(Long loginUserId, BpmApprovalDetailReqVO reqVO) {
236   - // 1.1 校验任务存在,且是当前用户的
237   - Task task = taskService.validateTask(loginUserId, reqVO.getTaskId());
238   - // 1.2 校验流程实例存在
239   - ProcessInstance instance = getProcessInstance(task.getProcessInstanceId());
240   - if (instance == null) {
241   - throw exception(PROCESS_INSTANCE_NOT_EXISTS);
242   - }
243   - HistoricProcessInstance historicProcessInstance = getHistoricProcessInstance(task.getProcessInstanceId());
244   - if (historicProcessInstance == null) {
245   - throw exception(ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS);
246   - }
247   - // 1.3 校验BpmnModel
248   - BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(task.getProcessDefinitionId());
249   - if (bpmnModel == null) {
250   - return null;
251   - }
252   -
253   - // 2. 设置流程变量
254   - Map<String, Object> processVariables = new HashMap<>();
255   - // 2.1 获取历史中流程变量
256   - if (CollUtil.isNotEmpty(historicProcessInstance.getProcessVariables())) {
257   - processVariables.putAll(historicProcessInstance.getProcessVariables());
258   - }
259   - // 2.2 合并前端传递的流程变量,以前端为准
260   - if (CollUtil.isNotEmpty(reqVO.getProcessVariables())) {
261   - processVariables.putAll(reqVO.getProcessVariables());
262   - }
263   -
264   - // 3. 获取下一个将要执行的节点集合
265   - FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey());
266   - List<FlowNode> nextFlowNodes = BpmnModelUtils.getNextFlowNodes(flowElement, bpmnModel, processVariables);
267   - List<ActivityNode> nextActivityNodes = convertList(nextFlowNodes, node -> new ActivityNode().setId(node.getId())
268   - .setName(node.getName()).setNodeType(BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType())
269   - .setStatus(BpmTaskStatusEnum.RUNNING.getStatus())
270   - .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(node))
271   - .setCandidateUserIds(getTaskCandidateUserList(bpmnModel, node.getId(),
272   - loginUserId, historicProcessInstance.getProcessDefinitionId(), processVariables)));
273   - if (CollUtil.isNotEmpty(nextActivityNodes)) {
274   - return nextActivityNodes;
275   - }
276   -
277   - // 4. 拼接基础信息
278   - Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
279   - convertSetByFlatMap(nextActivityNodes, ActivityNode::getCandidateUserIds, Collection::stream));
280   - Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
281   - nextActivityNodes.forEach(node -> node.setCandidateUsers(convertList(node.getCandidateUserIds(), userId -> {
282   - AdminUserRespDTO user = userMap.get(userId);
283   - if (user != null) {
284   - return BpmProcessInstanceConvert.INSTANCE.buildUser(userId, userMap, deptMap);
285   - }
286   - return null;
287   - })));
288   - return nextActivityNodes;
289   - }
290   -
291   - @Override
292   - @SuppressWarnings("unchecked")
293   - public PageResult<HistoricProcessInstance> getProcessInstancePage(Long userId,
294   - BpmProcessInstancePageReqVO pageReqVO) {
295   - // 1. 构建查询条件
296   - HistoricProcessInstanceQuery processInstanceQuery = historyService.createHistoricProcessInstanceQuery()
297   - .includeProcessVariables()
298   - .processInstanceTenantId(FlowableUtils.getTenantId())
299   - .orderByProcessInstanceStartTime().desc();
300   - if (userId != null) { // 【我的流程】菜单时,需要传递该字段
301   - processInstanceQuery.startedBy(String.valueOf(userId));
302   - } else if (pageReqVO.getStartUserId() != null) { // 【管理流程】菜单时,才会传递该字段
303   - processInstanceQuery.startedBy(String.valueOf(pageReqVO.getStartUserId()));
304   - }
305   - if (StrUtil.isNotEmpty(pageReqVO.getName())) {
306   - processInstanceQuery.processInstanceNameLike("%" + pageReqVO.getName() + "%");
307   - }
308   - if (StrUtil.isNotEmpty(pageReqVO.getProcessDefinitionKey())) {
309   - processInstanceQuery.processDefinitionKey(pageReqVO.getProcessDefinitionKey());
310   - }
311   - if (StrUtil.isNotEmpty(pageReqVO.getCategory())) {
312   - processInstanceQuery.processDefinitionCategory(pageReqVO.getCategory());
313   - }
314   - if (pageReqVO.getStatus() != null) {
315   - processInstanceQuery.variableValueEquals(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS,
316   - pageReqVO.getStatus());
317   - }
318   - if (ArrayUtil.isNotEmpty(pageReqVO.getCreateTime())) {
319   - processInstanceQuery.startedAfter(DateUtils.of(pageReqVO.getCreateTime()[0]));
320   - processInstanceQuery.startedBefore(DateUtils.of(pageReqVO.getCreateTime()[1]));
321   - }
322   - if (ArrayUtil.isNotEmpty(pageReqVO.getEndTime())) {
323   - processInstanceQuery.finishedAfter(DateUtils.of(pageReqVO.getEndTime()[0]));
324   - processInstanceQuery.finishedBefore(DateUtils.of(pageReqVO.getEndTime()[1]));
325   - }
326   - // 表单字段查询
327   - Map<String, Object> formFieldsParams = JsonUtils.parseObject(pageReqVO.getFormFieldsParams(), Map.class);
328   - if (CollUtil.isNotEmpty(formFieldsParams)) {
329   - formFieldsParams.forEach((key, value) -> {
330   - if (StrUtil.isEmpty(String.valueOf(value))) {
331   - return;
332   - }
333   - // TODO @lesan:应支持多种类型的查询方式,目前只有字符串全等
334   - processInstanceQuery.variableValueEquals(key, value);
335   - });
336   - }
337   -
338   - // 2.1 查询数量
339   - long processInstanceCount = processInstanceQuery.count();
340   - if (processInstanceCount == 0) {
341   - return PageResult.empty(processInstanceCount);
342   - }
343   - // 2.2 查询列表
344   - List<HistoricProcessInstance> processInstanceList = processInstanceQuery.listPage(PageUtils.getStart(pageReqVO),
345   - pageReqVO.getPageSize());
346   - return new PageResult<>(processInstanceList, processInstanceCount);
347   - }
348   -
349   - /**
350   - * 拼接审批详情的最终数据
351   - * <p>
352   - * 主要是,拼接审批人的用户信息、部门信息
353   - */
354   - private BpmApprovalDetailRespVO buildApprovalDetail(BpmApprovalDetailReqVO reqVO,
355   - BpmnModel bpmnModel,
356   - ProcessDefinition processDefinition,
357   - BpmProcessDefinitionInfoDO processDefinitionInfo,
358   - HistoricProcessInstance processInstance,
359   - Integer processInstanceStatus,
360   - List<ActivityNode> endApprovalNodeInfos,
361   - List<ActivityNode> runningApprovalNodeInfos,
362   - List<ActivityNode> simulateApprovalNodeInfos,
363   - BpmTaskRespVO todoTask) {
364   - // 1. 获取所有需要读取用户信息的 userIds
365   - List<ActivityNode> approveNodes = newArrayList(
366   - asList(endApprovalNodeInfos, runningApprovalNodeInfos, simulateApprovalNodeInfos));
367   - Set<Long> userIds = BpmProcessInstanceConvert.INSTANCE.parseUserIds(processInstance, approveNodes, todoTask);
368   - Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
369   - Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
370   -
371   - // 2. 表单权限
372   - String taskId = reqVO.getTaskId() == null && todoTask != null ? todoTask.getId() : reqVO.getTaskId();
373   - Map<String, String> formFieldsPermission = getFormFieldsPermission(bpmnModel, reqVO.getActivityId(), taskId);
374   -
375   - // 3. 拼接数据
376   - return BpmProcessInstanceConvert.INSTANCE.buildApprovalDetail(bpmnModel, processDefinition,
377   - processDefinitionInfo, processInstance,
378   - processInstanceStatus, approveNodes, todoTask, formFieldsPermission, userMap, deptMap);
379   - }
380   -
381   - /**
382   - * 获得【已结束】的活动节点们
383   - */
384   - private List<ActivityNode> getEndActivityNodeList(Long startUserId, BpmnModel bpmnModel,
385   - BpmProcessDefinitionInfoDO processDefinitionInfo,
386   - HistoricProcessInstance historicProcessInstance, Integer processInstanceStatus,
387   - List<HistoricActivityInstance> activities, List<HistoricTaskInstance> tasks) {
388   - // 遍历 tasks 列表,只处理已结束的 UserTask
389   - // 为什么不通过 activities 呢?因为,加签场景下,它只存在于 tasks,没有 activities,导致如果遍历 activities 的话,它无法成为一个节点
390   - List<HistoricTaskInstance> endTasks = filterList(tasks, task -> task.getEndTime() != null);
391   - List<ActivityNode> approvalNodes = convertList(endTasks, task -> {
392   - FlowElement flowNode = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
393   - ActivityNode activityNode = new ActivityNode().setId(task.getTaskDefinitionKey()).setName(task.getName())
394   - .setNodeType(START_USER_NODE_ID.equals(task.getTaskDefinitionKey())
395   - ? BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType()
396   - : ObjUtil.defaultIfNull(parseNodeType(flowNode), // 目的:解决“办理节点”的识别
397   - BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()))
398   - .setStatus(FlowableUtils.getTaskStatus(task))
399   - .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode))
400   - .setStartTime(DateUtils.of(task.getCreateTime())).setEndTime(DateUtils.of(task.getEndTime()))
401   - .setTasks(singletonList(BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(task)));
402   - // 如果是取消状态,则跳过
403   - if (BpmTaskStatusEnum.isCancelStatus(activityNode.getStatus())) {
404   - return null;
405   - }
406   - return activityNode;
407   - });
408   -
409   - // 遍历 activities,只处理已结束的 StartEvent、EndEvent
410   - List<HistoricActivityInstance> endActivities = filterList(activities, activity -> activity.getEndTime() != null
411   - && (StrUtil.equalsAny(activity.getActivityType(), ELEMENT_EVENT_START, ELEMENT_CALL_ACTIVITY, ELEMENT_EVENT_END)));
412   - endActivities.forEach(activity -> {
413   - // StartEvent:只处理 BPMN 的场景。因为,SIMPLE 情况下,已经有 START_USER_NODE 节点
414   - if (ELEMENT_EVENT_START.equals(activity.getActivityType())
415   - && BpmModelTypeEnum.BPMN.getType().equals(processDefinitionInfo.getModelType())) {
416   - ActivityNodeTask startTask = new ActivityNodeTask().setId(BpmnModelConstants.START_USER_NODE_ID)
417   - .setAssignee(startUserId).setStatus(BpmTaskStatusEnum.APPROVE.getStatus());
418   - ActivityNode startNode = new ActivityNode().setId(startTask.getId())
419   - .setName(BpmSimpleModelNodeTypeEnum.START_USER_NODE.getName())
420   - .setNodeType(BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType())
421   - .setStatus(startTask.getStatus()).setTasks(ListUtil.of(startTask))
422   - .setStartTime(DateUtils.of(activity.getStartTime()))
423   - .setEndTime(DateUtils.of(activity.getEndTime()));
424   - approvalNodes.add(0, startNode);
425   - return;
426   - }
427   - // EndEvent
428   - if (ELEMENT_EVENT_END.equals(activity.getActivityType())) {
429   - if (BpmProcessInstanceStatusEnum.isRejectStatus(processInstanceStatus)) {
430   - // 拒绝情况下,不需要展示 EndEvent 结束节点。原因是:前端已经展示 x 效果,无需重复展示
431   - return;
432   - }
433   - ActivityNode endNode = new ActivityNode().setId(activity.getId())
434   - .setName(BpmSimpleModelNodeTypeEnum.END_NODE.getName())
435   - .setNodeType(BpmSimpleModelNodeTypeEnum.END_NODE.getType()).setStatus(processInstanceStatus)
436   - .setStartTime(DateUtils.of(activity.getStartTime()))
437   - .setEndTime(DateUtils.of(activity.getEndTime()));
438   - String reason = FlowableUtils.getProcessInstanceReason(historicProcessInstance);
439   - if (StrUtil.isNotEmpty(reason)) {
440   - endNode.setTasks(singletonList(new ActivityNodeTask().setId(endNode.getId())
441   - .setStatus(endNode.getStatus()).setReason(reason)));
442   - }
443   - approvalNodes.add(endNode);
444   - }
445   - // CallActivity
446   - if (ELEMENT_CALL_ACTIVITY.equals(activity.getActivityType())) {
447   - ActivityNode callActivity = new ActivityNode().setId(activity.getId())
448   - .setName(BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getName())
449   - .setNodeType(BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType()).setStatus(processInstanceStatus)
450   - .setStartTime(DateUtils.of(activity.getStartTime()))
451   - .setEndTime(DateUtils.of(activity.getEndTime()))
452   - .setProcessInstanceId(activity.getProcessInstanceId());
453   - approvalNodes.add(callActivity);
454   - }
455   - });
456   -
457   - // 按照时间排序
458   - approvalNodes.sort(Comparator.comparing(ActivityNode::getStartTime));
459   - return approvalNodes;
460   - }
461   -
462   - /**
463   - * 获得【进行中】的活动节点们
464   - */
465   - private List<ActivityNode> getRunApproveNodeList(Long startUserId,
466   - BpmnModel bpmnModel,
467   - ProcessDefinition processDefinition,
468   - Map<String, Object> processVariables,
469   - List<HistoricActivityInstance> activities,
470   - List<HistoricTaskInstance> tasks) {
471   - // 构建运行中的任务、子流程,基于 activityId 分组
472   - List<HistoricActivityInstance> runActivities = filterList(activities, activity -> activity.getEndTime() == null
473   - && (StrUtil.equalsAny(activity.getActivityType(), ELEMENT_TASK_USER, ELEMENT_CALL_ACTIVITY)));
474   - Map<String, List<HistoricActivityInstance>> runningTaskMap = convertMultiMap(runActivities,
475   - HistoricActivityInstance::getActivityId);
476   -
477   - // 按照 activityId 分组,构建 ApprovalNodeInfo 节点
478   - Map<String, HistoricTaskInstance> taskMap = convertMap(tasks, HistoricTaskInstance::getId);
479   - return convertList(runningTaskMap.entrySet(), entry -> {
480   - String activityId = entry.getKey();
481   - List<HistoricActivityInstance> taskActivities = entry.getValue();
482   - // 构建活动节点
483   - FlowElement flowNode = BpmnModelUtils.getFlowElementById(bpmnModel, activityId);
484   - HistoricActivityInstance firstActivity = CollUtil.getFirst(taskActivities); // 取第一个任务,会签/或签的任务,开始时间相同
485   - ActivityNode activityNode = new ActivityNode().setId(firstActivity.getActivityId())
486   - .setName(firstActivity.getActivityName())
487   - .setNodeType(ObjUtil.defaultIfNull(parseNodeType(flowNode), // 目的:解决“办理节点”和"子流程"的识别
488   - BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()))
489   - .setStatus(BpmTaskStatusEnum.RUNNING.getStatus())
490   - .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode))
491   - .setStartTime(DateUtils.of(CollUtil.getFirst(taskActivities).getStartTime()))
492   - .setTasks(new ArrayList<>());
493   - // 处理每个任务的 tasks 属性
494   - for (HistoricActivityInstance activity : taskActivities) {
495   - HistoricTaskInstance task = taskMap.get(activity.getTaskId());
496   - // 特殊情况:子流程节点 ChildProcess 仅存在于 activity 中,并且没有自身的 task,需要跳过执行
497   - // TODO @芋艿:后续看看怎么优化!
498   - if (task == null) {
499   - continue;
500   - }
501   - activityNode.getTasks().add(BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(task));
502   - // 加签子任务,需要过滤掉已经完成的加签子任务
503   - List<HistoricTaskInstance> childrenTasks = filterList(
504   - taskService.getAllChildrenTaskListByParentTaskId(activity.getTaskId(), tasks),
505   - childTask -> childTask.getEndTime() == null);
506   - if (CollUtil.isNotEmpty(childrenTasks)) {
507   - activityNode.getTasks().addAll(
508   - convertList(childrenTasks, BpmProcessInstanceConvert.INSTANCE::buildApprovalTaskInfo));
509   - }
510   - }
511   - // 处理每个任务的 candidateUsers 属性:如果是依次审批,需要预测它的后续审批人。因为 Task 是审批完一个,创建一个新的 Task
512   - if (BpmnModelUtils.isSequentialUserTask(flowNode)) {
513   - List<Long> candidateUserIds = getTaskCandidateUserList(bpmnModel, flowNode.getId(),
514   - startUserId, processDefinition.getId(), processVariables);
515   - // 截取当前审批人位置后面的候选人,不包含当前审批人
516   - ActivityNodeTask approvalTaskInfo = CollUtil.getFirst(activityNode.getTasks());
517   - Assert.notNull(approvalTaskInfo, "任务不能为空");
518   - int index = CollUtil.indexOf(candidateUserIds,
519   - userId -> ObjectUtils.equalsAny(userId, approvalTaskInfo.getOwner(),
520   - approvalTaskInfo.getAssignee())); // 委派或者向前加签情况,需要先比较 owner
521   - activityNode.setCandidateUserIds(CollUtil.sub(candidateUserIds, index + 1, candidateUserIds.size()));
522   - }
523   - if (BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType().equals(activityNode.getNodeType())) {
524   - activityNode.setProcessInstanceId(firstActivity.getProcessInstanceId());
525   - }
526   - return activityNode;
527   - });
528   - }
529   -
530   - /**
531   - * 获得【预测(未来)】的活动节点们
532   - */
533   - private List<ActivityNode> getSimulateApproveNodeList(Long startUserId, BpmnModel bpmnModel,
534   - BpmProcessDefinitionInfoDO processDefinitionInfo,
535   - Map<String, Object> processVariables,
536   - List<HistoricActivityInstance> activities) {
537   - // TODO @芋艿:【可优化】在驳回场景下,未来的预测准确性不高。原因是,驳回后,HistoricActivityInstance
538   - // 包括了历史的操作,不是只有 startEvent 到当前节点的记录
539   - Set<String> runActivityIds = convertSet(activities, HistoricActivityInstance::getActivityId);
540   - // 情况一:BPMN 设计器
541   - if (Objects.equals(BpmModelTypeEnum.BPMN.getType(), processDefinitionInfo.getModelType())) {
542   - List<FlowElement> flowElements = BpmnModelUtils.simulateProcess(bpmnModel, processVariables);
543   - return convertList(flowElements, flowElement -> buildNotRunApproveNodeForBpmn(startUserId, bpmnModel,
544   - processDefinitionInfo, processVariables, flowElement, runActivityIds));
545   - }
546   - // 情况二:SIMPLE 设计器
547   - if (Objects.equals(BpmModelTypeEnum.SIMPLE.getType(), processDefinitionInfo.getModelType())) {
548   - BpmSimpleModelNodeVO simpleModel = JsonUtils.parseObject(processDefinitionInfo.getSimpleModel(),
549   - BpmSimpleModelNodeVO.class);
550   - List<BpmSimpleModelNodeVO> simpleNodes = SimpleModelUtils.simulateProcess(simpleModel, processVariables);
551   - return convertList(simpleNodes, simpleNode -> buildNotRunApproveNodeForSimple(startUserId, bpmnModel,
552   - processDefinitionInfo, processVariables, simpleNode, runActivityIds));
553   - }
554   - throw new IllegalArgumentException("未知设计器类型:" + processDefinitionInfo.getModelType());
555   - }
556   -
557   - private ActivityNode buildNotRunApproveNodeForSimple(Long startUserId, BpmnModel bpmnModel,
558   - BpmProcessDefinitionInfoDO processDefinitionInfo, Map<String, Object> processVariables,
559   - BpmSimpleModelNodeVO node, Set<String> runActivityIds) {
560   - // TODO @芋艿:【可优化】在驳回场景下,未来的预测准确性不高。原因是,驳回后,HistoricActivityInstance
561   - // 包括了历史的操作,不是只有 startEvent 到当前节点的记录
562   - if (runActivityIds.contains(node.getId())) {
563   - return null;
564   - }
565   -
566   - ActivityNode activityNode = new ActivityNode().setId(node.getId()).setName(node.getName())
567   - .setNodeType(node.getType()).setCandidateStrategy(node.getCandidateStrategy())
568   - .setStatus(BpmTaskStatusEnum.NOT_START.getStatus());
569   -
570   - // 1. 开始节点/审批节点
571   - if (ObjectUtils.equalsAny(node.getType(),
572   - BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType(),
573   - BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType(),
574   - BpmSimpleModelNodeTypeEnum.TRANSACTOR_NODE.getType())) {
575   - List<Long> candidateUserIds = getTaskCandidateUserList(bpmnModel, node.getId(),
576   - startUserId, processDefinitionInfo.getProcessDefinitionId(), processVariables);
577   - activityNode.setCandidateUserIds(candidateUserIds);
578   - return activityNode;
579   - }
580   -
581   - // 2. 结束节点
582   - if (BpmSimpleModelNodeTypeEnum.END_NODE.getType().equals(node.getType())) {
583   - return activityNode;
584   - }
585   -
586   - // 3. 抄送节点
587   - if (CollUtil.isEmpty(runActivityIds) && // 流程发起时:需要展示抄送节点,用于选择抄送人
588   - BpmSimpleModelNodeTypeEnum.COPY_NODE.getType().equals(node.getType())) {
589   - List<Long> candidateUserIds = getTaskCandidateUserList(bpmnModel, node.getId(),
590   - startUserId, processDefinitionInfo.getProcessDefinitionId(), processVariables);
591   - activityNode.setCandidateUserIds(candidateUserIds);
592   - return activityNode;
593   - }
594   -
595   - // 4. 子流程节点
596   - if (BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType().equals(node.getType())) {
597   - return activityNode;
598   - }
599   - return null;
600   - }
601   -
602   - private ActivityNode buildNotRunApproveNodeForBpmn(Long startUserId, BpmnModel bpmnModel,
603   - BpmProcessDefinitionInfoDO processDefinitionInfo, Map<String, Object> processVariables,
604   - FlowElement node, Set<String> runActivityIds) {
605   - if (runActivityIds.contains(node.getId())) {
606   - return null;
607   - }
608   - ActivityNode activityNode = new ActivityNode().setId(node.getId())
609   - .setStatus(BpmTaskStatusEnum.NOT_START.getStatus());
610   -
611   - // 1. 开始节点
612   - if (node instanceof StartEvent) {
613   - return activityNode.setName(BpmSimpleModelNodeTypeEnum.START_USER_NODE.getName())
614   - .setNodeType(BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType());
615   - }
616   -
617   - // 2. 审批节点
618   - if (node instanceof UserTask) {
619   - List<Long> candidateUserIds = getTaskCandidateUserList(bpmnModel, node.getId(),
620   - startUserId, processDefinitionInfo.getProcessDefinitionId(), processVariables);
621   - return activityNode.setName(node.getName()).setNodeType(BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType())
622   - .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(node))
623   - .setCandidateUserIds(candidateUserIds);
624   - }
625   -
626   - // 3. 结束节点
627   - if (node instanceof EndEvent) {
628   - return activityNode.setName(BpmSimpleModelNodeTypeEnum.END_NODE.getName())
629   - .setNodeType(BpmSimpleModelNodeTypeEnum.END_NODE.getType());
630   - }
631   - return null;
632   - }
633   -
634   - private List<Long> getTaskCandidateUserList(BpmnModel bpmnModel, String activityId,
635   - Long startUserId, String processDefinitionId, Map<String, Object> processVariables) {
636   - Set<Long> userIds = taskCandidateInvoker.calculateUsersByActivity(bpmnModel, activityId,
637   - startUserId, processDefinitionId, processVariables);
638   - return new ArrayList<>(userIds);
639   - }
640   -
641   - @Override
642   - public BpmProcessInstanceBpmnModelViewRespVO getProcessInstanceBpmnModelView(String id) {
643   - // 1.1 获得流程实例
644   - HistoricProcessInstance processInstance = getHistoricProcessInstance(id);
645   - if (processInstance == null) {
646   - return null;
647   - }
648   - // 1.2 获得流程定义
649   - BpmnModel bpmnModel = processDefinitionService
650   - .getProcessDefinitionBpmnModel(processInstance.getProcessDefinitionId());
651   - if (bpmnModel == null) {
652   - return null;
653   - }
654   - BpmSimpleModelNodeVO simpleModel = null;
655   - BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.getProcessDefinitionInfo(
656   - processInstance.getProcessDefinitionId());
657   - if (processDefinitionInfo != null
658   - && BpmModelTypeEnum.SIMPLE.getType().equals(processDefinitionInfo.getModelType())) {
659   - simpleModel = JsonUtils.parseObject(processDefinitionInfo.getSimpleModel(), BpmSimpleModelNodeVO.class);
660   - }
661   - // 1.3 获得流程实例对应的活动实例列表 + 任务列表
662   - List<HistoricActivityInstance> activities = taskService.getActivityListByProcessInstanceId(id);
663   - List<HistoricTaskInstance> tasks = taskService.getTaskListByProcessInstanceId(id, true);
664   -
665   - // 2.1 拼接进度信息
666   - Set<String> unfinishedTaskActivityIds = convertSet(activities, HistoricActivityInstance::getActivityId,
667   - activityInstance -> activityInstance.getEndTime() == null);
668   - Set<String> finishedTaskActivityIds = convertSet(activities, HistoricActivityInstance::getActivityId,
669   - activityInstance -> activityInstance.getEndTime() != null
670   - && ObjectUtil.notEqual(activityInstance.getActivityType(),
671   - BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW));
672   - Set<String> finishedSequenceFlowActivityIds = convertSet(activities, HistoricActivityInstance::getActivityId,
673   - activityInstance -> activityInstance.getEndTime() != null
674   - && ObjectUtil.equals(activityInstance.getActivityType(),
675   - BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW));
676   - // 特殊:会签情况下,会有部分已完成(审批)、部分未完成(待审批),此时需要 finishedTaskActivityIds 移除掉
677   - finishedTaskActivityIds.removeAll(unfinishedTaskActivityIds);
678   - // 特殊:如果流程实例被拒绝,则需要计算是哪个活动节点。
679   - // 注意,只取最后一个。因为会存在多次拒绝的情况,拒绝驳回到指定节点
680   - Set<String> rejectTaskActivityIds = CollUtil.newHashSet();
681   - if (BpmProcessInstanceStatusEnum.isRejectStatus(FlowableUtils.getProcessInstanceStatus(processInstance))) {
682   - tasks.stream()
683   - .filter(task -> BpmTaskStatusEnum.isRejectStatus(FlowableUtils.getTaskStatus(task)))
684   - .max(Comparator.comparing(HistoricTaskInstance::getEndTime))
685   - .ifPresent(reject -> rejectTaskActivityIds.add(reject.getTaskDefinitionKey()));
686   - finishedTaskActivityIds.removeAll(rejectTaskActivityIds);
687   - }
688   -
689   - // 2.2 拼接基础信息
690   - Set<Long> userIds = BpmProcessInstanceConvert.INSTANCE.parseUserIds02(processInstance, tasks);
691   - Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
692   - Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
693   - return BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceBpmnModelView(processInstance, tasks, bpmnModel,
694   - simpleModel,
695   - unfinishedTaskActivityIds, finishedTaskActivityIds, finishedSequenceFlowActivityIds,
696   - rejectTaskActivityIds,
697   - userMap, deptMap);
698   - }
699   -
700   - // ========== Update 写入相关方法 ==========
701   -
702   - @Override
703   - @Transactional(rollbackFor = Exception.class)
704   - public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) {
705   - // 获得流程定义
706   - ProcessDefinition definition = processDefinitionService
707   - .getProcessDefinition(createReqVO.getProcessDefinitionId());
708   - // 发起流程
709   - return createProcessInstance0(userId, definition, createReqVO.getVariables(), null,
710   - createReqVO.getStartUserSelectAssignees());
711   - }
712   -
713   - @Override
714   - public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) {
715   - return FlowableUtils.executeAuthenticatedUserId(userId, () -> {
716   - // 获得流程定义
717   - ProcessDefinition definition = processDefinitionService
718   - .getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey());
719   - // 发起流程
720   - return createProcessInstance0(userId, definition, createReqDTO.getVariables(),
721   - createReqDTO.getBusinessKey(),
722   - createReqDTO.getStartUserSelectAssignees());
723   - });
724   - }
725   -
726   - private String createProcessInstance0(Long userId, ProcessDefinition definition,
727   - Map<String, Object> variables, String businessKey,
728   - Map<String, List<Long>> startUserSelectAssignees) {
729   - // 1.1 校验流程定义
730   - if (definition == null) {
731   - throw exception(PROCESS_DEFINITION_NOT_EXISTS);
732   - }
733   - if (definition.isSuspended()) {
734   - throw exception(PROCESS_DEFINITION_IS_SUSPENDED);
735   - }
736   - BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService
737   - .getProcessDefinitionInfo(definition.getId());
738   - if (processDefinitionInfo == null) {
739   - throw exception(PROCESS_DEFINITION_NOT_EXISTS);
740   - }
741   - // 1.2 校验是否能够发起
742   - if (!processDefinitionService.canUserStartProcessDefinition(processDefinitionInfo, userId)) {
743   - throw exception(PROCESS_INSTANCE_START_USER_CAN_START);
744   - }
745   - // 1.3 校验发起人自选审批人
746   - validateStartUserSelectAssignees(userId, definition, startUserSelectAssignees, variables);
747   -
748   - // 2. 创建流程实例
749   - if (variables == null) {
750   - variables = new HashMap<>();
751   - }
752   - FlowableUtils.filterProcessInstanceFormVariable(variables); // 过滤一下,避免 ProcessInstance 系统级的变量被占用
753   - variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, userId); // 设置流程变量,发起人 ID
754   - variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, // 流程实例状态:审批中
755   - BpmProcessInstanceStatusEnum.RUNNING.getStatus());
756   - variables.put(BpmnVariableConstants.PROCESS_INSTANCE_SKIP_EXPRESSION_ENABLED, true); // 跳过表达式需要添加此变量为 true,不影响没配置 skipExpression 的节点
757   - if (CollUtil.isNotEmpty(startUserSelectAssignees)) {
758   - // 设置流程变量,发起人自选审批人
759   - variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES,
760   - startUserSelectAssignees);
761   - }
762   -
763   - // 3. 创建流程
764   - ProcessInstanceBuilder processInstanceBuilder = runtimeService.createProcessInstanceBuilder()
765   - .processDefinitionId(definition.getId())
766   - .businessKey(businessKey)
767   - .variables(variables);
768   - // 3.1 创建流程 ID
769   - BpmModelMetaInfoVO.ProcessIdRule processIdRule = processDefinitionInfo.getProcessIdRule();
770   - if (processIdRule != null && Boolean.TRUE.equals(processIdRule.getEnable())) {
771   - processInstanceBuilder.predefineProcessInstanceId(processIdRedisDAO.generate(processIdRule));
772   - }
773   - // 3.2 流程名称
774   - BpmModelMetaInfoVO.TitleSetting titleSetting = processDefinitionInfo.getTitleSetting();
775   - if (titleSetting != null && Boolean.TRUE.equals(titleSetting.getEnable())) {
776   - AdminUserRespDTO user = adminUserApi.getUser(userId);
777   - Map<String, Object> cloneVariables = new HashMap<>(variables);
778   - cloneVariables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, user.getNickname());
779   - cloneVariables.put(BpmnVariableConstants.PROCESS_START_TIME, DateUtil.now());
780   - cloneVariables.put(BpmnVariableConstants.PROCESS_DEFINITION_NAME, definition.getName().trim());
781   - processInstanceBuilder.name(StrUtil.format(titleSetting.getTitle(), cloneVariables));
782   - } else {
783   - processInstanceBuilder.name(definition.getName().trim());
784   - }
785   - // 3.3 发起流程实例
786   - ProcessInstance instance = processInstanceBuilder.start();
787   - return instance.getId();
788   - }
789   -
790   - private void validateStartUserSelectAssignees(Long userId, ProcessDefinition definition,
791   - Map<String, List<Long>> startUserSelectAssignees,
792   - Map<String, Object> variables) {
793   - // 1. 获取预测的节点信息
794   - BpmApprovalDetailRespVO detailRespVO = getApprovalDetail(userId, new BpmApprovalDetailReqVO()
795   - .setProcessDefinitionId(definition.getId())
796   - .setProcessVariables(variables));
797   - List<ActivityNode> activityNodes = detailRespVO.getActivityNodes();
798   - if (CollUtil.isEmpty(activityNodes)) {
799   - return;
800   - }
801   -
802   - // 2.1 移除掉不是发起人自选审批人节点
803   - activityNodes.removeIf(task ->
804   - ObjectUtil.notEqual(BpmTaskCandidateStrategyEnum.START_USER_SELECT.getStrategy(), task.getCandidateStrategy()));
805   - // 2.2 流程发起时要先获取当前流程的预测走向节点,发起时只校验预测的节点发起人自选审批人的审批人和抄送人是否都配置了
806   - activityNodes.forEach(task -> {
807   - List<Long> assignees = startUserSelectAssignees != null ? startUserSelectAssignees.get(task.getId()) : null;
808   - if (CollUtil.isEmpty(assignees)) {
809   - throw exception(PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIG, task.getName());
810   - }
811   - Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(assignees);
812   - assignees.forEach(assignee -> {
813   - if (userMap.get(assignee) == null) {
814   - throw exception(PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_EXISTS, task.getName(), assignee);
815   - }
816   - });
817   - });
818   - }
819   -
820   - @Override
821   - public void cancelProcessInstanceByStartUser(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) {
822   - // 1.1 校验流程实例存在
823   - ProcessInstance instance = getProcessInstance(cancelReqVO.getId());
824   - if (instance == null) {
825   - throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS);
826   - }
827   - // 1.2 只能取消自己的
828   - if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) {
829   - throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF);
830   - }
831   - // 1.3 校验允许撤销审批中的申请
832   - BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService
833   - .getProcessDefinitionInfo(instance.getProcessDefinitionId());
834   - Assert.notNull(processDefinitionInfo, "流程定义({})不存在", processDefinitionInfo);
835   - if (processDefinitionInfo.getAllowCancelRunningProcess() != null // 防止未配置 AllowCancelRunningProcess , 默认为可取消
836   - && Boolean.FALSE.equals(processDefinitionInfo.getAllowCancelRunningProcess())) {
837   - throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW);
838   - }
839   - // 1.4 子流程不允许取消
840   - if (StrUtil.isNotBlank(instance.getSuperExecutionId())) {
841   - throw exception(PROCESS_INSTANCE_CANCEL_CHILD_FAIL_NOT_ALLOW);
842   - }
843   -
844   - // 2. 取消流程
845   - updateProcessInstanceCancel(cancelReqVO.getId(),
846   - BpmReasonEnum.CANCEL_PROCESS_INSTANCE_BY_START_USER.format(cancelReqVO.getReason()));
847   - }
848   -
849   - @Override
850   - public void cancelProcessInstanceByAdmin(Long userId, BpmProcessInstanceCancelReqVO cancelReqVO) {
851   - // 1.1 校验流程实例存在
852   - ProcessInstance instance = getProcessInstance(cancelReqVO.getId());
853   - if (instance == null) {
854   - throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS);
855   - }
856   -
857   - // 2. 取消流程
858   - AdminUserRespDTO user = adminUserApi.getUser(userId);
859   - updateProcessInstanceCancel(cancelReqVO.getId(),
860   - BpmReasonEnum.CANCEL_PROCESS_INSTANCE_BY_ADMIN.format(user.getNickname(), cancelReqVO.getReason()));
861   - }
862   -
863   - private void updateProcessInstanceCancel(String id, String reason) {
864   - // 1. 更新流程实例 status
865   - runtimeService.setVariable(id, BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS,
866   - BpmProcessInstanceStatusEnum.CANCEL.getStatus());
867   - runtimeService.setVariable(id, BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON, reason);
868   -
869   - // 2. 取消所有子流程
870   - List<ProcessInstance> childProcessInstances = runtimeService.createProcessInstanceQuery()
871   - .superProcessInstanceId(id).list();
872   - childProcessInstances.forEach(processInstance -> updateProcessInstanceCancel(
873   - processInstance.getProcessInstanceId(), BpmReasonEnum.CANCEL_CHILD_PROCESS_INSTANCE_BY_MAIN_PROCESS.getReason()));
874   -
875   - // 3. 结束流程
876   - taskService.moveTaskToEnd(id, reason);
877   - }
878   -
879   - @Override
880   - public void updateProcessInstanceReject(ProcessInstance processInstance, String reason) {
881   - runtimeService.setVariable(processInstance.getProcessInstanceId(),
882   - BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS,
883   - BpmProcessInstanceStatusEnum.REJECT.getStatus());
884   - runtimeService.setVariable(processInstance.getProcessInstanceId(),
885   - BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON,
886   - BpmReasonEnum.REJECT_TASK.format(reason));
887   - }
888   -
889   - @Override
890   - public void updateProcessInstanceVariables(String id, Map<String, Object> variables) {
891   - runtimeService.setVariables(id, variables);
892   - }
893   -
894   - @Override
895   - public void removeProcessInstanceVariables(String id, Collection<String> variableNames) {
896   - runtimeService.removeVariables(id, variableNames);
897   - }
898   -
899   - // ========== Event 事件相关方法 ==========
900   -
901   - @Override
902   - public void processProcessInstanceCompleted(ProcessInstance instance) {
903   - // 注意:需要基于 instance 设置租户编号,避免 Flowable 内部异步时,丢失租户编号
904   - FlowableUtils.execute(instance.getTenantId(), () -> {
905   - // 1.1 获取当前状态
906   - Integer status = (Integer) instance.getProcessVariables()
907   - .get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS);
908   - String reason = (String) instance.getProcessVariables()
909   - .get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON);
910   - // 1.2 当流程状态还是审批状态中,说明审批通过了,则变更下它的状态
911   - // 为什么这么处理?因为流程完成,并且完成了,说明审批通过了
912   - if (Objects.equals(status, BpmProcessInstanceStatusEnum.RUNNING.getStatus())) {
913   - status = BpmProcessInstanceStatusEnum.APPROVE.getStatus();
914   - runtimeService.setVariable(instance.getId(), BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS,
915   - status);
916   - }
917   -
918   - // 2. 发送对应的消息通知
919   - if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) {
920   - messageService.sendMessageWhenProcessInstanceApprove(
921   - BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceApproveMessage(instance));
922   - } else if (Objects.equals(status, BpmProcessInstanceStatusEnum.REJECT.getStatus())) {
923   - messageService.sendMessageWhenProcessInstanceReject(
924   - BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceRejectMessage(instance, reason));
925   - }
926   -
927   - // 3. 发送流程实例的状态事件
928   - processInstanceEventPublisher.sendProcessInstanceResultEvent(
929   - BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceStatusEvent(this, instance, status));
930   -
931   - // 4. 流程后置通知
932   - if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) {
933   - BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.
934   - getProcessDefinitionInfo(instance.getProcessDefinitionId());
935   - if (ObjUtil.isNotNull(processDefinitionInfo) &&
936   - ObjUtil.isNotNull(processDefinitionInfo.getProcessAfterTriggerSetting())) {
937   - BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessAfterTriggerSetting();
938   -
939   - BpmHttpRequestUtils.executeBpmHttpRequest(instance,
940   - setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse());
941   - }
942   - }
943   - });
944   - }
945   -
946   - @Override
947   - public void processProcessInstanceCreated(ProcessInstance instance) {
948   - // 注意:需要基于 instance 设置租户编号,避免 Flowable 内部异步时,丢失租户编号
949   - FlowableUtils.execute(instance.getTenantId(), () -> {
950   - // 流程前置通知
951   - BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.
952   - getProcessDefinitionInfo(instance.getProcessDefinitionId());
953   - if (ObjUtil.isNull(processDefinitionInfo) ||
954   - ObjUtil.isNull(processDefinitionInfo.getProcessBeforeTriggerSetting())) {
955   - return;
956   - }
957   - BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessBeforeTriggerSetting();
958   - BpmHttpRequestUtils.executeBpmHttpRequest(instance,
959   - setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse());
960   - });
961   - }
962   -
963   -}
  1 +package cn.iocoder.yudao.module.bpm.service.task;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.collection.ListUtil;
  5 +import cn.hutool.core.date.DateUtil;
  6 +import cn.hutool.core.lang.Assert;
  7 +import cn.hutool.core.util.ArrayUtil;
  8 +import cn.hutool.core.util.ObjUtil;
  9 +import cn.hutool.core.util.ObjectUtil;
  10 +import cn.hutool.core.util.StrUtil;
  11 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  12 +import cn.iocoder.yudao.framework.common.util.date.DateUtils;
  13 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  14 +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
  15 +import cn.iocoder.yudao.framework.common.util.object.PageUtils;
  16 +import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
  17 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModelMetaInfoVO;
  18 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
  19 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
  20 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO.ActivityNodeTask;
  21 +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
  22 +import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert;
  23 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
  24 +import cn.iocoder.yudao.module.bpm.dal.redis.BpmProcessIdRedisDAO;
  25 +import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants;
  26 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelTypeEnum;
  27 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmSimpleModelNodeTypeEnum;
  28 +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
  29 +import cn.iocoder.yudao.module.bpm.enums.task.BpmReasonEnum;
  30 +import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
  31 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateInvoker;
  32 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
  33 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
  34 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants;
  35 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.event.BpmProcessInstanceEventPublisher;
  36 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmHttpRequestUtils;
  37 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
  38 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
  39 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils;
  40 +import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
  41 +import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
  42 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  43 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  44 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  45 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  46 +import jakarta.annotation.Resource;
  47 +import jakarta.validation.Valid;
  48 +import lombok.extern.slf4j.Slf4j;
  49 +import org.flowable.bpmn.constants.BpmnXMLConstants;
  50 +import org.flowable.bpmn.model.*;
  51 +import org.flowable.engine.HistoryService;
  52 +import org.flowable.engine.RuntimeService;
  53 +import org.flowable.engine.history.HistoricActivityInstance;
  54 +import org.flowable.engine.history.HistoricProcessInstance;
  55 +import org.flowable.engine.history.HistoricProcessInstanceQuery;
  56 +import org.flowable.engine.repository.ProcessDefinition;
  57 +import org.flowable.engine.runtime.ProcessInstance;
  58 +import org.flowable.engine.runtime.ProcessInstanceBuilder;
  59 +import org.flowable.task.api.Task;
  60 +import org.flowable.task.api.history.HistoricTaskInstance;
  61 +import org.springframework.context.annotation.Lazy;
  62 +import org.springframework.stereotype.Service;
  63 +import org.springframework.transaction.annotation.Transactional;
  64 +import org.springframework.validation.annotation.Validated;
  65 +
  66 +import java.util.*;
  67 +
  68 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  69 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
  70 +import static cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO.ActivityNode;
  71 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
  72 +import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.START_USER_NODE_ID;
  73 +import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseNodeType;
  74 +import static java.util.Arrays.asList;
  75 +import static java.util.Collections.singletonList;
  76 +import static org.flowable.bpmn.constants.BpmnXMLConstants.*;
  77 +
  78 +/**
  79 + * 流程实例 Service 实现类
  80 + * <p>
  81 + * ProcessDefinition & ProcessInstance & Execution & Task 的关系:
  82 + * 1. <a href="https://blog.csdn.net/bobozai86/article/details/105210414" />
  83 + * <p>
  84 + * HistoricProcessInstance & ProcessInstance 的关系:
  85 + * 1. <a href=" https://my.oschina.net/843294669/blog/71902" />
  86 + * <p>
  87 + * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例
  88 + *
  89 + * @author 芋道源码
  90 + */
  91 +@Service
  92 +@Validated
  93 +@Slf4j
  94 +public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService {
  95 +
  96 + @Resource
  97 + private RuntimeService runtimeService;
  98 + @Resource
  99 + private HistoryService historyService;
  100 +
  101 + @Resource
  102 + private BpmProcessDefinitionService processDefinitionService;
  103 + @Resource
  104 + @Lazy // 避免循环依赖
  105 + private BpmTaskService taskService;
  106 + @Resource
  107 + private BpmMessageService messageService;
  108 +
  109 + @Resource
  110 + private AdminUserApi adminUserApi;
  111 + @Resource
  112 + private DeptApi deptApi;
  113 +
  114 + @Resource
  115 + private BpmProcessInstanceEventPublisher processInstanceEventPublisher;
  116 +
  117 + @Resource
  118 + private BpmTaskCandidateInvoker taskCandidateInvoker;
  119 +
  120 + @Resource
  121 + private BpmProcessIdRedisDAO processIdRedisDAO;
  122 +
  123 + // ========== Query 查询相关方法 ==========
  124 +
  125 + @Override
  126 + public ProcessInstance getProcessInstance(String id) {
  127 + return runtimeService.createProcessInstanceQuery()
  128 + .includeProcessVariables()
  129 + .processInstanceId(id)
  130 + .singleResult();
  131 + }
  132 +
  133 + @Override
  134 + public List<ProcessInstance> getProcessInstances(Set<String> ids) {
  135 + return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).includeProcessVariables().list();
  136 + }
  137 +
  138 + @Override
  139 + public HistoricProcessInstance getHistoricProcessInstance(String id) {
  140 + return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).includeProcessVariables()
  141 + .singleResult();
  142 + }
  143 +
  144 + @Override
  145 + public List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids) {
  146 + return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).includeProcessVariables()
  147 + .list();
  148 + }
  149 +
  150 + private Map<String, String> getFormFieldsPermission(BpmnModel bpmnModel,
  151 + String activityId, String taskId) {
  152 + // 1. 获取流程活动编号。流程活动 Id 为空事,从流程任务中获取流程活动 Id
  153 + if (StrUtil.isEmpty(activityId) && StrUtil.isNotEmpty(taskId)) {
  154 + activityId = Optional.ofNullable(taskService.getHistoricTask(taskId))
  155 + .map(HistoricTaskInstance::getTaskDefinitionKey).orElse(null);
  156 + }
  157 + if (StrUtil.isEmpty(activityId)) {
  158 + return null;
  159 + }
  160 +
  161 + // 2. 从 BpmnModel 中解析表单字段权限
  162 + return BpmnModelUtils.parseFormFieldsPermission(bpmnModel, activityId);
  163 + }
  164 +
  165 + @Override
  166 + public BpmApprovalDetailRespVO getApprovalDetail(Long loginUserId, BpmApprovalDetailReqVO reqVO) {
  167 + // 1.1 从 reqVO 中,读取公共变量
  168 + Long startUserId = loginUserId; // 流程发起人
  169 + HistoricProcessInstance historicProcessInstance = null; // 流程实例
  170 + Integer processInstanceStatus = BpmProcessInstanceStatusEnum.NOT_START.getStatus(); // 流程状态
  171 + Map<String, Object> processVariables = new HashMap<>(); // 流程变量
  172 + // 1.2 如果是流程已发起的场景,则使用流程实例的数据
  173 + if (reqVO.getProcessInstanceId() != null) {
  174 + historicProcessInstance = getHistoricProcessInstance(reqVO.getProcessInstanceId());
  175 + if (historicProcessInstance == null) {
  176 + throw exception(ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS);
  177 + }
  178 + startUserId = Long.valueOf(historicProcessInstance.getStartUserId());
  179 + processInstanceStatus = FlowableUtils.getProcessInstanceStatus(historicProcessInstance);
  180 + // 合并 DB 和前端传递的流量变量,以前端的为主
  181 + if (CollUtil.isNotEmpty(historicProcessInstance.getProcessVariables())) {
  182 + processVariables.putAll(historicProcessInstance.getProcessVariables());
  183 + }
  184 + }
  185 + if (CollUtil.isNotEmpty(reqVO.getProcessVariables())) {
  186 + processVariables.putAll(reqVO.getProcessVariables());
  187 + }
  188 + // 1.3 读取其它相关数据
  189 + ProcessDefinition processDefinition = processDefinitionService.getProcessDefinition(
  190 + historicProcessInstance != null ? historicProcessInstance.getProcessDefinitionId()
  191 + : reqVO.getProcessDefinitionId());
  192 + BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService
  193 + .getProcessDefinitionInfo(processDefinition.getId());
  194 + BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(processDefinition.getId());
  195 +
  196 + // 2.1 已结束 + 进行中的活动节点
  197 + List<ActivityNode> endActivityNodes = null; // 已结束的审批信息
  198 + List<ActivityNode> runActivityNodes = null; // 进行中的审批信息
  199 + List<HistoricActivityInstance> activities = null; // 流程实例列表
  200 + if (reqVO.getProcessInstanceId() != null) {
  201 + activities = taskService.getActivityListByProcessInstanceId(reqVO.getProcessInstanceId());
  202 + List<HistoricTaskInstance> tasks = taskService.getTaskListByProcessInstanceId(reqVO.getProcessInstanceId(),
  203 + true);
  204 + endActivityNodes = getEndActivityNodeList(startUserId, bpmnModel, processDefinitionInfo,
  205 + historicProcessInstance, processInstanceStatus, activities, tasks);
  206 + runActivityNodes = getRunApproveNodeList(startUserId, bpmnModel, processDefinition, processVariables,
  207 + activities, tasks);
  208 + }
  209 +
  210 + // 2.2 流程已经结束,直接 return,无需预测
  211 + if (BpmProcessInstanceStatusEnum.isProcessEndStatus(processInstanceStatus)) {
  212 + return buildApprovalDetail(reqVO, bpmnModel, processDefinition, processDefinitionInfo,
  213 + historicProcessInstance,
  214 + processInstanceStatus, endActivityNodes, runActivityNodes, null, null);
  215 + }
  216 +
  217 + // 3.1 计算当前登录用户的待办任务
  218 + BpmTaskRespVO todoTask = taskService.getTodoTask(loginUserId, reqVO.getTaskId(), reqVO.getProcessInstanceId());
  219 + // 3.2 预测未运行节点的审批信息
  220 + List<ActivityNode> simulateActivityNodes = getSimulateApproveNodeList(startUserId, bpmnModel,
  221 + processDefinitionInfo,
  222 + processVariables, activities);
  223 + // 3.3 如果是发起动作,activityId 为开始节点,不校验审批人自选节点
  224 + if (ObjUtil.equals(reqVO.getActivityId(), BpmnModelConstants.START_USER_NODE_ID)) {
  225 + simulateActivityNodes.removeIf(node ->
  226 + BpmTaskCandidateStrategyEnum.APPROVE_USER_SELECT.getStrategy().equals(node.getCandidateStrategy()));
  227 + }
  228 +
  229 + // 4. 拼接最终数据
  230 + return buildApprovalDetail(reqVO, bpmnModel, processDefinition, processDefinitionInfo, historicProcessInstance,
  231 + processInstanceStatus, endActivityNodes, runActivityNodes, simulateActivityNodes, todoTask);
  232 + }
  233 +
  234 + @Override
  235 + public List<ActivityNode> getNextApprovalNodes(Long loginUserId, BpmApprovalDetailReqVO reqVO) {
  236 + // 1.1 校验任务存在,且是当前用户的
  237 + Task task = taskService.validateTask(loginUserId, reqVO.getTaskId());
  238 + // 1.2 校验流程实例存在
  239 + ProcessInstance instance = getProcessInstance(task.getProcessInstanceId());
  240 + if (instance == null) {
  241 + throw exception(PROCESS_INSTANCE_NOT_EXISTS);
  242 + }
  243 + HistoricProcessInstance historicProcessInstance = getHistoricProcessInstance(task.getProcessInstanceId());
  244 + if (historicProcessInstance == null) {
  245 + throw exception(ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS);
  246 + }
  247 + // 1.3 校验BpmnModel
  248 + BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(task.getProcessDefinitionId());
  249 + if (bpmnModel == null) {
  250 + return null;
  251 + }
  252 +
  253 + // 2. 设置流程变量
  254 + Map<String, Object> processVariables = new HashMap<>();
  255 + // 2.1 获取历史中流程变量
  256 + if (CollUtil.isNotEmpty(historicProcessInstance.getProcessVariables())) {
  257 + processVariables.putAll(historicProcessInstance.getProcessVariables());
  258 + }
  259 + // 2.2 合并前端传递的流程变量,以前端为准
  260 + if (CollUtil.isNotEmpty(reqVO.getProcessVariables())) {
  261 + processVariables.putAll(reqVO.getProcessVariables());
  262 + }
  263 +
  264 + // 3. 获取下一个将要执行的节点集合
  265 + FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey());
  266 + List<FlowNode> nextFlowNodes = BpmnModelUtils.getNextFlowNodes(flowElement, bpmnModel, processVariables);
  267 + List<ActivityNode> nextActivityNodes = convertList(nextFlowNodes, node -> new ActivityNode().setId(node.getId())
  268 + .setName(node.getName()).setNodeType(BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType())
  269 + .setStatus(BpmTaskStatusEnum.RUNNING.getStatus())
  270 + .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(node))
  271 + .setCandidateUserIds(getTaskCandidateUserList(bpmnModel, node.getId(),
  272 + loginUserId, historicProcessInstance.getProcessDefinitionId(), processVariables)));
  273 + if (CollUtil.isNotEmpty(nextActivityNodes)) {
  274 + return nextActivityNodes;
  275 + }
  276 +
  277 + // 4. 拼接基础信息
  278 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
  279 + convertSetByFlatMap(nextActivityNodes, ActivityNode::getCandidateUserIds, Collection::stream));
  280 + Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
  281 + nextActivityNodes.forEach(node -> node.setCandidateUsers(convertList(node.getCandidateUserIds(), userId -> {
  282 + AdminUserRespDTO user = userMap.get(userId);
  283 + if (user != null) {
  284 + return BpmProcessInstanceConvert.INSTANCE.buildUser(userId, userMap, deptMap);
  285 + }
  286 + return null;
  287 + })));
  288 + return nextActivityNodes;
  289 + }
  290 +
  291 + @Override
  292 + @SuppressWarnings("unchecked")
  293 + public PageResult<HistoricProcessInstance> getProcessInstancePage(Long userId,
  294 + BpmProcessInstancePageReqVO pageReqVO) {
  295 + // 1. 构建查询条件
  296 + HistoricProcessInstanceQuery processInstanceQuery = historyService.createHistoricProcessInstanceQuery()
  297 + .includeProcessVariables()
  298 + .processInstanceTenantId(FlowableUtils.getTenantId())
  299 + .orderByProcessInstanceStartTime().desc();
  300 + if (userId != null) { // 【我的流程】菜单时,需要传递该字段
  301 + processInstanceQuery.startedBy(String.valueOf(userId));
  302 + } else if (pageReqVO.getStartUserId() != null) { // 【管理流程】菜单时,才会传递该字段
  303 + processInstanceQuery.startedBy(String.valueOf(pageReqVO.getStartUserId()));
  304 + }
  305 + if (StrUtil.isNotEmpty(pageReqVO.getName())) {
  306 + processInstanceQuery.processInstanceNameLike("%" + pageReqVO.getName() + "%");
  307 + }
  308 + if (StrUtil.isNotEmpty(pageReqVO.getProcessDefinitionKey())) {
  309 + processInstanceQuery.processDefinitionKey(pageReqVO.getProcessDefinitionKey());
  310 + }
  311 + if (StrUtil.isNotEmpty(pageReqVO.getCategory())) {
  312 + processInstanceQuery.processDefinitionCategory(pageReqVO.getCategory());
  313 + }
  314 + if (pageReqVO.getStatus() != null) {
  315 + processInstanceQuery.variableValueEquals(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS,
  316 + pageReqVO.getStatus());
  317 + }
  318 + if (ArrayUtil.isNotEmpty(pageReqVO.getCreateTime())) {
  319 + processInstanceQuery.startedAfter(DateUtils.of(pageReqVO.getCreateTime()[0]));
  320 + processInstanceQuery.startedBefore(DateUtils.of(pageReqVO.getCreateTime()[1]));
  321 + }
  322 + if (ArrayUtil.isNotEmpty(pageReqVO.getEndTime())) {
  323 + processInstanceQuery.finishedAfter(DateUtils.of(pageReqVO.getEndTime()[0]));
  324 + processInstanceQuery.finishedBefore(DateUtils.of(pageReqVO.getEndTime()[1]));
  325 + }
  326 + // 表单字段查询
  327 + Map<String, Object> formFieldsParams = JsonUtils.parseObject(pageReqVO.getFormFieldsParams(), Map.class);
  328 + if (CollUtil.isNotEmpty(formFieldsParams)) {
  329 + formFieldsParams.forEach((key, value) -> {
  330 + if (StrUtil.isEmpty(String.valueOf(value))) {
  331 + return;
  332 + }
  333 + // TODO @lesan:应支持多种类型的查询方式,目前只有字符串全等
  334 + processInstanceQuery.variableValueEquals(key, value);
  335 + });
  336 + }
  337 +
  338 + // 2.1 查询数量
  339 + long processInstanceCount = processInstanceQuery.count();
  340 + if (processInstanceCount == 0) {
  341 + return PageResult.empty(processInstanceCount);
  342 + }
  343 + // 2.2 查询列表
  344 + List<HistoricProcessInstance> processInstanceList = processInstanceQuery.listPage(PageUtils.getStart(pageReqVO),
  345 + pageReqVO.getPageSize());
  346 + return new PageResult<>(processInstanceList, processInstanceCount);
  347 + }
  348 +
  349 + /**
  350 + * 拼接审批详情的最终数据
  351 + * <p>
  352 + * 主要是,拼接审批人的用户信息、部门信息
  353 + */
  354 + private BpmApprovalDetailRespVO buildApprovalDetail(BpmApprovalDetailReqVO reqVO,
  355 + BpmnModel bpmnModel,
  356 + ProcessDefinition processDefinition,
  357 + BpmProcessDefinitionInfoDO processDefinitionInfo,
  358 + HistoricProcessInstance processInstance,
  359 + Integer processInstanceStatus,
  360 + List<ActivityNode> endApprovalNodeInfos,
  361 + List<ActivityNode> runningApprovalNodeInfos,
  362 + List<ActivityNode> simulateApprovalNodeInfos,
  363 + BpmTaskRespVO todoTask) {
  364 + // 1. 获取所有需要读取用户信息的 userIds
  365 + List<ActivityNode> approveNodes = newArrayList(
  366 + asList(endApprovalNodeInfos, runningApprovalNodeInfos, simulateApprovalNodeInfos));
  367 + Set<Long> userIds = BpmProcessInstanceConvert.INSTANCE.parseUserIds(processInstance, approveNodes, todoTask);
  368 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
  369 + Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
  370 +
  371 + // 2. 表单权限
  372 + String taskId = reqVO.getTaskId() == null && todoTask != null ? todoTask.getId() : reqVO.getTaskId();
  373 + Map<String, String> formFieldsPermission = getFormFieldsPermission(bpmnModel, reqVO.getActivityId(), taskId);
  374 +
  375 + // 3. 拼接数据
  376 + return BpmProcessInstanceConvert.INSTANCE.buildApprovalDetail(bpmnModel, processDefinition,
  377 + processDefinitionInfo, processInstance,
  378 + processInstanceStatus, approveNodes, todoTask, formFieldsPermission, userMap, deptMap);
  379 + }
  380 +
  381 + /**
  382 + * 获得【已结束】的活动节点们
  383 + */
  384 + private List<ActivityNode> getEndActivityNodeList(Long startUserId, BpmnModel bpmnModel,
  385 + BpmProcessDefinitionInfoDO processDefinitionInfo,
  386 + HistoricProcessInstance historicProcessInstance, Integer processInstanceStatus,
  387 + List<HistoricActivityInstance> activities, List<HistoricTaskInstance> tasks) {
  388 + // 遍历 tasks 列表,只处理已结束的 UserTask
  389 + // 为什么不通过 activities 呢?因为,加签场景下,它只存在于 tasks,没有 activities,导致如果遍历 activities 的话,它无法成为一个节点
  390 + List<HistoricTaskInstance> endTasks = filterList(tasks, task -> task.getEndTime() != null);
  391 + List<ActivityNode> approvalNodes = convertList(endTasks, task -> {
  392 + FlowElement flowNode = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
  393 + ActivityNode activityNode = new ActivityNode().setId(task.getTaskDefinitionKey()).setName(task.getName())
  394 + .setNodeType(START_USER_NODE_ID.equals(task.getTaskDefinitionKey())
  395 + ? BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType()
  396 + : ObjUtil.defaultIfNull(parseNodeType(flowNode), // 目的:解决“办理节点”的识别
  397 + BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()))
  398 + .setStatus(FlowableUtils.getTaskStatus(task))
  399 + .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode))
  400 + .setStartTime(DateUtils.of(task.getCreateTime())).setEndTime(DateUtils.of(task.getEndTime()))
  401 + .setTasks(singletonList(BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(task)));
  402 + // 如果是取消状态,则跳过
  403 + if (BpmTaskStatusEnum.isCancelStatus(activityNode.getStatus())) {
  404 + return null;
  405 + }
  406 + return activityNode;
  407 + });
  408 +
  409 + // 遍历 activities,只处理已结束的 StartEvent、EndEvent
  410 + List<HistoricActivityInstance> endActivities = filterList(activities, activity -> activity.getEndTime() != null
  411 + && (StrUtil.equalsAny(activity.getActivityType(), ELEMENT_EVENT_START, ELEMENT_CALL_ACTIVITY, ELEMENT_EVENT_END)));
  412 + endActivities.forEach(activity -> {
  413 + // StartEvent:只处理 BPMN 的场景。因为,SIMPLE 情况下,已经有 START_USER_NODE 节点
  414 + if (ELEMENT_EVENT_START.equals(activity.getActivityType())
  415 + && BpmModelTypeEnum.BPMN.getType().equals(processDefinitionInfo.getModelType())) {
  416 + ActivityNodeTask startTask = new ActivityNodeTask().setId(BpmnModelConstants.START_USER_NODE_ID)
  417 + .setAssignee(startUserId).setStatus(BpmTaskStatusEnum.APPROVE.getStatus());
  418 + ActivityNode startNode = new ActivityNode().setId(startTask.getId())
  419 + .setName(BpmSimpleModelNodeTypeEnum.START_USER_NODE.getName())
  420 + .setNodeType(BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType())
  421 + .setStatus(startTask.getStatus()).setTasks(ListUtil.of(startTask))
  422 + .setStartTime(DateUtils.of(activity.getStartTime()))
  423 + .setEndTime(DateUtils.of(activity.getEndTime()));
  424 + approvalNodes.add(0, startNode);
  425 + return;
  426 + }
  427 + // EndEvent
  428 + if (ELEMENT_EVENT_END.equals(activity.getActivityType())) {
  429 + if (BpmProcessInstanceStatusEnum.isRejectStatus(processInstanceStatus)) {
  430 + // 拒绝情况下,不需要展示 EndEvent 结束节点。原因是:前端已经展示 x 效果,无需重复展示
  431 + return;
  432 + }
  433 + ActivityNode endNode = new ActivityNode().setId(activity.getId())
  434 + .setName(BpmSimpleModelNodeTypeEnum.END_NODE.getName())
  435 + .setNodeType(BpmSimpleModelNodeTypeEnum.END_NODE.getType()).setStatus(processInstanceStatus)
  436 + .setStartTime(DateUtils.of(activity.getStartTime()))
  437 + .setEndTime(DateUtils.of(activity.getEndTime()));
  438 + String reason = FlowableUtils.getProcessInstanceReason(historicProcessInstance);
  439 + if (StrUtil.isNotEmpty(reason)) {
  440 + endNode.setTasks(singletonList(new ActivityNodeTask().setId(endNode.getId())
  441 + .setStatus(endNode.getStatus()).setReason(reason)));
  442 + }
  443 + approvalNodes.add(endNode);
  444 + }
  445 + // CallActivity
  446 + if (ELEMENT_CALL_ACTIVITY.equals(activity.getActivityType())) {
  447 + ActivityNode callActivity = new ActivityNode().setId(activity.getId())
  448 + .setName(BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getName())
  449 + .setNodeType(BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType()).setStatus(processInstanceStatus)
  450 + .setStartTime(DateUtils.of(activity.getStartTime()))
  451 + .setEndTime(DateUtils.of(activity.getEndTime()))
  452 + .setProcessInstanceId(activity.getProcessInstanceId());
  453 + approvalNodes.add(callActivity);
  454 + }
  455 + });
  456 +
  457 + // 按照时间排序
  458 + approvalNodes.sort(Comparator.comparing(ActivityNode::getStartTime));
  459 + return approvalNodes;
  460 + }
  461 +
  462 + /**
  463 + * 获得【进行中】的活动节点们
  464 + */
  465 + private List<ActivityNode> getRunApproveNodeList(Long startUserId,
  466 + BpmnModel bpmnModel,
  467 + ProcessDefinition processDefinition,
  468 + Map<String, Object> processVariables,
  469 + List<HistoricActivityInstance> activities,
  470 + List<HistoricTaskInstance> tasks) {
  471 + // 构建运行中的任务、子流程,基于 activityId 分组
  472 + List<HistoricActivityInstance> runActivities = filterList(activities, activity -> activity.getEndTime() == null
  473 + && (StrUtil.equalsAny(activity.getActivityType(), ELEMENT_TASK_USER, ELEMENT_CALL_ACTIVITY)));
  474 + Map<String, List<HistoricActivityInstance>> runningTaskMap = convertMultiMap(runActivities,
  475 + HistoricActivityInstance::getActivityId);
  476 +
  477 + // 按照 activityId 分组,构建 ApprovalNodeInfo 节点
  478 + Map<String, HistoricTaskInstance> taskMap = convertMap(tasks, HistoricTaskInstance::getId);
  479 + return convertList(runningTaskMap.entrySet(), entry -> {
  480 + String activityId = entry.getKey();
  481 + List<HistoricActivityInstance> taskActivities = entry.getValue();
  482 + // 构建活动节点
  483 + FlowElement flowNode = BpmnModelUtils.getFlowElementById(bpmnModel, activityId);
  484 + HistoricActivityInstance firstActivity = CollUtil.getFirst(taskActivities); // 取第一个任务,会签/或签的任务,开始时间相同
  485 + ActivityNode activityNode = new ActivityNode().setId(firstActivity.getActivityId())
  486 + .setName(firstActivity.getActivityName())
  487 + .setNodeType(ObjUtil.defaultIfNull(parseNodeType(flowNode), // 目的:解决“办理节点”和"子流程"的识别
  488 + BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()))
  489 + .setStatus(BpmTaskStatusEnum.RUNNING.getStatus())
  490 + .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode))
  491 + .setStartTime(DateUtils.of(CollUtil.getFirst(taskActivities).getStartTime()))
  492 + .setTasks(new ArrayList<>());
  493 + // 处理每个任务的 tasks 属性
  494 + for (HistoricActivityInstance activity : taskActivities) {
  495 + HistoricTaskInstance task = taskMap.get(activity.getTaskId());
  496 + // 特殊情况:子流程节点 ChildProcess 仅存在于 activity 中,并且没有自身的 task,需要跳过执行
  497 + // TODO @芋艿:后续看看怎么优化!
  498 + if (task == null) {
  499 + continue;
  500 + }
  501 + activityNode.getTasks().add(BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(task));
  502 + // 加签子任务,需要过滤掉已经完成的加签子任务
  503 + List<HistoricTaskInstance> childrenTasks = filterList(
  504 + taskService.getAllChildrenTaskListByParentTaskId(activity.getTaskId(), tasks),
  505 + childTask -> childTask.getEndTime() == null);
  506 + if (CollUtil.isNotEmpty(childrenTasks)) {
  507 + activityNode.getTasks().addAll(
  508 + convertList(childrenTasks, BpmProcessInstanceConvert.INSTANCE::buildApprovalTaskInfo));
  509 + }
  510 + }
  511 + // 处理每个任务的 candidateUsers 属性:如果是依次审批,需要预测它的后续审批人。因为 Task 是审批完一个,创建一个新的 Task
  512 + if (BpmnModelUtils.isSequentialUserTask(flowNode)) {
  513 + List<Long> candidateUserIds = getTaskCandidateUserList(bpmnModel, flowNode.getId(),
  514 + startUserId, processDefinition.getId(), processVariables);
  515 + // 截取当前审批人位置后面的候选人,不包含当前审批人
  516 + ActivityNodeTask approvalTaskInfo = CollUtil.getFirst(activityNode.getTasks());
  517 + Assert.notNull(approvalTaskInfo, "任务不能为空");
  518 + int index = CollUtil.indexOf(candidateUserIds,
  519 + userId -> ObjectUtils.equalsAny(userId, approvalTaskInfo.getOwner(),
  520 + approvalTaskInfo.getAssignee())); // 委派或者向前加签情况,需要先比较 owner
  521 + activityNode.setCandidateUserIds(CollUtil.sub(candidateUserIds, index + 1, candidateUserIds.size()));
  522 + }
  523 + if (BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType().equals(activityNode.getNodeType())) {
  524 + activityNode.setProcessInstanceId(firstActivity.getProcessInstanceId());
  525 + }
  526 + return activityNode;
  527 + });
  528 + }
  529 +
  530 + /**
  531 + * 获得【预测(未来)】的活动节点们
  532 + */
  533 + private List<ActivityNode> getSimulateApproveNodeList(Long startUserId, BpmnModel bpmnModel,
  534 + BpmProcessDefinitionInfoDO processDefinitionInfo,
  535 + Map<String, Object> processVariables,
  536 + List<HistoricActivityInstance> activities) {
  537 + // TODO @芋艿:【可优化】在驳回场景下,未来的预测准确性不高。原因是,驳回后,HistoricActivityInstance
  538 + // 包括了历史的操作,不是只有 startEvent 到当前节点的记录
  539 + Set<String> runActivityIds = convertSet(activities, HistoricActivityInstance::getActivityId);
  540 + // 情况一:BPMN 设计器
  541 + if (Objects.equals(BpmModelTypeEnum.BPMN.getType(), processDefinitionInfo.getModelType())) {
  542 + List<FlowElement> flowElements = BpmnModelUtils.simulateProcess(bpmnModel, processVariables);
  543 + return convertList(flowElements, flowElement -> buildNotRunApproveNodeForBpmn(startUserId, bpmnModel,
  544 + processDefinitionInfo, processVariables, flowElement, runActivityIds));
  545 + }
  546 + // 情况二:SIMPLE 设计器
  547 + if (Objects.equals(BpmModelTypeEnum.SIMPLE.getType(), processDefinitionInfo.getModelType())) {
  548 + BpmSimpleModelNodeVO simpleModel = JsonUtils.parseObject(processDefinitionInfo.getSimpleModel(),
  549 + BpmSimpleModelNodeVO.class);
  550 + List<BpmSimpleModelNodeVO> simpleNodes = SimpleModelUtils.simulateProcess(simpleModel, processVariables);
  551 + return convertList(simpleNodes, simpleNode -> buildNotRunApproveNodeForSimple(startUserId, bpmnModel,
  552 + processDefinitionInfo, processVariables, simpleNode, runActivityIds));
  553 + }
  554 + throw new IllegalArgumentException("未知设计器类型:" + processDefinitionInfo.getModelType());
  555 + }
  556 +
  557 + private ActivityNode buildNotRunApproveNodeForSimple(Long startUserId, BpmnModel bpmnModel,
  558 + BpmProcessDefinitionInfoDO processDefinitionInfo, Map<String, Object> processVariables,
  559 + BpmSimpleModelNodeVO node, Set<String> runActivityIds) {
  560 + // TODO @芋艿:【可优化】在驳回场景下,未来的预测准确性不高。原因是,驳回后,HistoricActivityInstance
  561 + // 包括了历史的操作,不是只有 startEvent 到当前节点的记录
  562 + if (runActivityIds.contains(node.getId())) {
  563 + return null;
  564 + }
  565 +
  566 + ActivityNode activityNode = new ActivityNode().setId(node.getId()).setName(node.getName())
  567 + .setNodeType(node.getType()).setCandidateStrategy(node.getCandidateStrategy())
  568 + .setStatus(BpmTaskStatusEnum.NOT_START.getStatus());
  569 +
  570 + // 1. 开始节点/审批节点
  571 + if (ObjectUtils.equalsAny(node.getType(),
  572 + BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType(),
  573 + BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType(),
  574 + BpmSimpleModelNodeTypeEnum.TRANSACTOR_NODE.getType())) {
  575 + List<Long> candidateUserIds = getTaskCandidateUserList(bpmnModel, node.getId(),
  576 + startUserId, processDefinitionInfo.getProcessDefinitionId(), processVariables);
  577 + activityNode.setCandidateUserIds(candidateUserIds);
  578 + return activityNode;
  579 + }
  580 +
  581 + // 2. 结束节点
  582 + if (BpmSimpleModelNodeTypeEnum.END_NODE.getType().equals(node.getType())) {
  583 + return activityNode;
  584 + }
  585 +
  586 + // 3. 抄送节点
  587 + if (CollUtil.isEmpty(runActivityIds) && // 流程发起时:需要展示抄送节点,用于选择抄送人
  588 + BpmSimpleModelNodeTypeEnum.COPY_NODE.getType().equals(node.getType())) {
  589 + List<Long> candidateUserIds = getTaskCandidateUserList(bpmnModel, node.getId(),
  590 + startUserId, processDefinitionInfo.getProcessDefinitionId(), processVariables);
  591 + activityNode.setCandidateUserIds(candidateUserIds);
  592 + return activityNode;
  593 + }
  594 +
  595 + // 4. 子流程节点
  596 + if (BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType().equals(node.getType())) {
  597 + return activityNode;
  598 + }
  599 + return null;
  600 + }
  601 +
  602 + private ActivityNode buildNotRunApproveNodeForBpmn(Long startUserId, BpmnModel bpmnModel,
  603 + BpmProcessDefinitionInfoDO processDefinitionInfo, Map<String, Object> processVariables,
  604 + FlowElement node, Set<String> runActivityIds) {
  605 + if (runActivityIds.contains(node.getId())) {
  606 + return null;
  607 + }
  608 + ActivityNode activityNode = new ActivityNode().setId(node.getId())
  609 + .setStatus(BpmTaskStatusEnum.NOT_START.getStatus());
  610 +
  611 + // 1. 开始节点
  612 + if (node instanceof StartEvent) {
  613 + return activityNode.setName(BpmSimpleModelNodeTypeEnum.START_USER_NODE.getName())
  614 + .setNodeType(BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType());
  615 + }
  616 +
  617 + // 2. 审批节点
  618 + if (node instanceof UserTask) {
  619 + List<Long> candidateUserIds = getTaskCandidateUserList(bpmnModel, node.getId(),
  620 + startUserId, processDefinitionInfo.getProcessDefinitionId(), processVariables);
  621 + return activityNode.setName(node.getName()).setNodeType(BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType())
  622 + .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(node))
  623 + .setCandidateUserIds(candidateUserIds);
  624 + }
  625 +
  626 + // 3. 结束节点
  627 + if (node instanceof EndEvent) {
  628 + return activityNode.setName(BpmSimpleModelNodeTypeEnum.END_NODE.getName())
  629 + .setNodeType(BpmSimpleModelNodeTypeEnum.END_NODE.getType());
  630 + }
  631 + return null;
  632 + }
  633 +
  634 + private List<Long> getTaskCandidateUserList(BpmnModel bpmnModel, String activityId,
  635 + Long startUserId, String processDefinitionId, Map<String, Object> processVariables) {
  636 + Set<Long> userIds = taskCandidateInvoker.calculateUsersByActivity(bpmnModel, activityId,
  637 + startUserId, processDefinitionId, processVariables);
  638 + return new ArrayList<>(userIds);
  639 + }
  640 +
  641 + @Override
  642 + public BpmProcessInstanceBpmnModelViewRespVO getProcessInstanceBpmnModelView(String id) {
  643 + // 1.1 获得流程实例
  644 + HistoricProcessInstance processInstance = getHistoricProcessInstance(id);
  645 + if (processInstance == null) {
  646 + return null;
  647 + }
  648 + // 1.2 获得流程定义
  649 + BpmnModel bpmnModel = processDefinitionService
  650 + .getProcessDefinitionBpmnModel(processInstance.getProcessDefinitionId());
  651 + if (bpmnModel == null) {
  652 + return null;
  653 + }
  654 + BpmSimpleModelNodeVO simpleModel = null;
  655 + BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.getProcessDefinitionInfo(
  656 + processInstance.getProcessDefinitionId());
  657 + if (processDefinitionInfo != null
  658 + && BpmModelTypeEnum.SIMPLE.getType().equals(processDefinitionInfo.getModelType())) {
  659 + simpleModel = JsonUtils.parseObject(processDefinitionInfo.getSimpleModel(), BpmSimpleModelNodeVO.class);
  660 + }
  661 + // 1.3 获得流程实例对应的活动实例列表 + 任务列表
  662 + List<HistoricActivityInstance> activities = taskService.getActivityListByProcessInstanceId(id);
  663 + List<HistoricTaskInstance> tasks = taskService.getTaskListByProcessInstanceId(id, true);
  664 +
  665 + // 2.1 拼接进度信息
  666 + Set<String> unfinishedTaskActivityIds = convertSet(activities, HistoricActivityInstance::getActivityId,
  667 + activityInstance -> activityInstance.getEndTime() == null);
  668 + Set<String> finishedTaskActivityIds = convertSet(activities, HistoricActivityInstance::getActivityId,
  669 + activityInstance -> activityInstance.getEndTime() != null
  670 + && ObjectUtil.notEqual(activityInstance.getActivityType(),
  671 + BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW));
  672 + Set<String> finishedSequenceFlowActivityIds = convertSet(activities, HistoricActivityInstance::getActivityId,
  673 + activityInstance -> activityInstance.getEndTime() != null
  674 + && ObjectUtil.equals(activityInstance.getActivityType(),
  675 + BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW));
  676 + // 特殊:会签情况下,会有部分已完成(审批)、部分未完成(待审批),此时需要 finishedTaskActivityIds 移除掉
  677 + finishedTaskActivityIds.removeAll(unfinishedTaskActivityIds);
  678 + // 特殊:如果流程实例被拒绝,则需要计算是哪个活动节点。
  679 + // 注意,只取最后一个。因为会存在多次拒绝的情况,拒绝驳回到指定节点
  680 + Set<String> rejectTaskActivityIds = CollUtil.newHashSet();
  681 + if (BpmProcessInstanceStatusEnum.isRejectStatus(FlowableUtils.getProcessInstanceStatus(processInstance))) {
  682 + tasks.stream()
  683 + .filter(task -> BpmTaskStatusEnum.isRejectStatus(FlowableUtils.getTaskStatus(task)))
  684 + .max(Comparator.comparing(HistoricTaskInstance::getEndTime))
  685 + .ifPresent(reject -> rejectTaskActivityIds.add(reject.getTaskDefinitionKey()));
  686 + finishedTaskActivityIds.removeAll(rejectTaskActivityIds);
  687 + }
  688 +
  689 + // 2.2 拼接基础信息
  690 + Set<Long> userIds = BpmProcessInstanceConvert.INSTANCE.parseUserIds02(processInstance, tasks);
  691 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
  692 + Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
  693 + return BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceBpmnModelView(processInstance, tasks, bpmnModel,
  694 + simpleModel,
  695 + unfinishedTaskActivityIds, finishedTaskActivityIds, finishedSequenceFlowActivityIds,
  696 + rejectTaskActivityIds,
  697 + userMap, deptMap);
  698 + }
  699 +
  700 + // ========== Update 写入相关方法 ==========
  701 +
  702 + @Override
  703 + @Transactional(rollbackFor = Exception.class)
  704 + public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) {
  705 + // 获得流程定义
  706 + ProcessDefinition definition = processDefinitionService
  707 + .getProcessDefinition(createReqVO.getProcessDefinitionId());
  708 + // 发起流程
  709 + return createProcessInstance0(userId, definition, createReqVO.getVariables(), null,
  710 + createReqVO.getStartUserSelectAssignees());
  711 + }
  712 +
  713 + @Override
  714 + public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) {
  715 + return FlowableUtils.executeAuthenticatedUserId(userId, () -> {
  716 + // 获得流程定义
  717 + ProcessDefinition definition = processDefinitionService
  718 + .getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey());
  719 + // 发起流程
  720 + return createProcessInstance0(userId, definition, createReqDTO.getVariables(),
  721 + createReqDTO.getBusinessKey(),
  722 + createReqDTO.getStartUserSelectAssignees());
  723 + });
  724 + }
  725 +
  726 + private String createProcessInstance0(Long userId, ProcessDefinition definition,
  727 + Map<String, Object> variables, String businessKey,
  728 + Map<String, List<Long>> startUserSelectAssignees) {
  729 + // 1.1 校验流程定义
  730 + if (definition == null) {
  731 + throw exception(PROCESS_DEFINITION_NOT_EXISTS);
  732 + }
  733 + if (definition.isSuspended()) {
  734 + throw exception(PROCESS_DEFINITION_IS_SUSPENDED);
  735 + }
  736 + BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService
  737 + .getProcessDefinitionInfo(definition.getId());
  738 + if (processDefinitionInfo == null) {
  739 + throw exception(PROCESS_DEFINITION_NOT_EXISTS);
  740 + }
  741 + // 1.2 校验是否能够发起
  742 + if (!processDefinitionService.canUserStartProcessDefinition(processDefinitionInfo, userId)) {
  743 + throw exception(PROCESS_INSTANCE_START_USER_CAN_START);
  744 + }
  745 + // 1.3 校验发起人自选审批人
  746 + validateStartUserSelectAssignees(userId, definition, startUserSelectAssignees, variables);
  747 +
  748 + // 2. 创建流程实例
  749 + if (variables == null) {
  750 + variables = new HashMap<>();
  751 + }
  752 + FlowableUtils.filterProcessInstanceFormVariable(variables); // 过滤一下,避免 ProcessInstance 系统级的变量被占用
  753 + variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, userId); // 设置流程变量,发起人 ID
  754 + variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, // 流程实例状态:审批中
  755 + BpmProcessInstanceStatusEnum.RUNNING.getStatus());
  756 + variables.put(BpmnVariableConstants.PROCESS_INSTANCE_SKIP_EXPRESSION_ENABLED, true); // 跳过表达式需要添加此变量为 true,不影响没配置 skipExpression 的节点
  757 + if (CollUtil.isNotEmpty(startUserSelectAssignees)) {
  758 + // 设置流程变量,发起人自选审批人
  759 + variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES,
  760 + startUserSelectAssignees);
  761 + }
  762 +
  763 + // 3. 创建流程
  764 + ProcessInstanceBuilder processInstanceBuilder = runtimeService.createProcessInstanceBuilder()
  765 + .processDefinitionId(definition.getId())
  766 + .businessKey(businessKey)
  767 + .variables(variables);
  768 + // 3.1 创建流程 ID
  769 + BpmModelMetaInfoVO.ProcessIdRule processIdRule = processDefinitionInfo.getProcessIdRule();
  770 + if (processIdRule != null && Boolean.TRUE.equals(processIdRule.getEnable())) {
  771 + processInstanceBuilder.predefineProcessInstanceId(processIdRedisDAO.generate(processIdRule));
  772 + }
  773 + // 3.2 流程名称
  774 + BpmModelMetaInfoVO.TitleSetting titleSetting = processDefinitionInfo.getTitleSetting();
  775 + if (titleSetting != null && Boolean.TRUE.equals(titleSetting.getEnable())) {
  776 + AdminUserRespDTO user = adminUserApi.getUser(userId);
  777 + Map<String, Object> cloneVariables = new HashMap<>(variables);
  778 + cloneVariables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, user.getNickname());
  779 + cloneVariables.put(BpmnVariableConstants.PROCESS_START_TIME, DateUtil.now());
  780 + cloneVariables.put(BpmnVariableConstants.PROCESS_DEFINITION_NAME, definition.getName().trim());
  781 + processInstanceBuilder.name(StrUtil.format(titleSetting.getTitle(), cloneVariables));
  782 + } else {
  783 + processInstanceBuilder.name(definition.getName().trim());
  784 + }
  785 + // 3.3 发起流程实例
  786 + ProcessInstance instance = processInstanceBuilder.start();
  787 + return instance.getId();
  788 + }
  789 +
  790 + private void validateStartUserSelectAssignees(Long userId, ProcessDefinition definition,
  791 + Map<String, List<Long>> startUserSelectAssignees,
  792 + Map<String, Object> variables) {
  793 + // 1. 获取预测的节点信息
  794 + BpmApprovalDetailRespVO detailRespVO = getApprovalDetail(userId, new BpmApprovalDetailReqVO()
  795 + .setProcessDefinitionId(definition.getId())
  796 + .setProcessVariables(variables));
  797 + List<ActivityNode> activityNodes = detailRespVO.getActivityNodes();
  798 + if (CollUtil.isEmpty(activityNodes)) {
  799 + return;
  800 + }
  801 +
  802 + // 2.1 移除掉不是发起人自选审批人节点
  803 + activityNodes.removeIf(task ->
  804 + ObjectUtil.notEqual(BpmTaskCandidateStrategyEnum.START_USER_SELECT.getStrategy(), task.getCandidateStrategy()));
  805 + // 2.2 流程发起时要先获取当前流程的预测走向节点,发起时只校验预测的节点发起人自选审批人的审批人和抄送人是否都配置了
  806 + activityNodes.forEach(task -> {
  807 + List<Long> assignees = startUserSelectAssignees != null ? startUserSelectAssignees.get(task.getId()) : null;
  808 + if (CollUtil.isEmpty(assignees)) {
  809 + throw exception(PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_CONFIG, task.getName());
  810 + }
  811 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(assignees);
  812 + assignees.forEach(assignee -> {
  813 + if (userMap.get(assignee) == null) {
  814 + throw exception(PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_EXISTS, task.getName(), assignee);
  815 + }
  816 + });
  817 + });
  818 + }
  819 +
  820 + @Override
  821 + public void cancelProcessInstanceByStartUser(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) {
  822 + // 1.1 校验流程实例存在
  823 + ProcessInstance instance = getProcessInstance(cancelReqVO.getId());
  824 + if (instance == null) {
  825 + throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS);
  826 + }
  827 + // 1.2 只能取消自己的
  828 + if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) {
  829 + throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF);
  830 + }
  831 + // 1.3 校验允许撤销审批中的申请
  832 + BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService
  833 + .getProcessDefinitionInfo(instance.getProcessDefinitionId());
  834 + Assert.notNull(processDefinitionInfo, "流程定义({})不存在", processDefinitionInfo);
  835 + if (processDefinitionInfo.getAllowCancelRunningProcess() != null // 防止未配置 AllowCancelRunningProcess , 默认为可取消
  836 + && Boolean.FALSE.equals(processDefinitionInfo.getAllowCancelRunningProcess())) {
  837 + throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW);
  838 + }
  839 + // 1.4 子流程不允许取消
  840 + if (StrUtil.isNotBlank(instance.getSuperExecutionId())) {
  841 + throw exception(PROCESS_INSTANCE_CANCEL_CHILD_FAIL_NOT_ALLOW);
  842 + }
  843 +
  844 + // 2. 取消流程
  845 + updateProcessInstanceCancel(cancelReqVO.getId(),
  846 + BpmReasonEnum.CANCEL_PROCESS_INSTANCE_BY_START_USER.format(cancelReqVO.getReason()));
  847 + }
  848 +
  849 + @Override
  850 + public void cancelProcessInstanceByAdmin(Long userId, BpmProcessInstanceCancelReqVO cancelReqVO) {
  851 + // 1.1 校验流程实例存在
  852 + ProcessInstance instance = getProcessInstance(cancelReqVO.getId());
  853 + if (instance == null) {
  854 + throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS);
  855 + }
  856 +
  857 + // 2. 取消流程
  858 + AdminUserRespDTO user = adminUserApi.getUser(userId);
  859 + updateProcessInstanceCancel(cancelReqVO.getId(),
  860 + BpmReasonEnum.CANCEL_PROCESS_INSTANCE_BY_ADMIN.format(user.getNickname(), cancelReqVO.getReason()));
  861 + }
  862 +
  863 + private void updateProcessInstanceCancel(String id, String reason) {
  864 + // 1. 更新流程实例 status
  865 + runtimeService.setVariable(id, BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS,
  866 + BpmProcessInstanceStatusEnum.CANCEL.getStatus());
  867 + runtimeService.setVariable(id, BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON, reason);
  868 +
  869 + // 2. 取消所有子流程
  870 + List<ProcessInstance> childProcessInstances = runtimeService.createProcessInstanceQuery()
  871 + .superProcessInstanceId(id).list();
  872 + childProcessInstances.forEach(processInstance -> updateProcessInstanceCancel(
  873 + processInstance.getProcessInstanceId(), BpmReasonEnum.CANCEL_CHILD_PROCESS_INSTANCE_BY_MAIN_PROCESS.getReason()));
  874 +
  875 + // 3. 结束流程
  876 + taskService.moveTaskToEnd(id, reason);
  877 + }
  878 +
  879 + @Override
  880 + public void updateProcessInstanceReject(ProcessInstance processInstance, String reason) {
  881 + runtimeService.setVariable(processInstance.getProcessInstanceId(),
  882 + BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS,
  883 + BpmProcessInstanceStatusEnum.REJECT.getStatus());
  884 + runtimeService.setVariable(processInstance.getProcessInstanceId(),
  885 + BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON,
  886 + BpmReasonEnum.REJECT_TASK.format(reason));
  887 + }
  888 +
  889 + @Override
  890 + public void updateProcessInstanceVariables(String id, Map<String, Object> variables) {
  891 + runtimeService.setVariables(id, variables);
  892 + }
  893 +
  894 + @Override
  895 + public void removeProcessInstanceVariables(String id, Collection<String> variableNames) {
  896 + runtimeService.removeVariables(id, variableNames);
  897 + }
  898 +
  899 + // ========== Event 事件相关方法 ==========
  900 +
  901 + @Override
  902 + public void processProcessInstanceCompleted(ProcessInstance instance) {
  903 + // 注意:需要基于 instance 设置租户编号,避免 Flowable 内部异步时,丢失租户编号
  904 + FlowableUtils.execute(instance.getTenantId(), () -> {
  905 + // 1.1 获取当前状态
  906 + Integer status = (Integer) instance.getProcessVariables()
  907 + .get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS);
  908 + String reason = (String) instance.getProcessVariables()
  909 + .get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON);
  910 + // 1.2 当流程状态还是审批状态中,说明审批通过了,则变更下它的状态
  911 + // 为什么这么处理?因为流程完成,并且完成了,说明审批通过了
  912 + if (Objects.equals(status, BpmProcessInstanceStatusEnum.RUNNING.getStatus())) {
  913 + status = BpmProcessInstanceStatusEnum.APPROVE.getStatus();
  914 + runtimeService.setVariable(instance.getId(), BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS,
  915 + status);
  916 + }
  917 +
  918 + // 2. 发送对应的消息通知
  919 + if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) {
  920 + messageService.sendMessageWhenProcessInstanceApprove(
  921 + BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceApproveMessage(instance));
  922 + } else if (Objects.equals(status, BpmProcessInstanceStatusEnum.REJECT.getStatus())) {
  923 + messageService.sendMessageWhenProcessInstanceReject(
  924 + BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceRejectMessage(instance, reason));
  925 + }
  926 +
  927 + // 3. 发送流程实例的状态事件
  928 + processInstanceEventPublisher.sendProcessInstanceResultEvent(
  929 + BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceStatusEvent(this, instance, status));
  930 +
  931 + // 4. 流程后置通知
  932 + if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) {
  933 + BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.
  934 + getProcessDefinitionInfo(instance.getProcessDefinitionId());
  935 + if (ObjUtil.isNotNull(processDefinitionInfo) &&
  936 + ObjUtil.isNotNull(processDefinitionInfo.getProcessAfterTriggerSetting())) {
  937 + BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessAfterTriggerSetting();
  938 +
  939 + BpmHttpRequestUtils.executeBpmHttpRequest(instance,
  940 + setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse());
  941 + }
  942 + }
  943 + });
  944 + }
  945 +
  946 + @Override
  947 + public void processProcessInstanceCreated(ProcessInstance instance) {
  948 + // 注意:需要基于 instance 设置租户编号,避免 Flowable 内部异步时,丢失租户编号
  949 + FlowableUtils.execute(instance.getTenantId(), () -> {
  950 + // 流程前置通知
  951 + BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.
  952 + getProcessDefinitionInfo(instance.getProcessDefinitionId());
  953 + if (ObjUtil.isNull(processDefinitionInfo) ||
  954 + ObjUtil.isNull(processDefinitionInfo.getProcessBeforeTriggerSetting())) {
  955 + return;
  956 + }
  957 + BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessBeforeTriggerSetting();
  958 + BpmHttpRequestUtils.executeBpmHttpRequest(instance,
  959 + setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse());
  960 + });
  961 + }
  962 +
  963 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmUserTaskListener.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.task.listener;
  2 +
  3 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
  4 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmHttpRequestParamTypeEnum;
  5 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmHttpRequestUtils;
  6 +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  7 +import jakarta.annotation.Resource;
  8 +import lombok.Setter;
  9 +import lombok.extern.slf4j.Slf4j;
  10 +import org.flowable.engine.delegate.TaskListener;
  11 +import org.flowable.engine.impl.el.FixedValue;
  12 +import org.flowable.engine.runtime.ProcessInstance;
  13 +import org.flowable.task.service.delegate.DelegateTask;
  14 +import org.springframework.context.annotation.Scope;
  15 +import org.springframework.stereotype.Component;
  16 +
  17 +import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseListenerConfig;
  18 +
  19 +// TODO @芋艿:可能会想换个包地址
  20 +/**
  21 + * BPM 用户任务通用监听器
  22 + *
  23 + * @author Lesan
  24 + */
  25 +@Component
  26 +@Slf4j
  27 +@Scope("prototype")
  28 +public class BpmUserTaskListener implements TaskListener {
  29 +
  30 + public static final String DELEGATE_EXPRESSION = "${bpmUserTaskListener}";
  31 +
  32 + @Resource
  33 + private BpmProcessInstanceService processInstanceService;
  34 +
  35 + @Setter
  36 + private FixedValue listenerConfig;
  37 +
  38 + @Override
  39 + public void notify(DelegateTask delegateTask) {
  40 + // 1. 获取所需基础信息
  41 + ProcessInstance processInstance = processInstanceService.getProcessInstance(delegateTask.getProcessInstanceId());
  42 + BpmSimpleModelNodeVO.ListenerHandler listenerHandler = parseListenerConfig(listenerConfig);
  43 +
  44 + // 2. 发起请求
  45 + // TODO @芋艿:哪些默认参数,后续再调研下;感觉可以搞个 task 字段,把整个 delegateTask 放进去;
  46 + listenerHandler.getBody().add(new BpmSimpleModelNodeVO.HttpRequestParam().setKey("processInstanceId")
  47 + .setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType()).setValue(delegateTask.getProcessInstanceId()));
  48 + listenerHandler.getBody().add(new BpmSimpleModelNodeVO.HttpRequestParam().setKey("assignee")
  49 + .setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType()).setValue(delegateTask.getAssignee()));
  50 + listenerHandler.getBody().add(new BpmSimpleModelNodeVO.HttpRequestParam().setKey("taskDefinitionKey")
  51 + .setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType()).setValue(delegateTask.getTaskDefinitionKey()));
  52 + listenerHandler.getBody().add(new BpmSimpleModelNodeVO.HttpRequestParam().setKey("taskId")
  53 + .setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType()).setValue(delegateTask.getId()));
  54 + BpmHttpRequestUtils.executeBpmHttpRequest(processInstance,
  55 + listenerHandler.getPath(), listenerHandler.getHeader(), listenerHandler.getBody(), false, null);
  56 +
  57 + // 3. 是否需要后续操作?TODO 芋艿:待定!
  58 + }
  59 +}
0 60 \ No newline at end of file
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmTrigger.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmTrigger.java
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/form/BpmFormDeleteTrigger.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.task.trigger.form;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
  6 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum;
  7 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
  8 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils;
  9 +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  10 +import cn.iocoder.yudao.module.bpm.service.task.trigger.BpmTrigger;
  11 +import com.fasterxml.jackson.core.type.TypeReference;
  12 +import jakarta.annotation.Resource;
  13 +import lombok.extern.slf4j.Slf4j;
  14 +import org.springframework.stereotype.Component;
  15 +
  16 +import java.util.HashSet;
  17 +import java.util.List;
  18 +import java.util.Map;
  19 +import java.util.Set;
  20 +
  21 +/**
  22 + * BPM 删除流程表单数据触发器
  23 + *
  24 + * @author jason
  25 + */
  26 +@Component
  27 +@Slf4j
  28 +public class BpmFormDeleteTrigger implements BpmTrigger {
  29 +
  30 + @Resource
  31 + private BpmProcessInstanceService processInstanceService;
  32 +
  33 + @Override
  34 + public BpmTriggerTypeEnum getType() {
  35 + return BpmTriggerTypeEnum.FORM_DELETE;
  36 + }
  37 +
  38 + @Override
  39 + public void execute(String processInstanceId, String param) {
  40 + // 1. 解析删除流程表单数据配置
  41 + List<BpmSimpleModelNodeVO.TriggerSetting.FormTriggerSetting> settings = JsonUtils.parseObject(param, new TypeReference<>() {});
  42 + if (CollUtil.isEmpty(settings)) {
  43 + log.error("[execute][流程({}) 删除流程表单数据触发器配置为空]", processInstanceId);
  44 + return;
  45 + }
  46 +
  47 + // 2. 获取流程变量
  48 + Map<String, Object> processVariables = processInstanceService.getProcessInstance(processInstanceId).getProcessVariables();
  49 +
  50 + // 3.1 获取需要删除的表单字段
  51 + Set<String> deleteFields = new HashSet<>();
  52 + settings.forEach(setting -> {
  53 + if (CollUtil.isEmpty(setting.getDeleteFields())) {
  54 + return;
  55 + }
  56 + // 配置了条件,判断条件是否满足
  57 + boolean isFieldDeletedNeeded = true;
  58 + if (setting.getConditionType() != null) {
  59 + String conditionExpression = SimpleModelUtils.buildConditionExpression(
  60 + setting.getConditionType(), setting.getConditionExpression(), setting.getConditionGroups());
  61 + isFieldDeletedNeeded = BpmnModelUtils.evalConditionExpress(processVariables, conditionExpression);
  62 + }
  63 + if (isFieldDeletedNeeded) {
  64 + deleteFields.addAll(setting.getDeleteFields());
  65 + }
  66 + });
  67 +
  68 + // 3.2 删除流程变量
  69 + if (CollUtil.isNotEmpty(deleteFields)) {
  70 + processInstanceService.removeProcessInstanceVariables(processInstanceId, deleteFields);
  71 + }
  72 + }
  73 +}
... ...
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/form/BpmFormUpdateTrigger.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.task.trigger.form;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  5 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.TriggerSetting.FormTriggerSetting;
  6 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum;
  7 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
  8 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils;
  9 +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  10 +import cn.iocoder.yudao.module.bpm.service.task.trigger.BpmTrigger;
  11 +import com.fasterxml.jackson.core.type.TypeReference;
  12 +import jakarta.annotation.Resource;
  13 +import lombok.extern.slf4j.Slf4j;
  14 +import org.springframework.stereotype.Component;
  15 +
  16 +import java.util.List;
  17 +import java.util.Map;
  18 +
  19 +/**
  20 + * BPM 更新流程表单触发器
  21 + *
  22 + * @author jason
  23 + */
  24 +@Component
  25 +@Slf4j
  26 +public class BpmFormUpdateTrigger implements BpmTrigger {
  27 +
  28 + @Resource
  29 + private BpmProcessInstanceService processInstanceService;
  30 +
  31 + @Override
  32 + public BpmTriggerTypeEnum getType() {
  33 + return BpmTriggerTypeEnum.FORM_UPDATE;
  34 + }
  35 +
  36 + @Override
  37 + public void execute(String processInstanceId, String param) {
  38 + // 1. 解析更新流程表单配置
  39 + List<FormTriggerSetting> settings = JsonUtils.parseObject(param, new TypeReference<>() {});
  40 + if (CollUtil.isEmpty(settings)) {
  41 + log.error("[execute][流程({}) 更新流程表单触发器配置为空]", processInstanceId);
  42 + return;
  43 + }
  44 +
  45 + // 2. 获取流程变量
  46 + Map<String, Object> processVariables = processInstanceService.getProcessInstance(processInstanceId).getProcessVariables();
  47 +
  48 + // 3. 更新流程变量
  49 + for (FormTriggerSetting setting : settings) {
  50 + if (CollUtil.isEmpty(setting.getUpdateFormFields())) {
  51 + continue;
  52 + }
  53 + // 配置了条件,判断条件是否满足
  54 + boolean isFormUpdateNeeded = true;
  55 + if (setting.getConditionType() != null) {
  56 + String conditionExpression = SimpleModelUtils.buildConditionExpression(
  57 + setting.getConditionType(), setting.getConditionExpression(), setting.getConditionGroups());
  58 + isFormUpdateNeeded = BpmnModelUtils.evalConditionExpress(processVariables, conditionExpression);
  59 + }
  60 + // 更新流程表单
  61 + if (isFormUpdateNeeded) {
  62 + processInstanceService.updateProcessInstanceVariables(processInstanceId, setting.getUpdateFormFields());
  63 + }
  64 + }
  65 + }
  66 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmAbstractHttpRequestTrigger.java renamed to yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmAbstractHttpRequestTrigger.java
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmHttpCallbackTrigger.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.task.trigger.http;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  4 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
  5 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmHttpRequestParamTypeEnum;
  6 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum;
  7 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmHttpRequestUtils;
  8 +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  9 +import jakarta.annotation.Resource;
  10 +import lombok.extern.slf4j.Slf4j;
  11 +import org.flowable.engine.runtime.ProcessInstance;
  12 +import org.springframework.stereotype.Component;
  13 +import org.springframework.web.client.RestTemplate;
  14 +
  15 +/**
  16 + * BPM HTTP 回调触发器
  17 + *
  18 + * @author jason
  19 + */
  20 +@Component
  21 +@Slf4j
  22 +public class BpmHttpCallbackTrigger extends BpmAbstractHttpRequestTrigger {
  23 +
  24 + @Resource
  25 + private BpmProcessInstanceService processInstanceService;
  26 +
  27 + @Override
  28 + public BpmTriggerTypeEnum getType() {
  29 + return BpmTriggerTypeEnum.HTTP_CALLBACK;
  30 + }
  31 +
  32 + @Override
  33 + public void execute(String processInstanceId, String param) {
  34 + // 1. 解析 http 请求配置
  35 + BpmSimpleModelNodeVO.TriggerSetting.HttpRequestTriggerSetting setting = JsonUtils.parseObject(param,
  36 + BpmSimpleModelNodeVO.TriggerSetting.HttpRequestTriggerSetting.class);
  37 + if (setting == null) {
  38 + log.error("[execute][流程({}) HTTP 回调触发器配置为空]", processInstanceId);
  39 + return;
  40 + }
  41 +
  42 + // 2. 发起请求
  43 + ProcessInstance processInstance = processInstanceService.getProcessInstance(processInstanceId);
  44 + setting.getBody().add(new BpmSimpleModelNodeVO.HttpRequestParam()
  45 + .setKey("taskDefineKey") // 重要:回调请求 taskDefineKey 需要传给被调用方,用于回调执行
  46 + .setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType()).setValue(setting.getCallbackTaskDefineKey()));
  47 + BpmHttpRequestUtils.executeBpmHttpRequest(processInstance,
  48 + setting.getUrl(), setting.getHeader(), setting.getBody(), false, null);
  49 + }
  50 +
  51 +}
... ...
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmSyncHttpRequestTrigger.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.task.trigger.http;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  4 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.TriggerSetting.HttpRequestTriggerSetting;
  5 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum;
  6 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmHttpRequestUtils;
  7 +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  8 +import jakarta.annotation.Resource;
  9 +import lombok.extern.slf4j.Slf4j;
  10 +import org.flowable.engine.runtime.ProcessInstance;
  11 +import org.springframework.stereotype.Component;
  12 +import org.springframework.web.client.RestTemplate;
  13 +
  14 +/**
  15 + * BPM 发送同步 HTTP 请求触发器
  16 + *
  17 + * @author jason
  18 + */
  19 +@Component
  20 +@Slf4j
  21 +public class BpmSyncHttpRequestTrigger extends BpmAbstractHttpRequestTrigger {
  22 +
  23 + @Resource
  24 + private BpmProcessInstanceService processInstanceService;
  25 +
  26 + @Override
  27 + public BpmTriggerTypeEnum getType() {
  28 + return BpmTriggerTypeEnum.HTTP_REQUEST;
  29 + }
  30 +
  31 + @Override
  32 + public void execute(String processInstanceId, String param) {
  33 + // 1. 解析 http 请求配置
  34 + HttpRequestTriggerSetting setting = JsonUtils.parseObject(param, HttpRequestTriggerSetting.class);
  35 + if (setting == null) {
  36 + log.error("[execute][流程({}) HTTP 触发器请求配置为空]", processInstanceId);
  37 + return;
  38 + }
  39 +
  40 + // 2. 发起请求
  41 + ProcessInstance processInstance = processInstanceService.getProcessInstance(processInstanceId);
  42 + BpmHttpRequestUtils.executeBpmHttpRequest(processInstance,
  43 + setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse());
  44 + }
  45 +
  46 +}
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvokerTest.java renamed to yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvokerTest.java
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignLeaderExpressionTest.java renamed to yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignLeaderExpressionTest.java
yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateDeptLeaderMultiStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.dept;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  4 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  5 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  6 +import org.assertj.core.util.Sets;
  7 +import org.junit.jupiter.api.Test;
  8 +import org.mockito.InjectMocks;
  9 +import org.mockito.Mock;
  10 +import org.mockito.stubbing.Answer;
  11 +
  12 +import java.util.Set;
  13 +
  14 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  15 +import static org.junit.jupiter.api.Assertions.assertEquals;
  16 +import static org.mockito.ArgumentMatchers.any;
  17 +import static org.mockito.Mockito.when;
  18 +
  19 +public class BpmTaskCandidateDeptLeaderMultiStrategyTest extends BaseMockitoUnitTest {
  20 +
  21 + @InjectMocks
  22 + private BpmTaskCandidateDeptLeaderMultiStrategy strategy;
  23 +
  24 + @Mock
  25 + private DeptApi deptApi;
  26 +
  27 + @Test
  28 + public void testCalculateUsers() {
  29 + // 准备参数
  30 + String param = "10,20|2";
  31 + // mock 方法
  32 + when(deptApi.getDept(any())).thenAnswer((Answer<DeptRespDTO>) invocationOnMock -> {
  33 + Long deptId = invocationOnMock.getArgument(0);
  34 + return randomPojo(DeptRespDTO.class, o -> o.setId(deptId).setParentId(deptId * 100).setLeaderUserId(deptId + 1));
  35 + });
  36 +
  37 + // 调用
  38 + Set<Long> userIds = strategy.calculateUsers(param);
  39 + // 断言结果
  40 + assertEquals(Sets.newLinkedHashSet(11L, 1001L, 21L, 2001L), userIds);
  41 + }
  42 +
  43 +}
... ...
yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateDeptLeaderStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.dept;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
  4 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  5 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  6 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  7 +import org.assertj.core.util.Sets;
  8 +import org.junit.jupiter.api.Test;
  9 +import org.mockito.InjectMocks;
  10 +import org.mockito.Mock;
  11 +
  12 +import java.util.Set;
  13 +
  14 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  15 +import static java.util.Arrays.asList;
  16 +import static org.junit.jupiter.api.Assertions.assertEquals;
  17 +import static org.mockito.ArgumentMatchers.eq;
  18 +import static org.mockito.Mockito.when;
  19 +
  20 +public class BpmTaskCandidateDeptLeaderStrategyTest extends BaseMockitoUnitTest {
  21 +
  22 + @InjectMocks
  23 + private BpmTaskCandidateDeptLeaderStrategy strategy;
  24 +
  25 + @Mock
  26 + private DeptApi deptApi;
  27 +
  28 + @Test
  29 + public void testCalculateUsers() {
  30 + // 准备参数
  31 + String param = "10,20";
  32 + // mock 方法
  33 + when(deptApi.getDeptList(eq(SetUtils.asSet(10L, 20L)))).thenReturn(asList(
  34 + randomPojo(DeptRespDTO.class, o -> o.setId(10L).setParentId(10L).setLeaderUserId(11L)),
  35 + randomPojo(DeptRespDTO.class, o -> o.setId(20L).setParentId(20L).setLeaderUserId(21L))));
  36 +
  37 + // 调用
  38 + Set<Long> userIds = strategy.calculateUsers(param);
  39 + // 断言结果
  40 + assertEquals(Sets.newLinkedHashSet(11L, 21L), userIds);
  41 + }
  42 +
  43 +}
... ...
yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateDeptMemberStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.dept;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
  4 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  5 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  6 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  7 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  8 +import org.assertj.core.util.Sets;
  9 +import org.junit.jupiter.api.Test;
  10 +import org.mockito.InjectMocks;
  11 +import org.mockito.Mock;
  12 +
  13 +import java.util.Set;
  14 +
  15 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  16 +import static java.util.Arrays.asList;
  17 +import static org.junit.jupiter.api.Assertions.assertEquals;
  18 +import static org.mockito.ArgumentMatchers.eq;
  19 +import static org.mockito.Mockito.when;
  20 +
  21 +public class BpmTaskCandidateDeptMemberStrategyTest extends BaseMockitoUnitTest {
  22 +
  23 + @InjectMocks
  24 + private BpmTaskCandidateDeptMemberStrategy strategy;
  25 +
  26 + @Mock
  27 + private DeptApi deptApi;
  28 + @Mock
  29 + private AdminUserApi adminUserApi;
  30 +
  31 + @Test
  32 + public void testCalculateUsers() {
  33 + // 准备参数
  34 + String param = "10,20";
  35 + // mock 方法
  36 + when(adminUserApi.getUserListByDeptIds(eq(SetUtils.asSet(10L, 20L)))).thenReturn(asList(
  37 + randomPojo(AdminUserRespDTO.class, o -> o.setId(11L)),
  38 + randomPojo(AdminUserRespDTO.class, o -> o.setId(21L))));
  39 +
  40 + // 调用
  41 + Set<Long> userIds = strategy.calculateUsers(param);
  42 + // 断言结果
  43 + assertEquals(Sets.newLinkedHashSet(11L, 21L), userIds);
  44 + }
  45 +
  46 +}
... ...
yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderMultiStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.dept;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  4 +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  5 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  6 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  7 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  8 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  9 +import org.assertj.core.util.Sets;
  10 +import org.flowable.engine.delegate.DelegateExecution;
  11 +import org.flowable.engine.runtime.ProcessInstance;
  12 +import org.junit.jupiter.api.Test;
  13 +import org.mockito.InjectMocks;
  14 +import org.mockito.Mock;
  15 +import org.mockito.stubbing.Answer;
  16 +
  17 +import java.util.Set;
  18 +
  19 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  20 +import static org.junit.jupiter.api.Assertions.assertEquals;
  21 +import static org.mockito.ArgumentMatchers.any;
  22 +import static org.mockito.ArgumentMatchers.eq;
  23 +import static org.mockito.Mockito.mock;
  24 +import static org.mockito.Mockito.when;
  25 +
  26 +public class BpmTaskCandidateStartUserDeptLeaderMultiStrategyTest extends BaseMockitoUnitTest {
  27 +
  28 + @InjectMocks
  29 + private BpmTaskCandidateStartUserDeptLeaderMultiStrategy strategy;
  30 +
  31 + @Mock
  32 + private BpmProcessInstanceService processInstanceService;
  33 +
  34 + @Mock
  35 + private AdminUserApi adminUserApi;
  36 + @Mock
  37 + private DeptApi deptApi;
  38 +
  39 + @Test
  40 + public void testCalculateUsersByTask() {
  41 + // 准备参数
  42 + String param = "2";
  43 + // mock 方法(获得流程发起人)
  44 + Long startUserId = 1L;
  45 + ProcessInstance processInstance = mock(ProcessInstance.class);
  46 + DelegateExecution execution = mock(DelegateExecution.class);
  47 + when(processInstanceService.getProcessInstance(eq(execution.getProcessInstanceId()))).thenReturn(processInstance);
  48 + when(processInstance.getStartUserId()).thenReturn(startUserId.toString());
  49 + // mock 方法(获取发起人的 multi 部门负责人)
  50 + mockGetStartUserDept(startUserId);
  51 +
  52 + // 调用
  53 + Set<Long> userIds = strategy.calculateUsersByTask(execution, param);
  54 + // 断言
  55 + assertEquals(Sets.newLinkedHashSet(11L, 1001L), userIds);
  56 + }
  57 +
  58 + @Test
  59 + public void testCalculateUsersByActivity() {
  60 + // 准备参数
  61 + String param = "2";
  62 + // mock 方法
  63 + Long startUserId = 1L;
  64 + mockGetStartUserDept(startUserId);
  65 +
  66 + // 调用
  67 + Set<Long> userIds = strategy.calculateUsersByActivity(null, null, param,
  68 + startUserId, null, null);
  69 + // 断言
  70 + assertEquals(Sets.newLinkedHashSet(11L, 1001L), userIds);
  71 + }
  72 +
  73 + private void mockGetStartUserDept(Long startUserId) {
  74 + when(adminUserApi.getUser(eq(startUserId))).thenReturn(
  75 + randomPojo(AdminUserRespDTO.class, o -> o.setId(startUserId).setDeptId(10L)));
  76 + when(deptApi.getDept(any())).thenAnswer((Answer<DeptRespDTO>) invocationOnMock -> {
  77 + Long deptId = invocationOnMock.getArgument(0);
  78 + return randomPojo(DeptRespDTO.class, o -> o.setId(deptId).setParentId(deptId * 100).setLeaderUserId(deptId + 1));
  79 + });
  80 + }
  81 +
  82 +}
... ...
yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.dept;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  4 +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  5 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  6 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  7 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  8 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  9 +import org.assertj.core.util.Sets;
  10 +import org.flowable.engine.delegate.DelegateExecution;
  11 +import org.flowable.engine.runtime.ProcessInstance;
  12 +import org.junit.jupiter.api.Test;
  13 +import org.mockito.InjectMocks;
  14 +import org.mockito.Mock;
  15 +import org.mockito.stubbing.Answer;
  16 +
  17 +import java.util.Set;
  18 +
  19 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  20 +import static org.junit.jupiter.api.Assertions.assertEquals;
  21 +import static org.mockito.ArgumentMatchers.any;
  22 +import static org.mockito.ArgumentMatchers.eq;
  23 +import static org.mockito.Mockito.mock;
  24 +import static org.mockito.Mockito.when;
  25 +
  26 +public class BpmTaskCandidateStartUserDeptLeaderStrategyTest extends BaseMockitoUnitTest {
  27 +
  28 + @InjectMocks
  29 + private BpmTaskCandidateStartUserDeptLeaderStrategy strategy;
  30 +
  31 + @Mock
  32 + private BpmProcessInstanceService processInstanceService;
  33 +
  34 + @Mock
  35 + private AdminUserApi adminUserApi;
  36 + @Mock
  37 + private DeptApi deptApi;
  38 +
  39 + @Test
  40 + public void testCalculateUsersByTask() {
  41 + // 准备参数
  42 + String param = "2";
  43 + // mock 方法(获得流程发起人)
  44 + Long startUserId = 1L;
  45 + ProcessInstance processInstance = mock(ProcessInstance.class);
  46 + DelegateExecution execution = mock(DelegateExecution.class);
  47 + when(processInstanceService.getProcessInstance(eq(execution.getProcessInstanceId()))).thenReturn(processInstance);
  48 + when(processInstance.getStartUserId()).thenReturn(startUserId.toString());
  49 + // mock 方法(获取发起人的部门负责人)
  50 + mockGetStartUserDeptLeader(startUserId);
  51 +
  52 + // 调用
  53 + Set<Long> userIds = strategy.calculateUsersByTask(execution, param);
  54 + // 断言
  55 + assertEquals(Sets.newLinkedHashSet(1001L), userIds);
  56 + }
  57 +
  58 + @Test
  59 + public void testGetStartUserDeptLeader() {
  60 + // 准备参数
  61 + String param = "2";
  62 + // mock 方法
  63 + Long startUserId = 1L;
  64 + mockGetStartUserDeptLeader(startUserId);
  65 +
  66 + // 调用
  67 + Set<Long> userIds = strategy.calculateUsersByActivity(null, null, param,
  68 + startUserId, null, null);
  69 + // 断言
  70 + assertEquals(Sets.newLinkedHashSet(1001L), userIds);
  71 + }
  72 +
  73 + private void mockGetStartUserDeptLeader(Long startUserId) {
  74 + when(adminUserApi.getUser(eq(startUserId))).thenReturn(
  75 + randomPojo(AdminUserRespDTO.class, o -> o.setId(startUserId).setDeptId(10L)));
  76 + when(deptApi.getDept(any())).thenAnswer((Answer<DeptRespDTO>) invocationOnMock -> {
  77 + Long deptId = invocationOnMock.getArgument(0);
  78 + return randomPojo(DeptRespDTO.class, o -> o.setId(deptId).setParentId(deptId * 100).setLeaderUserId(deptId + 1));
  79 + });
  80 + }
  81 +
  82 +}
... ...
yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserSelectStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.dept;
  2 +
  3 +import cn.hutool.core.map.MapUtil;
  4 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  5 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants;
  6 +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  7 +import org.assertj.core.util.Sets;
  8 +import org.flowable.engine.delegate.DelegateExecution;
  9 +import org.flowable.engine.runtime.ProcessInstance;
  10 +import org.junit.jupiter.api.Test;
  11 +import org.mockito.InjectMocks;
  12 +import org.mockito.Mock;
  13 +
  14 +import java.util.HashMap;
  15 +import java.util.List;
  16 +import java.util.Map;
  17 +import java.util.Set;
  18 +
  19 +import static org.junit.jupiter.api.Assertions.assertEquals;
  20 +import static org.mockito.ArgumentMatchers.eq;
  21 +import static org.mockito.Mockito.mock;
  22 +import static org.mockito.Mockito.when;
  23 +
  24 +public class BpmTaskCandidateStartUserSelectStrategyTest extends BaseMockitoUnitTest {
  25 +
  26 + @InjectMocks
  27 + private BpmTaskCandidateStartUserSelectStrategy strategy;
  28 +
  29 + @Mock
  30 + private BpmProcessInstanceService processInstanceService;
  31 +
  32 + @Test
  33 + public void testCalculateUsersByTask() {
  34 + // 准备参数
  35 + String param = "2";
  36 + // mock 方法(获得流程发起人)
  37 + ProcessInstance processInstance = mock(ProcessInstance.class);
  38 + DelegateExecution execution = mock(DelegateExecution.class);
  39 + when(processInstanceService.getProcessInstance(eq(execution.getProcessInstanceId()))).thenReturn(processInstance);
  40 + when(execution.getCurrentActivityId()).thenReturn("activity_001");
  41 + // mock 方法(FlowableUtils)
  42 + Map<String, Object> processVariables = new HashMap<>();
  43 + processVariables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES,
  44 + MapUtil.of("activity_001", List.of(1L, 2L)));
  45 + when(processInstance.getProcessVariables()).thenReturn(processVariables);
  46 +
  47 + // 调用
  48 + Set<Long> userIds = strategy.calculateUsersByTask(execution, param);
  49 + // 断言
  50 + assertEquals(Sets.newLinkedHashSet(1L, 2L), userIds);
  51 + }
  52 +
  53 + @Test
  54 + public void testCalculateUsersByActivity() {
  55 + // 准备参数
  56 + String activityId = "activity_001";
  57 + Map<String, Object> processVariables = new HashMap<>();
  58 + processVariables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES,
  59 + MapUtil.of("activity_001", List.of(1L, 2L)));
  60 +
  61 + // 调用
  62 + Set<Long> userIds = strategy.calculateUsersByActivity(null, activityId, null,
  63 + null, null, processVariables);
  64 + // 断言
  65 + assertEquals(Sets.newLinkedHashSet(1L, 2L), userIds);
  66 + }
  67 +
  68 +}
... ...
yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/other/BpmTaskCandidateAssignEmptyStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.other;
  2 +
  3 +import cn.hutool.core.collection.ListUtil;
  4 +import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
  5 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  6 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
  7 +import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskAssignEmptyHandlerTypeEnum;
  8 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
  9 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
  10 +import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
  11 +import org.flowable.bpmn.model.BpmnModel;
  12 +import org.flowable.bpmn.model.FlowElement;
  13 +import org.flowable.engine.delegate.DelegateExecution;
  14 +import org.junit.jupiter.api.Test;
  15 +import org.mockito.InjectMocks;
  16 +import org.mockito.Mock;
  17 +import org.mockito.MockedStatic;
  18 +
  19 +import java.util.Set;
  20 +
  21 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  22 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
  23 +import static org.junit.jupiter.api.Assertions.assertEquals;
  24 +import static org.mockito.Mockito.*;
  25 +
  26 +public class BpmTaskCandidateAssignEmptyStrategyTest extends BaseMockitoUnitTest {
  27 +
  28 + @InjectMocks
  29 + private BpmTaskCandidateAssignEmptyStrategy strategy;
  30 +
  31 + @Mock
  32 + private BpmProcessDefinitionService processDefinitionService;
  33 +
  34 + @Test
  35 + public void testCalculateUsersByTask() {
  36 + try (MockedStatic<FlowableUtils> flowableUtilMockedStatic = mockStatic(FlowableUtils.class);
  37 + MockedStatic<BpmnModelUtils> bpmnModelUtilsMockedStatic = mockStatic(BpmnModelUtils.class)) {
  38 + // 准备参数
  39 + DelegateExecution execution = mock(DelegateExecution.class);
  40 + String param = randomString();
  41 + // mock 方法(execution)
  42 + String processDefinitionId = randomString();
  43 + when(execution.getProcessDefinitionId()).thenReturn(processDefinitionId);
  44 + FlowElement flowElement = mock(FlowElement.class);
  45 + when(execution.getCurrentFlowElement()).thenReturn(flowElement);
  46 + // mock 方法(parseAssignEmptyHandlerType)
  47 + bpmnModelUtilsMockedStatic.when(() -> BpmnModelUtils.parseAssignEmptyHandlerType(same(flowElement)))
  48 + .thenReturn(BpmUserTaskAssignEmptyHandlerTypeEnum.ASSIGN_USER.getType());
  49 + bpmnModelUtilsMockedStatic.when(() -> BpmnModelUtils.parseAssignEmptyHandlerUserIds(same(flowElement)))
  50 + .thenReturn(ListUtil.of(1L, 2L));
  51 +
  52 + // 调用
  53 + Set<Long> userIds = strategy.calculateUsersByTask(execution, param);
  54 + // 断言
  55 + assertEquals(SetUtils.asSet(1L, 2L), userIds);
  56 + }
  57 +
  58 + }
  59 +
  60 + @Test
  61 + public void testCalculateUsersByActivity() {
  62 + try (MockedStatic<BpmnModelUtils> bpmnModelUtilsMockedStatic = mockStatic(BpmnModelUtils.class)) {
  63 + // 准备参数
  64 + String processDefinitionId = randomString();
  65 + String activityId = randomString();
  66 + String param = randomString();
  67 + // mock 方法(getFlowElementById)
  68 + FlowElement flowElement = mock(FlowElement.class);
  69 + BpmnModel bpmnModel = mock(BpmnModel.class);
  70 + bpmnModelUtilsMockedStatic.when(() -> BpmnModelUtils.getFlowElementById(same(bpmnModel), eq(activityId)))
  71 + .thenReturn(flowElement);
  72 + // mock 方法(parseAssignEmptyHandlerType)
  73 + bpmnModelUtilsMockedStatic.when(() -> BpmnModelUtils.parseAssignEmptyHandlerType(same(flowElement)))
  74 + .thenReturn(BpmUserTaskAssignEmptyHandlerTypeEnum.ASSIGN_ADMIN.getType());
  75 + // mock 方法(getProcessDefinitionInfo)
  76 + BpmProcessDefinitionInfoDO processDefinition = randomPojo(BpmProcessDefinitionInfoDO.class,
  77 + o -> o.setManagerUserIds(ListUtil.of(1L, 2L)));
  78 + when(processDefinitionService.getProcessDefinitionInfo(eq(processDefinitionId))).thenReturn(processDefinition);
  79 +
  80 + // 调用
  81 + Set<Long> userIds = strategy.calculateUsersByActivity(bpmnModel, activityId, param,
  82 + null, processDefinitionId, null);
  83 + // 断言
  84 + assertEquals(SetUtils.asSet(1L, 2L), userIds);
  85 + }
  86 + }
  87 +
  88 +}
... ...
yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/other/BpmTaskCandidateExpressionStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.other;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  4 +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
  5 +import org.flowable.engine.delegate.DelegateExecution;
  6 +import org.junit.jupiter.api.Disabled;
  7 +import org.junit.jupiter.api.Test;
  8 +import org.mockito.InjectMocks;
  9 +import org.mockito.MockedStatic;
  10 +
  11 +import java.util.HashMap;
  12 +import java.util.Map;
  13 +import java.util.Set;
  14 +
  15 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
  16 +import static org.junit.jupiter.api.Assertions.assertEquals;
  17 +import static org.mockito.ArgumentMatchers.eq;
  18 +import static org.mockito.Mockito.*;
  19 +
  20 +@Disabled // TODO 芋艿:临时注释
  21 +public class BpmTaskCandidateExpressionStrategyTest extends BaseMockitoUnitTest {
  22 +
  23 + @InjectMocks
  24 + private BpmTaskCandidateExpressionStrategy strategy;
  25 +
  26 + @Test
  27 + public void testCalculateUsersByTask() {
  28 + try (MockedStatic<FlowableUtils> flowableUtilMockedStatic = mockStatic(FlowableUtils.class)) {
  29 + // 准备参数
  30 + String param = "1,2";
  31 + DelegateExecution execution = mock(DelegateExecution.class);
  32 + // mock 方法
  33 + flowableUtilMockedStatic.when(() -> FlowableUtils.getExpressionValue(same(execution), eq(param)))
  34 + .thenReturn(asSet(1L, 2L));
  35 +
  36 + // 调用
  37 + Set<Long> results = strategy.calculateUsersByTask(execution, param);
  38 + // 断言
  39 + assertEquals(asSet(1L, 2L), results);
  40 + }
  41 + }
  42 +
  43 + @Test
  44 + public void testCalculateUsersByActivity() {
  45 + try (MockedStatic<FlowableUtils> flowableUtilMockedStatic = mockStatic(FlowableUtils.class)) {
  46 + // 准备参数
  47 + String param = "1,2";
  48 + Map<String, Object> processVariables = new HashMap<>();
  49 + // mock 方法
  50 + flowableUtilMockedStatic.when(() -> FlowableUtils.getExpressionValue(same(processVariables), eq(param)))
  51 + .thenReturn(asSet(1L, 2L));
  52 +
  53 + // 调用
  54 + Set<Long> results = strategy.calculateUsersByActivity(null, null, param,
  55 + null, null, processVariables);
  56 + // 断言
  57 + assertEquals(asSet(1L, 2L), results);
  58 + }
  59 + }
  60 +
  61 +}
... ...
yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidateGroupStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.user;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  4 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
  5 +import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
  6 +import org.junit.jupiter.api.Disabled;
  7 +import org.junit.jupiter.api.Test;
  8 +import org.mockito.InjectMocks;
  9 +import org.mockito.Mock;
  10 +
  11 +import java.util.Arrays;
  12 +import java.util.Set;
  13 +
  14 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
  15 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  16 +import static org.junit.jupiter.api.Assertions.assertEquals;
  17 +import static org.mockito.ArgumentMatchers.eq;
  18 +import static org.mockito.Mockito.when;
  19 +
  20 +@Disabled // TODO 芋艿:临时注释
  21 +public class BpmTaskCandidateGroupStrategyTest extends BaseMockitoUnitTest {
  22 +
  23 + @InjectMocks
  24 + private BpmTaskCandidateGroupStrategy strategy;
  25 +
  26 + @Mock
  27 + private BpmUserGroupService userGroupService;
  28 +
  29 + @Test
  30 + public void testCalculateUsers() {
  31 + // 准备参数
  32 + String param = "1,2";
  33 + // mock 方法
  34 + BpmUserGroupDO userGroup1 = randomPojo(BpmUserGroupDO.class, o -> o.setUserIds(asSet(11L, 12L)));
  35 + BpmUserGroupDO userGroup2 = randomPojo(BpmUserGroupDO.class, o -> o.setUserIds(asSet(21L, 22L)));
  36 + when(userGroupService.getUserGroupList(eq(asSet(1L, 2L)))).thenReturn(Arrays.asList(userGroup1, userGroup2));
  37 +
  38 + // 调用
  39 + Set<Long> userIds = strategy.calculateUsersByTask(null, param);
  40 + // 断言
  41 + assertEquals(asSet(11L, 12L, 21L, 22L), userIds);
  42 + }
  43 +
  44 +}
... ...
yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidatePostStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.user;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  4 +import cn.iocoder.yudao.module.system.api.dept.PostApi;
  5 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  6 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  7 +import org.junit.jupiter.api.Disabled;
  8 +import org.junit.jupiter.api.Test;
  9 +import org.mockito.InjectMocks;
  10 +import org.mockito.Mock;
  11 +
  12 +import java.util.List;
  13 +import java.util.Set;
  14 +
  15 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  16 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
  17 +import static org.junit.jupiter.api.Assertions.assertEquals;
  18 +import static org.mockito.ArgumentMatchers.eq;
  19 +import static org.mockito.Mockito.when;
  20 +
  21 +@Disabled // TODO 芋艿:临时注释
  22 +public class BpmTaskCandidatePostStrategyTest extends BaseMockitoUnitTest {
  23 +
  24 + @InjectMocks
  25 + private BpmTaskCandidatePostStrategy strategy;
  26 +
  27 + @Mock
  28 + private PostApi postApi;
  29 + @Mock
  30 + private AdminUserApi adminUserApi;
  31 +
  32 + @Test
  33 + public void testCalculateUsers() {
  34 + // 准备参数
  35 + String param = "1,2";
  36 + // mock 方法
  37 + List<AdminUserRespDTO> users = convertList(asSet(11L, 22L),
  38 + id -> new AdminUserRespDTO().setId(id));
  39 + when(adminUserApi.getUserListByPostIds(eq(asSet(1L, 2L)))).thenReturn(users);
  40 +
  41 + // 调用
  42 + Set<Long> userIds = strategy.calculateUsersByTask(null, param);
  43 + // 断言
  44 + assertEquals(asSet(11L, 22L), userIds);
  45 + }
  46 +
  47 +}
... ...
yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidateRoleStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.user;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  4 +import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
  5 +import cn.iocoder.yudao.module.system.api.permission.RoleApi;
  6 +import org.junit.jupiter.api.Disabled;
  7 +import org.junit.jupiter.api.Test;
  8 +import org.mockito.InjectMocks;
  9 +import org.mockito.Mock;
  10 +
  11 +import java.util.Set;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
  14 +import static org.junit.jupiter.api.Assertions.assertEquals;
  15 +import static org.mockito.ArgumentMatchers.eq;
  16 +import static org.mockito.Mockito.when;
  17 +
  18 +@Disabled // TODO 芋艿:临时注释
  19 +public class BpmTaskCandidateRoleStrategyTest extends BaseMockitoUnitTest {
  20 +
  21 + @InjectMocks
  22 + private BpmTaskCandidateRoleStrategy strategy;
  23 +
  24 + @Mock
  25 + private RoleApi roleApi;
  26 + @Mock
  27 + private PermissionApi permissionApi;
  28 +
  29 + @Test
  30 + public void testCalculateUsers() {
  31 + // 准备参数
  32 + String param = "1,2";
  33 + // mock 方法
  34 + when(permissionApi.getUserRoleIdListByRoleIds(eq(asSet(1L, 2L))))
  35 + .thenReturn(asSet(11L, 22L));
  36 +
  37 + // 调用
  38 + Set<Long> userIds = strategy.calculateUsersByTask(null, param);
  39 + // 断言
  40 + assertEquals(asSet(11L, 22L), userIds);
  41 + }
  42 +
  43 +}
... ...
yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidateStartUserStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.user;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  4 +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  5 +import org.assertj.core.util.Sets;
  6 +import org.flowable.engine.delegate.DelegateExecution;
  7 +import org.flowable.engine.runtime.ProcessInstance;
  8 +import org.junit.jupiter.api.Test;
  9 +import org.mockito.InjectMocks;
  10 +import org.mockito.Mock;
  11 +
  12 +import java.util.Set;
  13 +
  14 +import static org.junit.jupiter.api.Assertions.assertEquals;
  15 +import static org.mockito.ArgumentMatchers.eq;
  16 +import static org.mockito.Mockito.mock;
  17 +import static org.mockito.Mockito.when;
  18 +
  19 +public class BpmTaskCandidateStartUserStrategyTest extends BaseMockitoUnitTest {
  20 +
  21 + @InjectMocks
  22 + private BpmTaskCandidateStartUserStrategy strategy;
  23 +
  24 + @Mock
  25 + private BpmProcessInstanceService processInstanceService;
  26 +
  27 + @Test
  28 + public void testCalculateUsersByTask() {
  29 + // 准备参数
  30 + String param = "2";
  31 + // mock 方法(获得流程发起人)
  32 + Long startUserId = 1L;
  33 + ProcessInstance processInstance = mock(ProcessInstance.class);
  34 + DelegateExecution execution = mock(DelegateExecution.class);
  35 + when(processInstanceService.getProcessInstance(eq(execution.getProcessInstanceId()))).thenReturn(processInstance);
  36 + when(processInstance.getStartUserId()).thenReturn(startUserId.toString());
  37 +
  38 + // 调用
  39 + Set<Long> userIds = strategy.calculateUsersByTask(execution, param);
  40 + // 断言
  41 + assertEquals(Sets.newLinkedHashSet(startUserId), userIds);
  42 + }
  43 +
  44 + @Test
  45 + public void testCalculateUsersByActivity() {
  46 + // 准备参数
  47 + Long startUserId = 1L;
  48 +
  49 + // 调用
  50 + Set<Long> userIds = strategy.calculateUsersByActivity(null, null, null,
  51 + startUserId, null, null);
  52 + // 断言
  53 + assertEquals(Sets.newLinkedHashSet(startUserId), userIds);
  54 + }
  55 +
  56 +}
... ...
yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidateUserStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.user;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  4 +import org.junit.jupiter.api.Disabled;
  5 +import org.junit.jupiter.api.Test;
  6 +import org.mockito.InjectMocks;
  7 +
  8 +import java.util.Set;
  9 +
  10 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
  11 +import static org.junit.jupiter.api.Assertions.assertEquals;
  12 +
  13 +@Disabled // TODO 芋艿:临时注释
  14 +public class BpmTaskCandidateUserStrategyTest extends BaseMockitoUnitTest {
  15 +
  16 + @InjectMocks
  17 + private BpmTaskCandidateUserStrategy strategy;
  18 +
  19 + @Test
  20 + public void test() {
  21 + // 准备参数
  22 + String param = "1,2";
  23 +
  24 + // 调用
  25 + Set<Long> userIds = strategy.calculateUsersByTask(null, param);
  26 + // 断言
  27 + assertEquals(asSet(1L, 2L), userIds);
  28 + }
  29 +
  30 +
  31 +}
... ...
yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/service/category/BpmCategoryServiceImplTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.category;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
  6 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.category.BpmCategoryPageReqVO;
  7 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.category.BpmCategorySaveReqVO;
  8 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
  9 +import cn.iocoder.yudao.module.bpm.dal.mysql.category.BpmCategoryMapper;
  10 +import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryServiceImpl;
  11 +import jakarta.annotation.Resource;
  12 +import org.junit.jupiter.api.Test;
  13 +import org.springframework.context.annotation.Import;
  14 +
  15 +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
  16 +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
  17 +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
  18 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
  19 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
  20 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
  21 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.CATEGORY_NOT_EXISTS;
  22 +import static org.junit.jupiter.api.Assertions.*;
  23 +
  24 +/**
  25 + * {@link BpmCategoryServiceImpl} 的单元测试类
  26 + *
  27 + * @author 芋道源码
  28 + */
  29 +@Import(BpmCategoryServiceImpl.class)
  30 +public class BpmCategoryServiceImplTest extends BaseDbUnitTest {
  31 +
  32 + @Resource
  33 + private BpmCategoryServiceImpl categoryService;
  34 +
  35 + @Resource
  36 + private BpmCategoryMapper categoryMapper;
  37 +
  38 + @Test
  39 + public void testCreateCategory_success() {
  40 + // 准备参数
  41 + BpmCategorySaveReqVO createReqVO = randomPojo(BpmCategorySaveReqVO.class).setId(null)
  42 + .setStatus(randomCommonStatus());
  43 +
  44 + // 调用
  45 + Long categoryId = categoryService.createCategory(createReqVO);
  46 + // 断言
  47 + assertNotNull(categoryId);
  48 + // 校验记录的属性是否正确
  49 + BpmCategoryDO category = categoryMapper.selectById(categoryId);
  50 + assertPojoEquals(createReqVO, category, "id");
  51 + }
  52 +
  53 + @Test
  54 + public void testUpdateCategory_success() {
  55 + // mock 数据
  56 + BpmCategoryDO dbCategory = randomPojo(BpmCategoryDO.class);
  57 + categoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据
  58 + // 准备参数
  59 + BpmCategorySaveReqVO updateReqVO = randomPojo(BpmCategorySaveReqVO.class, o -> {
  60 + o.setId(dbCategory.getId()); // 设置更新的 ID
  61 + o.setStatus(randomCommonStatus());
  62 + });
  63 +
  64 + // 调用
  65 + categoryService.updateCategory(updateReqVO);
  66 + // 校验是否更新正确
  67 + BpmCategoryDO category = categoryMapper.selectById(updateReqVO.getId()); // 获取最新的
  68 + assertPojoEquals(updateReqVO, category);
  69 + }
  70 +
  71 + @Test
  72 + public void testUpdateCategory_notExists() {
  73 + // 准备参数
  74 + BpmCategorySaveReqVO updateReqVO = randomPojo(BpmCategorySaveReqVO.class);
  75 +
  76 + // 调用, 并断言异常
  77 + assertServiceException(() -> categoryService.updateCategory(updateReqVO), CATEGORY_NOT_EXISTS);
  78 + }
  79 +
  80 + @Test
  81 + public void testDeleteCategory_success() {
  82 + // mock 数据
  83 + BpmCategoryDO dbCategory = randomPojo(BpmCategoryDO.class);
  84 + categoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据
  85 + // 准备参数
  86 + Long id = dbCategory.getId();
  87 +
  88 + // 调用
  89 + categoryService.deleteCategory(id);
  90 + // 校验数据不存在了
  91 + assertNull(categoryMapper.selectById(id));
  92 + }
  93 +
  94 + @Test
  95 + public void testDeleteCategory_notExists() {
  96 + // 准备参数
  97 + Long id = randomLongId();
  98 +
  99 + // 调用, 并断言异常
  100 + assertServiceException(() -> categoryService.deleteCategory(id), CATEGORY_NOT_EXISTS);
  101 + }
  102 +
  103 + @Test
  104 + public void testGetCategoryPage() {
  105 + // mock 数据
  106 + BpmCategoryDO dbCategory = randomPojo(BpmCategoryDO.class, o -> { // 等会查询到
  107 + o.setName("芋头");
  108 + o.setCode("xiaodun");
  109 + o.setStatus(CommonStatusEnum.ENABLE.getStatus());
  110 + o.setCreateTime(buildTime(2023, 2, 2));
  111 + });
  112 + categoryMapper.insert(dbCategory);
  113 + // 测试 name 不匹配
  114 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setName("小盾")));
  115 + // 测试 code 不匹配
  116 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setCode("tudou")));
  117 + // 测试 status 不匹配
  118 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  119 + // 测试 createTime 不匹配
  120 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setCreateTime(buildTime(2024, 2, 2))));
  121 + // 准备参数
  122 + BpmCategoryPageReqVO reqVO = new BpmCategoryPageReqVO();
  123 + reqVO.setName("芋");
  124 + reqVO.setCode("xiao");
  125 + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
  126 + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
  127 +
  128 + // 调用
  129 + PageResult<BpmCategoryDO> pageResult = categoryService.getCategoryPage(reqVO);
  130 + // 断言
  131 + assertEquals(1, pageResult.getTotal());
  132 + assertEquals(1, pageResult.getList().size());
  133 + assertPojoEquals(dbCategory, pageResult.getList().get(0));
  134 + }
  135 +
  136 +}
0 137 \ No newline at end of file
... ...
yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormServiceTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.definition;
  2 +
  3 +import cn.hutool.core.util.RandomUtil;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  6 +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
  7 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormSaveReqVO;
  8 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormPageReqVO;
  9 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
  10 +import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmFormMapper;
  11 +import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmFormFieldRespDTO;
  12 +import org.junit.jupiter.api.Test;
  13 +import org.springframework.context.annotation.Import;
  14 +
  15 +import jakarta.annotation.Resource;
  16 +import java.util.List;
  17 +import java.util.stream.Collectors;
  18 +import java.util.stream.Stream;
  19 +
  20 +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
  21 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
  22 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
  23 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
  24 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  25 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.FORM_NOT_EXISTS;
  26 +import static org.junit.jupiter.api.Assertions.*;
  27 +
  28 +/**
  29 + * {@link BpmFormServiceImpl} 的单元测试类
  30 + *
  31 + * @author 芋道源码
  32 + */
  33 +@Import(BpmFormServiceImpl.class)
  34 +public class BpmFormServiceTest extends BaseDbUnitTest {
  35 +
  36 + @Resource
  37 + private BpmFormServiceImpl formService;
  38 +
  39 + @Resource
  40 + private BpmFormMapper formMapper;
  41 +
  42 + @Test
  43 + public void testCreateForm_success() {
  44 + // 准备参数
  45 + BpmFormSaveReqVO reqVO = randomPojo(BpmFormSaveReqVO.class, o -> {
  46 + o.setConf("{}");
  47 + o.setFields(randomFields());
  48 + });
  49 +
  50 + // 调用
  51 + Long formId = formService.createForm(reqVO);
  52 + // 断言
  53 + assertNotNull(formId);
  54 + // 校验记录的属性是否正确
  55 + BpmFormDO form = formMapper.selectById(formId);
  56 + assertPojoEquals(reqVO, form);
  57 + }
  58 +
  59 + @Test
  60 + public void testUpdateForm_success() {
  61 + // mock 数据
  62 + BpmFormDO dbForm = randomPojo(BpmFormDO.class, o -> {
  63 + o.setConf("{}");
  64 + o.setFields(randomFields());
  65 + });
  66 + formMapper.insert(dbForm);// @Sql: 先插入出一条存在的数据
  67 + // 准备参数
  68 + BpmFormSaveReqVO reqVO = randomPojo(BpmFormSaveReqVO.class, o -> {
  69 + o.setId(dbForm.getId()); // 设置更新的 ID
  70 + o.setConf("{'yudao': 'yuanma'}");
  71 + o.setFields(randomFields());
  72 + });
  73 +
  74 + // 调用
  75 + formService.updateForm(reqVO);
  76 + // 校验是否更新正确
  77 + BpmFormDO form = formMapper.selectById(reqVO.getId()); // 获取最新的
  78 + assertPojoEquals(reqVO, form);
  79 + }
  80 +
  81 + @Test
  82 + public void testUpdateForm_notExists() {
  83 + // 准备参数
  84 + BpmFormSaveReqVO reqVO = randomPojo(BpmFormSaveReqVO.class, o -> {
  85 + o.setConf("{'yudao': 'yuanma'}");
  86 + o.setFields(randomFields());
  87 + });
  88 +
  89 + // 调用, 并断言异常
  90 + assertServiceException(() -> formService.updateForm(reqVO), FORM_NOT_EXISTS);
  91 + }
  92 +
  93 + @Test
  94 + public void testDeleteForm_success() {
  95 + // mock 数据
  96 + BpmFormDO dbForm = randomPojo(BpmFormDO.class);
  97 + formMapper.insert(dbForm);// @Sql: 先插入出一条存在的数据
  98 + // 准备参数
  99 + Long id = dbForm.getId();
  100 +
  101 + // 调用
  102 + formService.deleteForm(id);
  103 + // 校验数据不存在了
  104 + assertNull(formMapper.selectById(id));
  105 + }
  106 +
  107 + @Test
  108 + public void testDeleteForm_notExists() {
  109 + // 准备参数
  110 + Long id = randomLongId();
  111 +
  112 + // 调用, 并断言异常
  113 + assertServiceException(() -> formService.deleteForm(id), FORM_NOT_EXISTS);
  114 + }
  115 +
  116 + @Test
  117 + public void testGetFormPage() {
  118 + // mock 数据
  119 + BpmFormDO dbForm = randomPojo(BpmFormDO.class, o -> { // 等会查询到
  120 + o.setName("芋道源码");
  121 + });
  122 + formMapper.insert(dbForm);
  123 + // 测试 name 不匹配
  124 + formMapper.insert(cloneIgnoreId(dbForm, o -> o.setName("源码")));
  125 + // 准备参数
  126 + BpmFormPageReqVO reqVO = new BpmFormPageReqVO();
  127 + reqVO.setName("芋道");
  128 +
  129 + // 调用
  130 + PageResult<BpmFormDO> pageResult = formService.getFormPage(reqVO);
  131 + // 断言
  132 + assertEquals(1, pageResult.getTotal());
  133 + assertEquals(1, pageResult.getList().size());
  134 + assertPojoEquals(dbForm, pageResult.getList().get(0));
  135 + }
  136 +
  137 + private List<String> randomFields() {
  138 + int size = RandomUtil.randomInt(1, 3);
  139 + return Stream.iterate(0, i -> i).limit(size)
  140 + .map(i -> JsonUtils.toJsonString(randomPojo(BpmFormFieldRespDTO.class)))
  141 + .collect(Collectors.toList());
  142 + }
  143 +
  144 +}
... ...
yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.bpm.service.definition;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
  6 +import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
  7 +import cn.iocoder.yudao.framework.test.core.util.RandomUtils;
  8 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupSaveReqVO;
  9 +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupPageReqVO;
  10 +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
  11 +import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmUserGroupMapper;
  12 +import org.junit.jupiter.api.Assertions;
  13 +import org.junit.jupiter.api.Test;
  14 +import org.springframework.context.annotation.Import;
  15 +
  16 +import jakarta.annotation.Resource;
  17 +
  18 +import java.time.LocalDateTime;
  19 +
  20 +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
  21 +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
  22 +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.USER_GROUP_NOT_EXISTS;
  23 +
  24 +/**
  25 + * {@link BpmUserGroupServiceImpl} 的单元测试类
  26 + *
  27 + * @author 芋道源码
  28 + */
  29 +@Import(BpmUserGroupServiceImpl.class)
  30 +public class BpmUserGroupServiceTest extends BaseDbUnitTest {
  31 +
  32 + @Resource
  33 + private BpmUserGroupServiceImpl userGroupService;
  34 +
  35 + @Resource
  36 + private BpmUserGroupMapper userGroupMapper;
  37 +
  38 + @Test
  39 + public void testCreateUserGroup_success() {
  40 + // 准备参数
  41 + BpmUserGroupSaveReqVO reqVO = RandomUtils.randomPojo(BpmUserGroupSaveReqVO.class);
  42 +
  43 + // 调用
  44 + Long userGroupId = userGroupService.createUserGroup(reqVO);
  45 + // 断言
  46 + Assertions.assertNotNull(userGroupId);
  47 + // 校验记录的属性是否正确
  48 + BpmUserGroupDO userGroup = userGroupMapper.selectById(userGroupId);
  49 + AssertUtils.assertPojoEquals(reqVO, userGroup);
  50 + }
  51 +
  52 + @Test
  53 + public void testUpdateUserGroup_success() {
  54 + // mock 数据
  55 + BpmUserGroupDO dbUserGroup = RandomUtils.randomPojo(BpmUserGroupDO.class);
  56 + userGroupMapper.insert(dbUserGroup);// @Sql: 先插入出一条存在的数据
  57 + // 准备参数
  58 + BpmUserGroupSaveReqVO reqVO = RandomUtils.randomPojo(BpmUserGroupSaveReqVO.class, o -> {
  59 + o.setId(dbUserGroup.getId()); // 设置更新的 ID
  60 + });
  61 +
  62 + // 调用
  63 + userGroupService.updateUserGroup(reqVO);
  64 + // 校验是否更新正确
  65 + BpmUserGroupDO userGroup = userGroupMapper.selectById(reqVO.getId()); // 获取最新的
  66 + AssertUtils.assertPojoEquals(reqVO, userGroup);
  67 + }
  68 +
  69 + @Test
  70 + public void testUpdateUserGroup_notExists() {
  71 + // 准备参数
  72 + BpmUserGroupSaveReqVO reqVO = RandomUtils.randomPojo(BpmUserGroupSaveReqVO.class);
  73 +
  74 + // 调用, 并断言异常
  75 + AssertUtils.assertServiceException(() -> userGroupService.updateUserGroup(reqVO), USER_GROUP_NOT_EXISTS);
  76 + }
  77 +
  78 + @Test
  79 + public void testDeleteUserGroup_success() {
  80 + // mock 数据
  81 + BpmUserGroupDO dbUserGroup = RandomUtils.randomPojo(BpmUserGroupDO.class);
  82 + userGroupMapper.insert(dbUserGroup);// @Sql: 先插入出一条存在的数据
  83 + // 准备参数
  84 + Long id = dbUserGroup.getId();
  85 +
  86 + // 调用
  87 + userGroupService.deleteUserGroup(id);
  88 + // 校验数据不存在了
  89 + Assertions.assertNull(userGroupMapper.selectById(id));
  90 + }
  91 +
  92 + @Test
  93 + public void testDeleteUserGroup_notExists() {
  94 + // 准备参数
  95 + Long id = RandomUtils.randomLongId();
  96 +
  97 + // 调用, 并断言异常
  98 + AssertUtils.assertServiceException(() -> userGroupService.deleteUserGroup(id), USER_GROUP_NOT_EXISTS);
  99 + }
  100 +
  101 + @Test
  102 + public void testGetUserGroupPage() {
  103 + // mock 数据
  104 + BpmUserGroupDO dbUserGroup = RandomUtils.randomPojo(BpmUserGroupDO.class, o -> { // 等会查询到
  105 + o.setName("芋道源码");
  106 + o.setStatus(CommonStatusEnum.ENABLE.getStatus());
  107 + o.setCreateTime(buildTime(2021, 11, 11));
  108 + });
  109 + userGroupMapper.insert(dbUserGroup);
  110 + // 测试 name 不匹配
  111 + userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setName("芋道")));
  112 + // 测试 status 不匹配
  113 + userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  114 + // 测试 createTime 不匹配
  115 + userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setCreateTime(buildTime(2021, 12, 12))));
  116 + // 准备参数
  117 + BpmUserGroupPageReqVO reqVO = new BpmUserGroupPageReqVO();
  118 + reqVO.setName("源码");
  119 + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
  120 + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 11, 10),buildTime(2021, 11, 12)}));
  121 +
  122 + // 调用
  123 + PageResult<BpmUserGroupDO> pageResult = userGroupService.getUserGroupPage(reqVO);
  124 + // 断言
  125 + Assertions.assertEquals(1, pageResult.getTotal());
  126 + Assertions.assertEquals(1, pageResult.getList().size());
  127 + AssertUtils.assertPojoEquals(dbUserGroup, pageResult.getList().get(0));
  128 + }
  129 +
  130 +}
... ...
yudao-module-bpm/src/test/resources/application-unit-test.yaml 0 → 100644
  1 +spring:
  2 + main:
  3 + lazy-initialization: true # 开启懒加载,加快速度
  4 + banner-mode: off # 单元测试,禁用 Banner
  5 +
  6 +--- #################### 数据库相关配置 ####################
  7 +
  8 +spring:
  9 + # 数据源配置项
  10 + datasource:
  11 + name: ruoyi-vue-pro
  12 + url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写
  13 + driver-class-name: org.h2.Driver
  14 + username: sa
  15 + password:
  16 + druid:
  17 + async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度
  18 + initial-size: 1 # 单元测试,配置为 1,提升启动速度
  19 + sql:
  20 + init:
  21 + schema-locations: classpath:/sql/create_tables.sql
  22 +
  23 +mybatis-plus:
  24 + lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
  25 + type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject
  26 +
  27 +--- #################### 定时任务相关配置 ####################
  28 +
  29 +--- #################### 配置中心相关配置 ####################
  30 +
  31 +--- #################### 服务保障相关配置 ####################
  32 +
  33 +# Lock4j 配置项(单元测试,禁用 Lock4j)
  34 +
  35 +--- #################### 监控相关配置 ####################
  36 +
  37 +--- #################### 芋道相关配置 ####################
  38 +
  39 +# 芋道配置项,设置当前项目所有自定义的配置
  40 +yudao:
  41 + info:
  42 + base-package: cn.iocoder.yudao.module
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/test/resources/logback.xml renamed to yudao-module-bpm/src/test/resources/logback.xml
yudao-module-bpm/yudao-module-bpm-biz/src/test/resources/sql/clean.sql renamed to yudao-module-bpm/src/test/resources/sql/clean.sql
yudao-module-bpm/src/test/resources/sql/create_tables.sql 0 → 100644
  1 +CREATE TABLE IF NOT EXISTS "bpm_user_group" (
  2 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  3 + "name" varchar(63) NOT NULL,
  4 + "description" varchar(255) NOT NULL,
  5 + "status" tinyint NOT NULL,
  6 + "user_ids" varchar(255) NOT NULL,
  7 + "creator" varchar(64) DEFAULT '',
  8 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  9 + "updater" varchar(64) DEFAULT '',
  10 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  11 + "deleted" bit NOT NULL DEFAULT FALSE,
  12 + PRIMARY KEY ("id")
  13 +) COMMENT '用户组';
  14 +
  15 +CREATE TABLE IF NOT EXISTS "bpm_category" (
  16 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  17 + "name" varchar(63) NOT NULL,
  18 + "code" varchar(63) NOT NULL,
  19 + "description" varchar(255) NOT NULL,
  20 + "status" tinyint NOT NULL,
  21 + "sort" int NOT NULL,
  22 + "creator" varchar(64) DEFAULT '',
  23 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  24 + "updater" varchar(64) DEFAULT '',
  25 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  26 + "deleted" bit NOT NULL DEFAULT FALSE,
  27 + PRIMARY KEY ("id")
  28 +) COMMENT '分类';
  29 +
  30 +CREATE TABLE IF NOT EXISTS "bpm_form" (
  31 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  32 + "name" varchar(63) NOT NULL,
  33 + "status" tinyint NOT NULL,
  34 + "fields" varchar(255) NOT NULL,
  35 + "conf" varchar(255) NOT NULL,
  36 + "remark" varchar(255),
  37 + "creator" varchar(64) DEFAULT '',
  38 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  39 + "updater" varchar(64) DEFAULT '',
  40 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  41 + "deleted" bit NOT NULL DEFAULT FALSE,
  42 + PRIMARY KEY ("id")
  43 +) COMMENT '动态表单';
... ...
yudao-module-bpm/yudao-module-bpm-api/pom.xml deleted
1   -<?xml version="1.0" encoding="UTF-8"?>
2   -<project xmlns="http://maven.apache.org/POM/4.0.0"
3   - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4   - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5   - <parent>
6   - <groupId>cn.iocoder.boot</groupId>
7   - <artifactId>yudao-module-bpm</artifactId>
8   - <version>${revision}</version>
9   - </parent>
10   - <modelVersion>4.0.0</modelVersion>
11   - <artifactId>yudao-module-bpm-api</artifactId>
12   - <packaging>jar</packaging>
13   -
14   - <name>${project.artifactId}</name>
15   - <description>
16   - bpm 模块 API,暴露给其它模块调用
17   - </description>
18   -
19   - <dependencies>
20   - <dependency>
21   - <groupId>cn.iocoder.boot</groupId>
22   - <artifactId>yudao-common</artifactId>
23   - </dependency>
24   -
25   - <!-- 参数校验 -->
26   - <dependency>
27   - <groupId>org.springframework.boot</groupId>
28   - <artifactId>spring-boot-starter-validation</artifactId>
29   - <optional>true</optional>
30   - </dependency>
31   - </dependencies>
32   -
33   -</project>
yudao-module-bpm/yudao-module-bpm-biz/pom.xml deleted
1   -<?xml version="1.0" encoding="UTF-8"?>
2   -<project xmlns="http://maven.apache.org/POM/4.0.0"
3   - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4   - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5   - <parent>
6   - <groupId>cn.iocoder.boot</groupId>
7   - <artifactId>yudao-module-bpm</artifactId>
8   - <version>${revision}</version>
9   - </parent>
10   - <modelVersion>4.0.0</modelVersion>
11   - <artifactId>yudao-module-bpm-biz</artifactId>
12   -
13   - <name>${project.artifactId}</name>
14   - <description>
15   - bpm 包下,业务流程管理(Business Process Management),我们放工作流的功能,基于 Flowable 6 版本实现。
16   - 例如说:流程定义、表单配置、审核中心(我的申请、我的待办、我的已办)等等
17   - </description>
18   - <dependencies>
19   - <dependency>
20   - <groupId>cn.iocoder.boot</groupId>
21   - <artifactId>yudao-module-bpm-api</artifactId>
22   - <version>${revision}</version>
23   - </dependency>
24   - <dependency>
25   - <groupId>cn.iocoder.boot</groupId>
26   - <artifactId>yudao-module-system-api</artifactId>
27   - <version>${revision}</version>
28   - </dependency>
29   -
30   - <!-- 业务组件 -->
31   - <dependency>
32   - <groupId>cn.iocoder.boot</groupId>
33   - <artifactId>yudao-spring-boot-starter-biz-data-permission</artifactId>
34   - </dependency>
35   - <dependency>
36   - <groupId>cn.iocoder.boot</groupId>
37   - <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
38   - </dependency>
39   -
40   - <!-- Web 相关 -->
41   - <dependency>
42   - <groupId>cn.iocoder.boot</groupId>
43   - <artifactId>yudao-spring-boot-starter-web</artifactId>
44   - </dependency>
45   -
46   - <dependency>
47   - <groupId>cn.iocoder.boot</groupId>
48   - <artifactId>yudao-spring-boot-starter-security</artifactId>
49   - </dependency>
50   -
51   - <!-- DB 相关 -->
52   - <dependency>
53   - <groupId>cn.iocoder.boot</groupId>
54   - <artifactId>yudao-spring-boot-starter-mybatis</artifactId>
55   - </dependency>
56   -
57   - <!-- Test 测试相关 -->
58   - <dependency>
59   - <groupId>cn.iocoder.boot</groupId>
60   - <artifactId>yudao-spring-boot-starter-test</artifactId>
61   - </dependency>
62   -
63   - <!-- 工具类相关 -->
64   - <dependency>
65   - <groupId>cn.iocoder.boot</groupId>
66   - <artifactId>yudao-spring-boot-starter-excel</artifactId>
67   - </dependency>
68   -
69   - <!-- Flowable 工作流相关 -->
70   - <dependency>
71   - <groupId>org.flowable</groupId>
72   - <artifactId>flowable-spring-boot-starter-process</artifactId>
73   - </dependency>
74   - <dependency>
75   - <groupId>org.flowable</groupId>
76   - <artifactId>flowable-spring-boot-starter-actuator</artifactId>
77   - </dependency>
78   - </dependencies>
79   -</project>
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/api/package-info.java deleted
1   -/**
2   - * bpm API 实现类,定义暴露给其它模块的 API
3   - */
4   -package cn.iocoder.yudao.module.bpm.api;
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmUserTaskListener.java deleted
1   -package cn.iocoder.yudao.module.bpm.service.task.listener;
2   -
3   -import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
4   -import cn.iocoder.yudao.module.bpm.enums.definition.BpmHttpRequestParamTypeEnum;
5   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmHttpRequestUtils;
6   -import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
7   -import jakarta.annotation.Resource;
8   -import lombok.Setter;
9   -import lombok.extern.slf4j.Slf4j;
10   -import org.flowable.engine.delegate.TaskListener;
11   -import org.flowable.engine.impl.el.FixedValue;
12   -import org.flowable.engine.runtime.ProcessInstance;
13   -import org.flowable.task.service.delegate.DelegateTask;
14   -import org.springframework.context.annotation.Scope;
15   -import org.springframework.stereotype.Component;
16   -
17   -import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseListenerConfig;
18   -
19   -// TODO @芋艿:可能会想换个包地址
20   -/**
21   - * BPM 用户任务通用监听器
22   - *
23   - * @author Lesan
24   - */
25   -@Component
26   -@Slf4j
27   -@Scope("prototype")
28   -public class BpmUserTaskListener implements TaskListener {
29   -
30   - public static final String DELEGATE_EXPRESSION = "${bpmUserTaskListener}";
31   -
32   - @Resource
33   - private BpmProcessInstanceService processInstanceService;
34   -
35   - @Setter
36   - private FixedValue listenerConfig;
37   -
38   - @Override
39   - public void notify(DelegateTask delegateTask) {
40   - // 1. 获取所需基础信息
41   - ProcessInstance processInstance = processInstanceService.getProcessInstance(delegateTask.getProcessInstanceId());
42   - BpmSimpleModelNodeVO.ListenerHandler listenerHandler = parseListenerConfig(listenerConfig);
43   -
44   - // 2. 发起请求
45   - // TODO @芋艿:哪些默认参数,后续再调研下;感觉可以搞个 task 字段,把整个 delegateTask 放进去;
46   - listenerHandler.getBody().add(new BpmSimpleModelNodeVO.HttpRequestParam().setKey("processInstanceId")
47   - .setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType()).setValue(delegateTask.getProcessInstanceId()));
48   - listenerHandler.getBody().add(new BpmSimpleModelNodeVO.HttpRequestParam().setKey("assignee")
49   - .setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType()).setValue(delegateTask.getAssignee()));
50   - listenerHandler.getBody().add(new BpmSimpleModelNodeVO.HttpRequestParam().setKey("taskDefinitionKey")
51   - .setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType()).setValue(delegateTask.getTaskDefinitionKey()));
52   - listenerHandler.getBody().add(new BpmSimpleModelNodeVO.HttpRequestParam().setKey("taskId")
53   - .setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType()).setValue(delegateTask.getId()));
54   - BpmHttpRequestUtils.executeBpmHttpRequest(processInstance,
55   - listenerHandler.getPath(), listenerHandler.getHeader(), listenerHandler.getBody(), false, null);
56   -
57   - // 3. 是否需要后续操作?TODO 芋艿:待定!
58   - }
59   -}
60 0 \ No newline at end of file
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/form/BpmFormDeleteTrigger.java deleted
1   -package cn.iocoder.yudao.module.bpm.service.task.trigger.form;
2   -
3   -import cn.hutool.core.collection.CollUtil;
4   -import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
5   -import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
6   -import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum;
7   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
8   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils;
9   -import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
10   -import cn.iocoder.yudao.module.bpm.service.task.trigger.BpmTrigger;
11   -import com.fasterxml.jackson.core.type.TypeReference;
12   -import jakarta.annotation.Resource;
13   -import lombok.extern.slf4j.Slf4j;
14   -import org.springframework.stereotype.Component;
15   -
16   -import java.util.HashSet;
17   -import java.util.List;
18   -import java.util.Map;
19   -import java.util.Set;
20   -
21   -/**
22   - * BPM 删除流程表单数据触发器
23   - *
24   - * @author jason
25   - */
26   -@Component
27   -@Slf4j
28   -public class BpmFormDeleteTrigger implements BpmTrigger {
29   -
30   - @Resource
31   - private BpmProcessInstanceService processInstanceService;
32   -
33   - @Override
34   - public BpmTriggerTypeEnum getType() {
35   - return BpmTriggerTypeEnum.FORM_DELETE;
36   - }
37   -
38   - @Override
39   - public void execute(String processInstanceId, String param) {
40   - // 1. 解析删除流程表单数据配置
41   - List<BpmSimpleModelNodeVO.TriggerSetting.FormTriggerSetting> settings = JsonUtils.parseObject(param, new TypeReference<>() {});
42   - if (CollUtil.isEmpty(settings)) {
43   - log.error("[execute][流程({}) 删除流程表单数据触发器配置为空]", processInstanceId);
44   - return;
45   - }
46   -
47   - // 2. 获取流程变量
48   - Map<String, Object> processVariables = processInstanceService.getProcessInstance(processInstanceId).getProcessVariables();
49   -
50   - // 3.1 获取需要删除的表单字段
51   - Set<String> deleteFields = new HashSet<>();
52   - settings.forEach(setting -> {
53   - if (CollUtil.isEmpty(setting.getDeleteFields())) {
54   - return;
55   - }
56   - // 配置了条件,判断条件是否满足
57   - boolean isFieldDeletedNeeded = true;
58   - if (setting.getConditionType() != null) {
59   - String conditionExpression = SimpleModelUtils.buildConditionExpression(
60   - setting.getConditionType(), setting.getConditionExpression(), setting.getConditionGroups());
61   - isFieldDeletedNeeded = BpmnModelUtils.evalConditionExpress(processVariables, conditionExpression);
62   - }
63   - if (isFieldDeletedNeeded) {
64   - deleteFields.addAll(setting.getDeleteFields());
65   - }
66   - });
67   -
68   - // 3.2 删除流程变量
69   - if (CollUtil.isNotEmpty(deleteFields)) {
70   - processInstanceService.removeProcessInstanceVariables(processInstanceId, deleteFields);
71   - }
72   - }
73   -}
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/form/BpmFormUpdateTrigger.java deleted
1   -package cn.iocoder.yudao.module.bpm.service.task.trigger.form;
2   -
3   -import cn.hutool.core.collection.CollUtil;
4   -import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
5   -import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.TriggerSetting.FormTriggerSetting;
6   -import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum;
7   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
8   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils;
9   -import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
10   -import cn.iocoder.yudao.module.bpm.service.task.trigger.BpmTrigger;
11   -import com.fasterxml.jackson.core.type.TypeReference;
12   -import jakarta.annotation.Resource;
13   -import lombok.extern.slf4j.Slf4j;
14   -import org.springframework.stereotype.Component;
15   -
16   -import java.util.List;
17   -import java.util.Map;
18   -
19   -/**
20   - * BPM 更新流程表单触发器
21   - *
22   - * @author jason
23   - */
24   -@Component
25   -@Slf4j
26   -public class BpmFormUpdateTrigger implements BpmTrigger {
27   -
28   - @Resource
29   - private BpmProcessInstanceService processInstanceService;
30   -
31   - @Override
32   - public BpmTriggerTypeEnum getType() {
33   - return BpmTriggerTypeEnum.FORM_UPDATE;
34   - }
35   -
36   - @Override
37   - public void execute(String processInstanceId, String param) {
38   - // 1. 解析更新流程表单配置
39   - List<FormTriggerSetting> settings = JsonUtils.parseObject(param, new TypeReference<>() {});
40   - if (CollUtil.isEmpty(settings)) {
41   - log.error("[execute][流程({}) 更新流程表单触发器配置为空]", processInstanceId);
42   - return;
43   - }
44   -
45   - // 2. 获取流程变量
46   - Map<String, Object> processVariables = processInstanceService.getProcessInstance(processInstanceId).getProcessVariables();
47   -
48   - // 3. 更新流程变量
49   - for (FormTriggerSetting setting : settings) {
50   - if (CollUtil.isEmpty(setting.getUpdateFormFields())) {
51   - continue;
52   - }
53   - // 配置了条件,判断条件是否满足
54   - boolean isFormUpdateNeeded = true;
55   - if (setting.getConditionType() != null) {
56   - String conditionExpression = SimpleModelUtils.buildConditionExpression(
57   - setting.getConditionType(), setting.getConditionExpression(), setting.getConditionGroups());
58   - isFormUpdateNeeded = BpmnModelUtils.evalConditionExpress(processVariables, conditionExpression);
59   - }
60   - // 更新流程表单
61   - if (isFormUpdateNeeded) {
62   - processInstanceService.updateProcessInstanceVariables(processInstanceId, setting.getUpdateFormFields());
63   - }
64   - }
65   - }
66   -}
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmHttpCallbackTrigger.java deleted
1   -package cn.iocoder.yudao.module.bpm.service.task.trigger.http;
2   -
3   -import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
4   -import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
5   -import cn.iocoder.yudao.module.bpm.enums.definition.BpmHttpRequestParamTypeEnum;
6   -import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum;
7   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmHttpRequestUtils;
8   -import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
9   -import jakarta.annotation.Resource;
10   -import lombok.extern.slf4j.Slf4j;
11   -import org.flowable.engine.runtime.ProcessInstance;
12   -import org.springframework.stereotype.Component;
13   -import org.springframework.web.client.RestTemplate;
14   -
15   -/**
16   - * BPM HTTP 回调触发器
17   - *
18   - * @author jason
19   - */
20   -@Component
21   -@Slf4j
22   -public class BpmHttpCallbackTrigger extends BpmAbstractHttpRequestTrigger {
23   -
24   - @Resource
25   - private BpmProcessInstanceService processInstanceService;
26   -
27   - @Override
28   - public BpmTriggerTypeEnum getType() {
29   - return BpmTriggerTypeEnum.HTTP_CALLBACK;
30   - }
31   -
32   - @Override
33   - public void execute(String processInstanceId, String param) {
34   - // 1. 解析 http 请求配置
35   - BpmSimpleModelNodeVO.TriggerSetting.HttpRequestTriggerSetting setting = JsonUtils.parseObject(param,
36   - BpmSimpleModelNodeVO.TriggerSetting.HttpRequestTriggerSetting.class);
37   - if (setting == null) {
38   - log.error("[execute][流程({}) HTTP 回调触发器配置为空]", processInstanceId);
39   - return;
40   - }
41   -
42   - // 2. 发起请求
43   - ProcessInstance processInstance = processInstanceService.getProcessInstance(processInstanceId);
44   - setting.getBody().add(new BpmSimpleModelNodeVO.HttpRequestParam()
45   - .setKey("taskDefineKey") // 重要:回调请求 taskDefineKey 需要传给被调用方,用于回调执行
46   - .setType(BpmHttpRequestParamTypeEnum.FIXED_VALUE.getType()).setValue(setting.getCallbackTaskDefineKey()));
47   - BpmHttpRequestUtils.executeBpmHttpRequest(processInstance,
48   - setting.getUrl(), setting.getHeader(), setting.getBody(), false, null);
49   - }
50   -
51   -}
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmSyncHttpRequestTrigger.java deleted
1   -package cn.iocoder.yudao.module.bpm.service.task.trigger.http;
2   -
3   -import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
4   -import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.TriggerSetting.HttpRequestTriggerSetting;
5   -import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum;
6   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmHttpRequestUtils;
7   -import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
8   -import jakarta.annotation.Resource;
9   -import lombok.extern.slf4j.Slf4j;
10   -import org.flowable.engine.runtime.ProcessInstance;
11   -import org.springframework.stereotype.Component;
12   -import org.springframework.web.client.RestTemplate;
13   -
14   -/**
15   - * BPM 发送同步 HTTP 请求触发器
16   - *
17   - * @author jason
18   - */
19   -@Component
20   -@Slf4j
21   -public class BpmSyncHttpRequestTrigger extends BpmAbstractHttpRequestTrigger {
22   -
23   - @Resource
24   - private BpmProcessInstanceService processInstanceService;
25   -
26   - @Override
27   - public BpmTriggerTypeEnum getType() {
28   - return BpmTriggerTypeEnum.HTTP_REQUEST;
29   - }
30   -
31   - @Override
32   - public void execute(String processInstanceId, String param) {
33   - // 1. 解析 http 请求配置
34   - HttpRequestTriggerSetting setting = JsonUtils.parseObject(param, HttpRequestTriggerSetting.class);
35   - if (setting == null) {
36   - log.error("[execute][流程({}) HTTP 触发器请求配置为空]", processInstanceId);
37   - return;
38   - }
39   -
40   - // 2. 发起请求
41   - ProcessInstance processInstance = processInstanceService.getProcessInstance(processInstanceId);
42   - BpmHttpRequestUtils.executeBpmHttpRequest(processInstance,
43   - setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse());
44   - }
45   -
46   -}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateDeptLeaderMultiStrategyTest.java deleted
1   -package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.dept;
2   -
3   -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
4   -import cn.iocoder.yudao.module.system.api.dept.DeptApi;
5   -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
6   -import org.assertj.core.util.Sets;
7   -import org.junit.jupiter.api.Test;
8   -import org.mockito.InjectMocks;
9   -import org.mockito.Mock;
10   -import org.mockito.stubbing.Answer;
11   -
12   -import java.util.Set;
13   -
14   -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
15   -import static org.junit.jupiter.api.Assertions.assertEquals;
16   -import static org.mockito.ArgumentMatchers.any;
17   -import static org.mockito.Mockito.when;
18   -
19   -public class BpmTaskCandidateDeptLeaderMultiStrategyTest extends BaseMockitoUnitTest {
20   -
21   - @InjectMocks
22   - private BpmTaskCandidateDeptLeaderMultiStrategy strategy;
23   -
24   - @Mock
25   - private DeptApi deptApi;
26   -
27   - @Test
28   - public void testCalculateUsers() {
29   - // 准备参数
30   - String param = "10,20|2";
31   - // mock 方法
32   - when(deptApi.getDept(any())).thenAnswer((Answer<DeptRespDTO>) invocationOnMock -> {
33   - Long deptId = invocationOnMock.getArgument(0);
34   - return randomPojo(DeptRespDTO.class, o -> o.setId(deptId).setParentId(deptId * 100).setLeaderUserId(deptId + 1));
35   - });
36   -
37   - // 调用
38   - Set<Long> userIds = strategy.calculateUsers(param);
39   - // 断言结果
40   - assertEquals(Sets.newLinkedHashSet(11L, 1001L, 21L, 2001L), userIds);
41   - }
42   -
43   -}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateDeptLeaderStrategyTest.java deleted
1   -package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.dept;
2   -
3   -import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
4   -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
5   -import cn.iocoder.yudao.module.system.api.dept.DeptApi;
6   -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
7   -import org.assertj.core.util.Sets;
8   -import org.junit.jupiter.api.Test;
9   -import org.mockito.InjectMocks;
10   -import org.mockito.Mock;
11   -
12   -import java.util.Set;
13   -
14   -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
15   -import static java.util.Arrays.asList;
16   -import static org.junit.jupiter.api.Assertions.assertEquals;
17   -import static org.mockito.ArgumentMatchers.eq;
18   -import static org.mockito.Mockito.when;
19   -
20   -public class BpmTaskCandidateDeptLeaderStrategyTest extends BaseMockitoUnitTest {
21   -
22   - @InjectMocks
23   - private BpmTaskCandidateDeptLeaderStrategy strategy;
24   -
25   - @Mock
26   - private DeptApi deptApi;
27   -
28   - @Test
29   - public void testCalculateUsers() {
30   - // 准备参数
31   - String param = "10,20";
32   - // mock 方法
33   - when(deptApi.getDeptList(eq(SetUtils.asSet(10L, 20L)))).thenReturn(asList(
34   - randomPojo(DeptRespDTO.class, o -> o.setId(10L).setParentId(10L).setLeaderUserId(11L)),
35   - randomPojo(DeptRespDTO.class, o -> o.setId(20L).setParentId(20L).setLeaderUserId(21L))));
36   -
37   - // 调用
38   - Set<Long> userIds = strategy.calculateUsers(param);
39   - // 断言结果
40   - assertEquals(Sets.newLinkedHashSet(11L, 21L), userIds);
41   - }
42   -
43   -}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateDeptMemberStrategyTest.java deleted
1   -package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.dept;
2   -
3   -import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
4   -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
5   -import cn.iocoder.yudao.module.system.api.dept.DeptApi;
6   -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
7   -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
8   -import org.assertj.core.util.Sets;
9   -import org.junit.jupiter.api.Test;
10   -import org.mockito.InjectMocks;
11   -import org.mockito.Mock;
12   -
13   -import java.util.Set;
14   -
15   -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
16   -import static java.util.Arrays.asList;
17   -import static org.junit.jupiter.api.Assertions.assertEquals;
18   -import static org.mockito.ArgumentMatchers.eq;
19   -import static org.mockito.Mockito.when;
20   -
21   -public class BpmTaskCandidateDeptMemberStrategyTest extends BaseMockitoUnitTest {
22   -
23   - @InjectMocks
24   - private BpmTaskCandidateDeptMemberStrategy strategy;
25   -
26   - @Mock
27   - private DeptApi deptApi;
28   - @Mock
29   - private AdminUserApi adminUserApi;
30   -
31   - @Test
32   - public void testCalculateUsers() {
33   - // 准备参数
34   - String param = "10,20";
35   - // mock 方法
36   - when(adminUserApi.getUserListByDeptIds(eq(SetUtils.asSet(10L, 20L)))).thenReturn(asList(
37   - randomPojo(AdminUserRespDTO.class, o -> o.setId(11L)),
38   - randomPojo(AdminUserRespDTO.class, o -> o.setId(21L))));
39   -
40   - // 调用
41   - Set<Long> userIds = strategy.calculateUsers(param);
42   - // 断言结果
43   - assertEquals(Sets.newLinkedHashSet(11L, 21L), userIds);
44   - }
45   -
46   -}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderMultiStrategyTest.java deleted
1   -package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.dept;
2   -
3   -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
4   -import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
5   -import cn.iocoder.yudao.module.system.api.dept.DeptApi;
6   -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
7   -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
8   -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
9   -import org.assertj.core.util.Sets;
10   -import org.flowable.engine.delegate.DelegateExecution;
11   -import org.flowable.engine.runtime.ProcessInstance;
12   -import org.junit.jupiter.api.Test;
13   -import org.mockito.InjectMocks;
14   -import org.mockito.Mock;
15   -import org.mockito.stubbing.Answer;
16   -
17   -import java.util.Set;
18   -
19   -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
20   -import static org.junit.jupiter.api.Assertions.assertEquals;
21   -import static org.mockito.ArgumentMatchers.any;
22   -import static org.mockito.ArgumentMatchers.eq;
23   -import static org.mockito.Mockito.mock;
24   -import static org.mockito.Mockito.when;
25   -
26   -public class BpmTaskCandidateStartUserDeptLeaderMultiStrategyTest extends BaseMockitoUnitTest {
27   -
28   - @InjectMocks
29   - private BpmTaskCandidateStartUserDeptLeaderMultiStrategy strategy;
30   -
31   - @Mock
32   - private BpmProcessInstanceService processInstanceService;
33   -
34   - @Mock
35   - private AdminUserApi adminUserApi;
36   - @Mock
37   - private DeptApi deptApi;
38   -
39   - @Test
40   - public void testCalculateUsersByTask() {
41   - // 准备参数
42   - String param = "2";
43   - // mock 方法(获得流程发起人)
44   - Long startUserId = 1L;
45   - ProcessInstance processInstance = mock(ProcessInstance.class);
46   - DelegateExecution execution = mock(DelegateExecution.class);
47   - when(processInstanceService.getProcessInstance(eq(execution.getProcessInstanceId()))).thenReturn(processInstance);
48   - when(processInstance.getStartUserId()).thenReturn(startUserId.toString());
49   - // mock 方法(获取发起人的 multi 部门负责人)
50   - mockGetStartUserDept(startUserId);
51   -
52   - // 调用
53   - Set<Long> userIds = strategy.calculateUsersByTask(execution, param);
54   - // 断言
55   - assertEquals(Sets.newLinkedHashSet(11L, 1001L), userIds);
56   - }
57   -
58   - @Test
59   - public void testCalculateUsersByActivity() {
60   - // 准备参数
61   - String param = "2";
62   - // mock 方法
63   - Long startUserId = 1L;
64   - mockGetStartUserDept(startUserId);
65   -
66   - // 调用
67   - Set<Long> userIds = strategy.calculateUsersByActivity(null, null, param,
68   - startUserId, null, null);
69   - // 断言
70   - assertEquals(Sets.newLinkedHashSet(11L, 1001L), userIds);
71   - }
72   -
73   - private void mockGetStartUserDept(Long startUserId) {
74   - when(adminUserApi.getUser(eq(startUserId))).thenReturn(
75   - randomPojo(AdminUserRespDTO.class, o -> o.setId(startUserId).setDeptId(10L)));
76   - when(deptApi.getDept(any())).thenAnswer((Answer<DeptRespDTO>) invocationOnMock -> {
77   - Long deptId = invocationOnMock.getArgument(0);
78   - return randomPojo(DeptRespDTO.class, o -> o.setId(deptId).setParentId(deptId * 100).setLeaderUserId(deptId + 1));
79   - });
80   - }
81   -
82   -}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderStrategyTest.java deleted
1   -package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.dept;
2   -
3   -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
4   -import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
5   -import cn.iocoder.yudao.module.system.api.dept.DeptApi;
6   -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
7   -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
8   -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
9   -import org.assertj.core.util.Sets;
10   -import org.flowable.engine.delegate.DelegateExecution;
11   -import org.flowable.engine.runtime.ProcessInstance;
12   -import org.junit.jupiter.api.Test;
13   -import org.mockito.InjectMocks;
14   -import org.mockito.Mock;
15   -import org.mockito.stubbing.Answer;
16   -
17   -import java.util.Set;
18   -
19   -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
20   -import static org.junit.jupiter.api.Assertions.assertEquals;
21   -import static org.mockito.ArgumentMatchers.any;
22   -import static org.mockito.ArgumentMatchers.eq;
23   -import static org.mockito.Mockito.mock;
24   -import static org.mockito.Mockito.when;
25   -
26   -public class BpmTaskCandidateStartUserDeptLeaderStrategyTest extends BaseMockitoUnitTest {
27   -
28   - @InjectMocks
29   - private BpmTaskCandidateStartUserDeptLeaderStrategy strategy;
30   -
31   - @Mock
32   - private BpmProcessInstanceService processInstanceService;
33   -
34   - @Mock
35   - private AdminUserApi adminUserApi;
36   - @Mock
37   - private DeptApi deptApi;
38   -
39   - @Test
40   - public void testCalculateUsersByTask() {
41   - // 准备参数
42   - String param = "2";
43   - // mock 方法(获得流程发起人)
44   - Long startUserId = 1L;
45   - ProcessInstance processInstance = mock(ProcessInstance.class);
46   - DelegateExecution execution = mock(DelegateExecution.class);
47   - when(processInstanceService.getProcessInstance(eq(execution.getProcessInstanceId()))).thenReturn(processInstance);
48   - when(processInstance.getStartUserId()).thenReturn(startUserId.toString());
49   - // mock 方法(获取发起人的部门负责人)
50   - mockGetStartUserDeptLeader(startUserId);
51   -
52   - // 调用
53   - Set<Long> userIds = strategy.calculateUsersByTask(execution, param);
54   - // 断言
55   - assertEquals(Sets.newLinkedHashSet(1001L), userIds);
56   - }
57   -
58   - @Test
59   - public void testGetStartUserDeptLeader() {
60   - // 准备参数
61   - String param = "2";
62   - // mock 方法
63   - Long startUserId = 1L;
64   - mockGetStartUserDeptLeader(startUserId);
65   -
66   - // 调用
67   - Set<Long> userIds = strategy.calculateUsersByActivity(null, null, param,
68   - startUserId, null, null);
69   - // 断言
70   - assertEquals(Sets.newLinkedHashSet(1001L), userIds);
71   - }
72   -
73   - private void mockGetStartUserDeptLeader(Long startUserId) {
74   - when(adminUserApi.getUser(eq(startUserId))).thenReturn(
75   - randomPojo(AdminUserRespDTO.class, o -> o.setId(startUserId).setDeptId(10L)));
76   - when(deptApi.getDept(any())).thenAnswer((Answer<DeptRespDTO>) invocationOnMock -> {
77   - Long deptId = invocationOnMock.getArgument(0);
78   - return randomPojo(DeptRespDTO.class, o -> o.setId(deptId).setParentId(deptId * 100).setLeaderUserId(deptId + 1));
79   - });
80   - }
81   -
82   -}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserSelectStrategyTest.java deleted
1   -package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.dept;
2   -
3   -import cn.hutool.core.map.MapUtil;
4   -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
5   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants;
6   -import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
7   -import org.assertj.core.util.Sets;
8   -import org.flowable.engine.delegate.DelegateExecution;
9   -import org.flowable.engine.runtime.ProcessInstance;
10   -import org.junit.jupiter.api.Test;
11   -import org.mockito.InjectMocks;
12   -import org.mockito.Mock;
13   -
14   -import java.util.HashMap;
15   -import java.util.List;
16   -import java.util.Map;
17   -import java.util.Set;
18   -
19   -import static org.junit.jupiter.api.Assertions.assertEquals;
20   -import static org.mockito.ArgumentMatchers.eq;
21   -import static org.mockito.Mockito.mock;
22   -import static org.mockito.Mockito.when;
23   -
24   -public class BpmTaskCandidateStartUserSelectStrategyTest extends BaseMockitoUnitTest {
25   -
26   - @InjectMocks
27   - private BpmTaskCandidateStartUserSelectStrategy strategy;
28   -
29   - @Mock
30   - private BpmProcessInstanceService processInstanceService;
31   -
32   - @Test
33   - public void testCalculateUsersByTask() {
34   - // 准备参数
35   - String param = "2";
36   - // mock 方法(获得流程发起人)
37   - ProcessInstance processInstance = mock(ProcessInstance.class);
38   - DelegateExecution execution = mock(DelegateExecution.class);
39   - when(processInstanceService.getProcessInstance(eq(execution.getProcessInstanceId()))).thenReturn(processInstance);
40   - when(execution.getCurrentActivityId()).thenReturn("activity_001");
41   - // mock 方法(FlowableUtils)
42   - Map<String, Object> processVariables = new HashMap<>();
43   - processVariables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES,
44   - MapUtil.of("activity_001", List.of(1L, 2L)));
45   - when(processInstance.getProcessVariables()).thenReturn(processVariables);
46   -
47   - // 调用
48   - Set<Long> userIds = strategy.calculateUsersByTask(execution, param);
49   - // 断言
50   - assertEquals(Sets.newLinkedHashSet(1L, 2L), userIds);
51   - }
52   -
53   - @Test
54   - public void testCalculateUsersByActivity() {
55   - // 准备参数
56   - String activityId = "activity_001";
57   - Map<String, Object> processVariables = new HashMap<>();
58   - processVariables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES,
59   - MapUtil.of("activity_001", List.of(1L, 2L)));
60   -
61   - // 调用
62   - Set<Long> userIds = strategy.calculateUsersByActivity(null, activityId, null,
63   - null, null, processVariables);
64   - // 断言
65   - assertEquals(Sets.newLinkedHashSet(1L, 2L), userIds);
66   - }
67   -
68   -}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/other/BpmTaskCandidateAssignEmptyStrategyTest.java deleted
1   -package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.other;
2   -
3   -import cn.hutool.core.collection.ListUtil;
4   -import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
5   -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
6   -import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
7   -import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskAssignEmptyHandlerTypeEnum;
8   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
9   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
10   -import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
11   -import org.flowable.bpmn.model.BpmnModel;
12   -import org.flowable.bpmn.model.FlowElement;
13   -import org.flowable.engine.delegate.DelegateExecution;
14   -import org.junit.jupiter.api.Test;
15   -import org.mockito.InjectMocks;
16   -import org.mockito.Mock;
17   -import org.mockito.MockedStatic;
18   -
19   -import java.util.Set;
20   -
21   -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
22   -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
23   -import static org.junit.jupiter.api.Assertions.assertEquals;
24   -import static org.mockito.Mockito.*;
25   -
26   -public class BpmTaskCandidateAssignEmptyStrategyTest extends BaseMockitoUnitTest {
27   -
28   - @InjectMocks
29   - private BpmTaskCandidateAssignEmptyStrategy strategy;
30   -
31   - @Mock
32   - private BpmProcessDefinitionService processDefinitionService;
33   -
34   - @Test
35   - public void testCalculateUsersByTask() {
36   - try (MockedStatic<FlowableUtils> flowableUtilMockedStatic = mockStatic(FlowableUtils.class);
37   - MockedStatic<BpmnModelUtils> bpmnModelUtilsMockedStatic = mockStatic(BpmnModelUtils.class)) {
38   - // 准备参数
39   - DelegateExecution execution = mock(DelegateExecution.class);
40   - String param = randomString();
41   - // mock 方法(execution)
42   - String processDefinitionId = randomString();
43   - when(execution.getProcessDefinitionId()).thenReturn(processDefinitionId);
44   - FlowElement flowElement = mock(FlowElement.class);
45   - when(execution.getCurrentFlowElement()).thenReturn(flowElement);
46   - // mock 方法(parseAssignEmptyHandlerType)
47   - bpmnModelUtilsMockedStatic.when(() -> BpmnModelUtils.parseAssignEmptyHandlerType(same(flowElement)))
48   - .thenReturn(BpmUserTaskAssignEmptyHandlerTypeEnum.ASSIGN_USER.getType());
49   - bpmnModelUtilsMockedStatic.when(() -> BpmnModelUtils.parseAssignEmptyHandlerUserIds(same(flowElement)))
50   - .thenReturn(ListUtil.of(1L, 2L));
51   -
52   - // 调用
53   - Set<Long> userIds = strategy.calculateUsersByTask(execution, param);
54   - // 断言
55   - assertEquals(SetUtils.asSet(1L, 2L), userIds);
56   - }
57   -
58   - }
59   -
60   - @Test
61   - public void testCalculateUsersByActivity() {
62   - try (MockedStatic<BpmnModelUtils> bpmnModelUtilsMockedStatic = mockStatic(BpmnModelUtils.class)) {
63   - // 准备参数
64   - String processDefinitionId = randomString();
65   - String activityId = randomString();
66   - String param = randomString();
67   - // mock 方法(getFlowElementById)
68   - FlowElement flowElement = mock(FlowElement.class);
69   - BpmnModel bpmnModel = mock(BpmnModel.class);
70   - bpmnModelUtilsMockedStatic.when(() -> BpmnModelUtils.getFlowElementById(same(bpmnModel), eq(activityId)))
71   - .thenReturn(flowElement);
72   - // mock 方法(parseAssignEmptyHandlerType)
73   - bpmnModelUtilsMockedStatic.when(() -> BpmnModelUtils.parseAssignEmptyHandlerType(same(flowElement)))
74   - .thenReturn(BpmUserTaskAssignEmptyHandlerTypeEnum.ASSIGN_ADMIN.getType());
75   - // mock 方法(getProcessDefinitionInfo)
76   - BpmProcessDefinitionInfoDO processDefinition = randomPojo(BpmProcessDefinitionInfoDO.class,
77   - o -> o.setManagerUserIds(ListUtil.of(1L, 2L)));
78   - when(processDefinitionService.getProcessDefinitionInfo(eq(processDefinitionId))).thenReturn(processDefinition);
79   -
80   - // 调用
81   - Set<Long> userIds = strategy.calculateUsersByActivity(bpmnModel, activityId, param,
82   - null, processDefinitionId, null);
83   - // 断言
84   - assertEquals(SetUtils.asSet(1L, 2L), userIds);
85   - }
86   - }
87   -
88   -}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/other/BpmTaskCandidateExpressionStrategyTest.java deleted
1   -package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.other;
2   -
3   -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
4   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
5   -import org.flowable.engine.delegate.DelegateExecution;
6   -import org.junit.jupiter.api.Disabled;
7   -import org.junit.jupiter.api.Test;
8   -import org.mockito.InjectMocks;
9   -import org.mockito.MockedStatic;
10   -
11   -import java.util.HashMap;
12   -import java.util.Map;
13   -import java.util.Set;
14   -
15   -import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
16   -import static org.junit.jupiter.api.Assertions.assertEquals;
17   -import static org.mockito.ArgumentMatchers.eq;
18   -import static org.mockito.Mockito.*;
19   -
20   -@Disabled // TODO 芋艿:临时注释
21   -public class BpmTaskCandidateExpressionStrategyTest extends BaseMockitoUnitTest {
22   -
23   - @InjectMocks
24   - private BpmTaskCandidateExpressionStrategy strategy;
25   -
26   - @Test
27   - public void testCalculateUsersByTask() {
28   - try (MockedStatic<FlowableUtils> flowableUtilMockedStatic = mockStatic(FlowableUtils.class)) {
29   - // 准备参数
30   - String param = "1,2";
31   - DelegateExecution execution = mock(DelegateExecution.class);
32   - // mock 方法
33   - flowableUtilMockedStatic.when(() -> FlowableUtils.getExpressionValue(same(execution), eq(param)))
34   - .thenReturn(asSet(1L, 2L));
35   -
36   - // 调用
37   - Set<Long> results = strategy.calculateUsersByTask(execution, param);
38   - // 断言
39   - assertEquals(asSet(1L, 2L), results);
40   - }
41   - }
42   -
43   - @Test
44   - public void testCalculateUsersByActivity() {
45   - try (MockedStatic<FlowableUtils> flowableUtilMockedStatic = mockStatic(FlowableUtils.class)) {
46   - // 准备参数
47   - String param = "1,2";
48   - Map<String, Object> processVariables = new HashMap<>();
49   - // mock 方法
50   - flowableUtilMockedStatic.when(() -> FlowableUtils.getExpressionValue(same(processVariables), eq(param)))
51   - .thenReturn(asSet(1L, 2L));
52   -
53   - // 调用
54   - Set<Long> results = strategy.calculateUsersByActivity(null, null, param,
55   - null, null, processVariables);
56   - // 断言
57   - assertEquals(asSet(1L, 2L), results);
58   - }
59   - }
60   -
61   -}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidateGroupStrategyTest.java deleted
1   -package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.user;
2   -
3   -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
4   -import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
5   -import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService;
6   -import org.junit.jupiter.api.Disabled;
7   -import org.junit.jupiter.api.Test;
8   -import org.mockito.InjectMocks;
9   -import org.mockito.Mock;
10   -
11   -import java.util.Arrays;
12   -import java.util.Set;
13   -
14   -import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
15   -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
16   -import static org.junit.jupiter.api.Assertions.assertEquals;
17   -import static org.mockito.ArgumentMatchers.eq;
18   -import static org.mockito.Mockito.when;
19   -
20   -@Disabled // TODO 芋艿:临时注释
21   -public class BpmTaskCandidateGroupStrategyTest extends BaseMockitoUnitTest {
22   -
23   - @InjectMocks
24   - private BpmTaskCandidateGroupStrategy strategy;
25   -
26   - @Mock
27   - private BpmUserGroupService userGroupService;
28   -
29   - @Test
30   - public void testCalculateUsers() {
31   - // 准备参数
32   - String param = "1,2";
33   - // mock 方法
34   - BpmUserGroupDO userGroup1 = randomPojo(BpmUserGroupDO.class, o -> o.setUserIds(asSet(11L, 12L)));
35   - BpmUserGroupDO userGroup2 = randomPojo(BpmUserGroupDO.class, o -> o.setUserIds(asSet(21L, 22L)));
36   - when(userGroupService.getUserGroupList(eq(asSet(1L, 2L)))).thenReturn(Arrays.asList(userGroup1, userGroup2));
37   -
38   - // 调用
39   - Set<Long> userIds = strategy.calculateUsersByTask(null, param);
40   - // 断言
41   - assertEquals(asSet(11L, 12L, 21L, 22L), userIds);
42   - }
43   -
44   -}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidatePostStrategyTest.java deleted
1   -package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.user;
2   -
3   -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
4   -import cn.iocoder.yudao.module.system.api.dept.PostApi;
5   -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
6   -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
7   -import org.junit.jupiter.api.Disabled;
8   -import org.junit.jupiter.api.Test;
9   -import org.mockito.InjectMocks;
10   -import org.mockito.Mock;
11   -
12   -import java.util.List;
13   -import java.util.Set;
14   -
15   -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
16   -import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
17   -import static org.junit.jupiter.api.Assertions.assertEquals;
18   -import static org.mockito.ArgumentMatchers.eq;
19   -import static org.mockito.Mockito.when;
20   -
21   -@Disabled // TODO 芋艿:临时注释
22   -public class BpmTaskCandidatePostStrategyTest extends BaseMockitoUnitTest {
23   -
24   - @InjectMocks
25   - private BpmTaskCandidatePostStrategy strategy;
26   -
27   - @Mock
28   - private PostApi postApi;
29   - @Mock
30   - private AdminUserApi adminUserApi;
31   -
32   - @Test
33   - public void testCalculateUsers() {
34   - // 准备参数
35   - String param = "1,2";
36   - // mock 方法
37   - List<AdminUserRespDTO> users = convertList(asSet(11L, 22L),
38   - id -> new AdminUserRespDTO().setId(id));
39   - when(adminUserApi.getUserListByPostIds(eq(asSet(1L, 2L)))).thenReturn(users);
40   -
41   - // 调用
42   - Set<Long> userIds = strategy.calculateUsersByTask(null, param);
43   - // 断言
44   - assertEquals(asSet(11L, 22L), userIds);
45   - }
46   -
47   -}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidateRoleStrategyTest.java deleted
1   -package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.user;
2   -
3   -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
4   -import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
5   -import cn.iocoder.yudao.module.system.api.permission.RoleApi;
6   -import org.junit.jupiter.api.Disabled;
7   -import org.junit.jupiter.api.Test;
8   -import org.mockito.InjectMocks;
9   -import org.mockito.Mock;
10   -
11   -import java.util.Set;
12   -
13   -import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
14   -import static org.junit.jupiter.api.Assertions.assertEquals;
15   -import static org.mockito.ArgumentMatchers.eq;
16   -import static org.mockito.Mockito.when;
17   -
18   -@Disabled // TODO 芋艿:临时注释
19   -public class BpmTaskCandidateRoleStrategyTest extends BaseMockitoUnitTest {
20   -
21   - @InjectMocks
22   - private BpmTaskCandidateRoleStrategy strategy;
23   -
24   - @Mock
25   - private RoleApi roleApi;
26   - @Mock
27   - private PermissionApi permissionApi;
28   -
29   - @Test
30   - public void testCalculateUsers() {
31   - // 准备参数
32   - String param = "1,2";
33   - // mock 方法
34   - when(permissionApi.getUserRoleIdListByRoleIds(eq(asSet(1L, 2L))))
35   - .thenReturn(asSet(11L, 22L));
36   -
37   - // 调用
38   - Set<Long> userIds = strategy.calculateUsersByTask(null, param);
39   - // 断言
40   - assertEquals(asSet(11L, 22L), userIds);
41   - }
42   -
43   -}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidateStartUserStrategyTest.java deleted
1   -package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.user;
2   -
3   -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
4   -import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
5   -import org.assertj.core.util.Sets;
6   -import org.flowable.engine.delegate.DelegateExecution;
7   -import org.flowable.engine.runtime.ProcessInstance;
8   -import org.junit.jupiter.api.Test;
9   -import org.mockito.InjectMocks;
10   -import org.mockito.Mock;
11   -
12   -import java.util.Set;
13   -
14   -import static org.junit.jupiter.api.Assertions.assertEquals;
15   -import static org.mockito.ArgumentMatchers.eq;
16   -import static org.mockito.Mockito.mock;
17   -import static org.mockito.Mockito.when;
18   -
19   -public class BpmTaskCandidateStartUserStrategyTest extends BaseMockitoUnitTest {
20   -
21   - @InjectMocks
22   - private BpmTaskCandidateStartUserStrategy strategy;
23   -
24   - @Mock
25   - private BpmProcessInstanceService processInstanceService;
26   -
27   - @Test
28   - public void testCalculateUsersByTask() {
29   - // 准备参数
30   - String param = "2";
31   - // mock 方法(获得流程发起人)
32   - Long startUserId = 1L;
33   - ProcessInstance processInstance = mock(ProcessInstance.class);
34   - DelegateExecution execution = mock(DelegateExecution.class);
35   - when(processInstanceService.getProcessInstance(eq(execution.getProcessInstanceId()))).thenReturn(processInstance);
36   - when(processInstance.getStartUserId()).thenReturn(startUserId.toString());
37   -
38   - // 调用
39   - Set<Long> userIds = strategy.calculateUsersByTask(execution, param);
40   - // 断言
41   - assertEquals(Sets.newLinkedHashSet(startUserId), userIds);
42   - }
43   -
44   - @Test
45   - public void testCalculateUsersByActivity() {
46   - // 准备参数
47   - Long startUserId = 1L;
48   -
49   - // 调用
50   - Set<Long> userIds = strategy.calculateUsersByActivity(null, null, null,
51   - startUserId, null, null);
52   - // 断言
53   - assertEquals(Sets.newLinkedHashSet(startUserId), userIds);
54   - }
55   -
56   -}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/user/BpmTaskCandidateUserStrategyTest.java deleted
1   -package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.user;
2   -
3   -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
4   -import org.junit.jupiter.api.Disabled;
5   -import org.junit.jupiter.api.Test;
6   -import org.mockito.InjectMocks;
7   -
8   -import java.util.Set;
9   -
10   -import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
11   -import static org.junit.jupiter.api.Assertions.assertEquals;
12   -
13   -@Disabled // TODO 芋艿:临时注释
14   -public class BpmTaskCandidateUserStrategyTest extends BaseMockitoUnitTest {
15   -
16   - @InjectMocks
17   - private BpmTaskCandidateUserStrategy strategy;
18   -
19   - @Test
20   - public void test() {
21   - // 准备参数
22   - String param = "1,2";
23   -
24   - // 调用
25   - Set<Long> userIds = strategy.calculateUsersByTask(null, param);
26   - // 断言
27   - assertEquals(asSet(1L, 2L), userIds);
28   - }
29   -
30   -
31   -}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/category/BpmCategoryServiceImplTest.java deleted
1   -package cn.iocoder.yudao.module.bpm.service.category;
2   -
3   -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4   -import cn.iocoder.yudao.framework.common.pojo.PageResult;
5   -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
6   -import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.category.BpmCategoryPageReqVO;
7   -import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.category.BpmCategorySaveReqVO;
8   -import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO;
9   -import cn.iocoder.yudao.module.bpm.dal.mysql.category.BpmCategoryMapper;
10   -import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryServiceImpl;
11   -import jakarta.annotation.Resource;
12   -import org.junit.jupiter.api.Test;
13   -import org.springframework.context.annotation.Import;
14   -
15   -import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
16   -import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
17   -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
18   -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
19   -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
20   -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
21   -import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.CATEGORY_NOT_EXISTS;
22   -import static org.junit.jupiter.api.Assertions.*;
23   -
24   -/**
25   - * {@link BpmCategoryServiceImpl} 的单元测试类
26   - *
27   - * @author 芋道源码
28   - */
29   -@Import(BpmCategoryServiceImpl.class)
30   -public class BpmCategoryServiceImplTest extends BaseDbUnitTest {
31   -
32   - @Resource
33   - private BpmCategoryServiceImpl categoryService;
34   -
35   - @Resource
36   - private BpmCategoryMapper categoryMapper;
37   -
38   - @Test
39   - public void testCreateCategory_success() {
40   - // 准备参数
41   - BpmCategorySaveReqVO createReqVO = randomPojo(BpmCategorySaveReqVO.class).setId(null)
42   - .setStatus(randomCommonStatus());
43   -
44   - // 调用
45   - Long categoryId = categoryService.createCategory(createReqVO);
46   - // 断言
47   - assertNotNull(categoryId);
48   - // 校验记录的属性是否正确
49   - BpmCategoryDO category = categoryMapper.selectById(categoryId);
50   - assertPojoEquals(createReqVO, category, "id");
51   - }
52   -
53   - @Test
54   - public void testUpdateCategory_success() {
55   - // mock 数据
56   - BpmCategoryDO dbCategory = randomPojo(BpmCategoryDO.class);
57   - categoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据
58   - // 准备参数
59   - BpmCategorySaveReqVO updateReqVO = randomPojo(BpmCategorySaveReqVO.class, o -> {
60   - o.setId(dbCategory.getId()); // 设置更新的 ID
61   - o.setStatus(randomCommonStatus());
62   - });
63   -
64   - // 调用
65   - categoryService.updateCategory(updateReqVO);
66   - // 校验是否更新正确
67   - BpmCategoryDO category = categoryMapper.selectById(updateReqVO.getId()); // 获取最新的
68   - assertPojoEquals(updateReqVO, category);
69   - }
70   -
71   - @Test
72   - public void testUpdateCategory_notExists() {
73   - // 准备参数
74   - BpmCategorySaveReqVO updateReqVO = randomPojo(BpmCategorySaveReqVO.class);
75   -
76   - // 调用, 并断言异常
77   - assertServiceException(() -> categoryService.updateCategory(updateReqVO), CATEGORY_NOT_EXISTS);
78   - }
79   -
80   - @Test
81   - public void testDeleteCategory_success() {
82   - // mock 数据
83   - BpmCategoryDO dbCategory = randomPojo(BpmCategoryDO.class);
84   - categoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据
85   - // 准备参数
86   - Long id = dbCategory.getId();
87   -
88   - // 调用
89   - categoryService.deleteCategory(id);
90   - // 校验数据不存在了
91   - assertNull(categoryMapper.selectById(id));
92   - }
93   -
94   - @Test
95   - public void testDeleteCategory_notExists() {
96   - // 准备参数
97   - Long id = randomLongId();
98   -
99   - // 调用, 并断言异常
100   - assertServiceException(() -> categoryService.deleteCategory(id), CATEGORY_NOT_EXISTS);
101   - }
102   -
103   - @Test
104   - public void testGetCategoryPage() {
105   - // mock 数据
106   - BpmCategoryDO dbCategory = randomPojo(BpmCategoryDO.class, o -> { // 等会查询到
107   - o.setName("芋头");
108   - o.setCode("xiaodun");
109   - o.setStatus(CommonStatusEnum.ENABLE.getStatus());
110   - o.setCreateTime(buildTime(2023, 2, 2));
111   - });
112   - categoryMapper.insert(dbCategory);
113   - // 测试 name 不匹配
114   - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setName("小盾")));
115   - // 测试 code 不匹配
116   - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setCode("tudou")));
117   - // 测试 status 不匹配
118   - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
119   - // 测试 createTime 不匹配
120   - categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setCreateTime(buildTime(2024, 2, 2))));
121   - // 准备参数
122   - BpmCategoryPageReqVO reqVO = new BpmCategoryPageReqVO();
123   - reqVO.setName("芋");
124   - reqVO.setCode("xiao");
125   - reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
126   - reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
127   -
128   - // 调用
129   - PageResult<BpmCategoryDO> pageResult = categoryService.getCategoryPage(reqVO);
130   - // 断言
131   - assertEquals(1, pageResult.getTotal());
132   - assertEquals(1, pageResult.getList().size());
133   - assertPojoEquals(dbCategory, pageResult.getList().get(0));
134   - }
135   -
136   -}
137 0 \ No newline at end of file
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmFormServiceTest.java deleted
1   -package cn.iocoder.yudao.module.bpm.service.definition;
2   -
3   -import cn.hutool.core.util.RandomUtil;
4   -import cn.iocoder.yudao.framework.common.pojo.PageResult;
5   -import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
6   -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
7   -import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormSaveReqVO;
8   -import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.form.BpmFormPageReqVO;
9   -import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
10   -import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmFormMapper;
11   -import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmFormFieldRespDTO;
12   -import org.junit.jupiter.api.Test;
13   -import org.springframework.context.annotation.Import;
14   -
15   -import jakarta.annotation.Resource;
16   -import java.util.List;
17   -import java.util.stream.Collectors;
18   -import java.util.stream.Stream;
19   -
20   -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
21   -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
22   -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
23   -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
24   -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
25   -import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.FORM_NOT_EXISTS;
26   -import static org.junit.jupiter.api.Assertions.*;
27   -
28   -/**
29   - * {@link BpmFormServiceImpl} 的单元测试类
30   - *
31   - * @author 芋道源码
32   - */
33   -@Import(BpmFormServiceImpl.class)
34   -public class BpmFormServiceTest extends BaseDbUnitTest {
35   -
36   - @Resource
37   - private BpmFormServiceImpl formService;
38   -
39   - @Resource
40   - private BpmFormMapper formMapper;
41   -
42   - @Test
43   - public void testCreateForm_success() {
44   - // 准备参数
45   - BpmFormSaveReqVO reqVO = randomPojo(BpmFormSaveReqVO.class, o -> {
46   - o.setConf("{}");
47   - o.setFields(randomFields());
48   - });
49   -
50   - // 调用
51   - Long formId = formService.createForm(reqVO);
52   - // 断言
53   - assertNotNull(formId);
54   - // 校验记录的属性是否正确
55   - BpmFormDO form = formMapper.selectById(formId);
56   - assertPojoEquals(reqVO, form);
57   - }
58   -
59   - @Test
60   - public void testUpdateForm_success() {
61   - // mock 数据
62   - BpmFormDO dbForm = randomPojo(BpmFormDO.class, o -> {
63   - o.setConf("{}");
64   - o.setFields(randomFields());
65   - });
66   - formMapper.insert(dbForm);// @Sql: 先插入出一条存在的数据
67   - // 准备参数
68   - BpmFormSaveReqVO reqVO = randomPojo(BpmFormSaveReqVO.class, o -> {
69   - o.setId(dbForm.getId()); // 设置更新的 ID
70   - o.setConf("{'yudao': 'yuanma'}");
71   - o.setFields(randomFields());
72   - });
73   -
74   - // 调用
75   - formService.updateForm(reqVO);
76   - // 校验是否更新正确
77   - BpmFormDO form = formMapper.selectById(reqVO.getId()); // 获取最新的
78   - assertPojoEquals(reqVO, form);
79   - }
80   -
81   - @Test
82   - public void testUpdateForm_notExists() {
83   - // 准备参数
84   - BpmFormSaveReqVO reqVO = randomPojo(BpmFormSaveReqVO.class, o -> {
85   - o.setConf("{'yudao': 'yuanma'}");
86   - o.setFields(randomFields());
87   - });
88   -
89   - // 调用, 并断言异常
90   - assertServiceException(() -> formService.updateForm(reqVO), FORM_NOT_EXISTS);
91   - }
92   -
93   - @Test
94   - public void testDeleteForm_success() {
95   - // mock 数据
96   - BpmFormDO dbForm = randomPojo(BpmFormDO.class);
97   - formMapper.insert(dbForm);// @Sql: 先插入出一条存在的数据
98   - // 准备参数
99   - Long id = dbForm.getId();
100   -
101   - // 调用
102   - formService.deleteForm(id);
103   - // 校验数据不存在了
104   - assertNull(formMapper.selectById(id));
105   - }
106   -
107   - @Test
108   - public void testDeleteForm_notExists() {
109   - // 准备参数
110   - Long id = randomLongId();
111   -
112   - // 调用, 并断言异常
113   - assertServiceException(() -> formService.deleteForm(id), FORM_NOT_EXISTS);
114   - }
115   -
116   - @Test
117   - public void testGetFormPage() {
118   - // mock 数据
119   - BpmFormDO dbForm = randomPojo(BpmFormDO.class, o -> { // 等会查询到
120   - o.setName("芋道源码");
121   - });
122   - formMapper.insert(dbForm);
123   - // 测试 name 不匹配
124   - formMapper.insert(cloneIgnoreId(dbForm, o -> o.setName("源码")));
125   - // 准备参数
126   - BpmFormPageReqVO reqVO = new BpmFormPageReqVO();
127   - reqVO.setName("芋道");
128   -
129   - // 调用
130   - PageResult<BpmFormDO> pageResult = formService.getFormPage(reqVO);
131   - // 断言
132   - assertEquals(1, pageResult.getTotal());
133   - assertEquals(1, pageResult.getList().size());
134   - assertPojoEquals(dbForm, pageResult.getList().get(0));
135   - }
136   -
137   - private List<String> randomFields() {
138   - int size = RandomUtil.randomInt(1, 3);
139   - return Stream.iterate(0, i -> i).limit(size)
140   - .map(i -> JsonUtils.toJsonString(randomPojo(BpmFormFieldRespDTO.class)))
141   - .collect(Collectors.toList());
142   - }
143   -
144   -}
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java deleted
1   -package cn.iocoder.yudao.module.bpm.service.definition;
2   -
3   -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4   -import cn.iocoder.yudao.framework.common.pojo.PageResult;
5   -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
6   -import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
7   -import cn.iocoder.yudao.framework.test.core.util.RandomUtils;
8   -import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupSaveReqVO;
9   -import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.group.BpmUserGroupPageReqVO;
10   -import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
11   -import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmUserGroupMapper;
12   -import org.junit.jupiter.api.Assertions;
13   -import org.junit.jupiter.api.Test;
14   -import org.springframework.context.annotation.Import;
15   -
16   -import jakarta.annotation.Resource;
17   -
18   -import java.time.LocalDateTime;
19   -
20   -import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
21   -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
22   -import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.USER_GROUP_NOT_EXISTS;
23   -
24   -/**
25   - * {@link BpmUserGroupServiceImpl} 的单元测试类
26   - *
27   - * @author 芋道源码
28   - */
29   -@Import(BpmUserGroupServiceImpl.class)
30   -public class BpmUserGroupServiceTest extends BaseDbUnitTest {
31   -
32   - @Resource
33   - private BpmUserGroupServiceImpl userGroupService;
34   -
35   - @Resource
36   - private BpmUserGroupMapper userGroupMapper;
37   -
38   - @Test
39   - public void testCreateUserGroup_success() {
40   - // 准备参数
41   - BpmUserGroupSaveReqVO reqVO = RandomUtils.randomPojo(BpmUserGroupSaveReqVO.class);
42   -
43   - // 调用
44   - Long userGroupId = userGroupService.createUserGroup(reqVO);
45   - // 断言
46   - Assertions.assertNotNull(userGroupId);
47   - // 校验记录的属性是否正确
48   - BpmUserGroupDO userGroup = userGroupMapper.selectById(userGroupId);
49   - AssertUtils.assertPojoEquals(reqVO, userGroup);
50   - }
51   -
52   - @Test
53   - public void testUpdateUserGroup_success() {
54   - // mock 数据
55   - BpmUserGroupDO dbUserGroup = RandomUtils.randomPojo(BpmUserGroupDO.class);
56   - userGroupMapper.insert(dbUserGroup);// @Sql: 先插入出一条存在的数据
57   - // 准备参数
58   - BpmUserGroupSaveReqVO reqVO = RandomUtils.randomPojo(BpmUserGroupSaveReqVO.class, o -> {
59   - o.setId(dbUserGroup.getId()); // 设置更新的 ID
60   - });
61   -
62   - // 调用
63   - userGroupService.updateUserGroup(reqVO);
64   - // 校验是否更新正确
65   - BpmUserGroupDO userGroup = userGroupMapper.selectById(reqVO.getId()); // 获取最新的
66   - AssertUtils.assertPojoEquals(reqVO, userGroup);
67   - }
68   -
69   - @Test
70   - public void testUpdateUserGroup_notExists() {
71   - // 准备参数
72   - BpmUserGroupSaveReqVO reqVO = RandomUtils.randomPojo(BpmUserGroupSaveReqVO.class);
73   -
74   - // 调用, 并断言异常
75   - AssertUtils.assertServiceException(() -> userGroupService.updateUserGroup(reqVO), USER_GROUP_NOT_EXISTS);
76   - }
77   -
78   - @Test
79   - public void testDeleteUserGroup_success() {
80   - // mock 数据
81   - BpmUserGroupDO dbUserGroup = RandomUtils.randomPojo(BpmUserGroupDO.class);
82   - userGroupMapper.insert(dbUserGroup);// @Sql: 先插入出一条存在的数据
83   - // 准备参数
84   - Long id = dbUserGroup.getId();
85   -
86   - // 调用
87   - userGroupService.deleteUserGroup(id);
88   - // 校验数据不存在了
89   - Assertions.assertNull(userGroupMapper.selectById(id));
90   - }
91   -
92   - @Test
93   - public void testDeleteUserGroup_notExists() {
94   - // 准备参数
95   - Long id = RandomUtils.randomLongId();
96   -
97   - // 调用, 并断言异常
98   - AssertUtils.assertServiceException(() -> userGroupService.deleteUserGroup(id), USER_GROUP_NOT_EXISTS);
99   - }
100   -
101   - @Test
102   - public void testGetUserGroupPage() {
103   - // mock 数据
104   - BpmUserGroupDO dbUserGroup = RandomUtils.randomPojo(BpmUserGroupDO.class, o -> { // 等会查询到
105   - o.setName("芋道源码");
106   - o.setStatus(CommonStatusEnum.ENABLE.getStatus());
107   - o.setCreateTime(buildTime(2021, 11, 11));
108   - });
109   - userGroupMapper.insert(dbUserGroup);
110   - // 测试 name 不匹配
111   - userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setName("芋道")));
112   - // 测试 status 不匹配
113   - userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
114   - // 测试 createTime 不匹配
115   - userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setCreateTime(buildTime(2021, 12, 12))));
116   - // 准备参数
117   - BpmUserGroupPageReqVO reqVO = new BpmUserGroupPageReqVO();
118   - reqVO.setName("源码");
119   - reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
120   - reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 11, 10),buildTime(2021, 11, 12)}));
121   -
122   - // 调用
123   - PageResult<BpmUserGroupDO> pageResult = userGroupService.getUserGroupPage(reqVO);
124   - // 断言
125   - Assertions.assertEquals(1, pageResult.getTotal());
126   - Assertions.assertEquals(1, pageResult.getList().size());
127   - AssertUtils.assertPojoEquals(dbUserGroup, pageResult.getList().get(0));
128   - }
129   -
130   -}
yudao-module-bpm/yudao-module-bpm-biz/src/test/resources/application-unit-test.yaml deleted
1   -spring:
2   - main:
3   - lazy-initialization: true # 开启懒加载,加快速度
4   - banner-mode: off # 单元测试,禁用 Banner
5   -
6   ---- #################### 数据库相关配置 ####################
7   -
8   -spring:
9   - # 数据源配置项
10   - datasource:
11   - name: ruoyi-vue-pro
12   - url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写
13   - driver-class-name: org.h2.Driver
14   - username: sa
15   - password:
16   - druid:
17   - async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度
18   - initial-size: 1 # 单元测试,配置为 1,提升启动速度
19   - sql:
20   - init:
21   - schema-locations: classpath:/sql/create_tables.sql
22   -
23   -mybatis-plus:
24   - lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
25   - type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject
26   -
27   ---- #################### 定时任务相关配置 ####################
28   -
29   ---- #################### 配置中心相关配置 ####################
30   -
31   ---- #################### 服务保障相关配置 ####################
32   -
33   -# Lock4j 配置项(单元测试,禁用 Lock4j)
34   -
35   ---- #################### 监控相关配置 ####################
36   -
37   ---- #################### 芋道相关配置 ####################
38   -
39   -# 芋道配置项,设置当前项目所有自定义的配置
40   -yudao:
41   - info:
42   - base-package: cn.iocoder.yudao.module
yudao-module-bpm/yudao-module-bpm-biz/src/test/resources/sql/create_tables.sql deleted
1   -CREATE TABLE IF NOT EXISTS "bpm_user_group" (
2   - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
3   - "name" varchar(63) NOT NULL,
4   - "description" varchar(255) NOT NULL,
5   - "status" tinyint NOT NULL,
6   - "user_ids" varchar(255) NOT NULL,
7   - "creator" varchar(64) DEFAULT '',
8   - "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
9   - "updater" varchar(64) DEFAULT '',
10   - "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
11   - "deleted" bit NOT NULL DEFAULT FALSE,
12   - PRIMARY KEY ("id")
13   -) COMMENT '用户组';
14   -
15   -CREATE TABLE IF NOT EXISTS "bpm_category" (
16   - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
17   - "name" varchar(63) NOT NULL,
18   - "code" varchar(63) NOT NULL,
19   - "description" varchar(255) NOT NULL,
20   - "status" tinyint NOT NULL,
21   - "sort" int NOT NULL,
22   - "creator" varchar(64) DEFAULT '',
23   - "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
24   - "updater" varchar(64) DEFAULT '',
25   - "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
26   - "deleted" bit NOT NULL DEFAULT FALSE,
27   - PRIMARY KEY ("id")
28   -) COMMENT '分类';
29   -
30   -CREATE TABLE IF NOT EXISTS "bpm_form" (
31   - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
32   - "name" varchar(63) NOT NULL,
33   - "status" tinyint NOT NULL,
34   - "fields" varchar(255) NOT NULL,
35   - "conf" varchar(255) NOT NULL,
36   - "remark" varchar(255),
37   - "creator" varchar(64) DEFAULT '',
38   - "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
39   - "updater" varchar(64) DEFAULT '',
40   - "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
41   - "deleted" bit NOT NULL DEFAULT FALSE,
42   - PRIMARY KEY ("id")
43   -) COMMENT '动态表单';