liding
5 天以前 dc5e5c07549b493e21c11dc7929c32ea9fd732b0
src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
@@ -1,19 +1,33 @@
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.service.IApproveProcessService;
import com.ruoyi.approve.vo.ApproveNodeVO;
import com.ruoyi.common.enums.FileNameType;
import com.ruoyi.common.utils.SecurityUtils;
import lombok.AllArgsConstructor;
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.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
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;
@@ -21,54 +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  IApproveProcessService approveProcessService;
    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 id) {
        //租户id
        Long tenantId = SecurityUtils.getLoginUser().getTenantId();
        ApproveProcess approve = approveProcessService.getApproveById(id);
        String[] names = approve.getApproveUserNames().split(",");
        Long approveId = approve.getId();
        for (int i = 0; i < names.length; i++) {
            ApproveNode approveNode = new ApproveNode();
            approveNode.setApproveProcessId(approveId);
            approveNode.setApproveNodeOrder(i +1);
            approveNode.setApproveNodeUser(names[i]);
            approveNode.setApproveNodeTime(new Date());
            approveNode.setApproveNodeStatus(0);
            approveNode.setTenantId(tenantId);
            approveNode.setDeleteFlag(0);
            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) {
        ApproveProcess approve = approveProcessService.getApproveById(id);
        Long approveId = approve.getId();
        LambdaQueryWrapper<ApproveNode> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApproveNode::getApproveProcessId, approveId);
        List<ApproveNode> list = list(queryWrapper);
        // 按照 approveNodeOrder 字段升序排序
        list.sort(Comparator.comparingInt(ApproveNode::getApproveNodeOrder));
        return list;
        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
    public void updateApproveNode(ApproveNode approveNode) {
         approveProcessService.updateApproveProcessStatus(approveNode);
    @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("当前用户无权审批此节点");
        approveNode.setApproveNodeTime(new Date());
        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);
        approveNodeMapper.updateById(approveNode);
        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();
    }
}