From fcccabc2af00c6f433210945566e24891efaf8fa Mon Sep 17 00:00:00 2001
From: yuan <123@>
Date: 星期一, 31 八月 2026 19:12:35 +0800
Subject: [PATCH] fix: 优化销售导入功能

---
 src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java |  406 +++++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 275 insertions(+), 131 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 0b66aea..ff1ef13 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -8,13 +8,20 @@
 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.ruoyi.account.service.AccountIncomeService;
+import com.ruoyi.account.mapper.sales.AccountInvoiceApplicationMapper;
+import com.ruoyi.account.mapper.sales.AccountSalesCollectionMapper;
+import com.ruoyi.account.pojo.sales.AccountInvoiceApplication;
+import com.ruoyi.account.pojo.sales.AccountSalesCollection;
 import com.ruoyi.basic.enums.ApplicationTypeEnum;
 import com.ruoyi.basic.enums.RecordTypeEnum;
 import com.ruoyi.basic.mapper.CustomerMapper;
+import com.ruoyi.basic.mapper.CustomerUserMapper;
 import com.ruoyi.basic.mapper.ProductMapper;
 import com.ruoyi.basic.mapper.ProductModelMapper;
 import com.ruoyi.basic.pojo.Customer;
+import com.ruoyi.basic.pojo.CustomerUser;
+import com.ruoyi.basic.pojo.Product;
+import com.ruoyi.basic.pojo.ProductModel;
 import com.ruoyi.basic.utils.FileUtil;
 import com.ruoyi.common.enums.FileNameType;
 import com.ruoyi.common.enums.SaleEnum;
@@ -27,8 +34,9 @@
 import com.ruoyi.framework.security.LoginUser;
 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.mapper.ProductionProductInputMapper;
+import com.ruoyi.production.mapper.ProductionProductMainMapper;
+import com.ruoyi.production.mapper.ProductionProductOutputMapper;
 import com.ruoyi.production.service.ProductionProductMainService;
 import com.ruoyi.project.system.domain.SysDept;
 import com.ruoyi.project.system.domain.SysUser;
@@ -38,13 +46,18 @@
 import com.ruoyi.purchase.mapper.PurchaseReturnOrderProductsMapper;
 import com.ruoyi.quality.mapper.QualityInspectMapper;
 import com.ruoyi.sales.dto.*;
-import com.ruoyi.sales.mapper.*;
-import com.ruoyi.sales.pojo.*;
+import com.ruoyi.sales.mapper.CommonFileMapper;
+import com.ruoyi.sales.mapper.SalesLedgerMapper;
+import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
+import com.ruoyi.sales.mapper.ShippingInfoMapper;
+import com.ruoyi.sales.pojo.CommonFile;
+import com.ruoyi.sales.pojo.SalesLedger;
+import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import com.ruoyi.sales.pojo.ShippingInfo;
 import com.ruoyi.sales.service.ISalesLedgerService;
 import com.ruoyi.sales.vo.SalesLedgerVo;
 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;
@@ -53,17 +66,15 @@
 import org.springframework.data.redis.core.script.DefaultRedisScript;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.interceptor.TransactionAspectSupport;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
 import org.springframework.web.multipart.MultipartFile;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 
-import java.io.IOException;
 import java.io.InputStream;
 import java.lang.reflect.Field;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
-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.YearMonth;
@@ -86,26 +97,28 @@
     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 static final String IMPORT_DEFAULT_VALUE = "/";
+    /** 瀵煎叆鑷姩鏂板浜у搧澶х被鏃舵寕杞界殑椤剁骇浜у搧鑺傜偣鍚嶇О */
+    private static final String FINISHED_PRODUCT_NAME = "鎴愬搧";
     private final SalesLedgerMapper salesLedgerMapper;
     private final CustomerMapper customerMapper;
+    private final CustomerUserMapper customerUserMapper;
     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 ProductionProductMainMapper productionProductMainMapper;
     private final ProductionProductOutputMapper productionProductOutputMapper;
     private final ProductionProductInputMapper productionProductInputMapper;
     private final QualityInspectMapper qualityInspectMapper;
     private final RedisTemplate<String, String> redisTemplate;
     private final FileUtil fileUtil;
