Commit 8c32eb24ec7c649660271a0cc0f6f2544c4d9978
1 parent
0a7f94dd
BPM:优化 task 加减签的实现
Showing
10 changed files
with
249 additions
and
247 deletions
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java
| @@ -50,10 +50,10 @@ public interface ErrorCodeConstants { | @@ -50,10 +50,10 @@ public interface ErrorCodeConstants { | ||
| 50 | ErrorCode TASK_RETURN_FAIL_SOURCE_TARGET_ERROR = new ErrorCode(1_009_005_006, "回退任务失败,目标节点是在并行网关上或非同一路线上,不可跳转"); | 50 | ErrorCode TASK_RETURN_FAIL_SOURCE_TARGET_ERROR = new ErrorCode(1_009_005_006, "回退任务失败,目标节点是在并行网关上或非同一路线上,不可跳转"); |
| 51 | ErrorCode TASK_DELEGATE_FAIL_USER_REPEAT = new ErrorCode(1_009_005_007, "任务委派失败,委派人和当前审批人为同一人"); | 51 | ErrorCode TASK_DELEGATE_FAIL_USER_REPEAT = new ErrorCode(1_009_005_007, "任务委派失败,委派人和当前审批人为同一人"); |
| 52 | ErrorCode TASK_DELEGATE_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_008, "任务委派失败,被委派人不存在"); | 52 | ErrorCode TASK_DELEGATE_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_008, "任务委派失败,被委派人不存在"); |
| 53 | - ErrorCode TASK_ADD_SIGN_USER_NOT_EXIST = new ErrorCode(1_009_005_009, "任务加签:选择的用户不存在"); | ||
| 54 | - ErrorCode TASK_ADD_SIGN_TYPE_ERROR = new ErrorCode(1_009_005_010, "任务加签:当前任务已经{},不能{}"); | ||
| 55 | - ErrorCode TASK_ADD_SIGN_USER_REPEAT = new ErrorCode(1_009_005_011, "任务加签失败,加签人与现有审批人[{}]重复"); | ||
| 56 | - ErrorCode TASK_SUB_SIGN_NO_PARENT = new ErrorCode(1_009_005_012, "任务减签失败,被减签的任务必须是通过加签生成的任务"); | 53 | + ErrorCode TASK_SIGN_CREATE_USER_NOT_EXIST = new ErrorCode(1_009_005_009, "任务加签:选择的用户不存在"); |
| 54 | + ErrorCode TASK_SIGN_CREATE_TYPE_ERROR = new ErrorCode(1_009_005_010, "任务加签:当前任务已经{},不能{}"); | ||
| 55 | + ErrorCode TASK_SIGN_CREATE_USER_REPEAT = new ErrorCode(1_009_005_011, "任务加签失败,加签人与现有审批人[{}]重复"); | ||
| 56 | + ErrorCode TASK_SIGN_DELETE_NO_PARENT = new ErrorCode(1_009_005_012, "任务减签失败,被减签的任务必须是通过加签生成的任务"); | ||
| 57 | ErrorCode TASK_TRANSFER_FAIL_USER_REPEAT = new ErrorCode(1_009_005_013, "任务转办失败,转办人和当前审批人为同一人"); | 57 | ErrorCode TASK_TRANSFER_FAIL_USER_REPEAT = new ErrorCode(1_009_005_013, "任务转办失败,转办人和当前审批人为同一人"); |
| 58 | ErrorCode TASK_TRANSFER_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_014, "任务转办失败,转办人不存在"); | 58 | ErrorCode TASK_TRANSFER_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_014, "任务转办失败,转办人不存在"); |
| 59 | 59 |
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskAddSignTypeEnum.java renamed to yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskSignTypeEnum.java
| 1 | package cn.iocoder.yudao.module.bpm.enums.task; | 1 | package cn.iocoder.yudao.module.bpm.enums.task; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.util.ArrayUtil; | ||
| 3 | import lombok.AllArgsConstructor; | 4 | import lombok.AllArgsConstructor; |
| 4 | import lombok.Getter; | 5 | import lombok.Getter; |
| 5 | 6 | ||
| 6 | /** | 7 | /** |
| 7 | - * 流程任务 -- 加签类型枚举类型 | 8 | + * 流程任务的加签类型枚举 |
| 9 | + * | ||
| 10 | + * @author kehaiyou | ||
| 8 | */ | 11 | */ |
| 9 | @Getter | 12 | @Getter |
| 10 | @AllArgsConstructor | 13 | @AllArgsConstructor |
| 11 | -public enum BpmTaskAddSignTypeEnum { | 14 | +public enum BpmTaskSignTypeEnum { |
| 12 | 15 | ||
| 13 | /** | 16 | /** |
| 14 | * 向前加签,需要前置任务审批完成,才回到原审批人 | 17 | * 向前加签,需要前置任务审批完成,才回到原审批人 |
| @@ -19,17 +22,26 @@ public enum BpmTaskAddSignTypeEnum { | @@ -19,17 +22,26 @@ public enum BpmTaskAddSignTypeEnum { | ||
| 19 | */ | 22 | */ |
| 20 | AFTER("after", "向后加签"); | 23 | AFTER("after", "向后加签"); |
| 21 | 24 | ||
| 25 | + /** | ||
| 26 | + * 类型 | ||
| 27 | + */ | ||
| 22 | private final String type; | 28 | private final String type; |
| 29 | + /** | ||
| 30 | + * 名字 | ||
| 31 | + */ | ||
| 32 | + private final String name; | ||
| 23 | 33 | ||
| 24 | - private final String desc; // TODO 芋艿:desc | ||
| 25 | - | ||
| 26 | - public static String formatDesc(String type) { | ||
| 27 | - for (BpmTaskAddSignTypeEnum value : values()) { | 34 | + public static String nameOfType(String type) { |
| 35 | + for (BpmTaskSignTypeEnum value : values()) { | ||
| 28 | if (value.type.equals(type)) { | 36 | if (value.type.equals(type)) { |
| 29 | - return value.desc; | 37 | + return value.name; |
| 30 | } | 38 | } |
| 31 | } | 39 | } |
| 32 | return null; | 40 | return null; |
| 33 | } | 41 | } |
| 34 | 42 | ||
| 43 | + public static BpmTaskSignTypeEnum of(String type) { | ||
| 44 | + return ArrayUtil.firstMatch(value -> value.getType().equals(type), values()); | ||
| 45 | + } | ||
| 46 | + | ||
| 35 | } | 47 | } |
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskStatustEnum.java
| @@ -22,23 +22,16 @@ public enum BpmTaskStatustEnum { | @@ -22,23 +22,16 @@ public enum BpmTaskStatustEnum { | ||
| 22 | DELEGATE(6, "委派中"), | 22 | DELEGATE(6, "委派中"), |
| 23 | 23 | ||
| 24 | /** | 24 | /** |
| 25 | - * 【加签】源任务已经审批完成,但是它使用了后加签,后加签的任务未完成,源任务就会是这个状态 | ||
| 26 | - * 相当于是 通过 APPROVE 的特殊状态 | ||
| 27 | - * 例如:A 审批,A 后加签了 B,并且审批通过了任务,但是 B 还未审批,则当前任务状态为“待后加签任务完成” | 25 | + * 使用场景: |
| 26 | + * 1. 任务被向后【加签】时,它在审批通过后,会变成 APPROVING 这个状态,然后等到【加签】出来的任务都被审批后,才会变成 APPROVE 审批通过 | ||
| 28 | */ | 27 | */ |
| 29 | APPROVING(7, "审批通过中"), | 28 | APPROVING(7, "审批通过中"), |
| 30 | /** | 29 | /** |
| 31 | - * 【加签】源任务未审批,但是向前加签了,所以源任务状态变为“待前加签任务完成” | ||
| 32 | - * 相当于是 处理中 PROCESS 的特殊状态 | ||
| 33 | - * 例如:A 审批,A 前加签了 B,B 还未审核 | 30 | + * 使用场景: |
| 31 | + * 1. 任务被向前【加签】时,它会变成 WAIT 状态,需要等待【加签】出来的任务被审批后,它才能继续变为 RUNNING 继续审批 | ||
| 32 | + * 2. 任务被向后【加签】时,【加签】出来的任务处于 WAIT 状态,它们需要等待该任务被审批后,它们才能继续变为 RUNNING 继续审批 | ||
| 34 | */ | 33 | */ |
| 35 | WAIT(0, "待审批"); | 34 | WAIT(0, "待审批"); |
| 36 | -// /** | ||
| 37 | -// * 【加签】后加签任务被创建时的初始状态 | ||
| 38 | -// * 相当于是 处理中 PROCESS 的特殊状态 | ||
| 39 | -// * 因为需要源任务先完成,才能到后加签的人来审批,所以加了一个状态区分 | ||
| 40 | -// */ | ||
| 41 | -// WAIT_BEFORE_TASK(9, "处理中【待前置任务完成】"); | ||
| 42 | 35 | ||
| 43 | /** | 36 | /** |
| 44 | * 状态 | 37 | * 状态 |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java
| @@ -4,8 +4,6 @@ import cn.hutool.core.collection.CollUtil; | @@ -4,8 +4,6 @@ import cn.hutool.core.collection.CollUtil; | ||
| 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | 6 | import cn.iocoder.yudao.framework.common.util.number.NumberUtils; |
| 7 | -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 8 | -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO; | ||
| 9 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; | 7 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; |
| 10 | import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; | 8 | import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; |
| 11 | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; | 9 | import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; |
| @@ -94,7 +92,8 @@ public class BpmTaskController { | @@ -94,7 +92,8 @@ public class BpmTaskController { | ||
| 94 | // 拼接数据 | 92 | // 拼接数据 |
| 95 | HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(processInstanceId); | 93 | HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(processInstanceId); |
| 96 | // 获得 User 和 Dept Map | 94 | // 获得 User 和 Dept Map |
| 97 | - Set<Long> userIds = convertSet(taskList, task -> NumberUtils.parseLong(task.getAssignee())); | 95 | + Set<Long> userIds = convertSetByFlatMap(taskList, task -> |
| 96 | + Stream.of(NumberUtils.parseLong(task.getAssignee()), NumberUtils.parseLong(task.getOwner()))); | ||
| 98 | userIds.add(NumberUtils.parseLong(processInstance.getStartUserId())); | 97 | userIds.add(NumberUtils.parseLong(processInstance.getStartUserId())); |
| 99 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); | 98 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); |
| 100 | Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap( | 99 | Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap( |
| @@ -155,7 +154,7 @@ public class BpmTaskController { | @@ -155,7 +154,7 @@ public class BpmTaskController { | ||
| 155 | @PutMapping("/create-sign") | 154 | @PutMapping("/create-sign") |
| 156 | @Operation(summary = "加签", description = "before 前加签,after 后加签") | 155 | @Operation(summary = "加签", description = "before 前加签,after 后加签") |
| 157 | @PreAuthorize("@ss.hasPermission('bpm:task:update')") | 156 | @PreAuthorize("@ss.hasPermission('bpm:task:update')") |
| 158 | - public CommonResult<Boolean> createSignTask(@Valid @RequestBody BpmTaskAddSignReqVO reqVO) { | 157 | + public CommonResult<Boolean> createSignTask(@Valid @RequestBody BpmTaskSignCreateReqVO reqVO) { |
| 159 | taskService.createSignTask(getLoginUserId(), reqVO); | 158 | taskService.createSignTask(getLoginUserId(), reqVO); |
| 160 | return success(true); | 159 | return success(true); |
| 161 | } | 160 | } |
| @@ -163,13 +162,12 @@ public class BpmTaskController { | @@ -163,13 +162,12 @@ public class BpmTaskController { | ||
| 163 | @DeleteMapping("/delete-sign") | 162 | @DeleteMapping("/delete-sign") |
| 164 | @Operation(summary = "减签") | 163 | @Operation(summary = "减签") |
| 165 | @PreAuthorize("@ss.hasPermission('bpm:task:update')") | 164 | @PreAuthorize("@ss.hasPermission('bpm:task:update')") |
| 166 | - public CommonResult<Boolean> deleteSignTask(@Valid @RequestBody BpmTaskSubSignReqVO reqVO) { | 165 | + public CommonResult<Boolean> deleteSignTask(@Valid @RequestBody BpmTaskSignDeleteReqVO reqVO) { |
| 167 | taskService.deleteSignTask(getLoginUserId(), reqVO); | 166 | taskService.deleteSignTask(getLoginUserId(), reqVO); |
| 168 | return success(true); | 167 | return success(true); |
| 169 | } | 168 | } |
| 170 | 169 | ||
| 171 | - // TODO 芋艿:待测试 | ||
| 172 | - @GetMapping("list-by-parent-task-id") | 170 | + @GetMapping("/list-by-parent-task-id") |
| 173 | @Operation(summary = "获得指定父级任务的子任务列表") // 目前用于,减签的时候,获得子任务列表 | 171 | @Operation(summary = "获得指定父级任务的子任务列表") // 目前用于,减签的时候,获得子任务列表 |
| 174 | @Parameter(name = "parentTaskId", description = "父级任务编号", required = true) | 172 | @Parameter(name = "parentTaskId", description = "父级任务编号", required = true) |
| 175 | @PreAuthorize("@ss.hasPermission('bpm:task:query')") | 173 | @PreAuthorize("@ss.hasPermission('bpm:task:query')") |
| @@ -179,12 +177,11 @@ public class BpmTaskController { | @@ -179,12 +177,11 @@ public class BpmTaskController { | ||
| 179 | return success(Collections.emptyList()); | 177 | return success(Collections.emptyList()); |
| 180 | } | 178 | } |
| 181 | // 拼接数据 | 179 | // 拼接数据 |
| 182 | - Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( | ||
| 183 | - convertSetByFlatMap(taskList, user -> Stream.of(Long.valueOf(user.getAssignee()), Long.valueOf(user.getOwner())))); | ||
| 184 | - return success(convertList(taskList, task -> BeanUtils.toBean(task, BpmTaskRespVO.class, taskVO -> { | ||
| 185 | - taskVO.setAssigneeUser(BeanUtils.toBean(userMap.get(NumberUtils.parseLong(task.getAssignee())), BpmProcessInstanceRespVO.User.class)); | ||
| 186 | - taskVO.setOwnerUser(BeanUtils.toBean(userMap.get(NumberUtils.parseLong(task.getOwner())), BpmProcessInstanceRespVO.User.class)); | ||
| 187 | - }))); | 180 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSetByFlatMap(taskList, |
| 181 | + user -> Stream.of(NumberUtils.parseLong(user.getAssignee()), NumberUtils.parseLong(user.getOwner())))); | ||
| 182 | + Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap( | ||
| 183 | + convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); | ||
| 184 | + return success(BpmTaskConvert.INSTANCE.buildTaskListByParentTaskId(taskList, userMap, deptMap)); | ||
| 188 | } | 185 | } |
| 189 | 186 | ||
| 190 | } | 187 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskAddSignReqVO.java deleted
| 1 | -package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; | ||
| 2 | - | ||
| 3 | -import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | -import lombok.Data; | ||
| 5 | - | ||
| 6 | -import jakarta.validation.constraints.NotEmpty; | ||
| 7 | -import java.util.Set; | ||
| 8 | - | ||
| 9 | -// TODO @海洋:类名,应该是 create 哈 | ||
| 10 | -@Schema(description = "管理后台 - 加签流程任务的 Request VO") | ||
| 11 | -@Data | ||
| 12 | -public class BpmTaskAddSignReqVO { | ||
| 13 | - | ||
| 14 | - @Schema(description = "需要加签的任务 ID") | ||
| 15 | - @NotEmpty(message = "任务编号不能为空") | ||
| 16 | - private String id; | ||
| 17 | - | ||
| 18 | - @Schema(description = "加签的用户 ID") | ||
| 19 | - @NotEmpty(message = "加签用户 ID 不能为空") | ||
| 20 | - private Set<Long> userIdList; | ||
| 21 | - | ||
| 22 | - @Schema(description = "加签类型,before 向前加签,after 向后加签") | ||
| 23 | - @NotEmpty(message = "加签类型不能为空") | ||
| 24 | - private String type; | ||
| 25 | - | ||
| 26 | - @Schema(description = "加签原因") | ||
| 27 | - @NotEmpty(message = "加签原因不能为空") | ||
| 28 | - private String reason; | ||
| 29 | - | ||
| 30 | -} |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskSignCreateReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import jakarta.validation.constraints.NotEmpty; | ||
| 7 | +import java.util.Set; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - 加签任务的创建(加签) Request VO") | ||
| 10 | +@Data | ||
| 11 | +public class BpmTaskSignCreateReqVO { | ||
| 12 | + | ||
| 13 | + @Schema(description = "需要加签的任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 14 | + @NotEmpty(message = "任务编号不能为空") | ||
| 15 | + private String id; | ||
| 16 | + | ||
| 17 | + @Schema(description = "加签的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "888") | ||
| 18 | + @NotEmpty(message = "加签用户不能为空") | ||
| 19 | + private Set<Long> userIds; | ||
| 20 | + | ||
| 21 | + @Schema(description = "加签类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "before") | ||
| 22 | + @NotEmpty(message = "加签类型不能为空") | ||
| 23 | + private String type; // 参见 BpmTaskSignTypeEnum 枚举 | ||
| 24 | + | ||
| 25 | + @Schema(description = "加签原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "需要加签") | ||
| 26 | + @NotEmpty(message = "加签原因不能为空") | ||
| 27 | + private String reason; | ||
| 28 | + | ||
| 29 | +} |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskSubSignReqVO.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskSignDeleteReqVO.java
| @@ -5,16 +5,16 @@ import lombok.Data; | @@ -5,16 +5,16 @@ import lombok.Data; | ||
| 5 | 5 | ||
| 6 | import jakarta.validation.constraints.NotEmpty; | 6 | import jakarta.validation.constraints.NotEmpty; |
| 7 | 7 | ||
| 8 | -// TODO @海洋:类名,应该是 delete 哈 | ||
| 9 | -@Schema(description = "管理后台 - 减签流程任务的 Request VO") | 8 | +@Schema(description = "管理后台 - 加签任务的删除(减签) Request VO") |
| 10 | @Data | 9 | @Data |
| 11 | -public class BpmTaskSubSignReqVO { | 10 | +public class BpmTaskSignDeleteReqVO { |
| 12 | 11 | ||
| 13 | - @Schema(description = "被减签的任务 ID") | 12 | + @Schema(description = "被减签的任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 14 | @NotEmpty(message = "任务编号不能为空") | 13 | @NotEmpty(message = "任务编号不能为空") |
| 15 | private String id; | 14 | private String id; |
| 16 | 15 | ||
| 17 | - @Schema(description = "加签原因") | 16 | + @Schema(description = "加签原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "需要减签") |
| 18 | @NotEmpty(message = "加签原因不能为空") | 17 | @NotEmpty(message = "加签原因不能为空") |
| 19 | private String reason; | 18 | private String reason; |
| 19 | + | ||
| 20 | } | 20 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
| @@ -24,8 +24,7 @@ import java.util.Date; | @@ -24,8 +24,7 @@ import java.util.Date; | ||
| 24 | import java.util.List; | 24 | import java.util.List; |
| 25 | import java.util.Map; | 25 | import java.util.Map; |
| 26 | 26 | ||
| 27 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; | ||
| 28 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; | 27 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; |
| 29 | 28 | ||
| 30 | /** | 29 | /** |
| 31 | * Bpm 任务 Convert | 30 | * Bpm 任务 Convert |
| @@ -91,6 +90,14 @@ public interface BpmTaskConvert { | @@ -91,6 +90,14 @@ public interface BpmTaskConvert { | ||
| 91 | taskVO.getAssigneeUser().setDeptName(dept.getName()); | 90 | taskVO.getAssigneeUser().setDeptName(dept.getName()); |
| 92 | } | 91 | } |
| 93 | } | 92 | } |
| 93 | + AdminUserRespDTO ownerUser = userMap.get(NumberUtils.parseLong(task.getOwner())); | ||
| 94 | + if (ownerUser != null) { | ||
| 95 | + taskVO.setOwnerUser(BeanUtils.toBean(ownerUser, BpmProcessInstanceRespVO.User.class)); | ||
| 96 | + DeptRespDTO dept = deptMap.get(ownerUser.getDeptId()); | ||
| 97 | + if (dept != null) { | ||
| 98 | + taskVO.getOwnerUser().setDeptName(dept.getName()); | ||
| 99 | + } | ||
| 100 | + } | ||
| 94 | return taskVO; | 101 | return taskVO; |
| 95 | }); | 102 | }); |
| 96 | 103 | ||
| @@ -104,6 +111,29 @@ public interface BpmTaskConvert { | @@ -104,6 +111,29 @@ public interface BpmTaskConvert { | ||
| 104 | return filterList(taskVOList, r -> StrUtil.isEmpty(r.getParentTaskId())); | 111 | return filterList(taskVOList, r -> StrUtil.isEmpty(r.getParentTaskId())); |
| 105 | } | 112 | } |
| 106 | 113 | ||
| 114 | + default List<BpmTaskRespVO> buildTaskListByParentTaskId(List<Task> taskList, | ||
| 115 | + Map<Long, AdminUserRespDTO> userMap, | ||
| 116 | + Map<Long, DeptRespDTO> deptMap) { | ||
| 117 | + return convertList(taskList, task -> BeanUtils.toBean(task, BpmTaskRespVO.class, taskVO -> { | ||
| 118 | + AdminUserRespDTO assignUser = userMap.get(NumberUtils.parseLong(task.getAssignee())); | ||
| 119 | + if (assignUser != null) { | ||
| 120 | + taskVO.setAssigneeUser(BeanUtils.toBean(assignUser, BpmProcessInstanceRespVO.User.class)); | ||
| 121 | + DeptRespDTO dept = deptMap.get(assignUser.getDeptId()); | ||
| 122 | + if (dept != null) { | ||
| 123 | + taskVO.getAssigneeUser().setDeptName(dept.getName()); | ||
| 124 | + } | ||
| 125 | + } | ||
| 126 | + AdminUserRespDTO ownerUser = userMap.get(NumberUtils.parseLong(task.getOwner())); | ||
| 127 | + if (ownerUser != null) { | ||
| 128 | + taskVO.setOwnerUser(BeanUtils.toBean(ownerUser, BpmProcessInstanceRespVO.User.class)); | ||
| 129 | + DeptRespDTO dept = deptMap.get(ownerUser.getDeptId()); | ||
| 130 | + if (dept != null) { | ||
| 131 | + taskVO.getOwnerUser().setDeptName(dept.getName()); | ||
| 132 | + } | ||
| 133 | + } | ||
| 134 | + })); | ||
| 135 | + } | ||
| 136 | + | ||
| 107 | default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser, | 137 | default BpmMessageSendWhenTaskCreatedReqDTO convert(ProcessInstance processInstance, AdminUserRespDTO startUser, |
| 108 | Task task) { | 138 | Task task) { |
| 109 | BpmMessageSendWhenTaskCreatedReqDTO reqDTO = new BpmMessageSendWhenTaskCreatedReqDTO(); | 139 | BpmMessageSendWhenTaskCreatedReqDTO reqDTO = new BpmMessageSendWhenTaskCreatedReqDTO(); |
| @@ -114,22 +144,28 @@ public interface BpmTaskConvert { | @@ -114,22 +144,28 @@ public interface BpmTaskConvert { | ||
| 114 | return reqDTO; | 144 | return reqDTO; |
| 115 | } | 145 | } |
| 116 | 146 | ||
| 117 | - //此处不用 mapstruct 映射,因为 TaskEntityImpl 还有很多其他属性,这里我们只设置我们需要的 | ||
| 118 | - //使用 mapstruct 会将里面嵌套的各个属性值都设置进去,会出现意想不到的问题 | ||
| 119 | - default TaskEntityImpl convert(TaskEntityImpl task,TaskEntityImpl parentTask){ | ||
| 120 | - task.setCategory(parentTask.getCategory()); | ||
| 121 | - task.setDescription(parentTask.getDescription()); | ||
| 122 | - task.setTenantId(parentTask.getTenantId()); | ||
| 123 | - task.setName(parentTask.getName()); | ||
| 124 | - task.setParentTaskId(parentTask.getId()); | ||
| 125 | - task.setProcessDefinitionId(parentTask.getProcessDefinitionId()); | ||
| 126 | - task.setProcessInstanceId(parentTask.getProcessInstanceId()); | ||
| 127 | -// task.setExecutionId(parentTask.getExecutionId()); // TODO 芋艿:新加的,不太确定;尴尬,不加时,子任务不通过会失败(报错);加了,子任务审批通过会失败(报错) | ||
| 128 | - task.setTaskDefinitionKey(parentTask.getTaskDefinitionKey()); | ||
| 129 | - task.setTaskDefinitionId(parentTask.getTaskDefinitionId()); | ||
| 130 | - task.setPriority(parentTask.getPriority()); | ||
| 131 | - task.setCreateTime(new Date()); | ||
| 132 | - return task; | 147 | + /** |
| 148 | + * 将父任务的属性,拷贝到子任务(加签任务) | ||
| 149 | + * | ||
| 150 | + * 为什么不使用 mapstruct 映射?因为 TaskEntityImpl 还有很多其他属性,这里我们只设置我们需要的。 | ||
| 151 | + * 使用 mapstruct 会将里面嵌套的各个属性值都设置进去,会出现意想不到的问题。 | ||
| 152 | + * | ||
| 153 | + * @param parentTask 父任务 | ||
| 154 | + * @param childTask 加签任务 | ||
| 155 | + */ | ||
| 156 | + default void copyTo(TaskEntityImpl parentTask, TaskEntityImpl childTask) { | ||
| 157 | + childTask.setName(parentTask.getName()); | ||
| 158 | + childTask.setDescription(parentTask.getDescription()); | ||
| 159 | + childTask.setCategory(parentTask.getCategory()); | ||
| 160 | + childTask.setParentTaskId(parentTask.getId()); | ||
| 161 | + childTask.setProcessDefinitionId(parentTask.getProcessDefinitionId()); | ||
| 162 | + childTask.setProcessInstanceId(parentTask.getProcessInstanceId()); | ||
| 163 | +// childTask.setExecutionId(parentTask.getExecutionId()); // TODO 芋艿:新加的,不太确定;尴尬,不加时,子任务不通过会失败(报错);加了,子任务审批通过会失败(报错) | ||
| 164 | + childTask.setTaskDefinitionKey(parentTask.getTaskDefinitionKey()); | ||
| 165 | + childTask.setTaskDefinitionId(parentTask.getTaskDefinitionId()); | ||
| 166 | + childTask.setPriority(parentTask.getPriority()); | ||
| 167 | + childTask.setCreateTime(new Date()); | ||
| 168 | + childTask.setTenantId(parentTask.getTenantId()); | ||
| 133 | } | 169 | } |
| 134 | 170 | ||
| 135 | } | 171 | } |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java
| @@ -148,7 +148,7 @@ public interface BpmTaskService { | @@ -148,7 +148,7 @@ public interface BpmTaskService { | ||
| 148 | * @param userId 被加签的用户和任务 ID,加签类型 | 148 | * @param userId 被加签的用户和任务 ID,加签类型 |
| 149 | * @param reqVO 当前用户 ID | 149 | * @param reqVO 当前用户 ID |
| 150 | */ | 150 | */ |
| 151 | - void createSignTask(Long userId, BpmTaskAddSignReqVO reqVO); | 151 | + void createSignTask(Long userId, BpmTaskSignCreateReqVO reqVO); |
| 152 | 152 | ||
| 153 | /** | 153 | /** |
| 154 | * 任务减签 | 154 | * 任务减签 |
| @@ -156,7 +156,7 @@ public interface BpmTaskService { | @@ -156,7 +156,7 @@ public interface BpmTaskService { | ||
| 156 | * @param userId 当前用户ID | 156 | * @param userId 当前用户ID |
| 157 | * @param reqVO 被减签的任务 ID,理由 | 157 | * @param reqVO 被减签的任务 ID,理由 |
| 158 | */ | 158 | */ |
| 159 | - void deleteSignTask(Long userId, BpmTaskSubSignReqVO reqVO); | 159 | + void deleteSignTask(Long userId, BpmTaskSignDeleteReqVO reqVO); |
| 160 | 160 | ||
| 161 | /** | 161 | /** |
| 162 | * 获取指定任务的子任务列表 | 162 | * 获取指定任务的子任务列表 |
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
| @@ -13,7 +13,10 @@ import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils; | @@ -13,7 +13,10 @@ import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils; | ||
| 13 | import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; | 13 | import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; |
| 14 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; | 14 | import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; |
| 15 | import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; | 15 | import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; |
| 16 | -import cn.iocoder.yudao.module.bpm.enums.task.*; | 16 | +import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum; |
| 17 | +import cn.iocoder.yudao.module.bpm.enums.task.BpmDeleteReasonEnum; | ||
| 18 | +import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskSignTypeEnum; | ||
| 19 | +import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatustEnum; | ||
| 17 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmConstants; | 20 | import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmConstants; |
| 18 | import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService; | 21 | import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService; |
| 19 | import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; | 22 | import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; |
| @@ -44,10 +47,10 @@ import org.springframework.transaction.support.TransactionSynchronizationManager | @@ -44,10 +47,10 @@ import org.springframework.transaction.support.TransactionSynchronizationManager | ||
| 44 | import org.springframework.util.Assert; | 47 | import org.springframework.util.Assert; |
| 45 | 48 | ||
| 46 | import java.util.*; | 49 | import java.util.*; |
| 50 | +import java.util.stream.Stream; | ||
| 47 | 51 | ||
| 48 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 52 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 49 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 50 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | 53 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; |
| 51 | import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; | 54 | import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; |
| 52 | 55 | ||
| 53 | /** | 56 | /** |
| @@ -170,7 +173,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -170,7 +173,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 170 | } | 173 | } |
| 171 | 174 | ||
| 172 | // 情况二:审批有【后】加签的任务 | 175 | // 情况二:审批有【后】加签的任务 |
| 173 | - if (BpmTaskAddSignTypeEnum.AFTER.getType().equals(task.getScopeType())) { | 176 | + if (BpmTaskSignTypeEnum.AFTER.getType().equals(task.getScopeType())) { |
| 174 | approveAfterSignTask(task, reqVO); | 177 | approveAfterSignTask(task, reqVO); |
| 175 | return; | 178 | return; |
| 176 | } | 179 | } |
| @@ -191,29 +194,23 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -191,29 +194,23 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 191 | /** | 194 | /** |
| 192 | * 审批通过存在“后加签”的任务。 | 195 | * 审批通过存在“后加签”的任务。 |
| 193 | * <p> | 196 | * <p> |
| 194 | - * 注意:该任务不能马上完成,需要一个中间状态(SIGN_AFTER),并激活剩余所有子任务(PROCESS)为可审批处理 | 197 | + * 注意:该任务不能马上完成,需要一个中间状态(APPROVING),并激活剩余所有子任务(PROCESS)为可审批处理 |
| 198 | + * 如果马上完成,则会触发下一个任务,甚至如果没有下一个任务则流程实例就直接结束了! | ||
| 195 | * | 199 | * |
| 196 | * @param task 当前任务 | 200 | * @param task 当前任务 |
| 197 | * @param reqVO 前端请求参数 | 201 | * @param reqVO 前端请求参数 |
| 198 | */ | 202 | */ |
| 199 | private void approveAfterSignTask(Task task, BpmTaskApproveReqVO reqVO) { | 203 | private void approveAfterSignTask(Task task, BpmTaskApproveReqVO reqVO) { |
| 200 | - // 1. 有向后加签,则该任务状态临时设置为 ADD_SIGN_AFTER 状态 | ||
| 201 | -// taskExtMapper.updateByTaskId( | ||
| 202 | -// new BpmTaskExtDO().setTaskId(task.getId()).setResult(BpmProcessInstanceResultEnum.SIGN_AFTER.getResult()) | ||
| 203 | -// .setReason(reqVO.getReason()).setEndTime(LocalDateTime.now())); | ||
| 204 | - // TODO @芋艿:reqVO.reason??? | ||
| 205 | - updateTaskStatus(task.getId(), BpmTaskStatustEnum.APPROVING.getStatus()); | 204 | + // 更新父 task 状态 + 原因 |
| 205 | + updateTaskStatusAndReason(task.getId(), BpmTaskStatustEnum.APPROVING.getStatus(), reqVO.getReason()); | ||
| 206 | 206 | ||
| 207 | // 2. 激活子任务 | 207 | // 2. 激活子任务 |
| 208 | - List<String> childrenTaskIdList = getChildrenTaskIdList(task.getId()); | ||
| 209 | - for (String childrenTaskId : childrenTaskIdList) { | ||
| 210 | - taskService.resolveTask(childrenTaskId); | ||
| 211 | - // 更新任务扩展表中子任务为进行中 | ||
| 212 | - updateTaskStatus(childrenTaskId, BpmTaskStatustEnum.RUNNING.getStatus()); | 208 | + List<Task> childrenTaskList = getTaskListByParentTaskId(task.getId()); |
| 209 | + for (Task childrenTask : childrenTaskList) { | ||
| 210 | + taskService.resolveTask(childrenTask.getId()); | ||
| 211 | + // 更新子 task 状态 | ||
| 212 | + updateTaskStatus(childrenTask.getId(), BpmTaskStatustEnum.RUNNING.getStatus()); | ||
| 213 | } | 213 | } |
| 214 | - // 2.1 更新任务扩展表中子任务为进行中 | ||
| 215 | -// taskExtMapper.updateBatchByTaskIdList(childrenTaskIdList, | ||
| 216 | -// new BpmTaskExtDO().setResult(BpmProcessInstanceResultEnum.PROCESS.getResult())); | ||
| 217 | } | 214 | } |
| 218 | 215 | ||
| 219 | /** | 216 | /** |
| @@ -229,14 +226,14 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -229,14 +226,14 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 229 | return; | 226 | return; |
| 230 | } | 227 | } |
| 231 | // 1.1 判断是否还有子任务。如果没有,就不处理 | 228 | // 1.1 判断是否还有子任务。如果没有,就不处理 |
| 232 | - Long childrenTaskCount = getChildrenTaskCount(parentTaskId); | 229 | + Long childrenTaskCount = getTaskCountByParentTaskId(parentTaskId); |
| 233 | if (childrenTaskCount > 0) { | 230 | if (childrenTaskCount > 0) { |
| 234 | return; | 231 | return; |
| 235 | } | 232 | } |
| 236 | // 1.2 只处理加签的父任务 | 233 | // 1.2 只处理加签的父任务 |
| 237 | Task parentTask = validateTaskExist(parentTaskId); | 234 | Task parentTask = validateTaskExist(parentTaskId); |
| 238 | String scopeType = parentTask.getScopeType(); | 235 | String scopeType = parentTask.getScopeType(); |
| 239 | - if (!validateSignType(scopeType)){ | 236 | + if (BpmTaskSignTypeEnum.of(scopeType) == null){ |
| 240 | return; | 237 | return; |
| 241 | } | 238 | } |
| 242 | 239 | ||
| @@ -246,14 +243,20 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -246,14 +243,20 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 246 | taskService.saveTask(parentTaskImpl); | 243 | taskService.saveTask(parentTaskImpl); |
| 247 | 244 | ||
| 248 | // 3.1 情况一:处理向【向前】加签 | 245 | // 3.1 情况一:处理向【向前】加签 |
| 249 | - if (BpmTaskAddSignTypeEnum.BEFORE.getType().equals(scopeType)) { | 246 | + if (BpmTaskSignTypeEnum.BEFORE.getType().equals(scopeType)) { |
| 250 | // 3.1.1 owner 重新赋值给父任务的 assignee,这样它就可以被审批 | 247 | // 3.1.1 owner 重新赋值给父任务的 assignee,这样它就可以被审批 |
| 251 | taskService.resolveTask(parentTaskId); | 248 | taskService.resolveTask(parentTaskId); |
| 252 | // 3.1.2 更新流程任务 status | 249 | // 3.1.2 更新流程任务 status |
| 253 | updateTaskStatus(parentTaskId, BpmTaskStatustEnum.RUNNING.getStatus()); | 250 | updateTaskStatus(parentTaskId, BpmTaskStatustEnum.RUNNING.getStatus()); |
| 254 | // 3.2 情况二:处理向【向后】加签 | 251 | // 3.2 情况二:处理向【向后】加签 |
| 255 | - } else if (BpmTaskAddSignTypeEnum.AFTER.getType().equals(scopeType)) { | ||
| 256 | - // 3.2.1 完成自己(因为它已经没有子任务,所以也可以完成) | 252 | + } else if (BpmTaskSignTypeEnum.AFTER.getType().equals(scopeType)) { |
| 253 | + // 只有 parentTask 处于 APPROVING 的情况下,才可以继续 complete 完成 | ||
| 254 | + // 否则,一个未审批的 parentTask 任务,在加签出来的任务都被减签的情况下,就直接完成审批,这样会存在问题 | ||
| 255 | + Integer status = (Integer) parentTask.getTaskLocalVariables().get(BpmConstants.TASK_VARIABLE_STATUS); | ||
| 256 | + if (ObjectUtil.notEqual(status, BpmTaskStatustEnum.APPROVING.getStatus())) { | ||
| 257 | + return; | ||
| 258 | + } | ||
| 259 | + // 3.2.2 完成自己(因为它已经没有子任务,所以也可以完成) | ||
| 257 | updateTaskStatus(parentTaskId, BpmTaskStatustEnum.APPROVE.getStatus()); | 260 | updateTaskStatus(parentTaskId, BpmTaskStatustEnum.APPROVE.getStatus()); |
| 258 | taskService.complete(parentTaskId); | 261 | taskService.complete(parentTaskId); |
| 259 | } | 262 | } |
| @@ -263,18 +266,6 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -263,18 +266,6 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 263 | } | 266 | } |
| 264 | 267 | ||
| 265 | /** | 268 | /** |
| 266 | - * 获取子任务个数 | ||
| 267 | - * | ||
| 268 | - * @param parentTaskId 父任务 ID | ||
| 269 | - * @return 剩余子任务个数 | ||
| 270 | - */ | ||
| 271 | - private Long getChildrenTaskCount(String parentTaskId) { | ||
| 272 | - String tableName = managementService.getTableName(TaskEntity.class); | ||
| 273 | - String sql = "SELECT COUNT(1) from " + tableName + " WHERE PARENT_TASK_ID_=#{parentTaskId}"; | ||
| 274 | - return taskService.createNativeTaskQuery().sql(sql).parameter("parentTaskId", parentTaskId).count(); | ||
| 275 | - } | ||
| 276 | - | ||
| 277 | - /** | ||
| 278 | * 审批被委派的任务 | 269 | * 审批被委派的任务 |
| 279 | * | 270 | * |
| 280 | * @param reqVO 前端请求参数,包含当前任务ID,审批意见等 | 271 | * @param reqVO 前端请求参数,包含当前任务ID,审批意见等 |
| @@ -339,7 +330,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -339,7 +330,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 339 | } | 330 | } |
| 340 | 331 | ||
| 341 | /** | 332 | /** |
| 342 | - * 校验任务是否存在, 并且是否是分配给自己的任务 | 333 | + * 校验任务是否存在,并且是否是分配给自己的任务 |
| 343 | * | 334 | * |
| 344 | * @param userId 用户 id | 335 | * @param userId 用户 id |
| 345 | * @param taskId task id | 336 | * @param taskId task id |
| @@ -388,7 +379,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -388,7 +379,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 388 | 379 | ||
| 389 | @Override | 380 | @Override |
| 390 | public void afterCommit() { | 381 | public void afterCommit() { |
| 391 | - if (StrUtil.isNotEmpty(task.getAssignee())) { | 382 | + if (StrUtil.isEmpty(task.getAssignee())) { |
| 392 | return; | 383 | return; |
| 393 | } | 384 | } |
| 394 | ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId()); | 385 | ProcessInstance processInstance = processInstanceService.getProcessInstance(task.getProcessInstanceId()); |
| @@ -574,52 +565,45 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -574,52 +565,45 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 574 | 565 | ||
| 575 | @Override | 566 | @Override |
| 576 | @Transactional(rollbackFor = Exception.class) | 567 | @Transactional(rollbackFor = Exception.class) |
| 577 | - public void createSignTask(Long userId, BpmTaskAddSignReqVO reqVO) { | 568 | + public void createSignTask(Long userId, BpmTaskSignCreateReqVO reqVO) { |
| 578 | // 1. 获取和校验任务 | 569 | // 1. 获取和校验任务 |
| 579 | - TaskEntityImpl taskEntity = validateAddSign(userId, reqVO); | ||
| 580 | - List<AdminUserRespDTO> userList = adminUserApi.getUserList(reqVO.getUserIdList()); | 570 | + TaskEntityImpl taskEntity = validateTaskCanCreateSign(userId, reqVO); |
| 571 | + List<AdminUserRespDTO> userList = adminUserApi.getUserList(reqVO.getUserIds()); | ||
| 581 | if (CollUtil.isEmpty(userList)) { | 572 | if (CollUtil.isEmpty(userList)) { |
| 582 | - throw exception(TASK_ADD_SIGN_USER_NOT_EXIST); | 573 | + throw exception(TASK_SIGN_CREATE_USER_NOT_EXIST); |
| 583 | } | 574 | } |
| 584 | 575 | ||
| 585 | // 2. 处理当前任务 | 576 | // 2. 处理当前任务 |
| 586 | // 2.1 开启计数功能,主要用于为了让表 ACT_RU_TASK 中的 SUB_TASK_COUNT_ 字段记录下总共有多少子任务,后续可能有用 | 577 | // 2.1 开启计数功能,主要用于为了让表 ACT_RU_TASK 中的 SUB_TASK_COUNT_ 字段记录下总共有多少子任务,后续可能有用 |
| 587 | taskEntity.setCountEnabled(true); | 578 | taskEntity.setCountEnabled(true); |
| 588 | - if (reqVO.getType().equals(BpmTaskAddSignTypeEnum.BEFORE.getType())) { | ||
| 589 | - // 2.2 向前加签,设置 owner,置空 assign。等子任务都完成后,再调用 resolveTask 重新将 owner 设置为 assign | ||
| 590 | - // 原因是:不能和向前加签的子任务一起审批,需要等前面的子任务都完成才能审批 | 579 | + // 2.2 向前加签,设置 owner,置空 assign。等子任务都完成后,再调用 resolveTask 重新将 owner 设置为 assign |
| 580 | + // 原因是:不能和向前加签的子任务一起审批,需要等前面的子任务都完成才能审批 | ||
| 581 | + if (reqVO.getType().equals(BpmTaskSignTypeEnum.BEFORE.getType())) { | ||
| 591 | taskEntity.setOwner(taskEntity.getAssignee()); | 582 | taskEntity.setOwner(taskEntity.getAssignee()); |
| 592 | taskEntity.setAssignee(null); | 583 | taskEntity.setAssignee(null); |
| 593 | - // 2.3 更新扩展表状态 | ||
| 594 | -// taskExtMapper.updateByTaskId( | ||
| 595 | -// new BpmTaskExtDO().setTaskId(taskEntity.getId()) | ||
| 596 | -// .setResult(BpmProcessInstanceResultEnum.SIGN_BEFORE.getResult()) | ||
| 597 | -// .setReason(reqVO.getReason())); | ||
| 598 | -// taskEntity.setTransientVariableLocal(BpmConstants.TASK_VARIABLE_STATUS, BpmProcessInstanceResultEnum.SIGN_BEFORE.getResult()); | ||
| 599 | -// updateTaskStatus(taskEntity.getId(), BpmProcessInstanceResultEnum.SIGN_BEFORE.getResult()); // TODO 芋艿:貌似会有实物并发的问题;所以不能用这个调用,只能 set | ||
| 600 | } | 584 | } |
| 601 | // 2.4 记录加签方式,完成任务时需要用到判断 | 585 | // 2.4 记录加签方式,完成任务时需要用到判断 |
| 602 | taskEntity.setScopeType(reqVO.getType()); | 586 | taskEntity.setScopeType(reqVO.getType()); |
| 603 | // 2.5 保存当前任务修改后的值 | 587 | // 2.5 保存当前任务修改后的值 |
| 604 | taskService.saveTask(taskEntity); | 588 | taskService.saveTask(taskEntity); |
| 605 | - if (reqVO.getType().equals(BpmTaskAddSignTypeEnum.BEFORE.getType())) { | ||
| 606 | - updateTaskStatus(taskEntity.getId(), BpmTaskStatustEnum.WAIT.getStatus()); // TODO 芋艿:貌似只能放在这个地方,不然会有并发修改的报错 | 589 | + // 2.6 更新 task 状态为 WAIT,只有在向前加签的时候 |
| 590 | + if (reqVO.getType().equals(BpmTaskSignTypeEnum.BEFORE.getType())) { | ||
| 591 | + updateTaskStatus(taskEntity.getId(), BpmTaskStatustEnum.WAIT.getStatus()); | ||
| 607 | } | 592 | } |
| 608 | 593 | ||
| 609 | // 3. 创建加签任务 | 594 | // 3. 创建加签任务 |
| 610 | - createSignTask(convertList(reqVO.getUserIdList(), String::valueOf), taskEntity); | 595 | + createSignTaskList(convertList(reqVO.getUserIds(), String::valueOf), taskEntity); |
| 611 | 596 | ||
| 612 | - // 4. 记录加签 comment,拼接结果为: [当前用户]向前加签/向后加签给了[多个用户],理由为:reason | 597 | + // 4. 记录加签的评论到 task 任务 |
| 613 | AdminUserRespDTO currentUser = adminUserApi.getUser(userId); | 598 | AdminUserRespDTO currentUser = adminUserApi.getUser(userId); |
| 614 | - String comment = StrUtil.format(BpmCommentTypeEnum.ADD_SIGN.getComment(), currentUser.getNickname(), | ||
| 615 | - BpmTaskAddSignTypeEnum.formatDesc(reqVO.getType()), String.join(",", convertList(userList, AdminUserRespDTO::getNickname)), reqVO.getReason()); | ||
| 616 | - taskService.addComment(reqVO.getId(), taskEntity.getProcessInstanceId(), | ||
| 617 | - BpmCommentTypeEnum.ADD_SIGN.getType().toString(), comment); | 599 | + String comment = StrUtil.format(BpmCommentTypeEnum.ADD_SIGN.getComment(), |
| 600 | + currentUser.getNickname(), BpmTaskSignTypeEnum.nameOfType(reqVO.getType()), | ||
| 601 | + String.join(",", convertList(userList, AdminUserRespDTO::getNickname)), reqVO.getReason()); | ||
| 602 | + taskService.addComment(reqVO.getId(), taskEntity.getProcessInstanceId(), BpmCommentTypeEnum.ADD_SIGN.getType(), comment); | ||
| 618 | } | 603 | } |
| 619 | 604 | ||
| 620 | - | ||
| 621 | /** | 605 | /** |
| 622 | - * 校验任务的加签是否一致 | 606 | + * 校验任务是否可以加签,主要校验加签类型是否一致: |
| 623 | * <p> | 607 | * <p> |
| 624 | * 1. 如果存在“向前加签”的任务,则不能“向后加签” | 608 | * 1. 如果存在“向前加签”的任务,则不能“向后加签” |
| 625 | * 2. 如果存在“向后加签”的任务,则不能“向前加签” | 609 | * 2. 如果存在“向后加签”的任务,则不能“向前加签” |
| @@ -628,24 +612,23 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -628,24 +612,23 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 628 | * @param reqVO 请求参数,包含任务 ID 和加签类型 | 612 | * @param reqVO 请求参数,包含任务 ID 和加签类型 |
| 629 | * @return 当前任务 | 613 | * @return 当前任务 |
| 630 | */ | 614 | */ |
| 631 | - private TaskEntityImpl validateAddSign(Long userId, BpmTaskAddSignReqVO reqVO) { | 615 | + private TaskEntityImpl validateTaskCanCreateSign(Long userId, BpmTaskSignCreateReqVO reqVO) { |
| 632 | TaskEntityImpl taskEntity = (TaskEntityImpl) validateTask(userId, reqVO.getId()); | 616 | TaskEntityImpl taskEntity = (TaskEntityImpl) validateTask(userId, reqVO.getId()); |
| 633 | // 向前加签和向后加签不能同时存在 | 617 | // 向前加签和向后加签不能同时存在 |
| 634 | if (taskEntity.getScopeType() != null | 618 | if (taskEntity.getScopeType() != null |
| 635 | && ObjectUtil.notEqual(taskEntity.getScopeType(), reqVO.getType())) { | 619 | && ObjectUtil.notEqual(taskEntity.getScopeType(), reqVO.getType())) { |
| 636 | - throw exception(TASK_ADD_SIGN_TYPE_ERROR, | ||
| 637 | - BpmTaskAddSignTypeEnum.formatDesc(taskEntity.getScopeType()), BpmTaskAddSignTypeEnum.formatDesc(reqVO.getType())); | 620 | + throw exception(TASK_SIGN_CREATE_TYPE_ERROR, |
| 621 | + BpmTaskSignTypeEnum.nameOfType(taskEntity.getScopeType()), BpmTaskSignTypeEnum.nameOfType(reqVO.getType())); | ||
| 638 | } | 622 | } |
| 639 | 623 | ||
| 640 | // 同一个 key 的任务,审批人不重复 | 624 | // 同一个 key 的任务,审批人不重复 |
| 641 | List<Task> taskList = taskService.createTaskQuery().processInstanceId(taskEntity.getProcessInstanceId()) | 625 | List<Task> taskList = taskService.createTaskQuery().processInstanceId(taskEntity.getProcessInstanceId()) |
| 642 | .taskDefinitionKey(taskEntity.getTaskDefinitionKey()).list(); | 626 | .taskDefinitionKey(taskEntity.getTaskDefinitionKey()).list(); |
| 643 | - List<Long> currentAssigneeList = convertList(taskList, task -> NumberUtils.parseLong(task.getAssignee())); | ||
| 644 | - // 保留交集在 currentAssigneeList 中 | ||
| 645 | - currentAssigneeList.retainAll(reqVO.getUserIdList()); | ||
| 646 | - if (CollUtil.isNotEmpty(currentAssigneeList)) { | ||
| 647 | - List<AdminUserRespDTO> userList = adminUserApi.getUserList(currentAssigneeList); | ||
| 648 | - throw exception(TASK_ADD_SIGN_USER_REPEAT, String.join(",", convertList(userList, AdminUserRespDTO::getNickname))); | 627 | + List<Long> currentAssigneeList = convertListByFlatMap(taskList, task -> // 需要考虑 owner 的情况,因为向后加签时,它暂时没 assignee 而是 owner |
| 628 | + Stream.of(NumberUtils.parseLong(task.getAssignee()), NumberUtils.parseLong(task.getOwner()))); | ||
| 629 | + if (CollUtil.containsAny(currentAssigneeList, reqVO.getUserIds())) { | ||
| 630 | + List<AdminUserRespDTO> userList = adminUserApi.getUserList( CollUtil.intersection(currentAssigneeList, reqVO.getUserIds())); | ||
| 631 | + throw exception(TASK_SIGN_CREATE_USER_REPEAT, String.join(",", convertList(userList, AdminUserRespDTO::getNickname))); | ||
| 649 | } | 632 | } |
| 650 | return taskEntity; | 633 | return taskEntity; |
| 651 | } | 634 | } |
| @@ -653,15 +636,15 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -653,15 +636,15 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 653 | /** | 636 | /** |
| 654 | * 创建加签子任务 | 637 | * 创建加签子任务 |
| 655 | * | 638 | * |
| 656 | - * @param addSingUserIdList 被加签的用户 ID | 639 | + * @param userIds 被加签的用户 ID |
| 657 | * @param taskEntity 被加签的任务 | 640 | * @param taskEntity 被加签的任务 |
| 658 | */ | 641 | */ |
| 659 | - private void createSignTask(List<String> addSingUserIdList, TaskEntityImpl taskEntity) { | ||
| 660 | - if (CollUtil.isEmpty(addSingUserIdList)) { | 642 | + private void createSignTaskList(List<String> userIds, TaskEntityImpl taskEntity) { |
| 643 | + if (CollUtil.isEmpty(userIds)) { | ||
| 661 | return; | 644 | return; |
| 662 | } | 645 | } |
| 663 | // 创建加签人的新任务,全部基于 taskEntity 为父任务来创建 | 646 | // 创建加签人的新任务,全部基于 taskEntity 为父任务来创建 |
| 664 | - for (String addSignId : addSingUserIdList) { | 647 | + for (String addSignId : userIds) { |
| 665 | if (StrUtil.isBlank(addSignId)) { | 648 | if (StrUtil.isBlank(addSignId)) { |
| 666 | continue; | 649 | continue; |
| 667 | } | 650 | } |
| @@ -678,31 +661,29 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -678,31 +661,29 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 678 | private void createSignTask(TaskEntityImpl parentTask, String assignee) { | 661 | private void createSignTask(TaskEntityImpl parentTask, String assignee) { |
| 679 | // 1. 生成子任务 | 662 | // 1. 生成子任务 |
| 680 | TaskEntityImpl task = (TaskEntityImpl) taskService.newTask(IdUtil.fastSimpleUUID()); | 663 | TaskEntityImpl task = (TaskEntityImpl) taskService.newTask(IdUtil.fastSimpleUUID()); |
| 681 | - task = BpmTaskConvert.INSTANCE.convert(task, parentTask); | ||
| 682 | - if (BpmTaskAddSignTypeEnum.BEFORE.getType().equals(parentTask.getScopeType())) { | ||
| 683 | - // 2.1 前加签,设置审批人 | 664 | + BpmTaskConvert.INSTANCE.copyTo(parentTask, task); |
| 665 | + | ||
| 666 | + // 2.1 向前加签,设置审批人 | ||
| 667 | + if (BpmTaskSignTypeEnum.BEFORE.getType().equals(parentTask.getScopeType())) { | ||
| 684 | task.setAssignee(assignee); | 668 | task.setAssignee(assignee); |
| 669 | + // 2.2 向后加签,设置 owner 不设置 assignee 是因为不能同时审批,需要等父任务完成 | ||
| 685 | } else { | 670 | } else { |
| 686 | - // 2.2.1 设置 owner 不设置 assignee 是因为不能同时审批,需要等父任务完成 | ||
| 687 | task.setOwner(assignee); | 671 | task.setOwner(assignee); |
| 688 | - // 2.2.2 设置向后加签任务的 scopeType 为 afterChildrenTask,用于设置任务扩展表的状态 | ||
| 689 | -// task.setScopeType(BpmTaskAddSignTypeEnum.AFTER_CHILDREN_TASK.getType()); | ||
| 690 | -// task.setVariableLocal(BpmConstants.TASK_VARIABLE_STATUS, BpmProcessInstanceResultEnum.WAIT.getResult()); | ||
| 691 | } | 672 | } |
| 692 | - // 2. 保存子任务 | 673 | + // 2.3 保存子任务 |
| 693 | taskService.saveTask(task); | 674 | taskService.saveTask(task); |
| 694 | - // 3. TODO | ||
| 695 | - if (BpmTaskAddSignTypeEnum.AFTER.getType().equals(parentTask.getScopeType())) { | 675 | + |
| 676 | + // 3. 向后前签,设置子任务的状态为 WAIT,因为需要等父任务审批完 | ||
| 677 | + if (BpmTaskSignTypeEnum.AFTER.getType().equals(parentTask.getScopeType())) { | ||
| 696 | updateTaskStatus(task.getId(), BpmTaskStatustEnum.WAIT.getStatus()); | 678 | updateTaskStatus(task.getId(), BpmTaskStatustEnum.WAIT.getStatus()); |
| 697 | } | 679 | } |
| 698 | } | 680 | } |
| 699 | 681 | ||
| 700 | @Override | 682 | @Override |
| 701 | @Transactional(rollbackFor = Exception.class) | 683 | @Transactional(rollbackFor = Exception.class) |
| 702 | - public void deleteSignTask(Long userId, BpmTaskSubSignReqVO reqVO) { | 684 | + public void deleteSignTask(Long userId, BpmTaskSignDeleteReqVO reqVO) { |
| 703 | // 1.1 校验 task 可以被减签 | 685 | // 1.1 校验 task 可以被减签 |
| 704 | -// Task task = validateSubSign(reqVO.getId()); // TODO 芋艿:这个判断,暂时有点问题!在前置加签的时候 | ||
| 705 | - Task task = validateTaskExist(reqVO.getId()); | 686 | + Task task = validateTaskCanSignDelete(reqVO.getId()); |
| 706 | // 1.2 校验取消人存在 | 687 | // 1.2 校验取消人存在 |
| 707 | AdminUserRespDTO cancelUser = null; | 688 | AdminUserRespDTO cancelUser = null; |
| 708 | if (StrUtil.isNotBlank(task.getAssignee())) { | 689 | if (StrUtil.isNotBlank(task.getAssignee())) { |
| @@ -713,21 +694,19 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -713,21 +694,19 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 713 | } | 694 | } |
| 714 | Assert.notNull(cancelUser, "任务中没有所有者和审批人,数据错误"); | 695 | Assert.notNull(cancelUser, "任务中没有所有者和审批人,数据错误"); |
| 715 | 696 | ||
| 716 | - // 2. 删除任务和对应子任务 | ||
| 717 | - // 2.1 获取所有需要删除的任务 ID ,包含当前任务和所有子任务 | ||
| 718 | - List<String> allTaskIdList = getAllChildTaskIds(task.getId()); | 697 | + // 2.1 获得子任务列表,包括子任务的子任务 |
| 698 | + List<Task> childTaskList = getAllChildTaskList(task); | ||
| 699 | + childTaskList.add(task); | ||
| 700 | + // 2.2 更新子任务为已取消 | ||
| 701 | + String cancelReason = StrUtil.format("任务被取消,原因:由于[{}]操作[减签],", cancelUser.getNickname()); | ||
| 702 | + childTaskList.forEach(childTask -> updateTaskStatusAndReason(childTask.getId(), BpmTaskStatustEnum.CANCEL.getStatus(), cancelReason)); | ||
| 719 | // 2.2 删除任务和所有子任务 | 703 | // 2.2 删除任务和所有子任务 |
| 720 | - taskService.deleteTasks(allTaskIdList); | ||
| 721 | - // 2.3 修改扩展表状态为取消 | ||
| 722 | -// taskExtMapper.updateBatchByTaskIdList(allTaskIdList, new BpmTaskExtDO().setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()) | ||
| 723 | -// .setReason(StrUtil.format("由于{}操作[减签],任务被取消", user.getNickname()))); | ||
| 724 | -// allTaskIdList.forEach(taskId -> updateTaskStatus(taskId, BpmProcessInstanceResultEnum.CANCEL.getResult())); // TODO @芋艿:交给取消;考虑到理由,可能不能直接给; | 704 | + taskService.deleteTasks(convertList(childTaskList, Task::getId)); |
| 725 | 705 | ||
| 726 | // 3. 记录日志到父任务中。先记录日志是因为,通过 handleParentTask 方法之后,任务可能被完成了,并且不存在了,会报异常,所以先记录 | 706 | // 3. 记录日志到父任务中。先记录日志是因为,通过 handleParentTask 方法之后,任务可能被完成了,并且不存在了,会报异常,所以先记录 |
| 727 | AdminUserRespDTO user = adminUserApi.getUser(userId); | 707 | AdminUserRespDTO user = adminUserApi.getUser(userId); |
| 728 | - String comment = StrUtil.format(BpmCommentTypeEnum.SUB_SIGN.getComment(), user.getNickname(), cancelUser.getNickname()); | ||
| 729 | - taskService.addComment(task.getParentTaskId(), task.getProcessInstanceId(), | ||
| 730 | - BpmCommentTypeEnum.SUB_SIGN.getType().toString(), comment); | 708 | + taskService.addComment(task.getParentTaskId(), task.getProcessInstanceId(), BpmCommentTypeEnum.SUB_SIGN.getType(), |
| 709 | + StrUtil.format(BpmCommentTypeEnum.SUB_SIGN.getComment(), user.getNickname(), cancelUser.getNickname())); | ||
| 731 | 710 | ||
| 732 | // 4. 处理当前任务的父任务 | 711 | // 4. 处理当前任务的父任务 |
| 733 | handleParentTaskIfSign(task.getParentTaskId()); | 712 | handleParentTaskIfSign(task.getParentTaskId()); |
| @@ -736,86 +715,72 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -736,86 +715,72 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 736 | /** | 715 | /** |
| 737 | * 校验任务是否能被减签 | 716 | * 校验任务是否能被减签 |
| 738 | * | 717 | * |
| 739 | - * @param id 任务ID | 718 | + * @param id 任务编号 |
| 740 | * @return 任务信息 | 719 | * @return 任务信息 |
| 741 | */ | 720 | */ |
| 742 | - private Task validateSubSign(String id) { | 721 | + private Task validateTaskCanSignDelete(String id) { |
| 743 | Task task = validateTaskExist(id); | 722 | Task task = validateTaskExist(id); |
| 744 | - | ||
| 745 | - // 必须有 scopeType | ||
| 746 | - String scopeType = task.getScopeType(); | ||
| 747 | - if (StrUtil.isEmpty(scopeType)) { | ||
| 748 | - throw exception(TASK_SUB_SIGN_NO_PARENT); | 723 | + if (task.getParentTaskId() == null) { |
| 724 | + throw exception(TASK_SIGN_DELETE_NO_PARENT); | ||
| 725 | + } | ||
| 726 | + Task parentTask = getTask(task.getParentTaskId()); | ||
| 727 | + if (parentTask == null) { | ||
| 728 | + throw exception(TASK_SIGN_DELETE_NO_PARENT); | ||
| 749 | } | 729 | } |
| 750 | - // 并且值为 向前和向后加签 | ||
| 751 | - if (!validateSignType(scopeType)) { | ||
| 752 | - throw exception(TASK_SUB_SIGN_NO_PARENT); | 730 | + if (BpmTaskSignTypeEnum.of(parentTask.getScopeType()) == null) { |
| 731 | + throw exception(TASK_SIGN_DELETE_NO_PARENT); | ||
| 753 | } | 732 | } |
| 754 | return task; | 733 | return task; |
| 755 | } | 734 | } |
| 756 | 735 | ||
| 757 | /** | 736 | /** |
| 758 | - * 判断当前类型是否为加签 | ||
| 759 | - * @param scopeType 任务的 scopeType | ||
| 760 | - * @return 当前 scopeType 为加签则返回 true | ||
| 761 | - */ | ||
| 762 | - private boolean validateSignType(String scopeType){ | ||
| 763 | - return StrUtil.equalsAny(scopeType,BpmTaskAddSignTypeEnum.BEFORE.getType(),scopeType, BpmTaskAddSignTypeEnum.AFTER.getType()); | ||
| 764 | - } | ||
| 765 | - | ||
| 766 | -// TODO @海:BpmProcessInstanceResultEnum.CAN_SUB_SIGN_STATUS_LIST) 应该作为条件,mapper 不要有业务 | ||
| 767 | - /** | ||
| 768 | - * 获取所有要被取消的删除的任务 ID 集合 | 737 | + * 获得所有子任务列表 |
| 769 | * | 738 | * |
| 770 | - * @param parentTaskId 父级任务ID | ||
| 771 | - * @return 所有任务ID | 739 | + * @param parentTask 父任务 |
| 740 | + * @return 所有子任务列表 | ||
| 772 | */ | 741 | */ |
| 773 | - public List<String> getAllChildTaskIds(String parentTaskId) { | ||
| 774 | - List<String> allChildTaskIds = new ArrayList<>(); | 742 | + private List<Task> getAllChildTaskList(Task parentTask) { |
| 743 | + List<Task> result = new ArrayList<>(); | ||
| 775 | // 1. 递归获取子级 | 744 | // 1. 递归获取子级 |
| 776 | - Stack<String> stack = new Stack<>(); | ||
| 777 | - // 1.1 将根任务ID入栈 | ||
| 778 | - stack.push(parentTaskId); | ||
| 779 | - //控制遍历的次数不超过 Byte.MAX_VALUE,避免脏数据造成死循环 | ||
| 780 | - int count = 0; | ||
| 781 | - // TODO @海:< 的前后空格,要注意哈; | ||
| 782 | - while (!stack.isEmpty() && count<Byte.MAX_VALUE) { | ||
| 783 | - // 1.2 弹出栈顶任务ID | ||
| 784 | - String taskId = stack.pop(); | ||
| 785 | - // 1.3 将任务ID添加到结果集合中 | ||
| 786 | - allChildTaskIds.add(taskId); | ||
| 787 | - // 1.4 获取该任务的子任务列表 | ||
| 788 | - // TODO @海:有个更高效的写法;一次性去 in 一层;不然每个节点,都去查询一次 db, 太浪费了;每次 in,最终就是 O(h) 查询,而不是 O(n) 查询; | ||
| 789 | - List<String> childrenTaskIdList = getChildrenTaskIdList(taskId); | ||
| 790 | - if (CollUtil.isNotEmpty(childrenTaskIdList)) { | ||
| 791 | - for (String childTaskId : childrenTaskIdList) { | ||
| 792 | - // 1.5 将子任务ID入栈,以便后续处理 | ||
| 793 | - stack.push(childTaskId); | ||
| 794 | - } | 745 | + Stack<Task> stack = new Stack<>(); |
| 746 | + stack.push(parentTask); | ||
| 747 | + // 2. 递归遍历 | ||
| 748 | + for (int i = 0; i < Short.MAX_VALUE; i++) { | ||
| 749 | + if (stack.isEmpty()) { | ||
| 750 | + break; | ||
| 751 | + } | ||
| 752 | + // 2.1 获取子任务们 | ||
| 753 | + Task task = stack.pop(); | ||
| 754 | + List<Task> childTaskList = getTaskListByParentTaskId(task.getId()); | ||
| 755 | + // 2.2 如果非空,则添加到 stack 进一步递归 | ||
| 756 | + if (CollUtil.isNotEmpty(childTaskList)) { | ||
| 757 | + stack.addAll(childTaskList); | ||
| 758 | + result.addAll(childTaskList); | ||
| 795 | } | 759 | } |
| 796 | - count++; | ||
| 797 | } | 760 | } |
| 798 | - return allChildTaskIds; | ||
| 799 | - } | ||
| 800 | - | ||
| 801 | - /** | ||
| 802 | - * 获取指定父级任务的所有子任务 ID 集合 | ||
| 803 | - * | ||
| 804 | - * @param parentTaskId 父任务 ID | ||
| 805 | - * @return 所有子任务的 ID 集合 | ||
| 806 | - */ | ||
| 807 | - private List<String> getChildrenTaskIdList(String parentTaskId) { | ||
| 808 | - return convertList(getTaskListByParentTaskId(parentTaskId), Task::getId); | 761 | + return result; |
| 809 | } | 762 | } |
| 810 | 763 | ||
| 811 | @Override | 764 | @Override |
| 812 | public List<Task> getTaskListByParentTaskId(String parentTaskId) { | 765 | public List<Task> getTaskListByParentTaskId(String parentTaskId) { |
| 813 | String tableName = managementService.getTableName(TaskEntity.class); | 766 | String tableName = managementService.getTableName(TaskEntity.class); |
| 814 | // taskService.createTaskQuery() 没有 parentId 参数,所以写 sql 查询 | 767 | // taskService.createTaskQuery() 没有 parentId 参数,所以写 sql 查询 |
| 815 | - String sql = "select ID_,OWNER_,ASSIGNEE_ from " + tableName + " where PARENT_TASK_ID_=#{parentTaskId}"; | 768 | + String sql = "select ID_,NAME_,OWNER_,ASSIGNEE_ from " + tableName + " where PARENT_TASK_ID_=#{parentTaskId}"; |
| 816 | return taskService.createNativeTaskQuery().sql(sql).parameter("parentTaskId", parentTaskId).list(); | 769 | return taskService.createNativeTaskQuery().sql(sql).parameter("parentTaskId", parentTaskId).list(); |
| 817 | } | 770 | } |
| 818 | 771 | ||
| 772 | + /** | ||
| 773 | + * 获取子任务个数 | ||
| 774 | + * | ||
| 775 | + * @param parentTaskId 父任务 ID | ||
| 776 | + * @return 剩余子任务个数 | ||
| 777 | + */ | ||
| 778 | + private Long getTaskCountByParentTaskId(String parentTaskId) { | ||
| 779 | + String tableName = managementService.getTableName(TaskEntity.class); | ||
| 780 | + String sql = "SELECT COUNT(1) from " + tableName + " WHERE PARENT_TASK_ID_=#{parentTaskId}"; | ||
| 781 | + return taskService.createNativeTaskQuery().sql(sql).parameter("parentTaskId", parentTaskId).count(); | ||
| 782 | + } | ||
| 783 | + | ||
| 819 | @Override | 784 | @Override |
| 820 | public Map<String, String> getTaskNameByTaskIds(Collection<String> taskIds) { | 785 | public Map<String, String> getTaskNameByTaskIds(Collection<String> taskIds) { |
| 821 | if (CollUtil.isEmpty(taskIds)) { | 786 | if (CollUtil.isEmpty(taskIds)) { |