Merge remote-tracking branch 'origin/test' into test

This commit is contained in:
2026-10-21 23:23:15 +08:00
5 changed files with 161 additions and 4 deletions
@@ -0,0 +1,24 @@
package com.baiyue.lastleg.client;
import com.baiyue.common.core.api.ApiResponse;
import com.baiyue.common.core.api.PageResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@FeignClient(name="order-service", contextId="lastlegOrderPreDepartureClient", path="/internal/order/v1/predeparture-orders")
public interface OrderPreDepartureClient {
@GetMapping
ApiResponse<PageResult<Row>> page(@RequestHeader("X-Internal-Service-Token") String token,
@RequestParam(required=false) Long customerId, @RequestParam(required=false) String orderNo,
@RequestParam(required=false) String inboundCode, @RequestParam int page, @RequestParam int size);
record Row(Long orderId, Long customerId, String orderNo, String inboundCode, String mainStatus,
String customerName, String lxCode, String receivingWarehouseName, String destinationWarehouseName,
String destinationCode, Integer packageCount, BigDecimal volumeCbm, BigDecimal grossWeightKg,
BigDecimal netWeightKg, LocalDateTime expectedArrivalAt, String containerNo, String cabinetNo,
LocalDateTime estimatedSailingAt, LocalDateTime actualSailingAt, LocalDateTime createdAt, LocalDateTime updatedAt) {}
}
@@ -19,6 +19,7 @@ import com.baiyue.lastleg.entity.LastlegOrderOperationLog;
import com.baiyue.lastleg.entity.LastlegOrderManualNode;
import com.baiyue.lastleg.entity.ReceivingWarehouseOperation;
import com.baiyue.lastleg.entity.ContainerArrivalTimeOperation;
import com.baiyue.lastleg.client.OrderPreDepartureClient;
import com.baiyue.lastleg.inboundplan.pda.gateway.WarehouseResourceGateway;
import com.baiyue.lastleg.inboundplan.entity.InboundPlanCarton;
import com.baiyue.lastleg.inboundplan.mapper.InboundPlanCartonMapper;
@@ -42,6 +43,7 @@ import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.server.ResponseStatusException;
import java.nio.charset.StandardCharsets;
@@ -88,12 +90,23 @@ public class LastlegOrderService {
@Resource private ContainerShippingGateMapper containerShippingGates;
@Resource private ReturnOrderReferenceResolver returnOrderReferences;
@Resource private com.baiyue.lastleg.transfer.service.TransferQuantityService transferQuantities;
@Resource private OrderPreDepartureClient orderPreDepartureClient;
@Value("${baiyue.security.internal-service-token:}") private String internalServiceToken;
public PageResult<LastlegOrderSummary> page(String customerId, LastlegOrderRequests.Query query) {
return page(customerId, query, null);
}
public PageResult<LastlegOrderSummary> page(String customerId, LastlegOrderRequests.Query query, String relabelNo) {
if (query.sailingStage() == LastlegOrderRequests.SailingStage.BEFORE_DEPARTURE) {
Long customer = parseLong(customerId);
var response = orderPreDepartureClient.page(internalServiceToken, customer, query.orderNo(), query.inboundCode(),
query.page().intValue(), query.size().intValue());
if (response == null || response.data() == null) throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE, "订单服务暂时不可用");
List<LastlegOrderSummary> rows = response.data().records().stream().map(this::preDepartureSummary).toList();
return new PageResult<>(rows, response.data().page(), response.data().size(), response.data().total(), response.data().pages());
}
if (query.sailingStage() == null && relabelNo == null) return aggregateAllPage(customerId, query);
Page<LastlegOrder> page = orderMapper.selectPage(
new Page<>(query.page(), query.size()), filter(customerId, query, relabelNo).orderByDesc(LastlegOrder::getCreatedAt).orderByDesc(LastlegOrder::getId));
Map<Long, List<LastlegOrderMapper.PalletMergeRelationRow>> mergeRelations = palletMergeRelations(page.getRecords());
@@ -113,6 +126,53 @@ public class LastlegOrderService {
page.getCurrent(), page.getSize(), page.getTotal(), page.getPages());
}
/** 全部页签合并订单服务的未开船头程数据与本服务已有尾程单,尾程记录优先覆盖同一来源订单。 */
private PageResult<LastlegOrderSummary> aggregateAllPage(String customerId, LastlegOrderRequests.Query query) {
var source = orderPreDepartureClient.page(internalServiceToken, parseLong(customerId), query.orderNo(), query.inboundCode(), 1, 2000);
if (source == null || source.data() == null) throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE, "订单服务暂时不可用");
List<LastlegOrder> existing = orderMapper.selectList(filter(customerId, query, null)
.orderByDesc(LastlegOrder::getCreatedAt).orderByDesc(LastlegOrder::getId));
Map<String, String> existingNodes = containerNodes(existing);
Map<Long, LastlegOrderMapper.OrderWeightRow> existingWeights = orderWeights(existing);
Map<String, LastlegOrderSummary> merged = new LinkedHashMap<>();
source.data().records().forEach(row -> {
var summary = preDepartureSummary(row);
merged.put(orderKey(summary.customerId(), summary.sourceOrderNo()), summary);
});
for (LastlegOrder order : existing) {
String key = orderKey(order.getCustomerId(), StringUtils.hasText(order.getSourceOrderNo()) ? order.getSourceOrderNo() : order.getOrderNo());
merged.put(key, summary(order, List.of(), StringUtils.hasText(order.getSourceContainerBookingId())
? existingNodes.get(order.getSourceContainerBookingId()) : null, "UNSCHEDULED",
existingWeights.get(order.getId()), List.of(), null, null));
}
List<LastlegOrderSummary> rows = merged.values().stream().sorted(java.util.Comparator.comparing(LastlegOrderSummary::createdAt,
java.util.Comparator.nullsLast(java.util.Comparator.reverseOrder()))).toList();
int from = Math.min((query.page().intValue() - 1) * query.size().intValue(), rows.size());
int to = Math.min(from + query.size().intValue(), rows.size());
long total = rows.size();
return new PageResult<>(rows.subList(from, to), query.page(), query.size(), total,
total == 0 ? 0 : (total + query.size() - 1) / query.size());
}
private static String orderKey(String customerId, String orderNo) {
return String.valueOf(customerId) + ":" + String.valueOf(orderNo);
}
/** 将订单服务权威头程摘要投影为只读尾程列表行;尚未生成尾程单的字段保持为空。 */
private LastlegOrderSummary preDepartureSummary(OrderPreDepartureClient.Row row) {
LastlegOrder order = new LastlegOrder();
// 头程聚合行尚未生成尾程单,尾程订单号必须保持为空;来源头程订单号单独保留。
order.setId(row.orderId()); order.setOrderNo(null); order.setOrderType("FIRST_LEG");
order.setInboundCode(row.inboundCode()); order.setLxCode(row.lxCode()); order.setSourceOrderNo(row.orderNo());
order.setCustomerId(row.customerId() == null ? null : String.valueOf(row.customerId())); order.setCustomerName(row.customerName());
order.setSourceWarehouseName(row.receivingWarehouseName()); order.setOverseasWarehouseName(row.receivingWarehouseName());
order.setFbaWarehouseCode(row.destinationCode());
order.setContainerNo(row.containerNo()); order.setPackageCount(row.packageCount()); order.setVolumeCbm(row.volumeCbm());
order.setEstimatedArrivalAt(row.expectedArrivalAt()); order.setCurrentStatus(row.mainStatus());
order.setCreatedAt(row.createdAt()); order.setUpdatedAt(row.updatedAt()); order.setVersion(0);
return summary(order, List.of(), null, "UNSCHEDULED", null, List.of(), null, null);
}
@Transactional(readOnly = true)
public PageResult<ContainerPlanProgressSummary> containerProgressPage(
LastlegOrderRequests.ContainerProgressQuery query) {