package com.ruoyi.purchase.service.impl; 
 | 
  
 | 
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.core.toolkit.Wrappers; 
 | 
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 
 | 
import com.ruoyi.account.pojo.AccountExpense; 
 | 
import com.ruoyi.account.pojo.AccountIncome; 
 | 
import com.ruoyi.account.service.AccountExpenseService; 
 | 
import com.ruoyi.account.service.AccountIncomeService; 
 | 
import com.ruoyi.basic.mapper.ProductMapper; 
 | 
import com.ruoyi.basic.mapper.ProductModelMapper; 
 | 
import com.ruoyi.basic.mapper.SupplierManageMapper; 
 | 
import com.ruoyi.basic.pojo.Product; 
 | 
import com.ruoyi.basic.pojo.ProductModel; 
 | 
import com.ruoyi.basic.pojo.SupplierManage; 
 | 
import com.ruoyi.common.enums.FileNameType; 
 | 
import com.ruoyi.common.exception.base.BaseException; 
 | 
import com.ruoyi.common.utils.DateUtils; 
 | 
import com.ruoyi.common.utils.SecurityUtils; 
 | 
import com.ruoyi.common.utils.StringUtils; 
 | 
import com.ruoyi.framework.security.LoginUser; 
 | 
import com.ruoyi.other.mapper.TempFileMapper; 
 | 
import com.ruoyi.other.pojo.TempFile; 
 | 
import com.ruoyi.project.system.domain.SysUser; 
 | 
import com.ruoyi.project.system.mapper.SysUserMapper; 
 | 
import com.ruoyi.purchase.dto.PurchaseLedgerDto; 
 | 
import com.ruoyi.purchase.mapper.ProductRecordMapper; 
 | 
import com.ruoyi.purchase.mapper.PurchaseLedgerMapper; 
 | 
import com.ruoyi.purchase.mapper.TicketRegistrationMapper; 
 | 
import com.ruoyi.purchase.pojo.ProductRecord; 
 | 
import com.ruoyi.purchase.pojo.PurchaseLedger; 
 | 
import com.ruoyi.purchase.pojo.TicketRegistration; 
 | 
import com.ruoyi.purchase.service.IPurchaseLedgerService; 
 | 
import com.ruoyi.sales.mapper.*; 
 | 
import com.ruoyi.sales.pojo.CommonFile; 
 | 
import com.ruoyi.sales.pojo.InvoiceRegistrationProduct; 
 | 
import com.ruoyi.sales.pojo.SalesLedger; 
 | 
import com.ruoyi.sales.pojo.SalesLedgerProduct; 
 | 
import lombok.RequiredArgsConstructor; 
 | 
import lombok.extern.slf4j.Slf4j; 
 | 
import org.apache.commons.io.FilenameUtils; 
 | 
import org.springframework.beans.BeanUtils; 
 | 
import org.springframework.beans.factory.annotation.Value; 
 | 
import org.springframework.data.redis.core.StringRedisTemplate; 
 | 
import org.springframework.stereotype.Service; 
 | 
import org.springframework.transaction.annotation.Transactional; 
 | 
  
 | 
import java.io.IOException; 
 | 
import java.math.BigDecimal; 
 | 
import java.nio.file.Files; 
 | 
import java.nio.file.Path; 
 | 
import java.nio.file.Paths; 
 | 
import java.nio.file.StandardCopyOption; 
 | 
import java.time.LocalDate; 
 | 
import java.time.LocalDateTime; 
 | 
import java.time.ZoneId; 
 | 
import java.time.format.DateTimeFormatter; 
 | 
import java.util.*; 
 | 
import java.util.concurrent.TimeUnit; 
 | 
import java.util.stream.Collectors; 
 | 
  
 | 
/** 
 | 
 * 采购台账Service业务层处理 
 | 
 * 
 | 
 * @author ruoyi 
 | 
 * @date 2025-05-09 
 | 
 */ 
 | 
@Service 
 | 
@RequiredArgsConstructor 
 | 
@Slf4j 
 | 
public class PurchaseLedgerServiceImpl extends ServiceImpl<PurchaseLedgerMapper, PurchaseLedger> implements IPurchaseLedgerService { 
 | 
    private final AccountExpenseService accountExpenseService; 
 | 
    private final PurchaseLedgerMapper purchaseLedgerMapper; 
 | 
  
