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 b78ffebcd..56f2c7319 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 @@ -103,6 +103,10 @@ public class MaterialBaseInfoApplicationService { @Resource private MaterialBaseInfoMapper materialBaseInfoMapper; + + @Autowired + private MaterialBaseInfoAsyncService materialBaseInfoAsyncService; + /** * 分页查询物料基础信息列表 */ @@ -472,202 +476,12 @@ public class MaterialBaseInfoApplicationService { } LoginUser loginUser = SecurityUtils.getLoginUser(); - // 异步执行导入 - doImportData(tmpFile, fileName, loginUser); + // 通过独立的异步 Service 执行导入(避免类内部 self-invocation 导致 @Async 失效) + materialBaseInfoAsyncService.doImportData(tmpFile, fileName, loginUser); return AjaxResult.success("导入任务已提交,正在后台异步处理,请稍后查看导入结果日志"); } - /** - * 异步执行物料主数据导入 - * - *

@Async 确保在独立线程中执行,不阻塞接口响应。 - * 每行独立事务,避免大事务锁表导致性能问题。

- */ - @Async - public void doImportData(File tmpFile, String fileName, LoginUser loginUser) { - long startTime = System.currentTimeMillis(); - log.info("=== 物料主数据异步导入开始,文件:{},大小:{}KB ===", fileName, tmpFile.length() / 1024); - try { - List rows; - try (InputStream is = new java.io.FileInputStream(tmpFile)) { - rows = MaterialBaseInfoImportExcelUtil.importRows(is); - } catch (Exception e) { - log.error("物料主数据异步导入失败 - 文件解析异常:{}", e.getMessage(), e); - return; - } - - if (CollectionUtils.isEmpty(rows)) { - log.warn("物料主数据异步导入结束 - 导入数据为空"); - return; - } - - Long loginOrgId = null; - Long loginTopOrgId = null; - if (loginUser != null && loginUser.getUserPo() != null) { - loginOrgId = loginUser.getUserPo().getOrganizationId(); - loginTopOrgId = loginUser.getUserPo().getTopOrganizationId(); - } - - StringBuilder errors = new StringBuilder(); - Set duplicateInFile = new HashSet<>(); - int successCount = 0; - int totalCount = rows.size(); - - // 包装规格缓存:避免 5000 行数据对 system 服务发起 5000 次重复远程调用 - Map> packCache = new HashMap<>(); - - for (int i = 0; i < rows.size(); i++) { - MaterialBaseInfoDTO row = rows.get(i); - int rowNum = i + 2; - if (row == null) { - continue; - } - try { - if (StringUtils.isBlank(row.getMaterialCode())) { - errors.append("第").append(rowNum).append("行:物料编码不能为空;"); - continue; - } - if (StringUtils.isBlank(row.getMaterialName())) { - errors.append("第").append(rowNum).append("行:物料名称不能为空;"); - continue; - } - if (row.getNullify() == null) { - row.setNullify(2); - } - if (row.getCommon() == null) { - row.setCommon(2); - } - if (StringUtils.isBlank(row.getHsCode()) && StringUtils.isNotBlank(row.getHsCodeImport())) { - row.setHsCode(row.getHsCodeImport().trim()); - } - normalizeImportBarCodeWhenDuplicateOfHs(row); - 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(), ""); - String duplicateKey = row.getOrganizationId() + "|" + shipperCode + "|" + row.getMaterialCode(); - if (!duplicateInFile.add(duplicateKey)) { - errors.append("第").append(rowNum).append("行:文件内存在重复物料(组织+货主编码+物料编码);"); - continue; - } - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(MaterialBaseInfo::getDelFlag, 1) - .eq(MaterialBaseInfo::getOrganizationId, row.getOrganizationId()) - .eq(MaterialBaseInfo::getMaterialCode, row.getMaterialCode()); - if (StringUtils.isBlank(row.getShipperCode())) { - wrapper.and(w -> w.isNull(MaterialBaseInfo::getShipperCode).or().eq(MaterialBaseInfo::getShipperCode, "")); - } else { - wrapper.eq(MaterialBaseInfo::getShipperCode, row.getShipperCode()); - } - if (materialBaseInfoService.count(wrapper) > 0) { - errors.append("第").append(rowNum).append("行:物料已存在(组织+货主编码+物料编码);"); - continue; - } - fillClassifyTypeAndUnit(row); - - // 包装规格查询(带本地缓存,避免 5000 行对 system 服务发起 5000 次远程调用) - String packCacheKey = row.getOrganizationId() + "|" + StringUtils.defaultString(row.getPackName()); - Map cachedPack = packCache.get(packCacheKey); - if (cachedPack == null) { - Object result = systemServiceFeign.getPackList(null, row.getPackName(), row.getOrganizationId()); - if (result == null) { - // 缓存空结果,避免重复查询不存在的包装规格 - packCache.put(packCacheKey, Collections.emptyMap()); - errors.append("第").append(rowNum).append("行:包装规格查询无返回,请稍后重试或检查系统服务;"); - continue; - } - Map resultMap = JSON.parseObject(JSONObject.toJSONString(result), new TypeReference>() {}); - List> rowsPack = extractTableDataRows(resultMap); - if (CollectionUtils.isEmpty(rowsPack)) { - packCache.put(packCacheKey, Collections.emptyMap()); - if (StringUtils.isNotBlank(row.getPackName())) { - errors.append("第").append(rowNum).append("行:包装规格「").append(row.getPackName()).append("」不存在或未在系统中维护;"); - } else { - errors.append("第").append(rowNum).append("行:包装规格未填写,或系统中无匹配的包装数据;"); - } - continue; - } - cachedPack = rowsPack.get(0); - packCache.put(packCacheKey, cachedPack); - } - if (cachedPack.isEmpty()) { - errors.append("第").append(rowNum).append("行:包装规格不存在(来自缓存);"); - continue; - } - if (cachedPack == null) { - errors.append("第").append(rowNum).append("行:包装规格查询结果为空;"); - continue; - } - String packCode = cachedPack.get("packCode") == null ? "" : String.valueOf(cachedPack.get("packCode")); - row.setPackCode(packCode); - String packId = cachedPack.get("packId") == null ? "" : String.valueOf(cachedPack.get("packId")); - if (StringUtils.isBlank(packId) || !StringUtils.isNumeric(packId)) { - errors.append("第").append(rowNum).append("行:包装规格数据异常(缺少包装ID);"); - continue; - } - row.setPackId(Long.valueOf(packId)); - String unitName = cachedPack.get("unitName") == null ? "" : String.valueOf(cachedPack.get("unitName")); - row.setUnitCode("EA"); - row.setUnitName(unitName); - - // 每行独立事务写入 - MaterialBaseInfoDO materialBaseInfoDO = new MaterialBaseInfoDO(); - BeanUtils.copyProperties(row, materialBaseInfoDO); - materialBaseInfoDO.setMaterialGoodsRule(buildImportMaterialGoodsRule(row)); - materialBaseInfoDO.setMaterialCommon(null); - materialBaseInfoDO.setMaterialWarehouseControl(null); - materialBaseInfoDO.setMaterialBarCodeList(buildImportBarCodeList(row)); - insert(materialBaseInfoDO); - Long materialBaseInfoId = materialBaseInfoDO.getMaterialBaseInfoId(); - - MaterialCommonDO materialCommonDO = materialBaseInfoDO.getMaterialCommon(); - if (materialCommonDO != null) { - materialCommonDO.setMaterialBaseInfoId(materialBaseInfoId); - materialCommonDomainService.insert(materialCommonDO); - } - MaterialWarehouseControlDO materialWarehouseControlDO = materialBaseInfoDO.getMaterialWarehouseControl(); - if (materialWarehouseControlDO != null) { - materialWarehouseControlDO.setMaterialBaseInfoId(materialBaseInfoId); - materialWarehouseControlDomainService.insert(materialWarehouseControlDO); - } - materialInventoryWarningDomainService.batchInsertOrUpdate(materialBaseInfoDO); - materialBarCodeDomainService.batchInsertOrUpdate(materialBaseInfoDO); - successCount++; - } catch (Exception e) { - log.error("物料主数据异步导入 - 第{}行处理异常", rowNum, e); - errors.append("第").append(rowNum).append("行:处理异常-").append(e.getMessage()).append(";"); - } - } - - long costTime = System.currentTimeMillis() - startTime; - if (errors.length() > 0) { - log.warn("=== 物料主数据异步导入完成,文件:{},总数:{},成功:{},失败:{},耗时:{}ms,失败原因:{} ===", - fileName, totalCount, successCount, totalCount - successCount, costTime, errors); - } else { - log.info("=== 物料主数据异步导入完成,文件:{},总数:{},成功:{},耗时:{}ms ===", - fileName, totalCount, successCount, costTime); - } - } finally { - // 清理临时文件 - try { - if (tmpFile.exists()) { - tmpFile.delete(); - } - } catch (Exception e) { - log.warn("物料主数据异步导入 - 临时文件清理失败:{}", e.getMessage()); - } - } - } - /** * 导入物料主数据(仅导入主表字段)- 原同步方法保留,供其他场景调用 */ @@ -826,7 +640,7 @@ public class MaterialBaseInfoApplicationService { /** * 使用已存在主数据按名称/编码反查并回填ID */ - private void fillIdsFromExistingMasterData(MaterialBaseInfoDTO row) { + public void fillIdsFromExistingMasterData(MaterialBaseInfoDTO row) { if (StringUtils.isBlank(row.getPackName()) && StringUtils.isNotBlank(row.getPackImport())) { row.setPackName(row.getPackImport().trim()); } @@ -1146,7 +960,7 @@ public class MaterialBaseInfoApplicationService { /** * Excel 已填货主 ID、但未填组织时,从货主用户补全组织信息。 */ - private void fillOrganizationFromShipperIfNeeded(MaterialBaseInfoDTO row) { + public void fillOrganizationFromShipperIfNeeded(MaterialBaseInfoDTO row) { if (isValidOrgId(row.getOrganizationId()) || row.getShipperId() == null) { return; } @@ -1205,7 +1019,7 @@ public class MaterialBaseInfoApplicationService { } } - private void fillOrganizationName(MaterialBaseInfoDTO row, LoginUser loginUser) { + public void fillOrganizationName(MaterialBaseInfoDTO row, LoginUser loginUser) { if (StringUtils.isNotBlank(row.getOrganizationName())) { return; } @@ -1225,7 +1039,7 @@ public class MaterialBaseInfoApplicationService { } } - private void fillClassifyTypeAndUnit(MaterialBaseInfoDTO row) { + public void fillClassifyTypeAndUnit(MaterialBaseInfoDTO row) { normalizeMaterialClassifyImportFields(row); // 按组织从 system 主数据反查分类编码,与名称列表对齐 fillMaterialClassifyCodesFromSystem(row); @@ -1406,7 +1220,7 @@ public class MaterialBaseInfoApplicationService { * 导入约定:「HS码/HS编码」与「物料条形码」为不同列。模板表头错位或两列误填相同 HS 时, * barCode 会与 hsCode 相同;此时保留 hsCode,清空主表/子表条码,避免 HS 写入 bar_code。 */ - private void normalizeImportBarCodeWhenDuplicateOfHs(MaterialBaseInfoDTO row) { + public void normalizeImportBarCodeWhenDuplicateOfHs(MaterialBaseInfoDTO row) { if (row == null) { return; } @@ -1421,7 +1235,7 @@ public class MaterialBaseInfoApplicationService { } } - private List buildImportBarCodeList(MaterialBaseInfoDTO row) { + public List buildImportBarCodeList(MaterialBaseInfoDTO row) { if (StringUtils.isBlank(row.getBarCode())) { return null; } @@ -1461,7 +1275,7 @@ public class MaterialBaseInfoApplicationService { return idObj == null ? null : Long.valueOf(String.valueOf(idObj)); } - private MaterialGoodsRuleDO buildImportMaterialGoodsRule(MaterialBaseInfoDTO row) { + public MaterialGoodsRuleDO buildImportMaterialGoodsRule(MaterialBaseInfoDTO row) { String batchName = StringUtils.isNotBlank(row.getBatchRuleNameImport()) ? row.getBatchRuleNameImport().trim() : (StringUtils.isNotBlank(row.getBatchName()) @@ -1536,7 +1350,7 @@ public class MaterialBaseInfoApplicationService { .trim(); } - private List> extractTableDataRows(Map resultMap) { + public List> extractTableDataRows(Map resultMap) { if (resultMap == null) { return new ArrayList<>(); }