diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/delivery/service/DeliveryTransferService.java b/lastleg-service/src/main/java/com/baiyue/lastleg/delivery/service/DeliveryTransferService.java index 5cf0b1f75..59aabd63e 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/delivery/service/DeliveryTransferService.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/delivery/service/DeliveryTransferService.java @@ -959,7 +959,7 @@ public class DeliveryTransferService { .filter(StringUtils::hasText).distinct().toList()) { WarehouseTransferOrder transfer = warehouseTransfers.lockNo(customerId, transferNo); if (transfer == null || !"WAIT_OUTBOUND".equals(transfer.getStatus())) continue; - String restored = StringUtils.hasText(transfer.getFbaWarehouseCode()) + String restored = "FBA".equals(transfer.getDestinationType()) || "PRIVATE".equals(transfer.getDestinationType()) ? "READY_FOR_DISPATCH" : "WAIT_FBA_DESTINATION"; transfer.setStatus(restored); transfer.setUpdatedAt(now); warehouseTransfers.updateById(transfer); LastlegOrder order = tailOrders.selectById(transfer.getLastlegOrderId()); diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/relabel/service/RelabelApplicationService.java b/lastleg-service/src/main/java/com/baiyue/lastleg/relabel/service/RelabelApplicationService.java index d7e0a524e..bcba7a6c9 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/relabel/service/RelabelApplicationService.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/relabel/service/RelabelApplicationService.java @@ -301,7 +301,8 @@ public class RelabelApplicationService implements WalletResultHandler { .and(w -> w.like(StringUtils.hasText(q), LastlegOrder::getOrderNo, q) .or().like(StringUtils.hasText(q), LastlegOrder::getSourceOrderNo, q) .or().like(StringUtils.hasText(q), LastlegOrder::getRelabelOrderNo, q) - .or().like(StringUtils.hasText(q), LastlegOrder::getOutboundOrderNo, q)) + .or().like(StringUtils.hasText(q), LastlegOrder::getOutboundOrderNo, q) + .or().like(StringUtils.hasText(q), LastlegOrder::getInboundCode, q)) .orderByDesc(LastlegOrder::getCreatedAt).orderByDesc(LastlegOrder::getId) .last("LIMIT 100")); Map result = new java.util.LinkedHashMap<>(); diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/transfer/service/WarehouseTransferService.java b/lastleg-service/src/main/java/com/baiyue/lastleg/transfer/service/WarehouseTransferService.java index ac35f3220..825deef0d 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/transfer/service/WarehouseTransferService.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/transfer/service/WarehouseTransferService.java @@ -147,6 +147,8 @@ public class WarehouseTransferService { validateDestination(request.destinationType(), request.destinationWarehouseCode(), request.fbaWarehouseCode(), request.privateDestinationAddress(), request.privateDestinationPostalCode(), request.privateDestinationContactName(), request.privateDestinationContactPhone()); + validateTransferDestinationRelabel(request.destinationType(), request.fbaWarehouseCode(), request.destinationWarehouseCode(), + request.needRelabel()); String key = request.idempotencyKey().trim(); String requestHash = hash(request); WarehouseTransferOrder replay = transfers.findKey(customerId, key); @@ -164,8 +166,8 @@ public class WarehouseTransferService { List selectedIds = request.sourceLastlegOrderIds() == null ? List.of() : request.sourceLastlegOrderIds().stream().distinct().toList(); boolean existingInventoryTransfer = StringUtils.hasText(requestedInboundCode) || !selectedIds.isEmpty(); - if (existingInventoryTransfer && (!StringUtils.hasText(requestedInboundCode) || selectedIds.isEmpty())) { - throw badRequest("Existing inventory transfer requires both inboundCode and sourceLastlegOrderIds"); + if (existingInventoryTransfer && !StringUtils.hasText(requestedInboundCode)) { + throw badRequest("Existing inventory transfer requires inboundCode"); } Long inboundOrderId; @@ -175,9 +177,16 @@ public class WarehouseTransferService { inboundCode = requestedInboundCode; inboundOrderId = inboundSnapshots.findId(customerId, inboundCode); if (inboundOrderId == null) throw notFound("Inbound order was not found for inboundCode " + inboundCode); - selectedOrders = orders.selectList(new LambdaQueryWrapper() - .eq(LastlegOrder::getCustomerId, customerId).in(LastlegOrder::getId, selectedIds)); - if (selectedOrders.size() != selectedIds.size()) { + // The merchant form may only submit the inventory inbound code. In that + // case derive all eligible tail orders for the inbound instead of + // rejecting a valid inventory transfer because source IDs were omitted. + selectedOrders = selectedIds.isEmpty() + ? orders.selectList(new LambdaQueryWrapper() + .eq(LastlegOrder::getCustomerId, customerId) + .eq(LastlegOrder::getInboundCode, inboundCode)) + : orders.selectList(new LambdaQueryWrapper() + .eq(LastlegOrder::getCustomerId, customerId).in(LastlegOrder::getId, selectedIds)); + if (selectedOrders.isEmpty() || (!selectedIds.isEmpty() && selectedOrders.size() != selectedIds.size())) { throw notFound("One or more selected customer orders do not exist in the current tenant"); } } else { @@ -270,6 +279,8 @@ public class WarehouseTransferService { validateDestination(request.destinationType(), request.destinationWarehouseCode(), request.fbaWarehouseCode(), request.privateDestinationAddress(), request.privateDestinationPostalCode(), request.privateDestinationContactName(), request.privateDestinationContactPhone()); + validateTransferDestinationRelabel(request.destinationType(), request.fbaWarehouseCode(), request.destinationWarehouseCode(), + request.needRelabel()); LastlegOrder order = requireTailOrder(customerId, transfer); LocalDateTime now = LocalDateTime.now(); @@ -1203,7 +1214,10 @@ public class WarehouseTransferService { @Transactional(readOnly = true) public List pdaCandidates(long overseasWarehouseId) { - return transfers.pdaCandidates(String.valueOf(overseasWarehouseId)).stream().map(value -> + return transfers.selectList(new LambdaQueryWrapper() + .eq(WarehouseTransferOrder::getOperatingWarehouseId, String.valueOf(overseasWarehouseId)) + .in(WarehouseTransferOrder::getStatus, List.of(WAIT_PDA_RECEIVING, APPROVED, ALLOCATED, WAIT_RELABEL, READY_FOR_DISPATCH)) + .orderByDesc(WarehouseTransferOrder::getUpdatedAt)).stream().map(value -> new WarehouseTransferResponses.Summary(value.getId(), value.getTransferNo(), value.getInboundCode(), value.getLastlegOrderId(), value.getLastlegOrderNo(), value.getOperatingWarehouseId(), value.getFbaWarehouseCode(), value.getDestinationType(), value.getDestinationWarehouseCode(), @@ -1377,6 +1391,21 @@ public class WarehouseTransferService { } } + private static void validateTransferDestinationRelabel(String destinationType, String fbaWarehouseCode, + String destinationWarehouseCode, boolean needRelabel) { + String type = trim(destinationType); + if (type == null && StringUtils.hasText(fbaWarehouseCode)) type = "FBA"; + if (type == null || "NONE".equalsIgnoreCase(type)) { + throw badRequest("仓储转运必须选择 FBA 仓或私人仓"); + } + if ("FBA".equalsIgnoreCase(type) && !needRelabel) { + throw badRequest("转运到 FBA 仓必须同时创建贴标单"); + } + if ("PRIVATE".equalsIgnoreCase(type) && needRelabel) { + throw badRequest("不需要贴标时请选择私人仓作为目的地"); + } + } + private static void applyDestination(WarehouseTransferOrder transfer, WarehouseTransferRequests.Create request) { String type = trim(request.destinationType()); if (type == null && StringUtils.hasText(request.fbaWarehouseCode())) type = "FBA";