This commit is contained in:
2026-08-06 15:32:11 +08:00
parent f3cfbdf59b
commit 5f8b1f64da
21 changed files with 435 additions and 36 deletions
@@ -4,7 +4,9 @@ import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Size;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
/** Order service internal query for the product-level order line. */
public record UnifiedInboundQuery(
@@ -15,6 +17,18 @@ public record UnifiedInboundQuery(
Long customerId,
Long receivingWarehouseId,
Long destinationWarehouseId,
@Size(max = 64) String inboundCode,
@Size(max = 32) String internalOrderStatus,
LocalDate expectedArrivalDate,
@Size(max = 32) String feeReviewStatus,
@Size(max = 128) String channelName,
@Size(max = 64) String containerNo,
@Size(max = 64) String cabinetNo,
LocalDate sailingDate,
Boolean loaded,
Boolean fullContainer,
@Size(max = 32) String measurementReviewStatus,
List<Long> candidateOrderIds,
LocalDateTime createdFrom,
LocalDateTime createdTo,
@Min(1) long page,
@@ -110,6 +110,9 @@ public class InboundOrderRepository {
.eq(query.tenantId() != null, InboundOrderEntity::getTenantId, query.tenantId())
.in(processStatuses != null && !processStatuses.isEmpty(), InboundOrderEntity::getProcessStatus, processStatuses)
.like(StringUtils.hasText(query.orderNo()), InboundOrderEntity::getOrderNo, query.orderNo())
.like(StringUtils.hasText(query.inboundCode()), InboundOrderEntity::getInboundCode, query.inboundCode())
.eq(StringUtils.hasText(query.internalOrderStatus()), InboundOrderEntity::getOrderStatusSnapshot,
query.internalOrderStatus())
.and(StringUtils.hasText(query.keyword()), nested -> nested
.like(InboundOrderEntity::getOrderNo, query.keyword())
.or().like(InboundOrderEntity::getInboundCode, query.keyword())
@@ -117,6 +120,57 @@ public class InboundOrderRepository {
.eq(query.customerId() != null, InboundOrderEntity::getCustomerId, query.customerId())
.eq(query.receivingWarehouseId() != null, InboundOrderEntity::getWarehouseId, query.receivingWarehouseId())
.eq(query.destinationWarehouseId() != null, InboundOrderEntity::getDeliveryWarehouseId, query.destinationWarehouseId())
.ge(query.expectedArrivalDate() != null, InboundOrderEntity::getExpectedArrivalAt,
query.expectedArrivalDate() == null ? null : query.expectedArrivalDate().atStartOfDay())
.lt(query.expectedArrivalDate() != null, InboundOrderEntity::getExpectedArrivalAt,
query.expectedArrivalDate() == null ? null : query.expectedArrivalDate().plusDays(1).atStartOfDay())
.eq(StringUtils.hasText(query.channelName()), InboundOrderEntity::getChannelName, query.channelName())
.eq(query.fullContainer() != null, InboundOrderEntity::getContainerMode,
query.fullContainer() == null ? null : query.fullContainer() ? "FULL_CONTAINER" : "LCL")
.and("UNRECORDED".equals(query.measurementReviewStatus()), nested -> nested
.isNull(InboundOrderEntity::getMeasureReviewStatus)
.or().eq(InboundOrderEntity::getMeasureReviewStatus, ""))
.eq(StringUtils.hasText(query.measurementReviewStatus())
&& !"UNRECORDED".equals(query.measurementReviewStatus()),
InboundOrderEntity::getMeasureReviewStatus, query.measurementReviewStatus())
.in(query.candidateOrderIds() != null && !query.candidateOrderIds().isEmpty(),
InboundOrderEntity::getOrderId,
query.candidateOrderIds() == null ? List.of() : query.candidateOrderIds())
.apply("UNRECORDED".equals(query.feeReviewStatus()),
"NOT EXISTS (SELECT 1 FROM fl_inbound_fee f WHERE f.tenant_id = fl_inbound_order.tenant_id "
+ "AND f.inbound_id = fl_inbound_order.id)")
.apply(StringUtils.hasText(query.feeReviewStatus()) && !"UNRECORDED".equals(query.feeReviewStatus()),
"EXISTS (SELECT 1 FROM fl_inbound_fee f WHERE f.tenant_id = fl_inbound_order.tenant_id "
+ "AND f.inbound_id = fl_inbound_order.id AND f.review_status = {0} "
+ "AND NOT EXISTS (SELECT 1 FROM fl_inbound_fee newer "
+ "WHERE newer.tenant_id = f.tenant_id AND newer.inbound_id = f.inbound_id "
+ "AND (newer.fee_version > f.fee_version "
+ "OR (newer.fee_version = f.fee_version AND newer.id > f.id))))",
query.feeReviewStatus())
.apply(StringUtils.hasText(query.containerNo()),
"EXISTS (SELECT 1 FROM fl_inbound_transport_snapshot t "
+ "WHERE t.tenant_id = fl_inbound_order.tenant_id AND t.inbound_id = fl_inbound_order.id "
+ "AND t.container_no LIKE CONCAT('%', {0}, '%'))", query.containerNo())
.apply(StringUtils.hasText(query.cabinetNo()),
"EXISTS (SELECT 1 FROM fl_inbound_transport_snapshot t "
+ "WHERE t.tenant_id = fl_inbound_order.tenant_id AND t.inbound_id = fl_inbound_order.id "
+ "AND t.cabinet_no LIKE CONCAT('%', {0}, '%'))", query.cabinetNo())
.apply(query.sailingDate() != null,
"EXISTS (SELECT 1 FROM fl_inbound_transport_snapshot t "
+ "WHERE t.tenant_id = fl_inbound_order.tenant_id AND t.inbound_id = fl_inbound_order.id "
+ "AND t.sailing_at >= {0} AND t.sailing_at < {1})",
query.sailingDate() == null ? null : query.sailingDate().atStartOfDay(),
query.sailingDate() == null ? null : query.sailingDate().plusDays(1).atStartOfDay())
.apply(Boolean.TRUE.equals(query.loaded()),
"EXISTS (SELECT 1 FROM fl_inbound_transport_snapshot t "
+ "WHERE t.tenant_id = fl_inbound_order.tenant_id AND t.inbound_id = fl_inbound_order.id "
+ "AND COALESCE(TRIM(t.loading_status), '') <> '' "
+ "AND t.loading_status NOT IN ('UNLOADED', 'PENDING'))")
.apply(Boolean.FALSE.equals(query.loaded()),
"NOT EXISTS (SELECT 1 FROM fl_inbound_transport_snapshot t "
+ "WHERE t.tenant_id = fl_inbound_order.tenant_id AND t.inbound_id = fl_inbound_order.id "
+ "AND COALESCE(TRIM(t.loading_status), '') <> '' "
+ "AND t.loading_status NOT IN ('UNLOADED', 'PENDING'))")
.ge(query.createdFrom() != null, InboundOrderEntity::getCreatedAt, query.createdFrom())
.le(query.createdTo() != null, InboundOrderEntity::getCreatedAt, query.createdTo())
.orderByDesc(InboundOrderEntity::getCreatedAt).orderByDesc(InboundOrderEntity::getId);
@@ -36,7 +36,8 @@ public class UnifiedInboundQueryService {
public PageResult<UnifiedInboundSummary> page(UnifiedInboundQuery query) {
validate(query);
if ("PENDING_REVIEW".equals(query.mainStatus())) {
if ("PENDING_REVIEW".equals(query.mainStatus())
|| query.candidateOrderIds() != null && query.candidateOrderIds().isEmpty()) {
return new PageResult<>(List.of(), query.page(), query.size(), 0, 0);
}
Page<InboundOrderEntity> source = inbounds.pageUnifiedEntities(query, internalStatuses(query.mainStatus()));