code review 工作流的代码

合并最新的 SQL
This commit is contained in:
YunaiV
2021-10-30 13:46:39 +08:00
parent 31c4a52858
commit 742125ed99
13 changed files with 210 additions and 878 deletions

View File

@ -1,33 +1,32 @@
package cn.iocoder.yudao.adminserver.modules.activiti.controller.oa;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.*;
import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa.OaLeaveDO;
import cn.iocoder.yudao.adminserver.modules.activiti.convert.oa.OaLeaveConvert;
import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa.OaLeaveDO;
import cn.iocoder.yudao.adminserver.modules.activiti.service.oa.OaLeaveService;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
// TODO @jasonOa=》OA 会不会好点,名词缩写哈
@Api(tags = "请假申请")
@RestController
@RequestMapping("/oa/leave")
@ -41,6 +40,7 @@ public class OaLeaveController {
@ApiOperation("创建请假申请")
@PreAuthorize("@ss.hasPermission('oa:leave:create')")
public CommonResult<Long> createLeave(@Valid @RequestBody OaLeaveCreateReqVO createReqVO) {
// TODO @芋艿processKey 自己去理解下。不过得把 leave 变成枚举
createReqVO.setProcessKey("leave");
return success(leaveService.createLeave(createReqVO));
}
@ -48,6 +48,7 @@ public class OaLeaveController {
@PostMapping("/form-key/create")
@ApiOperation("创建外置请假申请")
public CommonResult<Long> createFormKeyLeave(@Valid @RequestBody OaLeaveCreateReqVO createReqVO) {
// TODO @芋艿processKey 自己去理解下。不过得把 formkey 变成枚举
createReqVO.setProcessKey("leave-formkey");
return success(leaveService.createLeave(createReqVO));
}
@ -92,6 +93,7 @@ public class OaLeaveController {
@PreAuthorize("@ss.hasPermission('oa:leave:query')")
public CommonResult<PageResult<OaLeaveRespVO>> getLeavePage(@Valid OaLeavePageReqVO pageVO) {
//值查询自己申请请假
// TODO @芋艿:这里的传值,到底前端搞,还是后端搞。
pageVO.setUserId(SecurityFrameworkUtils.getLoginUser().getUsername());
PageResult<OaLeaveDO> pageResult = leaveService.getLeavePage(pageVO);
return success(OaLeaveConvert.INSTANCE.convertPage(pageResult));

View File

@ -1,9 +1,13 @@
package cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
import java.util.Map;
@ApiModel("请假申请更新 Request VO")
@Data
@ -15,6 +19,7 @@ public class OaLeaveUpdateReqVO extends OaLeaveBaseVO {
@NotNull(message = "请假表单主键不能为空")
private Long id;
// TODO @jsonswagger 和 validator 的注解要加哈。
private String taskId;
@ -22,4 +27,6 @@ public class OaLeaveUpdateReqVO extends OaLeaveBaseVO {
private Map<String,Object> variables;
// TODO @芋艿variables 的作用是啥。
}

View File

@ -3,8 +3,6 @@ package cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@ -12,6 +10,7 @@ import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
// TODO @jsonswagger 和 validation 的注解,后续要补全下哈。可以等 workflow 基本写的差不多之后
@RestController
@RequestMapping("/workflow/process/definition")
public class ProcessDefinitionController {
@ -31,4 +30,5 @@ public class ProcessDefinitionController {
// processRuntime.processDefinition(processDefinition.getId()).getFormKey();
return CommonResult.success("/flow/leave/apply");
}
}

View File

@ -14,6 +14,7 @@ import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
// TODO @jsonswagger 和 validation 的注解,后续要补全下哈。可以等 workflow 基本写的差不多之后
@Api(tags = "工作流待办任务")
@RestController
@RequestMapping("/workflow/task")
@ -22,8 +23,6 @@ public class TaskController {
@Resource
private TaskService taskService;
@GetMapping("/todo/page")
@ApiOperation("获取待办任务分页")
public CommonResult<PageResult<TodoTaskRespVO>> getTodoTaskPage(@Valid TodoTaskPageReqVO pageVO) {
@ -37,15 +36,14 @@ public class TaskController {
return success(true);
}
@PostMapping("/task-steps")
public CommonResult<TaskHandleVO> getTaskSteps(@RequestBody TaskQueryReqVO taskQuery) {
return success( taskService.getTaskSteps(taskQuery));
return success(taskService.getTaskSteps(taskQuery));
}
@PostMapping("/formKey")
public CommonResult<TodoTaskRespVO> getTaskFormKey(@RequestBody TaskQueryReqVO taskQuery) {
return success( taskService.getTaskFormKey(taskQuery));
return success(taskService.getTaskFormKey(taskQuery));
}
@PostMapping("/complete")
@ -54,9 +52,9 @@ public class TaskController {
return success(true);
}
@GetMapping("/process/history-steps")
public CommonResult<List<TaskStepVO>> getHistorySteps(@RequestParam("id") String processInstanceId) {
return success( taskService.getHistorySteps(processInstanceId));
return success(taskService.getHistorySteps(processInstanceId));
}
}

View File

@ -0,0 +1,2 @@
// TODO @芋艿:思考下 activiti、oa 的定位,边界,模块的拆分
package cn.iocoder.yudao.adminserver.modules.activiti;

View File

@ -4,9 +4,7 @@ import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa.OaLeaveDO
import cn.iocoder.yudao.adminserver.modules.activiti.dal.mysql.oa.OaLeaveMapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.ExecutionListener;
import org.activiti.engine.delegate.TaskListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@ -34,10 +32,12 @@ public class ReportBackEndProcessor implements ExecutionListener {
@Transactional(rollbackFor = Exception.class)
public void notify(DelegateExecution delegateExecution) {
final String businessKey = delegateExecution.getProcessInstanceBusinessKey();
// TODO @jsonservice 不要出现 dao 的元素,例如说 UpdateWrapper。这里我们可以调用 updateById 方法
UpdateWrapper<OaLeaveDO> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", Long.valueOf(businessKey));
OaLeaveDO updateDo = new OaLeaveDO();
updateDo.setStatus(2);
updateDo.setStatus(2); // TODO @jsonstatus 要枚举起来,不要出现 magic number
leaveMapper.update(updateDo, updateWrapper);
}
}

View File

@ -1,5 +1,14 @@
package cn.iocoder.yudao.adminserver.modules.activiti.service.oa.impl;
import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.OaLeaveCreateReqVO;
import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.OaLeaveExportReqVO;
import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.OaLeavePageReqVO;
import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.OaLeaveUpdateReqVO;
import cn.iocoder.yudao.adminserver.modules.activiti.convert.oa.OaLeaveConvert;
import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa.OaLeaveDO;
import cn.iocoder.yudao.adminserver.modules.activiti.dal.mysql.oa.OaLeaveMapper;
import cn.iocoder.yudao.adminserver.modules.activiti.service.oa.OaLeaveService;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.activiti.api.task.model.Task;
@ -7,24 +16,18 @@ import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.util.*;
import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.*;
import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa.OaLeaveDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.adminserver.modules.activiti.convert.oa.OaLeaveConvert;
import cn.iocoder.yudao.adminserver.modules.activiti.dal.mysql.oa.OaLeaveMapper;
import cn.iocoder.yudao.adminserver.modules.activiti.service.oa.OaLeaveService;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.adminserver.modules.activiti.enums.OaErrorCodeConstants.LEAVE_NOT_EXISTS;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.adminserver.modules.activiti.enums.OaErrorCodeConstants.*;
/**
* 请假申请 Service 实现类
@ -50,35 +53,34 @@ public class OaLeaveServiceImpl implements OaLeaveService {
@Override
@Transactional(rollbackFor = Exception.class)
public Long createLeave(OaLeaveCreateReqVO createReqVO) {
// 插入
// 插入 OA 请假单
OaLeaveDO leave = OaLeaveConvert.INSTANCE.convert(createReqVO);
leave.setStatus(1);
leave.setUserId(SecurityFrameworkUtils.getLoginUser().getUsername());
leaveMapper.insert(leave);
// 创建工作流
Map<String, Object> variables = new HashMap<>();
//如何得到部门领导人, 暂时写死
variables.put("deptLeader", "admin");
final Long id = leave.getId();
// 如何得到部门领导人,暂时写死
variables.put("deptLeader", "admin"); // TODO @芋艿:需要部门的负责人
Long id = leave.getId();
String businessKey = String.valueOf(id);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(createReqVO.getProcessKey(), businessKey, variables);
String processInstanceId = processInstance.getProcessInstanceId();
final String processInstanceId = processInstance.getProcessInstanceId();
// TODO @jsonservice 不要出现 dao 的元素,例如说 UpdateWrapper。这里我们可以调用 updateById 方法
// 将工作流的编号,更新到 OA 请假单中
UpdateWrapper<OaLeaveDO> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", id);
OaLeaveDO updateDo = new OaLeaveDO();
updateDo.setProcessInstanceId(processInstanceId);
leaveMapper.update(updateDo, updateWrapper);
// 返回
return id;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateLeave(OaLeaveUpdateReqVO updateReqVO) {
// 校验存在
this.validateLeaveExists(updateReqVO.getId());
@ -91,14 +93,14 @@ public class OaLeaveServiceImpl implements OaLeaveService {
taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(task.getId())
.withVariables(variables)
.build());
// TODO @jason不需要加 final 哈。虽然是不变,但是代码比较少这么去写
final Object reApply = variables.get("reApply");
// TODO @jason直接使用 Objects.equals(reApply, true) 就可以
if((reApply instanceof Boolean) && (Boolean)reApply){
// 更新 表单
OaLeaveDO updateObj = OaLeaveConvert.INSTANCE.convert(updateReqVO);
leaveMapper.updateById(updateObj);
}
}
@Override
@ -107,6 +109,7 @@ public class OaLeaveServiceImpl implements OaLeaveService {
this.validateLeaveExists(id);
// 删除
leaveMapper.deleteById(id);
// TODO @jason需要调用 runtimeService 的 delete 方法,删除???
}
private void validateLeaveExists(Long id) {

View File

@ -3,9 +3,9 @@ package cn.iocoder.yudao.adminserver.modules.activiti.service.workflow;
import cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
// TODO @芋艿:前缀,注释
public interface TaskService {
PageResult<TodoTaskRespVO> getTodoTaskPage(TodoTaskPageReqVO pageReqVO);
@ -22,4 +22,5 @@ public interface TaskService {
List<TaskStepVO> getHistorySteps(String processInstanceId);
TodoTaskRespVO getTaskFormKey(TaskQueryReqVO taskQuery);
}

View File

@ -1,39 +1,28 @@
package cn.iocoder.yudao.adminserver.modules.activiti.service.workflow.impl;
import cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo.*;
import cn.iocoder.yudao.adminserver.modules.activiti.convert.oa.OaLeaveConvert;
import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa.OaLeaveDO;
import cn.iocoder.yudao.adminserver.modules.activiti.dal.mysql.oa.OaLeaveMapper;
import cn.iocoder.yudao.adminserver.modules.activiti.service.oa.OaLeaveService;
import cn.iocoder.yudao.adminserver.modules.activiti.service.workflow.TaskService;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.google.common.collect.ImmutableMap;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.runtime.shared.query.Page;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.model.builders.ClaimTaskPayloadBuilder;
import org.activiti.api.task.model.builders.GetTasksPayloadBuilder;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.task.Comment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -70,8 +59,10 @@ public class TaskServiceImpl implements TaskService {
@Override
public PageResult<TodoTaskRespVO> getTodoTaskPage(TodoTaskPageReqVO pageReqVO) {
final LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
// TODO @jason封装一个方法用于转换成 activiti 的分页对象
final Pageable pageable = Pageable.of((pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize(), pageReqVO.getPageSize());
Page<Task> pageTasks = taskRuntime.tasks(pageable);
// TODO @jasonconvert 里转换
List<Task> tasks = pageTasks.getContent();
int totalItems = pageTasks.getTotalItems();
final List<TodoTaskRespVO> respVOList = tasks.stream().map(task -> {
@ -84,7 +75,8 @@ public class TaskServiceImpl implements TaskService {
respVO.setStatus(task.getAssignee() == null ? 1 : 2);
return respVO;
}).collect(Collectors.toList());
return new PageResult(respVOList, Long.valueOf(totalItems));
// TODO @jason要注意泛型哈。
return new PageResult(respVOList, Long.valueOf(totalItems)); // TODO @jason(long) 转换即可
}
@ -98,12 +90,11 @@ public class TaskServiceImpl implements TaskService {
@Override
public void getTaskHistory(String taskId) {
final List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().
processInstanceId("8e2801fc-1a38-11ec-98ce-74867a13730f").list();
}
// TODO @jason一个方法里会有多个方法的调用最好写下对应的注释。这样容易理解
@Override
@Transactional
public void completeTask(TaskReqVO taskReq) {
@ -173,38 +164,40 @@ public class TaskServiceImpl implements TaskService {
private List<TaskStepVO> getTaskSteps(String processInstanceId) {
List<TaskStepVO> steps = new ArrayList<>();
List<HistoricActivityInstance> finished = historyService
.createHistoricActivityInstanceQuery()
// 获得已完成的活动
List<HistoricActivityInstance> finished = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(processInstanceId)
.activityType("userTask")
.finished()
.orderByHistoricActivityInstanceStartTime().asc().list();
finished.forEach(instance->{
// 获得对应的步骤
List<TaskStepVO> steps = new ArrayList<>();
finished.forEach(instance -> {
// TODO @jason放到 convert 里
TaskStepVO step = new TaskStepVO();
step.setStepName(instance.getActivityName());
step.setStartTime(instance.getStartTime());
step.setEndTime(instance.getEndTime());
step.setAssignee(instance.getAssignee());
step.setStatus(1);
final List<Comment> comments = activitiTaskService.getTaskComments(instance.getTaskId());
if(comments.size()>0){
// TODO @jason一般判数组为空使用 CollUtil.isEmpty 会好点哈。另外null 时候,不用填写 "" 的哈
List<Comment> comments = activitiTaskService.getTaskComments(instance.getTaskId());
if (comments.size() > 0) {
step.setComment(comments.get(0).getFullMessage());
}else{
} else {
step.setComment("");
}
steps.add(step);
});
// 获得未完成的活动
List<HistoricActivityInstance> unfinished = historyService
.createHistoricActivityInstanceQuery()
.processInstanceId(processInstanceId)
.activityType("userTask")
.unfinished().list();
// 获得对应的步骤
// TODO @json其实已完成和未完成它们的 convert 的逻辑,是一致的
for (HistoricActivityInstance instance : unfinished) {
TaskStepVO step = new TaskStepVO();
step.setStepName(instance.getActivityName());
@ -221,13 +214,13 @@ public class TaskServiceImpl implements TaskService {
@Override
public List<TaskStepVO> getHistorySteps(String processInstanceId) {
return getTaskSteps(processInstanceId);
}
@Override
public TodoTaskRespVO getTaskFormKey(TaskQueryReqVO taskQuery) {
final Task task = taskRuntime.task(taskQuery.getTaskId());
// 转换结果
TodoTaskRespVO respVO = new TodoTaskRespVO();
respVO.setFormKey(task.getFormKey());
respVO.setBusinessKey(task.getBusinessKey());
@ -235,7 +228,6 @@ public class TaskServiceImpl implements TaskService {
return respVO;
}
// private List<String> getHighLightedFlows(ProcessDefinitionEntity processDefinition, String processInstanceId) {
//
// List<String> highLightedFlows = new ArrayList<String>();
@ -270,4 +262,5 @@ public class TaskServiceImpl implements TaskService {
// }
// return highLightedFlows;
// }
}