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

This commit is contained in:
jason 2024-10-20 09:48:59 +08:00
commit 6906f79a0e
4 changed files with 29 additions and 38 deletions

View File

@ -156,7 +156,7 @@
| 🚀 | 用户分组 | 自定义用户分组,可用于工作流的审批分组 |
| 🚀 | 我的流程 | 查看我发起的工作流程,支持新建、取消流程等操作,高亮流程图、审批时间线 |
| 🚀 | 待办任务 | 查看自己【未】审批的工作任务,支持通过、不通过、转发、委派、退回等操作 |
| 🚀 | 已办任务 | 查看自己【已】审批的工作任务,未来会支持退操作 |
| 🚀 | 已办任务 | 查看自己【已】审批的工作任务,未来会支持退操作 |
| 🚀 | OA 请假 | 作为业务自定义接入工作流的使用示例,只需创建请求对应的工作流程,即可进行审批 |
![功能图](/.image/common/bpm-feature.png)

View File

@ -8,7 +8,6 @@ import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
import cn.iocoder.yudao.module.bpm.service.definition.BpmFormService;
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
@ -20,7 +19,6 @@ import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
@ -30,7 +28,10 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -49,8 +50,6 @@ public class BpmTaskController {
private BpmProcessInstanceService processInstanceService;
@Resource
private BpmFormService formService;
@Resource
private BpmProcessDefinitionService bpmProcessDefinitionService;
@Resource
private AdminUserApi adminUserApi;
@ -135,10 +134,8 @@ public class BpmTaskController {
// 获得 Form Map
Map<Long, BpmFormDO> formMap = formService.getFormMap(
convertSet(taskList, task -> NumberUtils.parseLong(task.getFormKey())));
// 获得 BpmnModel
BpmnModel bpmnModel = bpmProcessDefinitionService.getProcessDefinitionBpmnModel(processInstance.getProcessDefinitionId());
return success(BpmTaskConvert.INSTANCE.buildTaskListByProcessInstanceId(taskList, processInstance,
formMap, userMap, deptMap, bpmnModel));
formMap, userMap, deptMap));
}
@PutMapping("/approve")

View File

