Files
klp-oa/klp-wms/src/main/java/com/klp/service/impl/WmsApprovalServiceImpl.java
Joshi 30a06d297b feat(approval): 添加审批撤销功能
- 在IWmsApprovalService中新增cancelApproval方法定义
- 在IWmsApprovalTaskService中新增deleteByApprovalId方法定义
- 在WmsApprovalController中新增cancelApproval接口
- 在WmsApprovalServiceImpl中实现撤销审批业务逻辑
- 在WmsApprovalTaskServiceImpl中实现按审批ID删除任务功能
- 添加撤销审批的权限验证和重复提交限制
- 实现审批状态校验和关联任务清理机制
2026-03-11 15:52:28 +08:00

553 lines
22 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.klp.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.core.domain.model.LoginUser;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.domain.entity.SysDept;
import com.klp.common.core.domain.entity.SysUser;
import com.klp.common.core.service.UserService;
import com.klp.common.helper.LoginHelper;
import com.klp.common.utils.StringUtils;
import com.klp.domain.*;
import com.klp.mapper.*;
import com.klp.system.mapper.SysDeptMapper;
import com.klp.system.mapper.SysUserMapper;
import com.klp.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.klp.domain.bo.WmsApprovalBo;
import com.klp.domain.vo.WmsApprovalVo;
import com.klp.domain.bo.WmsApprovalTaskBo;
import com.klp.domain.vo.WmsApprovalTaskVo;
import com.klp.service.IWmsApprovalService;
import com.klp.service.IWmsApprovalTaskService;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import com.klp.domain.vo.WmsLeaveRequestVo;
import com.klp.domain.vo.WmsOutRequestVo;
/**
* 通用审批(支持请假/外出等申请的审批Service业务层处理
*
* @author klp
* @date 2026-01-20
*/
@RequiredArgsConstructor
@Service
public class WmsApprovalServiceImpl implements IWmsApprovalService {
private final WmsApprovalMapper baseMapper;
private final WmsApprovalTaskMapper approvalTaskMapper;
private final IWmsApprovalTaskService approvalTaskService;
private final WmsLeaveRequestMapper leaveRequestMapper;
private final WmsOutRequestMapper outRequestMapper;
private final ISysUserService userService;
private final WmsDeptMapper wmsDeptMapper;
private final SysUserMapper userMapper;
/**
* 查询通用审批(支持请假/外出等申请的审批)
*/
@Override
public Map<String, Object> queryById(Long approvalId){
Map<String, Object> result = new HashMap<>();
WmsApprovalVo approval = baseMapper.selectVoById(approvalId);
if (approval == null) {
return result;
}
result.put("approval", approval);
String type = approval.getApplyType();
Long applyId = approval.getApplyId();
if (StringUtils.isNotBlank(type) && applyId != null) {
if ("leave".equalsIgnoreCase(type)) {
WmsLeaveRequestVo detail = leaveRequestMapper.selectVoById(applyId);
// 详情接口也可以补充昵称转换(可选)
if (detail != null && StringUtils.isNotBlank(detail.getCreateBy())) {
Map<String, String> nickMap = userService.selectNickNameMapByUserNames(Collections.singletonList(detail.getCreateBy()));
detail.setCreateByName(nickMap.getOrDefault(detail.getCreateBy(), detail.getCreateBy()));
}
result.put("detail", detail);
result.put("applyType", "leave");
} else if ("out".equalsIgnoreCase(type)) {
WmsOutRequestVo outDetail = outRequestMapper.selectVoById(applyId);
// 详情接口也可以补充昵称转换(可选)
if (outDetail != null && StringUtils.isNotBlank(outDetail.getCreateBy())) {
Map<String, String> nickMap = userService.selectNickNameMapByUserNames(Collections.singletonList(outDetail.getCreateBy()));
outDetail.setCreateByName(nickMap.getOrDefault(outDetail.getCreateBy(), outDetail.getCreateBy()));
}
result.put("detail", outDetail);
result.put("applyType", "out");
}
}
return result;
}
/**
* 查询通用审批列表(含请假/外出详情+创建人昵称转换+审批任务)
*/
@Override
public TableDataInfo<Map<String, Object>> queryPageList(WmsApprovalBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<WmsApproval> lqw = buildQueryWrapper(bo);
// 1. 查询审批列表分页数据
Page<WmsApprovalVo> approvalPage = baseMapper.selectVoPage(pageQuery.build(), lqw);
List<WmsApprovalVo> approvalList = approvalPage.getRecords();
if (CollectionUtil.isEmpty(approvalList)) {
Page<Map<String, Object>> emptyResultPage = new Page<>();
emptyResultPage.setRecords(new ArrayList<>());
emptyResultPage.setTotal(approvalPage.getTotal());
emptyResultPage.setSize(approvalPage.getSize());
emptyResultPage.setCurrent(approvalPage.getCurrent());
emptyResultPage.setPages(approvalPage.getPages());
return TableDataInfo.build(emptyResultPage);
}
// 2. 收集所有审批ID用于查询审批任务
List<Long> approvalIds = approvalList.stream()
.map(WmsApprovalVo::getApprovalId)
.collect(Collectors.toList());
// 2.1 批量查询所有审批任务
List<WmsApprovalTaskVo> allTasks = approvalTaskMapper.selectVoList(
Wrappers.<com.klp.domain.WmsApprovalTask>lambdaQuery()
.in(com.klp.domain.WmsApprovalTask::getApprovalId, approvalIds)
.orderByAsc(com.klp.domain.WmsApprovalTask::getCreateTime)
);
// 2.2 按审批ID分组任务
Map<Long, List<WmsApprovalTaskVo>> tasksMap = allTasks.stream()
.collect(Collectors.groupingBy(WmsApprovalTaskVo::getApprovalId));
// 3. 处理审批列表,拼接请假/外出详情,并收集所有需要转换的创建人账号
List<Map<String, Object>> resultList = new ArrayList<>();
Set<String> userNames = new HashSet<>(); // 存储所有需要查询昵称的账号
for (WmsApprovalVo approval : approvalList) {
Map<String, Object> item = new HashMap<>();
item.put("approval", approval); // 审批基础信息
// 3.1 添加审批任务列表
List<WmsApprovalTaskVo> tasks = tasksMap.getOrDefault(approval.getApprovalId(), new ArrayList<>());
item.put("tasks", tasks);
String applyType = approval.getApplyType();
Long applyId = approval.getApplyId();
Object detail = null;
// 4. 查询请假/外出详情,并收集创建人账号
if (StringUtils.isNotBlank(applyType) && applyId != null) {
if ("leave".equalsIgnoreCase(applyType)) {
WmsLeaveRequestVo leaveDetail = leaveRequestMapper.selectVoById(applyId);
detail = leaveDetail;
// 收集请假申请的创建人账号
if (leaveDetail != null && StringUtils.isNotBlank(leaveDetail.getCreateBy())) {
userNames.add(leaveDetail.getCreateBy());
}
item.put("applyType", "leave");
} else if ("out".equalsIgnoreCase(applyType)) {
WmsOutRequestVo outDetail = outRequestMapper.selectVoById(applyId);
detail = outDetail;
// 收集外出申请的创建人账号
if (outDetail != null && StringUtils.isNotBlank(outDetail.getCreateBy())) {
userNames.add(outDetail.getCreateBy());
}
item.put("applyType", "out");
}
item.put("detail", detail);
}
resultList.add(item);
}
// 5. 批量查询昵称映射
Map<String, String> nickMap = Collections.emptyMap();
if (!userNames.isEmpty()) {
nickMap = userService.selectNickNameMapByUserNames(new ArrayList<>(userNames));
}
// 6. 遍历填充请假/外出申请的创建人昵称
for (Map<String, Object> item : resultList) {
Object detail = item.get("detail");
if (detail == null || nickMap.isEmpty()) {
continue;
}
// 区分请假/外出类型,填充创建人昵称
if ("leave".equals(item.get("applyType"))) {
WmsLeaveRequestVo leaveDetail = (WmsLeaveRequestVo) detail;
if (StringUtils.isNotBlank(leaveDetail.getCreateBy())) {
// 填充创建人昵称
leaveDetail.setCreateByName(nickMap.getOrDefault(leaveDetail.getCreateBy(), leaveDetail.getCreateBy()));
}
} else if ("out".equals(item.get("applyType"))) {
WmsOutRequestVo outDetail = (WmsOutRequestVo) detail;
if (StringUtils.isNotBlank(outDetail.getCreateBy())) {
outDetail.setCreateByName(nickMap.getOrDefault(outDetail.getCreateBy(), outDetail.getCreateBy()));
}
}
}
// 7. 构建分页返回结果
Page<Map<String, Object>> resultPage = new Page<>();
resultPage.setRecords(resultList);
resultPage.setTotal(approvalPage.getTotal());
resultPage.setSize(approvalPage.getSize());
resultPage.setCurrent(approvalPage.getCurrent());
resultPage.setPages(approvalPage.getPages());
return TableDataInfo.build(resultPage);
}
/**
* 查询通用审批(支持请假/外出等申请的审批)列表
*/
@Override
public List<WmsApprovalVo> queryList(WmsApprovalBo bo) {
LambdaQueryWrapper<WmsApproval> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<WmsApproval> buildQueryWrapper(WmsApprovalBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<WmsApproval> lqw = Wrappers.lambdaQuery();
lqw.eq(StringUtils.isNotBlank(bo.getApplyType()), WmsApproval::getApplyType, bo.getApplyType());
lqw.eq(bo.getApplyId() != null, WmsApproval::getApplyId, bo.getApplyId());
lqw.like(StringUtils.isNotBlank(bo.getApproverName()), WmsApproval::getApproverName, bo.getApproverName());
lqw.eq(StringUtils.isNotBlank(bo.getApprovalStatus()), WmsApproval::getApprovalStatus, bo.getApprovalStatus());
lqw.eq(StringUtils.isNotBlank(bo.getApprovalOpinion()), WmsApproval::getApprovalOpinion, bo.getApprovalOpinion());
lqw.eq(bo.getApprovalTime() != null, WmsApproval::getApprovalTime, bo.getApprovalTime());
// 根据创建人筛选
lqw.eq(StringUtils.isNotBlank(bo.getCreateBy()), WmsApproval::getCreateBy, bo.getCreateBy());
// 根据创建时间倒叙
lqw.orderByDesc(WmsApproval::getCreateTime);
return lqw;
}
/**
* 新增通用审批(支持请假/外出等申请的审批)
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByBo(WmsApprovalBo bo) {
WmsApproval add = BeanUtil.toBean(bo, WmsApproval.class);
validEntityBeforeSave(add);
if (add.getApprovalType() == null) {
add.setApprovalType("single");
}
if (add.getRequiredApprovers() == null) {
add.setRequiredApprovers(0);
}
if (add.getCurrentApprovers() == null) {
add.setCurrentApprovers(0);
}
if (add.getFinalStatus() == null) {
add.setFinalStatus("pending");
}
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setApprovalId(add.getApprovalId());
if ("leave".equals(add.getApplyType()) && add.getApplyId() != null) {
createLeaveApprovalTasks(add.getApprovalId(), add.getApplyId(), add.getApplyType(), add.getApprovalType(), bo.getDeptId());
}
if ("out".equals(add.getApplyType()) && add.getApplyId() != null) {
createOutApprovalTasks(add.getApprovalId(), add.getApplyId(), add.getApplyType(), add.getApprovalType(), bo.getDeptId());
}
}
return flag;
}
private void createOutApprovalTasks(Long approvalId, Long applyId, String applyType, String approvalType, Long deptId) {
if (!"out".equals(applyType)) {
return;
}
WmsOutRequest outRequest = outRequestMapper.selectById(applyId);
if (outRequest == null) {
return;
}
WmsApproval updateApproval = new WmsApproval();
updateApproval.setApprovalId(approvalId);
updateApproval.setApprovalType(approvalType);
updateApproval.setRequiredApprovers(1);
// 根据applicantId查询审批人name和id
WmsDept dept = wmsDeptMapper.selectById(deptId);
SysUser leader = userMapper.selectById(dept.getLeader());
if (leader != null) {
WmsApprovalTaskBo taskBo = new WmsApprovalTaskBo();
taskBo.setApprovalId(approvalId);
taskBo.setApproverId(dept.getLeader());
taskBo.setApproverName(leader.getNickName());
taskBo.setTaskStatus("pending");
approvalTaskMapper.insert(BeanUtil.toBean(taskBo, WmsApprovalTask.class));
}
baseMapper.updateById(updateApproval);
}
private void createLeaveApprovalTasks(Long approvalId, Long applyId, String applyType, String approvalType, Long deptId) {
if (!"leave".equals(applyType)) {
return;
}
WmsLeaveRequest leaveRequest = leaveRequestMapper.selectById(applyId);
if (leaveRequest == null) {
return;
}
boolean isMultiLevel = approvalType.equals("multi");
WmsApproval updateApproval = new WmsApproval();
updateApproval.setApprovalId(approvalId);
updateApproval.setApprovalType(approvalType);
if (isMultiLevel) {
List<Long> leaderUserIds = getDeptLeaders(deptId);
updateApproval.setRequiredApprovers(leaderUserIds.size());
for (Long leaderUserId : leaderUserIds) {
SysUser leaderUser = userMapper.selectById(leaderUserId);
if (leaderUser != null) {
WmsApprovalTaskBo taskBo = new WmsApprovalTaskBo();
taskBo.setApprovalId(approvalId);
taskBo.setApproverId(leaderUserId);
taskBo.setApproverName(leaderUser.getNickName());
taskBo.setTaskStatus("pending");
approvalTaskMapper.insert(BeanUtil.toBean(taskBo, WmsApprovalTask.class));
}
}
} else {
updateApproval.setRequiredApprovers(1);
// 根据applicantId查询审批人name和id
WmsDept dept = wmsDeptMapper.selectById(deptId);
SysUser leader = userMapper.selectById(dept.getLeader());
if (leader != null) {
WmsApprovalTaskBo taskBo = new WmsApprovalTaskBo();
taskBo.setApprovalId(approvalId);
taskBo.setApproverId(dept.getLeader());
taskBo.setApproverName(leader.getNickName());
taskBo.setTaskStatus("pending");
approvalTaskMapper.insert(BeanUtil.toBean(taskBo, WmsApprovalTask.class));
}
}
baseMapper.updateById(updateApproval);
}
private List<Long> getDeptLeaders(Long deptId) {
List<Long> leaderUserIds = new ArrayList<>();
if (deptId == null) {
return leaderUserIds;
}
// 获取部门的所有祖先部门ID包括自己
List<Long> ancestorDeptIds = new ArrayList<>();
Long currentDeptId = deptId;
while (currentDeptId != null) {
ancestorDeptIds.add(currentDeptId);
WmsDept currentDept = wmsDeptMapper.selectById(currentDeptId);
if (currentDept != null) {
currentDeptId = currentDept.getParentId();
} else {
break;
}
}
// 查询每个祖先部门的leader字段内容
if (!ancestorDeptIds.isEmpty()) {
List<WmsDept> ancestorDepts = wmsDeptMapper.selectList(new LambdaQueryWrapper<WmsDept>()
.in(WmsDept::getDeptId, ancestorDeptIds));
if (CollectionUtil.isNotEmpty(ancestorDepts)) {
// 提取所有leader字段的内容
leaderUserIds = ancestorDepts.stream()
.map(WmsDept::getLeader)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList());
// // 根据leader名称查询对应的用户ID
// if (!leaderNames.isEmpty()) {
// List<SysUser> leaders = userMapper.selectList(new LambdaQueryWrapper<SysUser>()
// .in(SysUser::getNickName, leaderNames));
//
// if (CollectionUtil.isNotEmpty(leaders)) {
// leaderUserIds = leaders.stream()
// .map(SysUser::getUserId)
// .distinct()
// .collect(Collectors.toList());
// }
// }
}
}
return leaderUserIds;
}
/**
* 修改通用审批(支持请假/外出等申请的审批)
*/
@Override
public Boolean updateByBo(WmsApprovalBo bo) {
WmsApproval update = BeanUtil.toBean(bo, WmsApproval.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(WmsApproval entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除通用审批(支持请假/外出等申请的审批)
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> approveTask(Long taskId, String approvalOpinion) {
Map<String, Object> result = new HashMap<>();
com.klp.domain.WmsApprovalTask task = approvalTaskMapper.selectById(taskId);
if (task == null) {
result.put("success", false);
result.put("message", "审批任务不存在");
return result;
}
if (!"pending".equals(task.getTaskStatus())) {
result.put("success", false);
result.put("message", "该任务已审批,不能重复审批");
return result;
}
task.setTaskStatus("approved");
task.setApprovalOpinion(approvalOpinion);
task.setApprovalTime(new Date());
approvalTaskMapper.updateById(task);
WmsApproval approval = baseMapper.selectById(task.getApprovalId());
if (approval != null) {
int currentApprovers = (approval.getCurrentApprovers() != null ? approval.getCurrentApprovers() : 0) + 1;
approval.setCurrentApprovers(currentApprovers);
if (currentApprovers >= approval.getRequiredApprovers()) {
approval.setApprovalStatus("已同意");
approval.setFinalStatus("all_approved");
}
baseMapper.updateById(approval);
}
result.put("success", true);
result.put("message", "审批通过");
return result;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> rejectTask(Long taskId, String approvalOpinion) {
Map<String, Object> result = new HashMap<>();
com.klp.domain.WmsApprovalTask task = approvalTaskMapper.selectById(taskId);
if (task == null) {
result.put("success", false);
result.put("message", "审批任务不存在");
return result;
}
if (!"pending".equals(task.getTaskStatus())) {
result.put("success", false);
result.put("message", "该任务已审批,不能重复审批");
return result;
}
task.setTaskStatus("rejected");
task.setApprovalOpinion(approvalOpinion);
task.setApprovalTime(new Date());
approvalTaskMapper.updateById(task);
WmsApproval approval = baseMapper.selectById(task.getApprovalId());
if (approval != null) {
approval.setApprovalStatus("已驳回");
approval.setFinalStatus("rejected");
baseMapper.updateById(approval);
}
result.put("success", true);
result.put("message", "审批驳回");
return result;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> cancelApproval(Long approvalId) {
Map<String, Object> result = new HashMap<>();
result.put("success", false);
if (approvalId == null) {
result.put("message", "审批ID不能为空");
return result;
}
WmsApproval approval = baseMapper.selectById(approvalId);
if (approval == null) {
result.put("message", "审批记录不存在");
return result;
}
if ("已撤销".equals(approval.getApprovalStatus())) {
result.put("message", "该审批已被撤销");
return result;
}
if ("已同意".equals(approval.getApprovalStatus())) {
result.put("message", "已通过的审批不能撤销");
return result;
}
List<WmsApprovalTaskVo> tasks = approvalTaskService.queryByApprovalId(approvalId);
if (tasks != null && !tasks.isEmpty()) {
for (WmsApprovalTaskVo task : tasks) {
if (task.getTaskStatus() != null && !"pending".equals(task.getTaskStatus())) {
result.put("message", "该审批已被审批,不能撤销(审批人:" + task.getApproverName() + ",状态:" + task.getTaskStatus() + "");
return result;
}
}
}
Integer deletedCount = approvalTaskService.deleteByApprovalId(approvalId);
approval.setApprovalStatus("已撤销");
approval.setFinalStatus("cancelled");
baseMapper.updateById(approval);
result.put("success", true);
result.put("message", "撤销成功");
result.put("deletedTaskCount", deletedCount);
return result;
}
}