|
@@ -19,6 +19,7 @@ import cn.iocoder.yudao.module.pms.dal.mysql.iotmaterial.IotSapMaterialMapper;
|
|
|
import cn.iocoder.yudao.module.pms.dal.mysql.iotsappickinglist.IotSapPickingListMapper;
|
|
|
import cn.iocoder.yudao.module.pms.dal.mysql.iotsapstock.IotSapStockMapper;
|
|
|
import cn.iocoder.yudao.module.pms.dal.mysql.iotsapstocklog.IotSapStockLogMapper;
|
|
|
+import cn.iocoder.yudao.module.pms.job.sap.SyncSapStockContext;
|
|
|
import cn.iocoder.yudao.module.pms.sap.vo.*;
|
|
|
import cn.iocoder.yudao.module.supplier.dal.dataobject.product.SupplierDO;
|
|
|
import cn.iocoder.yudao.module.supplier.dal.mysql.product.SupplierMapper;
|
|
@@ -72,6 +73,10 @@ public class IotSapServiceImpl implements IotSapService {
|
|
|
@Autowired
|
|
|
private IotSapPickingListMapper iotSapPickingListMapper;
|
|
|
|
|
|
+ // 批量操作的分批大小
|
|
|
+ private static final int BATCH_SIZE = 1000;
|
|
|
+ private static final int LOG_BATCH_SIZE = 2000;
|
|
|
+
|
|
|
@Override
|
|
|
public void processMaterials(List<IotSapMaterialVO> sapMaterials) {
|
|
|
// SAP接口返回的物料编码 砍掉前端的 00000000
|
|
@@ -575,6 +580,7 @@ public class IotSapServiceImpl implements IotSapService {
|
|
|
reqVO.setFactoryCode(factoryCode);
|
|
|
List<IotSapStockDO> existStocks = TenantUtils.execute(1L, () -> iotSapStockMapper.selectList(reqVO));
|
|
|
if (CollUtil.isNotEmpty(existStocks)) {
|
|
|
+ log.info("当前工厂{} 当前库中已有sap库存数量{}:", factoryCode, existStockKeys.size());
|
|
|
existStockKeys = existStocks.stream()
|
|
|
// 过滤非空对象和非空code
|
|
|
.filter(stk -> ObjUtil.isNotEmpty(stk) && StrUtil.isNotBlank(stk.getMaterialCode())
|
|
@@ -726,6 +732,250 @@ public class IotSapServiceImpl implements IotSapService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public void processSapStockBatch(List<IotSapStockVO> allStockData, Object contextObj) {
|
|
|
+ if (!(contextObj instanceof SyncSapStockContext)) {
|
|
|
+ throw new IllegalArgumentException("无效的上下文对象");
|
|
|
+ }
|
|
|
+
|
|
|
+ SyncSapStockContext context = (SyncSapStockContext) contextObj;
|
|
|
+
|
|
|
+ if (CollUtil.isEmpty(allStockData)) {
|
|
|
+ log.error("没有需要处理的SAP库存数据");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ log.error("开始批量处理SAP库存数据,总计 {} 条记录", allStockData.size());
|
|
|
+ long startTime = System.currentTimeMillis();
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 按工厂分组处理
|
|
|
+ Map<String, List<IotSapStockVO>> factoryStocksMap = allStockData.stream()
|
|
|
+ .collect(Collectors.groupingBy(IotSapStockVO::getWERKS));
|
|
|
+
|
|
|
+ log.error("按工厂分组完成,共 {} 个工厂的数据需要处理", factoryStocksMap.size());
|
|
|
+
|
|
|
+ List<IotSapStockDO> totalActualUpdatedStocks = new ArrayList<>();
|
|
|
+ List<IotSapStockDO> totalTobeAddedStocks = new ArrayList<>();
|
|
|
+
|
|
|
+ // 处理每个工厂的数据
|
|
|
+ factoryStocksMap.forEach((factoryCode, stocks) -> {
|
|
|
+ try {
|
|
|
+ processSingleFactoryStocks(factoryCode, stocks, context, totalTobeAddedStocks, totalActualUpdatedStocks);
|
|
|
+ log.error("工厂 {} 库存数据处理完成,共处理 {} 条记录", factoryCode, stocks.size());
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("处理工厂 {} 库存数据时发生错误", factoryCode, e);
|
|
|
+ // 记录错误但继续处理其他工厂
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 分批处理库存日志数据
|
|
|
+ processStockLogsInBatches(allStockData);
|
|
|
+
|
|
|
+ // 分批处理新增库存数据
|
|
|
+ processNewStocksInBatches(totalTobeAddedStocks);
|
|
|
+
|
|
|
+ // 分批处理更新库存数据
|
|
|
+ processUpdatedStocksInBatches(totalActualUpdatedStocks);
|
|
|
+
|
|
|
+ long endTime = System.currentTimeMillis();
|
|
|
+ log.error("所有工厂库存数据处理完成,总耗时: {}ms", (endTime - startTime));
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("批量处理SAP库存数据时发生错误", e);
|
|
|
+ throw new RuntimeException("SAP库存数据处理失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分批处理库存日志数据
|
|
|
+ */
|
|
|
+ private void processStockLogsInBatches(List<IotSapStockVO> allStockData) {
|
|
|
+ if (CollUtil.isEmpty(allStockData)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 准备SAP库存日志数据
|
|
|
+ List<IotSapStockLogDO> tobeAddedSapStockLogs = allStockData.stream()
|
|
|
+ .map(stock -> {
|
|
|
+ IotSapStockLogDO sapStockLog = new IotSapStockLogDO();
|
|
|
+ sapStockLog.setFactoryCode(stock.getWERKS());
|
|
|
+ sapStockLog.setStorageLocationCode(stock.getLGORT());
|
|
|
+ sapStockLog.setMaterialCode(stock.getMATNR().replaceFirst("^0+", ""));
|
|
|
+ sapStockLog.setMaterialName(stock.getMAKTX());
|
|
|
+ sapStockLog.setQuantity(stock.getLABST());
|
|
|
+ sapStockLog.setUnitPrice(stock.getJIAGE());
|
|
|
+ sapStockLog.setUnit(stock.getMEINS());
|
|
|
+ sapStockLog.setSyncTime(LocalDateTime.now());
|
|
|
+ return sapStockLog;
|
|
|
+ })
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 先删除所有日志记录(分批删除)
|
|
|
+ deleteAllStockLogsInBatches();
|
|
|
+
|
|
|
+ // 分批插入新的日志记录
|
|
|
+ insertStockLogsInBatches(tobeAddedSapStockLogs);
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("处理库存日志数据时发生错误", e);
|
|
|
+ // 不抛出异常,继续处理其他数据
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分批删除所有库存日志
|
|
|
+ */
|
|
|
+ private void deleteAllStockLogsInBatches() {
|
|
|
+ try {
|
|
|
+ // 直接调用删除方法,不传递工厂代码
|
|
|
+ TenantUtils.execute(1L, () -> {
|
|
|
+ iotSapStockLogMapper.deleteSapStockLogs(null);
|
|
|
+ return null;
|
|
|
+ });
|
|
|
+ log.error("成功删除所有库存日志记录");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("删除库存日志记录时发生错误", e);
|
|
|
+ throw new RuntimeException("删除库存日志失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分批插入库存日志
|
|
|
+ */
|
|
|
+ private void insertStockLogsInBatches(List<IotSapStockLogDO> stockLogs) {
|
|
|
+ if (CollUtil.isEmpty(stockLogs)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ log.error("开始分批插入库存日志,总计 {} 条记录", stockLogs.size());
|
|
|
+
|
|
|
+ // 分批处理
|
|
|
+ List<List<IotSapStockLogDO>> batches = CollUtil.split(stockLogs, LOG_BATCH_SIZE);
|
|
|
+ CountDownLatch latch = new CountDownLatch(batches.size());
|
|
|
+
|
|
|
+ for (List<IotSapStockLogDO> batch : batches) {
|
|
|
+ pmsThreadPoolTaskExecutor.execute(() -> {
|
|
|
+ try {
|
|
|
+ TenantUtils.execute(1L, () -> {
|
|
|
+ try {
|
|
|
+ iotSapStockLogMapper.insertBatch(batch);
|
|
|
+ log.error("成功插入一批库存日志,数量: {}", batch.size());
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("插入库存日志批次时发生错误,批次大小: {}", batch.size(), e);
|
|
|
+ // 记录错误但继续处理其他批次
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ });
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("执行租户上下文操作时发生错误", e);
|
|
|
+ } finally {
|
|
|
+ latch.countDown();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ latch.await();
|
|
|
+ log.error("所有库存日志批次插入完成");
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
+ log.error("等待库存日志插入完成时被中断", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分批处理新增库存数据
|
|
|
+ */
|
|
|
+ private void processNewStocksInBatches(List<IotSapStockDO> newStocks) {
|
|
|
+ if (CollUtil.isEmpty(newStocks)) {
|
|
|
+ log.error("没有需要新增的库存数据");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ log.error("开始分批插入新增库存数据,总计 {} 条记录", newStocks.size());
|
|
|
+
|
|
|
+ List<List<IotSapStockDO>> batches = CollUtil.split(newStocks, BATCH_SIZE);
|
|
|
+ CountDownLatch latch = new CountDownLatch(batches.size());
|
|
|
+ final int[] successCount = {0};
|
|
|
+
|
|
|
+ for (List<IotSapStockDO> batch : batches) {
|
|
|
+ pmsThreadPoolTaskExecutor.execute(() -> {
|
|
|
+ try {
|
|
|
+ TenantUtils.execute(1L, () -> {
|
|
|
+ try {
|
|
|
+ iotSapStockMapper.insertBatch(batch);
|
|
|
+ successCount[0] += batch.size();
|
|
|
+ log.error("成功插入一批新增库存,数量: {}", batch.size());
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("插入新增库存批次时发生错误,批次大小: {}", batch.size(), e);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ });
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("执行新增库存租户上下文操作时发生错误", e);
|
|
|
+ } finally {
|
|
|
+ latch.countDown();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ latch.await();
|
|
|
+ log.error("新增库存数据插入完成,成功插入 {} 条记录", successCount[0]);
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
+ log.error("等待新增库存插入完成时被中断", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分批处理更新库存数据
|
|
|
+ */
|
|
|
+ private void processUpdatedStocksInBatches(List<IotSapStockDO> updatedStocks) {
|
|
|
+ if (CollUtil.isEmpty(updatedStocks)) {
|
|
|
+ log.error("没有需要更新的库存数据");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ log.error("开始分批更新库存数据,总计 {} 条记录", updatedStocks.size());
|
|
|
+
|
|
|
+ List<List<IotSapStockDO>> batches = CollUtil.split(updatedStocks, BATCH_SIZE);
|
|
|
+ CountDownLatch latch = new CountDownLatch(batches.size());
|
|
|
+ final int[] successCount = {0};
|
|
|
+
|
|
|
+ for (List<IotSapStockDO> batch : batches) {
|
|
|
+ pmsThreadPoolTaskExecutor.execute(() -> {
|
|
|
+ try {
|
|
|
+ TenantUtils.execute(1L, () -> {
|
|
|
+ try {
|
|
|
+ iotSapStockMapper.updateBatch(batch);
|
|
|
+ successCount[0] += batch.size();
|
|
|
+ log.error("成功更新一批库存,数量: {}", batch.size());
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("更新库存批次时发生错误,批次大小: {}", batch.size(), e);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ });
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("执行更新库存租户上下文操作时发生错误", e);
|
|
|
+ } finally {
|
|
|
+ latch.countDown();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ latch.await();
|
|
|
+ log.error("库存数据更新完成,成功更新 {} 条记录", successCount[0]);
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
+ log.error("等待库存更新完成时被中断", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 创建物料编码到描述的映射
|
|
|
* @param sapMaterials SAP返回的物料列表
|
|
@@ -828,4 +1078,162 @@ public class IotSapServiceImpl implements IotSapService {
|
|
|
(existing, replacement) -> existing // 如果有重复的key,保留第一个值
|
|
|
));
|
|
|
}
|
|
|
+
|
|
|
+ private void processSingleFactoryStocks(String factoryCode, List<IotSapStockVO> stocks, SyncSapStockContext context,
|
|
|
+ List<IotSapStockDO> totalTobeAddedStocks, List<IotSapStockDO> totalActualUpdatedStocks) {
|
|
|
+ if (CollUtil.isEmpty(stocks)) {
|
|
|
+ log.error("工厂 {} 没有库存数据需要处理", factoryCode);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 筛选出pms系统中未维护的库存地点信息(工厂-库存地点编码)
|
|
|
+ Set<String> notExistStorageLocations = new HashSet<>();
|
|
|
+ stocks.forEach(stock -> {
|
|
|
+ String uniqueKey = StrUtil.join("-", stock.getWERKS(), stock.getLGORT());
|
|
|
+ if (!context.storageLocationIdPair.containsKey(uniqueKey)) {
|
|
|
+ notExistStorageLocations.add(uniqueKey);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (CollUtil.isNotEmpty(notExistStorageLocations)) {
|
|
|
+ log.error("工厂 {} 发现 {} 个未维护的库存地点: {}", factoryCode,
|
|
|
+ notExistStorageLocations.size(), notExistStorageLocations);
|
|
|
+ notExistStorageLocations.forEach(location ->
|
|
|
+ log.error("系统中未维护的工厂编码-库存地点编码: {}", location));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询当前工厂的现有库存数据
|
|
|
+ Set<String> existStockKeys = new HashSet<>();
|
|
|
+ IotSapStockPageReqVO reqVO = new IotSapStockPageReqVO();
|
|
|
+ reqVO.setFactoryCode(factoryCode);
|
|
|
+ log.error("当前工厂 {} 已经存在的SAP库存数量:{}", factoryCode, context.existStocks.size());
|
|
|
+ // 从预加载的数据中过滤出当前工厂的库存
|
|
|
+ List<IotSapStockDO> factoryExistStocks = context.existStocks.stream()
|
|
|
+ .filter(stock -> factoryCode.equals(stock.getFactoryCode()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ if (CollUtil.isNotEmpty(factoryExistStocks)) {
|
|
|
+ log.error("工厂 {} 当前库中已有sap库存数量: {}", factoryCode, factoryExistStocks.size());
|
|
|
+ existStockKeys = factoryExistStocks.stream()
|
|
|
+ .filter(stk -> ObjUtil.isNotEmpty(stk) && StrUtil.isNotBlank(stk.getMaterialCode())
|
|
|
+ && StrUtil.isNotBlank(stk.getFactoryCode()) && StrUtil.isNotBlank(stk.getStorageLocationCode()))
|
|
|
+ .map(stk -> StrUtil.join("-", stk.getFactoryCode(), stk.getStorageLocationCode(), stk.getMaterialCode()))
|
|
|
+ .collect(Collectors.toSet());
|
|
|
+ }
|
|
|
+
|
|
|
+ log.error("工厂 {} 当前库中已有sap库存唯一键数量: {}", factoryCode, existStockKeys.size());
|
|
|
+
|
|
|
+ // 构建待更新库存映射
|
|
|
+ Map<String, IotSapStockDO> tobeUpdatedStockPair = factoryExistStocks.stream()
|
|
|
+ .filter(stk -> StrUtil.isNotBlank(stk.getMaterialCode()) && StrUtil.isNotBlank(stk.getFactoryCode())
|
|
|
+ && StrUtil.isNotBlank(stk.getStorageLocationCode()))
|
|
|
+ .collect(Collectors.toMap(
|
|
|
+ stk -> StrUtil.join("-", stk.getFactoryCode(), stk.getStorageLocationCode(), stk.getMaterialCode()),
|
|
|
+ stk -> stk,
|
|
|
+ (existing, replacement) -> existing
|
|
|
+ ));
|
|
|
+
|
|
|
+ // 找出需要新增的库存记录
|
|
|
+ Set<String> finalExistStockKeys = existStockKeys;
|
|
|
+ List<IotSapStockVO> newStocks = stocks.stream()
|
|
|
+ .filter(stk -> factoryCode.equals(stk.getWERKS()) && StrUtil.isNotBlank(stk.getMATNR()) && StrUtil.isNotBlank(stk.getLGORT())
|
|
|
+ && context.storageLocationIdPair.containsKey(StrUtil.join("-", stk.getWERKS(), stk.getLGORT())))
|
|
|
+ .filter(stk -> {
|
|
|
+ String processedCode = stk.getMATNR().replaceFirst("^0+", "");
|
|
|
+ String uniqueKey = StrUtil.join("-", stk.getWERKS(), stk.getLGORT());
|
|
|
+ return !finalExistStockKeys.contains(StrUtil.join("-", uniqueKey, processedCode));
|
|
|
+ })
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ log.error("工厂 {} 需要新增的sap库存数量: {}", factoryCode, newStocks.size());
|
|
|
+
|
|
|
+ // 准备新增的库存数据
|
|
|
+ List<IotSapStockDO> tobeAddedStocks = new ArrayList<>();
|
|
|
+ if (CollUtil.isNotEmpty(newStocks)) {
|
|
|
+ newStocks.forEach(stock -> {
|
|
|
+ String uniqueKey = StrUtil.join("-", stock.getWERKS(), stock.getLGORT());
|
|
|
+ IotSapStockDO sapStock = new IotSapStockDO();
|
|
|
+
|
|
|
+ // 设置部门ID
|
|
|
+ if (context.locationCodeDeptIdPair.containsKey(uniqueKey)) {
|
|
|
+ sapStock.setDeptId(context.locationCodeDeptIdPair.get(uniqueKey));
|
|
|
+ } else {
|
|
|
+ // 没有关联组织部门的SAP工厂库存地点,设置默认部门
|
|
|
+ sapStock.setDeptId(163L); // 科瑞石油技术
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置工厂信息
|
|
|
+ if (context.factoryIdPair.containsKey(stock.getWERKS())) {
|
|
|
+ sapStock.setFactoryId(context.factoryIdPair.get(stock.getWERKS()));
|
|
|
+ }
|
|
|
+ sapStock.setFactoryCode(stock.getWERKS());
|
|
|
+ if (context.factoryNamePair.containsKey(stock.getWERKS())) {
|
|
|
+ sapStock.setFactory(context.factoryNamePair.get(stock.getWERKS()));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置库存地点信息
|
|
|
+ if (context.storageLocationIdPair.containsKey(uniqueKey)) {
|
|
|
+ sapStock.setStorageLocationId(context.storageLocationIdPair.get(uniqueKey));
|
|
|
+ }
|
|
|
+ sapStock.setStorageLocationCode(stock.getLGORT());
|
|
|
+ if (context.stockLocationNamePair.containsKey(uniqueKey)) {
|
|
|
+ sapStock.setProjectDepartment(context.stockLocationNamePair.get(uniqueKey));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置物料信息
|
|
|
+ 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);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 准备更新的库存数据
|
|
|
+ List<IotSapStockDO> actualUpdatedStocks = new ArrayList<>();
|
|
|
+ Map<String, IotSapStockVO> existStockPair = createExistStockMap(factoryCode, stocks, existStockKeys, context.storageLocationIdPair);
|
|
|
+
|
|
|
+ if (CollUtil.isNotEmpty(existStockPair)) {
|
|
|
+ Map<String, IotSapStockDO> finalTobeUpdatedStockPair = tobeUpdatedStockPair;
|
|
|
+ existStockPair.forEach((key, sapStockVO) -> {
|
|
|
+ if (finalTobeUpdatedStockPair.containsKey(key)) {
|
|
|
+ IotSapStockDO existingStock = finalTobeUpdatedStockPair.get(key);
|
|
|
+ String uniqueKey = StrUtil.join("-", existingStock.getFactoryCode(), existingStock.getStorageLocationCode());
|
|
|
+
|
|
|
+ // 更新部门关联
|
|
|
+ if (context.locationCodeDeptIdPair.containsKey(uniqueKey)) {
|
|
|
+ existingStock.setDeptId(context.locationCodeDeptIdPair.get(uniqueKey));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新库存信息
|
|
|
+ existingStock.setUnitPrice(sapStockVO.getJIAGE());
|
|
|
+ existingStock.setQuantity(sapStockVO.getLABST());
|
|
|
+ existingStock.setUnit(sapStockVO.getMEINS());
|
|
|
+ existingStock.setSyncTime(LocalDateTime.now());
|
|
|
+
|
|
|
+ actualUpdatedStocks.add(existingStock);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ log.error("工厂 {} 需要更新的SAP库存数量: {}", factoryCode, actualUpdatedStocks.size());
|
|
|
+
|
|
|
+ // 本地库存 初始化 批量插入SAP 库存 工厂 库存地点 已经关联了组织架构部门
|
|
|
+ if (CollUtil.isNotEmpty(tobeAddedStocks)) {
|
|
|
+ totalTobeAddedStocks.addAll(tobeAddedStocks);
|
|
|
+ }
|
|
|
+
|
|
|
+ // pms中存在而且SAP接口也返回的库存数据:更新
|
|
|
+ if (CollUtil.isNotEmpty(actualUpdatedStocks)) {
|
|
|
+ totalActualUpdatedStocks.addAll(actualUpdatedStocks);
|
|
|
+ }
|
|
|
+
|
|
|
+ log.error("工厂 {} 库存数据处理完成: 新增 {} 条, 更新 {} 条, 日志 {} 条",
|
|
|
+ factoryCode,
|
|
|
+ CollUtil.size(tobeAddedStocks),
|
|
|
+ CollUtil.size(actualUpdatedStocks));
|
|
|
+ }
|
|
|
}
|