This commit is contained in:
2026-09-04 18:47:57 +08:00
parent 7c5ed85a36
commit 77817b4c94
20 changed files with 240 additions and 92 deletions
@@ -23,6 +23,8 @@ public final class PendingReviewOrderDtos {
@Size(max = 40) String inboundCode,
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate createdStart,
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate createdEnd,
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate expectedArrivalStart,
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate expectedArrivalEnd,
List<@Min(1) Long> excludedOrderIds,
@Min(1) long page,
@Min(1) @Max(200) long size
@@ -31,6 +33,12 @@ public final class PendingReviewOrderDtos {
public boolean isCreatedRangeValid() {
return createdStart == null || createdEnd == null || !createdStart.isAfter(createdEnd);
}
@AssertTrue(message = "预计到货日期起始日不能晚于结束日")
public boolean isExpectedArrivalRangeValid() {
return expectedArrivalStart == null || expectedArrivalEnd == null
|| !expectedArrivalStart.isAfter(expectedArrivalEnd);
}
}
public record Row(
@@ -44,6 +52,7 @@ public final class PendingReviewOrderDtos {
String channelName,
int totalPackageCount,
LocalDateTime createdAt,
LocalDateTime expectedArrivalAt,
String mainStatus
) {
}
@@ -217,6 +217,8 @@ public class OrderRepository {
Long customerId, String inboundCode,
LocalDateTime createdFrom,
LocalDateTime createdBefore,
LocalDateTime expectedArrivalFrom,
LocalDateTime expectedArrivalBefore,
List<Long> excludedOrderIds,
long page, long size) {
LambdaQueryWrapper<OrderEntity> wrapper = new LambdaQueryWrapper<OrderEntity>()
@@ -228,6 +230,8 @@ public class OrderRepository {
.eq(StringUtils.hasText(inboundCode), OrderEntity::getInboundCode, inboundCode)
.ge(createdFrom != null, OrderEntity::getCreatedAt, createdFrom)
.lt(createdBefore != null, OrderEntity::getCreatedAt, createdBefore)
.ge(expectedArrivalFrom != null, OrderEntity::getExpectedArrivalAt, expectedArrivalFrom)
.lt(expectedArrivalBefore != null, OrderEntity::getExpectedArrivalAt, expectedArrivalBefore)
.notIn(excludedOrderIds != null && !excludedOrderIds.isEmpty(), OrderEntity::getId,
excludedOrderIds)
.orderByDesc(OrderEntity::getCreatedAt)
@@ -25,7 +25,7 @@ public class PendingReviewOrderQueryService {
public PageResult<PendingReviewOrderDtos.Row> page(PendingReviewOrderDtos.Query query) {
if (query == null || query.page() < 1 || query.size() < 1 || query.size() > 200
|| !query.isCreatedRangeValid()) {
|| !query.isCreatedRangeValid() || !query.isExpectedArrivalRangeValid()) {
throw new BizException(ResultCode.VALIDATION_FAILED, "待审核订单查询参数不正确");
}
List<String> channelCodes = normalizeChannelCodes(query.channelCodes());
@@ -33,9 +33,13 @@ public class PendingReviewOrderQueryService {
: query.createdStart().atStartOfDay(BUSINESS_ZONE).toLocalDateTime();
LocalDateTime createdBefore = query.createdEnd() == null ? null
: query.createdEnd().plusDays(1).atStartOfDay(BUSINESS_ZONE).toLocalDateTime();
LocalDateTime expectedArrivalFrom = query.expectedArrivalStart() == null ? null
: query.expectedArrivalStart().atStartOfDay(BUSINESS_ZONE).toLocalDateTime();
LocalDateTime expectedArrivalBefore = query.expectedArrivalEnd() == null ? null
: query.expectedArrivalEnd().plusDays(1).atStartOfDay(BUSINESS_ZONE).toLocalDateTime();
var source = orders.pendingReviewPage(channelCodes, query.warehouseId(), query.customerId(),
normalize(query.inboundCode()), createdFrom, createdBefore, query.excludedOrderIds(),
query.page(), query.size());
normalize(query.inboundCode()), createdFrom, createdBefore, expectedArrivalFrom,
expectedArrivalBefore, query.excludedOrderIds(), query.page(), query.size());
List<Long> orderIds = source.records().stream().map(order -> order.getId()).toList();
Map<Long, Integer> packageCounts = orders.findCargoByOrderIds(null, orderIds).stream()
.collect(Collectors.groupingBy(OrderCargoEntity::getOrderId,
@@ -44,7 +48,7 @@ public class PendingReviewOrderQueryService {
order.getId(), order.getOrderNo(), order.getInboundCode(), order.getCustomerId(),
order.getCustomerName(), order.getReceivingWarehouseId(), order.getChannelCode(),
order.getChannelName(), packageCounts.getOrDefault(order.getId(), 0), order.getCreatedAt(),
"PENDING_REVIEW")).toList();
order.getExpectedArrivalAt(), "PENDING_REVIEW")).toList();
return new PageResult<>(rows, source.page(), source.size(), source.total(), source.pages());
}
@@ -12,8 +12,9 @@ paths:
summary: Firstleg 分页读取 Order 权威待审核订单
description: >-
仅接受内部服务令牌。只返回 ord_order 中未删除且 status=SUBMITTED 的头程订单,
mainStatus 固定为 PENDING_REVIEW。createdStart/createdEnd 按 Asia/Shanghai 自然日闭区间过滤
ord_order.created_at,稳定按 created_at DESC、id DESC 分页;不读取或修复 Firstleg 投影。
mainStatus 固定为 PENDING_REVIEW。createdStart/createdEnd 和 expectedArrivalStart/expectedArrivalEnd
均按 Asia/Shanghai 自然日闭区间分别过滤 ord_order.created_at 与 expected_arrival_at;
稳定按 created_at DESC、id DESC 分页;不读取或修复 Firstleg 投影。
excludedOrderIds 由 Firstleg 根据当前有效装柜计划提供,用于在数据库分页前排除已经占柜的订单。
parameters:
- name: X-Internal-Service-Token
@@ -26,6 +27,8 @@ paths:
- {name: inboundCode, in: query, required: false, schema: {type: string, maxLength: 40}}
- {name: createdStart, in: query, required: false, schema: {type: string, format: date}}
- {name: createdEnd, in: query, required: false, schema: {type: string, format: date}}
- {name: expectedArrivalStart, in: query, required: false, schema: {type: string, format: date}}
- {name: expectedArrivalEnd, in: query, required: false, schema: {type: string, format: date}}
- {name: excludedOrderIds, in: query, required: false, style: form, explode: true, schema: {type: array, items: {type: string, pattern: '^[1-9][0-9]*$'}}}
- {name: page, in: query, required: true, schema: {type: integer, format: int64, minimum: 1}}
- {name: size, in: query, required: true, schema: {type: integer, format: int64, minimum: 1, maximum: 200}}
@@ -1047,7 +1050,7 @@ components:
pages: {type: integer, format: int64, minimum: 0}
PendingReviewOrderRow:
type: object
required: [orderId, orderNo, inboundCode, customerId, customerName, warehouseId, channelCode, channelName, totalPackageCount, createdAt, mainStatus]
required: [orderId, orderNo, inboundCode, customerId, customerName, warehouseId, channelCode, channelName, totalPackageCount, createdAt, expectedArrivalAt, mainStatus]
properties:
orderId: {type: string, pattern: '^[1-9][0-9]*$'}
orderNo: {type: string}
@@ -1059,6 +1062,7 @@ components:
channelName: {type: string}
totalPackageCount: {type: integer, minimum: 0}
createdAt: {type: string, format: date-time}
expectedArrivalAt: {type: string, format: date-time, nullable: true}
mainStatus: {type: string, enum: [PENDING_REVIEW]}
FirstLegBatchDraftResponse:
type: object