Commit 6906f79a0ed19b1a1c7132183bc094494d126a8d
Merge remote-tracking branch 'origin/feature/bpm' into feature/bpm
Showing
4 changed files
with
29 additions
and
38 deletions
README.md
| ... | ... | @@ -156,7 +156,7 @@ |
| 156 | 156 | | 🚀 | 用户分组 | 自定义用户分组,可用于工作流的审批分组 | |
| 157 | 157 | | 🚀 | 我的流程 | 查看我发起的工作流程,支持新建、取消流程等操作,高亮流程图、审批时间线 | |
| 158 | 158 | | 🚀 | 待办任务 | 查看自己【未】审批的工作任务,支持通过、不通过、转发、委派、退回等操作 | |
| 159 | -| 🚀 | 已办任务 | 查看自己【已】审批的工作任务,未来会支持回退操作 | | |
| 159 | +| 🚀 | 已办任务 | 查看自己【已】审批的工作任务,未来会支持退回操作 | | |
| 160 | 160 | | 🚀 | OA 请假 | 作为业务自定义接入工作流的使用示例,只需创建请求对应的工作流程,即可进行审批 | |
| 161 | 161 | |
| 162 | 162 |  | ... | ... |
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())); | ... | ... |