liding
5 天以前 dc5e5c07549b493e21c11dc7929c32ea9fd732b0
src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
@@ -3,11 +3,14 @@
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;
@@ -15,14 +18,16 @@
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.sales.mapper.CommonFileMapper;
import com.ruoyi.sales.pojo.CommonFile;
import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
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;
@@ -30,142 +35,215 @@
@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;
    @Autowired
    private  ApproveNodeMapper approveNodeMapper;
    @Autowired
    private ApproveProcessMapper approveProcessMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private TempFileServiceImpl tempFileService;
    @Autowired
    private CommonFileMapper fileMapper;
    public ApproveProcess getApproveById(String id) {
        LambdaQueryWrapper<ApproveProcess> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApproveProcess::getApproveId, id);
        queryWrapper.eq(ApproveProcess::getApproveDelete, 0);
        queryWrapper.eq(ApproveProcess::getTenantId, SecurityUtils.getLoginUser().getTenantId());
        queryWrapper.last("limit 1");
        ApproveProcess one = approveProcessMapper.selectOne(queryWrapper);
        return one;
    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) {
        Long userId = SecurityUtils.getLoginUser().getUser().getUserId();
        ApproveProcess approve = getApproveById(approveID);
        String[] names = approveUserIds.split(",");
        String approveId = approve.getApproveId();
        for (int i = 0; i < names.length; i++) {
            SysUser sysUser = sysUserMapper.selectUserById(Long.parseLong(names[i]));
            if (sysUser == null) continue;
            ApproveNode approveNode = new ApproveNode();
            approveNode.setApproveProcessId(approveId);
            approveNode.setApproveNodeOrder(i +1);
            approveNode.setApproveNodeUser(sysUser.getNickName());
            approveNode.setApproveNodeUserId(sysUser.getUserId());
            approveNode.setApproveNodeTime(new Date());
            approveNode.setApproveNodeStatus(0);
            approveNode.setTenantId(tenantId);
            approveNode.setDeleteFlag(0);
            approveNode.setCreateUser(userId);
            approveNode.setUpdateUser(userId);
            approveNode.setCreateTime(LocalDateTime.now());
            approveNode.setUpdateTime(LocalDateTime.now());
            approveNodeMapper.insert(approveNode);
    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) {
        LambdaQueryWrapper<ApproveNode> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApproveNode::getApproveProcessId, id);
        queryWrapper.eq(ApproveNode::getDeleteFlag, 0);
        queryWrapper.eq(ApproveNode::getTenantId, SecurityUtils.getLoginUser().getTenantId());
        List<ApproveNode> list = list(queryWrapper);
        // 按照 approveNodeOrder 字段升序排序
        list.sort(Comparator.comparingInt(ApproveNode::getApproveNodeOrder));
        LambdaQueryWrapper<ApproveProcess> approveProcessLambdaQueryWrapper = new LambdaQueryWrapper<>();
        approveProcessLambdaQueryWrapper.eq(ApproveProcess::getApproveId, id)
                .eq(ApproveProcess::getApproveDelete, 0)
                .eq(ApproveProcess::getTenantId, SecurityUtils.getLoginUser().getTenantId())
                .last("limit 1");
        ApproveProcess approveProcess = approveProcessMapper.selectOne(approveProcessLambdaQueryWrapper);
        if(approveProcess != null && approveProcess.getApproveStatus() == 3){
            return list;
        }
        for (ApproveNode approveNode : list) {
            List<CommonFile> commonFiles = fileMapper.selectList(new LambdaQueryWrapper<CommonFile>()
                    .eq(CommonFile::getCommonId, approveNode.getId())
                    .eq(CommonFile::getType, FileNameType.ApproveNode.getValue()));
            if(!CollectionUtils.isEmpty(commonFiles)){
                approveNode.setUrl(commonFiles.get(0).getUrl());
            }
            if(approveNode.getApproveNodeStatus() == 1){
                continue;
            }
            approveNode.setIsShen(true);
            break;
        }
        return list;
    }
    public void updateApproveProcessStatus(ApproveNode approveNode,Integer status) throws IOException {
        LambdaQueryWrapper<ApproveProcess> approveProcessLambdaQueryWrapper = new LambdaQueryWrapper<>();
        approveProcessLambdaQueryWrapper.eq(ApproveProcess::getApproveId, approveNode.getApproveProcessId())
                .eq(ApproveProcess::getApproveDelete, 0)
                .eq(ApproveProcess::getTenantId, SecurityUtils.getLoginUser().getTenantId())
                .last("limit 1");
        ApproveProcess approveProcess = approveProcessMapper.selectOne(approveProcessLambdaQueryWrapper);
        if(approveProcess == null) throw new RuntimeException("审批不存在");
        LambdaQueryWrapper<ApproveNode> approveNodeLambdaQueryWrapper = new LambdaQueryWrapper<>();
        approveNodeLambdaQueryWrapper.eq(ApproveNode::getApproveProcessId, approveNode.getApproveProcessId())
                .eq(ApproveNode::getApproveNodeOrder, approveNode.getApproveNodeOrder() + 1)
        getApproveById(id);
        List<ApproveNode> nodes = approveNodeMapper.selectList(new LambdaQueryWrapper<ApproveNode>()
                .eq(ApproveNode::getApproveProcessId, id)
                .eq(ApproveNode::getDeleteFlag, 0)
                .eq(ApproveNode::getTenantId, SecurityUtils.getLoginUser().getTenantId())
                .last("limit 1");
        ApproveNode approveNode1 = approveNodeMapper.selectOne(approveNodeLambdaQueryWrapper);
        approveProcess.setApproveStatus(status);
        if(approveNode1 != null){
            approveProcess.setApproveUserCurrentId(approveNode.getApproveNodeUserId());
            approveProcess.setApproveUserCurrentName(approveNode1.getApproveNodeUser());
                .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()));
        }
        approveProcessMapper.updateById(approveProcess);
        nodes.sort(Comparator.comparingInt(ApproveNode::getApproveNodeOrder));
        return nodes;
    }
        // 绑定附件
        if(!CollectionUtils.isEmpty(approveNode.getTempFileIds()) && approveNode.getApproveNodeStatus() == 1){
            tempFileService.migrateTempFilesToFormal(approveNode.getId(), approveNode.getTempFileIds(), FileNameType.ApproveNode.getValue());
    @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 updateApproveNode(ApproveNode approveNode) throws IOException {
        // 审批节点状态:1同意,2拒绝,0尚未审核
        switch (approveNode.getApproveNodeStatus()){
            case 1:
                updateApproveProcessStatus(approveNode, Boolean.TRUE.equals(approveNode.getIsLast()) ? 2 : 1);
                break;
            case 2:
                updateApproveProcessStatus(approveNode, 3);
                break;
            default:
                break;
        }
        approveNode.setApproveNodeTime(new Date());
        approveNodeMapper.updateById(approveNode);
    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);
    }
    @Override
    public void delApproveNodeByApproveId(Long id) {
        UpdateWrapper<ApproveNode> queryWrapper = new UpdateWrapper<>();
        queryWrapper.lambda().set(ApproveNode::getDeleteFlag, 1)
                .eq(ApproveNode::getApproveProcessId, id);
        update(queryWrapper);
    private Long tenantId() {
        return SecurityUtils.getLoginUser().getTenantId();
    }
}