@@ -24,71 +24,80 @@ public async Task<IEnumerable<StuckOrderDto>> GetStuckOrdersAsync(
2424 CancellationToken cancellationToken = default )
2525 {
2626 const string baseSql = @"
27- SELECT
28- co.CONumber AS OrderId,
29- co.orderNumber AS OrderNumber,
30- opt.Status AS StatusId,
31- st.Tracking_Status_Name AS Status,
32- mt.MajorProductTypeName AS ProductType,
33- opt.lastUpdatedDate AS StuckSince,
34- DATEDIFF(HOUR, opt.lastUpdatedDate, GETUTCDATE()) AS HoursStuck,
35- CASE
36- WHEN opt.Status BETWEEN 3001 AND 3910 THEN 6
37- WHEN opt.Status BETWEEN 4001 AND 5830 THEN 48
38- ELSE 24
39- END AS ThresholdHours,
40- co.websiteCode AS Region,
41- NULL AS CustomerEmail
42- FROM ConsolidationOrder co (NOLOCK)
43- INNER JOIN OrderProductTracking opt (NOLOCK)
44- ON opt.CONumber = co.CONumber
45- INNER JOIN luk_Tracking_Status st (NOLOCK)
46- ON st.Tracking_Status_id = opt.Status
47- INNER JOIN mas_SnSpecification sn (NOLOCK)
48- ON sn.SnID = opt.OPT_SnSpId
49- INNER JOIN luk_MajorProductType mt (NOLOCK)
50- ON mt.MProductTypeID = sn.MasterProductTypeID
51- WHERE opt.isPrimaryComponent = 1
52- AND opt.OrderDate > DATEADD(YEAR, -2, GETUTCDATE())
53- AND opt.Status < 6400
54- AND (
55- (opt.Status BETWEEN 3001 AND 3910
56- AND DATEDIFF(HOUR, opt.lastUpdatedDate, GETUTCDATE()) > 6)
57- OR
58- (opt.Status BETWEEN 4001 AND 5830
59- AND DATEDIFF(HOUR, opt.lastUpdatedDate, GETUTCDATE()) > 48)
60- )" ;
27+ WITH StuckOrders AS (
28+ SELECT
29+ co.CONumber AS OrderId,
30+ co.orderNumber AS OrderNumber,
31+ opt.Status AS StatusId,
32+ st.Tracking_Status_Name AS Status,
33+ mt.MajorProductTypeName AS ProductType,
34+ opt.lastUpdatedDate AS StuckSince,
35+ DATEDIFF(HOUR, opt.lastUpdatedDate, GETUTCDATE()) AS HoursStuck,
36+ CASE
37+ WHEN opt.Status BETWEEN 3001 AND 3910 THEN 6
38+ WHEN opt.Status BETWEEN 4001 AND 5830 THEN 48
39+ ELSE 24
40+ END AS ThresholdHours,
41+ co.websiteCode AS Region,
42+ NULL AS CustomerEmail,
43+ CAST(ISNULL(opt.FacilityId, 0) AS VARCHAR(20)) AS FacilityCode,
44+ 'Facility ' + CAST(ISNULL(opt.FacilityId, 0) AS VARCHAR(10)) AS FacilityName,
45+ ROW_NUMBER() OVER (PARTITION BY co.CONumber ORDER BY opt.lastUpdatedDate DESC) AS RowNum
46+ FROM ConsolidationOrder co (NOLOCK)
47+ INNER JOIN OrderProductTracking opt (NOLOCK)
48+ ON opt.CONumber = co.CONumber
49+ INNER JOIN luk_Tracking_Status st (NOLOCK)
50+ ON st.Tracking_Status_id = opt.Status
51+ INNER JOIN mas_SnSpecification sn (NOLOCK)
52+ ON sn.SnID = opt.OPT_SnSpId
53+ INNER JOIN luk_MajorProductType mt (NOLOCK)
54+ ON mt.MProductTypeID = sn.MasterProductTypeID
55+ WHERE opt.isPrimaryComponent = 1
56+ AND opt.OrderDate > DATEADD(YEAR, -2, GETUTCDATE())
57+ AND opt.Status < 6400
58+ AND (
59+ (opt.Status BETWEEN 3001 AND 3910
60+ AND DATEDIFF(HOUR, opt.lastUpdatedDate, GETUTCDATE()) > 6)
61+ OR
62+ (opt.Status BETWEEN 4001 AND 5830
63+ AND DATEDIFF(HOUR, opt.lastUpdatedDate, GETUTCDATE()) > 48)
64+ )
65+ )
66+ SELECT OrderId, OrderNumber, StatusId, Status, ProductType, StuckSince,
67+ HoursStuck, ThresholdHours, Region, CustomerEmail, FacilityCode, FacilityName
68+ FROM StuckOrders
69+ WHERE RowNum = 1" ;
6170
6271 var sqlBuilder = new StringBuilder ( baseSql ) ;
6372 var parameters = new DynamicParameters ( ) ;
6473
65- // Apply optional filters
74+ // Apply optional filters (reference CTE columns, not original table aliases)
6675 if ( queryParams . StatusId . HasValue )
6776 {
68- sqlBuilder . Append ( " AND opt.Status = @StatusId" ) ;
77+ sqlBuilder . Append ( " AND StatusId = @StatusId" ) ;
6978 parameters . Add ( "StatusId" , queryParams . StatusId . Value ) ;
7079 }
7180
7281 if ( ! string . IsNullOrWhiteSpace ( queryParams . Status ) )
7382 {
74- sqlBuilder . Append ( " AND st.Tracking_Status_Name LIKE @Status" ) ;
83+ sqlBuilder . Append ( " AND Status LIKE @Status" ) ;
7584 parameters . Add ( "Status" , $ "%{ queryParams . Status } %") ;
7685 }
7786
7887 if ( queryParams . MinHours . HasValue )
7988 {
80- sqlBuilder . Append ( " AND DATEDIFF(HOUR, opt.lastUpdatedDate, GETUTCDATE()) >= @MinHours" ) ;
89+ sqlBuilder . Append ( " AND HoursStuck >= @MinHours" ) ;
8190 parameters . Add ( "MinHours" , queryParams . MinHours . Value ) ;
8291 }
8392
8493 if ( queryParams . MaxHours . HasValue )
8594 {
86- sqlBuilder . Append ( " AND DATEDIFF(HOUR, opt.lastUpdatedDate, GETUTCDATE()) <= @MaxHours" ) ;
95+ sqlBuilder . Append ( " AND HoursStuck <= @MaxHours" ) ;
8796 parameters . Add ( "MaxHours" , queryParams . MaxHours . Value ) ;
8897 }
8998
9099 // Order by hours stuck descending (oldest first)
91- sqlBuilder . Append ( " ORDER BY DATEDIFF(HOUR, opt.lastUpdatedDate, GETUTCDATE()) DESC" ) ;
100+ sqlBuilder . Append ( " ORDER BY HoursStuck DESC" ) ;
92101
93102 // Apply pagination
94103 sqlBuilder . Append ( " OFFSET @Offset ROWS FETCH NEXT @Limit ROWS ONLY" ) ;
@@ -104,7 +113,7 @@ AND DATEDIFF(HOUR, opt.lastUpdatedDate, GETUTCDATE()) > 48)
104113 public async Task < int > GetStuckOrdersCountAsync ( CancellationToken cancellationToken = default )
105114 {
106115 const string sql = @"
107- SELECT COUNT(* )
116+ SELECT COUNT(DISTINCT co.CONumber )
108117 FROM ConsolidationOrder co (NOLOCK)
109118 INNER JOIN OrderProductTracking opt (NOLOCK)
110119 ON opt.CONumber = co.CONumber
0 commit comments