@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.bpm.convert.task;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
@ -10,13 +9,10 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceRespVO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
import cn.iocoder.yudao.module.bpm.service.message.dto.BpmMessageSendWhenTaskCreatedReqDTO;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
@ -29,7 +25,7 @@ import java.util.Date;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
/**
@ -85,9 +81,8 @@ public interface BpmTaskConvert {
HistoricProcessInstance processInstance,
Map<Long, BpmFormDO> formMap,
Map<Long, AdminUserRespDTO> userMap,
Map<Long, DeptRespDTO> deptMap,
BpmnModel bpmnModel) {
List<BpmTaskRespVO> taskVOList = CollectionUtils.convertList(taskList, task -> {
Map<Long, DeptRespDTO> deptMap) {
return CollectionUtils.convertList(taskList, task -> {
BpmTaskRespVO taskVO = BeanUtils.toBean(task, BpmTaskRespVO.class);
Integer taskStatus = FlowableUtils.getTaskStatus(task);
taskVO.setStatus(taskStatus).setReason(FlowableUtils.getTaskReason(task));
@ -104,21 +99,8 @@ public interface BpmTaskConvert {
// 用户信息
buildTaskAssignee(taskVO, task.getAssignee(), userMap, deptMap);
buildTaskOwner(taskVO, task.getOwner(), userMap, deptMap);
if (BpmTaskStatusEnum.RUNNING.getStatus().equals(taskStatus)) {
// 操作按钮设置
taskVO.setButtonsSetting(BpmnModelUtils.parseButtonsSetting(bpmnModel, task.getTaskDefinitionKey()));
}
return taskVO;
});
// 拼接父子关系
Map<String, List<BpmTaskRespVO>> childrenTaskMap = convertMultiMap(
filterList(taskVOList, r -> StrUtil.isNotEmpty(r.getParentTaskId())),
BpmTaskRespVO::getParentTaskId);
for (BpmTaskRespVO taskVO : taskVOList) {
taskVO.setChildren(childrenTaskMap.get(taskVO.getId()));
}
return filterList(taskVOList, r -> StrUtil.isEmpty(r.getParentTaskId()));
}
default List<BpmTaskRespVO> buildTaskListByParentTaskId(List<Task> taskList,

View File

@ -156,9 +156,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
BpmnModel bpmnModel = bpmProcessDefinitionService.getProcessDefinitionBpmnModel(processInstance.getProcessDefinitionId());
List<BpmTaskRespVO> taskList = convertList(todoList, task -> {
// 找到分配给当前用户或者当前用户加签的任务为了减签
// TODO 3(!userId.equals(NumberUtil.parseLong(task.getOwner(), null)) || BpmTaskSignTypeEnum.of(task.getScopeType()) == null) 这个判断的目的是啥
// @芋艿 !isAddSignTask(userId, task) 该判断的目的被用户加签的任务该用户可以进行减签操作
if (!isAssignUserTask(userId, task) && !isAddSignTask(userId, task)) {
if (!isAssignUserTask(userId, task) && !isAddSignUserTask(userId, task)) {
return null;
}
BpmTaskRespVO taskVO = BeanUtils.toBean(task, BpmTaskRespVO.class);
@ -166,9 +164,10 @@ public class BpmTaskServiceImpl implements BpmTaskService {
taskVO.setButtonsSetting(BpmnModelUtils.parseButtonsSetting(bpmnModel, task.getTaskDefinitionKey()));
BpmTaskConvert.INSTANCE.buildTaskOwner(taskVO, task.getOwner(), userMap, deptMap);
// 如果是被加签的任务. 找到它的子任务 (为了减签)
if (isAddSignTask(userId, task)) {
// TODO @jason如果是向后加签这个判断有问题哈因为向后加签后当前任务assignee 还是没变可以简单点直接拿子任务哈另外需要考虑子任务的子任务
if (isAddSignUserTask(userId, task)) {
// TODO @jason这里其实可以考虑 157 173 把所有需要的数据都拿到然后交给 BpmTaskConvert.INSTANCE 转换出 taskVO这样service 只保留一些逻辑性强的东西类似 statusbuttonsetting都拿到 convert 里去
BpmTaskConvert.INSTANCE.buildTaskChildren(taskVO, childrenTaskMap, userMap, deptMap);
}
return taskVO;
});
@ -176,16 +175,24 @@ public class BpmTaskServiceImpl implements BpmTaskService {
}
/**
* 判断是否为被分配给用户的任务
* 判断指定用户是否是当前任务的分配人
*
* @param userId 用户编号
* @param task 任务
* @return 是否
*/
private boolean isAssignUserTask(Long userId, Task task) {
return ObjectUtil.equal(userId, NumberUtil.parseLong(task.getAssignee(), null));
}
/**
* 判断是否为被用户加签的任务
* 判断指定用户是否是当前任务的加签人
*
* @param userId 用户编号
* @param task 任务
* @return 是否
*/
private boolean isAddSignTask(Long userId, Task task) {
private boolean isAddSignUserTask(Long userId, Task task) {
return userId.equals(NumberUtil.parseLong(task.getOwner(), null))
&& BpmTaskSignTypeEnum.of(task.getScopeType()) != null;
}
@ -994,8 +1001,13 @@ public class BpmTaskServiceImpl implements BpmTaskService {
if (ObjectUtil.notEqual(transactionStatus, TransactionSynchronization.STATUS_COMMITTED)) {
return;
}
// TODO 芋艿可以后续优化成 getSelf();
// 特殊情况一人工审核审批人为空根据配置是否要自动通过自动拒绝
if (ObjectUtil.equal(approveType, BpmUserTaskApproveTypeEnum.USER.getType())) {
// 如果有审批人或者拥有人则说明不满足情况一不自动通过不自动拒绝
if (!ObjectUtil.isAllEmpty(task.getAssignee(), task.getOwner())) {
return;
}
if (ObjectUtil.equal(assignEmptyHandlerType, BpmUserTaskAssignEmptyHandlerTypeEnum.APPROVE.getType())) {
SpringUtil.getBean(BpmTaskService.class).approveTask(null, new BpmTaskApproveReqVO()
.setId(task.getId()).setReason(BpmReasonEnum.ASSIGN_EMPTY_APPROVE.getReason()));