refactor: remove unused CMS/JDE repositories and data sources

Remove legacy JDE and CMS direct-access code that is no longer used:
- Delete ICmsDataSource, IJdeDataSource interfaces
- Delete ISearchProcessor, IUpdateProcessor interfaces
- Delete IJdeRepository and ICmsRepository (all partials)
- Delete JdeRepository and CmsRepository implementations
- Delete JdeQueries and CmsQueries
- Delete JdeFileDataSource, JdeOracleDataSource
- Delete CmsFileDataSource, CmsOracleDataSource
- Remove unused methods from LotFinderRepository interfaces
- Delete associated unit tests (CmsRepositoryTests, JdeRepositoryTests)

All data sync now uses ETL pipelines via DataSync project.
This commit is contained in:
Joseph Doherty
2026-01-07 05:04:49 -05:00
parent 6952f686fa
commit 1618b6664d
52 changed files with 1497 additions and 3779 deletions
@@ -3,8 +3,6 @@ using JdeScoping.Core.Options;
using JdeScoping.Infrastructure.Auth;
using JdeScoping.Infrastructure.Options;
using JdeScoping.Infrastructure.Security;
using JdeScoping.Infrastructure.Sources.Cms;
using JdeScoping.Infrastructure.Sources.Jde;
using Microsoft.Extensions.Configuration;
namespace Microsoft.Extensions.DependencyInjection;
@@ -25,27 +23,9 @@ public static class InfrastructureDependencyInjection
IConfiguration configuration)
{
// Bind configuration
services.Configure<DataSourceOptions>(
configuration.GetSection(DataSourceOptions.SectionName));
services.Configure<LdapOptions>(
configuration.GetSection(LdapOptions.SectionName));
// Register data sources based on configuration
var dataSourceOptions = configuration
.GetSection(DataSourceOptions.SectionName)
.Get<DataSourceOptions>();
if (dataSourceOptions?.UseFileDataSource == true)
{
services.AddScoped<IJdeDataSource, JdeFileDataSource>();
services.AddScoped<ICmsDataSource, CmsFileDataSource>();
}
else
{
services.AddScoped<IJdeDataSource, JdeOracleDataSource>();
services.AddScoped<ICmsDataSource, CmsOracleDataSource>();
}
// Register auth service based on configuration
var ldapOptions = configuration
.GetSection(LdapOptions.SectionName)
@@ -7,13 +7,11 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Dapper" Version="2.1.66" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.1" />
<PackageReference Include="Oracle.ManagedDataAccess.Core" Version="23.26.0" />
<PackageReference Include="System.DirectoryServices.Protocols" Version="10.0.1" />
</ItemGroup>
@@ -1,22 +0,0 @@
namespace JdeScoping.Infrastructure.Options;
/// <summary>
/// Configuration options for data source selection (Oracle vs file-based).
/// </summary>
public class DataSourceOptions
{
/// <summary>
/// Configuration section name in appsettings.json.
/// </summary>
public const string SectionName = "DataSource";
/// <summary>
/// Use file-based data sources instead of Oracle for development.
/// </summary>
public bool UseFileDataSource { get; set; } = false;
/// <summary>
/// Directory containing JSON data files for file-based data source.
/// </summary>
public string FileDirectory { get; set; } = "DevData";
}
@@ -1,43 +0,0 @@
using System.Runtime.CompilerServices;
using System.Text.Json;
using JdeScoping.Core.Interfaces;
using JdeScoping.Core.Models;
using JdeScoping.Core.Models.Quality;
using JdeScoping.Infrastructure.Options;
using Microsoft.Extensions.Options;
namespace JdeScoping.Infrastructure.Sources.Cms;
/// <summary>
/// File-based CMS data source for development/testing.
/// </summary>
public class CmsFileDataSource : ICmsDataSource
{
private readonly string _dataDirectory;
/// <summary>
/// Initializes a new instance of the <see cref="CmsFileDataSource"/> class.
/// </summary>
public CmsFileDataSource(IOptions<DataSourceOptions> options)
{
_dataDirectory = options.Value.FileDirectory;
}
/// <inheritdoc/>
public async IAsyncEnumerable<MisData> GetMisDataAsync(
DateTime? minimumDt = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
var filePath = Path.Combine(_dataDirectory, "misdata.json");
if (!File.Exists(filePath))
yield break;
var json = await File.ReadAllTextAsync(filePath, cancellationToken);
var items = JsonSerializer.Deserialize<List<MisData>>(json) ?? [];
foreach (var item in items.Where(m => !minimumDt.HasValue || (m.ReleaseDate.HasValue && m.ReleaseDate.Value >= minimumDt)))
{
yield return item;
}
}
}
@@ -1,46 +0,0 @@
using System.Runtime.CompilerServices;
using Dapper;
using JdeScoping.Core.Interfaces;
using JdeScoping.Core.Models;
using JdeScoping.Core.Models.Quality;
using Microsoft.Extensions.Configuration;
using Oracle.ManagedDataAccess.Client;
namespace JdeScoping.Infrastructure.Sources.Cms;
/// <summary>
/// Oracle-based CMS data source for production use.
/// </summary>
public class CmsOracleDataSource : ICmsDataSource
{
private readonly string _connectionString;
/// <summary>
/// Initializes a new instance of the <see cref="CmsOracleDataSource"/> class.
/// </summary>
public CmsOracleDataSource(IConfiguration configuration)
{
_connectionString = configuration.GetConnectionString("CMS")
?? throw new InvalidOperationException("CMS connection string not configured");
}
/// <inheritdoc/>
public async IAsyncEnumerable<MisData> GetMisDataAsync(
DateTime? minimumDt = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
await using var connection = new OracleConnection(_connectionString);
await connection.OpenAsync(cancellationToken);
// TODO: Implement actual CMS query for MIS data
var sql = minimumDt.HasValue
? "SELECT * FROM MISDATA WHERE RELEASE_DATE >= :MinDate"
: "SELECT * FROM MISDATA";
var results = await connection.QueryAsync<MisData>(sql, new { MinDate = minimumDt });
foreach (var item in results)
{
yield return item;
}
}
}
@@ -1,133 +0,0 @@
using System.Runtime.CompilerServices;
using System.Text.Json;
using JdeScoping.Core.Interfaces;
using JdeScoping.Core.Models;
using JdeScoping.Core.Models.Inventory;
using JdeScoping.Core.Models.Organization;
using JdeScoping.Core.Models.WorkOrders;
using JdeScoping.Infrastructure.Options;
using Microsoft.Extensions.Options;
namespace JdeScoping.Infrastructure.Sources.Jde;
/// <summary>
/// File-based JDE data source for development/testing.
/// </summary>
public class JdeFileDataSource : IJdeDataSource
{
private readonly string _dataDirectory;
/// <summary>
/// Initializes a new instance of the <see cref="JdeFileDataSource"/> class.
/// </summary>
public JdeFileDataSource(IOptions<DataSourceOptions> options)
{
_dataDirectory = options.Value.FileDirectory;
}
/// <inheritdoc/>
public async IAsyncEnumerable<WorkOrder> GetWorkOrdersAsync(
DateTime? minimumDt = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
var items = await LoadFromFileAsync<WorkOrder>("workorders.json", cancellationToken);
foreach (var item in items.Where(wo => !minimumDt.HasValue || (wo.LastUpdateDt.HasValue && wo.LastUpdateDt.Value >= minimumDt)))
{
yield return item;
}
}
/// <inheritdoc/>
public async IAsyncEnumerable<LotUsage> GetLotUsagesAsync(
DateTime? minimumDt = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
var items = await LoadFromFileAsync<LotUsage>("lotusages.json", cancellationToken);
foreach (var item in items.Where(lu => !minimumDt.HasValue || (lu.LastUpdateDt.HasValue && lu.LastUpdateDt.Value >= minimumDt)))
{
yield return item;
}
}
/// <inheritdoc/>
public async IAsyncEnumerable<Lot> GetLotsAsync(
DateTime? minimumDt = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
var items = await LoadFromFileAsync<Lot>("lots.json", cancellationToken);
foreach (var item in items.Where(l => !minimumDt.HasValue || (l.LastUpdateDt.HasValue && l.LastUpdateDt.Value >= minimumDt)))
{
yield return item;
}
}
/// <inheritdoc/>
public async IAsyncEnumerable<Item> GetItemsAsync(
DateTime? minimumDt = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
var items = await LoadFromFileAsync<Item>("items.json", cancellationToken);
foreach (var item in items.Where(i => !minimumDt.HasValue || (i.LastUpdateDt.HasValue && i.LastUpdateDt.Value >= minimumDt)))
{
yield return item;
}
}
/// <inheritdoc/>
public async IAsyncEnumerable<WorkCenter> GetWorkCentersAsync(
DateTime? minimumDt = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
var items = await LoadFromFileAsync<WorkCenter>("workcenters.json", cancellationToken);
foreach (var item in items.Where(wc => !minimumDt.HasValue || (wc.LastUpdateDt.HasValue && wc.LastUpdateDt.Value >= minimumDt)))
{
yield return item;
}
}
/// <inheritdoc/>
public async IAsyncEnumerable<ProfitCenter> GetProfitCentersAsync(
DateTime? minimumDt = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
var items = await LoadFromFileAsync<ProfitCenter>("profitcenters.json", cancellationToken);
foreach (var item in items.Where(pc => !minimumDt.HasValue || (pc.LastUpdateDt.HasValue && pc.LastUpdateDt.Value >= minimumDt)))
{
yield return item;
}
}
/// <inheritdoc/>
public async IAsyncEnumerable<JdeUser> GetUsersAsync(
DateTime? minimumDt = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
var items = await LoadFromFileAsync<JdeUser>("users.json", cancellationToken);
foreach (var item in items.Where(u => !minimumDt.HasValue || (u.LastUpdateDt.HasValue && u.LastUpdateDt.Value >= minimumDt)))
{
yield return item;
}
}
/// <inheritdoc/>
public async IAsyncEnumerable<Branch> GetBranchesAsync(
DateTime? minimumDt = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
var items = await LoadFromFileAsync<Branch>("branches.json", cancellationToken);
foreach (var item in items)
{
yield return item;
}
}
private async Task<List<T>> LoadFromFileAsync<T>(string fileName, CancellationToken cancellationToken)
{
var filePath = Path.Combine(_dataDirectory, fileName);
if (!File.Exists(filePath))
return [];
var json = await File.ReadAllTextAsync(filePath, cancellationToken);
return JsonSerializer.Deserialize<List<T>>(json) ?? [];
}
}
@@ -1,180 +0,0 @@
using System.Runtime.CompilerServices;
using Dapper;
using JdeScoping.Core.Interfaces;
using JdeScoping.Core.Models;
using JdeScoping.Core.Models.Inventory;
using JdeScoping.Core.Models.Organization;
using JdeScoping.Core.Models.WorkOrders;
using Microsoft.Extensions.Configuration;
using Oracle.ManagedDataAccess.Client;
namespace JdeScoping.Infrastructure.Sources.Jde;
/// <summary>
/// Oracle-based JDE data source for production use.
/// </summary>
public class JdeOracleDataSource : IJdeDataSource
{
private readonly string _connectionString;
/// <summary>
/// Initializes a new instance of the <see cref="JdeOracleDataSource"/> class.
/// </summary>
public JdeOracleDataSource(IConfiguration configuration)
{
_connectionString = configuration.GetConnectionString("JDE")
?? throw new InvalidOperationException("JDE connection string not configured");
}
/// <inheritdoc/>
public async IAsyncEnumerable<WorkOrder> GetWorkOrdersAsync(
DateTime? minimumDt = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
await using var connection = new OracleConnection(_connectionString);
await connection.OpenAsync(cancellationToken);
// TODO: Implement actual JDE query with proper column mapping
var sql = minimumDt.HasValue
? "SELECT * FROM F4801 WHERE UPMJ >= :MinDate"
: "SELECT * FROM F4801";
var results = await connection.QueryAsync<WorkOrder>(sql, new { MinDate = minimumDt });
foreach (var item in results)
{
yield return item;
}
}
/// <inheritdoc/>
public async IAsyncEnumerable<LotUsage> GetLotUsagesAsync(
DateTime? minimumDt = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
await using var connection = new OracleConnection(_connectionString);
await connection.OpenAsync(cancellationToken);
// TODO: Implement actual JDE query
var sql = minimumDt.HasValue
? "SELECT * FROM F4111 WHERE UPMJ >= :MinDate"
: "SELECT * FROM F4111";
var results = await connection.QueryAsync<LotUsage>(sql, new { MinDate = minimumDt });
foreach (var item in results)
{
yield return item;
}
}
/// <inheritdoc/>
public async IAsyncEnumerable<Lot> GetLotsAsync(
DateTime? minimumDt = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
await using var connection = new OracleConnection(_connectionString);
await connection.OpenAsync(cancellationToken);
var sql = minimumDt.HasValue
? "SELECT * FROM F4108 WHERE UPMJ >= :MinDate"
: "SELECT * FROM F4108";
var results = await connection.QueryAsync<Lot>(sql, new { MinDate = minimumDt });
foreach (var item in results)
{
yield return item;
}
}
/// <inheritdoc/>
public async IAsyncEnumerable<Item> GetItemsAsync(
DateTime? minimumDt = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
await using var connection = new OracleConnection(_connectionString);
await connection.OpenAsync(cancellationToken);
var sql = minimumDt.HasValue
? "SELECT * FROM F4101 WHERE UPMJ >= :MinDate"
: "SELECT * FROM F4101";
var results = await connection.QueryAsync<Item>(sql, new { MinDate = minimumDt });
foreach (var item in results)
{
yield return item;
}
}
/// <inheritdoc/>
public async IAsyncEnumerable<WorkCenter> GetWorkCentersAsync(
DateTime? minimumDt = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
await using var connection = new OracleConnection(_connectionString);
await connection.OpenAsync(cancellationToken);
var sql = minimumDt.HasValue
? "SELECT * FROM F30006 WHERE UPMJ >= :MinDate"
: "SELECT * FROM F30006";
var results = await connection.QueryAsync<WorkCenter>(sql, new { MinDate = minimumDt });
foreach (var item in results)
{
yield return item;
}
}
/// <inheritdoc/>
public async IAsyncEnumerable<ProfitCenter> GetProfitCentersAsync(
DateTime? minimumDt = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
await using var connection = new OracleConnection(_connectionString);
await connection.OpenAsync(cancellationToken);
// TODO: Implement actual query for profit centers
var sql = "SELECT * FROM F0006";
var results = await connection.QueryAsync<ProfitCenter>(sql);
foreach (var item in results)
{
yield return item;
}
}
/// <inheritdoc/>
public async IAsyncEnumerable<JdeUser> GetUsersAsync(
DateTime? minimumDt = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
await using var connection = new OracleConnection(_connectionString);
await connection.OpenAsync(cancellationToken);
var sql = minimumDt.HasValue
? "SELECT * FROM F0092 WHERE UPMJ >= :MinDate"
: "SELECT * FROM F0092";
var results = await connection.QueryAsync<JdeUser>(sql, new { MinDate = minimumDt });
foreach (var item in results)
{
yield return item;
}
}
/// <inheritdoc/>
public async IAsyncEnumerable<Branch> GetBranchesAsync(
DateTime? minimumDt = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
await using var connection = new OracleConnection(_connectionString);
await connection.OpenAsync(cancellationToken);
// TODO: Implement actual query for branches
var sql = "SELECT * FROM F0101";
var results = await connection.QueryAsync<Branch>(sql);
foreach (var item in results)
{
yield return item;
}
}
}