From e978a226c2c1b22c9172a58539d876b298e9e2da Mon Sep 17 00:00:00 2001
From: liyong <18434998025@163.com>
Date: 星期四, 23 七月 2026 17:47:33 +0800
Subject: [PATCH] 物料删除校验

---
 yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java                           |    1 
 yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpSupplierMapper.java               |   10 +
 yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemServiceImpl.java                    |   22 ++
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDO.java   |    7 +
 yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/mysql/item/MdmItemMapper.java                       |   10 +
 yudao-module-erp/src/main/resources/mapper/purchase/ErpSupplierMapper.xml                                          |   52 ++++++++
 yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/enums/ErrorCodeConstants.java                           |    1 
 yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java            |   19 +++
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java               |   44 ++++--
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImpl.java |   56 ++++++--
 yudao-module-mdm/src/main/resources/mapper/item/MdmItemMapper.xml                                                  |   81 +++++++++++++
 11 files changed, 265 insertions(+), 38 deletions(-)

diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpSupplierMapper.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpSupplierMapper.java
index c74f1e6..5cdea73 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpSupplierMapper.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpSupplierMapper.java
@@ -6,8 +6,10 @@
 import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierPageReqVO;
 import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * ERP 渚涘簲鍟� Mapper
@@ -29,4 +31,12 @@
         return selectList(ErpSupplierDO::getStatus, status);
     }
 
+    /**
+     * 鏌ヨ渚涘簲鍟嗚鍝簺涓氬姟琛ㄥ紩鐢紙鏈垹闄ょ殑璁板綍锛�
+     *
+     * @param supplierId 渚涘簲鍟嗙紪鍙�
+     * @return 寮曠敤鏉ユ簮鍒楄〃锛屾瘡椤瑰寘鍚� source(鏉ユ簮鍚�) 鍜� cnt(寮曠敤鏁伴噺)锛屼粎杩斿洖 cnt > 0 鐨�
+     */
+    List<Map<String, Object>> selectSupplierReferenceCount(@Param("supplierId") Long supplierId);
+
 }
\ No newline at end of file
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java
index 9082005..5666784 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java
@@ -12,6 +12,7 @@
     // ========== ERP 渚涘簲鍟嗭紙1-030-100-000锛� ==========
     ErrorCode SUPPLIER_NOT_EXISTS = new ErrorCode(1_030_100_000, "渚涘簲鍟嗕笉瀛樺湪");
     ErrorCode SUPPLIER_NOT_ENABLE = new ErrorCode(1_030_100_000, "渚涘簲鍟�({})鏈惎鐢�");
+    ErrorCode SUPPLIER_EXISTS_REFERENCE = new ErrorCode(1_030_100_001, "渚涘簲鍟嗗凡琚笟鍔″紩鐢紝鏃犳硶鍒犻櫎");
 
     // ========== ERP 閲囪喘璁㈠崟锛�1-030-101-000锛� ==========
     ErrorCode PURCHASE_ORDER_NOT_EXISTS = new ErrorCode(1_030_101_000, "閲囪喘璁㈠崟涓嶅瓨鍦�");
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java
index 9e56f4a..6344326 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java
@@ -14,6 +14,8 @@
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;
@@ -50,10 +52,27 @@
     public void deleteSupplier(Long id) {
         // 鏍¢獙瀛樺湪
         validateSupplierExists(id);
+        // 鏍¢獙渚涘簲鍟嗘槸鍚﹁涓氬姟寮曠敤
+        validateSupplierNoReference(id);
         // 鍒犻櫎
         supplierMapper.deleteById(id);
     }
 
