refactor(data-access): remove TVP code and simplify SearchModel

- Remove all List<*FilterEntry> properties and *FilterEnabled computed properties from SearchModel
- Delete TableValuedParameterExtensions.cs
- Delete entire FilterEntries folder and all filter entry model classes
- Delete FilterHandlers folder and all filter handler classes
- Delete IFilterHandler interface and FilterResult model
- Update MisQueryBuilder to use SQL extraction functions instead of model properties
- Update SearchProcessor to get ExtractMisData from database using fn_GetSearchExtractMisData
- Update DependencyInjection to remove filter handler registrations
- Delete obsolete tests for TVP extensions and filter handlers

Filter criteria are now stored as JSON in Search.Criteria column and extracted using SQL functions (fn_GetSearch*) during query execution.
This commit is contained in:
Joseph Doherty
2026-01-06 14:32:03 -05:00
parent a2a8bb3e9f
commit 691a6d1ffd
26 changed files with 37 additions and 1910 deletions
@@ -73,12 +73,18 @@ public sealed class MisQueryBuilder
""";
}
private string BuildMisCteSql(SearchModel model)
private static string BuildMisCteSql()
{
var joins = BuildMisJoins(model);
var whereClause = BuildMisWhereClause(model);
// The SQL uses temp tables (#P_ItemNumbers, #P_WorkCenters, #P_OperatorIDs)
// and variables (@MinDt, @MaxDt) that were already populated by the main search query builder.
// This query uses dynamic join/filter conditions based on what filters exist.
return """
-- Build MIS extraction using existing temp tables and date variables
DECLARE @HasMisItemFilter BIT = CASE WHEN EXISTS(SELECT 1 FROM #P_ItemNumbers) THEN 1 ELSE 0 END;
DECLARE @HasMisWorkCenterFilter BIT = CASE WHEN EXISTS(SELECT 1 FROM #P_WorkCenters) THEN 1 ELSE 0 END;
DECLARE @HasMisOperatorFilter BIT = CASE WHEN EXISTS(SELECT 1 FROM #P_OperatorIDs) THEN 1 ELSE 0 END;
DECLARE @HasMisTimespanFilter BIT = CASE WHEN @MinDt IS NOT NULL OR @MaxDt IS NOT NULL THEN 1 ELSE 0 END;
return $"""
WITH MIS_CTE AS(
SELECT DISTINCT wo.WorkOrderNumber,
wo.ItemNumber,
@@ -90,11 +96,20 @@ public sealed class MisQueryBuilder
wos.EndDT,
wos.FunctionCode,
wos.FunctionOperationDescription
FROM dbo.WorkOrderStep AS wos INNER JOIN
dbo.WorkOrder AS wo ON (wos.WorkOrderNumber = wo.WorkOrderNumber AND LTRIM(wos.BranchCode) = wo.BranchCode) LEFT OUTER JOIN
dbo.WorkOrderTime AS wot ON (wos.WorkOrderNumber = wot.WorkOrderNumber AND LTRIM(wos.BranchCode) = wot.BranchCode AND wos.StepNumber = wot.StepNumber){joins}{whereClause}
FROM dbo.WorkOrderStep AS wos
INNER JOIN dbo.WorkOrder AS wo ON (wos.WorkOrderNumber = wo.WorkOrderNumber AND LTRIM(wos.BranchCode) = wo.BranchCode)
LEFT OUTER JOIN dbo.WorkOrderTime AS wot ON (wos.WorkOrderNumber = wot.WorkOrderNumber AND LTRIM(wos.BranchCode) = wot.BranchCode AND wos.StepNumber = wot.StepNumber)
LEFT OUTER JOIN #P_ItemNumbers p_in ON (@HasMisItemFilter = 0 OR wo.ItemNumber = p_in.ItemNumber)
LEFT OUTER JOIN #P_WorkCenters p_wc ON (@HasMisWorkCenterFilter = 0 OR wos.WorkCenterCode = p_wc.Code)
LEFT OUTER JOIN #P_OperatorIDs p_oi ON (@HasMisOperatorFilter = 0 OR wot.AddressNumber = p_oi.AddressNumber)
WHERE (@HasMisItemFilter = 0 OR p_in.ItemNumber IS NOT NULL)
AND (@HasMisWorkCenterFilter = 0 OR p_wc.Code IS NOT NULL)
AND (@HasMisOperatorFilter = 0 OR p_oi.AddressNumber IS NOT NULL)
AND (@HasMisTimespanFilter = 0 OR
((@MinDt IS NULL OR wos.EndDT >= @MinDt OR wot.GlDate >= @MinDt) AND
(@MaxDt IS NULL OR wos.EndDT <= @MaxDt OR wot.GlDate <= @MaxDt)))
)
INSERT INTO #TempMISData
INSERT INTO #TempMisData
(
WorkOrderNumber,
ItemNumber,
@@ -149,56 +164,4 @@ public sealed class MisQueryBuilder
c.FunctionCode, c.FunctionOperationDescription) AS mm;
""";
}
private static string BuildMisJoins(SearchModel model)
{
var joins = new List<string>();
if (model.ItemNumberFilterEnabled)
{
joins.Add(" INNER JOIN\r\n #P_ItemNumbers p_in ON (wo.ItemNumber = p_in.ItemNumber)");
}
if (model.ProfitCenterFilterEnabled || model.WorkCenterFilterEnabled)
{
joins.Add(" INNER JOIN \r\n #P_WorkCenters p_wc ON (wos.WorkCenterCode = p_wc.Code)");
}
if (model.OperatorFilterEnabled)
{
joins.Add(" INNER JOIN \r\n #P_OperatorIDs p_oi ON (wot.AddressNumber = p_oi.AddressNumber)");
}
return string.Join("", joins);
}
private static string BuildMisWhereClause(SearchModel model)
{
if (model.MinimumDt.HasValue && model.MaximumDt.HasValue)
{
return """
WHERE (((wos.EndDT <= @p_MaximumDT) AND (wos.EndDT >= @p_MinimumDT)) OR
((wot.GlDate <= @p_MaximumDT) AND (wot.GlDate >= @p_MinimumDT)))
""";
}
if (model.MinimumDt.HasValue && !model.MaximumDt.HasValue)
{
return """
WHERE (wos.EndDT >= @p_MinimumDT OR wot.GlDate >= @p_MinimumDT)
""";
}
if (!model.MinimumDt.HasValue && model.MaximumDt.HasValue)
{
return """
WHERE (wos.EndDT <= @p_MaximumDT OR wot.GlDate <= @p_MaximumDT)
""";
}
return "";
}
}