+    private final AccountInvoiceApplicationMapper accountInvoiceApplicationMapper;
+    private final AccountSalesCollectionMapper accountSalesCollectionMapper;
 
     @Autowired
     private SysDeptMapper sysDeptMapper;
@@ -176,10 +189,6 @@
         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());
             // 鍙戣揣淇℃伅
@@ -280,51 +289,37 @@
 
     @Override
     public List<MonthlyAmountDto> getAmountHalfYear(Integer type) {
-
         LocalDate now = LocalDate.now();
         List<MonthlyAmountDto> result = new ArrayList<>();
-
         for (int i = 5; i >= 0; i--) {
             YearMonth yearMonth = YearMonth.from(now.minusMonths(i));
-            LocalDateTime startTime = yearMonth.atDay(1).atStartOfDay();
-            LocalDateTime endTime = yearMonth.atEndOfMonth().atTime(23, 59, 59);
-
-            //  鍥炴閲戦
-            LambdaQueryWrapper<ReceiptPayment> receiptPaymentQuery = new LambdaQueryWrapper<>();
-            receiptPaymentQuery
-                    .ge(ReceiptPayment::getCreateTime, startTime)
-                    .le(ReceiptPayment::getCreateTime, endTime);
-
-            List<ReceiptPayment> receiptPayments =
-                    receiptPaymentMapper.selectList(receiptPaymentQuery);
-
-            BigDecimal receiptAmount = receiptPayments.stream()
-                    .map(ReceiptPayment::getReceiptPaymentAmount)
-                    .filter(Objects::nonNull)
-                    .reduce(BigDecimal.ZERO, BigDecimal::add);
-
-            //  寮�绁ㄩ噾棰�
-            LambdaQueryWrapper<InvoiceLedger> invoiceLedgerQuery = new LambdaQueryWrapper<>();
-            invoiceLedgerQuery
-                    .ge(InvoiceLedger::getCreateTime, startTime)
-                    .le(InvoiceLedger::getCreateTime, endTime);
-
-            List<InvoiceLedger> invoiceLedgers =
-                    invoiceLedgerMapper.selectList(invoiceLedgerQuery);
-
-            BigDecimal invoiceAmount = invoiceLedgers.stream()
-                    .map(InvoiceLedger::getInvoiceTotal)
-                    .filter(Objects::nonNull)
-                    .reduce(BigDecimal.ZERO, BigDecimal::add);
-
+            LocalDate startTime = yearMonth.atDay(1);
+            LocalDate endTime = yearMonth.atEndOfMonth();
             MonthlyAmountDto dto = new MonthlyAmountDto();
             dto.setMonth(yearMonth.format(DateTimeFormatter.ofPattern("yyyy-MM")));
-            dto.setReceiptAmount(receiptAmount);
-            dto.setInvoiceAmount(invoiceAmount);
-
+            //鍥炴閲戦
+            List<AccountSalesCollection> accountSalesCollections = accountSalesCollectionMapper.selectList(new LambdaQueryWrapper<AccountSalesCollection>()
+                    .between(AccountSalesCollection::getCollectionDate, startTime, endTime));
+            BigDecimal totalIncome = Optional.of(
+                    accountSalesCollections.stream()
+                            .map(AccountSalesCollection::getCollectionAmount)
+                            .filter(Objects::nonNull)
+                            .reduce(BigDecimal.ZERO, BigDecimal::add)
+            ).orElse(BigDecimal.ZERO);
+            dto.setReceiptAmount(totalIncome);
+            //寮�绁ㄩ噾棰�
+            List<AccountInvoiceApplication> accountInvoiceApplications = accountInvoiceApplicationMapper.selectList(new LambdaQueryWrapper<AccountInvoiceApplication>()
+                            .eq(AccountInvoiceApplication::getStatus,1)
+                    .between(AccountInvoiceApplication::getApplyDate, startTime, endTime));
+            BigDecimal totalInvoiceAmount = Optional.of(
+                    accountInvoiceApplications.stream()
+                            .map(AccountInvoiceApplication::getInvoiceAmount)
+                            .filter(Objects::nonNull)
+                            .reduce(BigDecimal.ZERO, BigDecimal::add)
+            ).orElse(BigDecimal.ZERO);
+            dto.setInvoiceAmount(totalInvoiceAmount);
             result.add(dto);
         }
-
         return result;
     }
 
