From 400169d87dee7a40802824875167a4dec4ef3bc0 Mon Sep 17 00:00:00 2001
From: buhuazhen <hua100783@gmail.com>
Date: 星期五, 24 四月 2026 15:34:57 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_天津_阳光彩印' into dev_天津_阳光彩印

---
 src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java |  528 +++++++++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 410 insertions(+), 118 deletions(-)

diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
index ffa35f1..fb94028 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -1,5 +1,11 @@
 package com.ruoyi.sales.service.impl;
 
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -8,14 +14,23 @@
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.deepoove.poi.XWPFTemplate;
+import com.deepoove.poi.config.Configure;
+import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
 import com.ruoyi.account.service.AccountIncomeService;
+import com.ruoyi.basic.dto.CustomerPrivatePoolDto;
+import com.ruoyi.basic.dto.ProductModelAnticlockwiseDto;
 import com.ruoyi.basic.mapper.CustomerMapper;
+import com.ruoyi.basic.mapper.CustomerPrivatePoolMapper;
 import com.ruoyi.basic.mapper.ProductMapper;
 import com.ruoyi.basic.mapper.ProductModelMapper;
 import com.ruoyi.basic.pojo.Customer;
+import com.ruoyi.basic.service.IProductModelService;
 import com.ruoyi.common.enums.FileNameType;
+import com.ruoyi.common.enums.SaleEnum;
 import com.ruoyi.common.exception.base.BaseException;
 import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.EnumUtil;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -23,36 +38,42 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 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.mapper.ProductStructureMapper;
+import com.ruoyi.production.service.ProductionProductMainService;
 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.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 com.ruoyi.sales.vo.ExportProcessContractVo;
 import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.FilenameUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.data.redis.core.script.DefaultRedisScript;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.constraints.NotNull;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.reflect.Field;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -76,69 +97,28 @@
 @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 InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
+    private final InvoiceRegistrationMapper invoiceRegistrationMapper;
     private final RedisTemplate<String, String> redisTemplate;
+    @Autowired
+    private SysDeptMapper sysDeptMapper;
+    @Value("${file.upload-dir}")
+    private String uploadDir;
     @Autowired
     private ProductModelMapper productModelMapper;
 
@@ -146,11 +126,27 @@
     private ProductMapper productMapper;
     @Autowired
     private ProductStructureMapper productStructureMapper;
-;
+    @Autowired
+    @Lazy
+    private ProductionProductMainService productionProductMainService;
+
+    @Autowired
+    private SysUserMapper sysUserMapper;
+    @Autowired
+    private CustomerPrivatePoolMapper customerPrivatePoolMapper;
+    @Autowired
+    private IProductModelService productModelService;
 
     @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
@@ -178,7 +174,7 @@
                     .eq(ShippingInfo::getSalesLedgerProductId, product.getId())
                     .orderByDesc(ShippingInfo::getCreateTime)
                     .last("limit 1"));
-            if(shippingInfo != null){
+            if (shippingInfo != null) {
                 product.setShippingStatus(shippingInfo.getStatus());
             }
         }
@@ -324,9 +320,6 @@
         return salesLedgerMapper.selectSalesLedgerListPage(page, salesLedgerDto);
     }
 
-    @Autowired
-    private SysUserMapper sysUserMapper;
-
     @Override
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult importData(MultipartFile file) {
@@ -350,7 +343,7 @@
 //            // 浜у搧澶х被鏁版嵁
 //            List<Product> productList = productMapper.selectList(new LambdaQueryWrapper<Product>().in(Product::getProductName,
 //                    salesLedgerProductImportDtoList.stream().map(SalesLedgerImportDto::getProductCategory).collect(Collectors.toList())));
-            List<Map<String,Object>> list = productModelMapper.getProductAndModelList();
+            List<Map<String, Object>> list = productModelMapper.getProductAndModelList();
             // 褰曞叆浜烘暟鎹�
             List<SysUser> sysUsers = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>().in(SysUser::getNickName,
                     salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getEntryPerson).collect(Collectors.toList())));
@@ -358,7 +351,7 @@
                 SalesLedger salesLedger1 = salesLedgerMapper.selectOne(new LambdaQueryWrapper<SalesLedger>()
                         .eq(SalesLedger::getSalesContractNo, salesLedgerImportDto.getSalesContractNo())
                         .last("LIMIT 1"));
