Commit 6906f79a0ed19b1a1c7132183bc094494d126a8d

Authored by jason
2 parents eebee1eb 84bf1c3b

Merge remote-tracking branch 'origin/feature/bpm' into feature/bpm

README.md
... ... @@ -156,7 +156,7 @@
156 156 | 🚀 | 用户分组 | 自定义用户分组,可用于工作流的审批分组 |
157 157 | 🚀 | 我的流程 | 查看我发起的工作流程,支持新建、取消流程等操作,高亮流程图、审批时间线 |
158 158 | 🚀 | 待办任务 | 查看自己【未】审批的工作任务,支持通过、不通过、转发、委派、退回等操作 |
159   -| 🚀 | 已办任务 | 查看自己【已】审批的工作任务,未来会支持回退操作 |
  159 +| 🚀 | 已办任务 | 查看自己【已】审批的工作任务,未来会支持退回操作 |
160 160 | 🚀 | OA 请假 | 作为业务自定义接入工作流的使用示例,只需创建请求对应的工作流程,即可进行审批 |
161 161  
162 162 ![功能图](/.image/common/bpm-feature.png)
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java
... ... @@ -8,7 +8,6 @@ import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
8 8 import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
9 9 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
10 10 import cn.iocoder.yudao.module.bpm.service.definition.BpmFormService;
11   -import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
12 11 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
13 12 import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
14 13 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
... ... @@ -20,7 +19,6 @@ import io.swagger.v3.oas.annotations.Parameter;
20 19 import io.swagger.v3.oas.annotations.tags.Tag;
21 20 import jakarta.annotation.Resource;
22 21 import jakarta.validation.Valid;
23   -import org.flowable.bpmn.model.BpmnModel;
24 22 import org.flowable.bpmn.model.UserTask;
25 23 import org.flowable.engine.history.HistoricProcessInstance;
26 24 import org.flowable.engine.runtime.ProcessInstance;
... ... @@ -30,7 +28,10 @@ import org.springframework.security.access.prepost.PreAuthorize;
30 28 import org.springframework.validation.annotation.Validated;
31 29 import org.springframework.web.bind.annotation.*;
32 30  
33   -import java.util.*;
  31 +import java.util.Collections;
  32 +import java.util.List;
  33 +import java.util.Map;
  34 +import java.util.Set;
34 35 import java.util.stream.Stream;
35 36  
36 37 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
... ... @@ -49,8 +50,6 @@ public class BpmTaskController {
49 50 private BpmProcessInstanceService processInstanceService;
50 51 @Resource
51 52 private BpmFormService formService;
52   - @Resource
53   - private BpmProcessDefinitionService bpmProcessDefinitionService;
54 53  
55 54 @Resource
56 55 private AdminUserApi adminUserApi;
... ... @@ -135,10 +134,8 @@ public class BpmTaskController {
135 134 // 获得 Form Map
136 135 Map<Long, BpmFormDO> formMap = formService.getFormMap(
137 136 convertSet(taskList, task -> NumberUtils.parseLong(task.getFormKey())));
138   - // 获得 BpmnModel
139   - BpmnModel bpmnModel = bpmProcessDefinitionService.getProcessDefinitionBpmnModel(processInstance.getProcessDefinitionId());
140 137 return success(BpmTaskConvert.INSTANCE.buildTaskListByProcessInstanceId(taskList, processInstance,
141   - formMap, userMap, deptMap, bpmnModel));
  138 + formMap, userMap, deptMap));
142 139 }
143 140  
144 141 @PutMapping("/approve")
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
... ... @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.bpm.convert.task;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.map.MapUtil;
5   -import cn.hutool.core.util.StrUtil;
6 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 6 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
8 7 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
... ... @@ -10,13 +9,10 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
10 9 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO;
11 10 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
12 11 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
13   -import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
14   -import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
15 12 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
16 13 import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
17 14 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
18 15 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
19   -import org.flowable.bpmn.model.BpmnModel;
20 16 import org.flowable.engine.history.HistoricProcessInstance;
21 17 import org.flowable.engine.runtime.ProcessInstance;
22 18 import org.flowable.task.api.Task;
... ... @@ -29,7 +25,7 @@ import java.util.Date;
29 25 import java.util.List;
30 26 import java.util.Map;
31 27  
32   -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
  28 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