@@ -347,16 +342,13 @@
             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,
-                    salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getCustomerName).collect(Collectors.toList())));
-//            // 瑙勬牸鍨嬪彿鏁版嵁
-//            List<ProductModel> productModels = productModelMapper.selectList(new LambdaQueryWrapper<ProductModel>().in(ProductModel::getModel,
-//                    salesLedgerProductImportDtoList.stream().map(SalesLedgerImportDto::getSpecificationModel).collect(Collectors.toList())));
-//            // 浜у搧澶х被鏁版嵁
-//            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();
+            // 瀹㈡埛鏁版嵁 - 鍙傝�� listPage 鏌ヨ绉佹捣瀹㈡埛锛坱ype = 0锛�
+            // type = 0锛堢娴峰鎴凤級鎴栬�� type = 1锛堝叕娴峰鎴凤級涓斿凡琚垎閰嶏紝骞朵笖鏄嚜宸遍鐢ㄣ�佽嚜宸卞垱寤烘垨鑰呭叡浜粰鑷繁鐨勫鎴�
+            // 瀹㈡埛涓嶅瓨鍦ㄦ椂鑷姩鏂板骞舵寕鍒拌嚜宸卞悕涓嬶紝鍏捣瀹㈡埛鑷姩棰嗙敤/鍏变韩缁欒嚜宸�
+            Long loginUserId = loginUser.getUser().getUserId();
+            Map<String, Customer> customerCache = new HashMap<>();
+            // 浜у搧澶х被銆佽鏍煎瀷鍙风紦瀛橈紝key = 浜у搧澶х被 + | + 瑙勬牸鍨嬪彿锛屼笉瀛樺湪鏃惰嚜鍔ㄦ柊澧�
+            Map<String, ProductModel> productModelCache = new HashMap<>();
             // 褰曞叆浜烘暟鎹�
             List<SysUser> sysUsers = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>().in(SysUser::getNickName,
                     salesLedgerImportDtoList.stream().map(SalesLedgerImportDto::getEntryPerson).collect(Collectors.toList())));
@@ -367,19 +359,22 @@
                 if (salesLedger1 != null) {
                     continue;
                 }
+
+                // 鍒ゆ柇涓氬姟鍛樻槸鍚﹀瓨鍦�
+                SysUser salesman = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>()
+                        .eq(SysUser::getNickName, salesLedgerImportDto.getSalesman()));
+                if (salesman == null) {
+                    throw new RuntimeException("涓氬姟鍛�:" + salesLedgerImportDto.getSalesman() + "涓嶅瓨鍦紒");
+                }
                 SalesLedger salesLedger = new SalesLedger();
                 BeanUtils.copyProperties(salesLedgerImportDto, salesLedger);
                 salesLedger.setExecutionDate(DateUtils.toLocalDate(salesLedgerImportDto.getExecutionDate()));
                 salesLedger.setDeliveryDate(DateUtils.toLocalDate(salesLedgerImportDto.getDeliveryDate()));
-                // 閫氳繃瀹㈡埛鍚嶇О鏌ヨ瀹㈡埛ID锛屽鎴峰悎鍚屽彿
-                Optional<Customer> customerOptional = customers.stream()
-                        .filter(customer -> customer.getCustomerName().equals(salesLedger.getCustomerName()))
-                        .findFirst();
-                if (customerOptional.isEmpty()) {
-                    throw new RuntimeException("瀹㈡埛:" + salesLedger.getCustomerName() + "涓嶅瓨鍦紒");
-                }
-                salesLedger.setCustomerId(customerOptional.get().getId());
-                salesLedger.setCustomerContractNo(customerOptional.get().getTaxpayerIdentificationNumber());
+                // 閫氳繃瀹㈡埛鍚嶇О鏌ヨ瀹㈡埛ID锛屽鎴峰悎鍚屽彿锛屽鎴蜂笉瀛樺湪鏃惰嚜鍔ㄦ柊澧�
+                Customer customer = resolveImportCustomer(salesLedger.getCustomerName(), loginUserId,
+                        loginUser.getNickName(), customerCache);
+                salesLedger.setCustomerId(customer.getId());
+                salesLedger.setCustomerContractNo(customer.getTaxpayerIdentificationNumber());
                 Long aLong = sysUsers.stream()
                         .filter(sysUser -> sysUser.getNickName().equals(salesLedger.getEntryPerson()))
                         .findFirst()
