From 481d8165f26fc7e37f0e87f6444ac0340bb563a3 Mon Sep 17 00:00:00 2001
From: xiaoyi <908147524@qq.com>
Date: 星期二, 03 十一月 2026 18:53:22 +0800
Subject: [PATCH] fix: 移植长辉已验证的四类接口 500/体验问题(不含物料颜色字段)

---
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java |  120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 112 insertions(+), 8 deletions(-)

diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java
index baec481..14430d4 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java
@@ -2,10 +2,13 @@
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
+import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesImportExcelVO;
+import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesImportRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesPageReqVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesSaveReqVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesShippingReqVO;
@@ -14,26 +17,34 @@
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDetailDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO;
 import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesMapper;
+import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesLineMapper;
 import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductSalesStatusEnum;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmSalesNoticeStatusEnum;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmStockReserveBizTypeEnum;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum;
-import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
 import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService;
 import cn.iocoder.yudao.module.mes.service.wm.salesnotice.MesWmSalesNoticeService;
 import cn.iocoder.yudao.module.mes.service.wm.stockreserve.MesWmStockReserveService;
 import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService;
 import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO;
+import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcService;
 import cn.iocoder.yudao.module.erp.api.sale.ErpSaleOrderApi;
+import cn.iocoder.yudao.module.erp.api.sale.enums.ErpSaleOrderOutStatusEnum;
 import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
@@ -42,21 +53,24 @@
 /**
  * MES 閿�鍞嚭搴撳崟 Service 瀹炵幇绫�
  *
- * @author 鑺嬮亾婧愮爜
+ * @author 瓒呯骇绠$悊鍛�
  */
 @Service
 @Validated
+@Slf4j
 public class MesWmProductSalesServiceImpl implements MesWmProductSalesService {
 
     @Resource
     private MesWmProductSalesMapper productSalesMapper;
+    @Resource
+    private MesWmProductSalesLineMapper productSalesLineMapper;
 
     @Resource
     private MesWmProductSalesLineService productSalesLineService;
     @Resource
     private MesWmProductSalesDetailService productSalesDetailService;
     @Resource
-    private MesMdClientService clientService;
+    private CrmCustomerApi customerApi;
     @Resource
     private MesWmSalesNoticeService salesNoticeService;
     @Resource
@@ -65,6 +79,9 @@
     private MesWmMaterialStockService materialStockService;
     @Resource
     private MesWmStockReserveService stockReserveService;
+    @Resource
+    @Lazy
+    private MesQcOqcService oqcService;
 
     @Resource
     private ErpSaleOrderApi saleOrderApi;
@@ -113,7 +130,8 @@
 
     @Override
     public PageResult<MesWmProductSalesDO> getProductSalesPage(MesWmProductSalesPageReqVO pageReqVO) {
-        return productSalesMapper.selectPage(pageReqVO);
+        List<Long> permittedClientIds = customerApi.getPermittedCustomerIds();
+        return productSalesMapper.selectPage(pageReqVO, permittedClientIds);
     }
 
     @Override
@@ -133,10 +151,26 @@
             }
         }
 
