Procházet zdrojové kódy

pms 更新SAP库存

zhangcl před 2 měsíci
rodič
revize
b41d7f4460

+ 134 - 5
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/sap/service/IotSapServiceImpl.java

@@ -457,8 +457,106 @@ public class IotSapServiceImpl implements IotSapService {
                 });
             }
         });
+        // 查询所有SAP库存集合A,以 ‘库存地点+物料编码’ 为唯一key 如果 sapStocks 中有物料不在A中 新增物料
+        Set<String> existStockKeys = new HashSet<>();
+        List<IotSapStockDO> existStocks = TenantUtils.execute(1L, () -> iotSapStockMapper.selectList());
+        if (CollUtil.isNotEmpty(existStocks)) {
+            existStockKeys = existStocks.stream()
+                    .filter(stk -> ObjUtil.isNotEmpty(stk) && StrUtil.isNotBlank(stk.getMaterialCode()) && ObjUtil.isNotEmpty(stk.getStorageLocationId()))  // 过滤非空对象和非空code
+                    .map(stk -> StrUtil.join("-", String.valueOf(stk.getStorageLocationId()), stk.getMaterialCode()))
+                    .collect(Collectors.toSet());
+        }
+        // 将已经存在的库存数据 设置成 Map<String, IotSapStockDO> 的形式 便于后续更新
+        // key库存地点id-物料编码       value库存对象   从此集合中筛选将要被更新的库存对象
+        Map<String, IotSapStockDO> tobeUpdatedStockPair = new HashMap<>();
+        tobeUpdatedStockPair = existStocks.stream()
+                .filter(stk -> StrUtil.isNotBlank(stk.getMaterialCode()) && ObjUtil.isNotEmpty(stk.getStorageLocationId())
+                        && stockLocationCodeIdPair.containsKey(stk.getStorageLocationId()))
+                .collect(Collectors.toMap(
+                        stk -> StrUtil.join("-", stk.getStorageLocationId(), stk.getMaterialCode()),
+                        stk -> stk, // 值为对象本身
+                        (existing, replacement) -> existing // 处理键冲突: 保留先出现的元素
+                ));
+
+        System.out.println(factoryCode + "当前库中已有sap库存数量:" + existStockKeys.size());
+        // 找出需要新增的库存(SAP物料编码去掉前导零后,不在现有物料集合中的记录)
+        Set<String> finalExistStockKeys = existStockKeys;
+        List<IotSapStockVO> newStocks = sapStocks.stream()
+                .filter(stk -> StrUtil.isNotBlank(stk.getMATNR()) && StrUtil.isNotBlank(stk.getLGORT())
+                        && storageLocationIdPair.containsKey(stk.getLGORT()))
+                .filter(stk -> {
+                    // 处理前导零:移除MATNR前的 00000000
+                    String processedCode = stk.getMATNR().replaceFirst("^0+", "");
+                    // 本地已经配置过库存地点 包含SAP库存接口返回的库存地点
+                    Long storageLocationId = storageLocationIdPair.get(stk.getLGORT());
+                    return !finalExistStockKeys.contains(StrUtil.join("-", storageLocationId, processedCode));
+                })
+                .collect(Collectors.toList());
+        System.out.println(factoryCode + "需要新增的sap库存数量:" + newStocks.size());
+        // 新增SAP库存数据
+        List<IotSapStockDO> tobeAddedStocks = new ArrayList<>();
+        if (CollUtil.isNotEmpty(newStocks)) {
+            newStocks.forEach(stock -> {
+                // 只保存pms维护过库存地点的数据
+                if (locationCodeDeptIdPair.containsKey(stock.getLGORT())) {
+                    IotSapStockDO sapStock = new IotSapStockDO();
+                    // 部门id
+                    sapStock.setDeptId(locationCodeDeptIdPair.get(stock.getLGORT()));
+                    // 工厂id
+                    if (factoryIdPair.containsKey(stock.getWERKS())) {
+                        sapStock.setFactoryId(factoryIdPair.get(stock.getWERKS()));
+                    }
+                    // 工厂名称
+                    if (factoryNamePair.containsKey(stock.getWERKS())) {
+                        sapStock.setFactory(factoryNamePair.get(stock.getWERKS()));
+                    }
+                    // 库存地点id
+                    if (storageLocationIdPair.containsKey(stock.getLGORT())) {
+                        sapStock.setStorageLocationId(storageLocationIdPair.get(stock.getLGORT()));
+                    }
+                    // 库存地点名称
+                    if (stockLocationNamePair.containsKey(stock.getLGORT())) {
+                        sapStock.setProjectDepartment(stockLocationNamePair.get(stock.getLGORT()));
+                    }
+                    // 物料编码 需要去掉前缀 00000000
+                    sapStock.setMaterialCode(stock.getMATNR().replaceFirst("^0+", ""));
+                    // 物料描述
+                    sapStock.setMaterialName(stock.getMAKTX());
+                    // 库存数量
+                    sapStock.setQuantity(stock.getLABST());
+                    // 单价
+                    sapStock.setUnitPrice(stock.getJIAGE());
+                    // 基本单位
+                    sapStock.setUnit(stock.getMEINS());
+                    // 同步时间
+                    sapStock.setSyncTime(LocalDateTime.now());
+                    tobeAddedStocks.add(sapStock);
+                }
+            });
+        }
+        // 使用返回的SAP库存数据更新已有的 库存数据
+        // pms中已有 SAP返回数据中也存在 则更新
+        List<IotSapStockDO> actualUpdatedStocks = new ArrayList<>();
+        // key库存id-物料编码      value库存对象
+        Map<String, IotSapStockVO> existStockPair = createExistStockMap(sapStocks, existStockKeys, storageLocationIdPair);
+        if (CollUtil.isNotEmpty(existStockPair)) {
+            Map<String, IotSapStockDO> finalTobeUpdatedStockPair = tobeUpdatedStockPair;
+            existStockPair.forEach((k, v) -> {
+                if (finalTobeUpdatedStockPair.containsKey(k)) {
+                    IotSapStockDO sapStock = finalTobeUpdatedStockPair.get(k);
+                    sapStock.setUnitPrice(v.getJIAGE());    // 更新库存价格
+                    sapStock.setQuantity(v.getLABST());     // 更新库存数量
+                    sapStock.setUnit(v.getMEINS());         // 更新基本单位
+                    actualUpdatedStocks.add(sapStock);
+                }
+            });
+        }
+        System.out.println(factoryCode + "需要更新的SAP库存数量:" + actualUpdatedStocks.size());
+        // pms中已有 但是 SAP返回数据不存在 如果设置了安全库存,则库存为0,若没有设置安全库存,则可以删除
+
+
         // 遍历明细数据 新增 修改 SAP库存数据