@@ -406,33 +401,20 @@
                     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());
-                    // 鏍¢獙浜у搧瑙勬牸鏄惁瀛樺湪
-                    Optional<Map<String, Object>> productModelOptional = list.stream()
-                            .filter(map -> Objects.equals(map.get("productName"), salesLedgerProduct.getProductCategory()) && Objects.equals(map.get("model"), salesLedgerProduct.getSpecificationModel()))
-                            .findFirst();
-                    if (productModelOptional.isEmpty()) {
-                        throw new RuntimeException("浜у搧澶х被:" + salesLedgerProduct.getProductCategory() + ",瑙勬牸鍨嬪彿:" + salesLedgerProduct.getSpecificationModel() + "涓嶅瓨鍦紒");
+                    salesLedgerProduct.setTaxExclusiveTotalPrice(salesLedgerProduct.getTaxInclusiveTotalPrice().divide(new BigDecimal(1).add(salesLedgerProduct.getTaxRate().divide(new BigDecimal(100))), 6, RoundingMode.HALF_UP));
+                    // 鏍¢獙浜у搧瑙勬牸鏄惁瀛樺湪锛屼骇鍝佸ぇ绫汇�佽鏍煎瀷鍙蜂笉瀛樺湪鏃惰嚜鍔ㄦ柊澧�
+                    ProductModel productModel = resolveImportProductModel(salesLedgerProduct.getProductCategory(),
+                            salesLedgerProduct.getSpecificationModel(), salesLedgerProduct.getUnit(), productModelCache);
+                    salesLedgerProduct.setProductModelId(productModel.getId());
+                    salesLedgerProduct.setProductId(productModel.getProductId());
+                    // 瑙勬牸鍨嬪彿涓虹┖鏃跺彇浜у搧澶х被锛屽崟浣嶄负绌烘椂鍙栬鏍煎瀷鍙蜂笂鐨勫崟浣�
+                    salesLedgerProduct.setSpecificationModel(productModel.getModel());
+                    if (StringUtils.isEmpty(salesLedgerProduct.getUnit())) {
+                        salesLedgerProduct.setUnit(productModel.getUnit());
                     }
-                    Map<String, Object> productModelMap = productModelOptional.get();
-                    salesLedgerProduct.setProductModelId(Long.parseLong(productModelMap.get("modelId").toString()));
-                    salesLedgerProduct.setProductId(Long.parseLong(productModelMap.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());
                     salesLedgerProduct.setIsProduction(salesLedgerProductImportDto.getIsProduction() == 1);
                     salesLedgerProductMapper.insert(salesLedgerProduct);
                     // 娣诲姞鐢熶骇鏁版嵁
@@ -443,8 +425,191 @@
             return AjaxResult.success("瀵煎叆鎴愬姛");
         } catch (Exception e) {
             e.printStackTrace();
+            // 瀵煎叆杩囩▼涓細鑷姩鏂板瀹㈡埛銆佷骇鍝佸ぇ绫汇�佽鏍煎瀷鍙凤紝澶辫触鏃堕渶瑕佸洖婊氾紝閬垮厤娈嬬暀鑴忔暟鎹�
+            if (TransactionSynchronizationManager.isActualTransactionActive()) {
+                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+            }
             return AjaxResult.error("瀵煎叆澶辫触锛�" + e.getMessage());
         }
+    }
+
+    /**
+     * 瀵煎叆鏃惰幏鍙栧鎴凤紝瀹㈡埛涓嶅瓨鍦ㄥ垯鑷姩鏂板骞舵寕鍒板綋鍓嶇櫥褰曚汉鍚嶄笅
+     * <p>
+     * 1銆佸綋鍓嶇櫥褰曚汉鍙敤鐨勫鎴凤紙绉佹捣锛屾垨鍏捣宸插垎閰嶄笖鑷繁棰嗙敤/鍒涘缓/鍏变韩锛夛細鐩存帴浣跨敤锛�
+     * 2銆佸悓鍚嶅叕娴峰鎴锋湭鍒嗛厤锛氶鐢ㄥ埌鑷繁鍚嶄笅锛�
+     * 3銆佸悓鍚嶅叕娴峰鎴峰凡鍒嗛厤缁欏埆浜猴細鍏变韩缁欒嚜宸憋紱
+     * 4銆佸悓鍚嶅鎴峰湪鍒汉绉佹捣锛氭姤閿欙紝涓嶆柊寤猴紱
+     * 5銆佸鎴蜂笉瀛樺湪锛氭柊澧炵娴峰鎴锋寕鍒拌嚜宸卞悕涓嬶紝绾崇◣浜鸿瘑鍒彿銆佺數璇濈瓑淇℃伅濉� "/"銆�
+     */
+    private Customer resolveImportCustomer(String customerName, Long loginUserId, String nickName,
+                                           Map<String, Customer> customerCache) {
+        String name = StringUtils.trim(customerName);
+        if (StringUtils.isEmpty(name)) {
+            throw new RuntimeException("瀹㈡埛鍚嶇О涓嶈兘涓虹┖锛�");
+        }
+        Customer cachedCustomer = customerCache.get(name);
+        if (cachedCustomer != null) {
+            return cachedCustomer;
+        }
+        // 褰撳墠鐧诲綍浜哄彲鐢ㄧ殑瀹㈡埛
+        Customer customer = customerMapper.selectOne(new QueryWrapper<Customer>()
+                .eq("customer_name", name)
+                .and(wrapper -> wrapper.eq("type", 0)
+                        .or(wrapper2 -> wrapper2.eq("type", 1).eq("is_assigned", 1)))
+                .and(wrapper -> wrapper.eq("usage_user", loginUserId)
+                        .or(wrapper2 -> wrapper2.eq("create_user", loginUserId)
+                                .or(wrapper3 -> wrapper3.exists("select 1 from customer_user cu where cu.customer_id = customer.id and cu.user_id = " + loginUserId))))
+                .last("limit 1"));
+        if (customer == null) {
+            customer = claimOrCreateImportCustomer(name, loginUserId, nickName);
+        }
+        customerCache.put(name, customer);
+        return customer;
+    }
+
+    /**
+     * 鍚屽悕瀹㈡埛涓嶅睘浜庡綋鍓嶇櫥褰曚汉鏃剁殑澶勭悊锛氬叕娴锋湭鍒嗛厤鐨勯鐢ㄥ埌鑷繁鍚嶄笅锛屽叕娴峰凡鍒嗛厤鐨勫叡浜粰鑷繁锛�
+     * 鍦ㄥ埆浜虹娴风殑鐩存帴鎶ラ敊锛岄兘涓嶅瓨鍦ㄥ垯鏂板瀹㈡埛
+     */
+    private Customer claimOrCreateImportCustomer(String customerName, Long loginUserId, String nickName) {
+        List<Customer> sameNameCustomers = customerMapper.selectList(new QueryWrapper<Customer>()
+                .eq("customer_name", customerName)
+                .orderByAsc("id"));
+        // 鍏捣鏈垎閰嶅鎴凤紝棰嗙敤鍒拌嚜宸卞悕涓�
+        Optional<Customer> publicUnassigned = sameNameCustomers.stream()
+                .filter(item -> Objects.equals(item.getType(), 1)
+                        && (item.getIsAssigned() == null || item.getIsAssigned() == 0))
+                .findFirst();
+        if (publicUnassigned.isPresent()) {
+            Customer customer = publicUnassigned.get();
+            customer.setIsAssigned(1);
+            customer.setUsageStatus(1L);
+            customer.setUsageUser(loginUserId);
+            customerMapper.updateById(customer);
+            return customer;
+        }
+        // 鍏捣宸插垎閰嶇粰鍒汉鐨勫鎴凤紝鍏变韩缁欒嚜宸�
+        Optional<Customer> publicAssigned = sameNameCustomers.stream()
+                .filter(item -> Objects.equals(item.getType(), 1) && Objects.equals(item.getIsAssigned(), 1))
+                .findFirst();
+        if (publicAssigned.isPresent()) {
+            Customer customer = publicAssigned.get();
+            CustomerUser customerUser = new CustomerUser();
+            customerUser.setCustomerId(customer.getId());
+            customerUser.setUserId(loginUserId);
+            customerUserMapper.insert(customerUser);
+            return customer;
+        }
+        // 鍓╀笅鐨勯兘鏄埆浜虹殑绉佹捣瀹㈡埛
+        if (!sameNameCustomers.isEmpty()) {
+            throw new RuntimeException("瀹㈡埛:" + customerName + "宸插湪鍏朵粬浜虹娴蜂腑锛屾棤娉曞鍏ワ紒");
+        }
+        // 瀹㈡埛涓嶅瓨鍦紝鏂板绉佹捣瀹㈡埛骞舵寕鍒拌嚜宸卞悕涓�
+        Customer customer = new Customer();
+        customer.setCustomerName(customerName);
+        customer.setCustomerType(IMPORT_DEFAULT_VALUE);
+        customer.setTaxpayerIdentificationNumber(IMPORT_DEFAULT_VALUE);
+        customer.setCompanyAddress(IMPORT_DEFAULT_VALUE);
+        customer.setCompanyPhone(IMPORT_DEFAULT_VALUE);
+        customer.setContactPerson(IMPORT_DEFAULT_VALUE);
+        customer.setContactPhone(IMPORT_DEFAULT_VALUE);
+        customer.setBasicBankAccount(IMPORT_DEFAULT_VALUE);
+        customer.setBankAccount(IMPORT_DEFAULT_VALUE);
+        customer.setBankCode(IMPORT_DEFAULT_VALUE);
+        customer.setMaintainer(nickName);
+        customer.setMaintenanceTime(new Date());
+        // 绉佹捣瀹㈡埛锛岄鐢ㄤ汉涓哄綋鍓嶇櫥褰曚汉
+        customer.setType(0);
+        customer.setIsAssigned(0);
+        customer.setUsageStatus(1L);
+        customer.setUsageUser(loginUserId);
+        customerMapper.insert(customer);
+        return customer;
+    }
+
+    /**
+     * 瀵煎叆鏃惰幏鍙栬鏍煎瀷鍙凤紝浜у搧澶х被銆佽鏍煎瀷鍙蜂笉瀛樺湪鍒欒嚜鍔ㄦ柊澧�
+     * <p>
+     * 瑙勬牸鍨嬪彿涓虹┖鏃跺彇浜у搧澶х被浣滀负瑙勬牸鍨嬪彿锛涗骇鍝佸ぇ绫讳笉瀛樺湪鏃舵寕鍒伴《绾�"鎴愬搧"鑺傜偣涓嬶紱
+     * 鏂板瑙勬牸鍨嬪彿鏃舵寜"瑙勬牸鍨嬪彿 + 瑙勬牸ID + _ + 涓変綅娴佹按鍙�"鐢熸垚浜у搧缂栫爜
+     */
+    private ProductModel resolveImportProductModel(String productCategory, String specificationModel, String unit,
+                                                   Map<String, ProductModel> productModelCache) {
+        String category = StringUtils.trim(productCategory);
+        if (StringUtils.isEmpty(category)) {
+            throw new RuntimeException("浜у搧澶х被涓嶈兘涓虹┖锛�");
+        }
+        // 瑙勬牸鍨嬪彿涓虹┖鏃跺彇浜у搧澶х被褰撲骇鍝佽鏍�
+        String model = StringUtils.trim(specificationModel);
+        if (StringUtils.isEmpty(model)) {
+            model = category;
+        }
+        String cacheKey = category + "|" + model;
+        ProductModel cachedProductModel = productModelCache.get(cacheKey);
+        if (cachedProductModel != null) {
+            return cachedProductModel;
+        }
+        // 浜у搧澶х被涓嶅瓨鍦ㄥ垯鏂板鍒伴《绾�"鎴愬搧"鑺傜偣涓�
+        Product product = productMapper.selectOne(new LambdaQueryWrapper<Product>()
+                .eq(Product::getProductName, category)
+                .orderByAsc(Product::getId)
+                .last("limit 1"));
+        if (product == null) {
+            product = new Product();
+            product.setParentId(getFinishedProductId());
+            product.setProductName(category);
+            productMapper.insert(product);
+        }
+        // 瑙勬牸鍨嬪彿涓嶅瓨鍦ㄥ垯鏂板
+        ProductModel productModel = productModelMapper.selectOne(new LambdaQueryWrapper<ProductModel>()
+                .eq(ProductModel::getProductId, product.getId())
+                .eq(ProductModel::getModel, model)
+                .orderByAsc(ProductModel::getId)
+                .last("limit 1"));
+        if (productModel == null) {
+            productModel = new ProductModel();
+            productModel.setProductId(product.getId());
+            productModel.setModel(model);
+            productModel.setUnit(StringUtils.isEmpty(unit) ? IMPORT_DEFAULT_VALUE : StringUtils.trim(unit));
+            productModelMapper.insert(productModel);
+            // 浜у搧缂栫爜渚濊禆鑷鐨勮鏍糏D锛屾彃鍏ュ悗鍐嶅洖濉�
+            productModel.setProductCode(generateProductCode(productModel.getModel(), productModel.getId()));
+            productModelMapper.updateById(productModel);
+        }
+        productModelCache.put(cacheKey, productModel);
+        return productModel;
+    }
+
+    /**
+     * 鏌ヨ椤剁骇"鎴愬搧"浜у搧鑺傜偣锛堜骇鍝佸悕绉颁负鎴愬搧涓旂埗ID涓虹┖锛�
+     */
+    private Long getFinishedProductId() {
+        Product finishedProduct = productMapper.selectOne(new LambdaQueryWrapper<Product>()
+                .eq(Product::getProductName, FINISHED_PRODUCT_NAME)
+                .isNull(Product::getParentId)
+                .orderByAsc(Product::getId)
+                .last("limit 1"));
+        if (finishedProduct == null) {
+            throw new RuntimeException("浜у搧妗f涓笉瀛樺湪椤剁骇鑺傜偣:" + FINISHED_PRODUCT_NAME + "锛屾棤娉曡嚜鍔ㄦ柊澧炰骇鍝佸ぇ绫伙紒");
+        }
+        return finishedProduct.getId();
+    }
+
+    /**
+     * 鐢熸垚浜у搧缂栫爜锛岃鍒欙細瑙勬牸鍨嬪彿 + 瑙勬牸ID + _ + 涓変綅娴佹按鍙凤紝缂栫爜宸插瓨鍦ㄦ椂娴佹按鍙烽�掑
+     */
+    private String generateProductCode(String model, Long productModelId) {
+        String prefix = model + productModelId + "_";
+        for (int sequence = 1; sequence < 1000; sequence++) {
+            String productCode = prefix + String.format("%03d", sequence);
+            Long count = productModelMapper.selectCount(new LambdaQueryWrapper<ProductModel>()
+                    .eq(ProductModel::getProductCode, productCode));
+            if (count == null || count == 0) {
+                return productCode;
+            }
+        }
+        throw new RuntimeException("瑙勬牸鍨嬪彿:" + model + "鐨勪骇鍝佺紪鐮佹祦姘村彿宸茶秴鍑鸿寖鍥达紒");
     }
 
     @Override
