src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -9,13 +9,13 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.account.service.AccountIncomeService;
import com.ruoyi.aftersalesservice.pojo.AfterSalesService;
import com.ruoyi.basic.mapper.CustomerMapper;
import com.ruoyi.basic.mapper.ProductMapper;
import com.ruoyi.basic.mapper.ProductModelMapper;
import com.ruoyi.basic.pojo.Customer;
import com.ruoyi.common.enums.FileNameType;
import com.ruoyi.common.enums.SaleEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.EnumUtil;
@@ -27,23 +27,22 @@
import com.ruoyi.other.mapper.TempFileMapper;
import com.ruoyi.other.pojo.TempFile;
import com.ruoyi.production.mapper.*;
import com.ruoyi.production.pojo.*;
import com.ruoyi.production.service.ProductionProductMainService;
import com.ruoyi.production.service.impl.ProductionProductMainServiceImpl;
import com.ruoyi.project.system.domain.SysDept;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysDeptMapper;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.purchase.dto.SimpleReturnOrderGroupDto;
import com.ruoyi.purchase.mapper.PurchaseReturnOrderProductsMapper;
import com.ruoyi.quality.mapper.QualityInspectMapper;
import com.ruoyi.quality.pojo.QualityInspect;
import com.ruoyi.sales.dto.*;
import com.ruoyi.sales.mapper.*;
import com.ruoyi.sales.pojo.*;
import com.ruoyi.sales.service.ISalesLedgerProductService;
import com.ruoyi.sales.service.ISalesLedgerService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@@ -53,8 +52,8 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
@@ -81,69 +80,41 @@
@RequiredArgsConstructor
@Slf4j
public class SalesLedgerServiceImpl extends ServiceImpl<SalesLedgerMapper, SalesLedger> implements ISalesLedgerService {
    private final AccountIncomeService accountIncomeService;
    private final SalesLedgerMapper salesLedgerMapper;
    private final CustomerMapper customerMapper;
    private final SalesLedgerProductMapper salesLedgerProductMapper;
    private final SalesLedgerProductServiceImpl salesLedgerProductServiceImpl;
    private final CommonFileMapper commonFileMapper;
    private final TempFileMapper tempFileMapper;
    private final ReceiptPaymentMapper receiptPaymentMapper;
    private final ShippingInfoServiceImpl shippingInfoServiceImpl;
    private final CommonFileServiceImpl commonFileService;
    private final ShippingInfoMapper shippingInfoMapper;
    private final InvoiceLedgerMapper invoiceLedgerMapper;
    private final SalesLedgerSchedulingMapper salesLedgerSchedulingMapper;
    private final SalesLedgerWorkMapper salesLedgerWorkMapper;
    private final SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper;
    private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
    private final InvoiceRegistrationMapper invoiceRegistrationMapper;
    private final ProductOrderMapper productOrderMapper;
    private final ProcessRouteMapper processRouteMapper;
    private final ProductProcessRouteMapper productProcessRouteMapper;
    private final ProcessRouteItemMapper processRouteItemMapper;
    private final ProductProcessRouteItemMapper productProcessRouteItemMapper;
    private final ProductWorkOrderMapper productWorkOrderMapper;
    private final ProductionProductMainMapper productionProductMainMapper;
    private final ProductionProductOutputMapper productionProductOutputMapper;
    private final ProductionProductInputMapper productionProductInputMapper;
    private final QualityInspectMapper qualityInspectMapper;
    @Autowired
    private SysDeptMapper sysDeptMapper;
    @Value("${file.upload-dir}")
    private String uploadDir;
    private static final String LOCK_PREFIX = "contract_no_lock:";
    private static final long LOCK_WAIT_TIMEOUT = 10; // 锁等待超时时间(秒)
    private static final long LOCK_EXPIRE_TIME = 30;  // 锁自动过期时间(秒)
    private final AccountIncomeService accountIncomeService;
    private final SalesLedgerMapper salesLedgerMapper;
    private final CustomerMapper customerMapper;
    private final SalesLedgerProductMapper salesLedgerProductMapper;
    private final SalesLedgerProductServiceImpl salesLedgerProductServiceImpl;
    private final CommonFileMapper commonFileMapper;
    private final TempFileMapper tempFileMapper;
    private final ReceiptPaymentMapper receiptPaymentMapper;
    private final ShippingInfoServiceImpl shippingInfoServiceImpl;
    private final CommonFileServiceImpl commonFileService;
    private final ShippingInfoMapper shippingInfoMapper;
    private final InvoiceLedgerMapper invoiceLedgerMapper;
    private final SalesLedgerSchedulingMapper salesLedgerSchedulingMapper;
    private final SalesLedgerWorkMapper salesLedgerWorkMapper;
    private final SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper;
    private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
    private final InvoiceRegistrationMapper invoiceRegistrationMapper;
    private final ProductOrderMapper productOrderMapper;
    private final ProcessRouteMapper processRouteMapper;
    private final ProductProcessRouteMapper productProcessRouteMapper;
    private final ProcessRouteItemMapper processRouteItemMapper;
    private final ProductProcessRouteItemMapper productProcessRouteItemMapper;
    private final ProductWorkOrderMapper productWorkOrderMapper;
    private final ProductionProductMainMapper productionProductMainMapper;
    private final ProductionProductOutputMapper productionProductOutputMapper;
    private final ProductionProductInputMapper productionProductInputMapper;
    private final QualityInspectMapper qualityInspectMapper;
    private final RedisTemplate<String, String> redisTemplate;
    @Autowired
    private SysDeptMapper sysDeptMapper;
    @Value("${file.upload-dir}")
    private String uploadDir;
    @Autowired
    private ProductModelMapper productModelMapper;
@@ -153,11 +124,48 @@
    private ProductStructureMapper productStructureMapper;
    @Autowired
    private ProductionProductMainService productionProductMainService;
    @Autowired
    private PurchaseReturnOrderProductsMapper purchaseReturnOrderProductsMapper;
    ;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Override
    public List<SalesLedger> selectSalesLedgerList(SalesLedgerDto salesLedgerDto) {
        return salesLedgerMapper.selectSalesLedgerList(salesLedgerDto);
    }
    public List<SalesLedgerProduct> getSalesLedgerProductListByRelateId(Long relateId, SaleEnum type) {
        LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>();
        productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, relateId);
        productWrapper.eq(SalesLedgerProduct::getType, type.getCode());
        return salesLedgerProductMapper.selectList(productWrapper);
    }
    @Override
    public List<SalesLedgerProduct> getSalesLedgerProductListByIds(@Nullable List<Long> relateIds, SaleEnum type) {
        if (CollectionUtils.isEmpty(relateIds)) {
            return Collections.emptyList();
        }
        LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>();
        productWrapper.in(SalesLedgerProduct::getId, relateIds);
        productWrapper.eq(SalesLedgerProduct::getType, type.getCode());
        List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(productWrapper);
        if (type.equals(SaleEnum.PURCHASE)) {
            // 查询退货信息
            List<Long> productIds = salesLedgerProducts.stream().map(SalesLedgerProduct::getId).collect(Collectors.toList());
            List<SimpleReturnOrderGroupDto> groupListByProductIds = new ArrayList<>();
            if(CollectionUtils.isNotEmpty(productIds)){
                groupListByProductIds = purchaseReturnOrderProductsMapper.getReturnOrderGroupListByProductIds(productIds);
            }
            Map<Long, BigDecimal> returnOrderGroupDtoMap = groupListByProductIds.stream().collect(Collectors.toMap(SimpleReturnOrderGroupDto::getSalesLedgerProductId, SimpleReturnOrderGroupDto::getSumReturnQuantity));
            salesLedgerProducts.forEach(item -> {
                BigDecimal returnQuality = returnOrderGroupDtoMap.getOrDefault(item.getId(), BigDecimal.ZERO);
                item.setReturnQuality(returnQuality);
                item.setAvailableQuality(item.getQuantity().subtract(returnQuality));
            });
        }
        return salesLedgerProducts;
    }
    @Override
