Commit a5dc4e787654b1adac667ca29cb995f4cb703f94
Committed by
Gitee
!839 流程增加抄送功能
Merge pull request !839 from 云开/feature/BPM_CC_develop
Showing
31 changed files
with
1966 additions
and
2 deletions
sql/mysql/ruoyi-vue-pro.sql
| ... | ... | @@ -2479,6 +2479,15 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i |
| 2479 | 2479 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2523, '客户限制配置导出', 'crm:customer-limit-config:export', 3, 5, 2518, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-18 13:33:53', '', '2023-11-18 13:33:53', b'0'); |
| 2480 | 2480 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2524, '系统配置', '', 1, 99, 2397, 'config', 'ep:connection', '', '', 0, b'1', b'1', b'1', '1', '2023-11-18 21:58:00', '1', '2023-11-18 21:58:00', b'0'); |
| 2481 | 2481 | INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2525, 'WebSocket 测试', '', 2, 7, 2, 'websocket', 'ep:connection', 'infra/webSocket/index', 'InfraWebSocket', 0, b'1', b'1', b'1', '1', '2023-11-23 19:41:55', '1', '2023-11-24 19:22:30', b'0'); |
| 2482 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, | |
| 2483 | + `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, | |
| 2484 | + `updater`, `update_time`, `deleted`) | |
| 2485 | +VALUES (2526, '抄送流程', '', 2, 21, 1200, 'processInstanceCC', 'eye', '/bpm/task/cc/index', | |
| 2486 | + 'BpmCCProcessInstance', 0, true, true, true, 1, '2023-01-13 16:14:00', '1', '2023-01-13 16:14:00', false), | |
| 2487 | + (2527, '抄送流程查询', 'bpm:process-instance-cc:query', 3, 1, 2526, '', '', '', NULL, 0, b'1', b'1', b'1', '1', | |
| 2488 | + '2023-01-13 16:14:00', '1', '2023-01-13 16:14:00', b'0'), | |
| 2489 | + (2528, '抄送流程创建', 'bpm:process-instance-cc:create', 3, 2, 2526, '', '', '', NULL, 0, b'1', b'1', b'1', '1', | |
| 2490 | + '2023-01-13 16:14:00', '1', '2023-01-13 16:14:00', b'0'); | |
| 2482 | 2491 | COMMIT; |
| 2483 | 2492 | |
| 2484 | 2493 | -- ---------------------------- | ... | ... |
yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java
| ... | ... | @@ -17,8 +17,8 @@ public class YudaoFlowableConfiguration { |
| 17 | 17 | * |
| 18 | 18 | * 如果不创建,会导致项目启动时,Flowable 报错的问题 |
| 19 | 19 | */ |
| 20 | - @Bean | |
| 21 | - @ConditionalOnMissingBean | |
| 20 | + @Bean(name = "applicationTaskExecutor") | |
| 21 | + @ConditionalOnMissingBean(name = "applicationTaskExecutor") | |
| 22 | 22 | public AsyncListenableTaskExecutor taskExecutor() { |
| 23 | 23 | ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); |
| 24 | 24 | executor.setCorePoolSize(8); | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/candidate/vo/BpmTaskCandidateRuleVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.rule.BpmTaskAssignRuleBaseVO; | |
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 5 | +import jakarta.validation.constraints.NotNull; | |
| 6 | +import lombok.Data; | |
| 7 | + | |
| 8 | +import java.util.Set; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 流程任务分配规则 Base VO,提供给添加、修改、详细的子 VO 使用 | |
| 12 | + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | |
| 13 | + * | |
| 14 | + * @see BpmTaskAssignRuleBaseVO | |
| 15 | + */ | |
| 16 | +@Data | |
| 17 | +public class BpmTaskCandidateRuleVO { | |
| 18 | + | |
| 19 | + @Schema(description = "规则类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "bpm_task_assign_rule_type") | |
| 20 | + @NotNull(message = "规则类型不能为空") | |
| 21 | + private Integer type; | |
| 22 | + | |
| 23 | + @Schema(description = "规则值数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1,2,3") | |
| 24 | + @NotNull(message = "规则值数组不能为空") | |
| 25 | + private Set<Long> options; | |
| 26 | + | |
| 27 | +} | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java
| ... | ... | @@ -2,7 +2,9 @@ package cn.iocoder.yudao.module.bpm.controller.admin.task; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; | |
| 5 | 6 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; |
| 7 | +import cn.iocoder.yudao.module.bpm.service.cc.BpmProcessInstanceCopyService; | |
| 6 | 8 | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; |
| 7 | 9 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 8 | 10 | import io.swagger.v3.oas.annotations.Parameter; |
| ... | ... | @@ -26,6 +28,9 @@ public class BpmProcessInstanceController { |
| 26 | 28 | @Resource |
| 27 | 29 | private BpmProcessInstanceService processInstanceService; |
| 28 | 30 | |
| 31 | + @Resource | |
| 32 | + private BpmProcessInstanceCopyService processInstanceCopyService; | |
| 33 | + | |
| 29 | 34 | @GetMapping("/my-page") |
| 30 | 35 | @Operation(summary = "获得我的实例分页列表", description = "在【我的流程】菜单中,进行调用") |
| 31 | 36 | @PreAuthorize("@ss.hasPermission('bpm:process-instance:query')") |
| ... | ... | @@ -56,4 +61,20 @@ public class BpmProcessInstanceController { |
| 56 | 61 | processInstanceService.cancelProcessInstance(getLoginUserId(), cancelReqVO); |
| 57 | 62 | return success(true); |
| 58 | 63 | } |
| 64 | + | |
| 65 | + | |
| 66 | + @PostMapping("/cc/create") | |
| 67 | + @Operation(summary = "抄送流程") | |
| 68 | + @PreAuthorize("@ss.hasPermission('bpm:process-instance-cc:create')") | |
| 69 | + public CommonResult<Boolean> createProcessInstanceCC(@Valid @RequestBody BpmProcessInstanceCCReqVO createReqVO) { | |
| 70 | + return success(processInstanceCopyService.ccProcessInstance(SecurityFrameworkUtils.getLoginUserId(), createReqVO)); | |
| 71 | + } | |
| 72 | + | |
| 73 | + @GetMapping("/cc/my-page") | |
| 74 | + @Operation(summary = "获得抄送流程分页列表") | |
| 75 | + @PreAuthorize("@ss.hasPermission('bpm:process-instance-cc:query')") | |
| 76 | + public CommonResult<PageResult<BpmProcessInstanceCCPageItemRespVO>> getProcessInstanceCCPage(@Valid BpmProcessInstanceCCMyPageReqVO pageReqVO) { | |
| 77 | + return success(processInstanceCopyService.getMyProcessInstanceCCPage(SecurityFrameworkUtils.getLoginUserId(), pageReqVO)); | |
| 78 | + } | |
| 79 | + | |
| 59 | 80 | } | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCCMyPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.EqualsAndHashCode; | |
| 7 | +import lombok.ToString; | |
| 8 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 9 | + | |
| 10 | +import java.time.LocalDateTime; | |
| 11 | + | |
| 12 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 13 | + | |
| 14 | +@Schema(description = "管理后台 - 流程实例抄送的分页 Item Response VO") | |
| 15 | +@Data | |
| 16 | +@EqualsAndHashCode(callSuper = true) | |
| 17 | +@ToString(callSuper = true) | |
| 18 | +public class BpmProcessInstanceCCMyPageReqVO extends PageParam { | |
| 19 | + | |
| 20 | + @Schema(description = "流程名称", example = "芋道") | |
| 21 | + private String processInstanceName; | |
| 22 | + | |
| 23 | + @Schema(description = "流程编号", example = "123456768") | |
| 24 | + private String processInstanceId; | |
| 25 | + | |
| 26 | + @Schema(description = "创建时间") | |
| 27 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 28 | + private LocalDateTime[] createTime; | |
| 29 | + | |
| 30 | +} | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCCPageItemRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.Data; | |
| 5 | + | |
| 6 | +import java.time.LocalDateTime; | |
| 7 | + | |
| 8 | +@Schema(description = "管理后台 - 流程实例抄送的分页 Item Response VO") | |
| 9 | +@Data | |
| 10 | +public class BpmProcessInstanceCCPageItemRespVO { | |
| 11 | + | |
| 12 | + /** | |
| 13 | + * 编号 | |
| 14 | + */ | |
| 15 | + @Schema(description = "抄送主键") | |
| 16 | + private Long id; | |
| 17 | + | |
| 18 | + /** | |
| 19 | + * 发起人Id | |
| 20 | + */ | |
| 21 | + @Schema(description = "发起人Id") | |
| 22 | + private Long startUserId; | |
| 23 | + | |
| 24 | + @Schema(description = "发起人别名") | |
| 25 | + private String startUserNickname; | |
| 26 | + | |
| 27 | + /** | |
| 28 | + * 流程主键 | |
| 29 | + */ | |
| 30 | + @Schema(description = "流程实例的主键") | |
| 31 | + private String processInstanceId; | |
| 32 | + | |
| 33 | + @Schema(description = "流程实例的名称") | |
| 34 | + private String processInstanceName; | |
| 35 | + /** | |
| 36 | + * 任务主键 | |
| 37 | + */ | |
| 38 | + @Schema(description = "发起抄送的任务编号") | |
| 39 | + private String taskId; | |
| 40 | + | |
| 41 | + @Schema(description = "发起抄送的任务名称") | |
| 42 | + private String taskName; | |
| 43 | + | |
| 44 | + @Schema(description = "抄送原因") | |
| 45 | + private String reason; | |
| 46 | + | |
| 47 | + @Schema(description = "抄送人") | |
| 48 | + private String creator; | |
| 49 | + | |
| 50 | + @Schema(description = "抄送人别名") | |
| 51 | + private String creatorNickname; | |
| 52 | + | |
| 53 | + @Schema(description = "抄送时间") | |
| 54 | + private LocalDateTime createTime; | |
| 55 | +} | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCCReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO; | |
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 5 | +import jakarta.validation.constraints.NotBlank; | |
| 6 | +import jakarta.validation.constraints.NotEmpty; | |
| 7 | +import jakarta.validation.constraints.NotNull; | |
| 8 | +import lombok.Data; | |
| 9 | +import lombok.EqualsAndHashCode; | |
| 10 | +import lombok.ToString; | |
| 11 | + | |
| 12 | +import java.util.Set; | |
| 13 | + | |
| 14 | +@Schema(description = "管理后台 - 流程实例的抄送 Request VO") | |
| 15 | +@Data | |
| 16 | +@EqualsAndHashCode(callSuper = true) | |
| 17 | +@ToString(callSuper = true) | |
| 18 | +public class BpmProcessInstanceCCReqVO extends BpmTaskCandidateRuleVO { | |
| 19 | + | |
| 20 | + @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 21 | + @NotEmpty(message = "任务编号不能为空") | |
| 22 | + private String taskKey; | |
| 23 | + | |
| 24 | + @Schema(description = "任务名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 25 | + @NotEmpty(message = "任务名称不能为空") | |
| 26 | + private String taskName; | |
| 27 | + | |
| 28 | + @Schema(description = "流程实例的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 29 | + @NotEmpty(message = "流程实例的编号不能为空") | |
| 30 | + private String processInstanceKey; | |
| 31 | + | |
| 32 | + @Schema(description = "发起流程的用户的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 33 | + @NotNull(message = "发起流程的用户的编号不能为空") | |
| 34 | + private Long startUserId; | |
| 35 | + | |
| 36 | + | |
| 37 | + @Schema(description = "任务实例名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 38 | + @NotEmpty(message = "任务实例名称不能为空") | |
| 39 | + private String processInstanceName; | |
| 40 | + | |
| 41 | + @Schema(description = "抄送原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "请帮忙审查下!") | |
| 42 | + @NotBlank(message = "抄送原因不能为空") | |
| 43 | + private String reason; | |
| 44 | +} | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/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/convert/cc/BpmProcessInstanceCopyConvert.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.convert.cc; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 4 | +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | |
| 5 | +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCCPageItemRespVO; | |
| 6 | +import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO; | |
| 7 | +import cn.iocoder.yudao.module.bpm.service.cc.BpmProcessInstanceCopyVO; | |
| 8 | +import org.mapstruct.Mapper; | |
| 9 | +import org.mapstruct.factory.Mappers; | |
| 10 | + | |
| 11 | +import java.util.List; | |
| 12 | +import java.util.Map; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * 动态表单 Convert | |
| 16 | + * | |
| 17 | + * @author 芋艿 | |
| 18 | + */ | |
| 19 | +@Mapper | |
| 20 | +public interface BpmProcessInstanceCopyConvert { | |
| 21 | + | |
| 22 | + BpmProcessInstanceCopyConvert INSTANCE = Mappers.getMapper(BpmProcessInstanceCopyConvert.class); | |
| 23 | + | |
| 24 | + BpmProcessInstanceCopyDO copy(BpmProcessInstanceCopyDO bean); | |
| 25 | + | |
| 26 | + BpmProcessInstanceCopyVO convert(BpmProcessInstanceCopyDO bean); | |
| 27 | + | |
| 28 | + List<BpmProcessInstanceCopyVO> convertList2(List<BpmProcessInstanceCopyDO> list); | |
| 29 | + | |
| 30 | + List<BpmProcessInstanceCCPageItemRespVO> convertList(List<BpmProcessInstanceCopyDO> list); | |
| 31 | + | |
| 32 | + default PageResult<BpmProcessInstanceCCPageItemRespVO> convertPage(PageResult<BpmProcessInstanceCopyDO> page | |
| 33 | + , Map<String/* taskId */, String/* taskName */> taskMap | |
| 34 | + , Map<String/* processInstaneId */, String/* processInstaneName */> processInstaneMap | |
| 35 | + , Map<Long/* userId */, String/* userName */> userMap | |
| 36 | + ) { | |
| 37 | + List<BpmProcessInstanceCCPageItemRespVO> list = convertList(page.getList()); | |
| 38 | + for (BpmProcessInstanceCCPageItemRespVO vo : list) { | |
| 39 | + MapUtils.findAndThen(userMap, Long.valueOf(vo.getCreator()), | |
| 40 | + vo::setCreatorNickname); | |
| 41 | + MapUtils.findAndThen(userMap, vo.getStartUserId(), | |
| 42 | + vo::setStartUserNickname); | |
| 43 | + MapUtils.findAndThen(taskMap, vo.getTaskId(), | |
| 44 | + vo::setTaskName); | |
| 45 | + MapUtils.findAndThen(processInstaneMap, vo.getProcessInstanceId(), | |
| 46 | + vo::setProcessInstanceName); | |
| 47 | + } | |
| 48 | + return new PageResult<>(list, page.getTotal()); | |
| 49 | + } | |
| 50 | + | |
| 51 | +} | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/cc/BpmProcessInstanceCopyDO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.dal.dataobject.cc; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | |
| 4 | +import com.baomidou.mybatisplus.annotation.TableId; | |
| 5 | +import com.baomidou.mybatisplus.annotation.TableName; | |
| 6 | +import lombok.*; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * 流程抄送对象 | |
| 10 | + * | |
| 11 | + * @author kyle | |
| 12 | + * @date 2022-05-19 | |
| 13 | + */ | |
| 14 | +@TableName(value = "bpm_process_instance_copy", autoResultMap = true) | |
| 15 | +@Data | |
| 16 | +@EqualsAndHashCode(callSuper = true) | |
| 17 | +@ToString(callSuper = true) | |
| 18 | +@Builder | |
| 19 | +@NoArgsConstructor | |
| 20 | +@AllArgsConstructor | |
| 21 | +public class BpmProcessInstanceCopyDO extends BaseDO { | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 编号 | |
| 25 | + */ | |
| 26 | + @TableId | |
| 27 | + private Long id; | |
| 28 | + | |
| 29 | + /** | |
| 30 | + * 发起人Id | |
| 31 | + */ | |
| 32 | + private Long startUserId; | |
| 33 | + /** | |
| 34 | + * 流程名 | |
| 35 | + */ | |
| 36 | + private String processInstanceName; | |
| 37 | + /** | |
| 38 | + * 流程主键 | |
| 39 | + */ | |
| 40 | + private String processInstanceId; | |
| 41 | + | |
| 42 | + /** | |
| 43 | + * 任务主键 | |
| 44 | + */ | |
| 45 | + private String taskId; | |
| 46 | + | |
| 47 | + /** | |
| 48 | + * 任务名称 | |
| 49 | + */ | |
| 50 | + private String taskName; | |
| 51 | + | |
| 52 | + /** | |
| 53 | + * 用户主键 | |
| 54 | + */ | |
| 55 | + private Long userId; | |
| 56 | + | |
| 57 | + /** | |
| 58 | + * 抄送原因 | |
| 59 | + */ | |
| 60 | + private String reason; | |
| 61 | + | |
| 62 | + /** | |
| 63 | + * 流程分类 | |
| 64 | + */ | |
| 65 | + private String processDefinitionCategory; | |
| 66 | + | |
| 67 | +} | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/cc/BpmProcessInstanceCopyMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.dal.mysql.cc; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | |
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 6 | +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCCMyPageReqVO; | |
| 7 | +import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO; | |
| 8 | +import org.apache.ibatis.annotations.Mapper; | |
| 9 | + | |
| 10 | +@Mapper | |
| 11 | +public interface BpmProcessInstanceCopyMapper extends BaseMapperX<BpmProcessInstanceCopyDO> { | |
| 12 | + default PageResult<BpmProcessInstanceCopyDO> selectPage(Long loginUserId, BpmProcessInstanceCCMyPageReqVO reqVO){ | |
| 13 | + return selectPage(reqVO, new LambdaQueryWrapperX<BpmProcessInstanceCopyDO>() | |
| 14 | + .eqIfPresent(BpmProcessInstanceCopyDO::getUserId, loginUserId) | |
| 15 | + .eqIfPresent(BpmProcessInstanceCopyDO::getProcessInstanceId, reqVO.getProcessInstanceId()) | |
| 16 | + .likeIfPresent(BpmProcessInstanceCopyDO::getProcessInstanceName, reqVO.getProcessInstanceName()) | |
| 17 | + .betweenIfPresent(BpmProcessInstanceCopyDO::getCreateTime, reqVO.getCreateTime()) | |
| 18 | + .orderByDesc(BpmProcessInstanceCopyDO::getId)); | |
| 19 | + } | |
| 20 | +} | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/config/BpmCandidateProcessorConfiguration.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.framework.bpm.config; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript; | |
| 4 | +import cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor.*; | |
| 5 | +import org.springframework.beans.factory.ObjectProvider; | |
| 6 | +import org.springframework.context.annotation.Bean; | |
| 7 | +import org.springframework.context.annotation.Configuration; | |
| 8 | + | |
| 9 | +import java.util.List; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * BPM 通用的 Configuration 配置类,提供给 Activiti 和 Flowable | |
| 13 | + * @author kyle | |
| 14 | + */ | |
| 15 | +@Configuration(proxyBeanMethods = false) | |
| 16 | +public class BpmCandidateProcessorConfiguration { | |
| 17 | + @Bean | |
| 18 | + public BpmCandidateAdminUserApiSourceInfoProcessor bpmCandidateAdminUserApiSourceInfoProcessor() { | |
| 19 | + return new BpmCandidateAdminUserApiSourceInfoProcessor(); | |
| 20 | + } | |
| 21 | + | |
| 22 | + @Bean | |
| 23 | + public BpmCandidateDeptApiSourceInfoProcessor bpmCandidateDeptApiSourceInfoProcessor() { | |
| 24 | + return new BpmCandidateDeptApiSourceInfoProcessor(); | |
| 25 | + } | |
| 26 | + | |
| 27 | + @Bean | |
| 28 | + public BpmCandidatePostApiSourceInfoProcessor bpmCandidatePostApiSourceInfoProcessor() { | |
| 29 | + return new BpmCandidatePostApiSourceInfoProcessor(); | |
| 30 | + } | |
| 31 | + | |
| 32 | + @Bean | |
| 33 | + public BpmCandidateRoleApiSourceInfoProcessor bpmCandidateRoleApiSourceInfoProcessor() { | |
| 34 | + return new BpmCandidateRoleApiSourceInfoProcessor(); | |
| 35 | + } | |
| 36 | + | |
| 37 | + @Bean | |
| 38 | + public BpmCandidateUserGroupApiSourceInfoProcessor bpmCandidateUserGroupApiSourceInfoProcessor() { | |
| 39 | + return new BpmCandidateUserGroupApiSourceInfoProcessor(); | |
| 40 | + } | |
| 41 | + | |
| 42 | + /** | |
| 43 | + * 可以自己定制脚本,然后通过这里设置到处理器里面去 | |
| 44 | + * @param scriptsOp 脚本包装对象 | |
| 45 | + * @return | |
| 46 | + */ | |
| 47 | + @Bean | |
| 48 | + public BpmCandidateScriptApiSourceInfoProcessor bpmCandidateScriptApiSourceInfoProcessor(ObjectProvider<BpmTaskAssignScript> scriptsOp) { | |
| 49 | + BpmCandidateScriptApiSourceInfoProcessor bpmCandidateScriptApiSourceInfoProcessor = new BpmCandidateScriptApiSourceInfoProcessor(); | |
| 50 | + bpmCandidateScriptApiSourceInfoProcessor.setScripts(scriptsOp); | |
| 51 | + return bpmCandidateScriptApiSourceInfoProcessor; | |
| 52 | + } | |
| 53 | +} | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfo.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO; | |
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 5 | +import lombok.AllArgsConstructor; | |
| 6 | +import lombok.Data; | |
| 7 | +import lombok.NoArgsConstructor; | |
| 8 | + | |
| 9 | +import jakarta.validation.constraints.NotEmpty; | |
| 10 | +import jakarta.validation.constraints.NotNull; | |
| 11 | +import java.util.HashSet; | |
| 12 | +import java.util.Set; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * 获取候选人信息 | |
| 16 | + */ | |
| 17 | +@AllArgsConstructor | |
| 18 | +@NoArgsConstructor | |
| 19 | +@Data | |
| 20 | +public class BpmCandidateSourceInfo { | |
| 21 | + | |
| 22 | + @Schema(description = "流程id") | |
| 23 | + @NotNull | |
| 24 | + private String processInstanceId; | |
| 25 | + | |
| 26 | + @Schema(description = "当前任务ID") | |
| 27 | + @NotNull | |
| 28 | + private String taskId; | |
| 29 | + /** | |
| 30 | + * 通过这些规则,生成最终需要生成的用户 | |
| 31 | + */ | |
| 32 | + @Schema(description = "当前任务预选规则") | |
| 33 | + @NotEmpty(message = "不允许空规则") | |
| 34 | + private Set<BpmTaskCandidateRuleVO> rules; | |
| 35 | + | |
| 36 | + @Schema(description = "发起抄送的用户") | |
| 37 | + private String creator; | |
| 38 | + | |
| 39 | + @Schema(description = "抄送原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "请帮忙审查下!") | |
| 40 | + @NotEmpty(message = "抄送原因不能为空") | |
| 41 | + private String reason; | |
| 42 | + | |
| 43 | + public void addRule(BpmTaskCandidateRuleVO vo) { | |
| 44 | + assert vo != null; | |
| 45 | + if (rules == null) { | |
| 46 | + rules = new HashSet<>(); | |
| 47 | + } | |
| 48 | + rules.add(vo); | |
| 49 | + } | |
| 50 | +} | |
| 0 | 51 | \ No newline at end of file | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfoProcessor.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO; | |
| 5 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; | |
| 6 | +import org.flowable.engine.delegate.DelegateExecution; | |
| 7 | + | |
| 8 | +import java.util.Collections; | |
| 9 | +import java.util.HashSet; | |
| 10 | +import java.util.Set; | |
| 11 | + | |
| 12 | +public interface BpmCandidateSourceInfoProcessor { | |
| 13 | + /** | |
| 14 | + * 获取该处理器支持的类型 | |
| 15 | + * 来自 {@link BpmTaskAssignRuleTypeEnum} | |
| 16 | + * | |
| 17 | + * @return | |
| 18 | + */ | |
| 19 | + Set<Integer> getSupportedTypes(); | |
| 20 | + | |
| 21 | + /** | |
| 22 | + * 对规则和人员做校验 | |
| 23 | + * | |
| 24 | + * @param type 规则 | |
| 25 | + * @param options 人员id | |
| 26 | + */ | |
| 27 | + void validRuleOptions(Integer type, Set<Long> options); | |
| 28 | + | |
| 29 | + /** | |
| 30 | + * 默认的处理 | |
| 31 | + * 如果想去操作所有的规则,则可以覆盖此方法 | |
| 32 | + * | |
| 33 | + * @param request 原始请求 | |
| 34 | + * @param delegateExecution 审批过程中的对象 | |
| 35 | + * @return 必须包含的是用户ID,而不是其他的ID | |
| 36 | + * @throws Exception | |
| 37 | + */ | |
| 38 | + default Set<Long> process(BpmCandidateSourceInfo request, DelegateExecution delegateExecution) throws Exception { | |
| 39 | + Set<BpmTaskCandidateRuleVO> rules = request.getRules(); | |
| 40 | + Set<Long> results = new HashSet<>(); | |
| 41 | + for (BpmTaskCandidateRuleVO rule : rules) { | |
| 42 | + // 每个处理器都有机会处理自己支持的事件 | |
| 43 | + if (CollUtil.contains(getSupportedTypes(), rule.getType())) { | |
| 44 | + results.addAll(doProcess(request, rule, delegateExecution)); | |
| 45 | + } | |
| 46 | + } | |
| 47 | + return results; | |
| 48 | + } | |
| 49 | + | |
| 50 | + default Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) { | |
| 51 | + return Collections.emptySet(); | |
| 52 | + } | |
| 53 | +} | |
| 0 | 54 | \ No newline at end of file | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfoProcessorChain.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import cn.hutool.core.collection.ListUtil; | |
| 5 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | |
| 6 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO; | |
| 7 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | |
| 8 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | |
| 9 | +import org.flowable.engine.delegate.DelegateExecution; | |
| 10 | +import org.springframework.beans.factory.ObjectProvider; | |
| 11 | +import org.springframework.stereotype.Service; | |
| 12 | + | |
| 13 | +import jakarta.annotation.Resource; | |
| 14 | +import java.util.*; | |
| 15 | + | |
| 16 | +@Service | |
| 17 | +public class BpmCandidateSourceInfoProcessorChain { | |
| 18 | + | |
| 19 | + // 保存处理节点 | |
| 20 | + | |
| 21 | + private List<BpmCandidateSourceInfoProcessor> processorList; | |
| 22 | + @Resource | |
| 23 | + private AdminUserApi adminUserApi; | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 可添加其他处理器 | |
| 27 | + * | |
| 28 | + * @param processorOp | |
| 29 | + * @return | |
| 30 | + */ | |
| 31 | + @Resource | |
| 32 | + // 动态扩展处理节点 | |
| 33 | + public BpmCandidateSourceInfoProcessorChain addProcessor(ObjectProvider<BpmCandidateSourceInfoProcessor> processorOp) { | |
| 34 | + List<BpmCandidateSourceInfoProcessor> processor = ListUtil.toList(processorOp.iterator()); | |
| 35 | + if (null == processorList) { | |
| 36 | + processorList = new ArrayList<>(processor.size()); | |
| 37 | + } | |
| 38 | + processorList.addAll(processor); | |
| 39 | + return this; | |
| 40 | + } | |
| 41 | + | |
| 42 | + // 获取处理器处理 | |
| 43 | + public Set<Long> process(BpmCandidateSourceInfo sourceInfo, DelegateExecution execution) throws Exception { | |
| 44 | + // Verify our parameters | |
| 45 | + if (sourceInfo == null) { | |
| 46 | + throw new IllegalArgumentException(); | |
| 47 | + } | |
| 48 | + for (BpmCandidateSourceInfoProcessor processor : processorList) { | |
| 49 | + try { | |
| 50 | + for (BpmTaskCandidateRuleVO vo : sourceInfo.getRules()) { | |
| 51 | + if (CollUtil.contains(processor.getSupportedTypes(), vo.getType())) { | |
| 52 | + processor.validRuleOptions(vo.getType(), vo.getOptions()); | |
| 53 | + } | |
| 54 | + } | |
| 55 | + } catch (Exception e) { | |
| 56 | + e.printStackTrace(); | |
| 57 | + throw e; | |
| 58 | + } | |
| 59 | + } | |
| 60 | + Set<Long> saveResult = Collections.emptySet(); | |
| 61 | + Exception saveException = null; | |
| 62 | + for (BpmCandidateSourceInfoProcessor processor : processorList) { | |
| 63 | + try { | |
| 64 | + saveResult = processor.process(sourceInfo, execution); | |
| 65 | + if (CollUtil.isNotEmpty(saveResult)) { | |
| 66 | + removeDisableUsers(saveResult); | |
| 67 | + break; | |
| 68 | + } | |
| 69 | + } catch (Exception e) { | |
| 70 | + saveException = e; | |
| 71 | + break; | |
| 72 | + } | |
| 73 | + } | |
| 74 | + // Return the exception or result state from the last execute() | |
| 75 | + if ((saveException != null)) { | |
| 76 | + throw saveException; | |
| 77 | + } else { | |
| 78 | + return (saveResult); | |
| 79 | + } | |
| 80 | + } | |
| 81 | + | |
| 82 | + public Set<Long> calculateTaskCandidateUsers(DelegateExecution execution, BpmCandidateSourceInfo sourceInfo) { | |
| 83 | + Set<Long> results = Collections.emptySet(); | |
| 84 | + try { | |
| 85 | + results = process(sourceInfo, execution); | |
| 86 | + } catch (Exception e) { | |
| 87 | + e.printStackTrace(); | |
| 88 | + } | |
| 89 | + return results; | |
| 90 | + } | |
| 91 | + | |
| 92 | + /** | |
| 93 | + * 移除禁用用户 | |
| 94 | + * | |
| 95 | + * @param assigneeUserIds | |
| 96 | + */ | |
| 97 | + public void removeDisableUsers(Set<Long> assigneeUserIds) { | |
| 98 | + if (CollUtil.isEmpty(assigneeUserIds)) { | |
| 99 | + return; | |
| 100 | + } | |
| 101 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(assigneeUserIds); | |
| 102 | + assigneeUserIds.removeIf(id -> { | |
| 103 | + AdminUserRespDTO user = userMap.get(id); | |
| 104 | + return user == null || !CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus()); | |
| 105 | + }); | |
| 106 | + } | |
| 107 | +} | |
| 0 | 108 | \ No newline at end of file | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateAdminUserApiSourceInfoProcessor.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | |
| 4 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO; | |
| 5 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; | |
| 6 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; | |
| 7 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessor; | |
| 8 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | |
| 9 | +import org.flowable.engine.delegate.DelegateExecution; | |
| 10 | + | |
| 11 | +import jakarta.annotation.Resource; | |
| 12 | +import java.util.Set; | |
| 13 | + | |
| 14 | +public class BpmCandidateAdminUserApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor { | |
| 15 | + @Resource | |
| 16 | + private AdminUserApi api; | |
| 17 | + | |
| 18 | + @Override | |
| 19 | + public Set<Integer> getSupportedTypes() { | |
| 20 | + return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.USER.getType()); | |
| 21 | + } | |
| 22 | + | |
| 23 | + @Override | |
| 24 | + public void validRuleOptions(Integer type, Set<Long> options) { | |
| 25 | + api.validateUserList(options); | |
| 26 | + } | |
| 27 | + | |
| 28 | + @Override | |
| 29 | + public Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) { | |
| 30 | + return rule.getOptions(); | |
| 31 | + } | |
| 32 | +} | |
| 0 | 33 | \ No newline at end of file | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateDeptApiSourceInfoProcessor.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | |
| 4 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO; | |
| 5 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; | |
| 6 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; | |
| 7 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessor; | |
| 8 | +import cn.iocoder.yudao.module.system.api.dept.DeptApi; | |
| 9 | +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; | |
| 10 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | |
| 11 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | |
| 12 | +import org.flowable.engine.delegate.DelegateExecution; | |
| 13 | + | |
| 14 | +import jakarta.annotation.Resource; | |
| 15 | +import java.util.Collections; | |
| 16 | +import java.util.List; | |
| 17 | +import java.util.Objects; | |
| 18 | +import java.util.Set; | |
| 19 | + | |
| 20 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | |
| 21 | + | |
| 22 | +public class BpmCandidateDeptApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor { | |
| 23 | + @Resource | |
| 24 | + private DeptApi api; | |
| 25 | + @Resource | |
| 26 | + private AdminUserApi adminUserApi; | |
| 27 | + | |
| 28 | + @Override | |
| 29 | + public Set<Integer> getSupportedTypes() { | |
| 30 | + return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(), | |
| 31 | + BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType()); | |
| 32 | + } | |
| 33 | + | |
| 34 | + @Override | |
| 35 | + public void validRuleOptions(Integer type, Set<Long> options) { | |
| 36 | + api.validateDeptList(options); | |
| 37 | + } | |
| 38 | + | |
| 39 | + @Override | |
| 40 | + public Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) { | |
| 41 | + if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(), rule.getType())) { | |
| 42 | + List<AdminUserRespDTO> users = adminUserApi.getUserListByDeptIds(rule.getOptions()); | |
| 43 | + return convertSet(users, AdminUserRespDTO::getId); | |
| 44 | + } else if (Objects.equals(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType(), rule.getType())) { | |
| 45 | + List<DeptRespDTO> depts = api.getDeptList(rule.getOptions()); | |
| 46 | + return convertSet(depts, DeptRespDTO::getLeaderUserId); | |
| 47 | + } | |
| 48 | + return Collections.emptySet(); | |
| 49 | + } | |
| 50 | +} | |
| 0 | 51 | \ No newline at end of file | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidatePostApiSourceInfoProcessor.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | |
| 4 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO; | |
| 5 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; | |
| 6 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; | |
| 7 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessor; | |
| 8 | +import cn.iocoder.yudao.module.system.api.dept.PostApi; | |
| 9 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | |
| 10 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | |
| 11 | +import org.flowable.engine.delegate.DelegateExecution; | |
| 12 | + | |
| 13 | +import jakarta.annotation.Resource; | |
| 14 | +import java.util.List; | |
| 15 | +import java.util.Set; | |
| 16 | + | |
| 17 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | |
| 18 | + | |
| 19 | +public class BpmCandidatePostApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor { | |
| 20 | + @Resource | |
| 21 | + private PostApi api; | |
| 22 | + @Resource | |
| 23 | + private AdminUserApi adminUserApi; | |
| 24 | + | |
| 25 | + @Override | |
| 26 | + public Set<Integer> getSupportedTypes() { | |
| 27 | + return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.POST.getType()); | |
| 28 | + } | |
| 29 | + | |
| 30 | + @Override | |
| 31 | + public void validRuleOptions(Integer type, Set<Long> options) { | |
| 32 | + api.validPostList(options); | |
| 33 | + } | |
| 34 | + | |
| 35 | + @Override | |
| 36 | + public Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) { | |
| 37 | + List<AdminUserRespDTO> users = adminUserApi.getUserListByPostIds(rule.getOptions()); | |
| 38 | + return convertSet(users, AdminUserRespDTO::getId); | |
| 39 | + } | |
| 40 | +} | |
| 0 | 41 | \ No newline at end of file | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateRoleApiSourceInfoProcessor.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | |
| 4 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO; | |
| 5 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; | |
| 6 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; | |
| 7 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessor; | |
| 8 | +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; | |
| 9 | +import cn.iocoder.yudao.module.system.api.permission.RoleApi; | |
| 10 | +import org.flowable.engine.delegate.DelegateExecution; | |
| 11 | + | |
| 12 | +import jakarta.annotation.Resource; | |
| 13 | +import java.util.Set; | |
| 14 | + | |
| 15 | +public class BpmCandidateRoleApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor { | |
| 16 | + @Resource | |
| 17 | + private RoleApi api; | |
| 18 | + | |
| 19 | + @Resource | |
| 20 | + private PermissionApi permissionApi; | |
| 21 | + | |
| 22 | + @Override | |
| 23 | + public Set<Integer> getSupportedTypes() { | |
| 24 | + return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.ROLE.getType()); | |
| 25 | + } | |
| 26 | + | |
| 27 | + @Override | |
| 28 | + public void validRuleOptions(Integer type, Set<Long> options) { | |
| 29 | + api.validRoleList(options); | |
| 30 | + } | |
| 31 | + | |
| 32 | + @Override | |
| 33 | + public Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) { | |
| 34 | + return permissionApi.getUserRoleIdListByRoleIds(rule.getOptions()); | |
| 35 | + } | |
| 36 | + | |
| 37 | +} | |
| 0 | 38 | \ No newline at end of file | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateScriptApiSourceInfoProcessor.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 5 | +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | |
| 6 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO; | |
| 7 | +import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants; | |
| 8 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; | |
| 9 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript; | |
| 10 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; | |
| 11 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessor; | |
| 12 | +import cn.iocoder.yudao.module.system.api.dict.DictDataApi; | |
| 13 | +import org.flowable.engine.delegate.DelegateExecution; | |
| 14 | +import org.springframework.beans.factory.ObjectProvider; | |
| 15 | + | |
| 16 | +import jakarta.annotation.Resource; | |
| 17 | +import java.util.*; | |
| 18 | +import java.util.stream.Collectors; | |
| 19 | + | |
| 20 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 21 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | |
| 22 | +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_ASSIGN_SCRIPT_NOT_EXISTS; | |
| 23 | + | |
| 24 | +public class BpmCandidateScriptApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor { | |
| 25 | + @Resource | |
| 26 | + private DictDataApi dictDataApi; | |
| 27 | + | |
| 28 | + /** | |
| 29 | + * 任务分配脚本 | |
| 30 | + */ | |
| 31 | + private Map<Long, BpmTaskAssignScript> scriptMap = Collections.emptyMap(); | |
| 32 | + | |
| 33 | + public void setScripts(ObjectProvider<BpmTaskAssignScript> scriptsOp) { | |
| 34 | + List<BpmTaskAssignScript> scripts = scriptsOp.orderedStream().collect(Collectors.toList()); | |
| 35 | + setScripts(scripts); | |
| 36 | + } | |
| 37 | + | |
| 38 | + public void setScripts(List<BpmTaskAssignScript> scripts) { | |
| 39 | + this.scriptMap = convertMap(scripts, script -> script.getEnum().getId()); | |
| 40 | + } | |
| 41 | + | |
| 42 | + @Override | |
| 43 | + public Set<Integer> getSupportedTypes() { | |
| 44 | + return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.SCRIPT.getType()); | |
| 45 | + } | |
| 46 | + | |
| 47 | + @Override | |
| 48 | + public void validRuleOptions(Integer type, Set<Long> options) { | |
| 49 | + dictDataApi.validateDictDataList(DictTypeConstants.TASK_ASSIGN_SCRIPT, | |
| 50 | + CollectionUtils.convertSet(options, String::valueOf)); | |
| 51 | + } | |
| 52 | + | |
| 53 | + @Override | |
| 54 | + public Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) { | |
| 55 | + return calculateTaskCandidateUsersByScript(delegateExecution, rule.getOptions()); | |
| 56 | + } | |
| 57 | + | |
| 58 | + private Set<Long> calculateTaskCandidateUsersByScript(DelegateExecution execution, Set<Long> options) { | |
| 59 | + // 获得对应的脚本 | |
| 60 | + List<BpmTaskAssignScript> scripts = new ArrayList<>(options.size()); | |
| 61 | + options.forEach(id -> { | |
| 62 | + BpmTaskAssignScript script = scriptMap.get(id); | |
| 63 | + if (script == null) { | |
| 64 | + throw exception(TASK_ASSIGN_SCRIPT_NOT_EXISTS, id); | |
| 65 | + } | |
| 66 | + scripts.add(script); | |
| 67 | + }); | |
| 68 | + // 逐个计算任务 | |
| 69 | + Set<Long> userIds = new HashSet<>(); | |
| 70 | + scripts.forEach(script -> CollUtil.addAll(userIds, script.calculateTaskCandidateUsers(execution))); | |
| 71 | + return userIds; | |
| 72 | + } | |
| 73 | +} | |
| 0 | 74 | \ No newline at end of file | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/sourceInfoProcessor/BpmCandidateUserGroupApiSourceInfoProcessor.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | |
| 4 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO; | |
| 5 | +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO; | |
| 6 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; | |
| 7 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; | |
| 8 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessor; | |
| 9 | +import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService; | |
| 10 | +import org.flowable.engine.delegate.DelegateExecution; | |
| 11 | + | |
| 12 | +import jakarta.annotation.Resource; | |
| 13 | +import java.util.HashSet; | |
| 14 | +import java.util.List; | |
| 15 | +import java.util.Set; | |
| 16 | + | |
| 17 | +public class BpmCandidateUserGroupApiSourceInfoProcessor implements BpmCandidateSourceInfoProcessor { | |
| 18 | + @Resource | |
| 19 | + private BpmUserGroupService api; | |
| 20 | + @Resource | |
| 21 | + private BpmUserGroupService userGroupService; | |
| 22 | + | |
| 23 | + @Override | |
| 24 | + public Set<Integer> getSupportedTypes() { | |
| 25 | + return SetUtils.asSet(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType()); | |
| 26 | + } | |
| 27 | + | |
| 28 | + @Override | |
| 29 | + public void validRuleOptions(Integer type, Set<Long> options) { | |
| 30 | + api.validUserGroups(options); | |
| 31 | + } | |
| 32 | + | |
| 33 | + @Override | |
| 34 | + public Set<Long> doProcess(BpmCandidateSourceInfo request, BpmTaskCandidateRuleVO rule, DelegateExecution delegateExecution) { | |
| 35 | + List<BpmUserGroupDO> userGroups = userGroupService.getUserGroupList(rule.getOptions()); | |
| 36 | + Set<Long> userIds = new HashSet<>(); | |
| 37 | + userGroups.forEach(group -> userIds.addAll(group.getMemberUserIds())); | |
| 38 | + return userIds; | |
| 39 | + } | |
| 40 | + | |
| 41 | +} | |
| 0 | 42 | \ No newline at end of file | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.cc; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 4 | +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCCMyPageReqVO; | |
| 5 | +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCCPageItemRespVO; | |
| 6 | +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCCReqVO; | |
| 7 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * 流程抄送Service接口 | |
| 11 | + * | |
| 12 | + * 现在是在审批的时候进行流程抄送 | |
| 13 | + */ | |
| 14 | +public interface BpmProcessInstanceCopyService { | |
| 15 | + | |
| 16 | + /** | |
| 17 | + * 查询流程抄送 | |
| 18 | + * | |
| 19 | + * @param copyId 流程抄送主键 | |
| 20 | + * @return 流程抄送 | |
| 21 | + */ | |
| 22 | + BpmProcessInstanceCopyVO queryById(Long copyId); | |
| 23 | + | |
| 24 | + /** | |
| 25 | + * 抄送 | |
| 26 | + * @param sourceInfo 抄送源信息,方便抄送处理 | |
| 27 | + * @return | |
| 28 | + */ | |
| 29 | + boolean makeCopy(BpmCandidateSourceInfo sourceInfo); | |
| 30 | + | |
| 31 | + /** | |
| 32 | + * 流程实例的抄送 | |
| 33 | + * @param loginUserId 当前登录用户 | |
| 34 | + * @param createReqVO 创建的抄送请求 | |
| 35 | + * @return 是否抄送成功,抄送成功则返回true | |
| 36 | + */ | |
| 37 | + boolean ccProcessInstance(Long loginUserId, BpmProcessInstanceCCReqVO createReqVO); | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * 抄送的流程 | |
| 41 | + * @param loginUserId 登录用户id | |
| 42 | + * @param pageReqVO 分页请求 | |
| 43 | + * @return 抄送的分页结果 | |
| 44 | + */ | |
| 45 | + PageResult<BpmProcessInstanceCCPageItemRespVO> getMyProcessInstanceCCPage(Long loginUserId, BpmProcessInstanceCCMyPageReqVO pageReqVO); | |
| 46 | +} | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.cc; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 5 | +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCCMyPageReqVO; | |
| 6 | +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCCPageItemRespVO; | |
| 7 | +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCCReqVO; | |
| 8 | +import cn.iocoder.yudao.module.bpm.convert.cc.BpmProcessInstanceCopyConvert; | |
| 9 | +import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO; | |
| 10 | +import cn.iocoder.yudao.module.bpm.dal.mysql.cc.BpmProcessInstanceCopyMapper; | |
| 11 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; | |
| 12 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessorChain; | |
| 13 | +import cn.iocoder.yudao.module.bpm.service.cc.dto.BpmDelegateExecutionDTO; | |
| 14 | +import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; | |
| 15 | +import cn.iocoder.yudao.module.bpm.util.FlowableUtils; | |
| 16 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | |
| 17 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | |
| 18 | +import lombok.extern.slf4j.Slf4j; | |
| 19 | +import org.flowable.engine.RuntimeService; | |
| 20 | +import org.flowable.engine.delegate.DelegateExecution; | |
| 21 | +import org.flowable.engine.repository.ProcessDefinition; | |
| 22 | +import org.flowable.engine.runtime.ProcessInstance; | |
| 23 | +import org.springframework.context.annotation.Lazy; | |
| 24 | +import org.springframework.stereotype.Service; | |
| 25 | +import org.springframework.validation.annotation.Validated; | |
| 26 | + | |
| 27 | +import jakarta.annotation.Resource; | |
| 28 | +import java.time.LocalDateTime; | |
| 29 | +import java.util.*; | |
| 30 | +import java.util.stream.Collectors; | |
| 31 | + | |
| 32 | +@Slf4j | |
| 33 | +@Service | |
| 34 | +@Validated | |
| 35 | +public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopyService { | |
| 36 | + @Resource | |
| 37 | + private BpmProcessInstanceCopyMapper processInstanceCopyMapper; | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * 和flowable有关的,查询流程名用的 | |
| 41 | + */ | |
| 42 | + @Resource | |
| 43 | + private RuntimeService runtimeService; | |
| 44 | + | |
| 45 | + /** | |
| 46 | + * 找抄送人用的 | |
| 47 | + */ | |
| 48 | + @Resource | |
| 49 | + private BpmCandidateSourceInfoProcessorChain processorChain; | |
| 50 | + | |
| 51 | + @Resource | |
| 52 | + @Lazy // 解决循环依赖 | |
| 53 | + private BpmTaskService taskService; | |
| 54 | + @Resource | |
| 55 | + private AdminUserApi adminUserApi; | |
| 56 | + | |
| 57 | + @Override | |
| 58 | + public BpmProcessInstanceCopyVO queryById(Long copyId) { | |
| 59 | + BpmProcessInstanceCopyDO bpmProcessInstanceCopyDO = processInstanceCopyMapper.selectById(copyId); | |
| 60 | + return BpmProcessInstanceCopyConvert.INSTANCE.convert(bpmProcessInstanceCopyDO); | |
| 61 | + } | |
| 62 | + | |
| 63 | + @Override | |
| 64 | + public boolean makeCopy(BpmCandidateSourceInfo sourceInfo) { | |
| 65 | + if (null == sourceInfo) { | |
| 66 | + return false; | |
| 67 | + } | |
| 68 | + | |
| 69 | + DelegateExecution executionEntity = new BpmDelegateExecutionDTO(sourceInfo.getProcessInstanceId()); | |
| 70 | + Set<Long> ccCandidates = processorChain.calculateTaskCandidateUsers(executionEntity, sourceInfo); | |
| 71 | + if (CollUtil.isEmpty(ccCandidates)) { | |
| 72 | + log.warn("相关抄送人不存在 {}", sourceInfo.getTaskId()); | |
| 73 | + return false; | |
| 74 | + } else { | |
| 75 | + BpmProcessInstanceCopyDO copyDO = new BpmProcessInstanceCopyDO(); | |
| 76 | + // 调用 | |
| 77 | + // 设置任务id | |
| 78 | + copyDO.setTaskId(sourceInfo.getTaskId()); | |
| 79 | + copyDO.setTaskName(FlowableUtils.getTaskNameByTaskId(sourceInfo.getTaskId())); | |
| 80 | + copyDO.setProcessInstanceId(sourceInfo.getProcessInstanceId()); | |
| 81 | + ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() | |
| 82 | + .processInstanceId(sourceInfo.getProcessInstanceId()) | |
| 83 | + .singleResult(); | |
| 84 | + if (null == processInstance) { | |
| 85 | + log.warn("相关流程实例不存在 {}", sourceInfo.getTaskId()); | |
| 86 | + return false; | |
| 87 | + } | |
| 88 | + copyDO.setStartUserId(FlowableUtils.getStartUserIdFromProcessInstance(processInstance)); | |
| 89 | + copyDO.setProcessInstanceName(processInstance.getName()); | |
| 90 | + ProcessDefinition processDefinition = FlowableUtils.getProcessDefinition(processInstance.getProcessDefinitionId()); | |
| 91 | + copyDO.setProcessDefinitionCategory(processDefinition.getCategory()); | |
| 92 | + copyDO.setReason(sourceInfo.getReason()); | |
| 93 | + copyDO.setCreator(sourceInfo.getCreator()); | |
| 94 | + copyDO.setCreateTime(LocalDateTime.now()); | |
| 95 | + List<BpmProcessInstanceCopyDO> copyList = new ArrayList<>(ccCandidates.size()); | |
| 96 | + for (Long userId : ccCandidates) { | |
| 97 | + BpmProcessInstanceCopyDO copy = BpmProcessInstanceCopyConvert.INSTANCE.copy(copyDO); | |
| 98 | + copy.setUserId(userId); | |
| 99 | + copyList.add(copy); | |
| 100 | + } | |
| 101 | + return processInstanceCopyMapper.insertBatch(copyList); | |
| 102 | + } | |
| 103 | + } | |
| 104 | + | |
| 105 | + @Override | |
| 106 | + public boolean ccProcessInstance(Long loginUserId, BpmProcessInstanceCCReqVO reqVO) { | |
| 107 | + // 在能正常审批的情况下抄送流程 | |
| 108 | + BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo(); | |
| 109 | + sourceInfo.setTaskId(reqVO.getTaskKey()); | |
| 110 | + sourceInfo.setProcessInstanceId(reqVO.getProcessInstanceKey()); | |
| 111 | + sourceInfo.addRule(reqVO); | |
| 112 | + sourceInfo.setCreator(String.valueOf(loginUserId)); | |
| 113 | + sourceInfo.setReason(reqVO.getReason()); | |
| 114 | + if (!makeCopy(sourceInfo)) { | |
| 115 | + throw new RuntimeException("抄送任务失败"); | |
| 116 | + } | |
| 117 | + return false; | |
| 118 | + } | |
| 119 | + | |
| 120 | + //获取流程抄送分页 | |
| 121 | + @Override | |
| 122 | + public PageResult<BpmProcessInstanceCCPageItemRespVO> getMyProcessInstanceCCPage(Long loginUserId, BpmProcessInstanceCCMyPageReqVO pageReqVO) { | |
| 123 | + // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 | |
| 124 | + PageResult<BpmProcessInstanceCopyDO> pageResult = processInstanceCopyMapper.selectPage(loginUserId, pageReqVO); | |
| 125 | + if (CollUtil.isEmpty(pageResult.getList())) { | |
| 126 | + return new PageResult<>(pageResult.getTotal()); | |
| 127 | + } | |
| 128 | + | |
| 129 | + Set<String/* taskId */> taskIds = new HashSet<>(); | |
| 130 | + Set<String/* processInstaneId */> processInstaneIds = new HashSet<>(); | |
| 131 | + Set<Long/* userId */> userIds = new HashSet<>(); | |
| 132 | + for (BpmProcessInstanceCopyDO doItem : pageResult.getList()) { | |
| 133 | + taskIds.add(doItem.getTaskId()); | |
| 134 | + processInstaneIds.add(doItem.getProcessInstanceId()); | |
| 135 | + userIds.add(doItem.getStartUserId()); | |
| 136 | + Long userId = Long.valueOf(doItem.getCreator()); | |
| 137 | + userIds.add(userId); | |
| 138 | + } | |
| 139 | + | |
| 140 | + Map<String, String> taskNameByTaskIds = FlowableUtils.getTaskNameByTaskIds(taskIds); | |
| 141 | + Map<String, String> processInstanceNameByTaskIds = FlowableUtils.getProcessInstanceNameByTaskIds(processInstaneIds); | |
| 142 | + | |
| 143 | + Map<Long, String> userMap = adminUserApi.getUserList(userIds).stream().collect(Collectors.toMap( | |
| 144 | + AdminUserRespDTO::getId, AdminUserRespDTO::getNickname)); | |
| 145 | + | |
| 146 | + // 转换返回 | |
| 147 | + return BpmProcessInstanceCopyConvert.INSTANCE.convertPage(pageResult, taskNameByTaskIds, processInstanceNameByTaskIds, userMap); | |
| 148 | + } | |
| 149 | + | |
| 150 | +} | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.cc; | |
| 2 | + | |
| 3 | +import com.baomidou.mybatisplus.annotation.TableId; | |
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 5 | +import lombok.Data; | |
| 6 | + | |
| 7 | +import java.time.LocalDateTime; | |
| 8 | +import java.util.Date; | |
| 9 | + | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 流程抄送视图对象 wf_copy | |
| 13 | + * | |
| 14 | + * @author ruoyi | |
| 15 | + * @date 2022-05-19 | |
| 16 | + */ | |
| 17 | +@Data | |
| 18 | +public class BpmProcessInstanceCopyVO { | |
| 19 | + | |
| 20 | + /** | |
| 21 | + * 编号 | |
| 22 | + */ | |
| 23 | + @Schema(description = "抄送主键") | |
| 24 | + private Long id; | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * 发起人Id | |
| 28 | + */ | |
| 29 | + @Schema(description = "发起人Id") | |
| 30 | + private Long startUserId; | |
| 31 | + | |
| 32 | + @Schema(description = "发起人别名") | |
| 33 | + private String startUserNickname; | |
| 34 | + | |
| 35 | + /** | |
| 36 | + * 流程主键 | |
| 37 | + */ | |
| 38 | + @Schema(description = "流程实例的主键") | |
| 39 | + private String processInstanceId; | |
| 40 | + | |
| 41 | + @Schema(description = "流程实例的名字") | |
| 42 | + private String processInstanceName; | |
| 43 | + | |
| 44 | + /** | |
| 45 | + * 任务主键 | |
| 46 | + */ | |
| 47 | + @Schema(description = "发起抄送的任务编号") | |
| 48 | + private String taskId; | |
| 49 | + | |
| 50 | + @Schema(description = "发起抄送的任务名称") | |
| 51 | + private String taskName; | |
| 52 | + /** | |
| 53 | + * 用户主键 | |
| 54 | + */ | |
| 55 | + @Schema(description = "用户编号") | |
| 56 | + private Long userId; | |
| 57 | + | |
| 58 | + @Schema(description = "用户别名") | |
| 59 | + private Long userNickname; | |
| 60 | + | |
| 61 | + @Schema(description = "抄送原因") | |
| 62 | + private String reason; | |
| 63 | + | |
| 64 | + @Schema(description = "抄送人") | |
| 65 | + private String creator; | |
| 66 | + | |
| 67 | + @Schema(description = "抄送时间") | |
| 68 | + private LocalDateTime createTime; | |
| 69 | +} | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/cc/dto/BpmDelegateExecutionDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.cc.dto; | |
| 2 | + | |
| 3 | +import org.flowable.bpmn.model.FlowElement; | |
| 4 | +import org.flowable.bpmn.model.FlowableListener; | |
| 5 | +import org.flowable.engine.delegate.DelegateExecution; | |
| 6 | +import org.flowable.engine.delegate.ReadOnlyDelegateExecution; | |
| 7 | +import org.flowable.variable.api.persistence.entity.VariableInstance; | |
| 8 | + | |
| 9 | +import java.util.Collection; | |
| 10 | +import java.util.List; | |
| 11 | +import java.util.Map; | |
| 12 | +import java.util.Set; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * 仅为了传输processInstanceId | |
| 16 | + */ | |
| 17 | +public class BpmDelegateExecutionDTO implements DelegateExecution { | |
| 18 | + | |
| 19 | + public BpmDelegateExecutionDTO(String getProcessInstanceId) { | |
| 20 | + this.getProcessInstanceId = getProcessInstanceId; | |
| 21 | + } | |
| 22 | + | |
| 23 | + private final String getProcessInstanceId; | |
| 24 | + | |
| 25 | + @Override | |
| 26 | + public String getId() { | |
| 27 | + return null; | |
| 28 | + } | |
| 29 | + | |
| 30 | + @Override | |
| 31 | + public String getProcessInstanceId() { | |
| 32 | + return null; | |
| 33 | + } | |
| 34 | + | |
| 35 | + @Override | |
| 36 | + public String getRootProcessInstanceId() { | |
| 37 | + return null; | |
| 38 | + } | |
| 39 | + | |
| 40 | + @Override | |
| 41 | + public String getEventName() { | |
| 42 | + return null; | |
| 43 | + } | |
| 44 | + | |
| 45 | + @Override | |
| 46 | + public void setEventName(String eventName) { | |
| 47 | + | |
| 48 | + } | |
| 49 | + | |
| 50 | + @Override | |
| 51 | + public String getProcessInstanceBusinessKey() { | |
| 52 | + return null; | |
| 53 | + } | |
| 54 | + | |
| 55 | + @Override | |
| 56 | + public String getProcessInstanceBusinessStatus() { | |
| 57 | + return null; | |
| 58 | + } | |
| 59 | + | |
| 60 | + @Override | |
| 61 | + public String getProcessDefinitionId() { | |
| 62 | + return null; | |
| 63 | + } | |
| 64 | + | |
| 65 | + @Override | |
| 66 | + public String getPropagatedStageInstanceId() { | |
| 67 | + return null; | |
| 68 | + } | |
| 69 | + | |
| 70 | + @Override | |
| 71 | + public String getParentId() { | |
| 72 | + return null; | |
| 73 | + } | |
| 74 | + | |
| 75 | + @Override | |
| 76 | + public String getSuperExecutionId() { | |
| 77 | + return null; | |
| 78 | + } | |
| 79 | + | |
| 80 | + @Override | |
| 81 | + public String getCurrentActivityId() { | |
| 82 | + return null; | |
| 83 | + } | |
| 84 | + | |
| 85 | + @Override | |
| 86 | + public String getTenantId() { | |
| 87 | + return null; | |
| 88 | + } | |
| 89 | + | |
| 90 | + @Override | |
| 91 | + public FlowElement getCurrentFlowElement() { | |
| 92 | + return null; | |
| 93 | + } | |
| 94 | + | |
| 95 | + @Override | |
| 96 | + public void setCurrentFlowElement(FlowElement flowElement) { | |
| 97 | + | |
| 98 | + } | |
| 99 | + | |
| 100 | + @Override | |
| 101 | + public FlowableListener getCurrentFlowableListener() { | |
| 102 | + return null; | |
| 103 | + } | |
| 104 | + | |
| 105 | + @Override | |
| 106 | + public void setCurrentFlowableListener(FlowableListener currentListener) { | |
| 107 | + | |
| 108 | + } | |
| 109 | + | |
| 110 | + @Override | |
| 111 | + public ReadOnlyDelegateExecution snapshotReadOnly() { | |
| 112 | + return null; | |
| 113 | + } | |
| 114 | + | |
| 115 | + @Override | |
| 116 | + public DelegateExecution getParent() { | |
| 117 | + return null; | |
| 118 | + } | |
| 119 | + | |
| 120 | + @Override | |
| 121 | + public List<? extends DelegateExecution> getExecutions() { | |
| 122 | + return null; | |
| 123 | + } | |
| 124 | + | |
| 125 | + @Override | |
| 126 | + public void setActive(boolean isActive) { | |
| 127 | + | |
| 128 | + } | |
| 129 | + | |
| 130 | + @Override | |
| 131 | + public boolean isActive() { | |
| 132 | + return false; | |
| 133 | + } | |
| 134 | + | |
| 135 | + @Override | |
| 136 | + public boolean isEnded() { | |
| 137 | + return false; | |
| 138 | + } | |
| 139 | + | |
| 140 | + @Override | |
| 141 | + public void setConcurrent(boolean isConcurrent) { | |
| 142 | + | |
| 143 | + } | |
| 144 | + | |
| 145 | + @Override | |
| 146 | + public boolean isConcurrent() { | |
| 147 | + return false; | |
| 148 | + } | |
| 149 | + | |
| 150 | + @Override | |
| 151 | + public boolean isProcessInstanceType() { | |
| 152 | + return false; | |
| 153 | + } | |
| 154 | + | |
| 155 | + @Override | |
| 156 | + public void inactivate() { | |
| 157 | + | |
| 158 | + } | |
| 159 | + | |
| 160 | + @Override | |
| 161 | + public boolean isScope() { | |
| 162 | + return false; | |
| 163 | + } | |
| 164 | + | |
| 165 | + @Override | |
| 166 | + public void setScope(boolean isScope) { | |
| 167 | + | |
| 168 | + } | |
| 169 | + | |
| 170 | + @Override | |
| 171 | + public boolean isMultiInstanceRoot() { | |
| 172 | + return false; | |
| 173 | + } | |
| 174 | + | |
| 175 | + @Override | |
| 176 | + public void setMultiInstanceRoot(boolean isMultiInstanceRoot) { | |
| 177 | + | |
| 178 | + } | |
| 179 | + | |
| 180 | + @Override | |
| 181 | + public Map<String, Object> getVariables() { | |
| 182 | + return null; | |
| 183 | + } | |
| 184 | + | |
| 185 | + @Override | |
| 186 | + public Map<String, VariableInstance> getVariableInstances() { | |
| 187 | + return null; | |
| 188 | + } | |
| 189 | + | |
| 190 | + @Override | |
| 191 | + public Map<String, Object> getVariables(Collection<String> collection) { | |
| 192 | + return null; | |
| 193 | + } | |
| 194 | + | |
| 195 | + @Override | |
| 196 | + public Map<String, VariableInstance> getVariableInstances(Collection<String> collection) { | |
| 197 | + return null; | |
| 198 | + } | |
| 199 | + | |
| 200 | + @Override | |
| 201 | + public Map<String, Object> getVariables(Collection<String> collection, boolean b) { | |
| 202 | + return null; | |
| 203 | + } | |
| 204 | + | |
| 205 | + @Override | |
| 206 | + public Map<String, VariableInstance> getVariableInstances(Collection<String> collection, boolean b) { | |
| 207 | + return null; | |
| 208 | + } | |
| 209 | + | |
| 210 | + @Override | |
| 211 | + public Map<String, Object> getVariablesLocal() { | |
| 212 | + return null; | |
| 213 | + } | |
| 214 | + | |
| 215 | + @Override | |
| 216 | + public Map<String, VariableInstance> getVariableInstancesLocal() { | |
| 217 | + return null; | |
| 218 | + } | |
| 219 | + | |
| 220 | + @Override | |
| 221 | + public Map<String, Object> getVariablesLocal(Collection<String> collection) { | |
| 222 | + return null; | |
| 223 | + } | |
| 224 | + | |
| 225 | + @Override | |
| 226 | + public Map<String, VariableInstance> getVariableInstancesLocal(Collection<String> collection) { | |
| 227 | + return null; | |
| 228 | + } | |
| 229 | + | |
| 230 | + @Override | |
| 231 | + public Map<String, Object> getVariablesLocal(Collection<String> collection, boolean b) { | |
| 232 | + return null; | |
| 233 | + } | |
| 234 | + | |
| 235 | + @Override | |
| 236 | + public Map<String, VariableInstance> getVariableInstancesLocal(Collection<String> collection, boolean b) { | |
| 237 | + return null; | |
| 238 | + } | |
| 239 | + | |
| 240 | + @Override | |
| 241 | + public Object getVariable(String s) { | |
| 242 | + return null; | |
| 243 | + } | |
| 244 | + | |
| 245 | + @Override | |
| 246 | + public VariableInstance getVariableInstance(String s) { | |
| 247 | + return null; | |
| 248 | + } | |
| 249 | + | |
| 250 | + @Override | |
| 251 | + public Object getVariable(String s, boolean b) { | |
| 252 | + return null; | |
| 253 | + } | |
| 254 | + | |
| 255 | + @Override | |
| 256 | + public VariableInstance getVariableInstance(String s, boolean b) { | |
| 257 | + return null; | |
| 258 | + } | |
| 259 | + | |
| 260 | + @Override | |
| 261 | + public Object getVariableLocal(String s) { | |
| 262 | + return null; | |
| 263 | + } | |
| 264 | + | |
| 265 | + @Override | |
| 266 | + public VariableInstance getVariableInstanceLocal(String s) { | |
| 267 | + return null; | |
| 268 | + } | |
| 269 | + | |
| 270 | + @Override | |
| 271 | + public Object getVariableLocal(String s, boolean b) { | |
| 272 | + return null; | |
| 273 | + } | |
| 274 | + | |
| 275 | + @Override | |
| 276 | + public VariableInstance getVariableInstanceLocal(String s, boolean b) { | |
| 277 | + return null; | |
| 278 | + } | |
| 279 | + | |
| 280 | + @Override | |
| 281 | + public <T> T getVariable(String s, Class<T> aClass) { | |
| 282 | + return null; | |
| 283 | + } | |
| 284 | + | |
| 285 | + @Override | |
| 286 | + public <T> T getVariableLocal(String s, Class<T> aClass) { | |
| 287 | + return null; | |
| 288 | + } | |
| 289 | + | |
| 290 | + @Override | |
| 291 | + public Set<String> getVariableNames() { | |
| 292 | + return null; | |
| 293 | + } | |
| 294 | + | |
| 295 | + @Override | |
| 296 | + public Set<String> getVariableNamesLocal() { | |
| 297 | + return null; | |
| 298 | + } | |
| 299 | + | |
| 300 | + @Override | |
| 301 | + public void setVariable(String s, Object o) { | |
| 302 | + | |
| 303 | + } | |
| 304 | + | |
| 305 | + @Override | |
| 306 | + public void setVariable(String s, Object o, boolean b) { | |
| 307 | + | |
| 308 | + } | |
| 309 | + | |
| 310 | + @Override | |
| 311 | + public Object setVariableLocal(String s, Object o) { | |
| 312 | + return null; | |
| 313 | + } | |
| 314 | + | |
| 315 | + @Override | |
| 316 | + public Object setVariableLocal(String s, Object o, boolean b) { | |
| 317 | + return null; | |
| 318 | + } | |
| 319 | + | |
| 320 | + @Override | |
| 321 | + public void setVariables(Map<String, ?> map) { | |
| 322 | + | |
| 323 | + } | |
| 324 | + | |
| 325 | + @Override | |
| 326 | + public void setVariablesLocal(Map<String, ?> map) { | |
| 327 | + | |
| 328 | + } | |
| 329 | + | |
| 330 | + @Override | |
| 331 | + public boolean hasVariables() { | |
| 332 | + return false; | |
| 333 | + } | |
| 334 | + | |
| 335 | + @Override | |
| 336 | + public boolean hasVariablesLocal() { | |
| 337 | + return false; | |
| 338 | + } | |
| 339 | + | |
| 340 | + @Override | |
| 341 | + public boolean hasVariable(String s) { | |
| 342 | + return false; | |
| 343 | + } | |
| 344 | + | |
| 345 | + @Override | |
| 346 | + public boolean hasVariableLocal(String s) { | |
| 347 | + return false; | |
| 348 | + } | |
| 349 | + | |
| 350 | + @Override | |
| 351 | + public void removeVariable(String s) { | |
| 352 | + | |
| 353 | + } | |
| 354 | + | |
| 355 | + @Override | |
| 356 | + public void removeVariableLocal(String s) { | |
| 357 | + | |
| 358 | + } | |
| 359 | + | |
| 360 | + @Override | |
| 361 | + public void removeVariables(Collection<String> collection) { | |
| 362 | + | |
| 363 | + } | |
| 364 | + | |
| 365 | + @Override | |
| 366 | + public void removeVariablesLocal(Collection<String> collection) { | |
| 367 | + | |
| 368 | + } | |
| 369 | + | |
| 370 | + @Override | |
| 371 | + public void removeVariables() { | |
| 372 | + | |
| 373 | + } | |
| 374 | + | |
| 375 | + @Override | |
| 376 | + public void removeVariablesLocal() { | |
| 377 | + | |
| 378 | + } | |
| 379 | + | |
| 380 | + @Override | |
| 381 | + public void setTransientVariable(String s, Object o) { | |
| 382 | + | |
| 383 | + } | |
| 384 | + | |
| 385 | + @Override | |
| 386 | + public void setTransientVariableLocal(String s, Object o) { | |
| 387 | + | |
| 388 | + } | |
| 389 | + | |
| 390 | + @Override | |
| 391 | + public void setTransientVariables(Map<String, Object> map) { | |
| 392 | + | |
| 393 | + } | |
| 394 | + | |
| 395 | + @Override | |
| 396 | + public Object getTransientVariable(String s) { | |
| 397 | + return null; | |
| 398 | + } | |
| 399 | + | |
| 400 | + @Override | |
| 401 | + public Map<String, Object> getTransientVariables() { | |
| 402 | + return null; | |
| 403 | + } | |
| 404 | + | |
| 405 | + @Override | |
| 406 | + public void setTransientVariablesLocal(Map<String, Object> map) { | |
| 407 | + | |
| 408 | + } | |
| 409 | + | |
| 410 | + @Override | |
| 411 | + public Object getTransientVariableLocal(String s) { | |
| 412 | + return null; | |
| 413 | + } | |
| 414 | + | |
| 415 | + @Override | |
| 416 | + public Map<String, Object> getTransientVariablesLocal() { | |
| 417 | + return null; | |
| 418 | + } | |
| 419 | + | |
| 420 | + @Override | |
| 421 | + public void removeTransientVariableLocal(String s) { | |
| 422 | + | |
| 423 | + } | |
| 424 | + | |
| 425 | + @Override | |
| 426 | + public void removeTransientVariable(String s) { | |
| 427 | + | |
| 428 | + } | |
| 429 | + | |
| 430 | + @Override | |
| 431 | + public void removeTransientVariables() { | |
| 432 | + | |
| 433 | + } | |
| 434 | + | |
| 435 | + @Override | |
| 436 | + public void removeTransientVariablesLocal() { | |
| 437 | + | |
| 438 | + } | |
| 439 | +} | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
| ... | ... | @@ -19,6 +19,8 @@ import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum; |
| 19 | 19 | import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; |
| 20 | 20 | import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; |
| 21 | 21 | import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskAddSignTypeEnum; |
| 22 | +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; | |
| 23 | +import cn.iocoder.yudao.module.bpm.service.cc.BpmProcessInstanceCopyService; | |
| 22 | 24 | import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService; |
| 23 | 25 | import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; |
| 24 | 26 | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| ... | ... | @@ -94,6 +96,9 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 94 | 96 | @Resource |
| 95 | 97 | private ManagementService managementService; |
| 96 | 98 | |
| 99 | + @Resource | |
| 100 | + private BpmProcessInstanceCopyService processInstanceCopyService; | |
| 101 | + | |
| 97 | 102 | @Override |
| 98 | 103 | public PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageVO) { |
| 99 | 104 | // 查询待办任务 | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/util/FlowableUtils.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.util; | |
| 2 | + | |
| 3 | + | |
| 4 | +import cn.hutool.core.collection.CollUtil; | |
| 5 | +import cn.hutool.extra.spring.SpringUtil; | |
| 6 | +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | |
| 7 | +import org.flowable.bpmn.model.BpmnModel; | |
| 8 | +import org.flowable.bpmn.model.ExtensionElement; | |
| 9 | +import org.flowable.bpmn.model.FlowElement; | |
| 10 | +import org.flowable.bpmn.model.FlowNode; | |
| 11 | +import org.flowable.engine.RepositoryService; | |
| 12 | +import org.flowable.engine.RuntimeService; | |
| 13 | +import org.flowable.engine.TaskService; | |
| 14 | +import org.flowable.engine.repository.ProcessDefinition; | |
| 15 | +import org.flowable.engine.runtime.ProcessInstance; | |
| 16 | +import org.flowable.task.api.Task; | |
| 17 | + | |
| 18 | +import java.util.*; | |
| 19 | + | |
| 20 | +/** | |
| 21 | + * 流程引擎工具类封装 | |
| 22 | + * | |
| 23 | + * @author: linjinp | |
| 24 | + * @create: 2019-12-24 13:51 | |
| 25 | + **/ | |
| 26 | +public class FlowableUtils { | |
| 27 | + | |
| 28 | + /** | |
| 29 | + * 获取流程名称 | |
| 30 | + * | |
| 31 | + * @param processDefinitionId | |
| 32 | + * @return | |
| 33 | + */ | |
| 34 | + public static String getProcessDefinitionName(String processDefinitionId) { | |
| 35 | + RepositoryService repositoryService = SpringUtil.getBean(RepositoryService.class); | |
| 36 | + ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); | |
| 37 | + return processDefinition.getName(); | |
| 38 | + } | |
| 39 | + | |
| 40 | + public static ProcessDefinition getProcessDefinition(String processDefinitionId) { | |
| 41 | + RepositoryService repositoryService = SpringUtil.getBean(RepositoryService.class); | |
| 42 | + return repositoryService.getProcessDefinition(processDefinitionId); | |
| 43 | + } | |
| 44 | + | |
| 45 | + /** | |
| 46 | + * 获取节点数据 | |
| 47 | + * | |
| 48 | + * @param processInstanceId | |
| 49 | + * @param nodeId | |
| 50 | + * @return | |
| 51 | + */ | |
| 52 | + public static FlowNode getFlowNode(String processInstanceId, String nodeId) { | |
| 53 | + | |
| 54 | + RuntimeService runtimeService = SpringUtil.getBean(RuntimeService.class); | |
| 55 | + RepositoryService repositoryService = SpringUtil.getBean(RepositoryService.class); | |
| 56 | + | |
| 57 | + String definitionld = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult().getProcessDefinitionId(); // 获取bpm(模型)对象 | |
| 58 | + BpmnModel bpmnModel = repositoryService.getBpmnModel(definitionld); | |
| 59 | + // 传节点定义key获取当前节点 | |
| 60 | + FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(nodeId); | |
| 61 | + return flowNode; | |
| 62 | + } | |
| 63 | + | |
| 64 | + public static ExtensionElement generateFlowNodeIdExtension(String nodeId) { | |
| 65 | + ExtensionElement extensionElement = new ExtensionElement(); | |
| 66 | + extensionElement.setElementText(nodeId); | |
| 67 | + extensionElement.setName("nodeId"); | |
| 68 | + extensionElement.setNamespacePrefix("flowable"); | |
| 69 | + extensionElement.setNamespace("nodeId"); | |
| 70 | + return extensionElement; | |
| 71 | + } | |
| 72 | + | |
| 73 | + public static String getNodeIdFromExtension(FlowElement flowElement) { | |
| 74 | + Map<String, List<ExtensionElement>> extensionElements = flowElement.getExtensionElements(); | |
| 75 | + return extensionElements.get("nodeId").get(0).getElementText(); | |
| 76 | + } | |
| 77 | + | |
| 78 | + public static Long getStartUserIdFromProcessInstance(ProcessInstance instance) { | |
| 79 | + if (null == instance) { | |
| 80 | + return null; | |
| 81 | + } | |
| 82 | + return NumberUtils.parseLong(instance.getStartUserId()); | |
| 83 | + } | |
| 84 | + | |
| 85 | + public static String getTaskNameByTaskId(String taskId) { | |
| 86 | + TaskService taskService = SpringUtil.getBean(TaskService.class); | |
| 87 | + Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); | |
| 88 | + return task.getName(); | |
| 89 | + } | |
| 90 | + | |
| 91 | + public static Map<String/* taskId */, String/* taskName */> getTaskNameByTaskIds(Collection<String> taskIds) { | |
| 92 | + TaskService taskService = SpringUtil.getBean(TaskService.class); | |
| 93 | + List<Task> tasks = taskService.createTaskQuery().taskIds(taskIds).list(); | |
| 94 | + if (CollUtil.isNotEmpty(tasks)) { | |
| 95 | + Map<String/* taskId */, String/* taskName */> taskMap = new HashMap<>(tasks.size()); | |
| 96 | + for (Task task : tasks) { | |
| 97 | + taskMap.putIfAbsent(task.getId(), task.getName()); | |
| 98 | + } | |
| 99 | + return taskMap; | |
| 100 | + } | |
| 101 | + return Collections.emptyMap(); | |
| 102 | + } | |
| 103 | + | |
| 104 | + public static String getProcessInstanceNameByTaskId(String processInstanceId) { | |
| 105 | + RuntimeService runtimeService = SpringUtil.getBean(RuntimeService.class); | |
| 106 | + ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() | |
| 107 | + .processInstanceId(processInstanceId) | |
| 108 | + .singleResult(); | |
| 109 | + return processInstance.getName(); | |
| 110 | + } | |
| 111 | + | |
| 112 | + public static Map<String/* processInstaneId */, String/* processInstaneName */> getProcessInstanceNameByTaskIds(Set<String> taskIds) { | |
| 113 | + RuntimeService runtimeService = SpringUtil.getBean(RuntimeService.class); | |
| 114 | + List<ProcessInstance> processInstances = runtimeService.createProcessInstanceQuery().processInstanceIds(taskIds).list(); | |
| 115 | + if (CollUtil.isNotEmpty(processInstances)) { | |
| 116 | + Map<String/* processInstaneId */, String/* processInstaneName */> processInstaneMap = new HashMap<>(processInstances.size()); | |
| 117 | + for (ProcessInstance processInstance : processInstances) { | |
| 118 | + processInstaneMap.putIfAbsent(processInstance.getId(), processInstance.getName()); | |
| 119 | + } | |
| 120 | + return processInstaneMap; | |
| 121 | + } | |
| 122 | + return Collections.emptyMap(); | |
| 123 | + } | |
| 124 | + | |
| 125 | +} | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfoProcessorChainTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.candidate; | |
| 2 | + | |
| 3 | +import cn.hutool.core.map.MapUtil; | |
| 4 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | |
| 5 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 6 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | |
| 7 | +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO; | |
| 8 | +import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO; | |
| 9 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; | |
| 10 | +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskRuleScriptEnum; | |
| 11 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript; | |
| 12 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl.BpmTaskAssignLeaderX1Script; | |
| 13 | +import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.impl.BpmTaskAssignLeaderX2Script; | |
| 14 | +import cn.iocoder.yudao.module.bpm.service.candidate.sourceInfoProcessor.BpmCandidateScriptApiSourceInfoProcessor; | |
| 15 | +import cn.iocoder.yudao.module.bpm.service.definition.BpmUserGroupService; | |
| 16 | +import cn.iocoder.yudao.module.system.api.dept.DeptApi; | |
| 17 | +import cn.iocoder.yudao.module.system.api.dept.PostApi; | |
| 18 | +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; | |
| 19 | +import cn.iocoder.yudao.module.system.api.dict.DictDataApi; | |
| 20 | +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; | |
| 21 | +import cn.iocoder.yudao.module.system.api.permission.RoleApi; | |
| 22 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | |
| 23 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | |
| 24 | +import jakarta.annotation.Resource; | |
| 25 | +import org.flowable.engine.delegate.DelegateExecution; | |
| 26 | +import org.junit.jupiter.api.Test; | |
| 27 | +import org.springframework.boot.test.mock.mockito.MockBean; | |
| 28 | +import org.springframework.context.annotation.Import; | |
| 29 | + | |
| 30 | +import java.util.Arrays; | |
| 31 | +import java.util.List; | |
| 32 | +import java.util.Map; | |
| 33 | +import java.util.Set; | |
| 34 | + | |
| 35 | +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; | |
| 36 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | |
| 37 | +import static java.util.Collections.singleton; | |
| 38 | +import static org.junit.jupiter.api.Assertions.assertEquals; | |
| 39 | +import static org.mockito.ArgumentMatchers.eq; | |
| 40 | +import static org.mockito.Mockito.when; | |
| 41 | + | |
| 42 | +@Import({BpmCandidateSourceInfoProcessorChain.class, | |
| 43 | + BpmCandidateScriptApiSourceInfoProcessor.class, BpmTaskAssignLeaderX1Script.class, | |
| 44 | + BpmTaskAssignLeaderX2Script.class}) | |
| 45 | +public class BpmCandidateSourceInfoProcessorChainTest extends BaseDbUnitTest { | |
| 46 | + @Resource | |
| 47 | + private BpmCandidateSourceInfoProcessorChain processorChain; | |
| 48 | + | |
| 49 | + @MockBean | |
| 50 | + private BpmUserGroupService userGroupService; | |
| 51 | + @MockBean | |
| 52 | + private DeptApi deptApi; | |
| 53 | + @MockBean | |
| 54 | + private AdminUserApi adminUserApi; | |
| 55 | + @MockBean | |
| 56 | + private PermissionApi permissionApi; | |
| 57 | + @MockBean | |
| 58 | + private RoleApi roleApi; | |
| 59 | + @MockBean | |
| 60 | + private PostApi postApi; | |
| 61 | + @MockBean | |
| 62 | + private DictDataApi dictDataApi; | |
| 63 | + @Resource | |
| 64 | + private BpmCandidateScriptApiSourceInfoProcessor bpmCandidateScriptApiSourceInfoProcessor; | |
| 65 | + | |
| 66 | + @Test | |
| 67 | + public void testCalculateTaskCandidateUsers_Role() { | |
| 68 | + // 准备参数 | |
| 69 | + BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(1L, 2L)) | |
| 70 | + .setType(BpmTaskAssignRuleTypeEnum.ROLE.getType()); | |
| 71 | + // mock 方法 | |
| 72 | + when(permissionApi.getUserRoleIdListByRoleIds(eq(rule.getOptions()))) | |
| 73 | + .thenReturn(asSet(11L, 22L)); | |
| 74 | + mockGetUserMap(asSet(11L, 22L)); | |
| 75 | + | |
| 76 | + // 调用 | |
| 77 | + BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo(); | |
| 78 | + sourceInfo.addRule(rule); | |
| 79 | + Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo); | |
| 80 | + // 断言 | |
| 81 | + assertEquals(asSet(11L, 22L), results); | |
| 82 | + } | |
| 83 | + | |
| 84 | + @Test | |
| 85 | + public void testCalculateTaskCandidateUsers_DeptMember() { | |
| 86 | + // 准备参数 | |
| 87 | + BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(1L, 2L)) | |
| 88 | + .setType(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType()); | |
| 89 | + // mock 方法 | |
| 90 | + List<AdminUserRespDTO> users = CollectionUtils.convertList(asSet(11L, 22L), | |
| 91 | + id -> new AdminUserRespDTO().setId(id)); | |
| 92 | + when(adminUserApi.getUserListByDeptIds(eq(rule.getOptions()))).thenReturn(users); | |
| 93 | + mockGetUserMap(asSet(11L, 22L)); | |
| 94 | + | |
| 95 | + // 调用 | |
| 96 | + BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo(); | |
| 97 | + sourceInfo.addRule(rule); | |
| 98 | + Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo); | |
| 99 | + // 断言 | |
| 100 | + assertEquals(asSet(11L, 22L), results); | |
| 101 | + } | |
| 102 | + | |
| 103 | + @Test | |
| 104 | + public void testCalculateTaskCandidateUsers_DeptLeader() { | |
| 105 | + // 准备参数 | |
| 106 | + BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(1L, 2L)) | |
| 107 | + .setType(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType()); | |
| 108 | + // mock 方法 | |
| 109 | + DeptRespDTO dept1 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(11L)); | |
| 110 | + DeptRespDTO dept2 = randomPojo(DeptRespDTO.class, o -> o.setLeaderUserId(22L)); | |
| 111 | + when(deptApi.getDeptList(eq(rule.getOptions()))).thenReturn(Arrays.asList(dept1, dept2)); | |
| 112 | + mockGetUserMap(asSet(11L, 22L)); | |
| 113 | + | |
| 114 | + // 调用 | |
| 115 | + BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo(); | |
| 116 | + sourceInfo.addRule(rule); | |
| 117 | + Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo); | |
| 118 | + // 断言 | |
| 119 | + assertEquals(asSet(11L, 22L), results); | |
| 120 | + } | |
| 121 | + | |
| 122 | + @Test | |
| 123 | + public void testCalculateTaskCandidateUsers_Post() { | |
| 124 | + // 准备参数 | |
| 125 | + BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(1L, 2L)) | |
| 126 | + .setType(BpmTaskAssignRuleTypeEnum.POST.getType()); | |
| 127 | + // mock 方法 | |
| 128 | + List<AdminUserRespDTO> users = CollectionUtils.convertList(asSet(11L, 22L), | |
| 129 | + id -> new AdminUserRespDTO().setId(id)); | |
| 130 | + when(adminUserApi.getUserListByPostIds(eq(rule.getOptions()))).thenReturn(users); | |
| 131 | + mockGetUserMap(asSet(11L, 22L)); | |
| 132 | + | |
| 133 | + // 调用 | |
| 134 | + BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo(); | |
| 135 | + sourceInfo.addRule(rule); | |
| 136 | + Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo); | |
| 137 | + // 断言 | |
| 138 | + assertEquals(asSet(11L, 22L), results); | |
| 139 | + } | |
| 140 | + | |
| 141 | + @Test | |
| 142 | + public void testCalculateTaskCandidateUsers_User() { | |
| 143 | + // 准备参数 | |
| 144 | + BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(1L, 2L)) | |
| 145 | + .setType(BpmTaskAssignRuleTypeEnum.USER.getType()); | |
| 146 | + // mock 方法 | |
| 147 | + mockGetUserMap(asSet(1L, 2L)); | |
| 148 | + | |
| 149 | + // 调用 | |
| 150 | + BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo(); | |
| 151 | + sourceInfo.addRule(rule); | |
| 152 | + Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo); | |
| 153 | + // 断言 | |
| 154 | + assertEquals(asSet(1L, 2L), results); | |
| 155 | + } | |
| 156 | + | |
| 157 | + @Test | |
| 158 | + public void testCalculateTaskCandidateUsers_UserGroup() { | |
| 159 | + // 准备参数 | |
| 160 | + BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(1L, 2L)) | |
| 161 | + .setType(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType()); | |
| 162 | + // mock 方法 | |
| 163 | + BpmUserGroupDO userGroup1 = randomPojo(BpmUserGroupDO.class, o -> o.setMemberUserIds(asSet(11L, 12L))); | |
| 164 | + BpmUserGroupDO userGroup2 = randomPojo(BpmUserGroupDO.class, o -> o.setMemberUserIds(asSet(21L, 22L))); | |
| 165 | + when(userGroupService.getUserGroupList(eq(rule.getOptions()))).thenReturn(Arrays.asList(userGroup1, userGroup2)); | |
| 166 | + mockGetUserMap(asSet(11L, 12L, 21L, 22L)); | |
| 167 | + | |
| 168 | + // 调用 | |
| 169 | + BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo(); | |
| 170 | + sourceInfo.addRule(rule); | |
| 171 | + Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo); | |
| 172 | + // 断言 | |
| 173 | + assertEquals(asSet(11L, 12L, 21L, 22L), results); | |
| 174 | + } | |
| 175 | + | |
| 176 | + private void mockGetUserMap(Set<Long> assigneeUserIds) { | |
| 177 | + Map<Long, AdminUserRespDTO> userMap = CollectionUtils.convertMap(assigneeUserIds, id -> id, | |
| 178 | + id -> new AdminUserRespDTO().setId(id).setStatus(CommonStatusEnum.ENABLE.getStatus())); | |
| 179 | + when(adminUserApi.getUserMap(eq(assigneeUserIds))).thenReturn(userMap); | |
| 180 | + } | |
| 181 | + | |
| 182 | + @Test | |
| 183 | + public void testCalculateTaskCandidateUsers_Script() { | |
| 184 | + // 准备参数 | |
| 185 | + BpmTaskCandidateRuleVO rule = new BpmTaskCandidateRuleVO().setOptions(asSet(20L, 21L)) | |
| 186 | + .setType(BpmTaskAssignRuleTypeEnum.SCRIPT.getType()); | |
| 187 | + // mock 方法 | |
| 188 | + BpmTaskAssignScript script1 = new BpmTaskAssignScript() { | |
| 189 | + | |
| 190 | + @Override | |
| 191 | + public Set<Long> calculateTaskCandidateUsers(DelegateExecution task) { | |
| 192 | + return singleton(11L); | |
| 193 | + } | |
| 194 | + | |
| 195 | + @Override | |
| 196 | + public BpmTaskRuleScriptEnum getEnum() { | |
| 197 | + return BpmTaskRuleScriptEnum.LEADER_X1; | |
| 198 | + } | |
| 199 | + }; | |
| 200 | + BpmTaskAssignScript script2 = new BpmTaskAssignScript() { | |
| 201 | + | |
| 202 | + @Override | |
| 203 | + public Set<Long> calculateTaskCandidateUsers(DelegateExecution task) { | |
| 204 | + return singleton(22L); | |
| 205 | + } | |
| 206 | + | |
| 207 | + @Override | |
| 208 | + public BpmTaskRuleScriptEnum getEnum() { | |
| 209 | + return BpmTaskRuleScriptEnum.LEADER_X2; | |
| 210 | + } | |
| 211 | + }; | |
| 212 | + bpmCandidateScriptApiSourceInfoProcessor.setScripts(Arrays.asList(script1, script2)); | |
| 213 | + mockGetUserMap(asSet(11L, 22L)); | |
| 214 | + | |
| 215 | + // 调用 | |
| 216 | + BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo(); | |
| 217 | + sourceInfo.addRule(rule); | |
| 218 | + Set<Long> results = processorChain.calculateTaskCandidateUsers(null, sourceInfo); | |
| 219 | + // 断言 | |
| 220 | + assertEquals(asSet(11L, 22L), results); | |
| 221 | + } | |
| 222 | + | |
| 223 | + @Test | |
| 224 | + public void testRemoveDisableUsers() { | |
| 225 | + // 准备参数. 1L 可以找到;2L 是禁用的;3L 找不到 | |
| 226 | + Set<Long> assigneeUserIds = asSet(1L, 2L, 3L); | |
| 227 | + // mock 方法 | |
| 228 | + AdminUserRespDTO user1 = randomPojo(AdminUserRespDTO.class, o -> o.setId(1L) | |
| 229 | + .setStatus(CommonStatusEnum.ENABLE.getStatus())); | |
| 230 | + AdminUserRespDTO user2 = randomPojo(AdminUserRespDTO.class, o -> o.setId(2L) | |
| 231 | + .setStatus(CommonStatusEnum.DISABLE.getStatus())); | |
| 232 | + Map<Long, AdminUserRespDTO> userMap = MapUtil.builder(user1.getId(), user1) | |
| 233 | + .put(user2.getId(), user2).build(); | |
| 234 | + when(adminUserApi.getUserMap(eq(assigneeUserIds))).thenReturn(userMap); | |
| 235 | + | |
| 236 | + // 调用 | |
| 237 | + processorChain.removeDisableUsers(assigneeUserIds); | |
| 238 | + // 断言 | |
| 239 | + assertEquals(asSet(1L), assigneeUserIds); | |
| 240 | + } | |
| 241 | + | |
| 242 | +} | |
| 0 | 243 | \ No newline at end of file | ... | ... |
yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyServiceTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.service.cc; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | |
| 4 | +import jakarta.annotation.Resource; | |
| 5 | +import org.junit.jupiter.api.Test; | |
| 6 | +import org.springframework.context.annotation.Import; | |
| 7 | + | |
| 8 | +@Import({BpmProcessInstanceCopyServiceImpl.class}) | |
| 9 | +class BpmProcessInstanceCopyServiceTest extends BaseDbUnitTest { | |
| 10 | + @Resource | |
| 11 | + private BpmProcessInstanceCopyServiceImpl service; | |
| 12 | + | |
| 13 | + @Test | |
| 14 | + void queryById() { | |
| 15 | + } | |
| 16 | +} | |
| 0 | 17 | \ No newline at end of file | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/user/SocialUserBindReqVO.java
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/ip/AreaConvert.java