@@ -466,11 +631,7 @@
             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.setRegister(SecurityUtils.getLoginUser().getUser().getNickName());
                 product.setRegisterDate(LocalDateTime.now());
                 // 鍙戣揣淇℃伅
                 ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>()
@@ -543,29 +704,8 @@
             salesLedgerProductMapper.deleteBatchIds(productIds);
         }
 
-        LambdaQueryWrapper<InvoiceRegistrationProduct> wrapper = new LambdaQueryWrapper<>();
-        wrapper.in(InvoiceRegistrationProduct::getSalesLedgerId, idList);
-        List<InvoiceRegistrationProduct> invoiceRegistrationProducts = invoiceRegistrationProductMapper.selectList(wrapper);
         List<Integer> invoiceLedgerIds = new ArrayList<>();
-        if (CollectionUtils.isNotEmpty(invoiceRegistrationProducts)) {
-            LambdaQueryWrapper<InvoiceLedger> wrapperOne = new LambdaQueryWrapper<>();
-            wrapperOne.in(InvoiceLedger::getInvoiceRegistrationProductId, invoiceRegistrationProducts.stream().map(InvoiceRegistrationProduct::getId).collect(Collectors.toList()));
-            List<InvoiceLedger> invoiceLedgers = invoiceLedgerMapper.selectList(wrapperOne);
-            if (CollectionUtils.isNotEmpty(invoiceLedgers)) {
-                invoiceLedgerIds = invoiceLedgers.stream().map(InvoiceLedger::getId).collect(Collectors.toList());
-            }
-            invoiceLedgerMapper.delete(wrapperOne);
-        }
-        invoiceRegistrationProductMapper.delete(wrapper);
-        LambdaQueryWrapper<InvoiceRegistration> wrapperTwo = new LambdaQueryWrapper<>();
-        wrapperTwo.in(InvoiceRegistration::getSalesLedgerId, idList);
-        invoiceRegistrationMapper.delete(wrapperTwo);
 