-                if(salesLedger1 != null){
+                if (salesLedger1 != null) {
                     continue;
                 }
                 SalesLedger salesLedger = new SalesLedger();
@@ -391,7 +384,7 @@
                     throw new RuntimeException("閿�鍞崟鍙�:" + salesLedgerImportDto.getSalesContractNo() + ",鏃犲搴斾骇鍝佹暟鎹紒");
                 salesLedger.setContractAmount(salesLedgerProductImportDtos.stream()
                         .map(SalesLedgerProductImportDto::getTaxInclusiveTotalPrice)
-                        .reduce(BigDecimal.ZERO,BigDecimal::add));
+                        .reduce(BigDecimal.ZERO, BigDecimal::add));
                 salesLedgerMapper.insert(salesLedger);
 
 
@@ -426,6 +419,8 @@
                     salesLedgerProduct.setApproveStatus(0);
                     salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProductImportDto.getTaxInclusiveTotalPrice());
                     salesLedgerProductMapper.insert(salesLedgerProduct);
+                    // 娣诲姞鐢熶骇鏁版嵁
+                    salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
                 }
             }
 
@@ -446,35 +441,271 @@
         return lossProductModelDtos;
     }
 
+    @Override
+    public IPage<SalesLedgerDto> listSalesLedger(SalesLedgerDto salesLedgerDto, Page page) {
+        IPage<SalesLedgerDto> salesLedgerDtoIPage = salesLedgerMapper.listSalesLedger(page, salesLedgerDto);
+        for (SalesLedgerDto salesLedger : salesLedgerDtoIPage.getRecords()) {
+            LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>();
+            productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, salesLedger.getId());
+            productWrapper.eq(SalesLedgerProduct::getType, 1);
+            List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(productWrapper);
+            for (SalesLedgerProduct product : products) {
+                product.setOriginalNoInvoiceNum(product.getNoInvoiceNum());
+                // 鎻愪緵涓存椂鏈紑绁ㄦ暟锛屾湭寮�绁ㄩ噾棰濅緵鍓嶆璁$畻
+                product.setTempnoInvoiceAmount(product.getNoInvoiceAmount());
+                product.setTempNoInvoiceNum(product.getNoInvoiceNum());
+                product.setRegister(SecurityUtils.getLoginUser().getUser().getNickName());
+                product.setRegisterDate(LocalDateTime.now());
+                // 鍙戣揣淇℃伅
+                ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>()
+                        .eq(ShippingInfo::getSalesLedgerProductId, product.getId())
+                        .orderByDesc(ShippingInfo::getCreateTime)
+                        .last("limit 1"));
+                if (shippingInfo != null) {
+                    product.setShippingStatus(shippingInfo.getStatus());
 
-    // 鍐呴儴绫荤敤浜庡瓨鍌ㄨ仛鍚堢粨鏋�
-    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);
+                }
+            }
+            if (!products.isEmpty()) {
+                salesLedger.setHasChildren(true);
+                salesLedger.setProductData(products);
             }
         }
 
