fix(lastleg): validate dropship SKU for PDA outbound
This commit is contained in:
+33
-13
@@ -217,9 +217,7 @@ public class DeliveryTransferService {
|
||||
OutboundOrder existing = outboundOrders.findByIdempotency(customerId, request.idempotencyKey().trim());
|
||||
if (existing != null) return taskResult(existing, pdaTasks.lockByOutbound(customerId, existing.getId()));
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
InventoryPosition firstPosition = inventoryPositions.selectById(request.items().get(0).inventoryPositionId());
|
||||
if (firstPosition == null || !customerId.equals(firstPosition.getCustomerId())) throw notFound("Inventory position not found");
|
||||
String selectedWarehouseId = firstPosition.getOverseasWarehouseId();
|
||||
String selectedWarehouseId = validateOneClickItems(customerId, request.items());
|
||||
OutboundOrder outbound = new OutboundOrder();
|
||||
outbound.setId(IdWorker.getId()); outbound.setCustomerId(customerId);
|
||||
outbound.setOutboundNo(orderNoGenerator.next("ONE_CLICK_DROPSHIP", selectedWarehouseId, outbound.getId()));
|
||||
@@ -230,11 +228,6 @@ public class DeliveryTransferService {
|
||||
for (DeliveryRequests.OneClickItem input : request.items()) {
|
||||
InventoryPosition position = inventoryPositions.selectById(input.inventoryPositionId());
|
||||
if (position == null || !customerId.equals(position.getCustomerId())) throw notFound("Inventory position not found");
|
||||
DropshipOrderProfile profile = dropshipProfiles.findPosition(customerId, position.getId());
|
||||
if (profile == null) throw conflict("Selected pallet is not one-click dropship inventory");
|
||||
if (selectedWarehouseId == null) selectedWarehouseId = position.getOverseasWarehouseId();
|
||||
else if (!Objects.equals(selectedWarehouseId, position.getOverseasWarehouseId())) throw conflict("One outbound order must use inventory from the same overseas warehouse");
|
||||
if (value(position.getAvailablePackages()) < input.packages()) throw conflict("Insufficient available inventory for pallet " + position.getPalletNo());
|
||||
OutboundPalletItem item = new OutboundPalletItem(); item.setId(IdWorker.getId()); item.setCustomerId(customerId); item.setOutboundOrderId(outbound.getId());
|
||||
item.setWarehousePalletId(position.getPalletId()); item.setPalletNo(position.getPalletNo()); item.setPackageCount(input.packages().intValue()); item.setPickedPackageCount(0); item.setStatus("WAIT_PICK"); item.setSkuCode(input.sku().trim()); item.setCreatedAt(now);
|
||||
outboundPallets.insert(item);
|
||||
@@ -245,6 +238,37 @@ public class DeliveryTransferService {
|
||||
return taskResult(outbound, task);
|
||||
}
|
||||
|
||||
private String validateOneClickItems(String customerId, List<DeliveryRequests.OneClickItem> items) {
|
||||
String warehouseId = null;
|
||||
Map<String, Long> requestedPackages = new LinkedHashMap<>();
|
||||
Map<String, DropshipOrderProfile> profiles = new HashMap<>();
|
||||
for (DeliveryRequests.OneClickItem input : items) {
|
||||
InventoryPosition position = inventoryPositions.selectById(input.inventoryPositionId());
|
||||
if (position == null || !customerId.equals(position.getCustomerId())) throw notFound("Inventory position not found");
|
||||
DropshipOrderProfile profile = dropshipProfiles.findPosition(customerId, position.getId());
|
||||
if (profile == null) throw conflict("Selected pallet is not one-click dropship inventory");
|
||||
if (warehouseId == null) warehouseId = position.getOverseasWarehouseId();
|
||||
else if (!Objects.equals(warehouseId, position.getOverseasWarehouseId())) {
|
||||
throw conflict("One outbound order must use inventory from the same overseas warehouse");
|
||||
}
|
||||
if (value(position.getAvailablePackages()) < input.packages()) {
|
||||
throw conflict("Insufficient available inventory for pallet " + position.getPalletNo());
|
||||
}
|
||||
String key = profile.getId() + "\u0000" + input.sku().trim();
|
||||
requestedPackages.merge(key, input.packages(), Long::sum);
|
||||
profiles.put(key, profile);
|
||||
}
|
||||
for (Map.Entry<String, Long> requested : requestedPackages.entrySet()) {
|
||||
String sku = requested.getKey().substring(requested.getKey().indexOf('\u0000') + 1);
|
||||
List<DropshipCarton> cartons = dropshipCartons.lockAvailable(customerId,
|
||||
profiles.get(requested.getKey()).getId(), sku, requested.getValue());
|
||||
if (cartons.size() != requested.getValue()) {
|
||||
throw conflict("Insufficient available one-click dropship cartons for SKU " + sku);
|
||||
}
|
||||
}
|
||||
return warehouseId;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public DeliveryResponses.PdaTask pdaPick(String warehouseId, String operatorId, String taskNo,
|
||||
DeliveryRequests.PdaPick request) {
|
||||
@@ -278,10 +302,6 @@ public class DeliveryTransferService {
|
||||
if (!warehouseId.equals(selectedPosition.getOverseasWarehouseId())) {
|
||||
throw conflict("Scanned inventory position does not belong to the bound warehouse");
|
||||
}
|
||||
InventoryBalance selectedBalance = inventoryBalances.selectById(selectedPosition.getBalanceId());
|
||||
if (!matchesOutboundItem(customerId, warehouseId, item, selectedBalance)) {
|
||||
throw conflict("Scanned inventory position does not belong to the outbound item");
|
||||
}
|
||||
DropshipOrderProfile profile = dropshipProfiles.findPosition(customerId, request.inventoryPositionId());
|
||||
if (profile == null) throw conflict("Scanned pallet is not one-click dropship inventory");
|
||||
List<DropshipCarton> cartons = dropshipCartons.lockAvailable(customerId, profile.getId(), item.getSkuCode(), request.packages());
|
||||
@@ -395,12 +415,12 @@ public class DeliveryTransferService {
|
||||
long available = value(position.getAvailablePackages());
|
||||
if (available <= 0 || !warehouseId.equals(position.getOverseasWarehouseId())) continue;
|
||||
InventoryBalance balance = inventoryBalances.selectById(position.getBalanceId());
|
||||
if (!matchesOutboundItem(customerId, warehouseId, item, balance)) continue;
|
||||
DropshipOrderProfile profile = dropshipProfiles.findPosition(customerId, position.getId());
|
||||
List<String> marks = profile == null ? List.of() : dropshipCartons.listProfile(customerId, profile.getId())
|
||||
.stream().filter(carton -> "AVAILABLE".equals(carton.getStatus()))
|
||||
.filter(carton -> Objects.equals(item.getSkuCode(), carton.getSkuCode()))
|
||||
.map(DropshipCarton::getCartonMark).filter(StringUtils::hasText).distinct().limit(available).toList();
|
||||
if (!matchesOutboundItem(customerId, warehouseId, item, balance) && marks.isEmpty()) continue;
|
||||
if (marks.isEmpty()) {
|
||||
result.add(pdaPosition(position, item, balance, null, available, value(position.getPickedPackages())));
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user