feat(appointments): unify pre-inbound planning and confirmed FBA bookings

This commit is contained in:
2026-10-10 10:38:06 +08:00
parent 24f5ccf7ff
commit c4c1bddeec
54 changed files with 1623 additions and 744 deletions
@@ -8,30 +8,34 @@ import java.util.List;
@Mapper
public interface AppointmentCoverageMapper {
String DESTINATION_TYPE="CASE WHEN o.order_type='WAREHOUSE_TRANSFER' THEN wt.destination_type ELSE o.destination_type END";
String DESTINATION_CODE="CASE WHEN o.order_type='WAREHOUSE_TRANSFER' THEN wt.destination_warehouse_code ELSE o.fba_warehouse_code END";
String SHIPMENT_MISSING="CASE WHEN o.order_type='WAREHOUSE_TRANSFER' THEN (wt.id IS NULL OR ((wt.fba_shipment_no IS NULL OR TRIM(wt.fba_shipment_no)='') AND (wt.tracking_no IS NULL OR TRIM(wt.tracking_no)=''))) ELSE " +
"(NOT EXISTS(SELECT 1 FROM ll_order_detail d WHERE d.order_id=o.id AND d.customer_id=o.customer_id) OR EXISTS(SELECT 1 FROM ll_order_detail d WHERE d.order_id=o.id AND d.customer_id=o.customer_id AND (d.shipment_no IS NULL OR TRIM(d.shipment_no)='') AND (d.fba_tracking_no IS NULL OR TRIM(d.fba_tracking_no)=''))) END";
String TRANSFER_JOIN=" LEFT JOIN ll_warehouse_transfer_order wt ON o.order_type='WAREHOUSE_TRANSFER' AND wt.lastleg_order_id=o.id AND wt.customer_id=o.customer_id ";
record OrderRef(String customerId, Long orderId) { }
record Source(Long orderId, String customerId, String destinationType, String fbaWarehouseCode,
Integer packages, Integer version, LocalDateTime updatedAt, boolean shipmentReferencesMissing) { }
record Fact(Long orderId, String customerId, String appointmentNo, String status,
LocalDateTime appointmentAt, LocalDateTime appointmentEndAt, LocalDateTime updatedAt,
Long lineId, Integer packages, String warehouseCode) { }
Long itemId, Integer packages, String warehouseCode,String sourceKey,String sourceVersion,
String confirmationNo,String timezone) { }
@Select({"<script>SELECT o.id AS orderId,o.customer_id AS customerId,o.destination_type AS destinationType,",
"o.fba_warehouse_code AS fbaWarehouseCode,o.package_count AS packages,o.version,o.updated_at AS updatedAt, ",
"(NOT EXISTS(SELECT 1 FROM ll_order_detail d WHERE d.order_id=o.id AND d.customer_id=o.customer_id) OR ",
"EXISTS(SELECT 1 FROM ll_order_detail d WHERE d.order_id=o.id AND d.customer_id=o.customer_id ",
"AND (d.shipment_no IS NULL OR TRIM(d.shipment_no)='') AND (d.fba_tracking_no IS NULL OR TRIM(d.fba_tracking_no)=''))) AS shipmentReferencesMissing ",
"FROM ll_order o WHERE <foreach collection='sources' item='s' open='(' separator=' OR ' close=')'>",
@Select({"<script>SELECT o.id AS orderId,o.customer_id AS customerId,"+DESTINATION_TYPE+" AS destinationType,",
DESTINATION_CODE+" AS fbaWarehouseCode,o.package_count AS packages,o.version,o.updated_at AS updatedAt, ",
SHIPMENT_MISSING+" AS shipmentReferencesMissing ",
"FROM ll_order o "+TRANSFER_JOIN+" WHERE <foreach collection='sources' item='s' open='(' separator=' OR ' close=')'>",
"(o.id=#{s.orderId} AND o.customer_id=#{s.customerId})</foreach></script>"})
List<Source> sources(@Param("sources") List<OrderRef> sources);
@Select({"<script>SELECT i.order_id AS orderId,i.customer_id AS customerId,a.appointment_no AS appointmentNo,",
"a.appointment_status AS status,a.appointment_at AS appointmentAt,a.appointment_end_at AS appointmentEndAt,",
"a.updated_at AS updatedAt,i.line_id AS lineId,l.required_package_count AS packages,l.fba_warehouse_code AS warehouseCode ",
"a.updated_at AS updatedAt,i.id AS itemId,i.package_count AS packages,i.fba_warehouse_code AS warehouseCode, ",
"i.source_key AS sourceKey,i.source_version AS sourceVersion,a.confirmation_no AS confirmationNo,a.timezone ",
"FROM ll_inbound_fba_appointment_item i JOIN ll_inbound_fba_appointment a ON a.id=i.appointment_id ",
"JOIN ll_inbound_plan_line l ON l.id=i.line_id AND l.plan_id=i.plan_id AND l.order_id=i.order_id AND l.customer_id=i.customer_id ",
"WHERE a.appointment_status NOT IN ('FAILED','CANCELLED') AND ",
"WHERE i.active=1 AND a.appointment_status NOT IN ('FAILED','CANCELLED') AND ",
"<foreach collection='sources' item='s' open='(' separator=' OR ' close=')'>",
"(i.order_id=#{s.orderId} AND i.customer_id=#{s.customerId})</foreach>",
"(i.source_key=#{s.sourceKey} AND i.customer_id=#{s.customerId})</foreach>",
" ORDER BY a.appointment_at,a.id,i.id</script>"})
List<Fact> appointments(@Param("sources") List<OrderRef> sources);
List<Fact> appointments(@Param("sources") List<AppointmentCoverageService.SourceRef> sources);
}