|
|
@ -247,34 +247,34 @@ public class InventoryMoveServiceImpl implements InventoryMoveService { |
|
|
/** |
|
|
/** |
|
|
* 批量同步到IFS - 按site、partNo、locationNo、lotBatchNo合并后调用 |
|
|
* 批量同步到IFS - 按site、partNo、locationNo、lotBatchNo合并后调用 |
|
|
*/ |
|
|
*/ |
|
|
private void syncToIFSBatch(InventoryMoveRequestDto dto, List<HandlingUnit> handlingUnits) { |
|
|
|
|
|
try { |
|
|
|
|
|
// 按site、partNo、原库位、lotBatchNo、expiredDate分组合并数量 |
|
|
|
|
|
Map<String, MoveGroup> moveGroups = new HashMap<>(); |
|
|
|
|
|
|
|
|
private void syncToIFSBatch(InventoryMoveRequestDto dto, List<HandlingUnit> handlingUnits) { |
|
|
|
|
|
try { |
|
|
|
|
|
// 按site、partNo、原库位、lotBatchNo、wdr分组合并数量 |
|
|
|
|
|
Map<String, MoveGroup> moveGroups = new HashMap<>(); |
|
|
|
|
|
|
|
|
for (HandlingUnit hu : handlingUnits) { |
|
|
|
|
|
String expiredDateStr = hu.getExpiredDate() != null ? |
|
|
|
|
|
new SimpleDateFormat("yyyy-MM-dd").format(hu.getExpiredDate()) : "null"; |
|
|
|
|
|
String groupKey = String.format("%s|%s|%s|%s|%s", |
|
|
|
|
|
hu.getSite(), hu.getPartNo(), hu.getLocationId(), hu.getBatchNo(), expiredDateStr); |
|
|
|
|
|
|
|
|
|
|
|
MoveGroup group = moveGroups.computeIfAbsent(groupKey, k -> { |
|
|
|
|
|
MoveGroup newGroup = new MoveGroup(); |
|
|
|
|
|
newGroup.site = hu.getSite(); |
|
|
|
|
|
newGroup.partNo = hu.getPartNo(); |
|
|
|
|
|
newGroup.sourceLocationNo = hu.getLocationId(); // 注意:这里使用的是更新前的原库位 |
|
|
|
|
|
newGroup.destLocationNo = dto.getTargetLocationId(); |
|
|
|
|
|
newGroup.lotBatchNo = hu.getBatchNo(); |
|
|
|
|
|
newGroup.expiredDate = hu.getExpiredDate(); |
|
|
|
|
|
newGroup.totalQty = BigDecimal.ZERO; |
|
|
|
|
|
return newGroup; |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
group.totalQty = group.totalQty.add(hu.getQty()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
for (HandlingUnit hu : handlingUnits) { |
|
|
|
|
|
String groupKey = String.format("%s|%s|%s|%s|%s", |
|
|
|
|
|
hu.getSite(), hu.getPartNo(), hu.getLocationId(), hu.getBatchNo(), |
|
|
|
|
|
hu.getWdr() != null ? hu.getWdr() : "*"); |
|
|
|
|
|
|
|
|
// 校验所有分组的库存数量是否足够 |
|
|
|
|
|
//validateInventoryStock(moveGroups); |
|
|
|
|
|
|
|
|
MoveGroup group = moveGroups.computeIfAbsent(groupKey, k -> { |
|
|
|
|
|
MoveGroup newGroup = new MoveGroup(); |
|
|
|
|
|
newGroup.site = hu.getSite(); |
|
|
|
|
|
newGroup.partNo = hu.getPartNo(); |
|
|
|
|
|
newGroup.sourceLocationNo = hu.getLocationId(); // 注意:这里使用的是更新前的原库位 |
|
|
|
|
|
newGroup.destLocationNo = dto.getTargetLocationId(); |
|
|
|
|
|
newGroup.lotBatchNo = hu.getBatchNo(); |
|
|
|
|
|
newGroup.wdr = hu.getWdr(); |
|
|
|
|
|
newGroup.expiredDate = hu.getExpiredDate(); // 有效期值保留 |
|
|
|
|
|
newGroup.totalQty = BigDecimal.ZERO; |
|
|
|
|
|
return newGroup; |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
group.totalQty = group.totalQty.add(hu.getQty()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 校验所有分组的库存数量是否足够 |
|
|
|
|
|
validateInventoryStock(moveGroups); |
|
|
|
|
|
|
|
|
// 为每个分组调用IFS接口 |
|
|
// 为每个分组调用IFS接口 |
|
|
for (MoveGroup group : moveGroups.values()) { |
|
|
for (MoveGroup group : moveGroups.values()) { |
|
|
@ -295,36 +295,36 @@ public class InventoryMoveServiceImpl implements InventoryMoveService { |
|
|
* @author rqrq |
|
|
* @author rqrq |
|
|
* @date 2025/10/08 |
|
|
* @date 2025/10/08 |
|
|
*/ |
|
|
*/ |
|
|
private void syncToIFSBatchForPallet(InventoryMoveRequestDto dto, List<HandlingUnit> handlingUnits) { |
|
|
|
|
|
try { |
|
|
|
|
|
// 按site、partNo、原库位、lotBatchNo、expiredDate分组合并数量 |
|
|
|
|
|
Map<String, MoveGroup> moveGroups = new HashMap<>(); |
|
|
|
|
|
|
|
|
|
|
|
for (HandlingUnit hu : handlingUnits) { |
|
|
|
|
|
String expiredDateStr = hu.getExpiredDate() != null ? |
|
|
|
|
|
new SimpleDateFormat("yyyy-MM-dd").format(hu.getExpiredDate()) : "null"; |
|
|
|
|
|
String groupKey = String.format("%s|%s|%s|%s|%s", |
|
|
|
|
|
hu.getSite(), hu.getPartNo(), hu.getLocationId(), hu.getBatchNo(), expiredDateStr); |
|
|
|
|
|
|
|
|
|
|
|
MoveGroup group = moveGroups.computeIfAbsent(groupKey, k -> { |
|
|
|
|
|
MoveGroup newGroup = new MoveGroup(); |
|
|
|
|
|
newGroup.site = hu.getSite(); |
|
|
|
|
|
newGroup.partNo = hu.getPartNo(); |
|
|
|
|
|
newGroup.sourceLocationNo = hu.getLocationId(); // 注意:这里使用的是更新前的原库位 |
|
|
|
|
|
newGroup.destLocationNo = dto.getTargetLocationId(); |
|
|
|
|
|
newGroup.lotBatchNo = hu.getBatchNo(); |
|
|
|
|
|
newGroup.expiredDate = hu.getExpiredDate(); |
|
|
|
|
|
newGroup.totalQty = BigDecimal.ZERO; |
|
|
|
|
|
return newGroup; |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
group.totalQty = group.totalQty.add(hu.getQty()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 为每个分组调用IFS接口 - rqrq |
|
|
|
|
|
for (MoveGroup group : moveGroups.values()) { |
|
|
|
|
|
syncSingleGroupToIFSForPallet(group); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
private void syncToIFSBatchForPallet(InventoryMoveRequestDto dto, List<HandlingUnit> handlingUnits) { |
|
|
|
|
|
try { |
|
|
|
|
|
// 按site、partNo、原库位、lotBatchNo、wdr分组合并数量 |
|
|
|
|
|
Map<String, MoveGroup> moveGroups = new HashMap<>(); |
|
|
|
|
|
|
|
|
|
|
|
for (HandlingUnit hu : handlingUnits) { |
|
|
|
|
|
String groupKey = String.format("%s|%s|%s|%s|%s", |
|
|
|
|
|
hu.getSite(), hu.getPartNo(), hu.getLocationId(), hu.getBatchNo(), |
|
|
|
|
|
hu.getWdr() != null ? hu.getWdr() : "*"); |
|
|
|
|
|
|
|
|
|
|
|
MoveGroup group = moveGroups.computeIfAbsent(groupKey, k -> { |
|
|
|
|
|
MoveGroup newGroup = new MoveGroup(); |
|
|
|
|
|
newGroup.site = hu.getSite(); |
|
|
|
|
|
newGroup.partNo = hu.getPartNo(); |
|
|
|
|
|
newGroup.sourceLocationNo = hu.getLocationId(); // 注意:这里使用的是更新前的原库位 |
|
|
|
|
|
newGroup.destLocationNo = dto.getTargetLocationId(); |
|
|
|
|
|
newGroup.lotBatchNo = hu.getBatchNo(); |
|
|
|
|
|
newGroup.wdr = hu.getWdr(); |
|
|
|
|
|
newGroup.expiredDate = hu.getExpiredDate(); // 有效期值保留 |
|
|
|
|
|
newGroup.totalQty = BigDecimal.ZERO; |
|
|
|
|
|
return newGroup; |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
group.totalQty = group.totalQty.add(hu.getQty()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 为每个分组调用IFS接口 - rqrq |
|
|
|
|
|
for (MoveGroup group : moveGroups.values()) { |
|
|
|
|
|
syncSingleGroupToIFSForPallet(group); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
log.info("IFS批量移库同步完成,共{}个分组", moveGroups.size()); |
|
|
log.info("IFS批量移库同步完成,共{}个分组", moveGroups.size()); |
|
|
|
|
|
|
|
|
@ -343,27 +343,28 @@ public class InventoryMoveServiceImpl implements InventoryMoveService { |
|
|
try { |
|
|
try { |
|
|
log.info("开始校验库存数量,共{}个分组需要校验", moveGroups.size()); |
|
|
log.info("开始校验库存数量,共{}个分组需要校验", moveGroups.size()); |
|
|
|
|
|
|
|
|
// 按站点分组获取库存信息,减少API调用次数 |
|
|
|
|
|
Map<String, List<IfsInventoryPartInStock>> siteInventoryMap = new HashMap<>(); |
|
|
|
|
|
|
|
|
// 按站点+物料分组获取库存信息,减少API调用次数 |
|
|
|
|
|
Map<String, List<IfsInventoryPartInStock>> inventoryMap = new HashMap<>(); |
|
|
|
|
|
|
|
|
for (MoveGroup group : moveGroups.values()) { |
|
|
|
|
|
String site = group.site; |
|
|
|
|
|
if (!siteInventoryMap.containsKey(site)) { |
|
|
|
|
|
// 获取该站点的所有库存信息 |
|
|
|
|
|
List<IfsInventoryPartInStock> inventoryList = ifsApiService.getInventoryPartInStock(site); |
|
|
|
|
|
siteInventoryMap.put(site, inventoryList); |
|
|
|
|
|
log.info("获取站点{}的库存信息,共{}条记录", site, inventoryList.size()); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
for (MoveGroup group : moveGroups.values()) { |
|
|
|
|
|
String key = group.site + "-" + group.partNo; // 使用site+partNo作为复合key |
|
|
|
|
|
if (!inventoryMap.containsKey(key)) { |
|
|
|
|
|
// 获取该站点指定物料的库存信息 |
|
|
|
|
|
List<IfsInventoryPartInStock> inventoryList = ifsApiService.getInventoryPartInStock(group.site, group.partNo); |
|
|
|
|
|
inventoryMap.put(key, inventoryList); |
|
|
|
|
|
log.info("获取站点{}物料{}的库存信息,共{}条记录", group.site, group.partNo, inventoryList.size()); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 校验每个分组的库存是否足够 |
|
|
|
|
|
List<String> insufficientStockErrors = new ArrayList<>(); |
|
|
|
|
|
|
|
|
// 校验每个分组的库存是否足够 |
|
|
|
|
|
List<String> insufficientStockErrors = new ArrayList<>(); |
|
|
|
|
|
|
|
|
for (MoveGroup group : moveGroups.values()) { |
|
|
|
|
|
List<IfsInventoryPartInStock> siteInventory = siteInventoryMap.get(group.site); |
|
|
|
|
|
|
|
|
for (MoveGroup group : moveGroups.values()) { |
|
|
|
|
|
String key = group.site + "-" + group.partNo; |
|
|
|
|
|
List<IfsInventoryPartInStock> inventoryList = inventoryMap.get(key); |
|
|
|
|
|
|
|
|
// 查找匹配的库存记录 |
|
|
|
|
|
IfsInventoryPartInStock matchedStock = findMatchingStock(siteInventory, group); |
|
|
|
|
|
|
|
|
// 查找匹配的库存记录 |
|
|
|
|
|
IfsInventoryPartInStock matchedStock = findMatchingStock(inventoryList, group); |
|
|
|
|
|
|
|
|
if (matchedStock == null) { |
|
|
if (matchedStock == null) { |
|
|
insufficientStockErrors.add(String.format( |
|
|
insufficientStockErrors.add(String.format( |
|
|
@ -403,23 +404,27 @@ public class InventoryMoveServiceImpl implements InventoryMoveService { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 查找匹配的库存记录 |
|
|
|
|
|
* @param inventoryList 库存列表 |
|
|
|
|
|
* @param group 移库分组 |
|
|
|
|
|
* @return 匹配的库存记录,未找到返回null |
|
|
|
|
|
*/ |
|
|
|
|
|
private IfsInventoryPartInStock findMatchingStock(List<IfsInventoryPartInStock> inventoryList, MoveGroup group) { |
|
|
|
|
|
for (IfsInventoryPartInStock stock : inventoryList) { |
|
|
|
|
|
// 匹配条件:物料号、批次号、库位号 |
|
|
|
|
|
if (group.partNo.equals(stock.getPartNo()) && |
|
|
|
|
|
group.lotBatchNo.equals(stock.getLotBatchNo()) && |
|
|
|
|
|
group.sourceLocationNo.equals(stock.getLocationNo())) { |
|
|
|
|
|
return stock; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return null; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 查找匹配的库存记录 |
|
|
|
|
|
* @param inventoryList 库存列表 |
|
|
|
|
|
* @param group 移库分组 |
|
|
|
|
|
* @return 匹配的库存记录,未找到返回null |
|
|
|
|
|
*/ |
|
|
|
|
|
private IfsInventoryPartInStock findMatchingStock(List<IfsInventoryPartInStock> inventoryList, MoveGroup group) { |
|
|
|
|
|
for (IfsInventoryPartInStock stock : inventoryList) { |
|
|
|
|
|
// 匹配条件:物料号、批次号、库位号、WDR |
|
|
|
|
|
boolean partNoMatch = group.partNo.equals(stock.getPartNo()); |
|
|
|
|
|
boolean lotBatchNoMatch = group.lotBatchNo.equals(stock.getLotBatchNo()); |
|
|
|
|
|
boolean locationNoMatch = group.sourceLocationNo.equals(stock.getLocationNo()); |
|
|
|
|
|
boolean wdrMatch = (group.wdr == null && stock.getWaivDevRejNo() == null) || |
|
|
|
|
|
(group.wdr != null && group.wdr.equals(stock.getWaivDevRejNo())); |
|
|
|
|
|
|
|
|
|
|
|
if (partNoMatch && lotBatchNoMatch && locationNoMatch && wdrMatch) { |
|
|
|
|
|
return stock; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return null; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 同步单个分组到IFS |
|
|
* 同步单个分组到IFS |
|
|
@ -659,18 +664,19 @@ public class InventoryMoveServiceImpl implements InventoryMoveService { |
|
|
return inventoryGroups; |
|
|
return inventoryGroups; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 移库分组内部类 |
|
|
|
|
|
*/ |
|
|
|
|
|
private static class MoveGroup { |
|
|
|
|
|
String site; |
|
|
|
|
|
String partNo; |
|
|
|
|
|
String sourceLocationNo; |
|
|
|
|
|
String destLocationNo; |
|
|
|
|
|
String lotBatchNo; |
|
|
|
|
|
BigDecimal totalQty; |
|
|
|
|
|
Date expiredDate; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 移库分组内部类 |
|
|
|
|
|
*/ |
|
|
|
|
|
private static class MoveGroup { |
|
|
|
|
|
String site; |
|
|
|
|
|
String partNo; |
|
|
|
|
|
String sourceLocationNo; |
|
|
|
|
|
String destLocationNo; |
|
|
|
|
|
String lotBatchNo; |
|
|
|
|
|
String wdr; |
|
|
|
|
|
BigDecimal totalQty; |
|
|
|
|
|
Date expiredDate; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 库存分组内部类 - 按库存主键字段分组 |
|
|
* 库存分组内部类 - 按库存主键字段分组 |
|
|
|