feat(order): expose unified order channel code

This commit is contained in:
2026-08-31 15:38:18 +08:00
parent c9792b1f63
commit 17d81b0b94
6 changed files with 34 additions and 6 deletions
@@ -45,7 +45,7 @@ public interface FirstlegUnifiedOrderClient {
String processStatus, String orderStatusSnapshot, String measureReviewStatus,
Integer version,
Long customerId, String customerName, Long warehouseId, String warehouseName,
Long deliveryWarehouseId, String deliveryWarehouseName, String channelName,
Long deliveryWarehouseId, String deliveryWarehouseName, String channelCode, String channelName,
Integer totalPackageCount, String locationCodes,
LocalDateTime expectedArrivalAt, LocalDateTime requestedPickupAt, String feeReviewStatus,
String companyName, String businessType, String taxMode, String containerMode,
@@ -15,7 +15,7 @@ public final class UnifiedOrderResponse {
Long orderId, Long tenantId, String orderNo, String mainStatus, String nextAction,
OrderRelationSummary relation,
OrderStatus internalOrderStatus,
Long customerId, String customerName, String channelName,
Long customerId, String customerName, String channelCode, String channelName,
Long receivingWarehouseId, String receivingWarehouseName,
Long destinationWarehouseId, String destinationWarehouseName,
Long inboundId, Integer inboundVersion, String inboundCode, LocalDate expectedShipDate,
@@ -267,7 +267,7 @@ public class UnifiedOrderQueryService {
order.getStatus() == OrderStatus.SUBMITTED ? "APPROVE_ORDER" : null,
relation(order, childCounts),
order.getStatus(), order.getCustomerId(), order.getCustomerName(),
order.getChannelName(), order.getReceivingWarehouseId(), order.getReceivingWarehouseName(),
order.getChannelCode(), order.getChannelName(), order.getReceivingWarehouseId(), order.getReceivingWarehouseName(),
order.getDestinationWarehouseId(), order.getDestinationWarehouseName(), null, null,
order.getInboundCode(),
order.getExpectedShipDate(), totalPackageCount(cargo), null, null, grossWeightKg(cargo), volumeCbm(cargo),
@@ -283,7 +283,7 @@ public class UnifiedOrderQueryService {
return new UnifiedOrderResponse.Row(order.getId(), order.getTenantId(), order.getOrderNo(),
summary.mainStatus(), summary.nextAction(), relation(order, childCounts), order.getStatus(),
order.getCustomerId(), order.getCustomerName(),
order.getChannelName(), order.getReceivingWarehouseId(), order.getReceivingWarehouseName(),
order.getChannelCode(), order.getChannelName(), order.getReceivingWarehouseId(), order.getReceivingWarehouseName(),
order.getDestinationWarehouseId(), order.getDestinationWarehouseName(), inbound.id(), inbound.version(), inbound.inboundCode(),
order.getExpectedShipDate(), inbound.totalPackageCount() != null ? inbound.totalPackageCount() : totalPackageCount(cargo), null, inbound.locationCodes(),
inbound.actualGrossWeightKg() != null ? inbound.actualGrossWeightKg() : grossWeightKg(cargo),
@@ -307,7 +307,7 @@ public class UnifiedOrderQueryService {
return new UnifiedOrderResponse.Row(inbound.orderId(), inbound.tenantId(), inbound.orderNo(),
summary.mainStatus(), summary.nextAction(), relation(order, childCounts),
parseOrderStatus(inbound.orderStatusSnapshot()),
inbound.customerId(), inbound.customerName(), inbound.channelName(), inbound.warehouseId(),
inbound.customerId(), inbound.customerName(), inbound.channelCode(), inbound.channelName(), inbound.warehouseId(),
inbound.warehouseName(), inbound.deliveryWarehouseId(), inbound.deliveryWarehouseName(),
inbound.id(), inbound.version(), inbound.inboundCode(), null,
inbound.totalPackageCount() != null ? inbound.totalPackageCount() : totalPackageCount(cargo),
@@ -477,6 +477,7 @@ components:
internalOrderStatus: {type: string, enum: [DRAFT, SUBMITTED, APPROVED, ACCEPTED, REJECTED, CANCELLED, PROCESSING, COMPLETED], nullable: true}
customerId: {type: integer, format: int64, nullable: true}
customerName: {type: string, nullable: true}
channelCode: {type: string, nullable: true, description: 稳定物流渠道编码,仅供业务校验;直接来自当前 Order 或 Firstleg 权威快照,不由 channelName 推导}
channelName: {type: string, nullable: true}
receivingWarehouseId: {type: integer, format: int64, nullable: true}
receivingWarehouseName: {type: string, nullable: true}
@@ -52,7 +52,7 @@ class UnifiedOrderApiContractTest {
Map<String, Object> row = stringMap(schemas.get("UnifiedOrderRow"));
assertThat(stringMap(row.get("properties"))).containsKeys(
"orderId", "mainStatus", "inboundId", "inboundVersion", "measurement", "preload",
"orderId", "mainStatus", "channelCode", "inboundId", "inboundVersion", "measurement", "preload",
"loading", "delivery", "transport", "customerRemark", "latestInternalNote",
"expectedArrivalAt", "requestedPickupAt", "feeReviewStatus", "companyName", "businessType", "pickupMethod",
"taxMode", "containerMode", "customsInspection", "destinationType", "destinationCode",
@@ -62,6 +62,8 @@ class UnifiedOrderApiContractTest {
Map<String, Object> inboundCode = stringMap(stringMap(row.get("properties")).get("inboundCode"));
assertThat(inboundCode).containsEntry("nullable", true);
assertThat(inboundCode.get("description").toString()).contains("不得回退");
Map<String, Object> channelCode = stringMap(stringMap(row.get("properties")).get("channelCode"));
assertThat(channelCode.get("description").toString()).contains("不由 channelName 推导");
Map<String, Object> coLoadGroup = stringMap(schemas.get("UnifiedCoLoadGroupSummary"));
assertThat(stringMap(coLoadGroup.get("properties")))
.containsOnlyKeys("status", "memberCount", "memberInboundCodes");
@@ -79,6 +81,8 @@ class UnifiedOrderApiContractTest {
Method page = FirstlegUnifiedOrderClient.class.getMethod(
"page", String.class, FirstlegUnifiedOrderClient.Query.class);
assertThat(page.getAnnotation(PostMapping.class).value()).containsExactly("/query");
assertThat(List.of(FirstlegUnifiedOrderClient.Inbound.class.getRecordComponents()).stream()
.map(component -> component.getName())).contains("channelCode", "channelName");
}
@Test
@@ -72,6 +72,7 @@ class UnifiedOrderQueryServiceTest {
assertThat(row.mainStatus()).isEqualTo("PENDING_REVIEW");
assertThat(row.nextAction()).isEqualTo("APPROVE_ORDER");
assertThat(row.inboundCode()).isEqualTo("RK-77");
assertThat(row.channelCode()).isEqualTo("MATSON");
assertThat(row.inboundId()).isNull();
assertThat(row.customerRemark()).isEqualTo("客户要求提货前联系");
assertThat(row.latestInternalNote()).isEqualTo("客服已确认提货时间");
@@ -243,6 +244,7 @@ class UnifiedOrderQueryServiceTest {
UnifiedOrderQuery query = query("PENDING_REVIEW");
OrderEntity order = order(OrderStatus.SUBMITTED);
order.setInboundCode(null);
order.setChannelCode(null);
when(orders.unifiedPage(eq(10001L), eq(query), eq(List.of(OrderStatus.SUBMITTED))))
.thenReturn(new PageResult<>(List.of(order), 1, 20, 1, 1));
@@ -250,9 +252,27 @@ class UnifiedOrderQueryServiceTest {
assertThat(row.orderId()).isEqualTo(77L);
assertThat(row.orderNo()).isEqualTo("FL-77");
assertThat(row.inboundCode()).isNull();
assertThat(row.channelName()).isEqualTo("美森");
assertThat(row.channelCode()).isNull();
});
}
@Test
void orderDrivenPageUsesOrderChannelCodeWithoutFirstlegOrNameFallback() {
UnifiedOrderQuery query = query(null);
OrderEntity order = order(OrderStatus.APPROVED);
order.setChannelCode("ORDER-SNAPSHOT");
var summary = summary("LOADING", null);
when(summary.inbound().channelCode()).thenReturn("FIRSTLEG-SNAPSHOT");
when(orders.unifiedPage(eq(10001L), eq(query), any()))
.thenReturn(new PageResult<>(List.of(order), 1, 20, 1, 1));
when(firstleg.summaries(eq("internal-token"), any()))
.thenReturn(ApiResponse.success(List.of(summary)));
assertThat(service.page(10001L, query).records()).singleElement()
.extracting(UnifiedOrderResponse.Row::channelCode).isEqualTo("ORDER-SNAPSHOT");
}
@Test
void platformPageAggregatesColoadStatusAndMemberInboundCodes() {
UnifiedOrderQuery query = query("PENDING_REVIEW");
@@ -425,6 +445,7 @@ class UnifiedOrderQueryServiceTest {
assertThat(row.loading().loadingVersion()).isEqualTo(3);
assertThat(row.loading().pickingVersion()).isEqualTo(3);
assertThat(row.inboundCode()).isEqualTo("RK-77");
assertThat(row.channelCode()).isEqualTo("MATSON");
assertThat(row.recommendedPalletType()).isNull();
assertThat(row.locationCodes()).isEqualTo("A0-01, B2-03");
assertThat(row.companyName()).isEqualTo("测试客户有限公司");
@@ -603,6 +624,7 @@ class UnifiedOrderQueryServiceTest {
OrderEntity order = new OrderEntity();
order.setId(77L); order.setTenantId(10001L); order.setOrderNo("FL-77");
order.setStatus(status); order.setCustomerId(30001L); order.setCustomerName("测试客户");
order.setChannelCode("MATSON"); order.setChannelName("美森");
order.setCreatedAt(LocalDateTime.of(2026, 8, 6, 10, 0));
return order;
}
@@ -625,6 +647,7 @@ class UnifiedOrderQueryServiceTest {
when(inbound.deliveryWarehouseId()).thenReturn(22L);
when(inbound.deliveryWarehouseName()).thenReturn("ONT8");
when(inbound.channelName()).thenReturn("美森");
when(inbound.channelCode()).thenReturn("MATSON");
when(inbound.totalPackageCount()).thenReturn(10);
when(inbound.locationCodes()).thenReturn("A0-01, B2-03");
when(inbound.companyName()).thenReturn("测试客户有限公司");