贴标申请,仓储转运

This commit is contained in:
2026-09-22 08:49:21 +08:00
parent 9147190d67
commit 9a8412279c
28 changed files with 549 additions and 48 deletions
@@ -72,6 +72,8 @@ public record LastlegOrderSummary(
String customerRemark,
String warehouseRemark,
LocalDateTime createdAt,
LocalDateTime updatedAt
LocalDateTime updatedAt,
@Schema(description = "同一主单关联的全部换标子单及各自状态,按创建时间排序")
List<RelabelSubOrder> relabelApplications
) {
}
@@ -0,0 +1,7 @@
package com.baiyue.lastleg.dto;
import java.time.LocalDateTime;
/** A relabel application keeps its own status within the received parent order. */
public record RelabelSubOrder(Long lastlegOrderId, String relabelNo, String status,
Integer quantity, LocalDateTime createdAt) { }
@@ -16,6 +16,11 @@ import java.math.BigDecimal;
@Mapper
public interface LastlegOrderMapper extends BaseMapper<LastlegOrder> {
@Select("<script>SELECT r.lastleg_order_id,r.relabel_no,r.status,r.notified_package_count AS quantity,r.created_at " +
"FROM ll_relabel_application r JOIN ll_order o ON o.id=r.lastleg_order_id AND o.customer_id=r.customer_id " +
"WHERE r.lastleg_order_id IN <foreach collection='orderIds' item='id' open='(' separator=',' close=')'>#{id}</foreach> " +
"ORDER BY r.created_at,r.id</script>")
List<com.baiyue.lastleg.dto.RelabelSubOrder> findRelabelSubOrders(@Param("orderIds") List<Long> orderIds);
String WAREHOUSE_FILTER_SQL = "(LOWER(TRIM(overseas_warehouse_code)) LIKE CONCAT('%',LOWER({0}),'%') " +
"OR LOWER(TRIM(overseas_warehouse_name)) LIKE CONCAT('%',LOWER({0}),'%'))";
@@ -38,7 +38,7 @@ public final class RelabelResponses {
String destinationFbaWarehouseName, String skuCode, String productNameZh,
long availablePackages, long version, List<InventoryPosition> positions,
String sourceType, Long returnCartonId, String cartonMark,
List<SkuItem> skuItems) {}
List<SkuItem> skuItems, long relabelledPackages) {}
public record HistoricalOrder(Long id, String orderNo, String sourceOrderNo, String outboundOrderNo,
String relabelOrderNo, String orderType, String status, Integer packageCount,
LocalDateTime createdAt) {}
@@ -260,7 +260,7 @@ public class RelabelApplicationService implements WalletResultHandler {
balance.getOverseasWarehouseCode(), balance.getOverseasWarehouseName(),
balance.getDestinationWarehouseCode(), balance.getDestinationWarehouseName(), balance.getSkuCode(),
balance.getProductNameZh(), available, value(balance.getVersion()), positions,
"INBOUND", null, null, List.of());
"INBOUND", null, null, List.of(), 0);
}).filter(candidate -> candidate.availablePackages() > 0).toList());
for (ReturnInventoryCarton carton : returnCartons.findAvailable(customerId, operationWarehouseId.trim())) {
String keyword = trim(inboundCode);
@@ -269,19 +269,23 @@ public class RelabelApplicationService implements WalletResultHandler {
&& !containsIgnoreCase(carton.getSourceReturnNo(), keyword)) continue;
List<RelabelResponses.SkuItem> cartonSkus = returnCartonItems.listCarton(carton.getId()).stream()
.filter(item -> value(item.getQuantity()) > 0)
.map(item -> new RelabelResponses.SkuItem(item.getSkuCode(), null,
Math.toIntExact(item.getQuantity()), null)).toList();
.map(item -> {
long used = returnCartons.relabelledQuantity(carton.getId(), item.getSkuCode());
long remaining = value(item.getQuantity()) - used;
return new RelabelResponses.SkuItem(item.getSkuCode(), null,
Math.toIntExact(Math.max(remaining, 0)), null);
}).filter(item -> item.quantity() > 0).toList();
if (cartonSkus.isEmpty()) continue;
String skuCodes = cartonSkus.stream().map(RelabelResponses.SkuItem::skuCode)
.collect(Collectors.joining(","));
long availablePackages = value(carton.getTotalQuantity());
if (availablePackages <= 0) {
availablePackages = cartonSkus.stream().mapToLong(RelabelResponses.SkuItem::quantity).sum();
}
long availablePackages = cartonSkus.stream().mapToLong(RelabelResponses.SkuItem::quantity).sum();
if (availablePackages <= 0) continue;
long relabelledPackages = carton.getTotalQuantity() == null ? 0
: Math.max(0, carton.getTotalQuantity() - availablePackages);
result.add(new RelabelResponses.InventoryCandidate(null, null, carton.getSourceReturnNo(),
null, carton.getOverseasWarehouseId(), null, null, carton.getDestinationWarehouseCode(),
carton.getDestinationWarehouseName(), skuCodes, "退货入库库存", availablePackages, 0, List.of(),
"RETURN_CARTON", carton.getId(), carton.getCartonMark(), cartonSkus));
"RETURN_CARTON", carton.getId(), carton.getCartonMark(), cartonSkus, relabelledPackages));
}
return result;
}
@@ -380,9 +384,10 @@ public class RelabelApplicationService implements WalletResultHandler {
if (!"AVAILABLE".equals(carton.getStatus()) || carton.getRelabelApplicationId() != null) {
throw conflict("仓库唛头 " + carton.getCartonMark() + " 已不可用于换标");
}
long previouslyRelabelled = returnCartons.relabelledQuantity(carton.getId(), item.skuCode());
long requestedPackages = selectedReturnPackages.merge(carton.getId(),
(long) item.notifiedPackageCount(), Math::addExact);
if (requestedPackages > value(carton.getTotalQuantity())) {
if (requestedPackages + previouslyRelabelled > value(carton.getTotalQuantity())) {
throw conflict("退货托盘 " + carton.getCartonMark() + " 可用箱数不足");
}
sources.add(new SourceInventory(item, null, carton));
@@ -455,9 +460,9 @@ public class RelabelApplicationService implements WalletResultHandler {
applications.insert(application);
for (ReturnInventoryCarton carton : selectedReturnCartons.values()) {
carton.setRelabelApplicationId(applicationId); carton.setRelabelNo(relabelNo);
carton.setRelabelStatus("PENDING"); carton.setStatus("RELABEL_PENDING"); carton.setUpdatedAt(now);
returnCartons.updateById(carton);
if (returnCartons.markRelabelPending(carton.getId(), applicationId, relabelNo, now) != 1) {
throw conflict("退货箱状态已变化,请刷新后重试");
}
}
if (requiresWallet) {
@@ -600,6 +605,7 @@ public class RelabelApplicationService implements WalletResultHandler {
}
}
for (LastlegOrder order : linkedOrders) {
if ("RETURN_RELABEL".equals(order.getOrderType()) && !Objects.equals(order.getRelabelOrderNo(), application.getRelabelNo())) continue;
String orderBefore = order.getCurrentStatus();
String mainStatus = "RELABEL_APPLICATION".equals(order.getOrderType())
? "WAIT_RELABEL" : orderBefore;
@@ -612,8 +618,7 @@ public class RelabelApplicationService implements WalletResultHandler {
};
// Reviewing/processing a return relabel must not move the already
// completed inbound order back to assignment or relabel waiting.
if ("RETURN_RELABEL".equals(order.getOrderType())
&& !Set.of("COMPLETED", "REJECTED", "CANCELLED").contains(next)) {
if ("RETURN_RELABEL".equals(order.getOrderType())) {
orderStatus = "INBOUND_COMPLETED";
}
order.setCurrentStatus(orderStatus);
@@ -703,6 +708,7 @@ public class RelabelApplicationService implements WalletResultHandler {
application.setStatus("PROCESSING"); application.setFulfillmentStatus("WAIT_RELABEL");
application.setUpdatedAt(LocalDateTime.now()); applications.updateById(application);
for (LastlegOrder order : tailOrders(application)) {
if ("RETURN_RELABEL".equals(order.getOrderType()) && !Objects.equals(order.getRelabelOrderNo(), application.getRelabelNo())) continue;
order.setRelabelStatus("PROCESSING"); order.setSubOrderStatus("RELABEL:PROCESSING");
order.setUpdatedAt(LocalDateTime.now()); orders.updateById(order);
}
@@ -748,9 +754,18 @@ public class RelabelApplicationService implements WalletResultHandler {
}
application.setUpdatedAt(now);
applications.updateById(application);
WarehouseTransferOrder linkedTransfer = warehouseTransfers == null ? null
: warehouseTransfers.lockByRelabelNo(customerId, relabelNo);
for (LastlegOrder order : tailOrders(application)) {
if ("RETURN_RELABEL".equals(order.getOrderType()) && !Objects.equals(order.getRelabelOrderNo(), application.getRelabelNo())) continue;
// 仓储转运尾程单由下方按转运目的仓一次性写入精确状态,避免先落入通用状态。
if (linkedTransfer != null && "WAIT_RELABEL".equals(linkedTransfer.getStatus())
&& Objects.equals(order.getId(), linkedTransfer.getLastlegOrderId())) continue;
String orderBefore = order.getCurrentStatus();
order.setCurrentStatus(requiresOutbound ? "PENDING_ASSIGNMENT" : "COMPLETED");
// 换标确认时货物已经完成入库,不得退回最初建单的“待分配”。
// 独立换标先进入待出库;仓储转运会在下方按目的仓进一步收敛为待排车或待确认目的仓。
order.setCurrentStatus("RETURN_RELABEL".equals(order.getOrderType()) ? "INBOUND_COMPLETED"
: requiresOutbound ? "WAIT_OUTBOUND" : "COMPLETED");
order.setSubOrderStatus("RELABEL:" + application.getFulfillmentStatus());
order.setRelabelStatus("COMPLETED");
order.setUpdatedAt(now);
@@ -774,13 +789,16 @@ public class RelabelApplicationService implements WalletResultHandler {
ReturnInventoryCarton carton = returnCartons.lockId(item.getReturnCartonId());
if (carton == null || !Objects.equals(carton.getRelabelApplicationId(), application.getId())) continue;
carton.setRelabelStatus("COMPLETED"); carton.setRelabelCompletedAt(now);
// 换标已完成后释放“当前申请占用”关系,但保留 COMPLETED 作为历史状态。
// 否则退货箱虽显示 AVAILABLE,下一次贴标申请仍会被旧 relabel_application_id 拦截。
carton.setRelabelApplicationId(null); carton.setRelabelNo(null);
carton.setStatus("AVAILABLE"); carton.setUpdatedAt(now); returnCartons.updateById(carton);
}
insertHistory(customerId, application.getId(), before, application.getStatus(), operatorId,
request.remark(), now);
// 仓储转运换标在客户确认后立即恢复为可排车,发车时再转为 OUTBOUNDED。
if (warehouseTransfers != null) {
WarehouseTransferOrder transfer = warehouseTransfers.lockByRelabelNo(customerId, relabelNo);
if (linkedTransfer != null) {
WarehouseTransferOrder transfer = linkedTransfer;
if (transfer != null && "WAIT_RELABEL".equals(transfer.getStatus())) {
Set<String> destinations = relabelItems.stream()
.map(RelabelItem::getDestinationFbaWarehouseCode)
@@ -8,7 +8,8 @@ public final class ReturnOrderResponses {
public record Summary(String returnNo, String lastlegOrderNo, String overseasWarehouseId,
String warehouseContactName, String warehouseContactPhone, String customerReferenceNo, String status,
int skuTypes, long expectedQuantity, long receivedQuantity, boolean needRelabel,
String relabelNo, String relabelStatus, String discrepancyReason, LocalDateTime createdAt) { }
String relabelNo, String relabelStatus, String discrepancyReason, LocalDateTime createdAt,
List<com.baiyue.lastleg.dto.RelabelSubOrder> relabelApplications) { }
public record Item(String skuCode, String productNameZh, long expectedQuantity,
long receivedQuantity) { }
public record Detail(Summary order, String remark, List<Item> items, List<Receipt> receipts, List<PalletDetail> pallets, List<Photo> photos) { }
@@ -36,6 +36,12 @@ public interface ReturnInventoryCartonMapper extends BaseMapper<ReturnInventoryC
@Select("SELECT * FROM ll_return_inventory_carton WHERE id=#{id} FOR UPDATE")
ReturnInventoryCarton lockId(@Param("id") long id);
@Select("SELECT COALESCE(SUM(ri.notified_package_count),0) FROM ll_relabel_item ri " +
"JOIN ll_relabel_application ra ON ra.id=ri.application_id " +
"WHERE ri.return_carton_id=#{cartonId} AND ri.sku_code=#{skuCode} " +
"AND ra.status NOT IN ('CANCELLED','REJECTED')")
long relabelledQuantity(@Param("cartonId") long cartonId, @Param("skuCode") String skuCode);
@Update("UPDATE ll_return_inventory_carton SET total_quantity=#{remaining},sku_types=#{skuTypes},status='AVAILABLE'," +
"relabel_application_id=NULL,relabel_no=NULL,relabel_status=NULL,updated_at=NOW(3) " +
"WHERE id=#{id} AND customer_id=#{customerId} AND relabel_application_id=#{applicationId} " +
@@ -44,6 +50,12 @@ public interface ReturnInventoryCartonMapper extends BaseMapper<ReturnInventoryC
@Param("applicationId") long applicationId, @Param("remaining") long remaining,
@Param("skuTypes") int skuTypes);
@Update("UPDATE ll_return_inventory_carton SET relabel_application_id=#{applicationId},relabel_no=#{relabelNo}," +
"relabel_status='PENDING',status='RELABEL_PENDING',updated_at=#{updatedAt} " +
"WHERE id=#{id} AND status='AVAILABLE' AND sku_types>0 AND total_quantity>0 AND relabel_application_id IS NULL")
int markRelabelPending(@Param("id") long id, @Param("applicationId") long applicationId,
@Param("relabelNo") String relabelNo, @Param("updatedAt") java.time.LocalDateTime updatedAt);
@Select("SELECT * FROM ll_return_inventory_carton WHERE source_receipt_id=#{receiptId} LIMIT 1")
ReturnInventoryCarton findReceipt(@Param("receiptId") long receiptId);
@@ -13,6 +13,8 @@ public interface ReturnOrderMapper extends BaseMapper<ReturnOrder> {
ReturnOrder findKey(@Param("customerId") String customerId, @Param("key") String key);
@Select("SELECT * FROM ll_return_order WHERE customer_id=#{customerId} AND return_no=#{returnNo} LIMIT 1")
ReturnOrder findNo(@Param("customerId") String customerId, @Param("returnNo") String returnNo);
@Select("SELECT * FROM ll_return_order WHERE customer_id=#{customerId} AND return_no=#{returnNo} LIMIT 1 FOR UPDATE")
ReturnOrder lockCustomerNo(@Param("customerId") String customerId, @Param("returnNo") String returnNo);
@Select("SELECT * FROM ll_return_order WHERE return_no=#{returnNo} LIMIT 1 FOR UPDATE")
ReturnOrder lockNo(@Param("returnNo") String returnNo);
@Select("SELECT * FROM ll_return_order WHERE return_no=#{returnNo} AND overseas_warehouse_id=#{warehouseId} " +
@@ -186,7 +186,9 @@ public class ReturnReceiptService {
w.in(ReturnOrder::getId, ids);
}
Page<ReturnOrder> result = orders.selectPage(Page.of(query.page(), query.size()), w);
return new PageResult<>(result.getRecords().stream().map(this::summary).toList(), result.getCurrent(),
var relabels = relabelSubOrders(result.getRecords());
return new PageResult<>(result.getRecords().stream().map(order -> summary(order,
relabels.getOrDefault(order.getLastlegOrderId(), List.of()))).toList(), result.getCurrent(),
result.getSize(), result.getTotal(), result.getPages());
}
@@ -216,7 +218,7 @@ public class ReturnReceiptService {
}).toList();
List<ReturnOrderResponses.Photo> photos = photoList(order).stream()
.map(file -> new ReturnOrderResponses.Photo(file.fileId(), file.fileName(), file.contentType(), file.sizeBytes())).toList();
return new ReturnOrderResponses.Detail(summary(order), order.getRemark(), items, receiptViews, palletViews, photos);
return new ReturnOrderResponses.Detail(summary(order, relabelSubOrders(List.of(order)).getOrDefault(order.getLastlegOrderId(), List.of())), order.getRemark(), items, receiptViews, palletViews, photos);
}
public com.baiyue.lastleg.relabel.pda.gateway.RelabelPhotoFileGateway.DownloadedFile downloadPhoto(String customerId, String returnNo, long fileId) {
@@ -265,7 +267,7 @@ public class ReturnReceiptService {
@Transactional
public ReturnOrderResponses.RelabelCreated createRelabel(String customerId, String operatorId, String returnNo,
ReturnOrderRequests.RelabelCreate request) {
ReturnOrder order = orders.findNo(customerId, text(returnNo));
ReturnOrder order = orders.lockCustomerNo(customerId, text(returnNo));
if (order == null) throw notFound("退货单不存在");
if (!COMPLETED.equals(order.getStatus())) throw conflict("退货单尚未完成签收");
String fileScope = norm(request.fileScope());
@@ -273,9 +275,14 @@ public class ReturnReceiptService {
String key = text(request.idempotencyKey());
String requestHash = hash(request);
RelabelApplication replay = relabelApplications.findKey(customerId, key);
if (replay != null) return new ReturnOrderResponses.RelabelCreated(replay.getRelabelNo(), replay.getId(),
order.getReturnNo(), request.items().stream().map(ReturnOrderRequests.RelabelItem::skuCode).toList(), replay.getStatus());
if (text(order.getRelabelNo()) != null) throw conflict("当前退货单已经生成贴标申请");
if (replay != null) {
if (!order.getReturnNo().equals(replay.getCustomerOrderNo()) || !requestHash.equals(replay.getRequestHash()))
throw conflict("相同幂等键的贴标申请内容不一致");
return new ReturnOrderResponses.RelabelCreated(replay.getRelabelNo(), replay.getId(),
order.getReturnNo(), request.items().stream().map(ReturnOrderRequests.RelabelItem::skuCode).toList(), replay.getStatus());
}
// The order keeps the latest application reference, not an order-wide inventory lock.
// Each new application must still allocate only unlabelled, available carton quantities below.
var destination = fbaWarehouseValidator.required(request.destinationFbaWarehouseId(), request.destinationFbaWarehouseCode(), null);
Map<String, ReturnOrderItem> receivedBySku = orderItems.lockOrder(order.getId()).stream()
.collect(java.util.stream.Collectors.toMap(item -> norm(item.getSkuCode()), item -> item));
@@ -311,8 +318,10 @@ public class ReturnReceiptService {
tail.setRelabelStatus("PENDING_REVIEW");
tail.setSubOrderStatus("RETURN_RELABEL:PENDING_REVIEW");
tail.setCurrentStatus("RETURN_RELABEL".equals(tail.getOrderType()) ? "INBOUND_COMPLETED" : tail.getCurrentStatus());
tail.setPackageCount(Math.toIntExact(totalQuantity));
tail.setProductQuantity(Math.toIntExact(totalQuantity));
if (!"RETURN_RELABEL".equals(tail.getOrderType())) {
tail.setPackageCount(Math.toIntExact(totalQuantity));
tail.setProductQuantity(Math.toIntExact(totalQuantity));
}
tail.setUpdatedAt(now);
lastlegOrders.updateById(tail);
RelabelApplication app = new RelabelApplication(); app.setId(appId); app.setCustomerId(customerId); app.setRelabelNo(relabelNo); app.setLastlegOrderId(tail.getId());
@@ -331,6 +340,7 @@ public class ReturnReceiptService {
long skuQuantity = cartonItems.listCarton(candidate.getId()).stream()
.filter(line -> norm(requested.skuCode()).equals(norm(line.getSkuCode())))
.mapToLong(line -> value(line.getQuantity())).sum();
skuQuantity -= cartons.relabelledQuantity(candidate.getId(), norm(requested.skuCode()));
if (skuQuantity <= 0) continue;
ReturnInventoryCarton carton = selectedCartons.computeIfAbsent(candidate.getId(), ignored -> cartons.lockId(candidate.getId()));
if (carton == null || !"AVAILABLE".equals(carton.getStatus()) || carton.getRelabelApplicationId() != null)
@@ -551,10 +561,16 @@ public class ReturnReceiptService {
return new PdaReturnReceiptResponses.Confirmed(order.getReturnNo(), receipt.getReceiptNo(), receipt.getReceiptBatchNo(), receipt.getPalletCode(),
order.getStatus(), completed, value(order.getExpectedQuantity()), value(order.getReceivedQuantity()), receipt.getSignedAt());
}
private ReturnOrderResponses.Summary summary(ReturnOrder order) { return new ReturnOrderResponses.Summary(order.getReturnNo(), order.getLastlegOrderNo(),
private Map<Long, List<com.baiyue.lastleg.dto.RelabelSubOrder>> relabelSubOrders(List<ReturnOrder> values) {
var ids = values.stream().map(ReturnOrder::getLastlegOrderId).filter(java.util.Objects::nonNull).distinct().toList();
if (ids.isEmpty()) return java.util.Collections.emptyMap();
var rows = lastlegOrders.findRelabelSubOrders(ids);
return rows == null ? java.util.Collections.emptyMap() : rows.stream().collect(java.util.stream.Collectors.groupingBy(com.baiyue.lastleg.dto.RelabelSubOrder::lastlegOrderId));
}
private ReturnOrderResponses.Summary summary(ReturnOrder order, List<com.baiyue.lastleg.dto.RelabelSubOrder> relabelApplications) { return new ReturnOrderResponses.Summary(order.getReturnNo(), order.getLastlegOrderNo(),
order.getOverseasWarehouseId(), order.getWarehouseContactName(), order.getWarehouseContactPhone(), order.getCustomerReferenceNo(), order.getStatus(),
order.getExpectedSkuTypes() == null ? 0 : order.getExpectedSkuTypes(), value(order.getExpectedQuantity()),
value(order.getReceivedQuantity()), Boolean.TRUE.equals(order.getNeedRelabel()), order.getRelabelNo(), order.getRelabelStatus(), order.getDiscrepancyReason(), order.getCreatedAt()); }
value(order.getReceivedQuantity()), Boolean.TRUE.equals(order.getNeedRelabel()), order.getRelabelNo(), order.getRelabelStatus(), order.getDiscrepancyReason(), order.getCreatedAt(), relabelApplications); }
private ReturnOrderResponses.Item item(ReturnOrderItem item) { return new ReturnOrderResponses.Item(item.getSkuCode(),
item.getProductNameZh(), value(item.getExpectedQuantity()), value(item.getReceivedQuantity())); }
private PdaReturnReceiptResponses.Item pdaItem(ReturnOrderItem item) { return new PdaReturnReceiptResponses.Item(item.getSkuCode(),
@@ -96,10 +96,12 @@ public class LastlegOrderService {
Map<String, String> containerNodes = containerNodes(page.getRecords());
Map<Long, String> dispatchStatuses = dispatchStatuses(page.getRecords());
Map<Long, LastlegOrderMapper.OrderWeightRow> weights = orderWeights(page.getRecords());
Map<Long, List<com.baiyue.lastleg.dto.RelabelSubOrder>> relabels = relabelSubOrders(page.getRecords());
return new PageResult<>(page.getRecords().stream().map(order -> summary(order, mergeRelations.get(order.getId()),
StringUtils.hasText(order.getSourceContainerBookingId())
? containerNodes.get(order.getSourceContainerBookingId()) : null,
dispatchStatuses.getOrDefault(order.getId(), "UNSCHEDULED"), weights.get(order.getId()))).toList(),
dispatchStatuses.getOrDefault(order.getId(), "UNSCHEDULED"), weights.get(order.getId()),
relabels.getOrDefault(order.getId(), List.of()))).toList(),
page.getCurrent(), page.getSize(), page.getTotal(), page.getPages());
}
@@ -353,7 +355,7 @@ public class LastlegOrderService {
.sorted(java.util.Comparator.comparingInt(value -> MANUAL_NODE_CODES.indexOf(value.nodeCode()))).toList();
return new LastlegOrderDetailResponse(summary(order, palletMergeRelations(List.of(order)).get(order.getId()),
containerNode(order), dispatchStatuses(List.of(order)).getOrDefault(order.getId(), "UNSCHEDULED"),
orderWeights(List.of(order)).get(order.getId())), manualNodes, cargo, history.stream()
orderWeights(List.of(order)).get(order.getId()), relabelSubOrders(List.of(order)).getOrDefault(order.getId(), List.of())), manualNodes, cargo, history.stream()
.map(value -> new LastlegOrderDetailResponse.History(value.getId(), value.getFromStatus(),
value.getToStatus(), value.getRemark(), value.getCreatedAt())).toList(), fees, operations.stream()
.map(value -> new LastlegOrderDetailResponse.Operation(value.getId(), value.getOperationNode(),
@@ -577,7 +579,10 @@ public class LastlegOrderService {
.like(LastlegOrder::getOrderNo, query.orderNo())
.or()
.like(LastlegOrder::getSourceOrderNo, query.orderNo()))
.like(StringUtils.hasText(relabelNo), LastlegOrder::getRelabelOrderNo, relabelNo)
.and(StringUtils.hasText(relabelNo), nested -> nested
.like(LastlegOrder::getRelabelOrderNo, relabelNo)
.or().apply("EXISTS (SELECT 1 FROM ll_relabel_application r WHERE r.lastleg_order_id=ll_order.id " +
"AND r.customer_id=ll_order.customer_id AND r.relabel_no LIKE CONCAT('%',{0},'%'))", relabelNo))
.eq(StringUtils.hasText(query.orderType()), LastlegOrder::getOrderType, query.orderType())
.like(StringUtils.hasText(query.inboundCode()), LastlegOrder::getInboundCode, query.inboundCode())
.like(StringUtils.hasText(query.lxCode()), LastlegOrder::getLxCode, query.lxCode())
@@ -637,9 +642,16 @@ public class LastlegOrderService {
return rows.stream().collect(Collectors.toMap(LastlegOrderMapper.OrderWeightRow::orderId, row -> row));
}
private Map<Long, List<com.baiyue.lastleg.dto.RelabelSubOrder>> relabelSubOrders(List<LastlegOrder> orders) {
if (orders.isEmpty()) return Map.of();
var rows = orderMapper.findRelabelSubOrders(orders.stream().map(LastlegOrder::getId).toList());
return rows == null ? Map.of() : rows.stream().collect(Collectors.groupingBy(com.baiyue.lastleg.dto.RelabelSubOrder::lastlegOrderId));
}
private LastlegOrderSummary summary(LastlegOrder o, List<LastlegOrderMapper.PalletMergeRelationRow> relations,
String containerNode, String dispatchStatus,
LastlegOrderMapper.OrderWeightRow weight) {
LastlegOrderMapper.OrderWeightRow weight,
List<com.baiyue.lastleg.dto.RelabelSubOrder> relabelApplications) {
List<LastlegOrderMapper.PalletMergeRelationRow> related = relations == null ? List.of() : relations;
return new LastlegOrderSummary(o.getId(), displayOrderNo(o), o.getOrderType(),
LastlegOrderType.labelOf(o.getOrderType()), o.getDestinationType(), o.getSourceInboundId(),
@@ -657,7 +669,7 @@ public class LastlegOrderService {
o.getPalletMergeFlag(), related.stream().map(LastlegOrderMapper.PalletMergeRelationRow::mergeGroupNo).distinct().findFirst().orElse(null),
related.stream().map(LastlegOrderMapper.PalletMergeRelationRow::relatedInboundNo).filter(Objects::nonNull).distinct().toList(),
o.getCurrentStatus(), o.getSubOrderStatus(), o.getPrivateRemark(),
o.getCustomerRemark(), o.getWarehouseRemark(), o.getCreatedAt(), o.getUpdatedAt());
o.getCustomerRemark(), o.getWarehouseRemark(), o.getCreatedAt(), o.getUpdatedAt(), relabelApplications);
}
private static Integer packageDifference(LastlegOrder order) {