Files
jdescopingtool/NEW/src/JdeScoping.DataAccess/QueryBuilders/MisQueryBuilder.cs
T
Joseph Doherty 8ce9a7dae1 docs: switch cache conversion design from MessagePack to protobuf-net-data
protobuf-net-data is purpose-built for IDataReader serialization and
returns IDataReader directly from Deserialize(), eliminating the need
for custom streaming reader implementations.
2026-01-06 14:15:19 -05:00

205 lines
7.2 KiB
C#

using SqlKata.Compilers;
namespace JdeScoping.DataAccess.QueryBuilders;
/// <summary>
/// Builds MIS extraction queries for work order step matching.
/// Uses SQL extraction functions to retrieve criteria from Search.Criteria JSON.
/// </summary>
public sealed class MisQueryBuilder
{
private readonly SqlServerCompiler _compiler;
/// <summary>
/// Initializes a new instance of MisQueryBuilder.
/// </summary>
/// <param name="compiler">The SqlKata SQL Server compiler.</param>
public MisQueryBuilder(SqlServerCompiler compiler)
{
_compiler = compiler;
}
/// <summary>
/// Builds the complete MIS extraction SQL including temp table setup and data population.
/// Uses extraction functions to get filter criteria from the database.
/// </summary>
/// <param name="searchId">The search ID to extract criteria from.</param>
/// <returns>The SQL statements for MIS extraction.</returns>
public IReadOnlyList<string> BuildMisExtractionSql(int searchId)
{
var statements = new List<string>();
// Create #TempMisData temp table
statements.Add(BuildTempMisDataTableSql());
// Build and execute MIS CTE query to populate temp table
statements.Add(BuildMisCteSql());
return statements;
}
private static string BuildTempMisDataTableSql()
{
return """
IF OBJECT_ID('tempdb.dbo.#TempMisData', 'U') IS NOT NULL
BEGIN
DROP TABLE #TempMisData;
END
CREATE TABLE #TempMisData (
WorkOrderNumber BIGINT,
ItemNumber VARCHAR(25),
ItemDescription VARCHAR(30),
BranchCode VARCHAR(12),
WorkCenterCode VARCHAR(12),
StepTimestamp DATETIME,
SequenceNumber DECIMAL(7, 2),
FunctionCode VARCHAR(15),
FunctionOperationDescription VARCHAR(80),
MatchedSequenceNumber DECIMAL(7, 2),
RoutingMatch BIT,
MasterMatch BIT,
MisNumber VARCHAR(32),
RevID VARCHAR(32),
CharNumber VARCHAR(32),
MisSequenceNumber VARCHAR(32),
TestDescription VARCHAR(2000),
SamplingType VARCHAR(32),
SamplingValue VARCHAR(32),
ToolsGauges VARCHAR(2000),
WorkInstructions VARCHAR(2000),
Status VARCHAR(32),
ReleaseDate DATETIME
);
""";
}
private string BuildMisCteSql(SearchModel model)
{
var joins = BuildMisJoins(model);
var whereClause = BuildMisWhereClause(model);
return $"""
WITH MIS_CTE AS(
SELECT DISTINCT wo.WorkOrderNumber,
wo.ItemNumber,
wo.BranchCode,
wo.RoutingType,
wo.IssueDate,
wos.WorkCenterCode,
wos.StepNumber,
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}
)
INSERT INTO #TempMISData
(
WorkOrderNumber,
ItemNumber,
ItemDescription,
BranchCode,
WorkCenterCode,
StepTimestamp,
SequenceNumber,
FunctionCode,
FunctionOperationDescription,
MatchedSequenceNumber,
RoutingMatch,
MasterMatch,
MisNumber,
RevID,
CharNumber,
MisSequenceNumber,
TestDescription,
SamplingType,
SamplingValue,
ToolsGauges,
WorkInstructions,
Status,
ReleaseDate
)
SELECT mm.WorkOrderNumber,
mm.ItemNumber,
mm.ItemDescription,
mm.BranchCode,
mm.WorkCenterCode,
mm.StepTimestamp,
mm.SequenceNumber,
mm.FunctionCode,
mm.FunctionOperationDescription,
mm.MatchedSequenceNumber,
mm.RoutingMatch,
mm.MasterMatch,
mm.MisNumber,
mm.RevID,
mm.CharNumber,
mm.MisSequenceNumber,
mm.TestDescription,
mm.SamplingType,
mm.SamplingValue,
mm.ToolsGauges,
mm.WorkInstructions,
mm.Status,
mm.ReleaseDate
FROM MIS_CTE c CROSS APPLY
dbo.MatchMIS(c.WorkOrderNumber, c.ItemNumber, c.BranchCode, c.RoutingType,
c.IssueDate, c.WorkCenterCode, c.StepNumber, c.EndDT,
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 "";
}
}