+    /**
+     * 鏍¢獙渚涘簲鍟嗘湭琚笟鍔″紩鐢紙閲囪喘銆佽川妫�銆佺敓浜с�佸簱瀛樼瓑锛�
+     *
+     * @param id 渚涘簲鍟嗙紪鍙�
+     */
+    private void validateSupplierNoReference(Long id) {
+        List<Map<String, Object>> references = supplierMapper.selectSupplierReferenceCount(id);
+        if (CollUtil.isNotEmpty(references)) {
+            String refDesc = references.stream()
+                    .map(r -> r.get("source") + "(" + r.get("cnt") + ")")
+                    .collect(Collectors.joining("銆�"));
+            throw exception(SUPPLIER_EXISTS_REFERENCE, refDesc);
+        }
+    }
+
     private void validateSupplierExists(Long id) {
         if (supplierMapper.selectById(id) == null) {
             throw exception(SUPPLIER_NOT_EXISTS);
diff --git a/yudao-module-erp/src/main/resources/mapper/purchase/ErpSupplierMapper.xml b/yudao-module-erp/src/main/resources/mapper/purchase/ErpSupplierMapper.xml
new file mode 100644
index 0000000..1ca6a19
--- /dev/null
+++ b/yudao-module-erp/src/main/resources/mapper/purchase/ErpSupplierMapper.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpSupplierMapper">
+
+    <!--
+        鏌ヨ渚涘簲鍟嗚鍝簺涓氬姟琛ㄥ紩鐢紙鏈垹闄ょ殑璁板綍锛�
+        ERP 妯″潡鐢� supplier_id锛孧ES 妯″潡鐢� vendor_id
+        杩斿洖鏈夊紩鐢ㄧ殑鏉ユ簮鍚嶅拰寮曠敤鏁伴噺锛岀敤浜庡垹闄ゆ牎楠�
+    -->
+    <select id="selectSupplierReferenceCount" resultType="map">
+        SELECT source, cnt FROM (
+            <!-- ERP锛氶噰璐鍗� -->
+            SELECT '閲囪喘-閲囪喘璁㈠崟' AS source, COUNT(*) AS cnt FROM erp_purchase_order WHERE supplier_id = #{supplierId} AND deleted = 0
+            UNION ALL
+            <!-- ERP锛氶噰璐敵璇� -->
+            SELECT '閲囪喘-閲囪喘鐢宠' AS source, COUNT(*) AS cnt FROM erp_purchase_request WHERE supplier_id = #{supplierId} AND deleted = 0
+            UNION ALL
+            <!-- ERP锛氫粯娆惧崟 -->
+            SELECT '閲囪喘-浠樻鍗�' AS source, COUNT(*) AS cnt FROM erp_finance_payment WHERE supplier_id = #{supplierId} AND deleted = 0
+            UNION ALL
+            <!-- MES锛氬埌璐ч�氱煡 -->
+            SELECT '閲囪喘-鍒拌揣閫氱煡' AS source, COUNT(*) AS cnt FROM mes_wm_arrival_notice WHERE vendor_id = #{supplierId} AND deleted = 0
+            UNION ALL
+            <!-- MES锛氶噰璐叆搴� -->
+            SELECT '閲囪喘-閲囪喘鍏ュ簱' AS source, COUNT(*) AS cnt FROM mes_wm_item_receipt WHERE vendor_id = #{supplierId} AND deleted = 0
+            UNION ALL
+            <!-- MES锛氬澶栧叆搴� -->
+            SELECT '閲囪喘-濮斿鍏ュ簱' AS source, COUNT(*) AS cnt FROM mes_wm_outsource_receipt WHERE vendor_id = #{supplierId} AND deleted = 0
+            UNION ALL
+            <!-- MES锛氬澶栧彂鏂� -->
+            SELECT '閲囪喘-濮斿鍙戞枡' AS source, COUNT(*) AS cnt FROM mes_wm_outsource_issue WHERE vendor_id = #{supplierId} AND deleted = 0
+            UNION ALL
+            <!-- MES锛氶噰璐��璐� -->
+            SELECT '閲囪喘-閲囪喘閫�璐�' AS source, COUNT(*) AS cnt FROM mes_wm_return_vendor WHERE vendor_id = #{supplierId} AND deleted = 0
+            UNION ALL
+            <!-- 璐ㄦ锛欼QC -->
+            SELECT '璐ㄦ-IQC' AS source, COUNT(*) AS cnt FROM mes_qc_iqc WHERE vendor_id = #{supplierId} AND deleted = 0
+            UNION ALL
+            <!-- 鐢熶骇锛氬伐鍗� -->
+            SELECT '鐢熶骇-宸ュ崟' AS source, COUNT(*) AS cnt FROM mes_pro_work_order WHERE vendor_id = #{supplierId} AND deleted = 0
+            UNION ALL
+            <!-- 搴撳瓨锛氬簱瀛� -->
+            SELECT '搴撳瓨-搴撳瓨' AS source, COUNT(*) AS cnt FROM mes_wm_material_stock WHERE vendor_id = #{supplierId} AND deleted = 0
+            UNION ALL
+            <!-- 搴撳瓨锛氭壒娆� -->
+            SELECT '搴撳瓨-鎵规' AS source, COUNT(*) AS cnt FROM mes_wm_batch WHERE vendor_id = #{supplierId} AND deleted = 0
+        ) t
+        WHERE t.cnt > 0
+        ORDER BY t.source
+    </select>
+
+</mapper>
diff --git a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/mysql/item/MdmItemMapper.java b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/mysql/item/MdmItemMapper.java
index 04edd6b..58289e2 100644
--- a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/mysql/item/MdmItemMapper.java
+++ b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/dal/mysql/item/MdmItemMapper.java
@@ -6,9 +6,11 @@
 import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemPageReqVO;
 import cn.iocoder.yudao.module.mdm.dal.dataobject.item.MdmItemDO;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 
 /**
  * MDM 鐗╂枡涓绘暟鎹� Mapper
@@ -81,4 +83,12 @@
         return selectList(MdmItemDO::getId, ids);
     }
 
+    /**
+     * 鏌ヨ鐗╂枡琚摢浜涗笟鍔¤〃寮曠敤锛堟湭鍒犻櫎鐨勮褰曪級
+     *
+     * @param itemId 鐗╂枡缂栧彿
+     * @return 寮曠敤鏉ユ簮鍒楄〃锛屾瘡椤瑰寘鍚� source(鏉ユ簮鍚�) 鍜� cnt(寮曠敤鏁伴噺)锛屼粎杩斿洖 cnt > 0 鐨�
+     */
+    List<Map<String, Object>> selectItemReferenceCount(@Param("itemId") Long itemId);
+
 }
\ No newline at end of file
diff --git a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/enums/ErrorCodeConstants.java b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/enums/ErrorCodeConstants.java
index 8186e50..747fc12 100644
--- a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/enums/ErrorCodeConstants.java
+++ b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/enums/ErrorCodeConstants.java
@@ -16,6 +16,7 @@
     ErrorCode MDM_ITEM_SKU_NOT_EXISTS = new ErrorCode(1_050_004, "鐗╂枡SKU涓嶅瓨鍦�");
     ErrorCode MDM_ITEM_SKU_IS_DISABLE = new ErrorCode(1_050_005, "鐗╂枡SKU宸茬鐢�");
     ErrorCode MDM_ITEM_SKU_CODE_DUPLICATE = new ErrorCode(1_050_006, "SKU缂栫爜宸插瓨鍦�");
+    ErrorCode MDM_ITEM_EXISTS_REFERENCE = new ErrorCode(1_050_007, "鐗╂枡宸茶涓氬姟寮曠敤锛屾棤娉曞垹闄�");
 
     // ========== 鐗╂枡鍒嗙被鐩稿叧 1-050-051 ~ 1-050-100 ==========
     ErrorCode MDM_ITEM_CATEGORY_NOT_EXISTS = new ErrorCode(1_050_051, "鐗╂枡鍒嗙被涓嶅瓨鍦�");
diff --git a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemServiceImpl.java b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemServiceImpl.java
index 5acea4b..503a0e4 100644
--- a/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemServiceImpl.java
+++ b/yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemServiceImpl.java
@@ -177,15 +177,27 @@
     public void deleteItem(Long id) {
         // 鏍¢獙瀛樺湪
         MdmItemDO item = validateItemExists(id);
-        // 瑙e喅杞垹闄ゅ敮涓�閿啿绐侊細濡傛灉宸插瓨鍦ㄧ浉鍚� code 涓斿凡杞垹闄ょ殑璁板綍锛屽厛鐗╃悊鍒犻櫎瀹�
-//        MdmItemDO existingDeleted = itemMapper.selectByCodeAndDeleted(item.getCode(), true);
-//        if (existingDeleted != null && !existingDeleted.getId().equals(id)) {
-//            itemMapper.physicalDeleteById(existingDeleted.getId());
-//        }
+        // 鏍¢獙鐗╂枡鏄惁琚笟鍔″紩鐢�
+        validateItemNoReference(id);
         // 杞垹闄ゅ綋鍓嶈褰�
         itemMapper.deleteById(id);
     }
 
+    /**
+     * 鏍¢獙鐗╂枡鏈涓氬姟寮曠敤锛堥攢鍞�侀噰璐�佺敓浜с�佽川妫�銆佸簱瀛樼瓑锛�
+     *
+     * @param id 鐗╂枡缂栧彿
+     */
+    private void validateItemNoReference(Long id) {
+        List<Map<String, Object>> references = itemMapper.selectItemReferenceCount(id);
+        if (CollUtil.isNotEmpty(references)) {
+            String refDesc = references.stream()
+                    .map(r -> r.get("source") + "(" + r.get("cnt") + ")")
+                    .collect(Collectors.joining("銆�"));
+            throw exception(MDM_ITEM_EXISTS_REFERENCE, refDesc);
+        }
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void deleteItemList(Collection<Long> ids) {
diff --git a/yudao-module-mdm/src/main/resources/mapper/item/MdmItemMapper.xml b/yudao-module-mdm/src/main/resources/mapper/item/MdmItemMapper.xml
new file mode 100644
index 0000000..f6a5aae
--- /dev/null
+++ b/yudao-module-mdm/src/main/resources/mapper/item/MdmItemMapper.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.iocoder.yudao.module.mdm.dal.mysql.item.MdmItemMapper">
+
+    <!--
+        鏌ヨ鐗╂枡琚摢浜涗笟鍔¤〃寮曠敤锛堟湭鍒犻櫎鐨勮褰曪級
+        杩斿洖鏈夊紩鐢ㄧ殑琛ㄥ悕鍜屽紩鐢ㄦ暟閲忥紝鐢ㄤ簬鍒犻櫎鏍¢獙
+    -->
+    <select id="selectItemReferenceCount" resultType="map">
+        SELECT source, cnt FROM (
+            <!-- 鐢熶骇锛氬伐鍗旴OM -->
+            SELECT '鐢熶骇-宸ュ崟BOM' AS source, COUNT(*) AS cnt FROM mes_pro_work_order_bom WHERE item_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- 鐢熶骇锛氭姤宸� -->
+            SELECT '鐢熶骇-鎶ュ伐' AS source, COUNT(*) AS cnt FROM mes_pro_feedback WHERE item_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- 鐢熶骇锛氱敓浜т换鍔� -->
+            SELECT '鐢熶骇-鐢熶骇浠诲姟' AS source, COUNT(*) AS cnt FROM mes_pro_task WHERE item_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- 鐢熶骇锛氬伐鑹鸿矾绾夸骇鍝� -->
+            SELECT '鐢熶骇-宸ヨ壓璺嚎' AS source, COUNT(*) AS cnt FROM mes_pro_route_product WHERE item_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- 鐢熶骇锛氬伐鑹鸿矾绾緽OM -->
+            SELECT '鐢熶骇-宸ヨ壓璺嚎BOM' AS source, COUNT(*) AS cnt FROM mes_pro_route_product_bom WHERE item_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- 璐ㄦ锛欼QC -->
+            SELECT '璐ㄦ-IQC' AS source, COUNT(*) AS cnt FROM mes_qc_iqc WHERE item_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- 璐ㄦ锛欼PQC -->
+            SELECT '璐ㄦ-IPQC' AS source, COUNT(*) AS cnt FROM mes_qc_ipqc WHERE item_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- 璐ㄦ锛歄QC -->
+            SELECT '璐ㄦ-OQC' AS source, COUNT(*) AS cnt FROM mes_qc_oqc WHERE item_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- 璐ㄦ锛歊QC -->
+            SELECT '璐ㄦ-RQC' AS source, COUNT(*) AS cnt FROM mes_qc_rqc WHERE item_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- 閲囪喘锛氬埌璐ч�氱煡琛� -->
+            SELECT '閲囪喘-鍒拌揣閫氱煡' AS source, COUNT(*) AS cnt FROM mes_wm_arrival_notice_line WHERE item_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- 閲囪喘锛氶噰璐叆搴撹 -->
+            SELECT '閲囪喘-閲囪喘鍏ュ簱' AS source, COUNT(*) AS cnt FROM mes_wm_item_receipt_line WHERE item_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- 閿�鍞細閿�鍞�氱煡琛� -->
+            SELECT '閿�鍞�-閿�鍞�氱煡' AS source, COUNT(*) AS cnt FROM mes_wm_sales_notice_line WHERE item_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- 閿�鍞細閿�鍞嚭搴撹 -->
+            SELECT '閿�鍞�-閿�鍞嚭搴�' AS source, COUNT(*) AS cnt FROM mes_wm_product_sales_line WHERE item_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- 閿�鍞細閿�鍞��璐ц -->
+            SELECT '閿�鍞�-閿�鍞��璐�' AS source, COUNT(*) AS cnt FROM mes_wm_return_sales_line WHERE item_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- 搴撳瓨锛氬簱瀛樿褰� -->
+            SELECT '搴撳瓨-搴撳瓨' AS source, COUNT(*) AS cnt FROM mes_wm_material_stock WHERE item_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- CRM锛氶攢鍞姤浠蜂骇鍝� -->
+            SELECT '閿�鍞�-鎶ヤ环鍗�' AS source, COUNT(*) AS cnt FROM crm_sale_quotation_product WHERE item_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- CRM锛氬晢鏈轰骇鍝� -->
+            SELECT '閿�鍞�-鍟嗘満' AS source, COUNT(*) AS cnt FROM crm_business_product WHERE item_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- CRM锛氬悎鍚屼骇鍝� -->
+            SELECT '閿�鍞�-鍚堝悓' AS source, COUNT(*) AS cnt FROM crm_contract_product WHERE item_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- ERP锛氶噰璐鍗曟槑缁嗭紙product_id 寮曠敤鐗╂枡锛� -->
+            SELECT '閲囪喘-閲囪喘璁㈠崟' AS source, COUNT(*) AS cnt FROM erp_purchase_order_items WHERE product_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- ERP锛氶噰璐敵璇锋槑缁嗭紙product_id 寮曠敤鐗╂枡锛� -->
+            SELECT '閲囪喘-閲囪喘鐢宠' AS source, COUNT(*) AS cnt FROM erp_purchase_request_items WHERE product_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- ERP锛氶攢鍞鍗曟槑缁嗭紙product_id 寮曠敤鐗╂枡锛� -->
+            SELECT '閿�鍞�-閿�鍞鍗�' AS source, COUNT(*) AS cnt FROM erp_sale_order_items WHERE product_id = #{itemId} AND deleted = 0
+            UNION ALL
+            <!-- 鐢熶骇锛氬伐鍗曚骇鍝侊紙product_id 寮曠敤鐗╂枡锛� -->
+            SELECT '鐢熶骇-鐢熶骇宸ュ崟' AS source, COUNT(*) AS cnt FROM mes_pro_work_order WHERE product_id = #{itemId} AND deleted = 0
+        ) t
+        WHERE t.cnt > 0
+        ORDER BY t.source
+    </select>
+
+</mapper>
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDO.java
index bd8cfdf..f641a4d 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDO.java
@@ -57,6 +57,13 @@
      */
     private String purchaseOrderCode;
     /**
+     * 閲囪喘璁㈠崟缂栧彿
+     *
+     * 鍏宠仈 ERP {@link cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO#getId()}
+     * 浠庡埌璐ч�氱煡鍗曞甫鍏ワ紝鐢ㄤ簬鍏ュ簱瀹屾垚鏃跺洖鍐欓噰璐鍗曞叆搴撴暟閲�
+     */
+    private Long purchaseOrderId;
+    /**
      * 渚涘簲鍟嗙紪鍙�
      *
      * 鍏宠仈 ERP 渚涘簲鍟� {@link cn.iocoder.yudao.module.erp.api.purchase.dto.ErpSupplierRespDTO#getId()}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java
index eb962d7..ec3f159 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java
@@ -20,6 +20,7 @@
 import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum;
 import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum;
 import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
+import cn.iocoder.yudao.module.mes.enums.pro.MesProFeedbackStatusEnum;
 import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
 import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService;
@@ -34,6 +35,7 @@
 import cn.iocoder.yudao.module.mes.service.wm.productproduce.MesWmProductProduceLineService;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 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;
@@ -54,6 +56,7 @@
  */
 @Service
 @Validated
+@Slf4j
 public class MesQcIpqcServiceImpl implements MesQcIpqcService {
 
     /**
@@ -225,25 +228,34 @@
      * @param ipqc 杩囩▼妫�楠屽崟
      */
     private void writeBackSourceDoc(MesQcIpqcDO ipqc) {
-        if (ipqc.getSourceDocType() == null) {
-            return;
-        }
-        if (ipqc.getSourceDocId() == null) {
-            throw new IllegalArgumentException(
-                    "IPQC 鍗昜" + ipqc.getId() + "] sourceDocType 闈炵┖浣� sourceDocId 涓虹┖");
+        // 1. 纭畾 sourceDocType/sourceDocId
+        Long sourceDocId = ipqc.getSourceDocId();
+        Long sourceLineId = ipqc.getSourceLineId();
+
+        // 濡傛灉 IPQC 鍗曟病鏈夎缃潵婧愶紝灏濊瘯閫氳繃 taskId 鏌ユ壘鍏宠仈鐨勫緟妫�楠屾姤宸�
+        if (sourceDocId == null && ipqc.getTaskId() != null) {
+            MesProFeedbackDO feedback = feedbackService.getFeedbackListByTaskId(ipqc.getTaskId()).stream()
+                    .filter(f -> MesProFeedbackStatusEnum.UNCHECK.getStatus().equals(f.getStatus()))
+                    .findFirst().orElse(null);
+            if (feedback != null) {
+                sourceDocId = feedback.getId();
+                log.info("[writeBackSourceDoc] IPQC({}) 鏈缃潵婧愬崟鎹紝閫氳繃 taskId({}) 鎵惧埌寰呮楠屾姤宸�({})",
+                        ipqc.getId(), ipqc.getTaskId(), feedback.getId());
+            }
         }
 
-        if (Objects.equals(ipqc.getSourceDocType(), MesBizTypeConstants.PRO_FEEDBACK)) {
-            feedbackService.updateProFeedbackWhenIpqcFinish(ipqc.getSourceDocId(), ipqc.getSourceLineId(),
-                    ObjectUtil.defaultIfNull(ipqc.getQualifiedQuantity(), BigDecimal.ZERO),
-                    ObjectUtil.defaultIfNull(ipqc.getUnqualifiedQuantity(), BigDecimal.ZERO),
-                    ObjectUtil.defaultIfNull(ipqc.getLaborScrapQuantity(), BigDecimal.ZERO),
-                    ObjectUtil.defaultIfNull(ipqc.getMaterialScrapQuantity(), BigDecimal.ZERO),
-                    ObjectUtil.defaultIfNull(ipqc.getOtherScrapQuantity(), BigDecimal.ZERO));
-        } else {
-            throw new IllegalArgumentException(
-                    "IPQC 鍗昜" + ipqc.getId() + "] sourceDocType=" + ipqc.getSourceDocType() + " 鏃犳硶璇嗗埆锛屾棤娉曞洖鍐欐潵婧愬崟鎹�");
+        if (sourceDocId == null) {
+            log.warn("[writeBackSourceDoc] IPQC({}) 鏃犳硶纭畾鏉ユ簮鎶ュ伐锛岃烦杩囧洖鍐�", ipqc.getId());
+            return;
         }
+
+        // 2. 鍥炲啓鎶ュ伐
+        feedbackService.updateProFeedbackWhenIpqcFinish(sourceDocId, sourceLineId,
+                ObjectUtil.defaultIfNull(ipqc.getQualifiedQuantity(), BigDecimal.ZERO),
+                ObjectUtil.defaultIfNull(ipqc.getUnqualifiedQuantity(), BigDecimal.ZERO),
+                ObjectUtil.defaultIfNull(ipqc.getLaborScrapQuantity(), BigDecimal.ZERO),
+                ObjectUtil.defaultIfNull(ipqc.getMaterialScrapQuantity(), BigDecimal.ZERO),
+                ObjectUtil.defaultIfNull(ipqc.getOtherScrapQuantity(), BigDecimal.ZERO));
     }
 
     @Override
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImpl.java
index e474e63..9611fdd 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImpl.java
@@ -247,28 +247,49 @@
      * 鍥炲啓 ERP 閲囪喘璁㈠崟鐨勫叆搴撴暟閲�
      */
     private void updateErpPurchaseOrderInCount(MesWmItemReceiptDO receipt) {
-        // 鑾峰彇鍏ュ簱鍗曡
-        List<MesWmItemReceiptLineDO> lines = itemReceiptLineService.getItemReceiptLineListByReceiptId(receipt.getId());
-        if (CollUtil.isEmpty(lines)) {
-            return;
+        // 1. 纭畾閲囪喘璁㈠崟 ID锛氫紭鍏堜粠鍏ュ簱鍗曞ご鍙栵紙浠庡埌璐ч�氱煡鍗曞甫鍏ワ級锛屽叾娆′粠琛屽弽鏌�
+        Long purchaseOrderId = receipt.getPurchaseOrderId();
+        if (purchaseOrderId == null && receipt.getNoticeId() != null) {
+            // 浠庡叧鑱旂殑鍒拌揣閫氱煡鍗曡幏鍙栭噰璐鍗� ID
+            MesWmArrivalNoticeDO notice = arrivalNoticeService.getArrivalNotice(receipt.getNoticeId());
+            if (notice != null) {
+                purchaseOrderId = notice.getPurchaseOrderId();
+            }
         }
-        // 鐢ㄤ簬瀛樺偍閲囪喘璁㈠崟 ID锛岄伩鍏嶉噸澶嶆洿鏂�
-        Long purchaseOrderId = null;
-        // 閬嶅巻琛岋紝鎸� purchaseOrderItemId 鏇存柊鍏ュ簱鏁伴噺
-        for (MesWmItemReceiptLineDO line : lines) {
-            if (line.getPurchaseOrderItemId() != null && line.getReceivedQuantity() != null) {
-                purchaseOrderApi.updateOrderItemInCount(line.getPurchaseOrderItemId(), line.getReceivedQuantity());
-                // 鑾峰彇閲囪喘璁㈠崟 ID锛堜粠绗竴涓湁鏁堢殑鏄庣粏椤硅幏鍙栵級
-                if (purchaseOrderId == null) {
-                    cn.iocoder.yudao.module.erp.api.purchase.dto.ErpPurchaseOrderItemRespDTO itemDTO =
-                            purchaseOrderApi.getPurchaseOrderItem(line.getPurchaseOrderItemId()).getCheckedData();
-                    if (itemDTO != null && itemDTO.getOrderId() != null) {
-                        purchaseOrderId = itemDTO.getOrderId();
+
+        // 2. 鑾峰彇鍏ュ簱鍗曡锛屾寜 purchaseOrderItemId 鏇存柊鍏ュ簱鏁伴噺
+        List<MesWmItemReceiptLineDO> lines = itemReceiptLineService.getItemReceiptLineListByReceiptId(receipt.getId());
+        if (CollUtil.isNotEmpty(lines)) {
+            for (MesWmItemReceiptLineDO line : lines) {
+                if (line.getPurchaseOrderItemId() != null && line.getReceivedQuantity() != null) {
+                    purchaseOrderApi.updateOrderItemInCount(line.getPurchaseOrderItemId(), line.getReceivedQuantity());
+                    // 濡傛灉杩樻病鎷垮埌 purchaseOrderId锛屼粠鏄庣粏椤瑰弽鏌�
+                    if (purchaseOrderId == null) {
+                        cn.iocoder.yudao.module.erp.api.purchase.dto.ErpPurchaseOrderItemRespDTO itemDTO =
+                                purchaseOrderApi.getPurchaseOrderItem(line.getPurchaseOrderItemId()).getCheckedData();
+                        if (itemDTO != null && itemDTO.getOrderId() != null) {
+                            purchaseOrderId = itemDTO.getOrderId();
+                        }
+                    }
+                }
+            }
+        } else if (receipt.getNoticeId() != null) {
+            // 鍏滃簳锛氬叆搴撹涓虹┖鏃讹紝浠庡埌璐ч�氱煡鍗曡鍥炲啓鍏ュ簱鏁伴噺
+            List<MesWmArrivalNoticeLineDO> noticeLines = arrivalNoticeLineService
+                    .getArrivalNoticeLineListByNoticeId(receipt.getNoticeId());
+            for (MesWmArrivalNoticeLineDO noticeLine : noticeLines) {
+                if (noticeLine.getPurchaseOrderItemId() != null) {
+                    // 浣跨敤鍚堟牸鏁伴噺锛堟湁 IQC 鏃朵负鍚堟牸鏁伴噺锛屽惁鍒欎负鍒拌揣鏁伴噺锛�
+                    BigDecimal qty = noticeLine.getQualifiedQuantity() != null
+                            ? noticeLine.getQualifiedQuantity() : noticeLine.getArrivalQuantity();
+                    if (qty != null && qty.compareTo(BigDecimal.ZERO) > 0) {
+                        purchaseOrderApi.updateOrderItemInCount(noticeLine.getPurchaseOrderItemId(), qty);
                     }
                 }
             }
         }
-        // 鏇存柊閲囪喘璁㈠崟鐨勫叆搴撶姸鎬�
+
+        // 3. 鏇存柊閲囪喘璁㈠崟鐨勫叆搴撶姸鎬�
         if (purchaseOrderId != null) {
             purchaseOrderApi.updateOrderInStatus(purchaseOrderId);
         }
@@ -394,6 +415,7 @@
         receipt.setCode(code);
         receipt.setName(notice.getName() + "鍏ュ簱鍗�");
         receipt.setNoticeId(arrivalNoticeId);
+        receipt.setPurchaseOrderId(notice.getPurchaseOrderId());
         receipt.setPurchaseOrderCode(notice.getPurchaseOrderCode());
         receipt.setVendorId(notice.getVendorId());
         receipt.setReceiptDate(java.time.LocalDateTime.now()); // 鍏ュ簱鏃堕棿涓哄綋鍓嶆椂闂�

--
Gitblit v1.9.3