贴标申请,仓储转运

This commit is contained in:
2026-09-23 08:41:53 +08:00
parent 2555eda797
commit b21690d943
3 changed files with 38 additions and 8 deletions
@@ -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());
@@ -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<String, RelabelResponses.HistoricalOrder> result = new java.util.LinkedHashMap<>();
@@ -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<Long> 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<LastlegOrder>()
.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<LastlegOrder>()
.eq(LastlegOrder::getCustomerId, customerId)
.eq(LastlegOrder::getInboundCode, inboundCode))
: orders.selectList(new LambdaQueryWrapper<LastlegOrder>()
.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<WarehouseTransferResponses.Summary> pdaCandidates(long overseasWarehouseId) {
return transfers.pdaCandidates(String.valueOf(overseasWarehouseId)).stream().map(value ->
return transfers.selectList(new LambdaQueryWrapper<WarehouseTransferOrder>()
.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";