@@ -331,22 +339,19 @@
        return salesLedgerMapper.selectSalesLedgerListPage(page, salesLedgerDto);
    }
    @Autowired
    private SysUserMapper sysUserMapper;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult importData(MultipartFile file) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        try {
            InputStream inputStream = file.getInputStream();
            byte[] fileBytes = file.getBytes();
            ExcelUtil<SalesLedgerImportDto> salesLedgerImportDtoExcelUtil = new ExcelUtil<>(SalesLedgerImportDto.class);
            Map<String, List<SalesLedgerImportDto>> stringListMap = salesLedgerImportDtoExcelUtil.importExcelMultiSheet(Arrays.asList("销售台账数据", "销售产品数据"), inputStream, 0);
            if (CollectionUtils.isEmpty(stringListMap)) return AjaxResult.error("销售表格为空!");
            // 业务层合并
            List<SalesLedgerImportDto> salesLedgerImportDtoList = stringListMap.get("销售台账数据");
            // 销售台账数据不跳过标题
            List<SalesLedgerImportDto> salesLedgerImportDtoList = salesLedgerImportDtoExcelUtil.importExcel("销售台账数据", new ByteArrayInputStream(fileBytes), 0);
            // 销售产品数据跳过1行标题
            List<SalesLedgerImportDto> salesLedgerProductImportDtoList = salesLedgerImportDtoExcelUtil.importExcel("销售产品数据", new ByteArrayInputStream(fileBytes), 1);
            if (CollectionUtils.isEmpty(salesLedgerImportDtoList)) return AjaxResult.error("销售台账数据为空!");
            List<SalesLedgerImportDto> salesLedgerProductImportDtoList = stringListMap.get("销售产品数据");
            if (CollectionUtils.isEmpty(salesLedgerProductImportDtoList)) return AjaxResult.error("销售产品数据为空!");
            // 客户数据
            List<Customer> customers = customerMapper.selectList(new LambdaQueryWrapper<Customer>().in(Customer::getCustomerName,
@@ -372,16 +377,20 @@
                BeanUtils.copyProperties(salesLedgerImportDto, salesLedger);
                salesLedger.setExecutionDate(DateUtils.toLocalDate(salesLedgerImportDto.getExecutionDate()));
                // 通过客户名称查询客户ID,客户合同号
                salesLedger.setCustomerId(customers.stream()
                // 查询客户档案并设置销售类型(对公1/对私2)
                Customer matchedCustomer = customers.stream()
                        .filter(customer -> customer.getCustomerName().equals(salesLedger.getCustomerName()))
                        .findFirst()
                        .map(Customer::getId)
                        .orElse(null));
                salesLedger.setCustomerContractNo(customers.stream()
                        .filter(customer -> customer.getCustomerName().equals(salesLedger.getCustomerName()))
                        .findFirst()
                        .map(Customer::getTaxpayerIdentificationNumber)
                        .orElse(null));
                        .orElse(null);
                if (matchedCustomer != null) {
                    salesLedger.setCustomerId(matchedCustomer.getId());
                    salesLedger.setSalesType(matchedCustomer.getCustomerType());
                    salesLedger.setCustomerContractNo(matchedCustomer.getTaxpayerIdentificationNumber());
                } else {
                    salesLedger.setSalesType(1);
                }
                Long aLong = sysUsers.stream()
                        .filter(sysUser -> sysUser.getNickName().equals(salesLedger.getEntryPerson()))
                        .findFirst()
@@ -390,14 +399,30 @@
                if (aLong == null)
                    throw new RuntimeException("录入人:" + salesLedger.getEntryPerson() + ",无对应用户!");
                salesLedger.setEntryPerson(aLong.toString());
                // 销售产品数据绑定,通过销售单号获取对应销售产品数据
                // 销售产品数据绑定
                List<SalesLedgerProductImportDto> salesLedgerProductImportDtos = salesLedgerProductImportDtoList.stream()
                        .filter(salesLedgerProductImportDto -> salesLedgerProductImportDto.getSalesContractNo().equals(salesLedger.getSalesContractNo()))
                        .collect(Collectors.toList());
                if (CollectionUtils.isEmpty(salesLedgerProductImportDtos))
                    throw new RuntimeException("销售单号:" + salesLedgerImportDto.getSalesContractNo() + ",无对应产品数据!");
                boolean isPrivate = Integer.valueOf(2).equals(salesLedger.getSalesType());
                // 统一计算合同总金额
                salesLedger.setContractAmount(salesLedgerProductImportDtos.stream()
                        .map(SalesLedgerProductImportDto::getTaxInclusiveTotalPrice)
                        .map(dto -> {
                            if (isPrivate) {
                                if (dto.getTotalPrice() != null) return dto.getTotalPrice();
                                BigDecimal up = dto.getUnitPrice() != null ? dto.getUnitPrice() : BigDecimal.ZERO;
                                BigDecimal fr = dto.getFreight() != null ? dto.getFreight() : BigDecimal.ZERO;
                                BigDecimal qty = dto.getQuantity() != null ? dto.getQuantity() : BigDecimal.ZERO;
                                return up.add(fr).multiply(qty);
                            } else {
                                return dto.getTaxInclusiveTotalPrice() != null ? dto.getTaxInclusiveTotalPrice() : BigDecimal.ZERO;
                            }
                        })
                        .reduce(BigDecimal.ZERO, BigDecimal::add));
                salesLedgerMapper.insert(salesLedger);
@@ -407,10 +432,54 @@
                    BeanUtils.copyProperties(salesLedgerProductImportDto, salesLedgerProduct);
                    salesLedgerProduct.setSalesLedgerId(salesLedger.getId());
                    salesLedgerProduct.setType(1);
                    // 计算不含税总价
                    salesLedgerProduct.setTaxExclusiveTotalPrice(salesLedgerProduct.getTaxInclusiveTotalPrice().divide(new BigDecimal(1).add(salesLedgerProduct.getTaxRate().divide(new BigDecimal(100))), 2, RoundingMode.HALF_UP));
                    salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getQuantity());
                    salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxExclusiveTotalPrice());
                    if (isPrivate) {
                        // 对私业务
                        if (salesLedgerProduct.getFreight() == null) salesLedgerProduct.setFreight(BigDecimal.ZERO);
                        if (salesLedgerProduct.getUnitPrice() != null && salesLedgerProduct.getQuantity() != null) {
                            if (salesLedgerProduct.getPriceWithFreight() == null) {
                                salesLedgerProduct.setPriceWithFreight(salesLedgerProduct.getUnitPrice().add(salesLedgerProduct.getFreight()));
                            }
                            if (salesLedgerProduct.getTotalPrice() == null) {
                                salesLedgerProduct.setTotalPrice(salesLedgerProduct.getPriceWithFreight().multiply(salesLedgerProduct.getQuantity()));
                            }
                        }
                        BigDecimal tp = salesLedgerProduct.getTotalPrice() != null ? salesLedgerProduct.getTotalPrice() : BigDecimal.ZERO;
                        salesLedgerProduct.setTaxInclusiveTotalPrice(tp);
                        salesLedgerProduct.setTaxExclusiveTotalPrice(salesLedgerProduct.getUnitPrice() != null ?
                                salesLedgerProduct.getUnitPrice().multiply(salesLedgerProduct.getQuantity()) : tp);
                        //  使用含运费总价
                        salesLedgerProduct.setNoInvoiceAmount(tp);
                        salesLedgerProduct.setPendingInvoiceTotal(tp);
                        salesLedgerProduct.setTaxRate(null);
                        salesLedgerProduct.setTaxInclusiveUnitPrice(null);
                        salesLedgerProduct.setInvoiceType(null);
                    } else {
                        // 对公业务逻辑
                        if (salesLedgerProduct.getTaxInclusiveTotalPrice() != null && salesLedgerProduct.getTaxRate() != null) {
                            salesLedgerProduct.setTaxExclusiveTotalPrice(
                                    salesLedgerProduct.getTaxInclusiveTotalPrice()
                                            .divide(new BigDecimal(1).add(salesLedgerProduct.getTaxRate().divide(new BigDecimal(100))), 2, RoundingMode.HALF_UP)
                            );
                        }
                        // 对公使用含税总价
                        BigDecimal titp = salesLedgerProduct.getTaxInclusiveTotalPrice() != null ? salesLedgerProduct.getTaxInclusiveTotalPrice() : BigDecimal.ZERO;
                        salesLedgerProduct.setNoInvoiceAmount(titp);
                        salesLedgerProduct.setPendingInvoiceTotal(titp);
                        salesLedgerProduct.setUnitPrice(null);
                        salesLedgerProduct.setTotalPrice(null);
                        salesLedgerProduct.setFreight(BigDecimal.ZERO);
                        salesLedgerProduct.setPriceWithFreight(null);
                    }
                    // 匹配产品种类和规格型号映射ID
                    list.stream()
                            .filter(map -> map.get("productName").equals(salesLedgerProduct.getProductCategory()) && map.get("model").equals(salesLedgerProduct.getSpecificationModel()))
                            .findFirst()
@@ -418,20 +487,12 @@
                                salesLedgerProduct.setProductModelId(Long.parseLong(map.get("modelId").toString()));
                                salesLedgerProduct.setProductId(Long.parseLong(map.get("id").toString()));
                            });
