Initial commit: JDE Scoping Tool migration project

Set up repository with legacy .NET Framework 4.8 source (OLD/),
new .NET 10 Blazor solution (NEW/), OpenSpec specifications,
documentation, and project configuration.
This commit is contained in:
Joseph Doherty
2026-01-02 07:43:29 -05:00
commit 26ff8d9b4f
1761 changed files with 596509 additions and 0 deletions
@@ -0,0 +1,20 @@
namespace JdeScoping.DataSync.Models;
/// <summary>
/// Represents the schema of a database column.
/// </summary>
/// <param name="Name">Column name.</param>
/// <param name="DataType">SQL Server data type name (e.g., "nvarchar", "int", "decimal").</param>
/// <param name="MaxLength">Maximum length for string columns (-1 for MAX).</param>
/// <param name="Precision">Precision for decimal columns.</param>
/// <param name="Scale">Scale for decimal columns.</param>
/// <param name="IsNullable">Whether the column allows null values.</param>
/// <param name="OrdinalPosition">Column ordinal position (1-based).</param>
public record ColumnSchema(
string Name,
string DataType,
int? MaxLength,
int? Precision,
int? Scale,
bool IsNullable,
int OrdinalPosition);
@@ -0,0 +1,62 @@
using JdeScoping.Core.Models.Enums;
using JdeScoping.DataSync.Configuration;
namespace JdeScoping.DataSync.Models;
/// <summary>
/// Represents a pending data update task to be executed.
/// </summary>
public class DataUpdateTask
{
/// <summary>
/// Unique identifier for this operation (used for staging table suffixes).
/// </summary>
public Guid OperationId { get; init; } = Guid.NewGuid();
/// <summary>
/// Target table name in SQL Server cache.
/// </summary>
public required string TableName { get; init; }
/// <summary>
/// Source system: "JDE" or "CMS".
/// </summary>
public required string SourceSystem { get; init; }
/// <summary>
/// Source data identifier.
/// </summary>
public string SourceData { get; init; } = string.Empty;
/// <summary>
/// Type of update (Hourly, Daily, Mass).
/// </summary>
public UpdateTypes UpdateType { get; init; }
/// <summary>
/// For incremental updates, the minimum datetime to fetch records from.
/// Null for mass updates (full refresh).
/// </summary>
public DateTime? MinimumDt { get; init; }
/// <summary>
/// The data source configuration for this task.
/// </summary>
public required DataSourceConfig Config { get; init; }
/// <summary>
/// Gets a unique key for logging purposes.
/// </summary>
public string LogKey => $"{TableName}_{UpdateType}_{OperationId:N}";
/// <summary>
/// Gets the schedule configuration for this update type.
/// </summary>
public ScheduleConfig ScheduleConfig => UpdateType switch
{
UpdateTypes.Mass => Config.MassConfig,
UpdateTypes.Daily => Config.DailyConfig,
UpdateTypes.Hourly => Config.HourlyConfig,
_ => throw new ArgumentOutOfRangeException(nameof(UpdateType))
};
}
@@ -0,0 +1,33 @@
namespace JdeScoping.DataSync.Models;
/// <summary>
/// Result of a bulk merge operation.
/// </summary>
/// <param name="TotalRowsProcessed">Total number of rows processed from source.</param>
/// <param name="RowsInserted">Number of rows inserted (new records).</param>
/// <param name="RowsUpdated">Number of rows updated (existing records).</param>
/// <param name="BatchCount">Number of batches processed.</param>
/// <param name="Elapsed">Total elapsed time for the operation.</param>
public record MergeResult(
int TotalRowsProcessed,
int RowsInserted,
int RowsUpdated,
int BatchCount,
TimeSpan Elapsed)
{
/// <summary>
/// Total rows affected (inserted + updated).
/// </summary>
public int TotalRowsAffected => RowsInserted + RowsUpdated;
}
/// <summary>
/// Result of a mass insert operation.
/// </summary>
/// <param name="TotalRowsInserted">Total rows inserted.</param>
/// <param name="Elapsed">Total elapsed time.</param>
/// <param name="IndexesRebuilt">Whether indexes were rebuilt (vs just re-enabled).</param>
public record MassInsertResult(
long TotalRowsInserted,
TimeSpan Elapsed,
bool IndexesRebuilt);