using JdeScoping.DataAccess.Models;
using SqlKata.Compilers;
namespace JdeScoping.DataAccess.QueryBuilders;
///
/// Builds MIS extraction queries for work order step matching.
///
public sealed class MisQueryBuilder
{
private readonly SqlServerCompiler _compiler;
///
/// Initializes a new instance of MisQueryBuilder.
///
/// The SqlKata SQL Server compiler.
public MisQueryBuilder(SqlServerCompiler compiler)
{
_compiler = compiler;
}
///
/// Builds the complete MIS extraction SQL including temp table setup and data population.
///
/// The search model containing filter criteria.
/// The SQL statements for MIS extraction.
public IReadOnlyList BuildMisExtractionSql(SearchModel model)
{
var statements = new List();
// Create #TempMisData temp table
statements.Add(BuildTempMisDataTableSql());
// Build and execute MIS CTE query to populate temp table
statements.Add(BuildMisCteSql(model));
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();
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 "";
}
}