From fd5ff7ce41f402720c79546617842bbf679e576e Mon Sep 17 00:00:00 2001
From: tuqin <tuqin@tuqin.cn>
Date: 星期三, 21 十月 2026 16:32:55 +0800
Subject: [PATCH] fix(销售台账/产品维护): 图号与销售合同号长度校验、导入提示优化
---
src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java | 170 ++++++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 145 insertions(+), 25 deletions(-)
diff --git a/src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java
index bd46fb4..0f2e47a 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java
@@ -28,6 +28,7 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
@@ -57,9 +58,19 @@
public int addOrEditProductModel(ProductModelDto productModelDto) {
String model = StringUtils.trim(productModelDto.getModel());
String productCode = StringUtils.trim(productModelDto.getProductCode());
+ String drawingNo = StringUtils.trim(productModelDto.getDrawingNo());
productModelDto.setModel(model);
productModelDto.setProductCode(productCode);
+ productModelDto.setDrawingNo(drawingNo);
+ // 鍥惧彿蹇呭~
+ if (StringUtils.isEmpty(drawingNo)) {
+ throw new ServiceException("鍥惧彿涓嶈兘涓虹┖");
+ }
+ if (drawingNo.length() > 255) {
+ throw new ServiceException("鍥惧彿闀垮害涓嶈兘瓒呰繃255涓瓧绗�");
+ }
checkModelAndProductCodeUnique(model, productCode, productModelDto.getId());
+ checkDrawingNoUnique(drawingNo, productModelDto.getId());
if (productModelDto.getId() == null) {
ProductModel productModel = new ProductModel();
@@ -67,6 +78,23 @@
return productModelMapper.insert(productModel);
} else {
return productModelMapper.updateById(productModelDto);
+ }
+ }
+
+ /**
+ * 鍥惧彿鍞竴鏍¢獙锛堝叏灞�锛岀紪杈戞椂鎺掗櫎鑷韩锛�
+ */
+ private void checkDrawingNoUnique(String drawingNo, Long currentId) {
+ if (StringUtils.isEmpty(drawingNo)) {
+ return;
+ }
+ LambdaQueryWrapper<ProductModel> queryWrapper = new LambdaQueryWrapper<>();
+ queryWrapper.eq(ProductModel::getDrawingNo, drawingNo)
+ .ne(currentId != null, ProductModel::getId, currentId)
+ .last("limit 1");
+ ProductModel duplicateProductModel = productModelMapper.selectOne(queryWrapper);
+ if (duplicateProductModel != null) {
+ throw new ServiceException("鍥惧彿" + drawingNo + "宸茬粡瀛樺湪");
}
}
@@ -145,6 +173,9 @@
return AjaxResult.error("鏈壘鍒� [鍘熸枡/鍗婃垚鍝�/鎴愬搧] 宸ヤ綔琛紝鎴栨枃浠朵腑娌℃湁鏁版嵁");
}
+ // 鍘婚噸閿細浜у搧鍚嶇О + 瑙勬牸鍨嬪彿 + 缂栫爜锛堢┖缂栫爜鎸夌┖涓插弬涓庢瘮杈冿級
+ Set<String> seenKeys = loadExistingProductKeys(sheetMap);
+
int successCount = 0;
int skipCount = 0;
Set<String> generatedCodes = new HashSet<>();
@@ -155,45 +186,61 @@
}
Long topId = findOrCreateTopProduct(sheetName);
Map<String, Long> nodeCache = new HashMap<>();
- Map<Long, Set<String>> codeCache = new HashMap<>();
for (int i = 0; i < rows.size(); i++) {
ProductImportRowDto row = rows.get(i);
- int rowNum = i + 2;
+ // 娌℃湁鍚嶇О/缂栫爜/瑙勬牸鐨勮鏋勪笉鎴愪骇鍝佹暟鎹紝鎸夌┖琛岃烦杩�
+ if (hasNoProductContent(row)) {
+ continue;
+ }
String parentName = trimToNull(row.getProductParentName());
String categoryName = trimToNull(row.getProductCategoryName());
String productName = trimToNull(row.getProductName());
- if (categoryName == null) {
- throw new ServiceException("绗� " + rowNum + " 琛� [浜у搧澶х被] 涓嶈兘涓虹┖");
- }
if (productName == null) {
- throw new ServiceException("绗� " + rowNum + " 琛� [浜у搧鍚嶇О] 涓嶈兘涓虹┖");
+ throw new ServiceException(String.format("宸ヤ綔琛ㄣ��%s銆戠 %d 琛� [浜у搧鍚嶇О] 涓嶈兘涓虹┖锛堣琛屽凡濉細%s锛�",
+ sheetName, resolveRowNum(row, i), describeRow(row)));
+ }
+
+ String model = trimToNull(row.getModel());
+ if (model == null) {
+ model = "/";
+ }
+ String code = trimToNull(row.getProductCode());
+ if (!seenKeys.add(dedupKey(productName, model, code))) {
+ skipCount++;
+ continue;
}
String path = String.valueOf(topId);
- Long parentNodeId = topId;
+ Long currentParentId = topId;
if (parentName != null) {
path = path + ">" + parentName;
- parentNodeId = ensureChildNode(nodeCache, path, parentNodeId, parentName);
+ currentParentId = ensureChildNode(nodeCache, path, currentParentId, parentName);
}
- path = path + ">" + categoryName;
- Long categoryId = ensureChildNode(nodeCache, path, parentNodeId, categoryName);
+ if (categoryName != null) {
+ path = path + ">" + categoryName;
+ currentParentId = ensureChildNode(nodeCache, path, currentParentId, categoryName);
+ }
path = path + ">" + productName;
- Long leafId = ensureChildNode(nodeCache, path, categoryId, productName);
+ Long leafId = ensureChildNode(nodeCache, path, currentParentId, productName);
- String code = trimToNull(row.getProductCode());
if (code == null) {
code = generateUniqueCode(generatedCodes);
}
- Set<String> codes = codeCache.computeIfAbsent(leafId, this::loadProductCodes);
- if (!codes.add(code)) {
- skipCount++;
- continue;
+
+ // 鍥惧彿锛氬鍏ユ椂鍙�夛紝濉啓鍒欐牎楠屽敮涓�
+ String drawingNo = trimToNull(row.getDrawingNo());
+ if (drawingNo != null) {
+ if (drawingNo.length() > 255) {
+ throw new ServiceException("宸ヤ綔绨裤��" + sheetName + "銆戠 " + resolveRowNum(row, i) + " 琛岋細鍥惧彿闀垮害涓嶈兘瓒呰繃255涓瓧绗�");
+ }
+ checkDrawingNoUnique(drawingNo, null);
}
ProductModel productModel = new ProductModel();
productModel.setProductId(leafId);
productModel.setProductCode(code);
- productModel.setModel(StringUtils.isEmpty(row.getModel()) ? "/" : row.getModel().trim());
+ productModel.setModel(model);
+ productModel.setDrawingNo(drawingNo);
productModel.setUnit(trimToNull(row.getUnit()));
productModelMapper.insert(productModel);
successCount++;
@@ -241,16 +288,89 @@
return product.getId();
}
- private Set<String> loadProductCodes(Long productId) {
- List<ProductModel> list = productModelMapper.selectList(new LambdaQueryWrapper<ProductModel>()
- .eq(ProductModel::getProductId, productId));
- Set<String> codes = new HashSet<>();
- for (ProductModel productModel : list) {
- if (productModel.getProductCode() != null) {
- codes.add(productModel.getProductCode().trim());
+ /**
+ * 棰勫姞杞藉簱涓凡瀛樺湪鐨勫幓閲嶉敭锛堜骇鍝佸悕绉� + 瑙勬牸鍨嬪彿 + 缂栫爜锛夛紝骞朵綔涓烘湰娆″鍏ョ殑鍒濆闆嗗悎銆�
+ */
+ private Set<String> loadExistingProductKeys(Map<String, List<ProductImportRowDto>> sheetMap) {
+ Set<String> productNames = new HashSet<>();
+ for (List<ProductImportRowDto> rows : sheetMap.values()) {
+ if (CollectionUtils.isEmpty(rows)) {
+ continue;
+ }
+ for (ProductImportRowDto row : rows) {
+ String productName = trimToNull(row.getProductName());
+ if (productName != null) {
+ productNames.add(productName);
+ }
}
}
- return codes;
+ Set<String> keys = new HashSet<>();
+ if (productNames.isEmpty()) {
+ return keys;
+ }
+
+ List<Product> products = productMapper.selectList(new LambdaQueryWrapper<Product>()
+ .in(Product::getProductName, productNames));
+ if (CollectionUtils.isEmpty(products)) {
+ return keys;
+ }
+ Map<Long, String> nameById = new HashMap<>();
+ List<Long> productIds = new ArrayList<>();
+ for (Product product : products) {
+ nameById.put(product.getId(), product.getProductName());
+ productIds.add(product.getId());
+ }
+
+ List<ProductModel> productModels = productModelMapper.selectList(new LambdaQueryWrapper<ProductModel>()
+ .in(ProductModel::getProductId, productIds));
+ for (ProductModel productModel : productModels) {
+ String productName = nameById.get(productModel.getProductId());
+ if (productName != null) {
+ keys.add(dedupKey(productName, productModel.getModel(), productModel.getProductCode()));
+ }
+ }
+ return keys;
+ }
+
+ /**
+ * 瑙f瀽鏃朵細璺宠繃绌鸿
+ */
+ private static int resolveRowNum(ProductImportRowDto row, int index) {
+ return row.getExcelRowNum() != null ? row.getExcelRowNum() : index + 2;
+ }
+
+ private static boolean hasNoProductContent(ProductImportRowDto row) {
+ return trimToNull(row.getProductName()) == null
+ && trimToNull(row.getProductCode()) == null
+ && trimToNull(row.getModel()) == null;
+ }
+
+ private static String describeRow(ProductImportRowDto row) {
+ StringBuilder description = new StringBuilder();
+ appendFilledColumn(description, "浜у搧鐖剁被", row.getProductParentName());
+ appendFilledColumn(description, "浜у搧澶х被", row.getProductCategoryName());
+ appendFilledColumn(description, "浜у搧鍚嶇О", row.getProductName());
+ appendFilledColumn(description, "浜у搧缂栫爜", row.getProductCode());
+ appendFilledColumn(description, "瑙勬牸鍨嬪彿", row.getModel());
+ appendFilledColumn(description, "鍗曚綅", row.getUnit());
+ return description.length() == 0 ? "鏃�" : description.toString();
+ }
+
+ private static void appendFilledColumn(StringBuilder description, String columnName, String value) {
+ String trimmed = trimToNull(value);
+ if (trimmed == null) {
+ return;
+ }
+ if (description.length() > 0) {
+ description.append("锛�");
+ }
+ description.append(columnName).append('=').append(trimmed);
+ }
+
+ private static String dedupKey(String productName, String model, String productCode) {
+ String normalizedModel = trimToNull(model) == null ? "/" : model.trim();
+ String normalizedCode = productCode == null ? "" : productCode.trim();
+ return productName.trim() + "\u0001" + normalizedModel + "\u0001" + normalizedCode;
}
private String generateUniqueCode(Set<String> generatedCodes) {
--
Gitblit v1.9.3