diff --git a/order/src/main/java/com/baiyue/order/dto/UnifiedOrderQuery.java b/order/src/main/java/com/baiyue/order/dto/UnifiedOrderQuery.java index 27b61e6ee..c052e646d 100644 --- a/order/src/main/java/com/baiyue/order/dto/UnifiedOrderQuery.java +++ b/order/src/main/java/com/baiyue/order/dto/UnifiedOrderQuery.java @@ -13,7 +13,7 @@ public record UnifiedOrderQuery( @Size(max = 64) String keyword, @Size(max = 64) String orderNo, @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, Long customerId, Long receivingWarehouseId, diff --git a/order/src/main/java/com/baiyue/order/service/UnifiedOrderQueryService.java b/order/src/main/java/com/baiyue/order/service/UnifiedOrderQueryService.java index fd7d4a5ff..d62472c54 100644 --- a/order/src/main/java/com/baiyue/order/service/UnifiedOrderQueryService.java +++ b/order/src/main/java/com/baiyue/order/service/UnifiedOrderQueryService.java @@ -38,7 +38,7 @@ import java.util.stream.Collectors; public class UnifiedOrderQueryService { private static final Set MAIN_STATUSES = Set.of( "PENDING_REVIEW", "WAIT_MEASURE", "WAIT_PALLETIZE", "INBOUNDED", "WAIT_SPLIT", - "LOADING", "LOADED", "DELIVERED"); + "LOADING", "LOADED", "DELIVERED", "COMPLETED"); private static final Set REVIEW_STATUSES = Set.of("UNRECORDED", "PENDING", "APPROVED", "REJECTED"); private static final List ACTIVE_ORDER_STATUSES = List.copyOf(EnumSet.of( OrderStatus.SUBMITTED, OrderStatus.APPROVED, OrderStatus.ACCEPTED, @@ -81,7 +81,8 @@ public class UnifiedOrderQueryService { return pageFromFirstleg(tenantId, query, includeCoLoadGroups); } List 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 source = orders.unifiedPage(tenantId, query, statuses); List sourceOrderIds = source.records().stream().map(OrderEntity::getId).toList(); Map inboundByOrder = "PENDING_REVIEW".equals(query.mainStatus()) @@ -335,8 +336,9 @@ public class UnifiedOrderQueryService { } FirstlegUnifiedOrderClient.Inbound inbound = summary.inbound(); boolean pendingReview = order.getStatus() == OrderStatus.SUBMITTED; - String mainStatus = pendingReview ? "PENDING_REVIEW" : summary.mainStatus(); - String nextAction = pendingReview ? "APPROVE_ORDER" : summary.nextAction(); + boolean completed = order.getStatus() == OrderStatus.COMPLETED; + 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(), mainStatus, nextAction, Boolean.TRUE.equals(summary.customerFeeConfirmationRequired()), relation(order, childCounts), order.getStatus(), order.getCustomerId(), order.getCustomerName(), @@ -366,8 +368,9 @@ public class UnifiedOrderQueryService { CargoSummary cargo, UnifiedOrderResponse.CoLoadGroupSummary coLoadGroup) { 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(), - 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()), inbound.customerId(), inbound.customerName(), inbound.channelCode(), inbound.channelName(), order != null && Boolean.TRUE.equals(order.getChannelChanged()), inbound.warehouseId(), @@ -424,6 +427,7 @@ public class UnifiedOrderQueryService { private String orderMainStatus(OrderStatus status) { if (status == null) return null; return status == OrderStatus.SUBMITTED ? "PENDING_REVIEW" + : status == OrderStatus.COMPLETED ? "COMPLETED" : ACTIVE_ORDER_STATUSES.contains(status) ? "WAIT_MEASURE" : null; } @@ -559,7 +563,8 @@ public class UnifiedOrderQueryService { } 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 || StringUtils.hasText(query.feeReviewStatus()) || StringUtils.hasText(query.containerNo()) || StringUtils.hasText(query.cabinetNo()) || query.sailingDate() != null || query.loaded() != null diff --git a/order/src/main/resources/openapi/order-v1.yaml b/order/src/main/resources/openapi/order-v1.yaml index 22662a888..eb5873cb7 100644 --- a/order/src/main/resources/openapi/order-v1.yaml +++ b/order/src/main/resources/openapi/order-v1.yaml @@ -802,7 +802,7 @@ components: tenantId: {type: string, pattern: '^[1-9][0-9]*$'} keyword: {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]*$'} receivingWarehouseId: {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} UnifiedMainStatus: 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: >- 统一订单八态产品主状态。ONE_CLICK_DROPSHIP 测量计费完成后进入 WAIT_PALLETIZE,封托完成后进入 WAIT_SPLIT; STANDARD 保持既有流程,INBOUNDED 仅兼容存量已入库记录。 @@ -1389,7 +1389,7 @@ components: description: 统一订单八态主状态筛选;WAIT_PALLETIZE、WAIT_SPLIT 与存量兼容状态 INBOUNDED 独立查询 schema: 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: {name: inboundCode, in: query, required: false, description: 订单创建时生成的入仓码,所有订单状态均可查询, schema: {type: string, maxLength: 40}} UnifiedInternalOrderStatus: diff --git a/order/src/test/java/com/baiyue/order/controller/UnifiedOrderApiContractTest.java b/order/src/test/java/com/baiyue/order/controller/UnifiedOrderApiContractTest.java index 90086d33e..07a5ecf2d 100644 --- a/order/src/test/java/com/baiyue/order/controller/UnifiedOrderApiContractTest.java +++ b/order/src/test/java/com/baiyue/order/controller/UnifiedOrderApiContractTest.java @@ -28,7 +28,7 @@ class UnifiedOrderApiContractTest { } @Test - void documentsEightProductMainStatuses() throws Exception { + void documentsProductMainStatusesThroughCompletion() throws Exception { String yaml = new ClassPathResource("openapi/order-v1.yaml") .getContentAsString(StandardCharsets.UTF_8); Map document = stringMap(new Yaml().load(yaml)); @@ -43,7 +43,7 @@ class UnifiedOrderApiContractTest { Map schema = stringMap(mainStatus.get("schema")); assertThat(stringList(schema.get("enum"))).containsExactly( "PENDING_REVIEW", "WAIT_MEASURE", "WAIT_PALLETIZE", "INBOUNDED", "WAIT_SPLIT", - "LOADING", "LOADED", "DELIVERED"); + "LOADING", "LOADED", "DELIVERED", "COMPLETED"); assertThat(mainStatus.get("description").toString()) .contains("WAIT_PALLETIZE", "WAIT_SPLIT", "INBOUNDED"); @@ -51,7 +51,7 @@ class UnifiedOrderApiContractTest { Map responseStatus = stringMap(schemas.get("UnifiedMainStatus")); assertThat(stringList(responseStatus.get("enum"))).containsExactly( "PENDING_REVIEW", "WAIT_MEASURE", "WAIT_PALLETIZE", "INBOUNDED", "WAIT_SPLIT", - "LOADING", "LOADED", "DELIVERED"); + "LOADING", "LOADED", "DELIVERED", "COMPLETED"); assertThat(responseStatus.get("description").toString()) .contains("WAIT_PALLETIZE", "WAIT_SPLIT", "INBOUNDED"); Schema queryAnnotation = UnifiedOrderQuery.class.getDeclaredField("mainStatus") @@ -59,7 +59,7 @@ class UnifiedOrderApiContractTest { assertThat(queryAnnotation).isNotNull(); assertThat(queryAnnotation.allowableValues()).containsExactly( "PENDING_REVIEW", "WAIT_MEASURE", "WAIT_PALLETIZE", "INBOUNDED", "WAIT_SPLIT", - "LOADING", "LOADED", "DELIVERED"); + "LOADING", "LOADED", "DELIVERED", "COMPLETED"); Map row = stringMap(schemas.get("UnifiedOrderRow")); assertThat(stringMap(row.get("properties"))).containsKeys( diff --git a/order/src/test/java/com/baiyue/order/service/UnifiedOrderQueryServiceTest.java b/order/src/test/java/com/baiyue/order/service/UnifiedOrderQueryServiceTest.java index a3c60af43..685449005 100644 --- a/order/src/test/java/com/baiyue/order/service/UnifiedOrderQueryServiceTest.java +++ b/order/src/test/java/com/baiyue/order/service/UnifiedOrderQueryServiceTest.java @@ -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 void newlyCreatedOrderUsesItsOwnCargoPackageCountBeforeInboundExists() { UnifiedOrderQuery query = query(null);