7 天以前 11214e3074266a23fe61e8eebbce647fdb7305ef
src/main/java/com/ruoyi/sales/service/impl/SalesQuotationServiceImpl.java
@@ -4,71 +4,160 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.approve.bean.dto.ApprovalInstanceDto;
import com.ruoyi.approve.bean.vo.ApproveGetAndUpdateVo;
import com.ruoyi.approve.mapper.ApprovalTemplateMapper;
import com.ruoyi.approve.pojo.ApprovalInstance;
import com.ruoyi.approve.pojo.ApprovalTemplate;
import com.ruoyi.approve.pojo.ApproveProcess;
import com.ruoyi.approve.service.ApprovalInstanceService;
import com.ruoyi.approve.service.impl.ApproveProcessServiceImpl;
import com.ruoyi.basic.mapper.CustomerMapper;
import com.ruoyi.basic.pojo.Customer;
import com.ruoyi.common.enums.IsDeleteEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.OrderUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.sales.dto.SalesQuotationDto;
import com.ruoyi.sales.dto.SalesQuotationImportDto;
import com.ruoyi.sales.dto.SalesQuotationMainImportDto;
import com.ruoyi.sales.dto.SalesQuotationProductImportDto;
import com.ruoyi.sales.mapper.SalesQuotationImportLogMapper;
import com.ruoyi.sales.mapper.SalesQuotationMapper;
import com.ruoyi.sales.mapper.SalesQuotationPriceHistoryMapper;
import com.ruoyi.sales.mapper.SalesQuotationProductMapper;
import com.ruoyi.sales.pojo.SalesQuotation;
import com.ruoyi.sales.pojo.SalesQuotationProduct;
import com.ruoyi.sales.pojo.*;
import com.ruoyi.sales.service.SalesQuotationProductService;
import com.ruoyi.sales.service.SalesQuotationService;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
@RequiredArgsConstructor
public class SalesQuotationServiceImpl extends ServiceImpl<SalesQuotationMapper, SalesQuotation> implements SalesQuotationService {
    @Autowired
    private SalesQuotationMapper salesQuotationMapper;
    @Autowired
    private SalesQuotationProductMapper salesQuotationProductMapper;
    @Autowired
    private SalesQuotationProductService salesQuotationProductService;
    private final SalesQuotationProductMapper salesQuotationProductMapper;
    private final SalesQuotationMapper salesQuotationMapper;
    private final SalesQuotationProductService salesQuotationProductService;
    private final SalesQuotationPriceHistoryMapper priceHistoryMapper;
    private final SalesQuotationImportLogMapper importLogMapper;
    private final ApproveProcessServiceImpl approveProcessService;
    private final CustomerMapper customerMapper;
    private final ApprovalTemplateMapper approvalTemplateMapper;
    private final ApprovalInstanceService approvalInstanceService;
    @Override
    public IPage<SalesQuotationDto> listPage(Page page, SalesQuotationDto salesQuotationDto) {
        IPage<SalesQuotationDto> salesQuotationDtoIPage = salesQuotationMapper.listPage(page, salesQuotationDto);
        if(CollectionUtils.isEmpty(salesQuotationDtoIPage.getRecords())){
            return salesQuotationDtoIPage;
        }
        salesQuotationDtoIPage.getRecords().forEach(record -> {
            List<SalesQuotationProduct> products = salesQuotationProductMapper.selectBySalesQuotationId(record.getId());
            record.setProducts(products);
        });
        // 批量查询产品,避免 N+1 问题
        List<Long> quotationIds = salesQuotationDtoIPage.getRecords().stream()
                .map(SalesQuotationDto::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        if (!quotationIds.isEmpty()) {
            List<SalesQuotationProduct> allProducts = salesQuotationProductMapper.selectList(
                    new LambdaQueryWrapper<SalesQuotationProduct>()
                            .in(SalesQuotationProduct::getSalesQuotationId, quotationIds)
            );
            Map<Long, List<SalesQuotationProduct>> productMap = allProducts.stream()
                    .collect(Collectors.groupingBy(SalesQuotationProduct::getSalesQuotationId));
            salesQuotationDtoIPage.getRecords().forEach(record ->
                    record.setProducts(productMap.getOrDefault(record.getId(), new ArrayList<>()))
            );
        }
        return salesQuotationDtoIPage;
    }
    @Override
    public boolean add(SalesQuotationDto salesQuotationDto) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SalesQuotation salesQuotation = new SalesQuotation();
        BeanUtils.copyProperties(salesQuotationDto, salesQuotation);
        String quotationNo = salesQuotation.getQuotationNo();
        salesQuotation.setId(null);
        Customer customer = customerMapper.selectById(salesQuotationDto.getCustomerId());
        if (ObjectUtils.isNotEmpty(customer))  {
            salesQuotation.setCustomer(customer.getCustomerName());
        }
        String quotationNo = OrderUtils.countTodayByCreateTime(salesQuotationMapper, "QT","quotation_no", salesQuotationDto.getCreateTime() != null ? salesQuotationDto.getCreateTime() : LocalDateTime.now());
        salesQuotation.setQuotationNo(quotationNo);
        salesQuotation.setStatus("待审批");
        salesQuotationMapper.insert(salesQuotation);
//        if(salesQuotationMapper.insert(salesQuotation)!=1){
//            return false;
//        }
        if(CollectionUtils.isEmpty(salesQuotationDto.getProducts())){
            return true;
        }
        List<SalesQuotationProduct> products = salesQuotationDto.getProducts().stream().map(product -> {
            SalesQuotationProduct salesQuotationProduct = new SalesQuotationProduct();
            BeanUtils.copyProperties(product, salesQuotationProduct);
            salesQuotationProduct.setSalesQuotationId(salesQuotationMapper.selectOne(new LambdaQueryWrapper<SalesQuotation>().eq(SalesQuotation::getQuotationNo, quotationNo)).getId());
            salesQuotationProduct.setSalesQuotationId(salesQuotation.getId());
            return salesQuotationProduct;
        }).collect(Collectors.toList());
        salesQuotationProductService.saveBatch(products);
        // 报价审批
        ApprovalTemplate approvalTemplate = approvalTemplateMapper.selectOne(
                new LambdaQueryWrapper<ApprovalTemplate>()
                        .eq(ApprovalTemplate::getBusinessType, 6L)
                        .eq(ApprovalTemplate::getDeleted, 0)
                        .orderByDesc(ApprovalTemplate::getId)
                        .last("LIMIT 1")
        );
        if (approvalTemplate == null) {
            throw new RuntimeException("请先配置报价审批模板");
        }
        ApprovalInstanceDto approvalInstance = new ApprovalInstanceDto();
        approvalInstance.setTemplateId(approvalTemplate.getId());
        approvalInstance.setTemplateName(approvalTemplate.getTemplateName());
        approvalInstance.setBusinessId(salesQuotation.getId());
        approvalInstance.setBusinessType(6L);
        approvalInstance.setCurrentLevel(1);
        approvalInstance.setTitle(quotationNo+"审批");
        approvalInstance.setApplicantId(loginUser.getUserId());
        approvalInstance.setApplicantName(loginUser.getNickName());
        approvalInstance.setApplyTime(LocalDateTime.now());
        try {
            approvalInstanceService.add(approvalInstance);
        } catch (Exception e) {
            log.error("SalesQuotationServiceImpl approve error for quotationNo: {}", e);
            throw new RuntimeException("审批失败: " + e.getMessage(), e);
        }
        return true;
    }
    @Override
    public boolean edit(SalesQuotationDto salesQuotationDto) {
        SalesQuotation salesQuotation = new SalesQuotation();
        BeanUtils.copyProperties(salesQuotationDto, salesQuotation);
        ApproveGetAndUpdateVo vo = new ApproveGetAndUpdateVo();
        if("拒绝".equals(salesQuotationDto.getStatus())){
            vo.setApproveStatus(0);
            salesQuotation.setStatus("待审批");
        }
        if(salesQuotationMapper.updateById(salesQuotation)!=1){
            return false;
        }
@@ -82,15 +171,361 @@
            salesQuotationProduct.setSalesQuotationId(salesQuotation.getId());
            return salesQuotationProduct;
        }).collect(Collectors.toList());
        salesQuotationProductService.saveBatch(products);
        // 修改报价审批
        // 先结束之前未结束的报价审批
        approvalInstanceService.lambdaUpdate().set(ApprovalInstance::getStatus,"REJECTED").eq(ApprovalInstance::getBusinessId,salesQuotation.getId()).eq(ApprovalInstance::getBusinessType,6L).update();
        ApprovalTemplate approvalTemplate = approvalTemplateMapper.selectOne(
                new LambdaQueryWrapper<ApprovalTemplate>()
                        .eq(ApprovalTemplate::getBusinessType, 6L)
                        .eq(ApprovalTemplate::getDeleted, 0)
                        .orderByDesc(ApprovalTemplate::getId)
                        .last("LIMIT 1")
        );
        if (approvalTemplate == null) {
            throw new RuntimeException("请先配置报价审批模板");
        }
        ApprovalInstanceDto approvalInstance = new ApprovalInstanceDto();
        approvalInstance.setTemplateId(approvalTemplate.getId());
        approvalInstance.setTemplateName(approvalTemplate.getTemplateName());
        approvalInstance.setBusinessId(salesQuotation.getId());
        approvalInstance.setBusinessType(6L);
        approvalInstance.setCurrentLevel(1);
        approvalInstance.setTitle(salesQuotation.getQuotationNo()+"审批");
        approvalInstance.setApplicantId(SecurityUtils.getUserId());
        approvalInstance.setApplicantName(SecurityUtils.getLoginUser().getNickName());
        approvalInstance.setApplyTime(LocalDateTime.now());
        try {
            approvalInstanceService.add(approvalInstance);
        } catch (Exception e) {
            log.error("SalesQuotationServiceImpl approve error for quotationNo: {}", e);
            throw new RuntimeException("审批失败: " + e.getMessage(), e);
        }
        return true;
    }
    @Override
    public boolean delete(Long id) {
        SalesQuotation salesQuotation = salesQuotationMapper.selectById(id);
        if(salesQuotation==null) return false;
        salesQuotationMapper.deleteById(id);
        salesQuotationProductMapper.delete(new LambdaQueryWrapper<SalesQuotationProduct>().eq(SalesQuotationProduct::getSalesQuotationId, id));
        // 删除报价审批
        ApproveProcess one = approveProcessService.getOne(new LambdaQueryWrapper<ApproveProcess>()
                .eq(ApproveProcess::getApproveType, 6)
                .eq(ApproveProcess::getApproveDelete, IsDeleteEnum.NOT_DELETED)
                .eq(ApproveProcess::getApproveReason, salesQuotation.getQuotationNo()));
        if(one != null){
            approveProcessService.delByIds(Collections.singletonList(one.getId()));
        }
        return true;
    }
    @Override
    public void downloadTemplate(HttpServletResponse response) {
        // 报价单数据示例
        List<SalesQuotationMainImportDto> mainList = new ArrayList<>();
        SalesQuotationMainImportDto mainExample = new SalesQuotationMainImportDto();
        mainExample.setQuotationNo("QT202606120001");
        mainExample.setCustomerName("示例客户");
        mainExample.setSalesperson("张三");
        mainExample.setPaymentMethod("月结30天");
        mainExample.setDeliveryPeriod("7天");
        mainExample.setRemark("示例报价单");
        mainList.add(mainExample);
        // 报价产品数据示例
        List<SalesQuotationProductImportDto> productList = new ArrayList<>();
        SalesQuotationProductImportDto productExample1 = new SalesQuotationProductImportDto();
        productExample1.setQuotationNo("QT202606120001");
        productExample1.setProductCategory("电池组件");
        productExample1.setSpecificationModel("MODEL-A-100W");
        productExample1.setUnit("片");
        productExample1.setUnitPrice(new BigDecimal("150.00"));
        productList.add(productExample1);
        SalesQuotationProductImportDto productExample2 = new SalesQuotationProductImportDto();
        productExample2.setQuotationNo("QT202606120001");
        productExample2.setProductCategory("电池组件");
        productExample2.setSpecificationModel("MODEL-B-200W");
        productExample2.setUnit("片");
        productExample2.setUnitPrice(new BigDecimal("200.00"));
        productList.add(productExample2);
        // 使用静态方法导出多Sheet模板
        Map<String, ExcelUtil.SheetData<?>> sheetDataMap = new LinkedHashMap<>();
        sheetDataMap.put("报价单数据", new ExcelUtil.SheetData<>(mainList, SalesQuotationMainImportDto.class));
        sheetDataMap.put("报价产品数据", new ExcelUtil.SheetData<>(productList, SalesQuotationProductImportDto.class));
        ExcelUtil.exportExcelMultiSheet(response, sheetDataMap, "销售报价导入模板");
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SalesQuotationImportLog importQuotation(MultipartFile file) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        // 检查审批模板是否存在
        ApprovalTemplate approvalTemplate = approvalTemplateMapper.selectOne(
                new LambdaQueryWrapper<ApprovalTemplate>()
                        .eq(ApprovalTemplate::getBusinessType, 6L)
                        .eq(ApprovalTemplate::getDeleted, 0)
                        .orderByDesc(ApprovalTemplate::getId)
                        .last("LIMIT 1")
        );
        if (approvalTemplate == null) {
            throw new ServiceException("请先配置报价审批模板,无法导入");
        }
        // 解析多Sheet Excel文件
        ExcelUtil<SalesQuotationMainImportDto> mainUtil = new ExcelUtil<>(SalesQuotationMainImportDto.class);
        Map<String, List<SalesQuotationMainImportDto>> sheetMap;
        try {
            sheetMap = mainUtil.importExcelMultiSheet(Arrays.asList("报价单数据", "报价产品数据"), file.getInputStream(), 0);
        } catch (IOException e) {
            throw new ServiceException("读取文件失败: " + e.getMessage());
        }
        List<SalesQuotationMainImportDto> mainList = sheetMap.get("报价单数据");
        List<SalesQuotationMainImportDto> productListRaw = sheetMap.get("报价产品数据");
        if (CollectionUtils.isEmpty(mainList)) {
            throw new ServiceException("报价单数据为空,请检查模板内容");
        }
        // 将产品数据转为正确的DTO类型
        ExcelUtil<SalesQuotationProductImportDto> productUtil = new ExcelUtil<>(SalesQuotationProductImportDto.class);
        Map<String, List<SalesQuotationProductImportDto>> productSheetMap;
        try {
            productSheetMap = productUtil.importExcelMultiSheet(Arrays.asList("报价产品数据"), file.getInputStream(), 0);
        } catch (IOException e) {
            throw new ServiceException("读取产品数据失败: " + e.getMessage());
        }
        List<SalesQuotationProductImportDto> productList = productSheetMap.get("报价产品数据");
        // 生成批次号
        String batchNo = "QT_IMP_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        // 创建导入记录
        SalesQuotationImportLog importLog = new SalesQuotationImportLog();
        importLog.setBatchNo(batchNo);
        importLog.setFileName(file.getOriginalFilename());
        importLog.setTotalCount(mainList.size());
        importLog.setSuccessCount(0);
        importLog.setUpdateCount(0);
        importLog.setNewCount(0);
        importLog.setFailCount(0);
        importLog.setStatus("completed");
        importLog.setCreateUser(loginUser.getUserId());
        importLog.setCreateUserName(loginUser.getNickName());
        importLogMapper.insert(importLog);
        // 查询相关数据
        List<Customer> customers = customerMapper.selectList(
                new LambdaQueryWrapper<Customer>()
                        .in(Customer::getCustomerName, mainList.stream()
                                .map(SalesQuotationMainImportDto::getCustomerName)
                                .filter(Objects::nonNull)
                                .collect(Collectors.toList()))
        );
        Map<String, Customer> customerMap = customers.stream()
                .collect(Collectors.toMap(Customer::getCustomerName, c -> c, (a, b) -> a));
        // 按报价单号分组产品
        Map<String, List<SalesQuotationProductImportDto>> productGroupMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(productList)) {
            productGroupMap = productList.stream()
                    .filter(p -> p.getQuotationNo() != null && !p.getQuotationNo().isEmpty())
                    .collect(Collectors.groupingBy(SalesQuotationProductImportDto::getQuotationNo));
        }
        int successCount = 0;
        int newCount = 0;
        int updateCount = 0;
        int failCount = 0;
        for (SalesQuotationMainImportDto mainDto : mainList) {
            try {
                String customerName = mainDto.getCustomerName();
                if (customerName == null || customerName.isEmpty()) {
                    failCount++;
                    continue;
                }
                // 查找客户
                Customer customer = customerMap.get(customerName);
                // 创建报价单
                SalesQuotation quotation = new SalesQuotation();
                quotation.setCustomer(customerName);
                quotation.setCustomerId(customer != null ? customer.getId() : null);
                // 生成报价单号
                String quotationNo;
                if (mainDto.getQuotationNo() != null && !mainDto.getQuotationNo().isEmpty()) {
                    quotationNo = mainDto.getQuotationNo();
                } else {
                    quotationNo = OrderUtils.countTodayByCreateTime(salesQuotationMapper, "QT", "quotation_no", LocalDateTime.now());
                }
                quotation.setQuotationNo(quotationNo);
                // 检查报价单号是否已存在
                SalesQuotation existing = salesQuotationMapper.selectOne(
                        new LambdaQueryWrapper<SalesQuotation>()
                                .eq(SalesQuotation::getQuotationNo, quotationNo)
                                .last("LIMIT 1")
                );
                boolean isUpdate = existing != null;
                if (isUpdate) {
                    quotation.setId(existing.getId());
                    quotation.setQuotationDate(existing.getQuotationDate());
                    quotation.setStatus(existing.getStatus());
                } else {
                    quotation.setQuotationDate(LocalDate.now());
                    quotation.setStatus("待审批");
                }
                quotation.setSalesperson(mainDto.getSalesperson());
                quotation.setPaymentMethod(mainDto.getPaymentMethod());
                quotation.setDeliveryPeriod(mainDto.getDeliveryPeriod());
                quotation.setRemark("导入批次号: " + batchNo + (mainDto.getRemark() != null ? "," + mainDto.getRemark() : ""));
                // 计算总金额并保存产品
                BigDecimal totalAmount = BigDecimal.ZERO;
                List<SalesQuotationProduct> quotationProducts = new ArrayList<>();
                List<SalesQuotationProductImportDto> products = productGroupMap.get(quotationNo);
                if (!CollectionUtils.isEmpty(products)) {
                    for (SalesQuotationProductImportDto productDto : products) {
                        SalesQuotationProduct product = new SalesQuotationProduct();
                        product.setProduct(productDto.getProductCategory());
                        product.setSpecification(productDto.getSpecificationModel());
                        product.setUnit(productDto.getUnit());
                        product.setQuantity(0);
                        product.setUnitPrice(productDto.getUnitPrice() != null ? productDto.getUnitPrice().doubleValue() : 0.0);
                        BigDecimal amount = productDto.getUnitPrice() != null
                                ? productDto.getUnitPrice()
                                : BigDecimal.ZERO;
                        product.setAmount(amount.doubleValue());
                        totalAmount = totalAmount.add(amount);
                        quotationProducts.add(product);
                    }
                }
                quotation.setTotalAmount(totalAmount);
                if (isUpdate) {
                    salesQuotationMapper.updateById(quotation);
                    // 删除旧产品数据
                    salesQuotationProductMapper.delete(new LambdaQueryWrapper<SalesQuotationProduct>()
                            .eq(SalesQuotationProduct::getSalesQuotationId, existing.getId()));
                } else {
                    salesQuotationMapper.insert(quotation);
                }
                // 保存产品并记录降价历史
                for (SalesQuotationProduct product : quotationProducts) {
                    product.setSalesQuotationId(quotation.getId());
                    salesQuotationProductMapper.insert(product);
                    recordPriceHistory(quotation.getId(), product, batchNo);
                }
                if (!isUpdate) {
                    // 创建审批实例
                    ApprovalInstanceDto approvalInstance = new ApprovalInstanceDto();
                    approvalInstance.setTemplateId(approvalTemplate.getId());
                    approvalInstance.setTemplateName(approvalTemplate.getTemplateName());
                    approvalInstance.setBusinessId(quotation.getId());
                    approvalInstance.setBusinessType(6L);
                    approvalInstance.setCurrentLevel(1);
                    approvalInstance.setTitle(quotationNo + "审批");
                    approvalInstance.setApplicantId(loginUser.getUserId());
                    approvalInstance.setApplicantName(loginUser.getNickName());
                    approvalInstance.setApplyTime(LocalDateTime.now());
                    approvalInstanceService.add(approvalInstance);
                }
                successCount++;
                if (isUpdate) {
                    updateCount++;
                } else {
                    newCount++;
                }
            } catch (Exception e) {
                log.error("导入报价单失败: {}", e.getMessage());
                failCount++;
            }
        }
        // 更新导入记录
        importLog.setSuccessCount(successCount);
        importLog.setNewCount(newCount);
        importLog.setUpdateCount(updateCount);
        importLog.setFailCount(failCount);
        importLogMapper.updateById(importLog);
        return importLog;
    }
    /**
     * 记录降价历史
     */
    private void recordPriceHistory(Long quotationId, SalesQuotationProduct product, String batchNo) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        // 查找相同项目名称的历史报价产品
        List<SalesQuotationProduct> historyProducts = salesQuotationProductMapper.selectList(
                new LambdaQueryWrapper<SalesQuotationProduct>()
                        .eq(SalesQuotationProduct::getProduct, product.getProduct())
                        .ne(SalesQuotationProduct::getId, product.getId())
                        .orderByDesc(SalesQuotationProduct::getCreateTime)
                        .last("LIMIT 1")
        );
        if (!historyProducts.isEmpty()) {
            SalesQuotationProduct historyProduct = historyProducts.get(0);
            BigDecimal oldPrice = historyProduct.getUnitPrice() != null
                    ? new BigDecimal(historyProduct.getUnitPrice().toString())
                    : BigDecimal.ZERO;
            BigDecimal newPrice = product.getUnitPrice() != null
                    ? new BigDecimal(product.getUnitPrice().toString())
                    : BigDecimal.ZERO;
            // 如果价格有变化,记录降价历史
            if (oldPrice.compareTo(newPrice) != 0) {
                SalesQuotationPriceHistory priceHistory = new SalesQuotationPriceHistory();
                priceHistory.setQuotationId(quotationId);
                priceHistory.setQuotationProductId(product.getId());
                priceHistory.setProductName(product.getProduct());
                priceHistory.setSpecification(product.getSpecification());
                priceHistory.setOldPrice(oldPrice);
                priceHistory.setNewPrice(newPrice);
                priceHistory.setPriceChange(newPrice.subtract(oldPrice));
                priceHistory.setImportBatch(batchNo);
                priceHistory.setImportTime(LocalDateTime.now());
                priceHistory.setCreateUser(loginUser.getUserId());
                priceHistory.setCreateUserName(loginUser.getNickName());
                priceHistory.setChangeReason(newPrice.compareTo(oldPrice) < 0 ? "降价" : "涨价");
                priceHistoryMapper.insert(priceHistory);
            }
        }
    }
    @Override
    public IPage<SalesQuotationImportLog> listImportLog(Page page) {
        return importLogMapper.selectPage(page,
                new LambdaQueryWrapper<SalesQuotationImportLog>()
                        .orderByDesc(SalesQuotationImportLog::getCreateTime));
    }
    @Override
    public List<SalesQuotationPriceHistory> listPriceHistory(Long quotationId) {
        return priceHistoryMapper.selectList(
                new LambdaQueryWrapper<SalesQuotationPriceHistory>()
                        .eq(SalesQuotationPriceHistory::getQuotationId, quotationId)
                        .orderByDesc(SalesQuotationPriceHistory::getImportTime));
    }
}