-        if (CollectionUtils.isNotEmpty(invoiceLedgerIds)) {
-            LambdaQueryWrapper<ReceiptPayment> wrapperTree = new LambdaQueryWrapper<>();
-            wrapperTree.in(ReceiptPayment::getInvoiceLedgerId, invoiceLedgerIds);
-            receiptPaymentMapper.delete(wrapperTree);
-        }
         // 鍒犻櫎鍙戣揣鍙拌处璁板綍
         List<ShippingInfo> shippingInfos = shippingInfoMapper.selectList(new LambdaQueryWrapper<ShippingInfo>()
                 .in(ShippingInfo::getSalesLedgerId, idList));
@@ -600,9 +740,16 @@
         SalesLedger salesLedger = convertToEntity(salesLedgerDto);
         salesLedger.setCustomerName(customer.getCustomerName());
         salesLedger.setTenantId(customer.getTenantId());
+        // 褰曞叆浜猴細濡傛灉鏈紶鍒欎娇鐢ㄥ綋鍓嶇櫥褰曠敤鎴�
+        if (StringUtils.isEmpty(salesLedger.getEntryPerson())) {
+            salesLedger.setEntryPerson(String.valueOf(SecurityUtils.getUserId()));
+        }
         // 3. 鏂板鎴栨洿鏂颁富琛�
         if (salesLedger.getId() == null) {
-            String contractNo = generateSalesContractNo();
+            String contractNo = salesLedger.getSalesContractNo();
+            if (StringUtils.isEmpty(contractNo)) {
+                contractNo = generateSalesContractNo(salesLedgerDto.getEntryDate());
+            }
             salesLedger.setSalesContractNo(contractNo);
             salesLedgerMapper.insert(salesLedger);
         } else {
@@ -650,9 +797,6 @@
         if (!insertList.isEmpty()) {
             for (SalesLedgerProduct salesLedgerProduct : insertList) {
                 salesLedgerProduct.setType(type.getCode());
-                salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getQuantity());
-                salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxInclusiveTotalPrice());
-                salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice());
                 salesLedgerProductMapper.insert(salesLedgerProduct);
                 // 娣诲姞鐢熶骇鏁版嵁
                 salesLedgerProductServiceImpl.addProductionData(salesLedgerProduct);
@@ -667,8 +811,8 @@
     }
 
     @Transactional(readOnly = true)
-    public String generateSalesContractNo() {
-        LocalDate currentDate = LocalDate.now();
+    public String generateSalesContractNo(Date entryDate) {
+        LocalDate currentDate = entryDate != null ? DateUtils.toLocalDate(entryDate) : LocalDate.now();
         String datePart = currentDate.format(DateTimeFormatter.BASIC_ISO_DATE);
         String lockKey = LOCK_PREFIX + datePart;
         String lockValue = Thread.currentThread().getId() + "-" + System.nanoTime(); // 鍞竴鏍囪瘑閿佹寔鏈夎��

--
Gitblit v1.9.3