33 29 import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
34 30  
35 31 /**
... ... @@ -85,9 +81,8 @@ public interface BpmTaskConvert {
85 81 HistoricProcessInstance processInstance,
86 82 Map<Long, BpmFormDO> formMap,
87 83 Map<Long, AdminUserRespDTO> userMap,
88   - Map<Long, DeptRespDTO> deptMap,
89   - BpmnModel bpmnModel) {
90   - List<BpmTaskRespVO> taskVOList = CollectionUtils.convertList(taskList, task -> {
  84 + Map<Long, DeptRespDTO> deptMap) {
  85 + return CollectionUtils.convertList(taskList, task -> {
91 86 BpmTaskRespVO taskVO = BeanUtils.toBean(task, BpmTaskRespVO.class);
92 87 Integer taskStatus = FlowableUtils.getTaskStatus(task);
93 88 taskVO.setStatus(taskStatus).setReason(FlowableUtils.getTaskReason(task));
... ... @@ -104,21 +99,8 @@ public interface BpmTaskConvert {
104 99 // 用户信息
105 100 buildTaskAssignee(taskVO, task.getAssignee(), userMap, deptMap);
106 101 buildTaskOwner(taskVO, task.getOwner(), userMap, deptMap);
107   - if (BpmTaskStatusEnum.RUNNING.getStatus().equals(taskStatus)) {
108   - // 操作按钮设置
109   - taskVO.setButtonsSetting(BpmnModelUtils.parseButtonsSetting(bpmnModel, task.getTaskDefinitionKey()));
110   - }
111 102 return taskVO;
112 103 });
113   -
114   - // 拼接父子关系
115   - Map<String, List<BpmTaskRespVO>> childrenTaskMap = convertMultiMap(
116   - filterList(taskVOList, r -> StrUtil.isNotEmpty(r.getParentTaskId())),
117   - BpmTaskRespVO::getParentTaskId);
118   - for (BpmTaskRespVO taskVO : taskVOList) {
119   - taskVO.setChildren(childrenTaskMap.get(taskVO.getId()));
120   - }
121   - return filterList(taskVOList, r -> StrUtil.isEmpty(r.getParentTaskId()));
122 104 }
123 105  
124 106 default List<BpmTaskRespVO> buildTaskListByParentTaskId(List<Task> taskList,
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
... ... @@ -156,9 +156,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
156 156 BpmnModel bpmnModel = bpmProcessDefinitionService.getProcessDefinitionBpmnModel(processInstance.getProcessDefinitionId());
157 157 List<BpmTaskRespVO> taskList = convertList(todoList, task -> {
158 158 // 找到分配给当前用户,或者当前用户加签的任务(为了减签)
159   - // TODO 3)(!userId.equals(NumberUtil.parseLong(task.getOwner(), null)) || BpmTaskSignTypeEnum.of(task.getScopeType()) == null) 这个判断的目的是啥?
160   - // @芋艿 !isAddSignTask(userId, task) 该判断的目的被用户加签的任务。该用户可以进行减签操作
161   - if (!isAssignUserTask(userId, task) && !isAddSignTask(userId, task)) {
  159 + if (!isAssignUserTask(userId, task) && !isAddSignUserTask(userId, task)) {
162 160 return null;
163 161 }
164 162 BpmTaskRespVO taskVO = BeanUtils.toBean(task, BpmTaskRespVO.class);
... ... @@ -166,9 +164,10 @@ public class BpmTaskServiceImpl implements BpmTaskService {
166 164 taskVO.setButtonsSetting(BpmnModelUtils.parseButtonsSetting(bpmnModel, task.getTaskDefinitionKey()));
167 165 BpmTaskConvert.INSTANCE.buildTaskOwner(taskVO, task.getOwner(), userMap, deptMap);
168 166 // 如果是被加签的任务. 找到它的子任务 (为了减签)
169   - if (isAddSignTask(userId, task)) {
  167 + // TODO @jason:如果是向后加签,这个判断有问题哈。因为向后加签后,当前任务,assignee 还是没变。可以简单点,直接拿子任务哈。另外,需要考虑子任务的子任务。
  168 + if (isAddSignUserTask(userId, task)) {
  169 + // TODO @jason:这里其实可以考虑,在 157 到 173 把所有需要的数据都拿到,然后交给 BpmTaskConvert.INSTANCE 转换出 taskVO。这样,service 只保留一些逻辑性强的东西,类似 status、buttonsetting,都拿到 convert 里去。
170 170 BpmTaskConvert.INSTANCE.buildTaskChildren(taskVO, childrenTaskMap, userMap, deptMap);
171   -
172 171 }
173 172 return taskVO;
174 173 });
... ... @@ -176,16 +175,24 @@ public class BpmTaskServiceImpl implements BpmTaskService {
176 175 }
177 176  
178 177 /**
179   - * 判断是否为被分配给用户的任务
  178 + * 判断指定用户,是否是当前任务的分配人
  179 + *
  180 + * @param userId 用户编号
  181 + * @param task 任务
  182 + * @return 是否
180 183 */
181 184 private boolean isAssignUserTask(Long userId, Task task) {
182 185 return ObjectUtil.equal(userId, NumberUtil.parseLong(task.getAssignee(), null));
183 186 }
184 187  
185 188 /**
186   - * 判断是否为被用户加签的任务
  189 + * 判断指定用户,是否是当前任务的加签人
  190 + *
  191 + * @param userId 用户编号
  192 + * @param task 任务
  193 + * @return 是否
187 194 */
188   - private boolean isAddSignTask(Long userId, Task task) {
  195 + private boolean isAddSignUserTask(Long userId, Task task) {
189 196 return userId.equals(NumberUtil.parseLong(task.getOwner(), null))
190 197 && BpmTaskSignTypeEnum.of(task.getScopeType()) != null;
191 198 }
... ... @@ -994,8 +1001,13 @@ public class BpmTaskServiceImpl implements BpmTaskService {
994 1001 if (ObjectUtil.notEqual(transactionStatus, TransactionSynchronization.STATUS_COMMITTED)) {
995 1002 return;
996 1003 }
  1004 + // TODO 芋艿:可以后续优化成 getSelf();
997 1005 // 特殊情况一:【人工审核】审批人为空,根据配置是否要自动通过、自动拒绝
998 1006 if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.USER.getType())) {
  1007 + // 如果有审批人、或者拥有人,则说明不满足情况一,不自动通过、不自动拒绝
  1008 + if (!ObjectUtil.isAllEmpty(task.getAssignee(), task.getOwner())) {
  1009 + return;
  1010 + }
999 1011 if (ObjectUtil.equal(assignEmptyHandlerType, BpmUserTaskAssignEmptyHandlerTypeEnum.APPROVE.getType())) {
1000 1012 SpringUtil.getBean(BpmTaskService.class).approveTask(null, new BpmTaskApproveReqVO()
1001 1013 .setId(task.getId()).setReason(BpmReasonEnum.ASSIGN_EMPTY_APPROVE.getReason()));
... ...