From 31168ec141483a6d74bb0413d01c6aaecbc5fb9d Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期一, 12 十月 2026 11:53:47 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_海西州_惠牧' into dev_海西州_惠牧

---
 yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemServiceImpl.java |   80 +++++++++++++++++++++++++++------------
 1 files changed, 55 insertions(+), 25 deletions(-)

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 e1c5a82..cfbc790 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
@@ -3,6 +3,7 @@
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjUtil;
 import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.exception.ServiceException;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
@@ -32,10 +33,13 @@
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.PlatformTransactionManager;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.support.TransactionTemplate;
 import org.springframework.validation.annotation.Validated;
 
 import java.util.*;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -73,6 +77,9 @@
 
     @Resource
     private MesMdItemTypeApi mesMdItemTypeApi;
+
+    @Resource
+    private PlatformTransactionManager transactionManager;
 
 
     @Override
@@ -129,7 +136,7 @@
      *
      * MDM 鐨� unitMeasureId/categoryId 涓� MES 鐨� unitMeasureId/itemTypeId 鍒嗗睘涓ゅ涓绘暟鎹紝
      * 杩欓噷鍏堝湪 MDM 渚цВ鏋愬嚭 code锛屽啀浜ょ敱 MesMdItemApi 鍦� MES 渚цВ鏋愪负瀵瑰簲 id銆�
-     * 鍚屾澶辫触灏嗘姏鍑哄紓甯革紝瑙﹀彂澶栧眰 @Transactional 鏁翠綋鍥炴粴锛圡DM 鎿嶄綔涓�骞跺洖婊氾級銆�
+     * 鍚屾澶辫触灏嗘姏鍑哄紓甯革紝鍥炴粴鏈浜嬪姟锛堟湰琛岀殑 MDM 鎿嶄綔涓�骞跺洖婊氾紝涓嶅奖鍝嶅叾瀹冭锛夈��
      */
     private void syncItemToMes(MdmItemSaveReqVO reqVO) {
         // 瑙f瀽璁¢噺鍗曚綅 id -> code
@@ -433,7 +440,6 @@
     }
 
     @Override
-    @Transactional(rollbackFor = Exception.class)
     @LogRecord(type = MDM_ITEM_TYPE, subType = MDM_ITEM_IMPORT_SUB_TYPE, bizNo = "0",
             success = MDM_ITEM_IMPORT_SUCCESS)
     public MdmItemImportRespVO importItemList(List<MdmItemImportExcelVO> importList, Boolean isUpdateSupport) {
@@ -458,13 +464,12 @@
             unitCodeIdMap.put(unit.getCode(), unit.getId());
         }
 
