Browse Source

IFS库存校验

master
han\hanst 3 months ago
parent
commit
e5c11240e9
  1. 2
      src/main/java/com/gaotao/modules/api/service/IfsApiService.java
  2. 7
      src/main/java/com/gaotao/modules/api/service/impl/IfsApiServiceImpl.java
  3. 210
      src/main/java/com/gaotao/modules/other/service/impl/InventoryMoveServiceImpl.java

2
src/main/java/com/gaotao/modules/api/service/IfsApiService.java

@ -25,7 +25,7 @@ public interface IfsApiService {
* @return 库存在库信息列表 * @return 库存在库信息列表
* @throws JsonProcessingException JSON处理异常 * @throws JsonProcessingException JSON处理异常
*/ */
List<IfsInventoryPartInStock> getInventoryPartInStock(String site) throws JsonProcessingException;
List<IfsInventoryPartInStock> getInventoryPartInStock(String site,String partNo) throws JsonProcessingException;
} }

7
src/main/java/com/gaotao/modules/api/service/impl/IfsApiServiceImpl.java

@ -90,15 +90,16 @@ public class IfsApiServiceImpl implements IfsApiService {
} }
@Override @Override
public List<IfsInventoryPartInStock> getInventoryPartInStock(String site) throws JsonProcessingException {
public List<IfsInventoryPartInStock> getInventoryPartInStock(String site,String partNo) throws JsonProcessingException {
Map<String, Object> params = Map.of( Map<String, Object> params = Map.of(
"ifsDBName", ifsDBName, "ifsDBName", ifsDBName,
"domainUserID", domainUserID, "domainUserID", domainUserID,
"ifsSiteID", site
"ifsSiteID", site,
"ifsPartNo", partNo
); );
ObjectMapper objectMapper = new ObjectMapper(); ObjectMapper objectMapper = new ObjectMapper();
String jsonBody = objectMapper.writeValueAsString(params); String jsonBody = objectMapper.writeValueAsString(params);
String ifsResponse = HttpUtils.doGetWithBody(ifsUrl + "InventoryPartInStock", jsonBody, null);
String ifsResponse = HttpUtils.doGetWithBody(ifsUrl + "AnInventoryPartInStock", jsonBody, null);
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
List<IfsInventoryPartInStock> result = mapper.readValue(ifsResponse, new TypeReference<List<IfsInventoryPartInStock>>() { List<IfsInventoryPartInStock> result = mapper.readValue(ifsResponse, new TypeReference<List<IfsInventoryPartInStock>>() {
}); });

210
src/main/java/com/gaotao/modules/other/service/impl/InventoryMoveServiceImpl.java

@ -247,34 +247,34 @@ public class InventoryMoveServiceImpl implements InventoryMoveService {
/** /**
* 批量同步到IFS - 按sitepartNolocationNolotBatchNo合并后调用 * 批量同步到IFS - 按sitepartNolocationNolotBatchNo合并后调用
*/ */
private void syncToIFSBatch(InventoryMoveRequestDto dto, List<HandlingUnit> handlingUnits) {
try {
// 按sitepartNo原库位lotBatchNoexpiredDate分组合并数量
Map<String, MoveGroup> moveGroups = new HashMap<>();
private void syncToIFSBatch(InventoryMoveRequestDto dto, List<HandlingUnit> handlingUnits) {
try {
// 按sitepartNo原库位lotBatchNowdr分组合并数量
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 {
// 按sitepartNo原库位lotBatchNoexpiredDate分组合并数量
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 {
// 按sitepartNo原库位lotBatchNowdr分组合并数量
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;
}
/** /**
* 库存分组内部类 - 按库存主键字段分组 * 库存分组内部类 - 按库存主键字段分组

Loading…
Cancel
Save