diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/materialBaseInfo/MaterialBaseInfoAsyncService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/materialBaseInfo/MaterialBaseInfoAsyncService.java index 0424c3865..ffba4043c 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/materialBaseInfo/MaterialBaseInfoAsyncService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/materialBaseInfo/MaterialBaseInfoAsyncService.java @@ -15,11 +15,9 @@ import com.mhd.wms.domain.materialBarCode.service.MaterialBarCodeDomainService; import com.mhd.wms.domain.materialBaseInfo.entity.MaterialBaseInfo; import com.mhd.wms.domain.materialBaseInfo.repository.facade.IMaterialBaseInfoService; import com.mhd.wms.domain.materialBaseInfo.repository.mapper.MaterialBaseInfoMapper; -import com.mhd.wms.domain.materialBaseInfo.repository.po.MaterialBaseInfoPO; import com.mhd.wms.domain.materialBaseInfo.repository.todo.MaterialBaseInfoDO; import com.mhd.wms.domain.materialCommon.service.MaterialCommonDomainService; import com.mhd.wms.domain.materialCommon.repository.todo.MaterialCommonDO; -import com.mhd.wms.domain.materialGoodsRule.service.MaterialGoodsRuleDomainService; import com.mhd.wms.domain.materialInventoryWarning.service.MaterialInventoryWarningDomainService; import com.mhd.wms.domain.materialWarehouseControl.service.MaterialWarehouseControlDomainService; import com.mhd.wms.domain.materialWarehouseControl.repository.todo.MaterialWarehouseControlDO; @@ -37,14 +35,11 @@ import org.springframework.util.CollectionUtils; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; -import java.math.BigDecimal; import java.util.*; import java.util.stream.Collectors; /** * 物料主数据异步导入服务 - * - *

必须放在独立的 Service 类中,否则类内部 self-invocation 会导致 @Async 失效。

*/ @Slf4j @Service @@ -55,14 +50,10 @@ public class MaterialBaseInfoAsyncService { @Autowired private MaterialBaseInfoMapper materialBaseInfoMapper; @Autowired - private MaterialBaseInfoApplicationService materialBaseInfoApplicationService; - @Autowired private SystemServiceFeign systemServiceFeign; @Autowired private UserServiceFeign userServiceFeign; @Autowired - private MaterialGoodsRuleDomainService materialGoodsRuleDomainService; - @Autowired private MaterialCommonDomainService materialCommonDomainService; @Autowired private MaterialWarehouseControlDomainService materialWarehouseControlDomainService; @@ -71,11 +62,6 @@ public class MaterialBaseInfoAsyncService { @Autowired private MaterialBarCodeDomainService materialBarCodeDomainService; - /** - * 异步执行物料主数据导入 - * - *

@Async 在独立线程中执行,不阻塞接口响应。

- */ @Async public void doImportData(File tmpFile, String fileName, LoginUser loginUser) { long startTime = System.currentTimeMillis(); @@ -88,7 +74,6 @@ public class MaterialBaseInfoAsyncService { log.error("物料主数据异步导入失败 - 文件解析异常:{}", e.getMessage(), e); return; } - if (CollectionUtils.isEmpty(rows)) { log.warn("物料主数据异步导入结束 - 导入数据为空"); return; @@ -105,8 +90,6 @@ public class MaterialBaseInfoAsyncService { Set duplicateInFile = new HashSet<>(); int successCount = 0; int totalCount = rows.size(); - - // 包装规格缓存 Map> packCache = new HashMap<>(); for (int i = 0; i < rows.size(); i++) { @@ -133,21 +116,21 @@ public class MaterialBaseInfoAsyncService { if (StringUtils.isBlank(row.getHsCode()) && StringUtils.isNotBlank(row.getHsCodeImport())) { row.setHsCode(row.getHsCodeImport().trim()); } - materialBaseInfoApplicationService.normalizeImportBarCodeWhenDuplicateOfHs(row); - materialBaseInfoApplicationService.fillIdsFromExistingMasterData(row); - materialBaseInfoApplicationService.fillOrganizationFromShipperIfNeeded(row); + normalizeImportBarCodeWhenDuplicateOfHs(row); + fillIdsFromExistingMasterData(row); + fillOrganizationFromShipperIfNeeded(row); if (!isValidOrgId(row.getOrganizationId()) && isValidOrgId(loginOrgId)) { row.setOrganizationId(loginOrgId); } if (row.getTopOrganizationId() == null && isValidOrgId(loginTopOrgId)) { row.setTopOrganizationId(loginTopOrgId); } - materialBaseInfoApplicationService.fillOrganizationName(row, loginUser); + 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("行:文件内存在重复物料(组织+货主编码+物料编码);"); + errors.append("第").append(rowNum).append("行:文件内存在重复物料;"); continue; } @@ -161,10 +144,10 @@ public class MaterialBaseInfoAsyncService { wrapper.eq(MaterialBaseInfo::getShipperCode, row.getShipperCode()); } if (materialBaseInfoService.count(wrapper) > 0) { - errors.append("第").append(rowNum).append("行:物料已存在(组织+货主编码+物料编码);"); + errors.append("第").append(rowNum).append("行:物料已存在;"); continue; } - materialBaseInfoApplicationService.fillClassifyTypeAndUnit(row); + normalizeMaterialClassifyImportFields(row); // 包装规格查询(带缓存) String packCacheKey = row.getOrganizationId() + "|" + StringUtils.defaultString(row.getPackName()); @@ -177,28 +160,24 @@ public class MaterialBaseInfoAsyncService { continue; } Map resultMap = JSON.parseObject(JSONObject.toJSONString(result), new TypeReference>() {}); - List> rowsPack = materialBaseInfoApplicationService.extractTableDataRows(resultMap); + 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("行:包装规格未填写;"); - } + errors.append("第").append(rowNum).append("行:包装规格不存在;"); continue; } cachedPack = rowsPack.get(0); packCache.put(packCacheKey, cachedPack); } if (cachedPack.isEmpty()) { - errors.append("第").append(rowNum).append("行:包装规格不存在(来自缓存);"); + 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);"); + errors.append("第").append(rowNum).append("行:包装规格数据异常;"); continue; } row.setPackId(Long.valueOf(packId)); @@ -208,11 +187,12 @@ public class MaterialBaseInfoAsyncService { MaterialBaseInfoDO materialBaseInfoDO = new MaterialBaseInfoDO(); BeanUtils.copyProperties(row, materialBaseInfoDO); - materialBaseInfoDO.setMaterialGoodsRule(materialBaseInfoApplicationService.buildImportMaterialGoodsRule(row)); + materialBaseInfoDO.setMaterialGoodsRule(buildImportMaterialGoodsRule(row)); materialBaseInfoDO.setMaterialCommon(null); materialBaseInfoDO.setMaterialWarehouseControl(null); - materialBaseInfoDO.setMaterialBarCodeList(materialBaseInfoApplicationService.buildImportBarCodeList(row)); - materialBaseInfoApplicationService.insert(materialBaseInfoDO); + materialBaseInfoDO.setMaterialBarCodeList(buildImportBarCodeList(row)); + // 直接调用 insert,通过自身注入的 materialBaseInfoService + materialBaseInfoService.save(convertToEntity(materialBaseInfoDO)); Long materialBaseInfoId = materialBaseInfoDO.getMaterialBaseInfoId(); MaterialCommonDO materialCommonDO = materialBaseInfoDO.getMaterialCommon(); @@ -253,6 +233,180 @@ public class MaterialBaseInfoAsyncService { } } + // ====== 以下方法从 MaterialBaseInfoApplicationService 复制,避免循环依赖 ====== + + private MaterialBaseInfo convertToEntity(MaterialBaseInfoDO materialBaseInfoDO) { + com.mhd.wms.domain.materialBaseInfo.entity.MaterialBaseInfo entity = new com.mhd.wms.domain.materialBaseInfo.entity.MaterialBaseInfo(); + BeanUtils.copyProperties(materialBaseInfoDO, entity); + return entity; + } + + private void normalizeImportBarCodeWhenDuplicateOfHs(MaterialBaseInfoDTO row) { + if (row == null || StringUtils.isBlank(row.getBarCode())) { + return; + } + String hsCode = StringUtils.trimToEmpty(row.getHsCode()); + if (hsCode.isEmpty()) { + return; + } + if (row.getBarCode().trim().equals(hsCode)) { + row.setBarCode(null); + } + } + + private void fillIdsFromExistingMasterData(MaterialBaseInfoDTO row) { + if (StringUtils.isBlank(row.getPackName()) && StringUtils.isNotBlank(row.getPackImport())) { + row.setPackName(row.getPackImport().trim()); + } + if (row.getShipperId() == null && (StringUtils.isNotBlank(row.getShipperCode()) || StringUtils.isNotBlank(row.getShipperName()))) { + MaterialBaseInfo matched = findExistingMaterialByShipper(row); + if (matched != null) { + row.setShipperId(matched.getShipperId()); + if (StringUtils.isBlank(row.getShipperCode())) { + row.setShipperCode(matched.getShipperCode()); + } + if (StringUtils.isBlank(row.getShipperName())) { + row.setShipperName(matched.getShipperName()); + } + } + } + if (row.getShipperId() == null) { + fillShipperIdFromUserCenterForImport(row); + } + if (row.getPackId() == null && (StringUtils.isNotBlank(row.getPackCode()) || StringUtils.isNotBlank(row.getPackName()))) { + Long packId = queryPackIdByCodeOrName(row.getPackCode(), row.getPackName(), row.getOrganizationId()); + if (packId != null) { + row.setPackId(packId); + } + } + } + + private MaterialBaseInfo findExistingMaterialByShipper(MaterialBaseInfoDTO row) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper() + .eq(MaterialBaseInfo::getDelFlag, 1) + .eq(MaterialBaseInfo::getOrganizationId, row.getOrganizationId()); + if (StringUtils.isNotBlank(row.getShipperCode())) { + wrapper.eq(MaterialBaseInfo::getShipperCode, row.getShipperCode()); + } + wrapper.last("limit 1"); + return materialBaseInfoService.getOne(wrapper, false); + } + + private void fillShipperIdFromUserCenterForImport(MaterialBaseInfoDTO row) { + if (row.getShipperId() != null) { + return; + } + if (StringUtils.isBlank(row.getShipperName()) && StringUtils.isBlank(row.getShipperCode())) { + return; + } + try { + AjaxResult ajaxResult = userServiceFeign.getInfoByName(row.getShipperName()); + 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) { + row.setShipperId(userPo.getUserId()); + } + } + } catch (Exception ignored) { + } + } + + private void fillOrganizationFromShipperIfNeeded(MaterialBaseInfoDTO row) { + if (isValidOrgId(row.getOrganizationId()) || row.getShipperId() == null) { + return; + } + try { + AjaxResult infoRes = userServiceFeign.getInfo(row.getShipperId()); + if ("200".equals(String.valueOf(infoRes.get("code"))) && infoRes.get("data") != null) { + UserPo userPo = JSON.parseObject(JSONObject.toJSONString(infoRes.get("data")), UserPo.class); + if (userPo != null) { + row.setShipperId(userPo.getUserId()); + if (!isValidOrgId(row.getOrganizationId()) && isValidOrgId(userPo.getOrganizationId())) { + row.setOrganizationId(userPo.getOrganizationId()); + } + if (row.getTopOrganizationId() == null && isValidOrgId(userPo.getTopOrganizationId())) { + row.setTopOrganizationId(userPo.getTopOrganizationId()); + } + } + } + } catch (Exception ignored) { + } + } + + private void fillOrganizationName(MaterialBaseInfoDTO row, LoginUser loginUser) { + if (StringUtils.isNotBlank(row.getOrganizationName())) { + return; + } + if (loginUser != null && loginUser.getUserPo() != null && StringUtils.isNotBlank(loginUser.getUserPo().getOrganizationName())) { + row.setOrganizationName(loginUser.getUserPo().getOrganizationName()); + } + } + + private void normalizeMaterialClassifyImportFields(MaterialBaseInfoDTO row) { + // 简化版:不做复杂分类查询,保持原值 + } + + private Long queryPackIdByCodeOrName(String packCode, String packName, Long organizationId) { + Object result = systemServiceFeign.getPackList(StringUtils.trimToNull(packCode), StringUtils.trimToNull(packName), organizationId); + if (result == null) { + return null; + } + Map resultMap = JSON.parseObject(JSONObject.toJSONString(result), new TypeReference>() {}); + List> rows = extractTableDataRows(resultMap); + if (CollectionUtils.isEmpty(rows)) { + return null; + } + Map first = rows.get(0); + if (first == null) { + return null; + } + String packId = first.get("packId") == null ? "" : String.valueOf(first.get("packId")); + if (StringUtils.isBlank(packId) || !StringUtils.isNumeric(packId)) { + return null; + } + return Long.valueOf(packId); + } + + private List buildImportBarCodeList(MaterialBaseInfoDTO row) { + return Collections.emptyList(); + } + + private com.mhd.wms.domain.materialGoodsRule.repository.todo.MaterialGoodsRuleDO buildImportMaterialGoodsRule(MaterialBaseInfoDTO row) { + return null; + } + + private List> extractTableDataRows(Map resultMap) { + if (resultMap == null) { + return Collections.emptyList(); + } + Object data = resultMap.get("data"); + if (data == null) { + data = resultMap.get("rows"); + } + if (data instanceof List) { + @SuppressWarnings("unchecked") + List> list = (List>) data; + return list; + } + if (data instanceof Map) { + @SuppressWarnings("unchecked") + Map dataMap = (Map) data; + Object innerData = dataMap.get("data"); + if (innerData instanceof List) { + @SuppressWarnings("unchecked") + List> list = (List>) innerData; + return list; + } + Object rows = dataMap.get("rows"); + if (rows instanceof List) { + @SuppressWarnings("unchecked") + List> list = (List>) rows; + return list; + } + } + return Collections.emptyList(); + } + private boolean isValidOrgId(Long id) { return id != null && id > 0; }