-        // 2. 閬嶅巻瀵煎叆
+        // 2. 閬嶅巻瀵煎叆锛堟瘡琛屼竴涓嫭绔嬩簨鍔★細鍗曡澶辫触鍙洖婊氳琛岋紝涓嶅奖鍝嶅叾浣欒锛�
+        TransactionTemplate importTxTemplate = new TransactionTemplate(transactionManager);
         for (MdmItemImportExcelVO importVO : importList) {
             // 2.1 鍩虹鏍¢獙
             if (StrUtil.isBlank(importVO.getCode()) || StrUtil.isBlank(importVO.getName())) {
-                String failKey = StrUtil.isNotBlank(importVO.getName()) ? importVO.getName()
-                        : (StrUtil.isNotBlank(importVO.getCode()) ? importVO.getCode() : "锛堝悕绉板拰缂栫爜涓虹┖鐨勮锛�");
-                respVO.getFailureList().put(failKey, "鐗╂枡缂栫爜鍜岀墿鏂欏悕绉颁笉鑳戒负绌�");
+                respVO.getFailureList().put(buildFailKey(importVO), "鐗╂枡缂栫爜鍜岀墿鏂欏悕绉颁笉鑳戒负绌�");
                 continue;
             }
             // 2.2 瑙f瀽鍒嗙被
@@ -472,7 +477,7 @@
             if (StrUtil.isNotBlank(importVO.getCategoryCode())) {
                 categoryId = categoryCodeIdMap.get(importVO.getCategoryCode());
                 if (categoryId == null) {
-                    respVO.getFailureList().put(StrUtil.blankToDefault(importVO.getName(), importVO.getCode()), "鐗╂枡鍒嗙被缂栫爜涓嶅瓨鍦細" + importVO.getCategoryCode());
+                    respVO.getFailureList().put(buildFailKey(importVO), "鐗╂枡鍒嗙被缂栫爜涓嶅瓨鍦細" + importVO.getCategoryCode());
                     continue;
                 }
             }
@@ -481,7 +486,7 @@
             if (StrUtil.isNotBlank(importVO.getUnitMeasureCode())) {
                 unitMeasureId = unitCodeIdMap.get(importVO.getUnitMeasureCode());
                 if (unitMeasureId == null) {
-                    respVO.getFailureList().put(StrUtil.blankToDefault(importVO.getName(), importVO.getCode()), "璁¢噺鍗曚綅缂栫爜涓嶅瓨鍦細" + importVO.getUnitMeasureCode());
+                    respVO.getFailureList().put(buildFailKey(importVO), "璁¢噺鍗曚綅缂栫爜涓嶅瓨鍦細" + importVO.getUnitMeasureCode());
                     continue;
                 }
             }
@@ -490,7 +495,7 @@
             if (StrUtil.isNotBlank(importVO.getUnitMeasureCode2())) {
                 unitMeasureId2 = unitCodeIdMap.get(importVO.getUnitMeasureCode2());
                 if (unitMeasureId2 == null) {
-                    respVO.getFailureList().put(StrUtil.blankToDefault(importVO.getName(), importVO.getCode()), "杈呭崟浣�1缂栫爜涓嶅瓨鍦細" + importVO.getUnitMeasureCode2());
+                    respVO.getFailureList().put(buildFailKey(importVO), "杈呭崟浣�1缂栫爜涓嶅瓨鍦細" + importVO.getUnitMeasureCode2());
                     continue;
                 }
             }
@@ -499,7 +504,7 @@
             if (StrUtil.isNotBlank(importVO.getUnitMeasureCode3())) {
                 unitMeasureId3 = unitCodeIdMap.get(importVO.getUnitMeasureCode3());
                 if (unitMeasureId3 == null) {
-                    respVO.getFailureList().put(StrUtil.blankToDefault(importVO.getName(), importVO.getCode()), "杈呭崟浣�2缂栫爜涓嶅瓨鍦細" + importVO.getUnitMeasureCode3());
+                    respVO.getFailureList().put(buildFailKey(importVO), "杈呭崟浣�2缂栫爜涓嶅瓨鍦細" + importVO.getUnitMeasureCode3());
                     continue;
                 }
             }
@@ -531,25 +536,37 @@
 
             // 2.7 宸插瓨鍦紙鎸夌紪鐮佸垽鏂級
             MdmItemDO existByCode = itemMapper.selectByCode(importVO.getCode());
+            if (existByCode != null && !Boolean.TRUE.equals(isUpdateSupport)) {
+                respVO.getFailureList().put(buildFailKey(importVO), "鐗╂枡缂栫爜宸插瓨鍦�");
+                continue;
+            }
+            if (existByCode != null) {
+                saveReqVO.setId(existByCode.getId());
+            }
+            boolean isUpdate = existByCode != null;
+            // 浜嬪姟鍐呭厛鐣欎綇鍘熷寮傚父锛氬悓姝ュ埌 MES 澶辫触鏃朵細鎶婁簨鍔℃爣璁颁负 rollback-only锛�
+            // 鎻愪氦闃舵鎶涘嚭鐨勫彧鏄缁熺殑 UnexpectedRollbackException锛岀湡瀹炲師鍥狅紙濡�"鐗╂枡鍚嶇О宸插瓨鍦�"锛変細涓�
+            AtomicReference<Throwable> rowError = new AtomicReference<>();
             try {
-                if (existByCode != null) {
-                    if (!Boolean.TRUE.equals(isUpdateSupport)) {
-                        respVO.getFailureList().put(StrUtil.blankToDefault(importVO.getName(), importVO.getCode()), "鐗╂枡缂栫爜宸插瓨鍦�");
-                        continue;
+                importTxTemplate.executeWithoutResult(status -> {
+                    try {
+                        if (isUpdate) {
+                            updateItem(saveReqVO);
+                        } else {
+                            createItem(saveReqVO);
+                        }
+                    } catch (Throwable t) {
+                        rowError.set(t);
+                        throw t;
                     }
-                    saveReqVO.setId(existByCode.getId());
-                    updateItem(saveReqVO);
-                    respVO.getUpdateList().add(importVO.getName());
-                } else {
-                    createItem(saveReqVO);
-                    respVO.getCreateList().add(importVO.getName());
-                }
+                });
+                // 鍙湁鏈浜嬪姟鎻愪氦鎴愬姛鎵嶈鍏ユ垚鍔熸竻鍗�
+                (isUpdate ? respVO.getUpdateList() : respVO.getCreateList()).add(importVO.getName());
             } catch (Exception ex) {
                 // 鍗曟潯澶辫触锛岃褰曞苟缁х画
-                String reason = ex instanceof cn.iocoder.yudao.framework.common.exception.ServiceException
-                        ? ((cn.iocoder.yudao.framework.common.exception.ServiceException) ex).getMessage()
-                        : ex.getMessage();
-                respVO.getFailureList().put(StrUtil.blankToDefault(importVO.getName(), importVO.getCode()), reason == null ? "瀵煎叆澶辫触" : reason);
+                Throwable cause = rowError.get() != null ? rowError.get() : ex;
+                String reason = cause instanceof ServiceException ? ((ServiceException) cause).getMessage() : cause.getMessage();
+                respVO.getFailureList().put(buildFailKey(importVO), reason == null ? "瀵煎叆澶辫触" : reason);
             }
         }
         // 璁板綍瀵煎叆缁撴灉姹囨�伙紝渚� @LogRecord 鐨� success 鏂囨寮曠敤
@@ -557,4 +574,17 @@
         return respVO;
     }
 
+    /**
+     * 澶辫触娓呭崟鐨� key锛氱敤銆岀紪鐮� 鍚嶇О銆嶏紝鑰屼笉鏄崟鐢ㄥ悕绉般��
+     * 鐗╂枡鍏佽鍚屽悕涓嶅悓缂栫爜鍚庯紝鍙寜鍚嶇О鍋� key 浼氳鍚屽悕琛屼簰鐩歌鐩栥�佸皯鎶ュけ璐ヨ锛�
+     * 鎷兼帴鍚庢棦鑳藉敮涓�鏍囪瘑銆佷篃鑳戒竴鐪肩湅鍑烘槸鍝釜鐗╂枡銆�
+     */
+    private static String buildFailKey(MdmItemImportExcelVO importVO) {
+        if (StrUtil.isNotBlank(importVO.getCode()) && StrUtil.isNotBlank(importVO.getName())) {
+            return importVO.getCode() + " " + importVO.getName();
+        }
+        return StrUtil.blankToDefault(importVO.getCode(),
+                StrUtil.blankToDefault(importVO.getName(), "锛堝悕绉板拰缂栫爜涓虹┖鐨勮锛�"));
+    }
+
 }
\ No newline at end of file

--
Gitblit v1.9.3