From fa612e9d7bc4be689fe9811926f0918b1536e53b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=A6=E9=B8=BF=E5=B1=95?= <18031053041@163.com> Date: Fri, 29 May 2026 10:38:42 +0800 Subject: [PATCH] =?UTF-8?q?=E7=89=A9=E6=96=99=E5=AF=BC=E5=85=A5=E7=B9=81?= =?UTF-8?q?=E4=BD=93=E8=A7=A3=E6=9E=901?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MaterialBaseInfoApplicationService.java | 58 +++++++++++-------- .../util/MaterialBaseInfoImportExcelUtil.java | 19 +++++- .../com/mhd/wms/util/ZhTextNormalizeUtil.java | 15 ++++- 3 files changed, 66 insertions(+), 26 deletions(-) diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/materialBaseInfo/MaterialBaseInfoApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/materialBaseInfo/MaterialBaseInfoApplicationService.java index bdd968c8b..e74ed185d 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/materialBaseInfo/MaterialBaseInfoApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/materialBaseInfo/MaterialBaseInfoApplicationService.java @@ -435,12 +435,6 @@ public class MaterialBaseInfoApplicationService { continue; } - if (!isValidOrgId(row.getOrganizationId()) && isValidOrgId(loginOrgId)) { - row.setOrganizationId(loginOrgId); - } - if (row.getTopOrganizationId() == null && isValidOrgId(loginTopOrgId)) { - row.setTopOrganizationId(loginTopOrgId); - } if (row.getNullify() == null) { row.setNullify(2); } @@ -450,11 +444,16 @@ public class MaterialBaseInfoApplicationService { if (StringUtils.isBlank(row.getHsCode()) && StringUtils.isNotBlank(row.getHsCodeImport())) { row.setHsCode(row.getHsCodeImport().trim()); } - // Excel 表头错位或重复时,HS 可能被读入「物料条形码」列;与 HS 完全相同时视为误填,保留 hsCode、清空条码 normalizeImportBarCodeWhenDuplicateOfHs(row); - // 先解析货主并补全组织,再做重复/存在性校验(组织维度依赖 organizationId) + // 客户模板通常只有「货主名称」无「货主id」:须先按名称解析货主,再回填组织;勿提前写入登录组织以免组织校验拦截货主匹配 fillIdsFromExistingMasterData(row); fillOrganizationFromShipperIfNeeded(row); + if (!isValidOrgId(row.getOrganizationId()) && isValidOrgId(loginOrgId)) { + row.setOrganizationId(loginOrgId); + } + if (row.getTopOrganizationId() == null && isValidOrgId(loginTopOrgId)) { + row.setTopOrganizationId(loginTopOrgId); + } fillOrganizationName(row, loginUser); String shipperCode = StringUtils.defaultString(row.getShipperCode(), ""); @@ -677,15 +676,28 @@ public class MaterialBaseInfoApplicationService { String shipperName = StringUtils.isNotBlank(row.getShipperName()) ? row.getShipperName().trim() : null; String shipperCode = StringUtils.isNotBlank(row.getShipperCode()) ? row.getShipperCode().trim() : null; + UserPo matched = resolveShipperUserForImport(shipperName, shipperCode, importOrgId, true); + if (matched == null) { + matched = resolveShipperUserForImport(shipperName, shipperCode, importOrgId, false); + } + if (matched != null) { + applyUserPoToMaterialImportRow(row, matched); + } + } + + /** + * @param enforceOrganization true=货主 organizationId 须与 importOrgId 一致;false=跨组织也接受并回填货主所属组织 + */ + private UserPo resolveShipperUserForImport(String shipperName, String shipperCode, Long importOrgId, + boolean enforceOrganization) { if (StringUtils.isNotBlank(shipperName)) { for (String nameVariant : ZhTextNormalizeUtil.nameLookupVariants(shipperName)) { try { AjaxResult ajaxResult = userServiceFeign.getInfoByName(nameVariant); if ("200".equals(String.valueOf(ajaxResult.get("code"))) && ajaxResult.get("data") != null) { UserPo userPo = JSON.parseObject(JSONObject.toJSONString(ajaxResult.get("data")), UserPo.class); - if (userPo != null && shipperUserMatchesImportOrganization(userPo, importOrgId)) { - applyUserPoToMaterialImportRow(row, userPo); - return; + if (userPo != null && shipperUserMatchesImportOrganization(userPo, importOrgId, enforceOrganization)) { + return userPo; } } } catch (Exception e) { @@ -697,7 +709,7 @@ public class MaterialBaseInfoApplicationService { try { AjaxResult shipperListResult = userServiceFeign.userShipperListAll(); if (!"200".equals(String.valueOf(shipperListResult.get("code"))) || shipperListResult.get("data") == null) { - return; + return null; } Object data = shipperListResult.get("data"); List> shipperList; @@ -719,7 +731,7 @@ public class MaterialBaseInfoApplicationService { shipperList = JSON.parseObject(JSONObject.toJSONString(data), new TypeReference>>() { }); } if (shipperList == null || shipperList.isEmpty()) { - return; + return null; } for (Map shipper : shipperList) { if (shipper == null) { @@ -738,15 +750,15 @@ public class MaterialBaseInfoApplicationService { } String normalizedName = StringUtils.isNotBlank(shipperName) ? shipperName : ""; String normalizedCode = StringUtils.isNotBlank(shipperCode) ? shipperCode : ""; - boolean matched = false; + boolean nameMatched = false; if (StringUtils.isNotEmpty(normalizedCode)) { String c1 = userCode != null ? String.valueOf(userCode).trim() : ""; String c2 = userMemberCode != null ? String.valueOf(userMemberCode).trim() : ""; if (normalizedCode.equals(c1) || normalizedCode.equals(c2)) { - matched = true; + nameMatched = true; } } - if (!matched && StringUtils.isNotEmpty(normalizedName)) { + if (!nameMatched && StringUtils.isNotEmpty(normalizedName)) { for (Object cand : new Object[] { userName, entName }) { if (cand == null) { continue; @@ -754,12 +766,12 @@ public class MaterialBaseInfoApplicationService { String s = String.valueOf(cand).trim(); if (ZhTextNormalizeUtil.textEquals(normalizedName, s) || ZhTextNormalizeUtil.textContains(s, normalizedName)) { - matched = true; + nameMatched = true; break; } } } - if (matched && userId != null) { + if (nameMatched && userId != null) { try { Long candidateId = Long.valueOf(String.valueOf(userId)); AjaxResult infoRes = userServiceFeign.getInfo(candidateId); @@ -767,9 +779,8 @@ public class MaterialBaseInfoApplicationService { continue; } UserPo up = JSON.parseObject(JSONObject.toJSONString(infoRes.get("data")), UserPo.class); - if (shipperUserMatchesImportOrganization(up, importOrgId)) { - applyUserPoToMaterialImportRow(row, up); - return; + if (shipperUserMatchesImportOrganization(up, importOrgId, enforceOrganization)) { + return up; } } catch (Exception ex) { log.debug("物料导入: 从货主列表解析用户失败: {}", ex.getMessage()); @@ -779,6 +790,7 @@ public class MaterialBaseInfoApplicationService { } catch (Exception e) { log.debug("物料导入: userShipperListAll 失败: {}", e.getMessage()); } + return null; } private void applyUserPoToMaterialImportRow(MaterialBaseInfoDTO row, UserPo userPo) { @@ -826,8 +838,8 @@ public class MaterialBaseInfoApplicationService { return organizationId != null && organizationId > 0; } - private boolean shipperUserMatchesImportOrganization(UserPo userPo, Long importOrganizationId) { - if (importOrganizationId == null) { + private boolean shipperUserMatchesImportOrganization(UserPo userPo, Long importOrganizationId, boolean enforceOrganization) { + if (!enforceOrganization || importOrganizationId == null) { return true; } if (userPo == null) { diff --git a/mhd_wms/src/main/java/com/mhd/wms/util/MaterialBaseInfoImportExcelUtil.java b/mhd_wms/src/main/java/com/mhd/wms/util/MaterialBaseInfoImportExcelUtil.java index beb1bff5a..678a72e6d 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/util/MaterialBaseInfoImportExcelUtil.java +++ b/mhd_wms/src/main/java/com/mhd/wms/util/MaterialBaseInfoImportExcelUtil.java @@ -13,7 +13,9 @@ import org.apache.poi.ss.usermodel.WorkbookFactory; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * 物料主数据导入:支持繁体中文表头的 Excel 解析。 @@ -23,6 +25,19 @@ public final class MaterialBaseInfoImportExcelUtil { private MaterialBaseInfoImportExcelUtil() { } + /** 客户模板常见表头别名 → 系统 @Excel 标准表头 */ + private static final Map HEADER_ALIASES = new HashMap<>(); + + static { + HEADER_ALIASES.put("条形码", "物料条形码"); + HEADER_ALIASES.put("保質期(天)", "保质期 单位:天"); + HEADER_ALIASES.put("保质期(天)", "保质期 单位:天"); + HEADER_ALIASES.put("净重(kg)", "净重 单位:千克"); + HEADER_ALIASES.put("淨重(kg)", "净重 单位:千克"); + HEADER_ALIASES.put("体积(m³)", "体积 单位:立方米"); + HEADER_ALIASES.put("體積(m³)", "体积 单位:立方米"); + } + public static List importRows(InputStream is) throws Exception { Workbook workbook = WorkbookFactory.create(is); try { @@ -54,7 +69,9 @@ public final class MaterialBaseInfoImportExcelUtil { if (StringUtils.isBlank(value)) { continue; } - cell.setCellValue(ZhTextNormalizeUtil.normalizeExcelHeader(value)); + String normalized = ZhTextNormalizeUtil.normalizeExcelHeader(value); + String alias = HEADER_ALIASES.get(normalized); + cell.setCellValue(alias != null ? alias : normalized); } } } diff --git a/mhd_wms/src/main/java/com/mhd/wms/util/ZhTextNormalizeUtil.java b/mhd_wms/src/main/java/com/mhd/wms/util/ZhTextNormalizeUtil.java index d610b746c..eb7cfac4a 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/util/ZhTextNormalizeUtil.java +++ b/mhd_wms/src/main/java/com/mhd/wms/util/ZhTextNormalizeUtil.java @@ -49,14 +49,25 @@ public final class ZhTextNormalizeUtil { if (a == null || b == null) { return false; } - return toSimple(a).equals(toSimple(b)); + return normalizeNameKey(a).equals(normalizeNameKey(b)); } public static boolean textContains(String haystack, String needle) { if (StringUtils.isBlank(haystack) || StringUtils.isBlank(needle)) { return false; } - return toSimple(haystack).contains(toSimple(needle)); + return normalizeNameKey(haystack).contains(normalizeNameKey(needle)); + } + + /** 简繁体 + 全角括号等常见差异归一化,便于货主/分类名称匹配。 */ + public static String normalizeNameKey(String text) { + if (StringUtils.isBlank(text)) { + return text; + } + String s = toSimple(text.trim()); + s = s.replace('(', '(').replace(')', ')'); + s = s.replace(' ', ' '); + return s; } /**