26ff8d9b4f
Set up repository with legacy .NET Framework 4.8 source (OLD/), new .NET 10 Blazor solution (NEW/), OpenSpec specifications, documentation, and project configuration.
122 lines
5.6 KiB
C#
122 lines
5.6 KiB
C#
using Dapper;
|
|
using JdeScoping.DataAccess.Interfaces;
|
|
using Microsoft.Data.SqlClient;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace JdeScoping.DataAccess.Services;
|
|
|
|
/// <summary>
|
|
/// Service for traversing downstream work orders iteratively.
|
|
/// </summary>
|
|
public sealed class WorkOrderTraversalService : IWorkOrderTraversalService
|
|
{
|
|
private readonly ILogger<WorkOrderTraversalService> _logger;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of WorkOrderTraversalService.
|
|
/// </summary>
|
|
/// <param name="logger">The logger.</param>
|
|
public WorkOrderTraversalService(ILogger<WorkOrderTraversalService> logger)
|
|
{
|
|
_logger = logger;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task TraverseDownstreamAsync(
|
|
SqlConnection connection,
|
|
int maxIterations = 20,
|
|
CancellationToken ct = default)
|
|
{
|
|
_logger.LogDebug("Starting downstream work order traversal (max {MaxIterations} iterations)", maxIterations);
|
|
|
|
// The traversal SQL iteratively finds work orders that received material from flagged work orders
|
|
const string traversalSql = """
|
|
--Add downlevel work orders that were issued material from flagged work orders
|
|
DECLARE @c_MAX_RUNS INT = @p_MaxIterations;
|
|
DECLARE @v_NumWO INT = -1;
|
|
DECLARE @v_NewNumWO INT;
|
|
DECLARE @v_NumRuns INT = 0;
|
|
|
|
WHILE(1 = 1) BEGIN
|
|
SET @v_NumWO = @v_NewNumWO;
|
|
|
|
--Add any work orders issued material from flagged work orders (parts list)
|
|
WITH CWO_D AS(
|
|
SELECT DISTINCT wo.WorkOrderNumber,
|
|
wo.LotNumber,
|
|
wo.BranchCode,
|
|
wo.ShortItemNumber
|
|
FROM dbo.WorkOrderComponent AS woc INNER JOIN
|
|
dbo.WorkOrder AS wo ON (woc.WorkOrderNumber = wo.WorkOrderNumber) INNER JOIN
|
|
#Temp_WO AS t_wo ON (woc.LotNumber = t_wo.LotNumber AND woc.ShortItemNumber = t_wo.ShortItemNumber)
|
|
)
|
|
MERGE #Temp_WO AS TARGET
|
|
USING CWO_D AS SOURCE
|
|
ON (TARGET.WorkOrderNumber = SOURCE.WorkOrderNumber)
|
|
WHEN MATCHED THEN
|
|
UPDATE SET TARGET.PartsList = 1
|
|
WHEN NOT MATCHED THEN
|
|
INSERT (WorkOrderNumber, LotNumber, BranchCode, ShortItemNumber, PartsList)
|
|
VALUES (SOURCE.WorkOrderNumber, COALESCE(SOURCE.LotNumber, CAST(SOURCE.WorkOrderNumber AS VARCHAR(8))), SOURCE.BranchCode, SOURCE.ShortItemNumber, 1);
|
|
|
|
--Add any work orders issued material from flagged work orders (CARDEX)
|
|
WITH CWO_D AS(
|
|
SELECT DISTINCT wo.WorkOrderNumber,
|
|
wo.LotNumber,
|
|
wo.BranchCode,
|
|
wo.ShortItemNumber
|
|
FROM dbo.LotUsage AS lu INNER JOIN
|
|
dbo.WorkOrder AS wo ON (lu.WorkOrderNumber = wo.WorkOrderNumber) INNER JOIN
|
|
#Temp_WO AS t_wo ON (lu.LotNumber = t_wo.LotNumber AND lu.ShortItemNumber = t_wo.ShortItemNumber)
|
|
)
|
|
MERGE #Temp_WO AS TARGET
|
|
USING CWO_D AS SOURCE
|
|
ON (TARGET.WorkOrderNumber = SOURCE.WorkOrderNumber)
|
|
WHEN MATCHED THEN
|
|
UPDATE SET TARGET.CARDEX = 1
|
|
WHEN NOT MATCHED THEN
|
|
INSERT (WorkOrderNumber, LotNumber, BranchCode, ShortItemNumber, CARDEX)
|
|
VALUES (SOURCE.WorkOrderNumber, COALESCE(SOURCE.LotNumber, CAST(SOURCE.WorkOrderNumber AS VARCHAR(8))), SOURCE.BranchCode, SOURCE.ShortItemNumber, 1);
|
|
|
|
--Add any work orders split from flagged work orders
|
|
WITH SP_WO AS
|
|
(
|
|
SELECT DISTINCT wo.WorkOrderNumber,
|
|
wo.LotNumber,
|
|
wo.BranchCode,
|
|
wo.ShortItemNumber
|
|
FROM dbo.WorkOrder AS wo INNER JOIN
|
|
#Temp_WO AS tw_o ON (wo.ParentWorkOrderNumber = CAST(tw_o.WorkOrderNumber AS VARCHAR(8)) AND wo.BranchCode = tw_o.BranchCode)
|
|
)
|
|
MERGE #Temp_WO AS TARGET
|
|
USING SP_WO AS SOURCE
|
|
ON (TARGET.WorkOrderNumber = SOURCE.WorkOrderNumber AND TARGET.BranchCode = SOURCE.BranchCode)
|
|
WHEN MATCHED THEN
|
|
UPDATE SET TARGET.SplitOrder = 1
|
|
WHEN NOT MATCHED BY TARGET THEN
|
|
INSERT (WorkOrderNumber, LotNumber, BranchCode, ShortItemNumber, SplitOrder)
|
|
VALUES (SOURCE.WorkOrderNumber, SOURCE.LotNumber, SOURCE.BranchCode, SOURCE.ShortItemNumber, 1);
|
|
|
|
SELECT @v_NewNumWO = COUNT(*) FROM #Temp_WO;
|
|
SET @v_NumRuns = @v_NumRuns + 1;
|
|
|
|
IF(@v_NumWO = @v_NewNumWO OR @v_NumRuns = @c_MAX_RUNS) BEGIN
|
|
BREAK;
|
|
END
|
|
END;
|
|
|
|
SELECT @v_NumRuns AS IterationsCompleted, @v_NewNumWO AS TotalWorkOrders;
|
|
""";
|
|
|
|
var result = await connection.QuerySingleAsync<(int IterationsCompleted, int TotalWorkOrders)>(
|
|
traversalSql,
|
|
new { p_MaxIterations = maxIterations },
|
|
commandTimeout: 600);
|
|
|
|
_logger.LogDebug(
|
|
"Downstream traversal completed in {Iterations} iterations, found {TotalWorkOrders} total work orders",
|
|
result.IterationsCompleted,
|
|
result.TotalWorkOrders);
|
|
}
|
|
}
|