From 48ee7c963f29f5614a8f86c08608620cc6310793 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期一, 26 十月 2026 17:11:33 +0800
Subject: [PATCH] feat: 完善产品编码与技术文件管理
---
yudao-module-mdm/src/main/java/cn/iocoder/yudao/module/mdm/service/item/MdmItemServiceImpl.java | 140 ++++++++++++++++++++++++++++++++++++----------
1 files changed, 110 insertions(+), 30 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 c3bc416..1780521 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,10 +3,12 @@
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;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.operatelog.core.util.OperateLogUtils;
import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemImportExcelVO;
import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemImportRespVO;
import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemPageReqVO;
@@ -17,6 +19,7 @@
import cn.iocoder.yudao.module.mdm.dal.dataobject.unit.MdmUnitMeasureDO;
import cn.iocoder.yudao.module.mdm.dal.mysql.item.MdmItemBatchConfigMapper;
import cn.iocoder.yudao.module.mdm.dal.mysql.item.MdmItemMapper;
+import cn.iocoder.yudao.module.mdm.dal.mysql.item.MdmItemCodeSequenceMapper;
import cn.iocoder.yudao.module.mdm.dal.mysql.unit.MdmUnitMeasureMapper;
import cn.iocoder.yudao.module.mdm.service.brand.MdmBrandService;
import cn.iocoder.yudao.module.mdm.service.category.MdmItemCategoryService;
@@ -26,19 +29,24 @@
import cn.iocoder.yudao.module.mes.api.item.dto.MesMdItemSyncReqDTO;
import cn.iocoder.yudao.module.mes.api.item.dto.MesMdItemTypeRespDTO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.mzt.logapi.starter.annotation.LogRecord;
import jakarta.annotation.Resource;
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;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.mdm.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.module.mdm.enums.LogRecordConstants.*;
/**
* MDM 鐗╂枡涓绘暟鎹� Service 瀹炵幇绫�
@@ -51,6 +59,9 @@
@Resource
private MdmItemMapper itemMapper;
+
+ @Resource
+ private MdmItemCodeSequenceMapper itemCodeSequenceMapper;
@Resource
private MdmItemCategoryService itemCategoryService;
@@ -71,10 +82,14 @@
@Resource
private MesMdItemTypeApi mesMdItemTypeApi;
+ @Resource
+ private PlatformTransactionManager transactionManager;
+
@Override
@Transactional(rollbackFor = Exception.class)
public Long createItem(MdmItemSaveReqVO createReqVO) {
+ createReqVO.setCode(generateItemCode(createReqVO.getItemType()));
// 鏍¢獙鏁版嵁
validateItemSaveData(createReqVO);
@@ -97,7 +112,10 @@
@Transactional(rollbackFor = Exception.class)
public void updateItem(MdmItemSaveReqVO updateReqVO) {
// 鏍¢獙瀛樺湪
- validateItemExists(updateReqVO.getId());
+ MdmItemDO existingItem = validateItemExists(updateReqVO.getId());
+ // 缂栧彿鐢辩郴缁熺敓鎴愶紝淇敼浜у搧鏃朵繚鎸佸師缂栧彿涓嶅彉銆�
+ updateReqVO.setCode(existingItem.getCode());
+ updateReqVO.setItemType(existingItem.getItemType());
// 鏍¢獙鏁版嵁
validateItemSaveData(updateReqVO);
@@ -117,8 +135,41 @@
}
private void validateItemSaveData(MdmItemSaveReqVO reqVO) {
+ if (reqVO.getItemType() == null || reqVO.getItemType() < 1 || reqVO.getItemType() > 5) {
+ throw exception(MDM_ITEM_TYPE_INVALID);
+ }
// 鏍¢獙鐗╂枡缂栫爜鐨勫敮涓�鎬�
validateItemCodeUnique(reqVO.getId(), reqVO.getCode());
+ }
+
+ /** 鐢熸垚鍥涗綅绫诲瀷鍓嶇紑 + 浜斾綅娴佹按鍙凤紝鍏变節浣嶃�傛祦姘磋鍦ㄤ簨鍔″唴鍔犻攣锛岄伩鍏嶅苟鍙戦噸澶嶃�� */
+ private String generateItemCode(Integer itemType) {
+ String prefix = switch (itemType == null ? 0 : itemType) {
+ case 1 -> "1001";
+ case 2 -> "1002";
+ case 3 -> "1003";
+ case 4 -> "1004";
+ case 5 -> "1005";
+ default -> throw exception(MDM_ITEM_TYPE_INVALID);
+ };
+ itemCodeSequenceMapper.insertIfAbsent(prefix);
+ Integer current = itemCodeSequenceMapper.selectCurrentValueForUpdate(prefix);
+ if (current == null) {
+ current = itemMapper.selectMaxSequenceByPrefix(prefix);
+ itemCodeSequenceMapper.insertIfAbsent(prefix);
+ itemCodeSequenceMapper.updateCurrentValue(prefix, current);
+ }
+ int maxExisting = itemMapper.selectMaxSequenceByPrefix(prefix);
+ if (current < maxExisting) {
+ current = maxExisting;
+ itemCodeSequenceMapper.updateCurrentValue(prefix, current);
+ }
+ if (current >= 99_999) {
+ throw exception(MDM_ITEM_CODE_SEQUENCE_EXHAUSTED);
+ }
+ itemCodeSequenceMapper.increment(prefix);
+ int next = current + 1;
+ return prefix + String.format("%05d", next);
}
/**
@@ -126,7 +177,7 @@
*
* MDM 鐨� unitMeasureId/categoryId 涓� MES 鐨� unitMeasureId/itemTypeId 鍒嗗睘涓ゅ涓绘暟鎹紝
* 杩欓噷鍏堝湪 MDM 渚цВ鏋愬嚭 code锛屽啀浜ょ敱 MesMdItemApi 鍦� MES 渚цВ鏋愪负瀵瑰簲 id銆�
- * 鍚屾澶辫触灏嗘姏鍑哄紓甯革紝瑙﹀彂澶栧眰 @Transactional 鏁翠綋鍥炴粴锛圡DM 鎿嶄綔涓�骞跺洖婊氾級銆�
+ * 鍚屾澶辫触灏嗘姏鍑哄紓甯革紝鍥炴粴鏈浜嬪姟锛堟湰琛岀殑 MDM 鎿嶄綔涓�骞跺洖婊氾紝涓嶅奖鍝嶅叾瀹冭锛夈��
*/
private void syncItemToMes(MdmItemSaveReqVO reqVO) {
// 瑙f瀽璁¢噺鍗曚綅 id -> code
@@ -430,7 +481,8 @@
}
@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) {
if (CollUtil.isEmpty(importList)) {
throw exception(MDM_ITEM_IMPORT_LIST_IS_EMPTY);
@@ -453,13 +505,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, "鐗╂枡缂栫爜鍜岀墿鏂欏悕绉颁笉鑳戒负绌�");
+ if (StrUtil.isBlank(importVO.getName())) {
+ respVO.getFailureList().put(buildFailKey(importVO), "鐗╂枡鍚嶇О涓嶈兘涓虹┖");
continue;
}
// 2.2 瑙f瀽鍒嗙被
@@ -467,7 +518,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;
}
}
@@ -476,7 +527,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;
}
}
@@ -485,7 +536,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;
}
}
@@ -494,17 +545,19 @@
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;
}
}
// 2.6 缁勮 SaveReqVO锛堝鐢� create/update 閫昏緫锛�
MdmItemSaveReqVO saveReqVO = new MdmItemSaveReqVO();
+ // 鏂板鏃跺拷鐣� Excel 涓殑鐗╂枡缂栫爜锛岀敱 MDM 鎸変骇鍝佺被鍨嬭嚜鍔ㄧ敓鎴愩��
saveReqVO.setCode(importVO.getCode());
saveReqVO.setName(importVO.getName());
saveReqVO.setBarCode(importVO.getBarCode());
saveReqVO.setSpecification(importVO.getSpecification());
+ saveReqVO.setTechnicalParameters(importVO.getTechnicalParameters());
saveReqVO.setCategoryId(categoryId);
saveReqVO.setUnitMeasureId(unitMeasureId);
saveReqVO.setUnitMeasureId2(unitMeasureId2);
@@ -522,32 +575,59 @@
saveReqVO.setStatus(importVO.getStatus() != null ? importVO.getStatus() : cn.iocoder.yudao.framework.common.enums.CommonStatusEnum.ENABLE.getStatus());
saveReqVO.setSyncMes(importVO.getSyncMes() != null ? importVO.getSyncMes() : false);
saveReqVO.setRemark(importVO.getRemark());
- saveReqVO.setItemType(1); // 榛樿鐗╂枡绫诲瀷锛氱墿鏂�
+ saveReqVO.setItemType(importVO.getItemType() != null ? importVO.getItemType() : 1); // 鏈彁渚涚被鍨嬫椂榛樿涓哄師鏉愭枡
// 2.7 宸插瓨鍦紙鎸夌紪鐮佸垽鏂級
- MdmItemDO existByCode = itemMapper.selectByCode(importVO.getCode());
+ MdmItemDO existByCode = StrUtil.isBlank(importVO.getCode()) ? null : 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 鏂囨寮曠敤
+ OperateLogUtils.putImportSummary(respVO.getCreateList(), respVO.getUpdateList(), respVO.getFailureList());
return respVO;
}
-}
\ No newline at end of file
+ /**
+ * 澶辫触娓呭崟鐨� 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(), "锛堝悕绉板拰缂栫爜涓虹┖鐨勮锛�"));
+ }
+
+}
--
Gitblit v1.9.3