//                    salesLedgerProduct.setProductId(productList.stream()
//                            .filter(product -> product.getProductName().equals(salesLedgerProduct.getProductCategory()))
//                            .findFirst()
//                            .map(Product::getId)
//                            .orElse(null));
//                    salesLedgerProduct.setProductModelId(productModels.stream()
//                            .filter(productModel -> productModel.getModel().equals(salesLedgerProduct.getSpecificationModel()))
//                            .findFirst()
//                            .map(ProductModel::getId)
//                            .orElse(null));
                    // 填充登记信息
                    salesLedgerProduct.setRegister(loginUser.getNickName());
                    salesLedgerProduct.setRegisterDate(LocalDateTime.now());
                    salesLedgerProduct.setApproveStatus(0);
                    salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProductImportDto.getTaxInclusiveTotalPrice());
                    salesLedgerProductMapper.insert(salesLedgerProduct);
                    // 添加生产数据
                    salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
@@ -440,9 +501,9 @@
            return AjaxResult.success("导入成功");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("导入失败:", e);
            throw new RuntimeException("导入数据过程中发生了错误:" + e.getMessage());
        }
        return AjaxResult.success("导入失败");
    }
    @Override
@@ -457,7 +518,7 @@
    @Override
    public IPage<SalesLedgerDto> listSalesLedger(SalesLedgerDto salesLedgerDto, Page page) {
        IPage<SalesLedgerDto> salesLedgerDtoIPage = salesLedgerMapper.listSalesLedger(page, salesLedgerDto);
        IPage<SalesLedgerDto> salesLedgerDtoIPage = salesLedgerMapper.listSalesLedgerAndShipped(page, salesLedgerDto);
        for (SalesLedgerDto salesLedger : salesLedgerDtoIPage.getRecords()) {
            LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>();
            productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, salesLedger.getId());
@@ -477,47 +538,18 @@
                        .last("limit 1"));
                if (shippingInfo != null) {
                    product.setShippingStatus(shippingInfo.getStatus());
                }
            }
            // 过滤只保留发货记录
            products = products.stream().filter(product -> "已发货".equals(product.getShippingStatus())).collect(Collectors.toList());
            if (!products.isEmpty()) {
                salesLedger.setHasChildren(true);
                salesLedger.setProductData(products);
            }
        }
        return salesLedgerDtoIPage;
    }
    // 内部类用于存储聚合结果
    private static class GroupedCustomer {
        private final Long customerId;
        private final String customerName;
        private BigDecimal totalAmount = BigDecimal.ZERO;
        public GroupedCustomer(Long customerId, String customerName) {
            this.customerId = customerId;
            this.customerName = customerName;
        }
        public void addAmount(BigDecimal amount) {
            if (amount != null) {
                this.totalAmount = this.totalAmount.add(amount);
            }
        }
        public Long getCustomerId() {
            return customerId;
        }
        public String getCustomerName() {
            return customerName;
        }
        public BigDecimal getTotalAmount() {
            return totalAmount;
        }
    }
    /**
@@ -637,16 +669,23 @@
            // 4. 处理子表数据
            List<SalesLedgerProduct> productList = salesLedgerDto.getProductData();
            if (productList != null && !productList.isEmpty()) {
                handleSalesLedgerProducts(salesLedger.getId(), productList, EnumUtil.fromCode(SaleEnum.class,salesLedgerDto.getType()));
            if (productList == null || productList.isEmpty()){
                throw new ServiceException("新增/修改失败,销售产品不能为空");
            }
                handleSalesLedgerProducts(salesLedger.getId(), productList, EnumUtil.fromCode(SaleEnum.class, salesLedgerDto.getType()), salesLedger.getSalesType());
                Function<SalesLedgerProduct, BigDecimal> amountGetter =
                    Integer.valueOf(2).equals(salesLedger.getSalesType()) ?
                        p -> p.getTotalPrice() != null ? p.getTotalPrice() : BigDecimal.ZERO
                        : p -> p.getTaxInclusiveTotalPrice() != null ? p.getTaxInclusiveTotalPrice() : BigDecimal.ZERO;
                updateMainContractAmount(
                        salesLedger.getId(),
                        productList,
                        SalesLedgerProduct::getTaxInclusiveTotalPrice,
                        amountGetter,
                        salesLedgerMapper,
                        SalesLedger.class
                );
            }
            // 5. 迁移临时文件到正式目录
            if (salesLedgerDto.getTempFileIds() != null && !salesLedgerDto.getTempFileIds().isEmpty()) {
@@ -657,8 +696,6 @@
            throw new BaseException("文件迁移失败: " + e.getMessage());
        }
    }
    // 文件迁移方法
    /**
     * 将临时文件迁移到正式目录
@@ -735,9 +772,14 @@
        }
    }
    // 文件迁移方法
    @Override
    public void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, SaleEnum type) {
        handleSalesLedgerProducts(salesLedgerId, products, type, 1);
    }
    public void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, SaleEnum type, Integer salesType) {
        // 按ID分组,区分新增和更新的记录
        Map<Boolean, List<SalesLedgerProduct>> partitionedProducts = products.stream()
                .peek(p -> p.setSalesLedgerId(salesLedgerId))
@@ -758,11 +800,16 @@
            for (SalesLedgerProduct salesLedgerProduct : insertList) {
                salesLedgerProduct.setType(type.getCode());
                salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getQuantity());
                salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxInclusiveTotalPrice());
                salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice());
                if (Integer.valueOf(2).equals(salesType)) {
                    salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTotalPrice() != null ? salesLedgerProduct.getTotalPrice() : BigDecimal.ZERO);
                    salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTotalPrice() != null ? salesLedgerProduct.getTotalPrice() : BigDecimal.ZERO);
                } else {
                    salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxInclusiveTotalPrice());
                    salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice());
                }
                salesLedgerProductMapper.insert(salesLedgerProduct);
                // 添加生产数据
                salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
//                salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
            }
        }
    }
@@ -876,4 +923,34 @@
            throw new RuntimeException("动态更新主表金额失败", e);
        }
    }
    // 内部类用于存储聚合结果
    private static class GroupedCustomer {
        private final Long customerId;
        private final String customerName;
        private BigDecimal totalAmount = BigDecimal.ZERO;
        public GroupedCustomer(Long customerId, String customerName) {
            this.customerId = customerId;
            this.customerName = customerName;
        }
        public void addAmount(BigDecimal amount) {
            if (amount != null) {
                this.totalAmount = this.totalAmount.add(amount);
            }
        }
        public Long getCustomerId() {
            return customerId;
        }
        public String getCustomerName() {
            return customerName;
        }
        public BigDecimal getTotalAmount() {
            return totalAmount;
        }
    }
}