-        List<IotSapStockDO> tobeSapStocks = new ArrayList<>();
+        /* List<IotSapStockDO> tobeSapStocks = new ArrayList<>();
         sapStocks.forEach(stock -> {
             // 只保存pms维护过库存地点的数据
             if (locationCodeDeptIdPair.containsKey(stock.getLGORT())) {
@@ -481,7 +579,7 @@ public class IotSapServiceImpl implements IotSapService {
                 if (stockLocationNamePair.containsKey(stock.getLGORT())) {
                     sapStock.setProjectDepartment(stockLocationNamePair.get(stock.getLGORT()));
                 }
-                // 物料编码
+                // 物料编码 需要去掉前缀 00000000
                 sapStock.setMaterialCode(stock.getMATNR());
                 // 物料描述
                 sapStock.setMaterialName(stock.getMAKTX());
@@ -495,10 +593,14 @@ public class IotSapServiceImpl implements IotSapService {
                 sapStock.setSyncTime(LocalDateTime.now());
                 tobeSapStocks.add(sapStock);
             }
-        });
+        }); */
         // 本地库存 初始化 批量插入本地库存 记录
-        if (CollUtil.isNotEmpty(tobeSapStocks)) {
-            TenantUtils.execute(1L, () -> iotSapStockMapper.insertBatch(tobeSapStocks));
+        if (CollUtil.isNotEmpty(tobeAddedStocks)) {
+            TenantUtils.execute(1L, () -> iotSapStockMapper.insertBatch(tobeAddedStocks));
+        }
+        // pms中存在而且SAP接口也返回的库存数据:更新
+        if (CollUtil.isNotEmpty(actualUpdatedStocks)) {
+            TenantUtils.execute(1L, () -> iotSapStockMapper.updateBatch(actualUpdatedStocks));
         }
     }
 
@@ -524,4 +626,31 @@ public class IotSapServiceImpl implements IotSapService {
                         (existing, replacement) -> existing // 如果有重复的key,保留第一个值
                 ));
     }
+
+    /**
+     * sap库存 更新 创建 唯一key(库存地点id-物料编码) 到 sap库存对象 的映射
+     * pms中已有的库存  SAP库存接口也返回了 需要更新
+     * @param sapStocks SAP库存列表
+     * @param existStockKeys 数据库中已存在的 sap库存 集合
+     * @param storageLocationIdPair key库存地点code    value库存地点id
+     * @return 物料编码到描述的映射
+     */
+    private Map<String, IotSapStockVO> createExistStockMap(List<IotSapStockVO> sapStocks, Set<String> existStockKeys, Map<String, Long> storageLocationIdPair) {
+        return sapStocks.stream()
+                .filter(sapStock -> StrUtil.isNotBlank(sapStock.getMATNR()) &&
+                        ObjUtil.isNotEmpty(sapStock.getLGORT()) && storageLocationIdPair.containsKey(sapStock.getLGORT()))
+                .map(sapStock -> {
+                    // 处理前导零:移除MATNR前的 00000000
+                    String processedCode = sapStock.getMATNR().replaceFirst("^0+", "");
+                    // 本地已经配置过库存地点 包含SAP库存接口返回的库存地点
+                    Long storageLocationId = storageLocationIdPair.get(sapStock.getLGORT());
+                    return new AbstractMap.SimpleEntry<>(StrUtil.join("-", storageLocationId, processedCode), sapStock);
+                })
+                .filter(entry -> existStockKeys.contains(entry.getKey()))
+                .collect(Collectors.toMap(
+                        Map.Entry::getKey,
+                        Map.Entry::getValue,
+                        (existing, replacement) -> existing // 如果有重复的key,保留第一个值
+                ));
+    }
 }