fix: expose completed unified order status
This commit is contained in:
@@ -13,7 +13,7 @@ public record UnifiedOrderQuery(
|
|||||||
@Size(max = 64) String keyword,
|
@Size(max = 64) String keyword,
|
||||||
@Size(max = 64) String orderNo,
|
@Size(max = 64) String orderNo,
|
||||||
@Schema(allowableValues = {"PENDING_REVIEW", "WAIT_MEASURE", "WAIT_PALLETIZE", "INBOUNDED",
|
@Schema(allowableValues = {"PENDING_REVIEW", "WAIT_MEASURE", "WAIT_PALLETIZE", "INBOUNDED",
|
||||||
"WAIT_SPLIT", "LOADING", "LOADED", "DELIVERED"})
|
"WAIT_SPLIT", "LOADING", "LOADED", "DELIVERED", "COMPLETED"})
|
||||||
@Size(max = 32) String mainStatus,
|
@Size(max = 32) String mainStatus,
|
||||||
Long customerId,
|
Long customerId,
|
||||||
Long receivingWarehouseId,
|
Long receivingWarehouseId,
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import java.util.stream.Collectors;
|
|||||||
public class UnifiedOrderQueryService {
|
public class UnifiedOrderQueryService {
|
||||||
private static final Set<String> MAIN_STATUSES = Set.of(
|
private static final Set<String> MAIN_STATUSES = Set.of(
|
||||||
"PENDING_REVIEW", "WAIT_MEASURE", "WAIT_PALLETIZE", "INBOUNDED", "WAIT_SPLIT",
|
"PENDING_REVIEW", "WAIT_MEASURE", "WAIT_PALLETIZE", "INBOUNDED", "WAIT_SPLIT",
|
||||||
"LOADING", "LOADED", "DELIVERED");
|
"LOADING", "LOADED", "DELIVERED", "COMPLETED");
|
||||||
private static final Set<String> REVIEW_STATUSES = Set.of("UNRECORDED", "PENDING", "APPROVED", "REJECTED");
|
private static final Set<String> REVIEW_STATUSES = Set.of("UNRECORDED", "PENDING", "APPROVED", "REJECTED");
|
||||||
private static final List<OrderStatus> ACTIVE_ORDER_STATUSES = List.copyOf(EnumSet.of(
|
private static final List<OrderStatus> ACTIVE_ORDER_STATUSES = List.copyOf(EnumSet.of(
|
||||||
OrderStatus.SUBMITTED, OrderStatus.APPROVED, OrderStatus.ACCEPTED,
|
OrderStatus.SUBMITTED, OrderStatus.APPROVED, OrderStatus.ACCEPTED,
|
||||||
@@ -81,7 +81,8 @@ public class UnifiedOrderQueryService {
|
|||||||
return pageFromFirstleg(tenantId, query, includeCoLoadGroups);
|
return pageFromFirstleg(tenantId, query, includeCoLoadGroups);
|
||||||
}
|
}
|
||||||
List<OrderStatus> statuses = "PENDING_REVIEW".equals(query.mainStatus())
|
List<OrderStatus> statuses = "PENDING_REVIEW".equals(query.mainStatus())
|
||||||
? List.of(OrderStatus.SUBMITTED) : ACTIVE_ORDER_STATUSES;
|
? List.of(OrderStatus.SUBMITTED)
|
||||||
|
: "COMPLETED".equals(query.mainStatus()) ? List.of(OrderStatus.COMPLETED) : ACTIVE_ORDER_STATUSES;
|
||||||
PageResult<OrderEntity> source = orders.unifiedPage(tenantId, query, statuses);
|
PageResult<OrderEntity> source = orders.unifiedPage(tenantId, query, statuses);
|
||||||
List<Long> sourceOrderIds = source.records().stream().map(OrderEntity::getId).toList();
|
List<Long> sourceOrderIds = source.records().stream().map(OrderEntity::getId).toList();
|
||||||
Map<Long, FirstlegUnifiedOrderClient.Summary> inboundByOrder = "PENDING_REVIEW".equals(query.mainStatus())
|
Map<Long, FirstlegUnifiedOrderClient.Summary> inboundByOrder = "PENDING_REVIEW".equals(query.mainStatus())
|
||||||
@@ -335,8 +336,9 @@ public class UnifiedOrderQueryService {
|
|||||||
}
|
}
|
||||||
FirstlegUnifiedOrderClient.Inbound inbound = summary.inbound();
|
FirstlegUnifiedOrderClient.Inbound inbound = summary.inbound();
|
||||||
boolean pendingReview = order.getStatus() == OrderStatus.SUBMITTED;
|
boolean pendingReview = order.getStatus() == OrderStatus.SUBMITTED;
|
||||||
String mainStatus = pendingReview ? "PENDING_REVIEW" : summary.mainStatus();
|
boolean completed = order.getStatus() == OrderStatus.COMPLETED;
|
||||||
String nextAction = pendingReview ? "APPROVE_ORDER" : summary.nextAction();
|
String mainStatus = pendingReview ? "PENDING_REVIEW" : completed ? "COMPLETED" : summary.mainStatus();
|
||||||
|
String nextAction = pendingReview ? "APPROVE_ORDER" : completed ? null : summary.nextAction();
|
||||||
return new UnifiedOrderResponse.Row(order.getId(), order.getVersion(), order.getTenantId(), order.getOrderNo(),
|
return new UnifiedOrderResponse.Row(order.getId(), order.getVersion(), order.getTenantId(), order.getOrderNo(),
|
||||||
mainStatus, nextAction, Boolean.TRUE.equals(summary.customerFeeConfirmationRequired()), relation(order, childCounts), order.getStatus(),
|
mainStatus, nextAction, Boolean.TRUE.equals(summary.customerFeeConfirmationRequired()), relation(order, childCounts), order.getStatus(),
|
||||||
order.getCustomerId(), order.getCustomerName(),
|
order.getCustomerId(), order.getCustomerName(),
|
||||||
@@ -366,8 +368,9 @@ public class UnifiedOrderQueryService {
|
|||||||
CargoSummary cargo,
|
CargoSummary cargo,
|
||||||
UnifiedOrderResponse.CoLoadGroupSummary coLoadGroup) {
|
UnifiedOrderResponse.CoLoadGroupSummary coLoadGroup) {
|
||||||
var inbound = summary.inbound();
|
var inbound = summary.inbound();
|
||||||
|
boolean completed = order != null && order.getStatus() == OrderStatus.COMPLETED;
|
||||||
return new UnifiedOrderResponse.Row(inbound.orderId(), order == null ? null : order.getVersion(), inbound.tenantId(), inbound.orderNo(),
|
return new UnifiedOrderResponse.Row(inbound.orderId(), order == null ? null : order.getVersion(), inbound.tenantId(), inbound.orderNo(),
|
||||||
summary.mainStatus(), summary.nextAction(), Boolean.TRUE.equals(summary.customerFeeConfirmationRequired()), relation(order, childCounts),
|
completed ? "COMPLETED" : summary.mainStatus(), completed ? null : summary.nextAction(), Boolean.TRUE.equals(summary.customerFeeConfirmationRequired()), relation(order, childCounts),
|
||||||
parseOrderStatus(inbound.orderStatusSnapshot()),
|
parseOrderStatus(inbound.orderStatusSnapshot()),
|
||||||
inbound.customerId(), inbound.customerName(), inbound.channelCode(), inbound.channelName(),
|
inbound.customerId(), inbound.customerName(), inbound.channelCode(), inbound.channelName(),
|
||||||
order != null && Boolean.TRUE.equals(order.getChannelChanged()), inbound.warehouseId(),
|
order != null && Boolean.TRUE.equals(order.getChannelChanged()), inbound.warehouseId(),
|
||||||
@@ -424,6 +427,7 @@ public class UnifiedOrderQueryService {
|
|||||||
private String orderMainStatus(OrderStatus status) {
|
private String orderMainStatus(OrderStatus status) {
|
||||||
if (status == null) return null;
|
if (status == null) return null;
|
||||||
return status == OrderStatus.SUBMITTED ? "PENDING_REVIEW"
|
return status == OrderStatus.SUBMITTED ? "PENDING_REVIEW"
|
||||||
|
: status == OrderStatus.COMPLETED ? "COMPLETED"
|
||||||
: ACTIVE_ORDER_STATUSES.contains(status) ? "WAIT_MEASURE" : null;
|
: ACTIVE_ORDER_STATUSES.contains(status) ? "WAIT_MEASURE" : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -559,7 +563,8 @@ public class UnifiedOrderQueryService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean requiresFirstlegQuery(UnifiedOrderQuery query) {
|
private boolean requiresFirstlegQuery(UnifiedOrderQuery query) {
|
||||||
return (StringUtils.hasText(query.mainStatus()) && !"PENDING_REVIEW".equals(query.mainStatus()))
|
return (StringUtils.hasText(query.mainStatus())
|
||||||
|
&& !Set.of("PENDING_REVIEW", "COMPLETED").contains(query.mainStatus()))
|
||||||
|| query.expectedArrivalDate() != null
|
|| query.expectedArrivalDate() != null
|
||||||
|| StringUtils.hasText(query.feeReviewStatus()) || StringUtils.hasText(query.containerNo())
|
|| StringUtils.hasText(query.feeReviewStatus()) || StringUtils.hasText(query.containerNo())
|
||||||
|| StringUtils.hasText(query.cabinetNo()) || query.sailingDate() != null || query.loaded() != null
|
|| StringUtils.hasText(query.cabinetNo()) || query.sailingDate() != null || query.loaded() != null
|
||||||
|
|||||||
@@ -802,7 +802,7 @@ components:
|
|||||||
tenantId: {type: string, pattern: '^[1-9][0-9]*$'}
|
tenantId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||||
keyword: {type: string, maxLength: 64}
|
keyword: {type: string, maxLength: 64}
|
||||||
orderNo: {type: string, maxLength: 64}
|
orderNo: {type: string, maxLength: 64}
|
||||||
mainStatus: {type: string, enum: [PENDING_REVIEW, WAIT_MEASURE, WAIT_PALLETIZE, INBOUNDED, WAIT_SPLIT, LOADING, LOADED, DELIVERED]}
|
mainStatus: {type: string, enum: [PENDING_REVIEW, WAIT_MEASURE, WAIT_PALLETIZE, INBOUNDED, WAIT_SPLIT, LOADING, LOADED, DELIVERED, COMPLETED]}
|
||||||
customerId: {type: string, pattern: '^[1-9][0-9]*$'}
|
customerId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||||
receivingWarehouseId: {type: string, pattern: '^[1-9][0-9]*$'}
|
receivingWarehouseId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||||
destinationWarehouseId: {type: string, pattern: '^[1-9][0-9]*$'}
|
destinationWarehouseId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||||
@@ -878,7 +878,7 @@ components:
|
|||||||
asOf: {type: string, format: date-time}
|
asOf: {type: string, format: date-time}
|
||||||
UnifiedMainStatus:
|
UnifiedMainStatus:
|
||||||
type: string
|
type: string
|
||||||
enum: [PENDING_REVIEW, WAIT_MEASURE, WAIT_PALLETIZE, INBOUNDED, WAIT_SPLIT, LOADING, LOADED, DELIVERED]
|
enum: [PENDING_REVIEW, WAIT_MEASURE, WAIT_PALLETIZE, INBOUNDED, WAIT_SPLIT, LOADING, LOADED, DELIVERED, COMPLETED]
|
||||||
description: >-
|
description: >-
|
||||||
统一订单八态产品主状态。ONE_CLICK_DROPSHIP 测量计费完成后进入 WAIT_PALLETIZE,封托完成后进入 WAIT_SPLIT;
|
统一订单八态产品主状态。ONE_CLICK_DROPSHIP 测量计费完成后进入 WAIT_PALLETIZE,封托完成后进入 WAIT_SPLIT;
|
||||||
STANDARD 保持既有流程,INBOUNDED 仅兼容存量已入库记录。
|
STANDARD 保持既有流程,INBOUNDED 仅兼容存量已入库记录。
|
||||||
@@ -1389,7 +1389,7 @@ components:
|
|||||||
description: 统一订单八态主状态筛选;WAIT_PALLETIZE、WAIT_SPLIT 与存量兼容状态 INBOUNDED 独立查询
|
description: 统一订单八态主状态筛选;WAIT_PALLETIZE、WAIT_SPLIT 与存量兼容状态 INBOUNDED 独立查询
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
enum: [PENDING_REVIEW, WAIT_MEASURE, WAIT_PALLETIZE, INBOUNDED, WAIT_SPLIT, LOADING, LOADED, DELIVERED]
|
enum: [PENDING_REVIEW, WAIT_MEASURE, WAIT_PALLETIZE, INBOUNDED, WAIT_SPLIT, LOADING, LOADED, DELIVERED, COMPLETED]
|
||||||
UnifiedInboundCode:
|
UnifiedInboundCode:
|
||||||
{name: inboundCode, in: query, required: false, description: 订单创建时生成的入仓码,所有订单状态均可查询, schema: {type: string, maxLength: 40}}
|
{name: inboundCode, in: query, required: false, description: 订单创建时生成的入仓码,所有订单状态均可查询, schema: {type: string, maxLength: 40}}
|
||||||
UnifiedInternalOrderStatus:
|
UnifiedInternalOrderStatus:
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class UnifiedOrderApiContractTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void documentsEightProductMainStatuses() throws Exception {
|
void documentsProductMainStatusesThroughCompletion() throws Exception {
|
||||||
String yaml = new ClassPathResource("openapi/order-v1.yaml")
|
String yaml = new ClassPathResource("openapi/order-v1.yaml")
|
||||||
.getContentAsString(StandardCharsets.UTF_8);
|
.getContentAsString(StandardCharsets.UTF_8);
|
||||||
Map<String, Object> document = stringMap(new Yaml().load(yaml));
|
Map<String, Object> document = stringMap(new Yaml().load(yaml));
|
||||||
@@ -43,7 +43,7 @@ class UnifiedOrderApiContractTest {
|
|||||||
Map<String, Object> schema = stringMap(mainStatus.get("schema"));
|
Map<String, Object> schema = stringMap(mainStatus.get("schema"));
|
||||||
assertThat(stringList(schema.get("enum"))).containsExactly(
|
assertThat(stringList(schema.get("enum"))).containsExactly(
|
||||||
"PENDING_REVIEW", "WAIT_MEASURE", "WAIT_PALLETIZE", "INBOUNDED", "WAIT_SPLIT",
|
"PENDING_REVIEW", "WAIT_MEASURE", "WAIT_PALLETIZE", "INBOUNDED", "WAIT_SPLIT",
|
||||||
"LOADING", "LOADED", "DELIVERED");
|
"LOADING", "LOADED", "DELIVERED", "COMPLETED");
|
||||||
assertThat(mainStatus.get("description").toString())
|
assertThat(mainStatus.get("description").toString())
|
||||||
.contains("WAIT_PALLETIZE", "WAIT_SPLIT", "INBOUNDED");
|
.contains("WAIT_PALLETIZE", "WAIT_SPLIT", "INBOUNDED");
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ class UnifiedOrderApiContractTest {
|
|||||||
Map<String, Object> responseStatus = stringMap(schemas.get("UnifiedMainStatus"));
|
Map<String, Object> responseStatus = stringMap(schemas.get("UnifiedMainStatus"));
|
||||||
assertThat(stringList(responseStatus.get("enum"))).containsExactly(
|
assertThat(stringList(responseStatus.get("enum"))).containsExactly(
|
||||||
"PENDING_REVIEW", "WAIT_MEASURE", "WAIT_PALLETIZE", "INBOUNDED", "WAIT_SPLIT",
|
"PENDING_REVIEW", "WAIT_MEASURE", "WAIT_PALLETIZE", "INBOUNDED", "WAIT_SPLIT",
|
||||||
"LOADING", "LOADED", "DELIVERED");
|
"LOADING", "LOADED", "DELIVERED", "COMPLETED");
|
||||||
assertThat(responseStatus.get("description").toString())
|
assertThat(responseStatus.get("description").toString())
|
||||||
.contains("WAIT_PALLETIZE", "WAIT_SPLIT", "INBOUNDED");
|
.contains("WAIT_PALLETIZE", "WAIT_SPLIT", "INBOUNDED");
|
||||||
Schema queryAnnotation = UnifiedOrderQuery.class.getDeclaredField("mainStatus")
|
Schema queryAnnotation = UnifiedOrderQuery.class.getDeclaredField("mainStatus")
|
||||||
@@ -59,7 +59,7 @@ class UnifiedOrderApiContractTest {
|
|||||||
assertThat(queryAnnotation).isNotNull();
|
assertThat(queryAnnotation).isNotNull();
|
||||||
assertThat(queryAnnotation.allowableValues()).containsExactly(
|
assertThat(queryAnnotation.allowableValues()).containsExactly(
|
||||||
"PENDING_REVIEW", "WAIT_MEASURE", "WAIT_PALLETIZE", "INBOUNDED", "WAIT_SPLIT",
|
"PENDING_REVIEW", "WAIT_MEASURE", "WAIT_PALLETIZE", "INBOUNDED", "WAIT_SPLIT",
|
||||||
"LOADING", "LOADED", "DELIVERED");
|
"LOADING", "LOADED", "DELIVERED", "COMPLETED");
|
||||||
|
|
||||||
Map<String, Object> row = stringMap(schemas.get("UnifiedOrderRow"));
|
Map<String, Object> row = stringMap(schemas.get("UnifiedOrderRow"));
|
||||||
assertThat(stringMap(row.get("properties"))).containsKeys(
|
assertThat(stringMap(row.get("properties"))).containsKeys(
|
||||||
|
|||||||
@@ -106,6 +106,26 @@ class UnifiedOrderQueryServiceTest {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void completedOrderOverridesDeliveredInboundProjectionAndSupportsMainStatusFilter() {
|
||||||
|
UnifiedOrderQuery query = query("COMPLETED");
|
||||||
|
OrderEntity order = order(OrderStatus.COMPLETED);
|
||||||
|
var summary = summary("DELIVERED", null);
|
||||||
|
when(orders.unifiedPage(eq(10001L), eq(query), eq(List.of(OrderStatus.COMPLETED))))
|
||||||
|
.thenReturn(new PageResult<>(List.of(order), 1, 20, 1, 1));
|
||||||
|
when(firstleg.summaries(eq("internal-token"), any()))
|
||||||
|
.thenReturn(ApiResponse.success(List.of(summary)));
|
||||||
|
|
||||||
|
var result = service.page(10001L, query);
|
||||||
|
|
||||||
|
assertThat(result.records()).singleElement().satisfies(row -> {
|
||||||
|
assertThat(row.mainStatus()).isEqualTo("COMPLETED");
|
||||||
|
assertThat(row.internalOrderStatus()).isEqualTo(OrderStatus.COMPLETED);
|
||||||
|
assertThat(row.nextAction()).isNull();
|
||||||
|
});
|
||||||
|
verify(firstleg, never()).page(any(), any());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void newlyCreatedOrderUsesItsOwnCargoPackageCountBeforeInboundExists() {
|
void newlyCreatedOrderUsesItsOwnCargoPackageCountBeforeInboundExists() {
|
||||||
UnifiedOrderQuery query = query(null);
|
UnifiedOrderQuery query = query(null);
|
||||||
|
|||||||
Reference in New Issue
Block a user