|
|
|
@ -804,11 +804,10 @@ public class WmsMessageServiceImpl implements WmsMessageService { |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @Description 执行自动化托运托盘移库(IFS调用改为写入队列表)- rqrq |
|
|
|
* @param request 移库请求参数 |
|
|
|
* @return 处理结果 |
|
|
|
* @author rqrq |
|
|
|
* @date 2026/08/24 |
|
|
|
* @Description 执行自动化托运托盘移库(IFS调用改为写入队列表)。开头只收在库Y且标签表存在的明细,查不到或非Y的留盘不抛错,避免脏标签把WCS/AGV整托打死 - rqrq |
|
|
|
* @param request 移库请求,site/palletId/目标仓库库位来自回调,username用于事务审计 - rqrq |
|
|
|
* @return 处理结果说明;无可搬标签时返回无需移库,调用方仍可更新托盘位置 - rqrq |
|
|
|
*/ |
|
|
|
@Override |
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
@ -834,43 +833,16 @@ public class WmsMessageServiceImpl implements WmsMessageService { |
|
|
|
|
|
|
|
pallet.setLocationCode(request.getToStation()); |
|
|
|
pallet.setWcsLocation(request.getToStation()); |
|
|
|
|
|
|
|
String fromWarehouseId; |
|
|
|
String fromLocationId; |
|
|
|
|
|
|
|
// 从pallet_detail的第一条记录获取serialNo,查询handling_unit的仓库和库位 - rqrq |
|
|
|
PalletDetail firstPalletDetail = palletDetails.get(0); |
|
|
|
HandlingUnit firstHu = handlingUnitService.lambdaQuery() |
|
|
|
.eq(HandlingUnit::getSite, request.getSite()) |
|
|
|
.eq(HandlingUnit::getUnitId, firstPalletDetail.getSerialNo()) |
|
|
|
.one(); |
|
|
|
|
|
|
|
if (firstHu == null) { |
|
|
|
throw new RuntimeException("未找到条码对应的处理单元:" + firstPalletDetail.getSerialNo()); |
|
|
|
} |
|
|
|
|
|
|
|
fromWarehouseId = firstHu.getWarehouseId(); |
|
|
|
fromLocationId = firstHu.getLocationId(); |
|
|
|
|
|
|
|
if(fromWarehouseId.equals(request.getToWarehouseId())&&fromLocationId.equals(request.getToLocationId())){ |
|
|
|
return "托盘无需执行移库操作:" + request.getPalletId(); |
|
|
|
} |
|
|
|
|
|
|
|
// 5. 获取条码对应的HandlingUnit信息 |
|
|
|
List<String> serialNos = palletDetails.stream() |
|
|
|
.map(PalletDetail::getSerialNo) |
|
|
|
.collect(Collectors.toList()); |
|
|
|
|
|
|
|
List<HandlingUnit> handlingUnits = handlingUnitService.lambdaQuery() |
|
|
|
.eq(HandlingUnit::getSite, request.getSite()) |
|
|
|
.in(HandlingUnit::getUnitId, serialNos) |
|
|
|
.list(); |
|
|
|
|
|
|
|
|
|
|
|
// 只收可自动搬库的Y标签:查不到/非Y/数量无效/已在目标库的明细留盘,不按第一条标签决定整托 - rqrq |
|
|
|
List<HandlingUnit> handlingUnits = collectAutoTransferHandlingUnits( |
|
|
|
request.getSite(), request.getPalletId(), request.getToWarehouseId(), request.getToLocationId(), palletDetails); |
|
|
|
if (handlingUnits.isEmpty()) { |
|
|
|
throw new RuntimeException("未找到托盘上的条码信息"); |
|
|
|
return "托盘无需执行移库操作:" + request.getPalletId(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 事务头来源仓库取第一份可搬Y标签;后续明细仍按标签自身库位分组,兼容混库位 - rqrq |
|
|
|
String fromWarehouseId = handlingUnits.get(0).getWarehouseId(); |
|
|
|
|
|
|
|
// 6. 生成移库出库和入库的事务号 |
|
|
|
TransNoControl stoTransData = transNoControlService.getTransNo(request.getSite(), "STO", 10); |
|
|
|
@ -1104,6 +1076,89 @@ public class WmsMessageServiceImpl implements WmsMessageService { |
|
|
|
detailSub.setEngChgLevel(hu.getEngChgLevel()); // 添加工程更改级别 - rqrq |
|
|
|
return detailSub; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @author rqrq |
|
|
|
* @Description 自动移库开头收紧可搬标签:只保留handling_unit存在、in_stock_flag=Y、数量>0、且仓库或库位与目标不同的标签。 |
|
|
|
* 查不到、非Y、数量无效或已在目标库的明细留在托盘不抛错、不删pallet_detail,避免脏数据把整托回调打死。 |
|
|
|
* 同一条码只收一次,防止重复明细把数量算两次。- rqrq |
|
|
|
* @param site 请求工厂,必须与托盘和标签site一致,禁止登录态兜底 - rqrq |
|
|
|
* @param palletId 托盘号,仅用于日志定位留盘标签 - rqrq |
|
|
|
* @param toWarehouseId 目标仓库,与当前仓库都相同且库位也相同时该标签跳过 - rqrq |
|
|
|
* @param toLocationId 目标库位,与当前库位都相同且仓库也相同时该标签跳过 - rqrq |
|
|
|
* @param palletDetails 当前托盘全部明细,本方法不改明细表 - rqrq |
|
|
|
* @return 需要自动移库的Y标签列表,空表示整托跳过移库 - rqrq |
|
|
|
*/ |
|
|
|
private List<HandlingUnit> collectAutoTransferHandlingUnits(String site, String palletId, String toWarehouseId, |
|
|
|
String toLocationId, List<PalletDetail> palletDetails) { |
|
|
|
List<HandlingUnit> movableUnits = new ArrayList<HandlingUnit>(); |
|
|
|
if (palletDetails == null || palletDetails.isEmpty()) { |
|
|
|
return movableUnits; |
|
|
|
} |
|
|
|
List<String> serialNos = new ArrayList<String>(); |
|
|
|
for (PalletDetail detail : palletDetails) { |
|
|
|
if (detail == null || !StringUtils.hasText(detail.getSerialNo())) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
serialNos.add(detail.getSerialNo().trim()); |
|
|
|
} |
|
|
|
if (serialNos.isEmpty()) { |
|
|
|
log.warn("自动移库跳过:托盘明细没有有效条码,site={},palletId={} - rqrq", site, palletId); |
|
|
|
return movableUnits; |
|
|
|
} |
|
|
|
// 按site+条码批量查标签主数据;查不到的后面按明细逐条留盘,这里空结果不抛错 - rqrq |
|
|
|
List<HandlingUnit> foundUnits = handlingUnitService.lambdaQuery() |
|
|
|
.eq(HandlingUnit::getSite, site) |
|
|
|
.in(HandlingUnit::getUnitId, serialNos) |
|
|
|
.list(); |
|
|
|
Map<String, HandlingUnit> huByUnitId = new LinkedHashMap<String, HandlingUnit>(); |
|
|
|
if (foundUnits != null) { |
|
|
|
for (HandlingUnit hu : foundUnits) { |
|
|
|
if (hu != null && StringUtils.hasText(hu.getUnitId())) { |
|
|
|
huByUnitId.put(hu.getUnitId().trim(), hu); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
Set<String> acceptedSerialNos = new HashSet<String>(); |
|
|
|
String targetWarehouse = StringUtils.hasText(toWarehouseId) ? toWarehouseId.trim() : ""; |
|
|
|
String targetLocation = StringUtils.hasText(toLocationId) ? toLocationId.trim() : ""; |
|
|
|
for (PalletDetail detail : palletDetails) { |
|
|
|
if (detail == null || !StringUtils.hasText(detail.getSerialNo())) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
String serialNo = detail.getSerialNo().trim(); |
|
|
|
if (!acceptedSerialNos.add(serialNo)) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
HandlingUnit hu = huByUnitId.get(serialNo); |
|
|
|
if (hu == null) { |
|
|
|
log.warn("自动移库留盘:标签表不存在,site={},palletId={},serialNo={} - rqrq", site, palletId, serialNo); |
|
|
|
continue; |
|
|
|
} |
|
|
|
if (!"Y".equalsIgnoreCase(StringUtils.hasText(hu.getInStockFlag()) ? hu.getInStockFlag().trim() : "")) { |
|
|
|
log.warn("自动移库留盘:标签非在库Y,site={},palletId={},serialNo={},inStockFlag={} - rqrq", |
|
|
|
site, palletId, serialNo, hu.getInStockFlag()); |
|
|
|
continue; |
|
|
|
} |
|
|
|
if (hu.getQty() == null || hu.getQty().compareTo(BigDecimal.ZERO) <= 0) { |
|
|
|
log.warn("自动移库留盘:标签数量无效,site={},palletId={},serialNo={},qty={} - rqrq", |
|
|
|
site, palletId, serialNo, hu.getQty()); |
|
|
|
continue; |
|
|
|
} |
|
|
|
String currentWarehouse = StringUtils.hasText(hu.getWarehouseId()) ? hu.getWarehouseId().trim() : ""; |
|
|
|
String currentLocation = StringUtils.hasText(hu.getLocationId()) ? hu.getLocationId().trim() : ""; |
|
|
|
if (targetWarehouse.equals(currentWarehouse) && targetLocation.equals(currentLocation)) { |
|
|
|
log.info("自动移库跳过:标签已在目标仓库库位,site={},palletId={},serialNo={} - rqrq", |
|
|
|
site, palletId, serialNo); |
|
|
|
continue; |
|
|
|
} |
|
|
|
movableUnits.add(hu); |
|
|
|
} |
|
|
|
if (movableUnits.isEmpty()) { |
|
|
|
log.info("自动移库跳过:托盘没有可搬的在库Y标签,site={},palletId={} - rqrq", site, palletId); |
|
|
|
} |
|
|
|
return movableUnits; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取托盘明细信息 |
|
|
|
|