-        public Long getCustomerId() {
-            return customerId;
+        return salesLedgerDtoIPage;
+    }
+
+    @Override
+    public void exportProcessContract(Long id) {
+        //鍔犲伐鎵挎徑鍚堝悓
+        ExportProcessContractVo exportProcessContract = new ExportProcessContractVo();
+        exportProcessContract.setId(id);
+        SalesLedger salesLedger = salesLedgerMapper.selectById(id);
+        // 鏌ヨ瀹㈡埛鍏徃淇℃伅
+        CustomerPrivatePoolDto customerPrivatePoolDto = customerPrivatePoolMapper.selectInfo(salesLedger.getCustomerId());
+
+        exportProcessContract.setCreateTime(LocalDateTimeUtil.format(Optional.ofNullable(salesLedger.getExecutionDate()).orElse(LocalDate.now()), "yyyy骞碝M鏈坉d鏃�"));
+        exportProcessContract.setRemark(Optional.ofNullable(salesLedger.getRemarks()).orElse("鏃�")); // 澶囨敞
+        exportProcessContract.setPlaceOfSinging(Optional.ofNullable(salesLedger.getPlaceOfSinging()).orElse(""));
+
+        // 濉啓鐢叉柟淇℃伅
+        ExportProcessContractVo.Customer partyA = ExportProcessContractVo.Customer.getCustomer(customerPrivatePoolDto);
+        exportProcessContract.setPartyAClientName(customerPrivatePoolDto.getCustomerName());
+        exportProcessContract.setPartyA(partyA);
+
+        // 濉啓涔欐柟淇℃伅
+        ExportProcessContractVo.Customer partyB = new ExportProcessContractVo.Customer();
+        exportProcessContract.setPartyBClientName("澶╂触闃冲厜褰╁嵃鑲′唤鏈夐檺鍏徃");
+        partyB.setBankName("鍐滆澶╂触姝︽竻寮�鍙戝尯鏀");
+        partyB.setBankCode("02061601040014681");
+        partyB.setTaxpayerIdentificationNumber("91120000562687393p");
+        partyB.setAddress("澶╂触姝︽竻鍖哄紑鍙戝尯娉夊窞鍖楄矾29鍙�");
+        partyB.setFax("022-82126666");
+        partyB.setPostCode("301700");
+        exportProcessContract.setPartyB(partyB);
+
+        // 濉啓鍟嗗搧淇℃伅
+        final BigDecimal[] totalAmount = {BigDecimal.ZERO}; // 鎬婚噾棰�
+        LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>();
+        productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, salesLedger.getId());
+        productWrapper.eq(SalesLedgerProduct::getType, 1);
+        List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(productWrapper);
+        List<ExportProcessContractVo.SaleProduct> productList = products.stream().map(it -> {
+            ExportProcessContractVo.SaleProduct saleProduct = BeanUtil.copyProperties(it, ExportProcessContractVo.SaleProduct.class);
+            // 璁$畻鎬讳环鏍�
+            totalAmount[0] = totalAmount[0].add(Optional.ofNullable(saleProduct.getTaxInclusiveTotalPrice()).orElse(BigDecimal.ZERO));
+            return saleProduct;
+        }).collect(Collectors.toList());
+        // 绗竴涓缃� 鍚堝悓缂栧彿
+        if (!productList.isEmpty()) {
+            productList.get(0).setSalesContractNo(salesLedger.getSalesContractNo());
+        }
+        // 鏌ョ湅绋庣巼 鐞嗚涓婄◣鐜囧崟涓�锛屽鏋滃绋庣巼涓虹┖
+        Map<BigDecimal, Long> rateMap = productList.stream().map(product -> product.getTaxRate()).filter(Objects::nonNull)
+                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
+        String taxRateStr = rateMap.size() == 1 ? rateMap.keySet().iterator().next().toString() + " %" : "";
+        exportProcessContract.setTaxRate(taxRateStr);
+        exportProcessContract.setSaleProducts(productList);// 鍟嗗搧淇℃伅
+        // 璁剧疆澶у啓鐨勬�讳环鏍�
+        exportProcessContract.setTotalAmountZh(Convert.digitToChinese(totalAmount[0].doubleValue()));
+
+        exportProcessContractToWord(exportProcessContract);
+    }
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public AjaxResult importSalsesLedger(MultipartFile file) {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        int successCount = 0;
+        Date lastDate = null;
+        BigDecimal lastUnitPrice = null;
+        int skipCount = 0;
+        List<String> errorMessages = new ArrayList<>();
+        CustomerPrivatePoolDto lastCustomer = null;
+
+        try {
+            InputStream inputStream = file.getInputStream();
+            ExcelUtil<SalesLedgerSimpleImportDto> excelUtil = new ExcelUtil<>(SalesLedgerSimpleImportDto.class);
+            List<SalesLedgerSimpleImportDto> importDataList = excelUtil.importExcel(inputStream);
+
+            if (CollectionUtils.isEmpty(importDataList)) {
+                return AjaxResult.error("瀵煎叆鏁版嵁涓虹┖锛�");
+            }
+
+            List<String> customerNames = importDataList.stream()
+                    .map(SalesLedgerSimpleImportDto::getCustomerName)
+                    .filter(StrUtil::isNotBlank)
+                    .distinct()
+                    .collect(Collectors.toList());
+
+            List<CustomerPrivatePoolDto> customers = customerPrivatePoolMapper.selectByCusterNames(customerNames);
+
+            for (int i = 0; i < importDataList.size(); i++) {
+                SalesLedgerSimpleImportDto importDto = importDataList.get(i);
+                int rowNum = i + 2;
+
+                if (StrUtil.isBlank(importDto.getOrderNo())) {
+                    errorMessages.add(String.format("绗�%d琛岋細璁㈠崟缂栧彿涓虹┖", rowNum));
+                    skipCount++;
+                    continue;
+                }
+
+                if (importDto.getQuantity() == null ) {
+                    errorMessages.add(String.format("绗�%d琛岋細鏁伴噺涓嶈兘涓虹┖", rowNum));
+                    skipCount++;
+                    continue;
+                }
+
+                long count = salesLedgerMapper.selectCount(new LambdaQueryWrapper<SalesLedger>()
+                        .eq(SalesLedger::getSalesContractNo, importDto.getOrderNo()));
+                if (count > 0) {
+                    errorMessages.add(String.format("绗�%d琛岋細璁㈠崟缂栧彿[%s]宸插瓨鍦�", rowNum, importDto.getOrderNo()));
+                    skipCount++;
+                    continue;
+                }
+
+                CustomerPrivatePoolDto matchedCustomer = customers.stream()
+                        .filter(c -> c.getCustomerName().equals(importDto.getCustomerName()))
+                        .findFirst()
+                        .orElse(lastCustomer);
+
+                if (matchedCustomer == null) {
+                    errorMessages.add(String.format("绗�%d琛岋細瀹㈡埛[%s]涓嶅瓨鍦ㄤ笖鏃犲巻鍙插鎴�", rowNum, importDto.getCustomerName()));
+                    skipCount++;
+                    continue;
+                }
+
+                lastCustomer = matchedCustomer;
+
+                try {
+                    SalesLedger salesLedger = new SalesLedger();
+                    salesLedger.setSalesContractNo(importDto.getOrderNo());
+                    salesLedger.setCustomerName(matchedCustomer.getCustomerName());
+                    salesLedger.setCustomerId(matchedCustomer.getId());
+                    salesLedger.setCustomerContractNo(matchedCustomer.getTaxpayerIdentificationNumber());
+                    Date date = importDto.getOrderDate();
+                    if (ObjectUtils.isEmpty(date)){
+                        date = lastDate;
+                    }
+                    lastDate = date;
+                    salesLedger.setEntryDate(date);
+
+                    salesLedger.setEntryPerson(loginUser.getUserId().toString());
+                    salesLedger.setTenantId(matchedCustomer.getTenantId());
+                    salesLedgerMapper.insert(salesLedger);
+
+                    SalesLedgerProduct product = new SalesLedgerProduct();
+                    product.setSalesLedgerId(salesLedger.getId());
+                    product.setType(1);
+                    product.setQuantity(importDto.getQuantity());
+                    BigDecimal unitPrice = importDto.getUnitPrice();
+                    if (ObjectUtils.isEmpty(unitPrice)) {
+                        unitPrice = lastUnitPrice;
+                    }
+                    lastUnitPrice = unitPrice;
+                    product.setTaxInclusiveUnitPrice(unitPrice);
+                    product.setTaxInclusiveTotalPrice(unitPrice.multiply(importDto.getQuantity()));
+                    product.setTaxExclusiveTotalPrice(unitPrice.multiply(importDto.getQuantity()));
+                    product.setNoInvoiceNum(importDto.getQuantity());
+                    product.setNoInvoiceAmount(importDto.getAmount());
+                    product.setPendingInvoiceTotal(importDto.getAmount());
+                    product.setUnit("/");
+                    product.setProductCategory(importDto.getProductName());
+                    product.setSpecificationModel(importDto.getProductName());
+                    product.setRegister(loginUser.getNickName());
+                    product.setRegisterDate(LocalDateTime.now());
+                    product.setApproveStatus(0);
+
+                    if (ObjectUtils.isEmpty(product.getProductModelId())) {
+                        ProductModelAnticlockwiseDto productModelAnticlockwiseDto = new ProductModelAnticlockwiseDto();
+                        productModelAnticlockwiseDto.setModel(product.getSpecificationModel());
+                        productModelAnticlockwiseDto.setProductName(product.getProductCategory());
+                        productModelAnticlockwiseDto.setUnit("/");
+                        productModelAnticlockwiseDto.setSubUnit("/");
+                        Long productModelId = productModelService.productModelAnticlockwise(productModelAnticlockwiseDto);
+                        product.setProductModelId(productModelId);
+                    }
+                    salesLedger.setContractAmount(product.getTaxInclusiveTotalPrice());
+                    salesLedgerMapper.updateById(salesLedger);
+
+                    salesLedgerProductMapper.insert(product);
+                    salesLedgerProductServiceImpl.addProductionData(product);
+                    successCount++;
+
+                } catch (Exception e) {
+                    log.error("绗瑊}琛岃鍗昜{}]瀵煎叆澶辫触锛歿}", rowNum, importDto.getOrderNo(), e.getMessage(), e);
+                    errorMessages.add(String.format("绗�%d琛岃鍗昜%s]锛氬鍏ュけ璐�-%s", rowNum, importDto.getOrderNo(), e.getMessage()));
+                    skipCount++;
+                }
+            }
+
+            String message = String.format("瀵煎叆瀹屾垚锛佹垚鍔�%d鏉★紝璺宠繃%d鏉�", successCount, skipCount);
+            if (!errorMessages.isEmpty()) {
+                message += "銆傞敊璇鎯咃細" + String.join("锛�", errorMessages);
+            }
+            return AjaxResult.success(message);
+        } catch (Exception e) {
+            log.error("瀵煎叆閿�鍞彴璐﹀け璐�", e);
+            throw new RuntimeException("瀵煎叆澶辫触锛�" + e.getMessage(), e);
+        }
+    }
+
+    @SneakyThrows
+    private void exportProcessContractToWord(@NotNull ExportProcessContractVo exportProcessContract) {
+        // 纭繚 saleProducts 涓嶄负 null
+        if (exportProcessContract.getSaleProducts() == null) {
+            exportProcessContract.setSaleProducts(new ArrayList<>());
         }
 
-        public String getCustomerName() {
-            return customerName;
-        }
+        // 妯℃澘杈撳叆娴�
+        InputStream inputStream = this.getClass().getResourceAsStream("/static/contract_tmp.docx");
+        Assert.isTrue(inputStream != null, "妯℃澘涓嶅瓨鍦�");
 
-        public BigDecimal getTotalAmount() {
-            return totalAmount;
-        }
+        // 杞� Map
+        Map<String, Object> dataMap = BeanUtil.beanToMap(exportProcessContract);
+
+        // 缁戝畾寰幆绛栫暐
+        Configure configure = Configure.builder()
+                .bind("saleProducts", new LoopRowTableRenderPolicy())
+                .build();
+
+        // 娓叉煋妯℃澘
+        XWPFTemplate template = XWPFTemplate.compile(inputStream, configure)
+                .render(dataMap);
+//        template.write(FileUtil.getOutputStream("/Users/ONEX/Downloads/a.docx"));
+
+        // 杈撳嚭鍒版祻瑙堝櫒
+        HttpServletResponse response =
+                ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes()))
+                        .getResponse();
+        String rawFileName = StrUtil.format("{}-{}鍚堝悓.docx",
+                exportProcessContract.getPartyAClientName(),
+                exportProcessContract.getCreateTime());
+        String encodedFileName = URLEncoder.encode(rawFileName, StandardCharsets.UTF_8.toString());
+        response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFileName);
+        response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
+        template.write(response.getOutputStream());
+        template.close();
+        response.flushBuffer();
     }
 
     /**
@@ -517,11 +748,12 @@
         List<Long> productIds = products.stream()
                 .map(SalesLedgerProduct::getId)
                 .collect(Collectors.toList());
-        //鍒犻櫎鐢熶骇鏁版嵁
-        salesLedgerProductServiceImpl.deleteProductionData(productIds);
+
 
         // 鎵归噺鍒犻櫎浜у搧瀛愯〃
         if (!productIds.isEmpty()) {
+            //鍒犻櫎鐢熶骇鏁版嵁
+            salesLedgerProductServiceImpl.deleteProductionData(productIds);
             salesLedgerProductMapper.deleteBatchIds(productIds);
         }
 
@@ -551,25 +783,20 @@
         // 鍒犻櫎鍙戣揣鍙拌处璁板綍
         List<ShippingInfo> shippingInfos = shippingInfoMapper.selectList(new LambdaQueryWrapper<ShippingInfo>()
                 .in(ShippingInfo::getSalesLedgerId, idList));
-        if(CollectionUtils.isNotEmpty(shippingInfos)){
+        if (CollectionUtils.isNotEmpty(shippingInfos)) {
             shippingInfoServiceImpl.delete(shippingInfos.stream().map(ShippingInfo::getId).collect(Collectors.toList()));
         }
         // 鍒犻櫎闄勪欢琛�
         commonFileService.deleteByBusinessIds(idList, FileNameType.SALE.getValue());
 
         // 鍒犻櫎鐢熶骇绠℃帶鏁版嵁
-        // 鍒犻櫎鐢熶骇璁㈠崟鏁版嵁
-        LambdaQueryWrapper<SalesLedgerScheduling> in = new LambdaQueryWrapper<SalesLedgerScheduling>()
-                .in(SalesLedgerScheduling::getSalesLedgerId, idList);
-        salesLedgerSchedulingMapper.delete(in);
-        // 鍒犻櫎鐢熶骇娲惧伐鏁版嵁
-        LambdaQueryWrapper<SalesLedgerWork> workOrderWrapper = new LambdaQueryWrapper<>();
-        workOrderWrapper.in(SalesLedgerWork::getSalesLedgerId, idList);
-        salesLedgerWorkMapper.delete(workOrderWrapper);
-        // 鍒犻櫎鐢熶骇鏍哥畻鏁版嵁
-        LambdaQueryWrapper<SalesLedgerProductionAccounting> reportWrapper = new LambdaQueryWrapper<>();
-        reportWrapper.in(SalesLedgerProductionAccounting::getSalesLedgerId, idList);
-        salesLedgerProductionAccountingMapper.delete(reportWrapper);
+        //鏌ヨ鐢熶骇鎶ュ伐id
+        ArrayList<Long> mainIdList = productionProductMainService.listMain(idList);
+        if (CollectionUtils.isNotEmpty(mainIdList)) {
+            mainIdList.stream().forEach(mainId -> {
+                productionProductMainService.removeProductMain(mainId);
+            });
+        }
         // 2. 鍐嶅垹闄や富琛ㄦ暟鎹�
         return salesLedgerMapper.deleteBatchIds(idList);
     }
@@ -577,30 +804,50 @@
     @Override
     @Transactional(rollbackFor = Exception.class)
     public int addOrUpdateSalesLedger(SalesLedgerDto salesLedgerDto) {
-        try {
             // 1. 鏍¢獙瀹㈡埛淇℃伅
-            Customer customer = customerMapper.selectById(salesLedgerDto.getCustomerId());
+            CustomerPrivatePoolDto customer = customerPrivatePoolMapper.selectInfo(salesLedgerDto.getCustomerId());
             if (customer == null) {
                 throw new BaseException("瀹㈡埛涓嶅瓨鍦�");
             }
+            // 蹇呴』濉啓閿�鍞悎鍚屽彿
+//            Assert.notNull(salesLedgerDto.getSalesContractNo(), "閿�鍞悎鍚屽彿涓嶈兘涓虹┖");
 
             // 2. DTO杞珽ntity
             SalesLedger salesLedger = convertToEntity(salesLedgerDto);
             salesLedger.setCustomerName(customer.getCustomerName());
             salesLedger.setTenantId(customer.getTenantId());
+
             // 3. 鏂板鎴栨洿鏂颁富琛�
             if (salesLedger.getId() == null) {
-                String contractNo = generateSalesContractNo();
+                // 涓虹┖ 鑷姩鐢熸垚
+                String contractNo =StrUtil.isBlank(salesLedgerDto.getSalesContractNo())? generateSalesContractNoBy8Date():salesLedgerDto.getSalesContractNo();
+                // 涓嶈兘鏈夐噸澶嶆暟鎹殑鍚堝悓鍙�
+               Assert.isTrue(salesLedgerMapper.selectOne(new LambdaQueryWrapper<SalesLedger>()
+                        .eq(SalesLedger::getSalesContractNo, contractNo)
+                        .last("limit 1")) == null, contractNo+"鍚堝悓鍙峰凡瀛樺湪");
                 salesLedger.setSalesContractNo(contractNo);
                 salesLedgerMapper.insert(salesLedger);
             } else {
+                salesLedger.setSalesContractNo(null);
                 salesLedgerMapper.updateById(salesLedger);
             }
 
             // 4. 澶勭悊瀛愯〃鏁版嵁
             List<SalesLedgerProduct> productList = salesLedgerDto.getProductData();
+            for (SalesLedgerProduct product : productList) {
+                //绌虹殑鍏堟柊澧炲熀纭�鏁版嵁  闈炵┖鐩存帴寰�涓嬭蛋
+                if (ObjectUtils.isEmpty(product.getProductModelId())) {
+                    ProductModelAnticlockwiseDto  productModelAnticlockwiseDto =  new ProductModelAnticlockwiseDto();
+                    productModelAnticlockwiseDto.setModel(product.getSpecificationModel());
+                    productModelAnticlockwiseDto.setProductName(product.getProductCategory());
+                    productModelAnticlockwiseDto.setUnit(product.getUnit());
+                    productModelAnticlockwiseDto.setSubUnit(product.getUnit());
+                    Long productModelId = productModelService.productModelAnticlockwise(productModelAnticlockwiseDto);
+                    product.setProductModelId(productModelId);
+                }
+            }
             if (productList != null && !productList.isEmpty()) {
-                handleSalesLedgerProducts(salesLedger.getId(), productList, salesLedgerDto.getType());
+                handleSalesLedgerProducts(salesLedger.getId(), productList, EnumUtil.fromCode(SaleEnum.class, salesLedgerDto.getType()));
                 updateMainContractAmount(
                         salesLedger.getId(),
                         productList,
@@ -609,6 +856,7 @@
                         SalesLedger.class
                 );
             }
+        try {
 
             // 5. 杩佺Щ涓存椂鏂囦欢鍒版寮忕洰褰�
             if (salesLedgerDto.getTempFileIds() != null && !salesLedgerDto.getTempFileIds().isEmpty()) {
@@ -619,8 +867,6 @@
             throw new BaseException("鏂囦欢杩佺Щ澶辫触: " + e.getMessage());
         }
     }
-
-    // 鏂囦欢杩佺Щ鏂规硶
 
     /**
      * 灏嗕复鏃舵枃浠惰縼绉诲埌姝e紡鐩綍
@@ -697,8 +943,10 @@
         }
     }
 
+    // 鏂囦欢杩佺Щ鏂规硶
 
-    private void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, Integer type) {
+    @Override
+    public void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, SaleEnum type) {
         // 鎸塈D鍒嗙粍锛屽尯鍒嗘柊澧炲拰鏇存柊鐨勮褰�
         Map<Boolean, List<SalesLedgerProduct>> partitionedProducts = products.stream()
                 .peek(p -> p.setSalesLedgerId(salesLedgerId))
@@ -710,14 +958,14 @@
         // 鎵ц鏇存柊鎿嶄綔
         if (!updateList.isEmpty()) {
             for (SalesLedgerProduct product : updateList) {
-                product.setType(type);
+                product.setType(type.getCode());
                 salesLedgerProductMapper.updateById(product);
             }
         }
         // 鎵ц鎻掑叆鎿嶄綔
         if (!insertList.isEmpty()) {
             for (SalesLedgerProduct salesLedgerProduct : insertList) {
-                salesLedgerProduct.setType(type);
+                salesLedgerProduct.setType(type.getCode());
                 salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getQuantity());
                 salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxInclusiveTotalPrice());
                 salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice());
@@ -733,6 +981,20 @@
         BeanUtils.copyProperties(dto, entity);
         return entity;
     }
+
+    public String generateSalesContractNoBy8Date(){
+        String yyMM = DateUtil.format(new Date(), "yyMM");
+        // 鏌ヨ涓�涓湀鏈夊灏戣鍗�
+        Date begin = DateUtil.beginOfMonth(new Date());
+        Date end = DateUtil.endOfMonth(new Date());
+        LambdaQueryWrapper<SalesLedger> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.between(SalesLedger::getEntryDate, begin, end);
+        long count = salesLedgerMapper.selectCount(queryWrapper);
+        Long seq = Optional.of(count).orElse(0L) + 1;
+        return String.format("%s%04d", yyMM, seq);
+    }
+
+
 
     @Transactional(readOnly = true)
     public String generateSalesContractNo() {
@@ -837,4 +1099,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;
+        }
+    }
 }

--
Gitblit v1.9.3