 | 
    private final SalesLedgerMapper salesLedgerMapper; 
 | 
    private final SalesLedgerProductMapper salesLedgerProductMapper; 
 | 
  
 | 
    private final SysUserMapper userMapper; 
 | 
  
 | 
    private final TempFileMapper tempFileMapper; 
 | 
  
 | 
    private final CommonFileMapper commonFileMapper; 
 | 
  
 | 
    private final SupplierManageMapper supplierManageMapper; 
 | 
  
 | 
    private final ProductMapper productMapper; 
 | 
  
 | 
    private final ProductModelMapper productModelMapper; 
 | 
  
 | 
    private final TicketRegistrationMapper ticketRegistrationMapper; 
 | 
  
 | 
    private final ProductRecordMapper productRecordMapper; 
 | 
  
 | 
    private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper; 
 | 
  
 | 
    private final StringRedisTemplate redisTemplate; 
 | 
  
 | 
    @Value("${file.upload-dir}") 
 | 
    private String uploadDir; 
 | 
  
 | 
    @Override 
 | 
    public List<PurchaseLedger> selectPurchaseLedgerList(PurchaseLedger purchaseLedger) { 
 | 
        LambdaQueryWrapper<PurchaseLedger> queryWrapper = new LambdaQueryWrapper<>(); 
 | 
        if (StringUtils.isNotBlank(purchaseLedger.getPurchaseContractNumber())) { 
 | 
            queryWrapper.like(PurchaseLedger::getPurchaseContractNumber, purchaseLedger.getPurchaseContractNumber()); 
 | 
        } 
 | 
        return purchaseLedgerMapper.selectList(queryWrapper); 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    @Transactional(rollbackFor = Exception.class) 
 | 
    public int addOrEditPurchase(PurchaseLedgerDto purchaseLedgerDto) throws IOException { 
 | 
  
 | 
        SalesLedger salesLedger = salesLedgerMapper.selectById(purchaseLedgerDto.getSalesLedgerId()); 
 | 
        //录入人 
 | 
        SysUser sysUser = userMapper.selectUserById(purchaseLedgerDto.getRecorderId()); 
 | 
  
 | 
        SupplierManage supplierManage = supplierManageMapper.selectById(purchaseLedgerDto.getSupplierId()); 
 | 
  
 | 
        // DTO转Entity 
 | 
        PurchaseLedger purchaseLedger = new PurchaseLedger(); 
 | 
        BeanUtils.copyProperties(purchaseLedgerDto, purchaseLedger); 
 | 
        LoginUser loginUser = SecurityUtils.getLoginUser(); 
 | 
        if(ObjectUtils.isNotEmpty(loginUser) && null != loginUser.getTenantId()) { 
 | 
            purchaseLedger.setTenantId(loginUser.getTenantId()); 
 | 
        } 
 | 
        purchaseLedger.setSalesContractNo(ObjectUtils.isNotEmpty(salesLedger) ? salesLedger.getSalesContractNo() : null); 
 | 
        purchaseLedger.setSupplierName(supplierManage.getSupplierName()); 
 | 
        purchaseLedger.setRecorderId(purchaseLedgerDto.getRecorderId()); 
 | 
        purchaseLedger.setRecorderName(sysUser.getNickName()); 
 | 
        purchaseLedger.setPhoneNumber(sysUser.getPhonenumber()); 
 | 
        // 2. 处理账户收入 
 | 
        AccountExpense accountExpense = new AccountExpense(); 
 | 
        accountExpense.setExpenseDate(purchaseLedger.getEntryDate()); 
 | 
        accountExpense.setExpenseType("0"); 
 | 
        accountExpense.setSupplierName(purchaseLedger.getSupplierName()); 
 | 
        accountExpense.setExpenseMoney(purchaseLedger.getContractAmount()); 
 | 
        accountExpense.setExpenseDescribed("采购合同:" + purchaseLedger.getPurchaseContractNumber()); 
 | 
        accountExpense.setExpenseMethod("0"); 
 | 
        accountExpense.setInvoiceNumber(purchaseLedger.getPurchaseContractNumber()); 
 | 
        accountExpense.setInputTime(new Date()); 
 | 
        accountExpense.setInputUser(loginUser.getNickName()); 
 | 
  
 | 
  
 | 
        // 3. 新增或更新主表 
 | 
        if (purchaseLedger.getId() == null) { 
 | 
            purchaseLedgerMapper.insert(purchaseLedger); 
 | 
//            accountIncomeService.save(accountIncome); 
 | 
            accountExpenseService.save(accountExpense); 
 | 
        } else { 
 | 
            purchaseLedgerMapper.updateById(purchaseLedger); 
 | 
            PurchaseLedger purchaseLedgerDB = purchaseLedgerMapper.selectById(purchaseLedger.getId()); 
 | 
            AccountExpense accountExpenseDB = accountExpenseService.getByInvoiceNumber(purchaseLedger.getPurchaseContractNumber()); 
 | 
            if (ObjectUtils.isEmpty(accountExpenseDB)) { 
 | 
                throw new BaseException("支出管理无该采购合同的支出记录"); 
 | 
            } 
 | 
            accountExpenseDB.setExpenseDate(purchaseLedgerDB.getEntryDate()); 
 | 
            accountExpenseDB.setExpenseType("0"); 
 | 
            accountExpenseDB.setSupplierName(purchaseLedgerDB.getSupplierName()); 
 | 
            accountExpenseDB.setExpenseMoney(purchaseLedgerDB.getContractAmount()); 
 | 
            accountExpenseDB.setExpenseDescribed("采购合同:" + purchaseLedgerDB.getPurchaseContractNumber()); 
 | 
            accountExpenseDB.setExpenseMethod("0"); 
 | 
            accountExpenseDB.setInvoiceNumber(purchaseLedgerDB.getPurchaseContractNumber()); 
 | 
            accountExpenseService.updateById(accountExpenseDB); 
 | 
        } 
 | 
  
 | 
        // 4. 处理子表数据 
 | 
        List<SalesLedgerProduct> productList = purchaseLedgerDto.getProductData(); 
 | 
        if (productList != null && !productList.isEmpty()) { 
 | 
            handleSalesLedgerProducts(purchaseLedger.getId(), productList, purchaseLedgerDto.getType()); 
 | 
        } 
 | 
  
 | 
        // 5. 迁移临时文件到正式目录 
 | 
        if (purchaseLedgerDto.getTempFileIds() != null && !purchaseLedgerDto.getTempFileIds().isEmpty()) { 
 | 
            migrateTempFilesToFormal(purchaseLedger.getId(), purchaseLedgerDto.getTempFileIds()); 
 | 
        } 
 | 
  
 | 
        return 1; 
 | 
    } 
 | 
  
 | 
    private void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, Integer type) { 
 | 
        if (products == null || products.isEmpty()) { 
 | 
            throw new BaseException("产品信息不存在"); 
 | 
        } 
 | 
  
 | 
        // 提前收集所有需要查询的ID 
 | 
        Set<Long> productIds = products.stream() 
 | 
                .map(SalesLedgerProduct::getProductId) 
 | 
                .filter(Objects::nonNull) 
 | 
                .collect(Collectors.toSet()); 
 | 
  
 | 
        Set<Long> modelIds = products.stream() 
 | 
                .map(SalesLedgerProduct::getProductModelId) 
 | 
                .filter(Objects::nonNull) 
 | 
                .collect(Collectors.toSet()); 
 | 
  
 | 
        // 一次性查询产品和型号信息 
 | 
        Map<Long, String> productMap = new HashMap<>(); 
 | 
        if (!productIds.isEmpty()) { 
 | 
            List<Product> productList = productMapper.selectBatchIds(productIds); 
 | 
            productList.forEach(p -> productMap.put(p.getId(), p.getProductName())); 
 | 
        } 
 | 
  
 | 
        Map<Long, String> modelMap = new HashMap<>(); 
 | 
        if (!modelIds.isEmpty()) { 
 | 
            List<ProductModel> modelList = productModelMapper.selectBatchIds(modelIds); 
 | 
            modelList.forEach(m -> modelMap.put(m.getId(), m.getModel())); 
 | 
        } 
 | 
  
 | 
        // 设置字段 
 | 
        for (SalesLedgerProduct product : products) { 
 | 
            product.setSalesLedgerId(salesLedgerId); 
 | 
  
 | 
            Long productId = product.getProductId(); 
 | 
            if (productId != null && productMap.containsKey(productId)) { 
 | 
                product.setProductCategory(productMap.get(productId)); 
 | 
            } 
 | 
  
 | 
            Long productModelId = product.getProductModelId(); 
 | 
            if (productModelId != null && modelMap.containsKey(productModelId)) { 
 | 
                product.setSpecificationModel(modelMap.get(productModelId)); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        // 分组处理 
 | 
        Map<Boolean, List<SalesLedgerProduct>> partitionedProducts = products.stream() 
 | 
                .collect(Collectors.partitioningBy(p -> p.getId() != null)); 
 | 
  
 | 
        List<SalesLedgerProduct> updateList = partitionedProducts.get(true); 
 | 
        List<SalesLedgerProduct> insertList = partitionedProducts.get(false); 
 | 
        PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(salesLedgerId); 
 | 
  
 | 
        // 执行更新操作 
 | 
        if (!updateList.isEmpty()) { 
 | 
            for (SalesLedgerProduct product : updateList) { 
 | 
                product.setType(type); 
 | 
                salesLedgerProductMapper.updateById(product); 
 | 
            } 
 | 
        } 
 | 
        // 执行插入操作 
 | 
        if (!insertList.isEmpty()) { 
 | 
            for (SalesLedgerProduct salesLedgerProduct : insertList) { 
 | 
                salesLedgerProduct.setType(type); 
 | 
                Date entryDate = purchaseLedger.getEntryDate(); 
 | 
  
 | 
                LocalDateTime localDateTime = entryDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); 
 | 
                salesLedgerProduct.setRegisterDate(localDateTime); 
 | 
                salesLedgerProductMapper.insert(salesLedgerProduct); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        // 计算总含税金额 
 | 
        BigDecimal totalTaxInclusiveAmount = products.stream() 
 | 
                .map(SalesLedgerProduct::getTaxInclusiveTotalPrice) 
 | 
                .filter(Objects::nonNull) 
 | 
                .reduce(BigDecimal.ZERO, BigDecimal::add); 
 | 
  
 | 
        // 更新主表的总金额字段 
 | 
        if (salesLedgerId != null) { 
 | 
            // 直接更新指定ID的记录的contractAmount字段为totalTaxInclusiveAmount 
 | 
            purchaseLedgerMapper.updateContractAmountById(salesLedgerId, totalTaxInclusiveAmount); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * 将临时文件迁移到正式目录 
 | 
     * 
 | 
     * @param businessId  业务ID(销售台账ID) 
 | 
     * @param tempFileIds 临时文件ID列表 
 | 
     * @throws IOException 文件操作异常 
 | 
     */ 
 | 
    private void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds) throws IOException { 
 | 
        if (CollectionUtils.isEmpty(tempFileIds)) { 
 | 
            return; 
 | 
        } 
 | 
  
 | 
        // 构建正式目录路径(按业务类型和日期分组) 
 | 
        String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE); 
 | 
  
 | 
        Path formalDirPath = Paths.get(formalDir); 
 | 
  
 | 
        // 确保正式目录存在(递归创建) 
 | 
        if (!Files.exists(formalDirPath)) { 
 | 
            Files.createDirectories(formalDirPath); 
 | 
        } 
 | 
  
 | 
        for (String tempFileId : tempFileIds) { 
 | 
            // 查询临时文件记录 
 | 
            TempFile tempFile = tempFileMapper.selectById(tempFileId); 
 | 
            if (tempFile == null) { 
 | 
                log.warn("临时文件不存在,跳过处理: {}", tempFileId); 
 | 
                continue; 
 | 
            } 
 | 
  
 | 
            // 构建正式文件名(包含业务ID和时间戳,避免冲突) 
 | 
            String originalFilename = tempFile.getOriginalName(); 
 | 
            String fileExtension = FilenameUtils.getExtension(originalFilename); 
 | 
            String formalFilename = businessId + "_" + 
 | 
                    System.currentTimeMillis() + "_" + 
 | 
                    UUID.randomUUID().toString().substring(0, 8) + 
 | 
                    (StringUtils.hasText(fileExtension) ? "." + fileExtension : ""); 
 | 
  
 | 
            Path formalFilePath = formalDirPath.resolve(formalFilename); 
 | 
  
 | 
            try { 
 | 
                // 执行文件迁移(使用原子操作确保安全性) 
 | 
//                Files.move( 
 | 
//                        Paths.get(tempFile.getTempPath()), 
 | 
//                        formalFilePath, 
 | 
//                        StandardCopyOption.REPLACE_EXISTING, 
 | 
//                        StandardCopyOption.ATOMIC_MOVE 
 | 
//                ); 
 | 
                // 原子移动失败,使用复制+删除 
 | 
                Files.copy(Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING); 
 | 
                Files.deleteIfExists(Paths.get(tempFile.getTempPath())); 
 | 
                log.info("文件迁移成功: {} -> {}", tempFile.getTempPath(), formalFilePath); 
 | 
  
 | 
                // 更新文件记录(关联到业务ID) 
 | 
                CommonFile fileRecord = new CommonFile(); 
 | 
                fileRecord.setCommonId(businessId); 
 | 
                fileRecord.setName(originalFilename); 
 | 
                fileRecord.setUrl(formalFilePath.toString()); 
 | 
                fileRecord.setCreateTime(LocalDateTime.now()); 
 | 
                fileRecord.setType(FileNameType.PURCHASE.getValue()); 
 | 
                commonFileMapper.insert(fileRecord); 
 | 
  
 | 
                // 删除临时文件记录 
 | 
                tempFileMapper.deleteById(tempFile); 
 | 
  
 | 
                log.info("文件迁移成功: {} -> {}", tempFile.getTempPath(), formalFilePath); 
 | 
            } catch (IOException e) { 
 | 
                log.error("文件迁移失败: {}", tempFile.getTempPath(), e); 
 | 
                // 可选择回滚事务或记录失败文件 
 | 
                throw new IOException("文件迁移异常", e); 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public int deletePurchaseLedgerByIds(Long[] ids) { 
 | 
        if (ids == null || ids.length == 0) { 
 | 
           throw new BaseException("请选中至少一条数据"); 
 | 
        } 
 | 
        // 批量删除关联的采购台账产品 
 | 
        LambdaQueryWrapper<SalesLedgerProduct> queryWrapper = new LambdaQueryWrapper<>(); 
 | 
        queryWrapper.in(SalesLedgerProduct::getSalesLedgerId, ids) 
 | 
                .eq(SalesLedgerProduct::getType, 2); 
 | 
        salesLedgerProductMapper.delete(queryWrapper); 
 | 
        // 批量删除关联的采购台账的来票登记 
 | 
        LambdaQueryWrapper<TicketRegistration> ticketRegistrationLambdaQueryWrapper = new LambdaQueryWrapper<>(); 
 | 
        ticketRegistrationLambdaQueryWrapper.in(TicketRegistration::getSalesLedgerId,ids); 
 | 
        ticketRegistrationMapper.delete(ticketRegistrationLambdaQueryWrapper); 
 | 
        // 批量删除关联的采购台账的来票登记记录 
 | 
        LambdaQueryWrapper<ProductRecord> productRecordLambdaQueryWrapper = new LambdaQueryWrapper<>(); 
 | 
        productRecordLambdaQueryWrapper.in(ProductRecord::getPurchaseLedgerId,ids); 
 | 
        productRecordMapper.delete(productRecordLambdaQueryWrapper); 
 | 
        // 批量删除采购台账 
 | 
        return purchaseLedgerMapper.deleteBatchIds(Arrays.asList(ids)); 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public PurchaseLedgerDto getPurchaseById(PurchaseLedgerDto purchaseLedgerDto) { 
 | 
        // 1. 查询主表 
 | 
        PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(purchaseLedgerDto.getId()); 
 | 
        if (purchaseLedger == null) { 
 | 
            throw new BaseException("采购台账不存在"); 
 | 
        } 
 | 
  
 | 
        // 2. 查询子表 
 | 
        LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>(); 
 | 
        productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId()) 
 | 
                .eq(SalesLedgerProduct::getType, purchaseLedgerDto.getType()); 
 | 
        List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(productWrapper); 
 | 
  
 | 
        // 3.查询上传文件 
 | 
        LambdaQueryWrapper<CommonFile> salesLedgerFileWrapper = new LambdaQueryWrapper<>(); 
 | 
        salesLedgerFileWrapper.eq(CommonFile::getCommonId, purchaseLedger.getId()); 
 | 
        List<CommonFile> salesLedgerFiles = commonFileMapper.selectList(salesLedgerFileWrapper); 
 | 
  
 | 
        // 4. 转换 DTO 
 | 
        PurchaseLedgerDto resultDto = new PurchaseLedgerDto(); 
 | 
        BeanUtils.copyProperties(purchaseLedger, resultDto); 
 | 
        if (!products.isEmpty()) { 
 | 
            resultDto.setHasChildren(true); 
 | 
            resultDto.setProductData(products); 
 | 
            resultDto.setSalesLedgerFiles(salesLedgerFiles); 
 | 
        } 
 | 
        return resultDto; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public List getProduct(PurchaseLedgerDto purchaseLedgerDto) { 
 | 
        LambdaQueryWrapper<PurchaseLedger> queryWrapper = Wrappers.lambdaQuery(); 
 | 
        queryWrapper.select(PurchaseLedger::getId, PurchaseLedger::getPurchaseContractNumber); 
 | 
  
 | 
        // 获取原始查询结果 
 | 
        List<Map<String, Object>> result = purchaseLedgerMapper.selectMaps(queryWrapper); 
 | 
  
 | 
        // 将下划线命名转换为驼峰命名 
 | 
        return result.stream().map(map -> map.entrySet().stream() 
 | 
                .collect(Collectors.toMap( 
 | 
                        entry -> underlineToCamel(entry.getKey()), 
 | 
                        Map.Entry::getValue)) 
 | 
        ).collect(Collectors.toList()); 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public PurchaseLedgerDto getInfo(PurchaseLedgerDto purchaseLedgerDto) { 
 | 
        PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(purchaseLedgerDto.getId()); 
 | 
        if (purchaseLedger == null) { 
 | 
            throw new BaseException("采购台账不存在"); 
 | 
        } 
 | 
        // 创建并填充DTO 
 | 
        PurchaseLedgerDto resultDto = new PurchaseLedgerDto(); 
 | 
        resultDto.setSalesLedgerId(purchaseLedger.getSalesLedgerId()); 
 | 
        resultDto.setSalesContractNoId(purchaseLedger.getSalesLedgerId()); 
 | 
        resultDto.setSalesContractNo(purchaseLedger.getSalesContractNo()); 
 | 
        resultDto.setSupplierName(purchaseLedger.getSupplierName()); 
 | 
        resultDto.setProjectName(purchaseLedger.getProjectName()); 
 | 
  
 | 
        // 查询并设置关联产品 
 | 
        LambdaQueryWrapper<SalesLedgerProduct> queryWrapper = new LambdaQueryWrapper<>(); 
 | 
        queryWrapper.eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId()) 
 | 
                .eq(SalesLedgerProduct::getType, 2); 
 | 
        List<SalesLedgerProduct> productList = salesLedgerProductMapper.selectList(queryWrapper); 
 | 
        productList.forEach(product -> { 
 | 
            product.setFutureTickets(product.getFutureTickets() != null ? product.getFutureTickets() : product.getQuantity()); 
 | 
            product.setFutureTicketsAmount(product.getFutureTicketsAmount() != null ? product.getFutureTicketsAmount() : product.getTaxInclusiveTotalPrice()); 
 | 
            product.setTicketsNum(null); 
 | 
            product.setTicketsAmount(null); 
 | 
            product.setTempFutureTickets(product.getFutureTickets()); 
 | 
            product.setTempFutureTicketsAmount(product.getFutureTicketsAmount()); 
 | 
        }); 
 | 
        resultDto.setProductData(productList); 
 | 
        return resultDto; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public List getPurchasesNo() { 
 | 
        LambdaQueryWrapper<PurchaseLedger> queryWrapper = Wrappers.lambdaQuery(); 
 | 
        queryWrapper.select(PurchaseLedger::getId, PurchaseLedger::getPurchaseContractNumber, PurchaseLedger::getSupplierId); 
 | 
  
 | 
        // 获取原始查询结果 
 | 
        List<Map<String, Object>> result = purchaseLedgerMapper.selectMaps(queryWrapper); 
 | 
  
 | 
        // 将下划线命名转换为驼峰命名 
 | 
        return result.stream().map(map -> map.entrySet().stream() 
 | 
                .collect(Collectors.toMap( 
 | 
                        entry -> underlineToCamel(entry.getKey()), 
 | 
                        Map.Entry::getValue)) 
 | 
        ).collect(Collectors.toList()); 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public PurchaseLedgerDto getPurchaseNoById(Long id) { 
 | 
        PurchaseLedgerDto purchaseLedgerDto = new PurchaseLedgerDto(); 
 | 
        PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(id); 
 | 
  
 | 
        BeanUtils.copyProperties(purchaseLedger, purchaseLedgerDto); 
 | 
//        TicketRegistration ticketRegistration = ticketRegistrationMapper.selectOne(new LambdaQueryWrapper<TicketRegistration>().eq(TicketRegistration::getPurchaseLedgerId, id)); 
 | 
//        if (ticketRegistration != null) { 
 | 
//            purchaseLedgerDto.setInvoiceNumber(ticketRegistration.getInvoiceNumber()); 
 | 
//            purchaseLedgerDto.setInvoiceAmount(ticketRegistration.getInvoiceAmount()); 
 | 
//            purchaseLedgerDto.setTicketRegistrationId(ticketRegistration.getId()); 
 | 
//        } 
 | 
        return purchaseLedgerDto; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public IPage<PurchaseLedgerDto> selectPurchaseLedgerListPage(IPage ipage, PurchaseLedgerDto purchaseLedger) { 
 | 
        IPage<PurchaseLedgerDto> purchaseLedgerDtoIPage = purchaseLedgerMapper.selectPurchaseLedgerListPage(ipage, purchaseLedger); 
 | 
        purchaseLedgerDtoIPage.getRecords().forEach(purchaseLedgerDto -> { 
 | 
            List<CommonFile> commonFiles = commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>().eq(CommonFile::getCommonId, purchaseLedgerDto.getId()).eq(CommonFile::getType, FileNameType.PURCHASELEDGER.getValue())); 
 | 
            purchaseLedgerDto.setSalesLedgerFiles(commonFiles); 
 | 
        }); 
 | 
        return purchaseLedgerDtoIPage; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public List<InvoiceRegistrationProduct> getProductBySalesNo(Long id) { 
 | 
        List<InvoiceRegistrationProduct> invoiceRegistrationProducts = invoiceRegistrationProductMapper.selectList(new LambdaQueryWrapper<InvoiceRegistrationProduct>() 
 | 
                        .select(InvoiceRegistrationProduct::getId, InvoiceRegistrationProduct::getProductCategory, InvoiceRegistrationProduct::getSpecificationModel, 
 | 
                                InvoiceRegistrationProduct::getUnit, InvoiceRegistrationProduct::getQuantity) 
 | 
                .eq(InvoiceRegistrationProduct::getSalesLedgerId, id)); 
 | 
        if (invoiceRegistrationProducts.isEmpty()) { 
 | 
            return new ArrayList<>(); 
 | 
        } 
 | 
        return invoiceRegistrationProducts; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public String getPurchaseNo() { 
 | 
        // 生成日期前缀(例如:CG20250405) 
 | 
        String purchaseNo = "CG" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); 
 | 
  
 | 
        // 构建 Redis Key(按天分隔) 
 | 
        String redisKey = "purchase_no:" + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE); 
 | 
  
 | 
        // 获取当前序号并递增(原子操作) 
 | 
        Long sequence = redisTemplate.opsForValue().increment(redisKey); 
 | 
  
 | 
        // 设置过期时间(次日失效,防止冗余数据) 
 | 
        if (sequence == 1) { 
 | 
            redisTemplate.expire(redisKey, 1, TimeUnit.DAYS); 
 | 
        } 
 | 
  
 | 
        // 返回完整编号(如 CG202504050001) 
 | 
        return purchaseNo + String.format("%03d", sequence); 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * 下划线命名转驼峰命名 
 | 
     */ 
 | 
    private String underlineToCamel(String param) { 
 | 
        if (param == null || "".equals(param.trim())) { 
 | 
            return ""; 
 | 
        } 
 | 
        int len = param.length(); 
 | 
        StringBuilder sb = new StringBuilder(len); 
 | 
        for (int i = 0; i < len; i++) { 
 | 
            char c = param.charAt(i); 
 | 
            if (c == '_') { 
 | 
                if (++i < len) { 
 | 
                    sb.append(Character.toUpperCase(param.charAt(i))); 
 | 
                } 
 | 
            } else { 
 | 
                sb.append(Character.toLowerCase(c)); 
 | 
            } 
 | 
        } 
 | 
        return sb.toString(); 
 | 
    } 
 | 
} 
 |