+        // 鑾峰彇鍑哄簱鍗曚俊鎭�
+        MesWmProductSalesDO sales = productSalesMapper.selectById(id);
+
         // 妫�鏌ユ墍鏈夎鐨� oqcCheckFlag锛氬鏋滄湁闇�瑕� OQC 妫�楠岀殑琛岋紝杩涘叆寰呮娴嬬姸鎬�
         boolean needOqc = CollectionUtils.anyMatch(lines,
                 line -> Boolean.TRUE.equals(line.getOqcCheckFlag()));
         if (needOqc) {
+            // 涓洪渶瑕� OQC 妫�楠屼笖灏氭湭鍒涘缓妫�楠屽崟鐨勬槑缁嗗垱寤� OQC 妫�楠屽崟
+            List<MesWmProductSalesLineDO> oqcLines = CollectionUtils.filterList(lines,
+                    line -> Boolean.TRUE.equals(line.getOqcCheckFlag()) && line.getOqcId() == null);
+            for (MesWmProductSalesLineDO line : oqcLines) {
+                // 鐩存帴璋冪敤锛岃寮傚父鎶涘嚭锛屼繚璇佹暟鎹竴鑷存��
+                Long oqcId = oqcService.createOqcFromProductSales(
+                        sales.getId(), line, sales.getCode(), sales.getClientId());
+                // 鏇存柊鍑哄簱鏄庣粏鐨� oqcId
+                productSalesLineMapper.updateById(new MesWmProductSalesLineDO()
+                        .setId(line.getId())
+                        .setOqcId(oqcId));
+            }
+
             // 鎵归噺鍒濆鍖� OQC 琛岀殑璐ㄩ噺鐘舵�佷负"寰呮楠�"
             List<Long> oqcLineIds = convertList(
                     CollectionUtils.filterList(lines, line -> Boolean.TRUE.equals(line.getOqcCheckFlag())),
@@ -213,6 +247,12 @@
         // 鎵ц鎷h揣锛堝緟鎷h揣 鈫� 寰呭~鍐欒繍鍗曪級
         productSalesMapper.updateById(new MesWmProductSalesDO()
                 .setId(id).setStatus(MesWmProductSalesStatusEnum.SHIPPING.getStatus()));
+
+        // 鍥炲啓 ERP 閿�鍞鍗曞嚭搴撶姸鎬佷负"閮ㄥ垎鍑哄簱"锛堣〃绀哄凡鎷h揣/鍗犵敤锛�
+        if (sales.getSaleOrderId() != null) {
+            saleOrderApi.updateOrderOutStatusTo(sales.getSaleOrderId(),
+                    ErpSaleOrderOutStatusEnum.PART_OUT.getStatus());
+        }
     }
 
     @Override
@@ -251,13 +291,30 @@
         productSalesMapper.updateById(new MesWmProductSalesDO()
                 .setId(id).setStatus(MesWmProductSalesStatusEnum.FINISHED.getStatus()));
 
-        // 5. 鏇存柊鍏宠仈鐨勫彂璐ч�氱煡鍗曠姸鎬�
+        // 5. 鏇存柊鍏宠仈鐨勫彂璐ч�氱煡鍗曞嚭搴撴暟閲忓拰鐘舵��
         if (sales.getNoticeId() != null) {
-            salesNoticeService.finishSalesNotice(sales.getNoticeId());
+            updateSalesNoticeOutCount(sales);
         }
 
         // 6. 鍥炲啓 ERP 閿�鍞鍗曠殑鍑哄簱鏁伴噺鍜岀姸鎬�
         updateErpSaleOrderOutCount(sales);
+    }
+
+    /**
+     * 鏇存柊鍙戣揣閫氱煡鍗曠殑鍑哄簱鏁伴噺鍜岀姸鎬�
+     */
+    private void updateSalesNoticeOutCount(MesWmProductSalesDO sales) {
+        // 鑾峰彇鍑哄簱鍗曡
+        List<MesWmProductSalesLineDO> lines = productSalesLineService.getProductSalesLineListBySalesId(sales.getId());
+        if (CollUtil.isEmpty(lines)) {
+            return;
+        }
+        // 閬嶅巻琛岋紝鎸� noticeLineId 鏇存柊鍑哄簱鏁伴噺
+        for (MesWmProductSalesLineDO line : lines) {
+            if (line.getNoticeLineId() != null && line.getQuantity() != null) {
+                salesNoticeService.updateSalesNoticeLineOutCount(line.getNoticeLineId(), line.getQuantity());
+            }
+        }
     }
 
     /**
@@ -299,7 +356,8 @@
                 .setBatchId(detail.getBatchId()).setBatchCode(detail.getBatchCode())
                 .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId())
                 .setBizType(MesBizTypeConstants.WM_PRODUCT_SALES).setBizId(sales.getId())
-                .setBizCode(sales.getCode()).setBizLineId(detail.getLineId())));
+                .setBizCode(sales.getCode()).setBizLineId(detail.getLineId())
+                .setMaterialStockId(detail.getMaterialStockId()))); // 鎸囧畾搴撳瓨璁板綍ID锛岄伩鍏嶉噸鏂板尮閰�
     }
 
     @Override
@@ -341,7 +399,7 @@
         // 鏍¢獙缂栫爜鍞竴
         validateCodeUnique(id, reqVO.getCode());
         // 鏍¢獙瀹㈡埛瀛樺湪
-        clientService.validateClientExistsAndEnable(reqVO.getClientId());
+        customerApi.validateCustomer(reqVO.getClientId());
         // 鏍¢獙鍙戣揣閫氱煡鍗�
         if (reqVO.getNoticeId() != null) {
             MesWmSalesNoticeDO notice = salesNoticeService.validateSalesNoticeExists(reqVO.getNoticeId());
@@ -389,4 +447,50 @@
         productSalesMapper.updateById(new MesWmProductSalesDO().setId(id).setStatus(status));
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public MesWmProductSalesImportRespVO importProductSalesList(List<MesWmProductSalesImportExcelVO> importList, boolean updateSupport) {
+        if (CollUtil.isEmpty(importList)) {
+            throw exception(WM_PRODUCT_SALES_IMPORT_LIST_IS_EMPTY);
+        }
+        MesWmProductSalesImportRespVO respVO = MesWmProductSalesImportRespVO.builder()
+                .createCodes(new ArrayList<>()).updateCodes(new ArrayList<>())
+                .failureCodes(new LinkedHashMap<>()).build();
+        AtomicInteger index = new AtomicInteger(1);
+        importList.forEach(importItem -> {
+            int currentIndex = index.getAndIncrement();
+            String code = importItem.getCode();
+            String key = StrUtil.blankToDefault(code, "绗� " + currentIndex + " 琛�");
+            if (StrUtil.isBlank(code)) {
+                respVO.getFailureCodes().put(key, "鍗曞彿涓嶈兘涓虹┖");
+                return;
+            }
+            if (StrUtil.isBlank(importItem.getName())) {
+                respVO.getFailureCodes().put(key, "鍚嶇О涓嶈兘涓虹┖");
+                return;
+            }
+            MesWmProductSalesDO existing = productSalesMapper.selectByCode(code);
+            if (existing != null && updateSupport) {
+                if (!MesWmProductSalesStatusEnum.PREPARE.getStatus().equals(existing.getStatus())) {
+                    respVO.getFailureCodes().put(key, "鍗曟嵁闈炶崏绋跨姸鎬侊紝涓嶅厑璁歌鐩栨洿鏂�");
+                    return;
+                }
+                MesWmProductSalesDO updateObj = BeanUtils.toBean(importItem, MesWmProductSalesDO.class);
+                updateObj.setId(existing.getId());
+                updateObj.setStatus(existing.getStatus());
+                productSalesMapper.updateById(updateObj);
+                respVO.getUpdateCodes().add(code);
+            } else if (existing != null) {
+                respVO.getFailureCodes().put(key, "鍗曞彿宸插瓨鍦細" + code);
+            } else {
+                MesWmProductSalesDO createObj = BeanUtils.toBean(importItem, MesWmProductSalesDO.class);
+                createObj.setId(null);
+                createObj.setStatus(MesWmProductSalesStatusEnum.PREPARE.getStatus());
+                productSalesMapper.insert(createObj);
+                respVO.getCreateCodes().add(code);
+            }
+        });
+        return respVO;
+    }
+
 }

--
Gitblit v1.9.3