package com.ruoyi.approve.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.ruoyi.approve.mapper.ApproveLogMapper;
|
import com.ruoyi.approve.mapper.ApproveNodeMapper;
|
import com.ruoyi.approve.mapper.ApproveProcessMapper;
|
import com.ruoyi.approve.pojo.ApproveLog;
|
import com.ruoyi.approve.pojo.ApproveNode;
|
import com.ruoyi.approve.pojo.ApproveProcess;
|
import com.ruoyi.approve.service.IApproveNodeService;
|
import com.ruoyi.approve.vo.ApproveNodeVO;
|
import com.ruoyi.common.enums.FileNameType;
|
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.other.service.impl.TempFileServiceImpl;
|
import com.ruoyi.project.system.domain.SysUser;
|
import com.ruoyi.project.system.mapper.SysUserMapper;
|
import com.ruoyi.sales.mapper.CommonFileMapper;
|
import com.ruoyi.sales.pojo.CommonFile;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.StringUtils;
|
|
import java.io.IOException;
|
import java.math.BigDecimal;
|
import java.time.LocalDateTime;
|
import java.util.ArrayList;
|
import java.util.Comparator;
|
import java.util.Date;
|
import java.util.List;
|
|
@Service
|
@RequiredArgsConstructor
|
public class ApproveNodeServiceImpl extends ServiceImpl<ApproveNodeMapper, ApproveNode> implements IApproveNodeService {
|
private final ApproveNodeMapper approveNodeMapper;
|
private final ApproveProcessMapper approveProcessMapper;
|
private final ApproveLogMapper approveLogMapper;
|
private final SysUserMapper sysUserMapper;
|
private final TempFileServiceImpl tempFileService;
|
private final CommonFileMapper fileMapper;
|
|
private ApproveProcess getApproveById(String code) {
|
ApproveProcess process = approveProcessMapper.selectOne(new LambdaQueryWrapper<ApproveProcess>()
|
.eq(ApproveProcess::getApproveId, code)
|
.eq(ApproveProcess::getApproveDelete, 0)
|
.eq(ApproveProcess::getTenantId, tenantId())
|
.last("limit 1"));
|
if (process == null) throw new RuntimeException("审批不存在");
|
return process;
|
}
|
|
@Override
|
public void initApproveNodes(String approveUserIds, String approveID, Long tenantId) {
|
if (!StringUtils.hasText(approveUserIds)) throw new RuntimeException("请选择审批人");
|
List<ApproveNodeVO> nodes = new ArrayList<>();
|
for (String id : approveUserIds.split(",")) {
|
ApproveNodeVO node = new ApproveNodeVO();
|
node.setUserId(Long.parseLong(id.trim()));
|
node.setConditionOperator("ALWAYS");
|
nodes.add(node);
|
}
|
initApproveNodes(nodes, approveID, tenantId);
|
}
|
|
@Override
|
public void initApproveNodes(List<ApproveNodeVO> nodes, String approveID, Long ignoredTenantId) {
|
if (CollectionUtils.isEmpty(nodes)) throw new RuntimeException("审批流程至少包含一个节点");
|
Long tenantId = tenantId();
|
Long currentUserId = SecurityUtils.getUserId();
|
ApproveProcess process = getApproveById(approveID);
|
int order = 1;
|
ApproveNode first = null;
|
Long previousUserId = null;
|
for (ApproveNodeVO request : nodes) {
|
if (request.getUserId() == null) throw new RuntimeException("审批人不能为空");
|
if (request.getUserId().equals(previousUserId)) throw new RuntimeException("相邻审批节点不能选择同一审批人");
|
previousUserId = request.getUserId();
|
if (!matchesCondition(process.getAmount(), request)) continue;
|
SysUser user = sysUserMapper.selectUserById(request.getUserId());
|
if (user == null || !tenantId.equals(user.getTenantId())) throw new RuntimeException("审批人不存在或不属于当前租户");
|
ApproveNode node = new ApproveNode();
|
node.setApproveProcessId(process.getApproveId());
|
node.setApproveNodeOrder(order++);
|
node.setApproveNodeName(StringUtils.hasText(request.getNodeName()) ? request.getNodeName() : "审批");
|
node.setApproveNodeUser(user.getNickName());
|
node.setApproveNodeUserId(user.getUserId());
|
node.setApproveNodeStatus(0);
|
node.setConditionField(request.getConditionField());
|
node.setConditionOperator(StringUtils.hasText(request.getConditionOperator()) ? request.getConditionOperator() : "ALWAYS");
|
node.setConditionValue(request.getConditionValue());
|
node.setIsCurrent(first == null ? 1 : 0);
|
node.setTenantId(tenantId);
|
node.setDeleteFlag(0);
|
node.setCreateUser(currentUserId);
|
node.setUpdateUser(currentUserId);
|
node.setCreateTime(LocalDateTime.now());
|
node.setUpdateTime(LocalDateTime.now());
|
approveNodeMapper.insert(node);
|
if (first == null) first = node;
|
}
|
if (first == null) throw new RuntimeException("没有满足条件的审批节点");
|
process.setApproveUserCurrentId(first.getApproveNodeUserId());
|
process.setApproveUserCurrentName(first.getApproveNodeUser());
|
process.setUpdateTime(LocalDateTime.now());
|
approveProcessMapper.updateById(process);
|
}
|
|
private boolean matchesCondition(BigDecimal amount, ApproveNodeVO node) {
|
String operator = node.getConditionOperator();
|
if (!StringUtils.hasText(operator) || "ALWAYS".equalsIgnoreCase(operator)) return true;
|
if (!"amount".equals(node.getConditionField())) throw new RuntimeException("审批条件仅支持金额字段");
|
if (amount == null || !StringUtils.hasText(node.getConditionValue())) return false;
|
try {
|
if ("BETWEEN".equalsIgnoreCase(operator)) {
|
String[] values = node.getConditionValue().replace("[", "").replace("]", "").split(",");
|
if (values.length != 2) throw new RuntimeException("金额区间格式不正确");
|
return amount.compareTo(new BigDecimal(values[0].trim())) >= 0
|
&& amount.compareTo(new BigDecimal(values[1].trim())) <= 0;
|
}
|
int compared = amount.compareTo(new BigDecimal(node.getConditionValue()));
|
if ("GT".equalsIgnoreCase(operator)) return compared > 0;
|
if ("GTE".equalsIgnoreCase(operator)) return compared >= 0;
|
if ("LT".equalsIgnoreCase(operator)) return compared < 0;
|
if ("LTE".equalsIgnoreCase(operator)) return compared <= 0;
|
if ("EQ".equalsIgnoreCase(operator)) return compared == 0;
|
} catch (NumberFormatException ex) {
|
throw new RuntimeException("审批条件金额格式不正确");
|
}
|
throw new RuntimeException("不支持的审批条件操作符");
|
}
|
|
@Override
|
public List<ApproveNode> details(String id) {
|
getApproveById(id);
|
List<ApproveNode> nodes = approveNodeMapper.selectList(new LambdaQueryWrapper<ApproveNode>()
|
.eq(ApproveNode::getApproveProcessId, id)
|
.eq(ApproveNode::getDeleteFlag, 0)
|
.eq(ApproveNode::getTenantId, tenantId())
|
.orderByAsc(ApproveNode::getApproveNodeOrder));
|
for (ApproveNode node : nodes) {
|
List<CommonFile> files = fileMapper.selectList(new LambdaQueryWrapper<CommonFile>()
|
.eq(CommonFile::getCommonId, node.getId())
|
.eq(CommonFile::getType, FileNameType.ApproveNode.getValue()));
|
if (!CollectionUtils.isEmpty(files)) node.setUrl(files.get(0).getUrl());
|
node.setIsShen(Integer.valueOf(1).equals(node.getIsCurrent())
|
&& node.getApproveNodeUserId().equals(SecurityUtils.getUserId()));
|
}
|
nodes.sort(Comparator.comparingInt(ApproveNode::getApproveNodeOrder));
|
return nodes;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void updateApproveNode(ApproveNode request) throws IOException {
|
if (request == null || request.getId() == null) throw new RuntimeException("审批节点不能为空");
|
if (request.getApproveNodeStatus() == null || (request.getApproveNodeStatus() != 1 && request.getApproveNodeStatus() != 2)) {
|
throw new RuntimeException("审批结果不正确");
|
}
|
if (!StringUtils.hasText(request.getApproveNodeReason())) throw new RuntimeException("审批意见不能为空");
|
Long tenantId = tenantId();
|
ApproveNode node = approveNodeMapper.selectOne(new LambdaQueryWrapper<ApproveNode>()
|
.eq(ApproveNode::getId, request.getId())
|
.eq(ApproveNode::getTenantId, tenantId)
|
.eq(ApproveNode::getDeleteFlag, 0));
|
if (node == null) throw new RuntimeException("审批节点不存在");
|
if (!Integer.valueOf(0).equals(node.getApproveNodeStatus()) || !Integer.valueOf(1).equals(node.getIsCurrent())) {
|
throw new RuntimeException("该节点已经处理或不是当前审批节点");
|
}
|
if (!SecurityUtils.getUserId().equals(node.getApproveNodeUserId())) throw new RuntimeException("当前用户无权审批此节点");
|
|
ApproveProcess process = getApproveById(node.getApproveProcessId());
|
if (Integer.valueOf(2).equals(process.getApproveStatus()) || Integer.valueOf(3).equals(process.getApproveStatus())) {
|
throw new RuntimeException("审批流程已经结束");
|
}
|
node.setApproveNodeStatus(request.getApproveNodeStatus());
|
node.setApproveNodeReason(request.getApproveNodeReason().trim());
|
node.setApproveNodeRemark(request.getApproveNodeRemark());
|
node.setApproveNodeTime(new Date());
|
node.setIsCurrent(0);
|
node.setUpdateUser(SecurityUtils.getUserId());
|
node.setUpdateTime(LocalDateTime.now());
|
approveNodeMapper.updateById(node);
|
|
if (node.getApproveNodeStatus() == 2) {
|
process.setApproveStatus(3);
|
process.setApproveUserCurrentId(null);
|
process.setApproveUserCurrentName(null);
|
process.setApproveOverTime(new Date());
|
} else {
|
ApproveNode next = approveNodeMapper.selectOne(new LambdaQueryWrapper<ApproveNode>()
|
.eq(ApproveNode::getApproveProcessId, node.getApproveProcessId())
|
.eq(ApproveNode::getTenantId, tenantId)
|
.eq(ApproveNode::getDeleteFlag, 0)
|
.eq(ApproveNode::getApproveNodeStatus, 0)
|
.gt(ApproveNode::getApproveNodeOrder, node.getApproveNodeOrder())
|
.orderByAsc(ApproveNode::getApproveNodeOrder)
|
.last("limit 1"));
|
if (next == null) {
|
process.setApproveStatus(2);
|
process.setApproveOverTime(new Date());
|
process.setApproveUserCurrentId(null);
|
process.setApproveUserCurrentName(null);
|
} else {
|
next.setIsCurrent(1);
|
next.setUpdateTime(LocalDateTime.now());
|
approveNodeMapper.updateById(next);
|
process.setApproveStatus(1);
|
process.setApproveUserCurrentId(next.getApproveNodeUserId());
|
process.setApproveUserCurrentName(next.getApproveNodeUser());
|
}
|
}
|
process.setUpdateTime(LocalDateTime.now());
|
approveProcessMapper.updateById(process);
|
|
ApproveLog log = new ApproveLog();
|
log.setApproveId(process.getId());
|
log.setApproveProcessId(process.getId());
|
log.setApproveNodeId(node.getId());
|
log.setApproveNodeOrder(node.getApproveNodeOrder());
|
log.setApproveUser(SecurityUtils.getUserId());
|
log.setApproveUserName(node.getApproveNodeUser());
|
log.setApproveTime(new Date());
|
log.setApproveStatus(node.getApproveNodeStatus());
|
log.setApproveRemark(node.getApproveNodeReason());
|
log.setTenantId(tenantId);
|
approveLogMapper.insert(log);
|
|
if (!CollectionUtils.isEmpty(request.getTempFileIds()) && node.getApproveNodeStatus() == 1) {
|
tempFileService.migrateTempFilesToFormal(node.getId(), request.getTempFileIds(), FileNameType.ApproveNode.getValue());
|
}
|
}
|
|
@Override
|
public void delApproveNodeByApproveId(String id) {
|
UpdateWrapper<ApproveNode> wrapper = new UpdateWrapper<>();
|
wrapper.lambda().set(ApproveNode::getDeleteFlag, 1)
|
.set(ApproveNode::getIsCurrent, 0)
|
.eq(ApproveNode::getApproveProcessId, id)
|
.eq(ApproveNode::getTenantId, tenantId());
|
update(wrapper);
|
}
|
|
private Long tenantId() {
|
return SecurityUtils.getLoginUser().getTenantId();
|
}
|
}
|