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,200 @@
using System.Data;
using Dapper;
using JdeScoping.Core.Models.Enums;
using JdeScoping.Core.Models.Search;
using JdeScoping.DataAccess.Queries;
using Microsoft.Data.SqlClient;
namespace JdeScoping.DataAccess.Repositories;
/// <summary>
/// Search management operations for LotFinder repository.
/// </summary>
public partial class LotFinderRepository
{
/// <inheritdoc/>
public async Task<List<Search>> GetUserSearchesAsync(string userName, CancellationToken ct = default)
{
const string operation = nameof(GetUserSearchesAsync);
try
{
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
var result = await connection.QueryAsync<Search>(
LotFinderQueries.SqlGetUserSearches,
new { userName },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
return result.ToList();
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
LogAndThrow(ex, operation, "SQL_GET_USER_SEARCHES");
throw; // Unreachable but satisfies compiler
}
}
/// <inheritdoc/>
public async Task<List<Search>> GetQueuedSearchesAsync(CancellationToken ct = default)
{
const string operation = nameof(GetQueuedSearchesAsync);
try
{
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
var result = await connection.QueryAsync<Search>(
LotFinderQueries.SqlGetQueuedSearches,
commandTimeout: _options.Value.DefaultTimeoutSeconds);
return result.ToList();
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
LogAndThrow(ex, operation, "SQL_GET_QUEUED_SEARCHES");
throw;
}
}
/// <inheritdoc/>
public async Task<Search?> GetSearchAsync(int id, CancellationToken ct = default)
{
const string operation = nameof(GetSearchAsync);
try
{
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
var result = await connection.QueryFirstOrDefaultAsync<Search>(
LotFinderQueries.SqlGetSearch,
new { id },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
if (result != null)
{
result.Id = id;
}
return result;
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
LogAndThrow(ex, operation, "SQL_GET_SEARCH");
throw;
}
}
/// <inheritdoc/>
public async Task<byte[]?> GetSearchResultsAsync(int id, CancellationToken ct = default)
{
const string operation = nameof(GetSearchResultsAsync);
try
{
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
return await connection.QueryFirstOrDefaultAsync<byte[]>(
LotFinderQueries.SqlGetSearchResults,
new { id },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
LogAndThrow(ex, operation, "SQL_GET_SEARCH_RESULTS");
throw;
}
}
/// <inheritdoc/>
public async Task<int> SubmitSearchAsync(Search search, CancellationToken ct = default)
{
const string operation = nameof(SubmitSearchAsync);
try
{
search.Status = SearchStatus.Queued;
search.SubmitDt = DateTime.UtcNow;
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
await using var command = new SqlCommand("SubmitSearch", connection)
{
CommandType = CommandType.StoredProcedure,
CommandTimeout = _options.Value.DefaultTimeoutSeconds
};
command.Parameters.AddWithValue("p_UserName", search.UserName);
command.Parameters.AddWithValue("p_Name", search.Name);
command.Parameters.AddWithValue("p_Criteria", search.CriteriaJson);
var searchIdParam = new SqlParameter("o_SearchID", SqlDbType.Int)
{
Direction = ParameterDirection.Output
};
command.Parameters.Add(searchIdParam);
await command.ExecuteNonQueryAsync(ct);
return Convert.ToInt32(searchIdParam.Value);
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
LogAndThrow(ex, operation, "SubmitSearch");
throw;
}
}
/// <inheritdoc/>
public async Task UpdateSearchStatusAsync(int id, SearchStatus status, CancellationToken ct = default)
{
const string operation = nameof(UpdateSearchStatusAsync);
try
{
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
await connection.ExecuteAsync(
LotFinderQueries.SqlUpdateSearchStatus,
new { id, status = (int)status },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
LogAndThrow(ex, operation, "SQL_UPDATE_SEARCH_STATUS");
throw;
}
}
/// <inheritdoc/>
public async Task UpdateSearchResultsAsync(int id, byte[] results, CancellationToken ct = default)
{
const string operation = nameof(UpdateSearchResultsAsync);
try
{
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(ct);
await connection.ExecuteAsync(
LotFinderQueries.SqlUpdateSearchResults,
new { id, results },
commandTimeout: _options.Value.DefaultTimeoutSeconds);
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
LogAndThrow(ex, operation, "SQL_UPDATE_SEARCH_RESULTS");
throw;
}
}
}