fix(lastleg): expose and validate individual return carton picks
This commit is contained in:
+48
-16
@@ -420,9 +420,11 @@ public class DeliveryTransferService {
|
||||
outbound.setRecipientInfo(request.recipient().trim()); outbound.setPackageCount(marks.size()); outbound.setPalletCount(0);
|
||||
outbound.setOverseasWarehouseId(warehouseId); outbound.setIdempotencyKey(request.idempotencyKey().trim());
|
||||
outbound.setCreatedBy(operatorId); outbound.setCreatedAt(now); outbound.setUpdatedAt(now); outboundOrders.insert(outbound);
|
||||
OutboundPalletItem item = new OutboundPalletItem(); item.setId(IdWorker.getId()); item.setCustomerId(customerId);
|
||||
item.setOutboundOrderId(outbound.getId()); item.setPackageCount(marks.size()); item.setPickedPackageCount(0); item.setStatus("WAIT_PICK");
|
||||
item.setCartonMarks(String.join(",", marks)); item.setInboundCode(request.returnNo().trim()); item.setCreatedAt(now); outboundPallets.insert(item);
|
||||
for (ReturnInventoryCarton carton : locked) {
|
||||
OutboundPalletItem item = new OutboundPalletItem(); item.setId(IdWorker.getId()); item.setCustomerId(customerId);
|
||||
item.setOutboundOrderId(outbound.getId()); item.setPackageCount(1); item.setPickedPackageCount(0); item.setStatus("WAIT_PICK");
|
||||
item.setCartonMarks(carton.getCartonMark()); item.setInboundCode(carton.getSourceReturnNo()); item.setCreatedAt(now); outboundPallets.insert(item);
|
||||
}
|
||||
OutboundPdaTask task = new OutboundPdaTask(); task.setId(IdWorker.getId()); task.setCustomerId(customerId); task.setOutboundOrderId(outbound.getId());
|
||||
task.setTaskNo("PDA" + now.format(DateTimeFormatter.BASIC_ISO_DATE) + task.getId()); task.setStatus("PENDING"); task.setPushedAt(now); task.setCreatedAt(now); task.setUpdatedAt(now); pdaTasks.insert(task);
|
||||
return taskResult(outbound, task);
|
||||
@@ -646,7 +648,12 @@ public class DeliveryTransferService {
|
||||
|| !request.packages().equals(replay.getPackages())) {
|
||||
throw conflict("Idempotency key was reused with a different outbound pick request");
|
||||
}
|
||||
return taskResult(requireOutbound(task), task);
|
||||
OutboundOrder replayOutbound = requireOutbound(task);
|
||||
if ("RETURN_OUTBOUND".equals(replayOutbound.getOutboundType())) {
|
||||
OutboundPalletItem replayItem = outboundPallets.selectById(replay.getOutboundPalletItemId());
|
||||
requireReturnScan(replayOutbound, replayItem, request);
|
||||
}
|
||||
return taskResult(replayOutbound, task);
|
||||
}
|
||||
OutboundOrder existingOutbound = requireOutbound(task);
|
||||
OutboundOrder outbound = outboundOrders.lockByNo(customerId, existingOutbound.getOutboundNo());
|
||||
@@ -660,17 +667,13 @@ public class DeliveryTransferService {
|
||||
|| !task.getOutboundOrderId().equals(item.getOutboundOrderId())) throw notFound("Outbound pallet item not found");
|
||||
if (request.packages() > item.getPackageCount() - value(item.getPickedPackageCount())) throw conflict("Picked quantity exceeds outbound pallet quantity");
|
||||
if ("RETURN_OUTBOUND".equals(outbound.getOutboundType())) {
|
||||
if (request.inventoryPositionId() != null) throw conflict("退货出库无需扫描库存仓位");
|
||||
List<String> marks = Arrays.stream(Optional.ofNullable(item.getCartonMarks()).orElse("").split(","))
|
||||
.map(String::trim).filter(StringUtils::hasText).toList();
|
||||
if (request.packages() != marks.size() || value(item.getPickedPackageCount()) > 0) throw conflict("退货出库必须一次扫描本次箱唛且不可重复");
|
||||
for (String mark : marks) {
|
||||
ReturnInventoryCarton carton = returnCartons.lockMark(mark);
|
||||
if (carton == null || !customerId.equals(carton.getCustomerId()) || !warehouseId.equals(carton.getOverseasWarehouseId()) || !"AVAILABLE".equals(carton.getStatus())) {
|
||||
throw conflict("退货箱唛不可出库:" + mark);
|
||||
}
|
||||
carton.setStatus("OUTBOUNDED"); carton.setUpdatedAt(LocalDateTime.now()); returnCartons.updateById(carton);
|
||||
}
|
||||
requireReturnScan(outbound, item, request);
|
||||
if (value(item.getPickedPackageCount()) > 0) throw conflict("退货箱唛已完成拣货");
|
||||
ReturnInventoryCarton carton = returnCartons.lockMark(item.getCartonMarks());
|
||||
requireReturnSource(outbound, item, carton);
|
||||
if (!"AVAILABLE".equals(carton.getStatus())) throw conflict("退货箱唛不可出库:" + item.getCartonMarks());
|
||||
carton.setStatus("OUTBOUNDED"); carton.setUpdatedAt(LocalDateTime.now());
|
||||
if (returnCartons.updateById(carton) != 1) throw conflict("退货箱唛状态已变化,请重新核对");
|
||||
OutboundPdaPick pick = new OutboundPdaPick(); pick.setId(IdWorker.getId()); pick.setCustomerId(customerId); pick.setTaskId(task.getId()); pick.setOutboundPalletItemId(item.getId()); pick.setInventoryPositionId(null); pick.setPackages(request.packages()); pick.setIdempotencyKey(request.idempotencyKey().trim()); pick.setPickedAt(LocalDateTime.now()); pdaPicks.insert(pick);
|
||||
item.setPickedPackageCount(request.packages().intValue()); item.setStatus("PICKED"); outboundPallets.updateById(item);
|
||||
updateOutboundPickingStatus(customerId, outbound);
|
||||
@@ -1037,7 +1040,8 @@ public class DeliveryTransferService {
|
||||
task.getOutboundOrderId()).stream().map(item -> new DeliveryResponses.PdaTaskItem(item.getId(),
|
||||
item.getPalletNo(), item.getSkuCode(), item.getInboundCode(), value(item.getPackageCount()),
|
||||
value(item.getPickedPackageCount()), item.getStatus(),
|
||||
pdaPickPositions(task.getCustomerId(), boundWarehouseId, item))).toList();
|
||||
"RETURN_OUTBOUND".equals(outbound.getOutboundType()) ? returnPickPositions(outbound, task, item)
|
||||
: pdaPickPositions(task.getCustomerId(), boundWarehouseId, item))).toList();
|
||||
return new DeliveryResponses.PdaTaskDetail(taskResult(outbound, task), items);
|
||||
}
|
||||
|
||||
@@ -1071,6 +1075,34 @@ public class DeliveryTransferService {
|
||||
throw notFound("Outbound or dispatch task not found in the bound warehouse");
|
||||
}
|
||||
|
||||
private void requireReturnScan(OutboundOrder outbound, OutboundPalletItem item, DeliveryRequests.PdaPick request) {
|
||||
if (item == null || !outbound.getId().equals(item.getOutboundOrderId())
|
||||
|| !outbound.getCustomerId().equals(item.getCustomerId())) throw notFound("退货出库明细不存在");
|
||||
if (request.inventoryPositionId() != null || !Long.valueOf(1).equals(request.packages()) || value(item.getPackageCount()) != 1)
|
||||
throw conflict("退货出库须逐箱扫描,无需库存仓位");
|
||||
if (request.cartonMarks() == null || request.cartonMarks().size() != 1 || request.cartonMarks().get(0) == null
|
||||
|| !Objects.equals(item.getCartonMarks(), request.cartonMarks().get(0).trim()))
|
||||
throw conflict("请扫描当前退货出库明细指定的箱唛");
|
||||
}
|
||||
|
||||
private void requireReturnSource(OutboundOrder outbound, OutboundPalletItem item, ReturnInventoryCarton carton) {
|
||||
if (carton == null || !outbound.getCustomerId().equals(carton.getCustomerId())
|
||||
|| !outbound.getOverseasWarehouseId().equals(carton.getOverseasWarehouseId())
|
||||
|| !Objects.equals(item.getInboundCode(), carton.getSourceReturnNo())
|
||||
|| !Objects.equals(item.getCartonMarks(), carton.getCartonMark()))
|
||||
throw conflict("退货箱唛与本次出库的客户、仓库或来源退货单不一致");
|
||||
}
|
||||
|
||||
private List<DeliveryResponses.PdaPickPosition> returnPickPositions(OutboundOrder outbound, OutboundPdaTask task,
|
||||
OutboundPalletItem item) {
|
||||
ReturnInventoryCarton carton = returnCartons.findMark(item.getCartonMarks());
|
||||
requireReturnSource(outbound, item, carton);
|
||||
boolean pending = Set.of("PENDING", "IN_PROGRESS").contains(task.getStatus()) && value(item.getPickedPackageCount()) == 0;
|
||||
long available = pending && "AVAILABLE".equals(carton.getStatus()) ? 1 : 0;
|
||||
return List.of(new DeliveryResponses.PdaPickPosition(null, null, item.getCartonMarks(), item.getSkuCode(),
|
||||
item.getInboundCode(), available, value(item.getPickedPackageCount())));
|
||||
}
|
||||
|
||||
private List<DeliveryResponses.PdaPickPosition> pdaPickPositions(String customerId, String warehouseId,
|
||||
OutboundPalletItem item) {
|
||||
if (item.getWarehousePalletId() == null) return List.of();
|
||||
|
||||
Reference in New Issue
Block a user