diff --git a/NEW/JdeScoping.slnx b/NEW/JdeScoping.slnx
index 0be7837..250a777 100644
--- a/NEW/JdeScoping.slnx
+++ b/NEW/JdeScoping.slnx
@@ -12,6 +12,7 @@
+
@@ -26,6 +27,7 @@
+
diff --git a/NEW/src/JdeScoping.Api/Controllers/AuthController.cs b/NEW/src/JdeScoping.Api/Controllers/AuthController.cs
index 277be27..6ab3a9a 100644
--- a/NEW/src/JdeScoping.Api/Controllers/AuthController.cs
+++ b/NEW/src/JdeScoping.Api/Controllers/AuthController.cs
@@ -28,6 +28,12 @@ public class AuthController : ApiControllerBase
private readonly IRsaKeyService _rsaKeyService;
private readonly ILogger _logger;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The authentication service.
+ /// The RSA key service for credential encryption.
+ /// Logger instance.
public AuthController(
IAuthService authService,
IRsaKeyService rsaKeyService,
diff --git a/NEW/src/JdeScoping.Api/Controllers/FileIOController.ComponentLots.cs b/NEW/src/JdeScoping.Api/Controllers/FileIOController.ComponentLots.cs
index 8b1d8f6..83c6437 100644
--- a/NEW/src/JdeScoping.Api/Controllers/FileIOController.ComponentLots.cs
+++ b/NEW/src/JdeScoping.Api/Controllers/FileIOController.ComponentLots.cs
@@ -14,6 +14,8 @@ public partial class FileIOController
///
/// Uploads an Excel file containing component lot/item pairs and returns the matched lots
///
+ /// The Excel file containing component lot/item pairs.
+ /// The cancellation token.
[HttpPost("componentlots/upload")]
[ProducesResponseType(typeof(FileUploadResult), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(FileUploadResult), StatusCodes.Status400BadRequest)]
@@ -63,6 +65,7 @@ public partial class FileIOController
///
/// Downloads an Excel template with current component lot data
///
+ /// The list of lot view models to include in the export.
[HttpPost("componentlots/download")]
[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]
public IActionResult DownloadComponentLots([FromBody] List? lotNumbers)
diff --git a/NEW/src/JdeScoping.Api/Controllers/FileIOController.Items.cs b/NEW/src/JdeScoping.Api/Controllers/FileIOController.Items.cs
index a41bf7a..7a63cdc 100644
--- a/NEW/src/JdeScoping.Api/Controllers/FileIOController.Items.cs
+++ b/NEW/src/JdeScoping.Api/Controllers/FileIOController.Items.cs
@@ -14,6 +14,8 @@ public partial class FileIOController
///
/// Uploads an Excel file containing item numbers and returns the matched items
///
+ /// The uploaded Excel file containing item numbers.
+ /// The cancellation token.
[HttpPost("items/upload")]
[ProducesResponseType(typeof(FileUploadResult), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(FileUploadResult), StatusCodes.Status400BadRequest)]
@@ -62,6 +64,7 @@ public partial class FileIOController
///
/// Downloads an Excel template with current item data
///
+ /// The list of items to include in the template.
[HttpPost("items/download")]
[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]
public IActionResult DownloadItems([FromBody] List? items)
diff --git a/NEW/src/JdeScoping.Api/Controllers/FileIOController.PartOperations.cs b/NEW/src/JdeScoping.Api/Controllers/FileIOController.PartOperations.cs
index 8d2eb27..13f1632 100644
--- a/NEW/src/JdeScoping.Api/Controllers/FileIOController.PartOperations.cs
+++ b/NEW/src/JdeScoping.Api/Controllers/FileIOController.PartOperations.cs
@@ -14,6 +14,8 @@ public partial class FileIOController
///
/// Uploads an Excel file containing part operations and returns the parsed data
///
+ /// The Excel file to upload.
+ /// Result containing parsed part operations.
[HttpPost("partoperations/upload")]
[ProducesResponseType(typeof(FileUploadResult), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(FileUploadResult), StatusCodes.Status400BadRequest)]
@@ -54,6 +56,8 @@ public partial class FileIOController
///
/// Downloads an Excel template with current part operation data
///
+ /// Optional list of part operations to include in template.
+ /// Excel file.
[HttpPost("partoperations/download")]
[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]
public IActionResult DownloadPartOperations([FromBody] List? partOperations)
diff --git a/NEW/src/JdeScoping.Api/Controllers/FileIOController.WorkOrders.cs b/NEW/src/JdeScoping.Api/Controllers/FileIOController.WorkOrders.cs
index d3a4803..093fc2b 100644
--- a/NEW/src/JdeScoping.Api/Controllers/FileIOController.WorkOrders.cs
+++ b/NEW/src/JdeScoping.Api/Controllers/FileIOController.WorkOrders.cs
@@ -14,6 +14,9 @@ public partial class FileIOController
///
/// Uploads an Excel file containing work order numbers and returns the matched work orders
///
+ /// The Excel file to upload.
+ /// Cancellation token.
+ /// Result containing parsed work orders.
[HttpPost("workorders/upload")]
[ProducesResponseType(typeof(FileUploadResult), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(FileUploadResult), StatusCodes.Status400BadRequest)]
@@ -63,6 +66,8 @@ public partial class FileIOController
///
/// Downloads an Excel template with current work order data
///
+ /// Optional list of work order numbers to include in template.
+ /// Excel file.
[HttpPost("workorders/download")]
[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]
public IActionResult DownloadWorkOrders([FromBody] List? workOrders)
diff --git a/NEW/src/JdeScoping.Api/Controllers/FileIOController.cs b/NEW/src/JdeScoping.Api/Controllers/FileIOController.cs
index 3fd3cbf..fab54ba 100644
--- a/NEW/src/JdeScoping.Api/Controllers/FileIOController.cs
+++ b/NEW/src/JdeScoping.Api/Controllers/FileIOController.cs
@@ -21,6 +21,13 @@ public partial class FileIOController : ApiControllerBase
private readonly IExcelTemplateService _templateService;
private readonly ILogger _logger;
+ ///
+ /// Initializes a new instance of the FileIOController class.
+ ///
+ /// Repository for accessing lot finder data.
+ /// Service for parsing Excel files.
+ /// Service for generating Excel templates.
+ /// Logger for controller operations.
public FileIOController(
ILotFinderRepository repository,
IExcelParserService parserService,
diff --git a/NEW/src/JdeScoping.Api/Controllers/LookupController.cs b/NEW/src/JdeScoping.Api/Controllers/LookupController.cs
index e33a9f3..152607f 100644
--- a/NEW/src/JdeScoping.Api/Controllers/LookupController.cs
+++ b/NEW/src/JdeScoping.Api/Controllers/LookupController.cs
@@ -15,6 +15,10 @@ public class LookupController : ApiControllerBase
{
private readonly ILotFinderRepository _repository;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The LotFinder repository for data access.
public LookupController(ILotFinderRepository repository)
{
_repository = repository;
diff --git a/NEW/src/JdeScoping.Api/Controllers/PipelineController.cs b/NEW/src/JdeScoping.Api/Controllers/PipelineController.cs
index 84953da..45a0986 100644
--- a/NEW/src/JdeScoping.Api/Controllers/PipelineController.cs
+++ b/NEW/src/JdeScoping.Api/Controllers/PipelineController.cs
@@ -20,6 +20,12 @@ public class PipelineController : ApiControllerBase
private readonly IDataUpdateRepository _dataUpdateRepository;
private readonly IPipelineMapper _mapper;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The ETL pipeline factory.
+ /// The data update repository.
+ /// The pipeline mapper.
public PipelineController(
IEtlPipelineFactory pipelineFactory,
IDataUpdateRepository dataUpdateRepository,
@@ -45,6 +51,7 @@ public class PipelineController : ApiControllerBase
///
/// Gets configuration for a specific pipeline.
///
+ /// The pipeline name.
[HttpGet(ApiRoutes.Pipelines.ByName)]
public ActionResult GetPipeline(string name)
{
@@ -60,6 +67,8 @@ public class PipelineController : ApiControllerBase
///
/// Gets schedule status for a pipeline.
///
+ /// The pipeline name.
+ /// The cancellation token.
[HttpGet(ApiRoutes.Pipelines.Status)]
public async Task> GetStatus(
string name,
@@ -104,6 +113,9 @@ public class PipelineController : ApiControllerBase
///
/// Gets recent execution history for a pipeline.
///
+ /// The pipeline name.
+ /// The maximum number of recent executions to retrieve.
+ /// The cancellation token.
[HttpGet(ApiRoutes.Pipelines.Executions)]
public async Task> GetExecutions(
string name,
diff --git a/NEW/src/JdeScoping.Api/Controllers/RefreshStatusController.cs b/NEW/src/JdeScoping.Api/Controllers/RefreshStatusController.cs
index 58b8fbf..ec6a476 100644
--- a/NEW/src/JdeScoping.Api/Controllers/RefreshStatusController.cs
+++ b/NEW/src/JdeScoping.Api/Controllers/RefreshStatusController.cs
@@ -17,6 +17,10 @@ public class RefreshStatusController : ApiControllerBase
{
private readonly ILotFinderRepository _repository;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The repository for accessing data update records.
public RefreshStatusController(ILotFinderRepository repository)
{
_repository = repository;
diff --git a/NEW/src/JdeScoping.Api/Controllers/SearchController.cs b/NEW/src/JdeScoping.Api/Controllers/SearchController.cs
index b24fc21..063b5f6 100644
--- a/NEW/src/JdeScoping.Api/Controllers/SearchController.cs
+++ b/NEW/src/JdeScoping.Api/Controllers/SearchController.cs
@@ -26,6 +26,13 @@ public class SearchController : ApiControllerBase
private readonly ILogger _logger;
private readonly TimeProvider _timeProvider;
+ ///
+ /// Initializes a new instance of the SearchController.
+ ///
+ /// The lot finder repository for data access.
+ /// The SignalR hub context for sending search updates.
+ /// The logger for recording search operations.
+ /// The time provider for generating timestamps.
public SearchController(
ILotFinderRepository repository,
IHubContext hubContext,
@@ -41,6 +48,7 @@ public class SearchController : ApiControllerBase
///
/// Gets all searches for the current user
///
+ /// The cancellation token.
[HttpGet]
[ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
@@ -59,6 +67,7 @@ public class SearchController : ApiControllerBase
///
/// Gets all queued searches
///
+ /// The cancellation token.
[HttpGet("queue")]
[ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)]
public async Task>> GetQueuedSearches(CancellationToken ct)
@@ -71,6 +80,8 @@ public class SearchController : ApiControllerBase
///
/// Gets a single search by ID
///
+ /// The search identifier.
+ /// The cancellation token.
[HttpGet("{id:int}")]
[ProducesResponseType(typeof(SearchViewModel), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
@@ -87,6 +98,8 @@ public class SearchController : ApiControllerBase
///
/// Copies an existing search for the current user (returns copy without persisting)
///
+ /// The search identifier to copy.
+ /// The cancellation token.
[HttpGet("{id:int}/copy")]
[ProducesResponseType(typeof(SearchViewModel), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
@@ -121,6 +134,8 @@ public class SearchController : ApiControllerBase
///
/// Creates a new search
///
+ /// The search view model containing criteria and name.
+ /// The cancellation token.
[HttpPost]
[ProducesResponseType(typeof(int), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
@@ -160,6 +175,8 @@ public class SearchController : ApiControllerBase
///
/// Downloads search results as an Excel file
///
+ /// The search identifier.
+ /// The cancellation token.
[HttpGet("{id:int}/results")]
[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
diff --git a/NEW/src/JdeScoping.Api/Hubs/StatusHub.cs b/NEW/src/JdeScoping.Api/Hubs/StatusHub.cs
index e04dfd6..85190c6 100644
--- a/NEW/src/JdeScoping.Api/Hubs/StatusHub.cs
+++ b/NEW/src/JdeScoping.Api/Hubs/StatusHub.cs
@@ -16,6 +16,12 @@ public class StatusHub : Hub
private readonly ILogger _logger;
private readonly TimeProvider _timeProvider;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The memory cache for caching status updates.
+ /// The logger instance.
+ /// The time provider for getting current UTC time.
public StatusHub(IMemoryCache cache, ILogger logger, TimeProvider timeProvider)
{
_cache = cache;
diff --git a/NEW/src/JdeScoping.Api/Mapping/IPipelineMapper.cs b/NEW/src/JdeScoping.Api/Mapping/IPipelineMapper.cs
index f3ac304..202e017 100644
--- a/NEW/src/JdeScoping.Api/Mapping/IPipelineMapper.cs
+++ b/NEW/src/JdeScoping.Api/Mapping/IPipelineMapper.cs
@@ -12,15 +12,23 @@ public interface IPipelineMapper
///
/// Maps a pipeline configuration to its DTO representation.
///
+ /// The pipeline name.
+ /// The pipeline configuration.
+ /// The default schedule settings.
PipelineConfigDto MapToDto(string name, PipelineConfig config, ScheduleDefaults defaults);
///
/// Gets the effective interval for a schedule, applying defaults if not specified.
///
+ /// The schedule configuration, or null to use defaults.
+ /// The default schedule settings.
+ /// The type of update to get the interval for.
int GetEffectiveInterval(ScheduleConfig? config, ScheduleDefaults defaults, UpdateTypes updateType);
///
/// Gets the schedule configuration for a specific update type.
///
+ /// The pipeline configuration.
+ /// The type of update to get the configuration for.
ScheduleConfig? GetScheduleConfig(PipelineConfig config, UpdateTypes updateType);
}
diff --git a/NEW/src/JdeScoping.Client/Auth/AuthStateProvider.cs b/NEW/src/JdeScoping.Client/Auth/AuthStateProvider.cs
index d6049d3..7b12864 100644
--- a/NEW/src/JdeScoping.Client/Auth/AuthStateProvider.cs
+++ b/NEW/src/JdeScoping.Client/Auth/AuthStateProvider.cs
@@ -18,6 +18,12 @@ public class AuthStateProvider : AuthenticationStateProvider, IAuthStateProvider
private readonly ILogger? _logger;
private readonly ClaimsPrincipal _anonymous = new(new ClaimsIdentity());
+ ///
+ /// Initializes a new instance of the AuthStateProvider class.
+ ///
+ /// Service for storing user authentication data.
+ /// The HTTP client for making API requests.
+ /// Optional logger for debugging authentication issues.
public AuthStateProvider(
IUserStorageService userStorage,
HttpClient httpClient,
@@ -28,6 +34,7 @@ public class AuthStateProvider : AuthenticationStateProvider, IAuthStateProvider
_logger = logger;
}
+ ///
public override async Task GetAuthenticationStateAsync()
{
// First check cached user info
@@ -93,6 +100,7 @@ public class AuthStateProvider : AuthenticationStateProvider, IAuthStateProvider
///
/// Called after successful login to update auth state.
///
+ /// The authenticated user information.
public async Task MarkUserAsAuthenticated(UserInfoDto user)
{
await _userStorage.SetUserAsync(user);
diff --git a/NEW/src/JdeScoping.Client/Auth/IUserStorageService.cs b/NEW/src/JdeScoping.Client/Auth/IUserStorageService.cs
index 2eaa4e0..3d071d9 100644
--- a/NEW/src/JdeScoping.Client/Auth/IUserStorageService.cs
+++ b/NEW/src/JdeScoping.Client/Auth/IUserStorageService.cs
@@ -17,6 +17,7 @@ public interface IUserStorageService
///
/// Stores the user info.
///
+ /// The user information to store.
Task SetUserAsync(UserInfoDto user);
///
diff --git a/NEW/src/JdeScoping.Client/Auth/UserStorageService.cs b/NEW/src/JdeScoping.Client/Auth/UserStorageService.cs
index e365ba3..c57f652 100644
--- a/NEW/src/JdeScoping.Client/Auth/UserStorageService.cs
+++ b/NEW/src/JdeScoping.Client/Auth/UserStorageService.cs
@@ -14,11 +14,19 @@ public class UserStorageService : IUserStorageService
private const string UserKey = "jdescoping_user";
private readonly IJSRuntime _jsRuntime;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The JS interop runtime for accessing browser storage.
public UserStorageService(IJSRuntime jsRuntime)
{
_jsRuntime = jsRuntime;
}
+ ///
+ /// Retrieves the stored user information from browser session storage.
+ ///
+ /// A task that completes with the user information, or null if not found.
public async Task GetUserAsync()
{
try
@@ -40,12 +48,21 @@ public class UserStorageService : IUserStorageService
}
}
+ ///
+ /// Stores user information in browser session storage.
+ ///
+ /// The user information to store.
+ /// A task that completes when the user information is stored.
public async Task SetUserAsync(UserInfoDto user)
{
var json = JsonSerializer.Serialize(user);
await _jsRuntime.InvokeVoidAsync("jdeScopingInterop.setSessionStorage", UserKey, json);
}
+ ///
+ /// Removes the stored user information from browser session storage.
+ ///
+ /// A task that completes when the user information is removed.
public async Task RemoveUserAsync()
{
await _jsRuntime.InvokeVoidAsync("jdeScopingInterop.removeSessionStorage", UserKey);
diff --git a/NEW/src/JdeScoping.Client/Components/FilterPanels/AutocompleteFilterPanelBase.cs b/NEW/src/JdeScoping.Client/Components/FilterPanels/AutocompleteFilterPanelBase.cs
index 41ff237..6c8ed01 100644
--- a/NEW/src/JdeScoping.Client/Components/FilterPanels/AutocompleteFilterPanelBase.cs
+++ b/NEW/src/JdeScoping.Client/Components/FilterPanels/AutocompleteFilterPanelBase.cs
@@ -9,6 +9,9 @@ namespace JdeScoping.Client.Components.FilterPanels;
/// The type of items displayed in the grid.
public abstract class AutocompleteFilterPanelBase : ComponentBase where TItem : class
{
+ ///
+ /// Gets or sets the Radzen dialog service for confirming user actions.
+ ///
[Inject]
protected DialogService DialogService { get; set; } = default!;
@@ -73,21 +76,29 @@ public abstract class AutocompleteFilterPanelBase : ComponentBase where T
///
/// Performs the search API call and returns matching items.
///
+ /// The search filter text.
+ /// A task that returns the list of matching items.
protected abstract Task> SearchApiAsync(string filter);
///
/// Gets the unique key value for an item.
///
+ /// The item to get the key for.
+ /// The unique key value.
protected abstract object GetItemKey(TItem item);
///
/// Gets the display text value for an item (used for matching in autocomplete).
///
+ /// The item to get the display text for.
+ /// The display text value.
protected abstract string GetDisplayText(TItem item);
///
/// Handles the autocomplete search.
///
+ /// The load data arguments containing the search filter.
+ /// A task representing the asynchronous search operation.
protected async Task OnSearchAsync(LoadDataArgs args)
{
if (!string.IsNullOrEmpty(args.Filter) && args.Filter.Length >= 3)
@@ -103,6 +114,7 @@ public abstract class AutocompleteFilterPanelBase : ComponentBase where T
///
/// Handles selection from the autocomplete.
///
+ /// The selected value from the autocomplete control.
protected void OnItemSelected(object value)
{
if (value is string text && !string.IsNullOrEmpty(text))
@@ -138,6 +150,8 @@ public abstract class AutocompleteFilterPanelBase : ComponentBase where T
///
/// Removes an item from the list.
///
+ /// The item to remove.
+ /// A task representing the asynchronous operation.
protected async Task DeleteItem(TItem item)
{
Items.Remove(item);
diff --git a/NEW/src/JdeScoping.Client/Components/FilterPanels/FileUploadFilterPanelBase.cs b/NEW/src/JdeScoping.Client/Components/FilterPanels/FileUploadFilterPanelBase.cs
index 735d7d8..6611895 100644
--- a/NEW/src/JdeScoping.Client/Components/FilterPanels/FileUploadFilterPanelBase.cs
+++ b/NEW/src/JdeScoping.Client/Components/FilterPanels/FileUploadFilterPanelBase.cs
@@ -11,12 +11,15 @@ namespace JdeScoping.Client.Components.FilterPanels;
/// The type of items displayed in the grid.
public abstract class FileUploadFilterPanelBase : ComponentBase where TItem : class
{
+ /// Service for managing dialogs.
[Inject]
protected DialogService DialogService { get; set; } = default!;
+ /// Service for displaying notifications.
[Inject]
protected NotificationService NotificationService { get; set; } = default!;
+ /// JavaScript interop runtime.
[Inject]
protected IJSRuntime JSRuntime { get; set; } = default!;
@@ -81,6 +84,8 @@ public abstract class FileUploadFilterPanelBase : ComponentBase where TIt
///
/// Uploads the file and returns the parsed items.
///
+ /// The file stream to upload.
+ /// The name of the file being uploaded.
protected abstract Task?> UploadFileApiAsync(Stream stream, string filename);
///
@@ -106,6 +111,7 @@ public abstract class FileUploadFilterPanelBase : ComponentBase where TIt
///
/// Handles file selection and upload.
///
+ /// The file change event arguments.
protected async Task OnFileSelected(InputFileChangeEventArgs e)
{
if (e.File == null) return;
diff --git a/NEW/src/JdeScoping.Client/Extensions/ViewModelMappingExtensions.cs b/NEW/src/JdeScoping.Client/Extensions/ViewModelMappingExtensions.cs
index 07fcb99..cece621 100644
--- a/NEW/src/JdeScoping.Client/Extensions/ViewModelMappingExtensions.cs
+++ b/NEW/src/JdeScoping.Client/Extensions/ViewModelMappingExtensions.cs
@@ -22,6 +22,7 @@ public static class ViewModelMappingExtensions
///
/// Maps Core SearchViewModel to Client SearchViewModel.
///
+ /// The Core SearchViewModel to map.
public static SearchViewModel ToClient(this CoreSearch vm) => new()
{
Id = vm.Id,
@@ -37,6 +38,7 @@ public static class ViewModelMappingExtensions
///
/// Maps Client SearchViewModel to Core SearchViewModel.
///
+ /// The Client SearchViewModel to map.
public static CoreSearch ToCore(this SearchViewModel vm)
{
ArgumentNullException.ThrowIfNull(vm);
@@ -58,6 +60,7 @@ public static class ViewModelMappingExtensions
/// Maps Core SearchCriteria to Client SearchCriteriaViewModel.
/// Core uses primitive lists; Client uses full view model objects.
///
+ /// The Core SearchCriteria to map.
public static SearchCriteriaViewModel ToClientCriteria(this SearchCriteria criteria)
{
var client = new SearchCriteriaViewModel
@@ -107,6 +110,7 @@ public static class ViewModelMappingExtensions
/// Maps Client SearchCriteriaViewModel to Core SearchCriteria.
/// Client uses full view model objects; Core uses primitive lists.
///
+ /// The Client SearchCriteriaViewModel to map.
public static SearchCriteria ToCoreCriteria(this SearchCriteriaViewModel criteria)
{
ArgumentNullException.ThrowIfNull(criteria);
@@ -131,6 +135,7 @@ public static class ViewModelMappingExtensions
///
/// Maps Core JdeUserViewModel to Client OperatorViewModel.
///
+ /// The Core JdeUserViewModel to map.
public static OperatorViewModel ToClientOperator(this CoreJdeUser vm) => new()
{
AddressNumber = vm.AddressNumber,
@@ -141,6 +146,7 @@ public static class ViewModelMappingExtensions
///
/// Maps a collection of Core SearchViewModels to Client SearchViewModels.
///
+ /// The collection of Core SearchViewModels to map.
public static List ToClientList(this IEnumerable list)
{
ArgumentNullException.ThrowIfNull(list);
@@ -150,6 +156,7 @@ public static class ViewModelMappingExtensions
///
/// Maps a collection of Core JdeUserViewModels to Client OperatorViewModels.
///
+ /// The collection of Core JdeUserViewModels to map.
public static List ToClientOperatorList(this IEnumerable list)
{
ArgumentNullException.ThrowIfNull(list);
diff --git a/NEW/src/JdeScoping.Client/Http/AuthRedirectHandler.cs b/NEW/src/JdeScoping.Client/Http/AuthRedirectHandler.cs
index 2731dad..c63b59f 100644
--- a/NEW/src/JdeScoping.Client/Http/AuthRedirectHandler.cs
+++ b/NEW/src/JdeScoping.Client/Http/AuthRedirectHandler.cs
@@ -11,11 +11,16 @@ public class AuthRedirectHandler : DelegatingHandler
{
private readonly NavigationManager _navigationManager;
+ ///
+ /// Initializes a new instance of the AuthRedirectHandler class.
+ ///
+ /// The navigation manager for redirecting to login.
public AuthRedirectHandler(NavigationManager navigationManager)
{
_navigationManager = navigationManager;
}
+ ///
protected override async Task SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
diff --git a/NEW/src/JdeScoping.Client/Models/SearchCriteriaViewModel.cs b/NEW/src/JdeScoping.Client/Models/SearchCriteriaViewModel.cs
index 2e926f8..49b586a 100644
--- a/NEW/src/JdeScoping.Client/Models/SearchCriteriaViewModel.cs
+++ b/NEW/src/JdeScoping.Client/Models/SearchCriteriaViewModel.cs
@@ -7,16 +7,53 @@ namespace JdeScoping.Client.Models;
///
public class SearchCriteriaViewModel
{
+ ///
+ /// Gets or sets the minimum date for search filtering.
+ ///
public DateTime? MinimumDt { get; set; }
+
+ ///
+ /// Gets or sets the maximum date for search filtering.
+ ///
public DateTime? MaximumDt { get; set; }
+ ///
+ /// Gets or sets the list of work orders to include in the search.
+ ///
public List WorkOrders { get; set; } = [];
+
+ ///
+ /// Gets or sets the list of items to include in the search.
+ ///
public List Items { get; set; } = [];
+
+ ///
+ /// Gets or sets the list of profit centers to include in the search.
+ ///
public List ProfitCenters { get; set; } = [];
+
+ ///
+ /// Gets or sets the list of work centers to include in the search.
+ ///
public List WorkCenters { get; set; } = [];
+
+ ///
+ /// Gets or sets the list of component lots to include in the search.
+ ///
public List ComponentLots { get; set; } = [];
+
+ ///
+ /// Gets or sets the list of operators to include in the search.
+ ///
public List Operators { get; set; } = [];
+
+ ///
+ /// Gets or sets the list of part operations to include in the search.
+ ///
public List PartOperations { get; set; } = [];
+ ///
+ /// Gets or sets a value indicating whether to extract MIS data in the search.
+ ///
public bool ExtractMisData { get; set; }
}
diff --git a/NEW/src/JdeScoping.Client/Models/SearchViewModel.cs b/NEW/src/JdeScoping.Client/Models/SearchViewModel.cs
index 1375469..eaddd62 100644
--- a/NEW/src/JdeScoping.Client/Models/SearchViewModel.cs
+++ b/NEW/src/JdeScoping.Client/Models/SearchViewModel.cs
@@ -7,15 +7,45 @@ namespace JdeScoping.Client.Models;
///
public class SearchViewModel
{
+ ///
+ /// Gets or sets the unique identifier for the search.
+ ///
public int Id { get; set; }
+ ///
+ /// Gets or sets the name of the search.
+ ///
[Required(ErrorMessage = "Name is required.")]
public string Name { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the username of the user who created the search.
+ ///
public string UserName { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the current status of the search.
+ ///
public string Status { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the date and time when the search was submitted.
+ ///
public DateTime? SubmitDt { get; set; }
+
+ ///
+ /// Gets or sets the date and time when the search execution started.
+ ///
public DateTime? StartDt { get; set; }
+
+ ///
+ /// Gets or sets the date and time when the search execution ended.
+ ///
public DateTime? EndDt { get; set; }
+
+ ///
+ /// Gets or sets the search criteria for filtering.
+ ///
public SearchCriteriaViewModel Criteria { get; set; } = new();
///
diff --git a/NEW/src/JdeScoping.Client/Models/ValidCombination.cs b/NEW/src/JdeScoping.Client/Models/ValidCombination.cs
index b5bb4b9..1891fb9 100644
--- a/NEW/src/JdeScoping.Client/Models/ValidCombination.cs
+++ b/NEW/src/JdeScoping.Client/Models/ValidCombination.cs
@@ -6,21 +6,74 @@ namespace JdeScoping.Client.Models;
///
public class ValidCombination
{
+ ///
+ /// The unique identifier for this combination.
+ ///
public int Id { get; private init; }
+
+ ///
+ /// The display name for this combination.
+ ///
public string Name { get; private init; } = string.Empty;
+
+ ///
+ /// Whether the timespan filter is included in this combination.
+ ///
public bool Timespan { get; private init; }
+
+ ///
+ /// Whether the work order filter is included in this combination.
+ ///
public bool WorkOrder { get; private init; }
+
+ ///
+ /// Whether the item number filter is included in this combination.
+ ///
public bool ItemNumber { get; private init; }
+
+ ///
+ /// Whether the profit center filter is included in this combination.
+ ///
public bool ProfitCenter { get; private init; }
+
+ ///
+ /// Whether the work center filter is included in this combination.
+ ///
public bool WorkCenter { get; private init; }
+
+ ///
+ /// Whether the component lot filter is included in this combination.
+ ///
public bool ComponentLot { get; private init; }
+
+ ///
+ /// Whether the operator filter is included in this combination.
+ ///
public bool Operator { get; private init; }
+
+ ///
+ /// Whether the item operation MIS filter is included in this combination.
+ ///
public bool ItemOperationMis { get; private init; }
+
+ ///
+ /// Whether the extract MIS filter is included in this combination.
+ ///
public bool ExtractMis { get; private init; }
///
/// Checks if the given filter flags match this combination.
///
+ /// Whether timespan filter is enabled.
+ /// Whether work order filter is enabled.
+ /// Whether item number filter is enabled.
+ /// Whether profit center filter is enabled.
+ /// Whether work center filter is enabled.
+ /// Whether component lot filter is enabled.
+ /// Whether operator filter is enabled.
+ /// Whether item operation MIS filter is enabled.
+ /// Whether extract MIS filter is enabled.
+ /// True if all flags match this combination.
public bool Matches(
bool timespan,
bool workOrder,
diff --git a/NEW/src/JdeScoping.Client/Services/ApiClientBase.cs b/NEW/src/JdeScoping.Client/Services/ApiClientBase.cs
index ca1eba7..5df550b 100644
--- a/NEW/src/JdeScoping.Client/Services/ApiClientBase.cs
+++ b/NEW/src/JdeScoping.Client/Services/ApiClientBase.cs
@@ -17,26 +17,55 @@ public abstract class ApiClientBase
PropertyNameCaseInsensitive = true
};
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The HTTP client to use for requests.
protected ApiClientBase(HttpClient httpClient)
{
HttpClient = httpClient;
}
+ ///
+ /// Executes a GET request and deserializes the response to the specified type.
+ ///
+ /// The response type.
+ /// The API route.
+ /// Cancellation token.
protected async Task> GetAsync(string route, CancellationToken ct = default)
{
return await ExecuteAsync(() => HttpClient.GetAsync(route, ct));
}
+ ///
+ /// Executes a POST request with a JSON body.
+ ///
+ /// The response type.
+ /// The request body type.
+ /// The API route.
+ /// The request body.
+ /// Cancellation token.
protected async Task> PostAsync(string route, TBody body, CancellationToken ct = default)
{
return await ExecuteAsync(() => HttpClient.PostAsJsonAsync(route, body, ct));
}
+ ///
+ /// Executes a POST request without a body.
+ ///
+ /// The response type.
+ /// The API route.
+ /// Cancellation token.
protected async Task> PostAsync(string route, CancellationToken ct = default)
{
return await ExecuteAsync(() => HttpClient.PostAsync(route, null, ct));
}
+ ///
+ /// Executes a GET request and returns the response as raw bytes.
+ ///
+ /// The API route.
+ /// Cancellation token.
protected async Task> GetBytesAsync(string route, CancellationToken ct = default)
{
try
@@ -50,6 +79,13 @@ public abstract class ApiClientBase
}
}
+ ///
+ /// Executes a POST request with a JSON body and returns the response as raw bytes.
+ ///
+ /// The request body type.
+ /// The API route.
+ /// The request body.
+ /// Cancellation token.
protected async Task> PostForBytesAsync(string route, TBody body, CancellationToken ct = default)
{
try
@@ -63,6 +99,14 @@ public abstract class ApiClientBase
}
}
+ ///
+ /// Executes a multipart POST request with a file stream.
+ ///
+ /// The response type.
+ /// The API route.
+ /// The file stream to upload.
+ /// The file name for the multipart form.
+ /// Cancellation token.
protected async Task> PostMultipartAsync(
string route,
Stream fileStream,
@@ -161,6 +205,9 @@ public abstract class ApiClientBase
///
private sealed class ValidationProblemDetails
{
+ ///
+ /// Gets or sets the validation errors by field name.
+ ///
public Dictionary? Errors { get; set; }
}
}
diff --git a/NEW/src/JdeScoping.Client/Services/AuthApiClient.cs b/NEW/src/JdeScoping.Client/Services/AuthApiClient.cs
index 63dc5cf..8f113fb 100644
--- a/NEW/src/JdeScoping.Client/Services/AuthApiClient.cs
+++ b/NEW/src/JdeScoping.Client/Services/AuthApiClient.cs
@@ -9,17 +9,42 @@ namespace JdeScoping.Client.Services;
///
public class AuthApiClient : ApiClientBase, IAuthApiClient
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The HTTP client for API requests.
public AuthApiClient(HttpClient httpClient) : base(httpClient) { }
+ ///
+ /// Retrieves the server's RSA public key for credential encryption.
+ ///
+ /// Cancellation token.
+ /// The public key response.
public Task> GetPublicKeyAsync(CancellationToken ct = default)
=> GetAsync(ApiRoutes.Auth.PublicKey, ct);
+ ///
+ /// Authenticates a user with encrypted credentials.
+ ///
+ /// The encrypted login request.
+ /// Cancellation token.
+ /// The login result with user info on success.
public Task> LoginAsync(EncryptedLoginRequest request, CancellationToken ct = default)
=> PostAsync(ApiRoutes.Auth.Login, request, ct);
+ ///
+ /// Logs out the current user.
+ ///
+ /// Cancellation token.
+ /// Result of logout operation.
public Task> LogoutAsync(CancellationToken ct = default)
=> PostAsync(ApiRoutes.Auth.Logout, ct);
+ ///
+ /// Retrieves information about the current authenticated user.
+ ///
+ /// Cancellation token.
+ /// The current user's information.
public Task> GetCurrentUserAsync(CancellationToken ct = default)
=> GetAsync(ApiRoutes.Auth.Me, ct);
}
diff --git a/NEW/src/JdeScoping.Client/Services/AuthService.cs b/NEW/src/JdeScoping.Client/Services/AuthService.cs
index 26fbc63..00c838a 100644
--- a/NEW/src/JdeScoping.Client/Services/AuthService.cs
+++ b/NEW/src/JdeScoping.Client/Services/AuthService.cs
@@ -13,6 +13,12 @@ public class AuthService : IAuthService
private readonly ICryptoService _cryptoService;
private readonly IAuthStateProvider _authStateProvider;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The HTTP client for API communication.
+ /// The cryptography service.
+ /// The authentication state provider.
public AuthService(
HttpClient httpClient,
ICryptoService cryptoService,
@@ -23,6 +29,11 @@ public class AuthService : IAuthService
_authStateProvider = authStateProvider;
}
+ ///
+ /// Authenticates a user with encrypted credentials.
+ ///
+ /// The login credentials.
+ /// The login result with user information if successful.
public async Task LoginAsync(LoginModel model)
{
try
@@ -54,6 +65,9 @@ public class AuthService : IAuthService
}
}
+ ///
+ /// Logs out the current user and clears authentication state.
+ ///
public async Task LogoutAsync()
{
try
diff --git a/NEW/src/JdeScoping.Client/Services/CryptoService.cs b/NEW/src/JdeScoping.Client/Services/CryptoService.cs
index 3b6bd90..f73f151 100644
--- a/NEW/src/JdeScoping.Client/Services/CryptoService.cs
+++ b/NEW/src/JdeScoping.Client/Services/CryptoService.cs
@@ -17,6 +17,11 @@ public class CryptoService : ICryptoService, IAsyncDisposable
private readonly SemaphoreSlim _keyLock = new(1, 1);
private bool _disposed;
+ ///
+ /// Initializes a new instance of the CryptoService.
+ ///
+ /// The HTTP client for fetching the public key from the server.
+ /// The JavaScript runtime for performing RSA encryption.
public CryptoService(HttpClient httpClient, IJSRuntime jsRuntime)
{
_httpClient = httpClient;
diff --git a/NEW/src/JdeScoping.Client/Services/FileApiClient.cs b/NEW/src/JdeScoping.Client/Services/FileApiClient.cs
index 58c371e..17b0ff2 100644
--- a/NEW/src/JdeScoping.Client/Services/FileApiClient.cs
+++ b/NEW/src/JdeScoping.Client/Services/FileApiClient.cs
@@ -9,33 +9,89 @@ namespace JdeScoping.Client.Services;
///
public class FileApiClient : ApiClientBase, IFileApiClient
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The HTTP client for API requests.
public FileApiClient(HttpClient httpClient) : base(httpClient) { }
// Downloads
+ ///
+ /// Downloads an Excel template with optional existing work order data.
+ ///
+ /// Optional list of existing work orders to include.
+ /// Cancellation token.
+ /// The Excel file bytes.
public Task> DownloadWorkOrdersTemplateAsync(IReadOnlyList? existingData = null, CancellationToken ct = default)
=> PostForBytesAsync(ApiRoutes.FileIO.DownloadWorkOrders, existingData, ct);
+ ///
+ /// Downloads an Excel template with optional existing item data.
+ ///
+ /// Optional list of existing items to include.
+ /// Cancellation token.
+ /// The Excel file bytes.
public Task> DownloadItemsTemplateAsync(IReadOnlyList? existingData = null, CancellationToken ct = default)
=> PostForBytesAsync(ApiRoutes.FileIO.DownloadItems, existingData, ct);
+ ///
+ /// Downloads an Excel template with optional existing component lot data.
+ ///
+ /// Optional list of existing lots to include.
+ /// Cancellation token.
+ /// The Excel file bytes.
public Task> DownloadComponentLotsTemplateAsync(IReadOnlyList? existingData = null, CancellationToken ct = default)
=> PostForBytesAsync(ApiRoutes.FileIO.DownloadComponentLots, existingData, ct);
+ ///
+ /// Downloads an Excel template with optional existing part operation data.
+ ///
+ /// Optional list of existing part operations to include.
+ /// Cancellation token.
+ /// The Excel file bytes.
public Task> DownloadPartOperationsTemplateAsync(IReadOnlyList? existingData = null, CancellationToken ct = default)
=> PostForBytesAsync(ApiRoutes.FileIO.DownloadPartOperations, existingData, ct);
// Uploads
+ ///
+ /// Uploads and parses an Excel file containing work orders.
+ ///
+ /// The file stream to upload.
+ /// The original file name.
+ /// Cancellation token.
+ /// List of parsed work order view models.
public Task>> UploadWorkOrdersAsync(Stream fileStream, string fileName, CancellationToken ct = default)
=> PostMultipartAsync>(ApiRoutes.FileIO.UploadWorkOrders, fileStream, fileName, ct);
+ ///
+ /// Uploads and parses an Excel file containing items.
+ ///
+ /// The file stream to upload.
+ /// The original file name.
+ /// Cancellation token.
+ /// List of parsed item view models.
public Task>> UploadItemsAsync(Stream fileStream, string fileName, CancellationToken ct = default)
=> PostMultipartAsync>(ApiRoutes.FileIO.UploadItems, fileStream, fileName, ct);
+ ///
+ /// Uploads and parses an Excel file containing component lots.
+ ///
+ /// The file stream to upload.
+ /// The original file name.
+ /// Cancellation token.
+ /// List of parsed lot view models.
public Task>> UploadComponentLotsAsync(Stream fileStream, string fileName, CancellationToken ct = default)
=> PostMultipartAsync>(ApiRoutes.FileIO.UploadComponentLots, fileStream, fileName, ct);
+ ///
+ /// Uploads and parses an Excel file containing part operations.
+ ///
+ /// The file stream to upload.
+ /// The original file name.
+ /// Cancellation token.
+ /// List of parsed part operation view models.
public Task>> UploadPartOperationsAsync(Stream fileStream, string fileName, CancellationToken ct = default)
=> PostMultipartAsync>(ApiRoutes.FileIO.UploadPartOperations, fileStream, fileName, ct);
}
diff --git a/NEW/src/JdeScoping.Client/Services/HubConnectionService.cs b/NEW/src/JdeScoping.Client/Services/HubConnectionService.cs
index e96e2e6..1ce954d 100644
--- a/NEW/src/JdeScoping.Client/Services/HubConnectionService.cs
+++ b/NEW/src/JdeScoping.Client/Services/HubConnectionService.cs
@@ -13,16 +13,33 @@ public class HubConnectionService : IHubConnectionService, IAsyncDisposable
private readonly NavigationManager _navigationManager;
private HubConnection? _hubConnection;
+ ///
+ /// Raised when a search is updated.
+ ///
public event Action? OnSearchUpdate;
+
+ ///
+ /// Raised when a status update is received.
+ ///
public event Action? OnStatusUpdate;
+ ///
+ /// Gets a value indicating whether the SignalR connection is active.
+ ///
public bool IsConnected => _hubConnection?.State == HubConnectionState.Connected;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The navigation manager for resolving hub URL.
public HubConnectionService(NavigationManager navigationManager)
{
_navigationManager = navigationManager;
}
+ ///
+ /// Establishes the SignalR connection and registers message handlers.
+ ///
public async Task StartAsync()
{
if (_hubConnection != null)
@@ -82,6 +99,9 @@ public class HubConnectionService : IHubConnectionService, IAsyncDisposable
}
}
+ ///
+ /// Stops the SignalR connection.
+ ///
public async Task StopAsync()
{
if (_hubConnection != null)
@@ -92,6 +112,10 @@ public class HubConnectionService : IHubConnectionService, IAsyncDisposable
}
}
+ ///
+ /// Retrieves the most recent status update from the server cache.
+ ///
+ /// The cached status update, or null if not available.
public async Task GetCachedStatusAsync()
{
if (_hubConnection == null || _hubConnection.State != HubConnectionState.Connected)
@@ -110,6 +134,9 @@ public class HubConnectionService : IHubConnectionService, IAsyncDisposable
}
}
+ ///
+ /// Releases the resources used by the service.
+ ///
public async ValueTask DisposeAsync()
{
await StopAsync();
diff --git a/NEW/src/JdeScoping.Client/Services/IAuthService.cs b/NEW/src/JdeScoping.Client/Services/IAuthService.cs
index 3cfe66a..e9fa70f 100644
--- a/NEW/src/JdeScoping.Client/Services/IAuthService.cs
+++ b/NEW/src/JdeScoping.Client/Services/IAuthService.cs
@@ -10,6 +10,8 @@ public interface IAuthService
///
/// Attempts to log in with the provided credentials (encrypted).
///
+ /// The login credentials.
+ /// The login result containing status and user information.
Task LoginAsync(LoginModel model);
///
diff --git a/NEW/src/JdeScoping.Client/Services/IRefreshStatusService.cs b/NEW/src/JdeScoping.Client/Services/IRefreshStatusService.cs
index ae9e5b6..1129672 100644
--- a/NEW/src/JdeScoping.Client/Services/IRefreshStatusService.cs
+++ b/NEW/src/JdeScoping.Client/Services/IRefreshStatusService.cs
@@ -10,5 +10,8 @@ public interface IRefreshStatusService
///
/// Gets refresh status records within the specified date range.
///
+ /// The minimum date/time (inclusive).
+ /// The maximum date/time (inclusive).
+ /// A list of data update status records.
Task> GetRefreshStatusAsync(DateTime minDt, DateTime maxDt);
}
diff --git a/NEW/src/JdeScoping.Client/Services/ISearchSubmissionService.cs b/NEW/src/JdeScoping.Client/Services/ISearchSubmissionService.cs
index bbf7d76..62dcf91 100644
--- a/NEW/src/JdeScoping.Client/Services/ISearchSubmissionService.cs
+++ b/NEW/src/JdeScoping.Client/Services/ISearchSubmissionService.cs
@@ -38,10 +38,14 @@ public class SearchSubmissionResult
///
/// Creates a successful result.
///
+ /// The ID of the successfully submitted search.
+ /// A successful search submission result.
public static SearchSubmissionResult Success(int searchId) => new() { SearchId = searchId };
///
/// Creates a failure result.
///
+ /// The error message describing the submission failure.
+ /// A failed search submission result.
public static SearchSubmissionResult Failure(string error) => new() { ErrorMessage = error };
}
diff --git a/NEW/src/JdeScoping.Client/Services/LookupApiClient.cs b/NEW/src/JdeScoping.Client/Services/LookupApiClient.cs
index ec50a54..ff5306f 100644
--- a/NEW/src/JdeScoping.Client/Services/LookupApiClient.cs
+++ b/NEW/src/JdeScoping.Client/Services/LookupApiClient.cs
@@ -9,17 +9,45 @@ namespace JdeScoping.Client.Services;
///
public class LookupApiClient : ApiClientBase, ILookupApiClient
{
+ ///
+ /// Initializes a new instance of the LookupApiClient class.
+ ///
+ /// The HTTP client for making API requests.
public LookupApiClient(HttpClient httpClient) : base(httpClient) { }
+ ///
+ /// Finds items matching the search query.
+ ///
+ /// The search query to match against item data.
+ /// Cancellation token.
+ /// An API result containing matching items.
public Task>> FindItemsAsync(string query, CancellationToken ct = default)
=> GetAsync>(ApiRoutes.Lookup.FindItems(query), ct);
+ ///
+ /// Finds profit centers matching the search query.
+ ///
+ /// The search query to match against profit center data.
+ /// Cancellation token.
+ /// An API result containing matching profit centers.
public Task>> FindProfitCentersAsync(string query, CancellationToken ct = default)
=> GetAsync>(ApiRoutes.Lookup.FindProfitCenters(query), ct);
+ ///
+ /// Finds work centers matching the search query.
+ ///
+ /// The search query to match against work center data.
+ /// Cancellation token.
+ /// An API result containing matching work centers.
public Task>> FindWorkCentersAsync(string query, CancellationToken ct = default)
=> GetAsync>(ApiRoutes.Lookup.FindWorkCenters(query), ct);
+ ///
+ /// Finds operators (JDE users) matching the search query.
+ ///
+ /// The search query to match against operator data.
+ /// Cancellation token.
+ /// An API result containing matching operators.
public Task>> FindOperatorsAsync(string query, CancellationToken ct = default)
=> GetAsync>(ApiRoutes.Lookup.FindOperators(query), ct);
}
diff --git a/NEW/src/JdeScoping.Client/Services/PipelineApiClient.cs b/NEW/src/JdeScoping.Client/Services/PipelineApiClient.cs
index 4dccd85..0522333 100644
--- a/NEW/src/JdeScoping.Client/Services/PipelineApiClient.cs
+++ b/NEW/src/JdeScoping.Client/Services/PipelineApiClient.cs
@@ -9,17 +9,45 @@ namespace JdeScoping.Client.Services;
///
public class PipelineApiClient : ApiClientBase, IPipelineApiClient
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The HTTP client for API communication.
public PipelineApiClient(HttpClient httpClient) : base(httpClient) { }
+ ///
+ /// Gets the list of available pipeline names from the API.
+ ///
+ /// Cancellation token for the request.
+ /// The API result containing the pipeline list.
public Task> GetPipelineNamesAsync(CancellationToken ct = default)
=> GetAsync(ApiRoutes.Pipelines.Base, ct);
+ ///
+ /// Gets the configuration for a specific pipeline by name.
+ ///
+ /// The pipeline name.
+ /// Cancellation token for the request.
+ /// The API result containing the pipeline configuration.
public Task> GetPipelineAsync(string name, CancellationToken ct = default)
=> GetAsync(ApiRoutes.Pipelines.GetByName(name), ct);
+ ///
+ /// Gets the current execution status of a pipeline.
+ ///
+ /// The pipeline name.
+ /// Cancellation token for the request.
+ /// The API result containing the pipeline status.
public Task> GetStatusAsync(string name, CancellationToken ct = default)
=> GetAsync(ApiRoutes.Pipelines.GetStatus(name), ct);
+ ///
+ /// Gets the recent execution history for a pipeline.
+ ///
+ /// The pipeline name.
+ /// The maximum number of execution records to retrieve.
+ /// Cancellation token for the request.
+ /// The API result containing the execution history.
public Task> GetExecutionsAsync(string name, int count = 30, CancellationToken ct = default)
=> GetAsync(ApiRoutes.Pipelines.GetExecutions(name, count), ct);
}
diff --git a/NEW/src/JdeScoping.Client/Services/RefreshStatusService.cs b/NEW/src/JdeScoping.Client/Services/RefreshStatusService.cs
index 61cf94e..5c4b5e8 100644
--- a/NEW/src/JdeScoping.Client/Services/RefreshStatusService.cs
+++ b/NEW/src/JdeScoping.Client/Services/RefreshStatusService.cs
@@ -11,11 +11,21 @@ public class RefreshStatusService : IRefreshStatusService
{
private readonly HttpClient _httpClient;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The HTTP client for API communication.
public RefreshStatusService(HttpClient httpClient)
{
_httpClient = httpClient;
}
+ ///
+ /// Gets the data refresh status for a date range.
+ ///
+ /// The minimum date for the status query.
+ /// The maximum date for the status query.
+ /// A list of data update information for the specified date range.
public async Task> GetRefreshStatusAsync(DateTime minDt, DateTime maxDt)
{
try
diff --git a/NEW/src/JdeScoping.Client/Services/SearchApiClient.cs b/NEW/src/JdeScoping.Client/Services/SearchApiClient.cs
index 258d589..5c54998 100644
--- a/NEW/src/JdeScoping.Client/Services/SearchApiClient.cs
+++ b/NEW/src/JdeScoping.Client/Services/SearchApiClient.cs
@@ -9,23 +9,61 @@ namespace JdeScoping.Client.Services;
///
public class SearchApiClient : ApiClientBase, ISearchApiClient
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The HTTP client for API requests.
public SearchApiClient(HttpClient httpClient) : base(httpClient) { }
+ ///
+ /// Retrieves the current user's searches.
+ ///
+ /// Cancellation token.
+ /// List of user searches.
public Task>> GetUserSearchesAsync(CancellationToken ct = default)
=> GetAsync>(ApiRoutes.Search.Base, ct);
+ ///
+ /// Retrieves searches queued for processing.
+ ///
+ /// Cancellation token.
+ /// List of queued searches.
public Task>> GetQueuedSearchesAsync(CancellationToken ct = default)
=> GetAsync>(ApiRoutes.Search.Queue, ct);
+ ///
+ /// Retrieves a specific search by ID.
+ ///
+ /// The search ID.
+ /// Cancellation token.
+ /// The search view model.
public Task> GetSearchAsync(int id, CancellationToken ct = default)
=> GetAsync(ApiRoutes.Search.GetById(id), ct);
+ ///
+ /// Creates a copy of an existing search.
+ ///
+ /// The ID of the search to copy.
+ /// Cancellation token.
+ /// The new copied search view model.
public Task> CopySearchAsync(int id, CancellationToken ct = default)
=> GetAsync(ApiRoutes.Search.GetCopy(id), ct);
+ ///
+ /// Creates a new search.
+ ///
+ /// The search view model to create.
+ /// Cancellation token.
+ /// The ID of the newly created search.
public Task> CreateSearchAsync(SearchViewModel search, CancellationToken ct = default)
=> PostAsync(ApiRoutes.Search.Base, search, ct);
+ ///
+ /// Retrieves the results of a completed search.
+ ///
+ /// The search ID.
+ /// Cancellation token.
+ /// The Excel file bytes containing results.
public Task> GetResultsAsync(int id, CancellationToken ct = default)
=> GetBytesAsync(ApiRoutes.Search.GetResults(id), ct);
}
diff --git a/NEW/src/JdeScoping.Client/Services/SearchSubmissionService.cs b/NEW/src/JdeScoping.Client/Services/SearchSubmissionService.cs
index 34f769d..10d898b 100644
--- a/NEW/src/JdeScoping.Client/Services/SearchSubmissionService.cs
+++ b/NEW/src/JdeScoping.Client/Services/SearchSubmissionService.cs
@@ -11,6 +11,10 @@ public class SearchSubmissionService : ISearchSubmissionService
{
private readonly ISearchApiClient _searchApi;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The search API client.
public SearchSubmissionService(ISearchApiClient searchApi)
{
_searchApi = searchApi;
diff --git a/NEW/src/JdeScoping.Core/ApiContracts/ApiRoutes.cs b/NEW/src/JdeScoping.Core/ApiContracts/ApiRoutes.cs
index dd94a54..6ed114c 100644
--- a/NEW/src/JdeScoping.Core/ApiContracts/ApiRoutes.cs
+++ b/NEW/src/JdeScoping.Core/ApiContracts/ApiRoutes.cs
@@ -26,12 +26,18 @@ public static class ApiRoutes
public const string Results = "{id:int}/results";
/// Builds the route to get a specific search.
+ /// The search ID.
+ /// The formatted route.
public static string GetById(int id) => $"api/search/{id}";
/// Builds the route to copy a search.
+ /// The search ID to copy.
+ /// The formatted route.
public static string GetCopy(int id) => $"api/search/{id}/copy";
/// Builds the route to get search results.
+ /// The search ID.
+ /// The formatted route.
public static string GetResults(int id) => $"api/search/{id}/results";
}
@@ -56,15 +62,23 @@ public static class ApiRoutes
public const string Operators = "api/lookup/operators";
/// Builds the route to find items with URL-encoded query.
+ /// The search query to URL-encode.
+ /// The formatted route.
public static string FindItems(string query) => $"{Items}?q={Uri.EscapeDataString(query)}";
/// Builds the route to find profit centers with URL-encoded query.
+ /// The search query to URL-encode.
+ /// The formatted route.
public static string FindProfitCenters(string query) => $"{ProfitCenters}?q={Uri.EscapeDataString(query)}";
/// Builds the route to find work centers with URL-encoded query.
+ /// The search query to URL-encode.
+ /// The formatted route.
public static string FindWorkCenters(string query) => $"{WorkCenters}?q={Uri.EscapeDataString(query)}";
/// Builds the route to find operators with URL-encoded query.
+ /// The search query to URL-encode.
+ /// The formatted route.
public static string FindOperators(string query) => $"{Operators}?q={Uri.EscapeDataString(query)}";
}
@@ -131,6 +145,9 @@ public static class ApiRoutes
public const string Base = "api/refresh-status";
/// Builds the route to get refresh status with date range.
+ /// The minimum date (inclusive).
+ /// The maximum date (inclusive).
+ /// The formatted route.
public static string Get(DateTime minDt, DateTime maxDt) =>
$"api/refresh-status?minDT={minDt:yyyy-MM-dd}&maxDT={maxDt:yyyy-MM-dd}";
}
@@ -153,12 +170,19 @@ public static class ApiRoutes
public const string Executions = "{name}/executions";
/// Builds the route to get a specific pipeline config.
+ /// The pipeline name to URL-encode.
+ /// The formatted route.
public static string GetByName(string name) => $"api/pipelines/{Uri.EscapeDataString(name)}";
/// Builds the route to get pipeline status.
+ /// The pipeline name to URL-encode.
+ /// The formatted route.
public static string GetStatus(string name) => $"api/pipelines/{Uri.EscapeDataString(name)}/status";
/// Builds the route to get pipeline executions.
+ /// The pipeline name to URL-encode.
+ /// The number of recent executions to retrieve.
+ /// The formatted route.
public static string GetExecutions(string name, int count = 10) =>
$"api/pipelines/{Uri.EscapeDataString(name)}/executions?count={count}";
}
diff --git a/NEW/src/JdeScoping.Core/ApiContracts/IAuthApiClient.cs b/NEW/src/JdeScoping.Core/ApiContracts/IAuthApiClient.cs
index 82e3df1..7f2b6c2 100644
--- a/NEW/src/JdeScoping.Core/ApiContracts/IAuthApiClient.cs
+++ b/NEW/src/JdeScoping.Core/ApiContracts/IAuthApiClient.cs
@@ -9,14 +9,19 @@ namespace JdeScoping.Core.ApiContracts;
public interface IAuthApiClient
{
/// Gets the server's RSA public key for encrypting login credentials.
+ /// The cancellation token.
Task> GetPublicKeyAsync(CancellationToken ct = default);
/// Authenticates with encrypted credentials.
+ /// The encrypted login request containing credentials.
+ /// The cancellation token.
Task> LoginAsync(EncryptedLoginRequest request, CancellationToken ct = default);
/// Logs out the current user.
+ /// The cancellation token.
Task> LogoutAsync(CancellationToken ct = default);
/// Gets the current authenticated user's information.
+ /// The cancellation token.
Task> GetCurrentUserAsync(CancellationToken ct = default);
}
diff --git a/NEW/src/JdeScoping.Core/ApiContracts/IFileApiClient.cs b/NEW/src/JdeScoping.Core/ApiContracts/IFileApiClient.cs
index e81b18d..6852258 100644
--- a/NEW/src/JdeScoping.Core/ApiContracts/IFileApiClient.cs
+++ b/NEW/src/JdeScoping.Core/ApiContracts/IFileApiClient.cs
@@ -12,28 +12,48 @@ public interface IFileApiClient
// Downloads (POST with existing data, returns Excel bytes)
/// Downloads work orders template, optionally pre-filled with existing data.
+ /// Optional existing data to pre-fill the template.
+ /// Cancellation token.
Task> DownloadWorkOrdersTemplateAsync(IReadOnlyList? existingData = null, CancellationToken ct = default);
/// Downloads items template, optionally pre-filled with existing data.
+ /// Optional existing data to pre-fill the template.
+ /// Cancellation token.
Task> DownloadItemsTemplateAsync(IReadOnlyList? existingData = null, CancellationToken ct = default);
/// Downloads component lots template, optionally pre-filled with existing data.
+ /// Optional existing data to pre-fill the template.
+ /// Cancellation token.
Task> DownloadComponentLotsTemplateAsync(IReadOnlyList? existingData = null, CancellationToken ct = default);
/// Downloads part operations template, optionally pre-filled with existing data.
+ /// Optional existing data to pre-fill the template.
+ /// Cancellation token.
Task> DownloadPartOperationsTemplateAsync(IReadOnlyList? existingData = null, CancellationToken ct = default);
// Uploads (multipart form, returns parsed data)
/// Uploads work orders Excel file and returns parsed data.
+ /// The file stream to upload.
+ /// The name of the file being uploaded.
+ /// Cancellation token.
Task>> UploadWorkOrdersAsync(Stream fileStream, string fileName, CancellationToken ct = default);
/// Uploads items Excel file and returns parsed data.
+ /// The file stream to upload.
+ /// The name of the file being uploaded.
+ /// Cancellation token.
Task>> UploadItemsAsync(Stream fileStream, string fileName, CancellationToken ct = default);
/// Uploads component lots Excel file and returns parsed data.
+ /// The file stream to upload.
+ /// The name of the file being uploaded.
+ /// Cancellation token.
Task>> UploadComponentLotsAsync(Stream fileStream, string fileName, CancellationToken ct = default);
/// Uploads part operations Excel file and returns parsed data.
+ /// The file stream to upload.
+ /// The name of the file being uploaded.
+ /// Cancellation token.
Task>> UploadPartOperationsAsync(Stream fileStream, string fileName, CancellationToken ct = default);
}
diff --git a/NEW/src/JdeScoping.Core/ApiContracts/ILookupApiClient.cs b/NEW/src/JdeScoping.Core/ApiContracts/ILookupApiClient.cs
index 6abd55e..9492454 100644
--- a/NEW/src/JdeScoping.Core/ApiContracts/ILookupApiClient.cs
+++ b/NEW/src/JdeScoping.Core/ApiContracts/ILookupApiClient.cs
@@ -9,14 +9,22 @@ namespace JdeScoping.Core.ApiContracts;
public interface ILookupApiClient
{
/// Finds items matching the search query.
+ /// The search query to match against item data.
+ /// Cancellation token.
Task>> FindItemsAsync(string query, CancellationToken ct = default);
/// Finds profit centers matching the search query.
+ /// The search query to match against profit center data.
+ /// Cancellation token.
Task>> FindProfitCentersAsync(string query, CancellationToken ct = default);
/// Finds work centers matching the search query.
+ /// The search query to match against work center data.
+ /// Cancellation token.
Task>> FindWorkCentersAsync(string query, CancellationToken ct = default);
/// Finds operators (JDE users) matching the search query.
+ /// The search query to match against operator data.
+ /// Cancellation token.
Task>> FindOperatorsAsync(string query, CancellationToken ct = default);
}
diff --git a/NEW/src/JdeScoping.Core/ApiContracts/IPipelineApiClient.cs b/NEW/src/JdeScoping.Core/ApiContracts/IPipelineApiClient.cs
index 7671f76..48fd2c8 100644
--- a/NEW/src/JdeScoping.Core/ApiContracts/IPipelineApiClient.cs
+++ b/NEW/src/JdeScoping.Core/ApiContracts/IPipelineApiClient.cs
@@ -9,14 +9,22 @@ namespace JdeScoping.Core.ApiContracts;
public interface IPipelineApiClient
{
/// Gets list of all available pipeline names.
+ /// Cancellation token.
Task> GetPipelineNamesAsync(CancellationToken ct = default);
/// Gets configuration for a specific pipeline.
+ /// The pipeline name.
+ /// Cancellation token.
Task> GetPipelineAsync(string name, CancellationToken ct = default);
/// Gets schedule status for a pipeline.
+ /// The pipeline name.
+ /// Cancellation token.
Task> GetStatusAsync(string name, CancellationToken ct = default);
/// Gets recent execution history for a pipeline.
+ /// The pipeline name.
+ /// The maximum number of executions to return.
+ /// Cancellation token.
Task> GetExecutionsAsync(string name, int count = 30, CancellationToken ct = default);
}
diff --git a/NEW/src/JdeScoping.Core/ApiContracts/ISearchApiClient.cs b/NEW/src/JdeScoping.Core/ApiContracts/ISearchApiClient.cs
index 2631fce..39df23a 100644
--- a/NEW/src/JdeScoping.Core/ApiContracts/ISearchApiClient.cs
+++ b/NEW/src/JdeScoping.Core/ApiContracts/ISearchApiClient.cs
@@ -9,20 +9,30 @@ namespace JdeScoping.Core.ApiContracts;
public interface ISearchApiClient
{
/// Gets all searches for the current user.
+ /// Cancellation token.
Task>> GetUserSearchesAsync(CancellationToken ct = default);
/// Gets all queued searches.
+ /// Cancellation token.
Task>> GetQueuedSearchesAsync(CancellationToken ct = default);
/// Gets a specific search by ID.
+ /// The search identifier.
+ /// Cancellation token.
Task> GetSearchAsync(int id, CancellationToken ct = default);
/// Copies an existing search to create a new one (returns copy without persisting).
+ /// The search identifier to copy.
+ /// Cancellation token.
Task> CopySearchAsync(int id, CancellationToken ct = default);
/// Creates and submits a new search.
+ /// The search to create.
+ /// Cancellation token.
Task> CreateSearchAsync(SearchViewModel search, CancellationToken ct = default);
/// Downloads the results for a completed search as Excel bytes.
+ /// The search identifier.
+ /// Cancellation token.
Task> GetResultsAsync(int id, CancellationToken ct = default);
}
diff --git a/NEW/src/JdeScoping.Core/ApiContracts/Results/ValidationError.cs b/NEW/src/JdeScoping.Core/ApiContracts/Results/ValidationError.cs
index ddbe43a..e622af6 100644
--- a/NEW/src/JdeScoping.Core/ApiContracts/Results/ValidationError.cs
+++ b/NEW/src/JdeScoping.Core/ApiContracts/Results/ValidationError.cs
@@ -10,6 +10,8 @@ public readonly record struct ValidationError(IReadOnlyDictionary
/// Creates a ValidationError from a dictionary of field errors.
///
+ /// Dictionary mapping field names to error message arrays.
+ /// A ValidationError containing the field errors.
public static ValidationError FromDictionary(Dictionary errors)
=> new(errors);
}
diff --git a/NEW/src/JdeScoping.Core/Models/Auth/LoginModel.cs b/NEW/src/JdeScoping.Core/Models/Auth/LoginModel.cs
index 172e342..54971d4 100644
--- a/NEW/src/JdeScoping.Core/Models/Auth/LoginModel.cs
+++ b/NEW/src/JdeScoping.Core/Models/Auth/LoginModel.cs
@@ -7,9 +7,15 @@ namespace JdeScoping.Core.Models.Auth;
///
public class LoginModel
{
+ ///
+ /// Gets or sets the user's login username.
+ ///
[Required(ErrorMessage = "Username is required")]
public string Username { get; set; } = string.Empty;
+ ///
+ /// Gets or sets the user's login password.
+ ///
[Required(ErrorMessage = "Password is required")]
public string Password { get; set; } = string.Empty;
}
diff --git a/NEW/src/JdeScoping.Core/Models/Infrastructure/DataUpdateDto.cs b/NEW/src/JdeScoping.Core/Models/Infrastructure/DataUpdateDto.cs
index ce07eb5..5bb6d2e 100644
--- a/NEW/src/JdeScoping.Core/Models/Infrastructure/DataUpdateDto.cs
+++ b/NEW/src/JdeScoping.Core/Models/Infrastructure/DataUpdateDto.cs
@@ -6,20 +6,34 @@ namespace JdeScoping.Core.Models.Infrastructure;
///
public class DataUpdateDto
{
+ /// The start time of the data update.
public DateTime StartDt { get; set; }
+ /// The end time of the data update.
public DateTime? EndDt { get; set; }
+ /// The number of branch records updated.
public int BranchRecords { get; set; }
+ /// The number of profit center records updated.
public int ProfitCenterRecords { get; set; }
+ /// The number of work center records updated.
public int WorkCenterRecords { get; set; }
+ /// The number of organizational hierarchy records updated.
public int OrgHierarchyRecords { get; set; }
+ /// The number of status code records updated.
public int StatusCodeRecords { get; set; }
+ /// The number of user records updated.
public int UserRecords { get; set; }
+ /// The number of item records updated.
public int ItemRecords { get; set; }
+ /// The number of lot records updated.
public int LotRecords { get; set; }
+ /// The number of work order records updated.
public int WorkOrderRecords { get; set; }
+ /// The number of work order step records updated.
public int WorkOrderStepRecords { get; set; }
+ /// The number of work order component records updated.
public int WorkOrderComponentRecords { get; set; }
+ /// Whether the data update was successful.
public bool WasSuccessful { get; set; }
}
diff --git a/NEW/src/JdeScoping.Core/Models/SearchResults/MisNonMatchSearchResult.cs b/NEW/src/JdeScoping.Core/Models/SearchResults/MisNonMatchSearchResult.cs
index 4c98756..53d0723 100644
--- a/NEW/src/JdeScoping.Core/Models/SearchResults/MisNonMatchSearchResult.cs
+++ b/NEW/src/JdeScoping.Core/Models/SearchResults/MisNonMatchSearchResult.cs
@@ -5,16 +5,28 @@ namespace JdeScoping.Core.Models.SearchResults;
///
public sealed class MisNonMatchSearchResult
{
+ /// The work center code.
public string WorkCenterCode { get; init; } = string.Empty;
+ /// The work order number.
public long WorkOrderNumber { get; init; }
+ /// The work order start date.
public DateTime WorkOrderStartDate { get; init; }
+ /// The job step number.
public decimal JobStepNumber { get; init; }
+ /// The job step description.
public string JobStepDescription { get; init; } = string.Empty;
+ /// The job step end date.
public DateTime? JobStepEndDate { get; init; }
+ /// The function code.
public string FunctionCode { get; init; } = string.Empty;
+ /// Indicates whether the job step was added.
public bool WasJobStepAdded { get; init; }
+ /// The matched job step number, if any.
public decimal? MatchedJobStepNumber { get; init; }
+ /// The item number.
public string ItemNumber { get; init; } = string.Empty;
+ /// The item description.
public string ItemDescription { get; init; } = string.Empty;
+ /// The routing type.
public string RoutingType { get; init; } = string.Empty;
}
diff --git a/NEW/src/JdeScoping.Core/Models/SearchResults/MisSearchResult.cs b/NEW/src/JdeScoping.Core/Models/SearchResults/MisSearchResult.cs
index 37f1194..9d1469d 100644
--- a/NEW/src/JdeScoping.Core/Models/SearchResults/MisSearchResult.cs
+++ b/NEW/src/JdeScoping.Core/Models/SearchResults/MisSearchResult.cs
@@ -5,23 +5,42 @@ namespace JdeScoping.Core.Models.SearchResults;
///
public sealed class MisSearchResult
{
+ /// The item number.
public string ItemNumber { get; init; } = string.Empty;
+ /// The item description.
public string ItemDescription { get; init; } = string.Empty;
+ /// The sequence number.
public string SequenceNumber { get; init; } = string.Empty;
+ /// The MIS (Manufacturing Instruction Sheet) number.
public string MisNumber { get; init; } = string.Empty;
+ /// The revision ID.
public string RevId { get; init; } = string.Empty;
+ /// The status.
public string Status { get; init; } = string.Empty;
+ /// The release date.
public DateTime? ReleaseDate { get; init; }
+ /// The branch code.
public string BranchCode { get; init; } = string.Empty;
+ /// The job step sequence number.
public decimal JobStepSequenceNumber { get; init; }
+ /// The matched sequence number.
public decimal? MatchedSequenceNumber { get; init; }
+ /// Whether the routing matches.
public bool RoutingMatch { get; init; }
+ /// Whether the master matches.
public bool MasterMatch { get; init; }
+ /// The function operation description.
public string FunctionOperationDescription { get; init; } = string.Empty;
+ /// The character number.
public string CharNumber { get; init; } = string.Empty;
+ /// The test description.
public string TestDescription { get; init; } = string.Empty;
+ /// The sampling type.
public string SamplingType { get; init; } = string.Empty;
+ /// The sampling value.
public string SamplingValue { get; init; } = string.Empty;
+ /// The tools and gauges required.
public string ToolsGauges { get; init; } = string.Empty;
+ /// The work instructions.
public string WorkInstructions { get; init; } = string.Empty;
}
diff --git a/NEW/src/JdeScoping.Core/Models/SearchResults/SearchModel.cs b/NEW/src/JdeScoping.Core/Models/SearchResults/SearchModel.cs
index 35e5897..351eba9 100644
--- a/NEW/src/JdeScoping.Core/Models/SearchResults/SearchModel.cs
+++ b/NEW/src/JdeScoping.Core/Models/SearchResults/SearchModel.cs
@@ -5,15 +5,25 @@ namespace JdeScoping.Core.Models.SearchResults;
///
public class SearchModel
{
+ /// The unique identifier for the search.
public int Id { get; set; }
+ /// The username of the user who submitted the search.
public string UserName { get; set; } = string.Empty;
+ /// The name of the search.
public string Name { get; set; } = string.Empty;
+ /// The date and time the search was submitted.
public DateTime? SubmitDt { get; set; }
+ /// The date and time when search execution started.
public DateTime? StartDt { get; set; }
+ /// The date and time when search execution ended.
public DateTime? EndDt { get; set; }
+ /// Indicates whether MIS data extraction is enabled for this search.
public bool ExtractMisData { get; set; }
+ /// The main search results.
public List Results { get; set; } = [];
+ /// The MIS-specific search results.
public List MisResults { get; set; } = [];
+ /// The MIS non-match investigation results.
public List MisNonMatchResults { get; set; } = [];
}
diff --git a/NEW/src/JdeScoping.Core/Models/SearchResults/SearchResult.cs b/NEW/src/JdeScoping.Core/Models/SearchResults/SearchResult.cs
index 49754aa..50008d1 100644
--- a/NEW/src/JdeScoping.Core/Models/SearchResults/SearchResult.cs
+++ b/NEW/src/JdeScoping.Core/Models/SearchResults/SearchResult.cs
@@ -5,30 +5,119 @@ namespace JdeScoping.Core.Models.SearchResults;
///
public sealed class SearchResult
{
+ ///
+ /// Work order number.
+ ///
public long WorkOrderNumber { get; init; }
+
+ ///
+ /// Branch code for the work order.
+ ///
public string WorkOrderBranchCode { get; init; } = string.Empty;
+
+ ///
+ /// Lot number.
+ ///
public string LotNumber { get; init; } = string.Empty;
+
+ ///
+ /// Item number.
+ ///
public string ItemNumber { get; init; } = string.Empty;
+
+ ///
+ /// Planning family.
+ ///
public string PlanningFamily { get; init; } = string.Empty;
+
+ ///
+ /// Stocking type.
+ ///
public string StockingType { get; init; } = string.Empty;
+
+ ///
+ /// Order quantity.
+ ///
public decimal OrderQuantity { get; init; }
+
+ ///
+ /// Held quantity.
+ ///
public decimal HeldQuantity { get; init; }
+
+ ///
+ /// Scrapped quantity.
+ ///
public decimal ScrappedQuantity { get; init; }
+
+ ///
+ /// Shipped quantity.
+ ///
public decimal ShippedQuantity { get; init; }
+
+ ///
+ /// Branch code for the step.
+ ///
public string StepBranchCode { get; init; } = string.Empty;
+
+ ///
+ /// Step number.
+ ///
public decimal StepNumber { get; init; }
+
+ ///
+ /// Description of the step.
+ ///
public string StepDescription { get; init; } = string.Empty;
+
+ ///
+ /// Function operation description.
+ ///
public string FunctionOperationDescription { get; init; } = string.Empty;
+
+ ///
+ /// Step update date and time.
+ ///
public DateTime StepUpdateDt { get; init; }
+
+ ///
+ /// Status code.
+ ///
public string StatusCode { get; init; } = string.Empty;
+
+ ///
+ /// Status description.
+ ///
public string StatusDescription { get; init; } = string.Empty;
+
+ ///
+ /// Status update date and time.
+ ///
public DateTime? StatusUpdateDt { get; init; }
- // Inclusion flags
+ ///
+ /// Indicates if manually specified in search criteria.
+ ///
public bool ManuallySpecified { get; init; }
+
+ ///
+ /// Indicates if part of a split order.
+ ///
public bool SplitOrder { get; init; }
+
+ ///
+ /// Indicates if flagged for cardex inclusion.
+ ///
public bool Cardex { get; init; }
+
+ ///
+ /// Indicates if included via parts list.
+ ///
public bool PartsList { get; init; }
+
+ ///
+ /// Indicates if flagged for inclusion.
+ ///
public bool Flagged { get; init; }
///
diff --git a/NEW/src/JdeScoping.Core/ViewModels/ComponentLotViewModel.cs b/NEW/src/JdeScoping.Core/ViewModels/ComponentLotViewModel.cs
index bb9d002..7f92f1c 100644
--- a/NEW/src/JdeScoping.Core/ViewModels/ComponentLotViewModel.cs
+++ b/NEW/src/JdeScoping.Core/ViewModels/ComponentLotViewModel.cs
@@ -8,9 +8,17 @@ namespace JdeScoping.Core.ViewModels;
///
public class ComponentLotViewModel
{
+ ///
+ /// Gets or sets the lot number.
+ ///
public string LotNumber { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the item number.
+ ///
public string ItemNumber { get; set; } = string.Empty;
+ ///
public override bool Equals(object? obj)
{
if (obj is ComponentLotViewModel other)
@@ -20,5 +28,6 @@ public class ComponentLotViewModel
return false;
}
+ ///
public override int GetHashCode() => HashCode.Combine(LotNumber, ItemNumber);
}
diff --git a/NEW/src/JdeScoping.Core/ViewModels/OperatorViewModel.cs b/NEW/src/JdeScoping.Core/ViewModels/OperatorViewModel.cs
index c949344..6f13cd0 100644
--- a/NEW/src/JdeScoping.Core/ViewModels/OperatorViewModel.cs
+++ b/NEW/src/JdeScoping.Core/ViewModels/OperatorViewModel.cs
@@ -5,10 +5,22 @@ namespace JdeScoping.Core.ViewModels;
///
public class OperatorViewModel
{
+ ///
+ /// Gets or sets the operator's address number.
+ ///
public long AddressNumber { get; set; }
+
+ ///
+ /// Gets or sets the operator's user ID.
+ ///
public string UserId { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the operator's full name.
+ ///
public string FullName { get; set; } = string.Empty;
+ ///
public override bool Equals(object? obj)
{
if (obj is OperatorViewModel other)
@@ -18,5 +30,6 @@ public class OperatorViewModel
return false;
}
+ ///
public override int GetHashCode() => UserId.GetHashCode();
}
diff --git a/NEW/src/JdeScoping.Core/ViewModels/ViewModelExtensions.cs b/NEW/src/JdeScoping.Core/ViewModels/ViewModelExtensions.cs
index d258a1c..57f970c 100644
--- a/NEW/src/JdeScoping.Core/ViewModels/ViewModelExtensions.cs
+++ b/NEW/src/JdeScoping.Core/ViewModels/ViewModelExtensions.cs
@@ -13,6 +13,8 @@ public static class ViewModelExtensions
///
/// Converts an Item to ItemViewModel
///
+ /// The item to convert.
+ /// An ItemViewModel containing the item data.
public static ItemViewModel ToViewModel(this Item item)
{
return new ItemViewModel
@@ -25,6 +27,8 @@ public static class ViewModelExtensions
///
/// Converts a ProfitCenter to ProfitCenterViewModel
///
+ /// The profit center to convert.
+ /// A ProfitCenterViewModel containing the profit center data.
public static ProfitCenterViewModel ToViewModel(this ProfitCenter profitCenter)
{
return new ProfitCenterViewModel
@@ -37,6 +41,8 @@ public static class ViewModelExtensions
///
/// Converts a WorkCenter to WorkCenterViewModel
///
+ /// The work center to convert.
+ /// A WorkCenterViewModel containing the work center data.
public static WorkCenterViewModel ToViewModel(this WorkCenter workCenter)
{
return new WorkCenterViewModel
@@ -49,6 +55,8 @@ public static class ViewModelExtensions
///
/// Converts a JdeUser to JdeUserViewModel
///
+ /// The JDE user to convert.
+ /// A JdeUserViewModel containing the user data.
public static JdeUserViewModel ToViewModel(this JdeUser user)
{
return new JdeUserViewModel
@@ -62,6 +70,8 @@ public static class ViewModelExtensions
///
/// Converts a WorkOrder to WorkOrderViewModel
///
+ /// The work order to convert.
+ /// A WorkOrderViewModel containing the work order data.
public static WorkOrderViewModel ToViewModel(this WorkOrder workOrder)
{
return new WorkOrderViewModel
@@ -74,6 +84,8 @@ public static class ViewModelExtensions
///
/// Converts a Lot to LotViewModel
///
+ /// The lot to convert.
+ /// A LotViewModel containing the lot data.
public static LotViewModel ToViewModel(this Lot lot)
{
return new LotViewModel
diff --git a/NEW/src/JdeScoping.DataAccess/Repositories/LotFinderRepository.cs b/NEW/src/JdeScoping.DataAccess/Repositories/LotFinderRepository.cs
index 03104b8..ff4e53e 100644
--- a/NEW/src/JdeScoping.DataAccess/Repositories/LotFinderRepository.cs
+++ b/NEW/src/JdeScoping.DataAccess/Repositories/LotFinderRepository.cs
@@ -21,6 +21,9 @@ public partial class LotFinderRepository : ILotFinderRepository
///
/// Initializes a new instance of the class.
///
+ /// The database connection factory.
+ /// The logger instance.
+ /// The data access options.
public LotFinderRepository(
IDbConnectionFactory connectionFactory,
ILogger logger,
diff --git a/NEW/src/JdeScoping.DataAccess/Services/SearchProcessor.cs b/NEW/src/JdeScoping.DataAccess/Services/SearchProcessor.cs
index fc13639..9eee446 100644
--- a/NEW/src/JdeScoping.DataAccess/Services/SearchProcessor.cs
+++ b/NEW/src/JdeScoping.DataAccess/Services/SearchProcessor.cs
@@ -27,6 +27,12 @@ public sealed class SearchProcessor : ISearchProcessor
///
/// Initializes a new instance of SearchProcessor.
///
+ /// The database connection factory.
+ /// The search query builder.
+ /// The work order traversal service.
+ /// The MIS query builder.
+ /// The search processing configuration options.
+ /// The logger instance.
public SearchProcessor(
IDbConnectionFactory connectionFactory,
ISearchQueryBuilder queryBuilder,
diff --git a/NEW/src/JdeScoping.DataSync.Dev/Configuration/DevPipelinesRoot.cs b/NEW/src/JdeScoping.DataSync.Dev/Configuration/DevPipelinesRoot.cs
index aa7e8b0..2ce2d4b 100644
--- a/NEW/src/JdeScoping.DataSync.Dev/Configuration/DevPipelinesRoot.cs
+++ b/NEW/src/JdeScoping.DataSync.Dev/Configuration/DevPipelinesRoot.cs
@@ -7,6 +7,9 @@ public record DevPipelinesRoot(
DevPipelineSettings? Settings,
Dictionary Pipelines)
{
+ ///
+ /// Gets the effective settings, using defaults if not specified.
+ ///
public DevPipelineSettings EffectiveSettings => Settings ?? new DevPipelineSettings();
}
diff --git a/NEW/src/JdeScoping.DataSync.Dev/DevEtlRegistry.cs b/NEW/src/JdeScoping.DataSync.Dev/DevEtlRegistry.cs
index 0b34dde..e9cb41f 100644
--- a/NEW/src/JdeScoping.DataSync.Dev/DevEtlRegistry.cs
+++ b/NEW/src/JdeScoping.DataSync.Dev/DevEtlRegistry.cs
@@ -15,6 +15,12 @@ public class DevEtlRegistry
private readonly string _cacheDirectory;
private readonly ILogger? _logger;
+ ///
+ /// Initializes a new instance of the DevEtlRegistry.
+ ///
+ /// The factory for creating ETL pipelines.
+ /// The directory containing cached protobuf files.
+ /// Optional logger for recording ETL operations.
public DevEtlRegistry(
IDevEtlPipelineFactory pipelineFactory,
string cacheDirectory,
@@ -32,8 +38,16 @@ public class DevEtlRegistry
_logger = logger;
}
+ ///
+ /// Gets the list of available tables that can be loaded.
+ ///
public IEnumerable GetAvailableTables() => _pipelineFactory.GetAvailableTables();
+ ///
+ /// Runs the ETL pipeline for a single table.
+ ///
+ /// The name of the table to load.
+ /// The cancellation token.
public async Task RunAsync(string tableName, CancellationToken cancellationToken = default)
{
_logger?.LogInformation("Running dev ETL for {TableName}", tableName);
@@ -51,6 +65,10 @@ public class DevEtlRegistry
return result;
}
+ ///
+ /// Runs the ETL pipeline for all available tables sequentially.
+ ///
+ /// The cancellation token.
public async Task> RunAllAsync(CancellationToken cancellationToken = default)
{
var results = new List();
diff --git a/NEW/src/JdeScoping.DataSync.Dev/Services/DevEtlPipelineFactory.cs b/NEW/src/JdeScoping.DataSync.Dev/Services/DevEtlPipelineFactory.cs
index 7dcb357..dd69011 100644
--- a/NEW/src/JdeScoping.DataSync.Dev/Services/DevEtlPipelineFactory.cs
+++ b/NEW/src/JdeScoping.DataSync.Dev/Services/DevEtlPipelineFactory.cs
@@ -31,6 +31,9 @@ public class DevEtlPipelineFactory : IDevEtlPipelineFactory
///
/// Creates a new development pipeline factory.
///
+ /// Factory for creating database connections.
+ /// Configuration options for the development pipeline.
+ /// Logger for pipeline operations.
public DevEtlPipelineFactory(
IDbConnectionFactory connectionFactory,
IOptions options,
@@ -49,6 +52,9 @@ public class DevEtlPipelineFactory : IDevEtlPipelineFactory
///
/// Creates a new development pipeline factory with pre-loaded config (for testing).
///
+ /// Factory for creating database connections.
+ /// Pre-loaded pipeline configuration.
+ /// Logger for pipeline operations.
internal DevEtlPipelineFactory(
IDbConnectionFactory connectionFactory,
DevPipelinesRoot config,
diff --git a/NEW/src/JdeScoping.DataSync.Dev/Sources/ProtobufZstdFileSource.cs b/NEW/src/JdeScoping.DataSync.Dev/Sources/ProtobufZstdFileSource.cs
index ff4fe3d..764c78a 100644
--- a/NEW/src/JdeScoping.DataSync.Dev/Sources/ProtobufZstdFileSource.cs
+++ b/NEW/src/JdeScoping.DataSync.Dev/Sources/ProtobufZstdFileSource.cs
@@ -26,8 +26,17 @@ public sealed class ProtobufZstdFileSource : IImportSource
private BufferedStream? _bufferedStream;
private IDataReader? _reader;
+ ///
+ /// The name of this source, including the file name.
+ ///
public string SourceName => $"Protobuf:{Path.GetFileName(_filePath)}";
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The path to the zstd-compressed protobuf file.
+ /// Thrown when filePath is null or empty.
+ /// Thrown when the file does not exist.
public ProtobufZstdFileSource(string filePath)
{
if (string.IsNullOrWhiteSpace(filePath))
@@ -39,6 +48,12 @@ public sealed class ProtobufZstdFileSource : IImportSource
_filePath = filePath;
}
+ ///
+ /// Reads and decompresses the protobuf file, returning an IDataReader for deserialization.
+ ///
+ /// The cancellation token.
+ /// An IDataReader for reading the decompressed protobuf data.
+ /// Thrown if ReadDataAsync has already been called.
public async Task ReadDataAsync(CancellationToken cancellationToken = default)
{
if (_fileStream != null)
@@ -85,6 +100,9 @@ public sealed class ProtobufZstdFileSource : IImportSource
_fileStream = null;
}
+ ///
+ /// Disposes of all unmanaged resources associated with this source.
+ ///
public async ValueTask DisposeAsync()
{
if (_reader != null)
diff --git a/NEW/src/JdeScoping.DataSync/Configuration/PipelinesRoot.cs b/NEW/src/JdeScoping.DataSync/Configuration/PipelinesRoot.cs
index b783b82..9ed6270 100644
--- a/NEW/src/JdeScoping.DataSync/Configuration/PipelinesRoot.cs
+++ b/NEW/src/JdeScoping.DataSync/Configuration/PipelinesRoot.cs
@@ -5,7 +5,9 @@ public record PipelinesRoot(
ScheduleDefaults? ScheduleDefaults, // Optional - defaults applied if missing
Dictionary Pipelines)
{
+ /// Gets the effective pipeline settings, using defaults if not specified.
public PipelineSettings EffectiveSettings => Settings ?? new PipelineSettings();
+ /// Gets the effective schedule defaults, using defaults if not specified.
public ScheduleDefaults EffectiveScheduleDefaults => ScheduleDefaults ?? new ScheduleDefaults();
}
diff --git a/NEW/src/JdeScoping.DataSync/Configuration/ScheduleConfig.cs b/NEW/src/JdeScoping.DataSync/Configuration/ScheduleConfig.cs
index b78a121..4b4db65 100644
--- a/NEW/src/JdeScoping.DataSync/Configuration/ScheduleConfig.cs
+++ b/NEW/src/JdeScoping.DataSync/Configuration/ScheduleConfig.cs
@@ -33,6 +33,7 @@ public record ScheduleConfig
///
/// Merges this config with defaults. Non-null/non-default values in this config override defaults.
///
+ /// The default configuration to merge with.
public ScheduleConfig MergeWith(ScheduleConfig defaults)
{
return new ScheduleConfig
@@ -92,7 +93,18 @@ public record ScheduleDefaults
///
public record PipelineSchedules
{
+ ///
+ /// Gets or initializes the Mass schedule configuration override.
+ ///
public ScheduleConfig? Mass { get; init; }
+
+ ///
+ /// Gets or initializes the Daily schedule configuration override.
+ ///
public ScheduleConfig? Daily { get; init; }
+
+ ///
+ /// Gets or initializes the Hourly schedule configuration override.
+ ///
public ScheduleConfig? Hourly { get; init; }
}
diff --git a/NEW/src/JdeScoping.DataSync/Etl/EtlServiceCollectionExtensions.cs b/NEW/src/JdeScoping.DataSync/Etl/EtlServiceCollectionExtensions.cs
index 5c6bbb0..4f196ca 100644
--- a/NEW/src/JdeScoping.DataSync/Etl/EtlServiceCollectionExtensions.cs
+++ b/NEW/src/JdeScoping.DataSync/Etl/EtlServiceCollectionExtensions.cs
@@ -11,6 +11,8 @@ public static class EtlServiceCollectionExtensions
///
/// Adds ETL pipeline services to the service collection.
///
+ /// The service collection to add ETL services to.
+ /// The service collection for method chaining.
public static IServiceCollection AddEtlPipeline(this IServiceCollection services)
{
// Register the builder as transient so each request gets a fresh builder
diff --git a/NEW/src/JdeScoping.DataSync/Etl/Pipeline/EtlPipeline.cs b/NEW/src/JdeScoping.DataSync/Etl/Pipeline/EtlPipeline.cs
index f9edfee..d78d6a1 100644
--- a/NEW/src/JdeScoping.DataSync/Etl/Pipeline/EtlPipeline.cs
+++ b/NEW/src/JdeScoping.DataSync/Etl/Pipeline/EtlPipeline.cs
@@ -15,8 +15,21 @@ public class EtlPipeline
private readonly IReadOnlyList _postScripts;
private readonly ILogger _logger;
+ ///
+ /// Gets the name of the pipeline.
+ ///
public string PipelineName { get; }
+ ///
+ /// Initializes a new instance of the EtlPipeline.
+ ///
+ /// The name of the pipeline.
+ /// The data source for the pipeline.
+ /// The data transformers to apply.
+ /// The destination for the transformed data.
+ /// Scripts to run before the pipeline executes.
+ /// Scripts to run after the pipeline executes.
+ /// The logger for recording pipeline execution.
internal EtlPipeline(
string name,
IImportSource source,
@@ -35,6 +48,10 @@ public class EtlPipeline
_logger = logger;
}
+ ///
+ /// Executes the ETL pipeline, running all steps in sequence.
+ ///
+ /// The cancellation token.
public async Task ExecuteAsync(CancellationToken cancellationToken = default)
{
var steps = new List();
diff --git a/NEW/src/JdeScoping.DataSync/Etl/Pipeline/EtlPipelineBuilder.cs b/NEW/src/JdeScoping.DataSync/Etl/Pipeline/EtlPipelineBuilder.cs
index 0a17c9b..bfe7464 100644
--- a/NEW/src/JdeScoping.DataSync/Etl/Pipeline/EtlPipelineBuilder.cs
+++ b/NEW/src/JdeScoping.DataSync/Etl/Pipeline/EtlPipelineBuilder.cs
@@ -15,18 +15,33 @@ public class EtlPipelineBuilder
private ILogger? _logger;
private int _defaultCommandTimeoutSeconds = 600;
+ ///
+ /// Sets the pipeline name.
+ ///
+ /// The pipeline name.
+ /// The builder for method chaining.
public EtlPipelineBuilder WithName(string name)
{
_name = name ?? throw new ArgumentNullException(nameof(name));
return this;
}
+ ///
+ /// Sets the data source for the pipeline.
+ ///
+ /// The import source.
+ /// The builder for method chaining.
public EtlPipelineBuilder WithSource(IImportSource source)
{
_source = source ?? throw new ArgumentNullException(nameof(source));
return this;
}
+ ///
+ /// Adds a data transformer to the pipeline.
+ ///
+ /// The data transformer.
+ /// The builder for method chaining.
public EtlPipelineBuilder WithTransformer(IDataTransformer transformer)
{
ArgumentNullException.ThrowIfNull(transformer);
@@ -34,12 +49,22 @@ public class EtlPipelineBuilder
return this;
}
+ ///
+ /// Sets the destination for the transformed data.
+ ///
+ /// The import destination.
+ /// The builder for method chaining.
public EtlPipelineBuilder WithDestination(IImportDestination destination)
{
_destination = destination ?? throw new ArgumentNullException(nameof(destination));
return this;
}
+ ///
+ /// Adds a pre-execution script to run before the pipeline starts.
+ ///
+ /// The script runner.
+ /// The builder for method chaining.
public EtlPipelineBuilder WithPreScript(IScriptRunner script)
{
ArgumentNullException.ThrowIfNull(script);
@@ -47,6 +72,11 @@ public class EtlPipelineBuilder
return this;
}
+ ///
+ /// Adds a post-execution script to run after the pipeline completes.
+ ///
+ /// The script runner.
+ /// The builder for method chaining.
public EtlPipelineBuilder WithPostScript(IScriptRunner script)
{
ArgumentNullException.ThrowIfNull(script);
@@ -54,6 +84,11 @@ public class EtlPipelineBuilder
return this;
}
+ ///
+ /// Sets the logger for the pipeline.
+ ///
+ /// The logger instance.
+ /// The builder for method chaining.
public EtlPipelineBuilder WithLogger(ILogger logger)
{
_logger = logger;
@@ -63,6 +98,11 @@ public class EtlPipelineBuilder
// TODO: Currently this timeout value is stored but not passed to destinations.
// In the future, the pipeline should pass this timeout to destinations that support it.
// For now, destinations use their own default timeout (600 seconds).
+ ///
+ /// Sets the command timeout for database operations.
+ ///
+ /// The timeout duration (must be between 0 and 24 hours).
+ /// The builder for method chaining.
public EtlPipelineBuilder WithCommandTimeout(TimeSpan timeout)
{
if (timeout < TimeSpan.Zero || timeout > TimeSpan.FromHours(24))
@@ -72,6 +112,11 @@ public class EtlPipelineBuilder
return this;
}
+ ///
+ /// Builds and returns the configured ETL pipeline.
+ ///
+ /// The constructed ETL pipeline.
+ /// Thrown when source or destination is not configured.
public EtlPipeline Build()
{
if (_source == null)
diff --git a/NEW/src/JdeScoping.DataSync/Etl/Scripts/CommonScripts.cs b/NEW/src/JdeScoping.DataSync/Etl/Scripts/CommonScripts.cs
index baade44..e2c5a75 100644
--- a/NEW/src/JdeScoping.DataSync/Etl/Scripts/CommonScripts.cs
+++ b/NEW/src/JdeScoping.DataSync/Etl/Scripts/CommonScripts.cs
@@ -9,6 +9,7 @@ public static class CommonScripts
/// Parses a table name, extracting schema if present.
/// Supports: "Table", "dbo.Table", "[dbo].[Table]"
///
+ /// The table name to parse.
public static (string Schema, string Table) ParseTableName(string tableName)
{
var cleaned = tableName.Replace("[", "").Replace("]", "");
@@ -21,12 +22,19 @@ public static class CommonScripts
///
/// Formats a table name as a properly quoted [schema].[table] identifier.
///
+ /// The table name to format.
public static string FormatQualifiedTableName(string tableName)
{
var (schema, table) = ParseTableName(tableName);
return $"[{schema}].[{table}]";
}
+ ///
+ /// Creates a script runner that disables all indexes on a table.
+ ///
+ /// The database connection factory.
+ /// The table name to disable indexes for.
+ /// The execution timeout in seconds (default 300).
public static IScriptRunner DisableIndexes(
IDbConnectionFactory factory,
string tableName,
@@ -54,6 +62,12 @@ IF LEN(@sql) > 0 EXEC sp_executesql @sql;";
timeoutSeconds: timeoutSeconds);
}
+ ///
+ /// Creates a script runner that rebuilds all indexes on a table.
+ ///
+ /// The database connection factory.
+ /// The table name to rebuild indexes for.
+ /// The execution timeout in seconds (default 3600).
public static IScriptRunner RebuildIndexes(
IDbConnectionFactory factory,
string tableName,
@@ -70,6 +84,12 @@ EXEC sp_executesql @sql;";
timeoutSeconds: timeoutSeconds);
}
+ ///
+ /// Creates a script runner that updates statistics on a table.
+ ///
+ /// The database connection factory.
+ /// The table name to update statistics for.
+ /// The execution timeout in seconds (default 600).
public static IScriptRunner UpdateStatistics(
IDbConnectionFactory factory,
string tableName,
@@ -86,6 +106,14 @@ EXEC sp_executesql @sql;";
timeoutSeconds: timeoutSeconds);
}
+ ///
+ /// Creates a script runner for executing custom SQL.
+ ///
+ /// The database connection factory.
+ /// The SQL statement to execute.
+ /// The name/description of the script.
+ /// Optional parameters for the SQL statement.
+ /// The execution timeout in seconds (default 30).
public static IScriptRunner CustomSql(
IDbConnectionFactory factory,
string sql,
diff --git a/NEW/src/JdeScoping.DataSync/Etl/Scripts/SqlScriptRunner.cs b/NEW/src/JdeScoping.DataSync/Etl/Scripts/SqlScriptRunner.cs
index 8f033b2..0949974 100644
--- a/NEW/src/JdeScoping.DataSync/Etl/Scripts/SqlScriptRunner.cs
+++ b/NEW/src/JdeScoping.DataSync/Etl/Scripts/SqlScriptRunner.cs
@@ -4,6 +4,9 @@ using JdeScoping.DataSync.Etl.Contracts;
namespace JdeScoping.DataSync.Etl.Scripts;
+///
+/// SQL script runner that executes SQL commands against the database.
+///
public class SqlScriptRunner : IScriptRunner
{
private readonly IDbConnectionFactory _connectionFactory;
@@ -11,8 +14,19 @@ public class SqlScriptRunner : IScriptRunner
private readonly object? _parameters;
private readonly int _timeoutSeconds;
+ ///
+ /// The name of this script.
+ ///
public string ScriptName { get; }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The database connection factory.
+ /// The SQL command to execute.
+ /// The optional name of the script.
+ /// The optional parameters for the SQL command.
+ /// The command timeout in seconds.
public SqlScriptRunner(
IDbConnectionFactory connectionFactory,
string sql,
@@ -30,6 +44,10 @@ public class SqlScriptRunner : IScriptRunner
ScriptName = name ?? "SqlScript";
}
+ ///
+ /// Executes the SQL script asynchronously.
+ ///
+ /// The cancellation token.
public async Task ExecuteAsync(CancellationToken cancellationToken = default)
{
await using var connection = await _connectionFactory.CreateLotFinderConnectionAsync(cancellationToken);
diff --git a/NEW/src/JdeScoping.DataSync/Etl/Transformers/DataTransformerBase.cs b/NEW/src/JdeScoping.DataSync/Etl/Transformers/DataTransformerBase.cs
index a105846..32ebb6f 100644
--- a/NEW/src/JdeScoping.DataSync/Etl/Transformers/DataTransformerBase.cs
+++ b/NEW/src/JdeScoping.DataSync/Etl/Transformers/DataTransformerBase.cs
@@ -31,36 +31,53 @@ public abstract class DataTransformerBase : IDataTransformer
/// Gets the field count from the source reader.
/// Override to add or remove fields.
///
+ /// The source data reader.
+ /// The field count.
public virtual int GetFieldCount(IDataReader source) => source.FieldCount;
///
/// Gets the name of a field at the specified ordinal.
/// Override to rename fields.
///
+ /// The field ordinal.
+ /// The source data reader.
+ /// The field name.
public virtual string GetName(int ordinal, IDataReader source) => source.GetName(ordinal);
///
/// Gets the type of a field at the specified ordinal.
/// Override to change field types.
///
+ /// The field ordinal.
+ /// The source data reader.
+ /// The field type.
public virtual Type GetFieldType(int ordinal, IDataReader source) => source.GetFieldType(ordinal);
///
/// Gets the value of a field at the specified ordinal.
/// Override to transform values.
///
+ /// The field ordinal.
+ /// The source data reader.
+ /// The field value.
public virtual object GetValue(int ordinal, IDataReader source) => source.GetValue(ordinal);
///
/// Gets the ordinal of a field by name.
/// Override to support renamed fields.
///
+ /// The field name.
+ /// The source data reader.
+ /// The field ordinal.
public virtual int GetOrdinal(string name, IDataReader source) => source.GetOrdinal(name);
///
/// Checks if a field value is DBNull.
/// Override to handle null transformations.
///
+ /// The field ordinal.
+ /// The source data reader.
+ /// True if the field value is DBNull; otherwise, false.
public virtual bool IsDBNull(int ordinal, IDataReader source) => source.IsDBNull(ordinal);
///
@@ -76,6 +93,13 @@ public abstract class DataTransformerBase : IDataTransformer
/// Gets bytes from a field at the specified ordinal.
/// Throws NotSupportedException for computed columns (where MapOrdinal returns -1).
///
+ /// The field ordinal.
+ /// The offset in the field data.
+ /// The buffer to copy bytes into.
+ /// The offset in the buffer where copying begins.
+ /// The maximum number of bytes to copy.
+ /// The source data reader.
+ /// The number of bytes actually copied.
public virtual long GetBytes(int ordinal, long fieldOffset, byte[]? buffer,
int bufferOffset, int length, IDataReader source)
{
@@ -90,6 +114,13 @@ public abstract class DataTransformerBase : IDataTransformer
/// Gets characters from a field at the specified ordinal.
/// Throws NotSupportedException for computed columns (where MapOrdinal returns -1).
///
+ /// The field ordinal.
+ /// The offset in the field data.
+ /// The buffer to copy characters into.
+ /// The offset in the buffer where copying begins.
+ /// The maximum number of characters to copy.
+ /// The source data reader.
+ /// The number of characters actually copied.
public virtual long GetChars(int ordinal, long fieldOffset, char[]? buffer,
int bufferOffset, int length, IDataReader source)
{
@@ -104,6 +135,9 @@ public abstract class DataTransformerBase : IDataTransformer
/// Gets nested data reader for a field at the specified ordinal.
/// Throws NotSupportedException for computed columns (where MapOrdinal returns -1).
///
+ /// The field ordinal.
+ /// The source data reader.
+ /// A nested data reader for the field.
public virtual IDataReader GetData(int ordinal, IDataReader source)
{
var sourceOrdinal = MapOrdinal(ordinal, source);
@@ -117,6 +151,9 @@ public abstract class DataTransformerBase : IDataTransformer
/// Gets the data type name for a field at the specified ordinal.
/// Throws NotSupportedException for computed columns (where MapOrdinal returns -1).
///
+ /// The field ordinal.
+ /// The source data reader.
+ /// The data type name.
public virtual string GetDataTypeName(int ordinal, IDataReader source)
{
var sourceOrdinal = MapOrdinal(ordinal, source);
diff --git a/NEW/src/JdeScoping.DataSync/Etl/Transformers/TransformingDataReader.cs b/NEW/src/JdeScoping.DataSync/Etl/Transformers/TransformingDataReader.cs
index c400bc9..2ca55dc 100644
--- a/NEW/src/JdeScoping.DataSync/Etl/Transformers/TransformingDataReader.cs
+++ b/NEW/src/JdeScoping.DataSync/Etl/Transformers/TransformingDataReader.cs
@@ -11,6 +11,11 @@ internal sealed class TransformingDataReader : IDataReader
private readonly IDataReader _source;
private readonly DataTransformerBase _transformer;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The underlying data reader to wrap.
+ /// The transformer to apply to field values.
public TransformingDataReader(IDataReader source, DataTransformerBase transformer)
{
_source = source ?? throw new ArgumentNullException(nameof(source));
@@ -18,41 +23,196 @@ internal sealed class TransformingDataReader : IDataReader
}
// Properties and methods delegated to transformer
+ ///
+ /// Gets the number of columns in the current row.
+ ///
public int FieldCount => _transformer.GetFieldCount(_source);
+
+ ///
+ /// Gets the name of the specified column.
+ ///
+ /// The zero-based column ordinal.
+ /// The name of the specified column.
public string GetName(int i) => _transformer.GetName(i, _source);
+
+ ///
+ /// Gets the data type of the specified column.
+ ///
+ /// The zero-based column ordinal.
+ /// The data type of the specified column.
public Type GetFieldType(int i) => _transformer.GetFieldType(i, _source);
+
+ ///
+ /// Gets the column ordinal given the name of the column.
+ ///
+ /// The name of the column.
+ /// The zero-based column ordinal.
public int GetOrdinal(string name) => _transformer.GetOrdinal(name, _source);
+
+ ///
+ /// Gets the value of the specified column as an object, applying transformations.
+ ///
+ /// The zero-based column ordinal.
+ /// The transformed value of the specified column.
public object GetValue(int i) => _transformer.GetValue(i, _source);
+
+ ///
+ /// Gets whether the value of the specified column is null.
+ ///
+ /// The zero-based column ordinal.
+ /// True if the value is null; otherwise, false.
public bool IsDBNull(int i) => _transformer.IsDBNull(i, _source);
+
+ ///
+ /// Gets the value of the column at the specified ordinal, applying transformations.
+ ///
+ /// The zero-based column ordinal.
+ /// The transformed value of the column.
public object this[int i] => GetValue(i);
+
+ ///
+ /// Gets the value of the column with the specified name, applying transformations.
+ ///
+ /// The name of the column.
+ /// The transformed value of the column.
public object this[string name] => GetValue(GetOrdinal(name));
// Row navigation - delegated directly to source
+ ///
+ /// Advances the reader to the next record.
+ ///
+ /// True if there are more rows; otherwise, false.
public bool Read() => _source.Read();
+
+ ///
+ /// Advances the reader to the next result set.
+ ///
+ /// True if there are more result sets; otherwise, false.
public bool NextResult() => _source.NextResult();
+
+ ///
+ /// Gets the nesting depth of the current row.
+ ///
public int Depth => _source.Depth;
+
+ ///
+ /// Gets whether the reader is closed.
+ ///
public bool IsClosed => _source.IsClosed;
+
+ ///
+ /// Gets the number of rows affected by the last operation.
+ ///
public int RecordsAffected => _source.RecordsAffected;
+
+ ///
+ /// Closes the reader.
+ ///
public void Close() => _source.Close();
+
+ ///
+ /// Releases all resources used by the reader.
+ ///
public void Dispose() => _source.Dispose();
// Typed accessors - use GetValue for transformation support
+ ///
+ /// Gets the value of the specified column as a boolean.
+ ///
+ /// The zero-based column ordinal.
+ /// The boolean value of the column.
public bool GetBoolean(int i) => (bool)GetValue(i);
+
+ ///
+ /// Gets the value of the specified column as a byte.
+ ///
+ /// The zero-based column ordinal.
+ /// The byte value of the column.
public byte GetByte(int i) => (byte)GetValue(i);
+
+ ///
+ /// Gets the value of the specified column as a character.
+ ///
+ /// The zero-based column ordinal.
+ /// The character value of the column.
public char GetChar(int i) => (char)GetValue(i);
+
+ ///
+ /// Gets the value of the specified column as a DateTime.
+ ///
+ /// The zero-based column ordinal.
+ /// The DateTime value of the column.
public DateTime GetDateTime(int i) => (DateTime)GetValue(i);
+
+ ///
+ /// Gets the value of the specified column as a decimal.
+ ///
+ /// The zero-based column ordinal.
+ /// The decimal value of the column.
public decimal GetDecimal(int i) => (decimal)GetValue(i);
+
+ ///
+ /// Gets the value of the specified column as a double.
+ ///
+ /// The zero-based column ordinal.
+ /// The double value of the column.
public double GetDouble(int i) => (double)GetValue(i);
+
+ ///
+ /// Gets the value of the specified column as a float.
+ ///
+ /// The zero-based column ordinal.
+ /// The float value of the column.
public float GetFloat(int i) => (float)GetValue(i);
+
+ ///
+ /// Gets the value of the specified column as a GUID.
+ ///
+ /// The zero-based column ordinal.
+ /// The GUID value of the column.
public Guid GetGuid(int i) => (Guid)GetValue(i);
+
+ ///
+ /// Gets the value of the specified column as a 16-bit signed integer.
+ ///
+ /// The zero-based column ordinal.
+ /// The 16-bit signed integer value of the column.
public short GetInt16(int i) => (short)GetValue(i);
+
+ ///
+ /// Gets the value of the specified column as a 32-bit signed integer.
+ ///
+ /// The zero-based column ordinal.
+ /// The 32-bit signed integer value of the column.
public int GetInt32(int i) => (int)GetValue(i);
+
+ ///
+ /// Gets the value of the specified column as a 64-bit signed integer.
+ ///
+ /// The zero-based column ordinal.
+ /// The 64-bit signed integer value of the column.
public long GetInt64(int i) => (long)GetValue(i);
+
+ ///
+ /// Gets the value of the specified column as a string.
+ ///
+ /// The zero-based column ordinal.
+ /// The string value of the column.
public string GetString(int i) => (string)GetValue(i);
// Schema and bulk data access - delegated to transformer
+ ///
+ /// Gets the name of the type for the specified column.
+ ///
+ /// The zero-based column ordinal.
+ /// The name of the data type of the specified column.
public string GetDataTypeName(int i) => _transformer.GetDataTypeName(i, _source);
+ ///
+ /// Populates an object array with the values of the current row.
+ ///
+ /// An array of objects to populate with column values.
+ /// The number of values populated.
public int GetValues(object[] values)
{
var count = Math.Min(values.Length, FieldCount);
@@ -61,13 +221,40 @@ internal sealed class TransformingDataReader : IDataReader
return count;
}
+ ///
+ /// Gets the byte values of the specified column starting at the given offset.
+ ///
+ /// The zero-based column ordinal.
+ /// The offset within the field.
+ /// The buffer to read bytes into.
+ /// The offset in the buffer to start writing.
+ /// The maximum number of bytes to read.
+ /// The number of bytes read.
public long GetBytes(int i, long fieldOffset, byte[]? buffer, int bufferoffset, int length)
=> _transformer.GetBytes(i, fieldOffset, buffer, bufferoffset, length, _source);
+ ///
+ /// Gets the character values of the specified column starting at the given offset.
+ ///
+ /// The zero-based column ordinal.
+ /// The offset within the field.
+ /// The buffer to read characters into.
+ /// The offset in the buffer to start writing.
+ /// The maximum number of characters to read.
+ /// The number of characters read.
public long GetChars(int i, long fieldoffset, char[]? buffer, int bufferoffset, int length)
=> _transformer.GetChars(i, fieldoffset, buffer, bufferoffset, length, _source);
+ ///
+ /// Gets a nested data reader for the specified column.
+ ///
+ /// The zero-based column ordinal.
+ /// A nested data reader for the specified column.
public IDataReader GetData(int i) => _transformer.GetData(i, _source);
+ ///
+ /// Gets a DataTable that describes the schema of the result set.
+ ///
+ /// A DataTable describing the result set schema, or null if no schema is available.
public DataTable? GetSchemaTable() => _source.GetSchemaTable();
}
diff --git a/NEW/src/JdeScoping.DataSync/HealthChecks/DataSyncHealthCheck.cs b/NEW/src/JdeScoping.DataSync/HealthChecks/DataSyncHealthCheck.cs
index 81179a5..02f132b 100644
--- a/NEW/src/JdeScoping.DataSync/HealthChecks/DataSyncHealthCheck.cs
+++ b/NEW/src/JdeScoping.DataSync/HealthChecks/DataSyncHealthCheck.cs
@@ -13,6 +13,7 @@ public class DataSyncHealthCheck : IHealthCheck
///
/// Initializes a new instance of the class.
///
+ /// The data update repository.
public DataSyncHealthCheck(IDataUpdateRepository repository)
{
_repository = repository ?? throw new ArgumentNullException(nameof(repository));
diff --git a/NEW/src/JdeScoping.DataSync/Options/PipelineOptions.cs b/NEW/src/JdeScoping.DataSync/Options/PipelineOptions.cs
index 7f7f2ee..572f3e9 100644
--- a/NEW/src/JdeScoping.DataSync/Options/PipelineOptions.cs
+++ b/NEW/src/JdeScoping.DataSync/Options/PipelineOptions.cs
@@ -3,5 +3,9 @@ namespace JdeScoping.DataSync.Options;
public class PipelineOptions
{
public const string SectionName = "Pipelines";
+
+ ///
+ /// Gets or sets the path to the pipeline configuration file.
+ ///
public string ConfigPath { get; set; } = "Pipelines/pipelines.json";
}
diff --git a/NEW/src/JdeScoping.DataSync/Services/DataUpdateRepository.cs b/NEW/src/JdeScoping.DataSync/Services/DataUpdateRepository.cs
index f0aa012..0dea1bc 100644
--- a/NEW/src/JdeScoping.DataSync/Services/DataUpdateRepository.cs
+++ b/NEW/src/JdeScoping.DataSync/Services/DataUpdateRepository.cs
@@ -22,6 +22,8 @@ public class DataUpdateRepository : IDataUpdateRepository
///
/// Initializes a new instance of the class.
///
+ /// The database connection factory.
+ /// The logger instance.
public DataUpdateRepository(
IDbConnectionFactory connectionFactory,
ILogger logger)
diff --git a/NEW/src/JdeScoping.DataSync/Services/EtlPipelineFactory.cs b/NEW/src/JdeScoping.DataSync/Services/EtlPipelineFactory.cs
index 5efa4db..a59a0f0 100644
--- a/NEW/src/JdeScoping.DataSync/Services/EtlPipelineFactory.cs
+++ b/NEW/src/JdeScoping.DataSync/Services/EtlPipelineFactory.cs
@@ -53,6 +53,9 @@ public class EtlPipelineFactory : IEtlPipelineFactory
///
/// Creates a new pipeline factory with a pre-loaded configuration (for testing).
///
+ /// Factory for creating database connections.
+ /// Pre-loaded pipeline configuration.
+ /// Logger for pipeline execution.
internal EtlPipelineFactory(
IDbConnectionFactory connectionFactory,
PipelinesRoot config,
@@ -167,6 +170,15 @@ public class EtlPipelineFactory : IEtlPipelineFactory
private UpdateTypes _updateType = UpdateTypes.Hourly;
private DateTime? _minDtOverride;
+ ///
+ /// Initializes a new instance of the PipelineBuilder class.
+ ///
+ /// Factory for creating database connections.
+ /// The name of the table for this pipeline.
+ /// The pipeline configuration.
+ /// Global pipeline settings.
+ /// Default schedule configuration.
+ /// Logger for pipeline execution.
public PipelineBuilder(
IDbConnectionFactory connectionFactory,
string tableName,
@@ -183,18 +195,32 @@ public class EtlPipelineFactory : IEtlPipelineFactory
_logger = logger;
}
+ ///
+ /// Specifies the update type for this pipeline.
+ ///
+ /// The type of update (Mass, Daily, or Hourly).
+ /// The builder for fluent configuration.
public IEtlPipelineBuilder WithUpdateType(UpdateTypes updateType)
{
_updateType = updateType;
return this;
}
+ ///
+ /// Specifies the minimum date for incremental data extraction.
+ ///
+ /// The minimum date, or null for no filter.
+ /// The builder for fluent configuration.
public IEtlPipelineBuilder WithMinimumDate(DateTime? minDt)
{
_minDtOverride = minDt;
return this;
}
+ ///
+ /// Builds and returns the configured ETL pipeline.
+ ///
+ /// A configured ETL pipeline ready for execution.
public EtlPipeline Build()
{
return BuildWithSchedules();
diff --git a/NEW/src/JdeScoping.DataSync/Services/ScheduleChecker.cs b/NEW/src/JdeScoping.DataSync/Services/ScheduleChecker.cs
index e590a5b..04d80e5 100644
--- a/NEW/src/JdeScoping.DataSync/Services/ScheduleChecker.cs
+++ b/NEW/src/JdeScoping.DataSync/Services/ScheduleChecker.cs
@@ -21,6 +21,9 @@ public class ScheduleChecker : IScheduleChecker
///
/// Initializes a new instance of the class.
///
+ /// Repository for data update records.
+ /// Data sync configuration options.
+ /// Logger instance.
public ScheduleChecker(
IDataUpdateRepository repository,
IOptions options,
diff --git a/NEW/src/JdeScoping.DataSync/Services/SearchExecutionService.cs b/NEW/src/JdeScoping.DataSync/Services/SearchExecutionService.cs
index 146bca2..15fb809 100644
--- a/NEW/src/JdeScoping.DataSync/Services/SearchExecutionService.cs
+++ b/NEW/src/JdeScoping.DataSync/Services/SearchExecutionService.cs
@@ -21,6 +21,15 @@ public class SearchExecutionService : ISearchExecutionService
private readonly WorkProcessorOptions _options;
private readonly ILogger _logger;
+ ///
+ /// Initializes a new instance of the SearchExecutionService.
+ ///
+ /// The repository for search data access.
+ /// The processor for executing search queries.
+ /// The service for generating Excel export files.
+ /// The service for sending search status notifications.
+ /// The work processor configuration options.
+ /// The logger for recording search execution events.
public SearchExecutionService(
ISearchRepository searchRepository,
ISearchProcessor searchProcessor,
diff --git a/NEW/src/JdeScoping.DataSync/Services/SyncOrchestrator.cs b/NEW/src/JdeScoping.DataSync/Services/SyncOrchestrator.cs
index 3ead9ee..8793aab 100644
--- a/NEW/src/JdeScoping.DataSync/Services/SyncOrchestrator.cs
+++ b/NEW/src/JdeScoping.DataSync/Services/SyncOrchestrator.cs
@@ -21,6 +21,11 @@ public class SyncOrchestrator : ISyncOrchestrator
///
/// Initializes a new instance of the class.
///
+ /// Factory for creating service scopes.
+ /// Checker for determining pending sync tasks.
+ /// Data sync configuration options.
+ /// Logger instance.
+ /// Metrics collector for sync operations.
public SyncOrchestrator(
IServiceScopeFactory scopeFactory,
IScheduleChecker scheduleChecker,
diff --git a/NEW/src/JdeScoping.DataSync/Services/TableSyncOperation.cs b/NEW/src/JdeScoping.DataSync/Services/TableSyncOperation.cs
index ec566b1..3b16576 100644
--- a/NEW/src/JdeScoping.DataSync/Services/TableSyncOperation.cs
+++ b/NEW/src/JdeScoping.DataSync/Services/TableSyncOperation.cs
@@ -24,6 +24,11 @@ public class TableSyncOperation : ITableSyncOperation
///
/// Initializes a new instance of the class.
///
+ /// Factory for creating ETL pipelines.
+ /// Repository for managing data update records.
+ /// Data sync configuration options.
+ /// Logger for operation events.
+ /// Metrics collector for operation tracking.
public TableSyncOperation(
IEtlPipelineFactory pipelineFactory,
IDataUpdateRepository updateRepository,
diff --git a/NEW/src/JdeScoping.DataSync/Telemetry/DataSyncMetrics.cs b/NEW/src/JdeScoping.DataSync/Telemetry/DataSyncMetrics.cs
index f13d2ca..1ac7961 100644
--- a/NEW/src/JdeScoping.DataSync/Telemetry/DataSyncMetrics.cs
+++ b/NEW/src/JdeScoping.DataSync/Telemetry/DataSyncMetrics.cs
@@ -18,6 +18,7 @@ public class DataSyncMetrics
///
/// Initializes a new instance of the class.
///
+ /// The meter factory for creating metrics.
public DataSyncMetrics(IMeterFactory meterFactory)
{
var meter = meterFactory.Create("JdeScoping.DataSync");
@@ -61,6 +62,8 @@ public class DataSyncMetrics
///
/// Records that a sync operation has started.
///
+ /// The name of the table being synced.
+ /// The type of update (e.g., Mass, Daily, Hourly).
public void RecordOperationStarted(string tableName, string updateType)
{
_operationsStarted.Add(1,
@@ -71,6 +74,10 @@ public class DataSyncMetrics
///
/// Records that a sync operation completed successfully.
///
+ /// The name of the table being synced.
+ /// The type of update (e.g., Mass, Daily, Hourly).
+ /// The number of records processed.
+ /// The operation duration in seconds.
public void RecordOperationCompleted(string tableName, string updateType, long recordCount, double durationSeconds)
{
var tags = new KeyValuePair[]
@@ -87,6 +94,8 @@ public class DataSyncMetrics
///
/// Records that a sync operation failed.
///
+ /// The name of the table being synced.
+ /// The type of update (e.g., Mass, Daily, Hourly).
public void RecordOperationFailed(string tableName, string updateType)
{
_operationsFailed.Add(1,
@@ -105,6 +114,9 @@ public class DataSyncMetrics
///
/// Records completion of a sync cycle.
///
+ /// Number of successful operations in the cycle.
+ /// Number of failed operations in the cycle.
+ /// The cycle duration in seconds.
public void RecordCycleCompleted(int successCount, int failedCount, double durationSeconds)
{
_cyclesCompleted.Add(1,
diff --git a/NEW/src/JdeScoping.DataSync/WorkProcessor.cs b/NEW/src/JdeScoping.DataSync/WorkProcessor.cs
index 1ec43d8..fa06e0f 100644
--- a/NEW/src/JdeScoping.DataSync/WorkProcessor.cs
+++ b/NEW/src/JdeScoping.DataSync/WorkProcessor.cs
@@ -26,6 +26,10 @@ public class WorkProcessor : BackgroundService
///
/// Initializes a new instance of the class.
///
+ /// Factory for creating service scopes.
+ /// Configuration options for work processing.
+ /// Logger for recording work processor events.
+ /// Metrics collector for tracking work cycles.
public WorkProcessor(
IServiceScopeFactory scopeFactory,
IOptions options,
diff --git a/NEW/src/JdeScoping.ExcelIO/Generators/FluentTableWriter.cs b/NEW/src/JdeScoping.ExcelIO/Generators/FluentTableWriter.cs
index e1a7c42..1ef8c3c 100644
--- a/NEW/src/JdeScoping.ExcelIO/Generators/FluentTableWriter.cs
+++ b/NEW/src/JdeScoping.ExcelIO/Generators/FluentTableWriter.cs
@@ -12,6 +12,10 @@ public sealed class FluentTableWriter
{
private readonly ExcelMapRegistry _registry;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The registry containing Excel column maps for types.
public FluentTableWriter(ExcelMapRegistry registry)
{
_registry = registry;
@@ -20,6 +24,15 @@ public sealed class FluentTableWriter
///
/// Writes a table to the worksheet using the registered map for type T.
///
+ /// The type of objects to write to the table.
+ /// The Excel worksheet to write to.
+ /// The starting row number (1-based).
+ /// The starting column number (1-based).
+ /// The data to write to the table.
+ /// Optional override for the table name; uses map name if null.
+ /// Whether to show a merged header above the table.
+ /// Optional text to display in the merged header.
+ /// The created Excel table, or null if no columns are configured.
public IXLTable? WriteTable(
IXLWorksheet worksheet,
int startRow,
diff --git a/NEW/src/JdeScoping.ExcelIO/Mapping/ColumnBuilder.cs b/NEW/src/JdeScoping.ExcelIO/Mapping/ColumnBuilder.cs
index d82fded..1c29d55 100644
--- a/NEW/src/JdeScoping.ExcelIO/Mapping/ColumnBuilder.cs
+++ b/NEW/src/JdeScoping.ExcelIO/Mapping/ColumnBuilder.cs
@@ -9,12 +9,17 @@ public sealed class ColumnBuilder
{
private readonly ColumnDefinition _definition;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The column definition to configure.
internal ColumnBuilder(ColumnDefinition definition)
{
_definition = definition;
}
/// Sets the column display order.
+ /// The display order position.
public ColumnBuilder Order(int order)
{
_definition.Order = order;
@@ -22,6 +27,7 @@ public sealed class ColumnBuilder
}
/// Sets the column header text.
+ /// The header text to display.
public ColumnBuilder Header(string text)
{
_definition.HeaderText = text;
@@ -29,6 +35,7 @@ public sealed class ColumnBuilder
}
/// Sets the Excel number format.
+ /// The Excel number format string.
public ColumnBuilder Format(string format)
{
_definition.Format = format;
@@ -36,6 +43,7 @@ public sealed class ColumnBuilder
}
/// Sets a fixed column width (disables auto-width).
+ /// The fixed column width.
public ColumnBuilder Width(double width)
{
_definition.AutoWidth = false;
@@ -44,6 +52,7 @@ public sealed class ColumnBuilder
}
/// Enables text wrapping for the column.
+ /// Whether to enable text wrapping.
public ColumnBuilder WrapText(bool wrap = true)
{
_definition.WrapText = wrap;
diff --git a/NEW/src/JdeScoping.ExcelIO/Mapping/ExcelClassMap.cs b/NEW/src/JdeScoping.ExcelIO/Mapping/ExcelClassMap.cs
index 7f607ef..0ddc508 100644
--- a/NEW/src/JdeScoping.ExcelIO/Mapping/ExcelClassMap.cs
+++ b/NEW/src/JdeScoping.ExcelIO/Mapping/ExcelClassMap.cs
@@ -44,6 +44,8 @@ public abstract class ExcelClassMap : IExcelClassMap
///
/// Configures the table and tab names for this model.
///
+ /// The Excel table name (for named ranges).
+ /// The worksheet tab name.
protected void Table(string tableName, string tabName)
{
TableName = tableName;
@@ -53,6 +55,9 @@ public abstract class ExcelClassMap : IExcelClassMap
///
/// Maps a property to an Excel column.
///
+ /// The type of the property being mapped.
+ /// Expression specifying the property to map.
+ /// A column builder for further configuration of the mapped property.
protected ColumnBuilder Map(Expression> property)
{
var memberExpr = property.Body as MemberExpression
diff --git a/NEW/src/JdeScoping.ExcelIO/Mapping/ExcelMapRegistry.cs b/NEW/src/JdeScoping.ExcelIO/Mapping/ExcelMapRegistry.cs
index c5e96b8..c204ea0 100644
--- a/NEW/src/JdeScoping.ExcelIO/Mapping/ExcelMapRegistry.cs
+++ b/NEW/src/JdeScoping.ExcelIO/Mapping/ExcelMapRegistry.cs
@@ -10,6 +10,8 @@ public sealed class ExcelMapRegistry
///
/// Registers a map for a type.
///
+ /// The type to register a map for.
+ /// The Excel class map.
public void Register(ExcelClassMap map)
{
_maps[typeof(T)] = map;
@@ -18,11 +20,15 @@ public sealed class ExcelMapRegistry
///
/// Gets the map for a type.
///
+ /// The type to get the map for.
+ /// The registered Excel class map.
public IExcelClassMap GetMap() => GetMap(typeof(T));
///
/// Gets the map for a type.
///
+ /// The type to get the map for.
+ /// The registered Excel class map.
public IExcelClassMap GetMap(Type type)
{
if (_maps.TryGetValue(type, out var map))
@@ -36,10 +42,14 @@ public sealed class ExcelMapRegistry
///
/// Checks if a map exists for a type.
///
+ /// The type to check for.
+ /// True if a map exists for the type; otherwise, false.
public bool HasMap() => HasMap(typeof(T));
///
/// Checks if a map exists for a type.
///
+ /// The type to check for.
+ /// True if a map exists for the type; otherwise, false.
public bool HasMap(Type type) => _maps.ContainsKey(type);
}
diff --git a/NEW/src/JdeScoping.ExcelIO/Mapping/Maps/FilterEntryMaps.cs b/NEW/src/JdeScoping.ExcelIO/Mapping/Maps/FilterEntryMaps.cs
index cc5db1a..10d1804 100644
--- a/NEW/src/JdeScoping.ExcelIO/Mapping/Maps/FilterEntryMaps.cs
+++ b/NEW/src/JdeScoping.ExcelIO/Mapping/Maps/FilterEntryMaps.cs
@@ -8,6 +8,9 @@ namespace JdeScoping.ExcelIO.Mapping.Maps;
///
public sealed class TimespanFilterMap : ExcelClassMap
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
public TimespanFilterMap()
{
Table("Timespan_Filter", "Timespan Filter");
@@ -22,6 +25,9 @@ public sealed class TimespanFilterMap : ExcelClassMap
///
public sealed class WorkOrderFilterEntryMap : ExcelClassMap
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
public WorkOrderFilterEntryMap()
{
Table("Work_Order_Filter", "Work Order Filter");
@@ -36,6 +42,9 @@ public sealed class WorkOrderFilterEntryMap : ExcelClassMap
public sealed class ItemNumberFilterEntryMap : ExcelClassMap
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
public ItemNumberFilterEntryMap()
{
Table("Item_Number_Filter", "Item Number Filter");
@@ -50,6 +59,9 @@ public sealed class ItemNumberFilterEntryMap : ExcelClassMap
public sealed class ProfitCenterFilterEntryMap : ExcelClassMap
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
public ProfitCenterFilterEntryMap()
{
Table("Profit_Center_Filter", "Profit Center Filter");
@@ -64,6 +76,9 @@ public sealed class ProfitCenterFilterEntryMap : ExcelClassMap
public sealed class WorkCenterFilterEntryMap : ExcelClassMap
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
public WorkCenterFilterEntryMap()
{
Table("Work_Center_Filter", "Work Center Filter");
@@ -78,6 +93,9 @@ public sealed class WorkCenterFilterEntryMap : ExcelClassMap
public sealed class OperatorFilterEntryMap : ExcelClassMap
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
public OperatorFilterEntryMap()
{
Table("Operator_Filter", "Operator Filter");
@@ -93,6 +111,9 @@ public sealed class OperatorFilterEntryMap : ExcelClassMap
///
public sealed class ComponentLotFilterEntryMap : ExcelClassMap
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
public ComponentLotFilterEntryMap()
{
Table("Component_Lot_Filter", "Component Lot Filter");
@@ -107,6 +128,9 @@ public sealed class ComponentLotFilterEntryMap : ExcelClassMap
public sealed class ItemOperationMisFilterEntryMap : ExcelClassMap
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
public ItemOperationMisFilterEntryMap()
{
Table("Item_Operation_MIS_Filter", "Item/Operation/MIS Filter");
diff --git a/NEW/src/JdeScoping.ExcelIO/Mapping/Maps/MisNonMatchSearchResultMap.cs b/NEW/src/JdeScoping.ExcelIO/Mapping/Maps/MisNonMatchSearchResultMap.cs
index 66ef306..6da5361 100644
--- a/NEW/src/JdeScoping.ExcelIO/Mapping/Maps/MisNonMatchSearchResultMap.cs
+++ b/NEW/src/JdeScoping.ExcelIO/Mapping/Maps/MisNonMatchSearchResultMap.cs
@@ -8,6 +8,10 @@ namespace JdeScoping.ExcelIO.Mapping.Maps;
///
public sealed class MisNonMatchSearchResultMap : ExcelClassMap
{
+ ///
+ /// Initializes a new instance of the class.
+ /// Defines the column mappings and headers for exporting MisNonMatchSearchResult to Excel.
+ ///
public MisNonMatchSearchResultMap()
{
Table("Investigation", "Investigation");
diff --git a/NEW/src/JdeScoping.ExcelIO/Mapping/Maps/MisSearchResultMap.cs b/NEW/src/JdeScoping.ExcelIO/Mapping/Maps/MisSearchResultMap.cs
index 857d7fe..48b6b40 100644
--- a/NEW/src/JdeScoping.ExcelIO/Mapping/Maps/MisSearchResultMap.cs
+++ b/NEW/src/JdeScoping.ExcelIO/Mapping/Maps/MisSearchResultMap.cs
@@ -8,6 +8,9 @@ namespace JdeScoping.ExcelIO.Mapping.Maps;
///
public sealed class MisSearchResultMap : ExcelClassMap
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
public MisSearchResultMap()
{
Table("MIS_Info", "MIS Info");
diff --git a/NEW/src/JdeScoping.ExcelIO/Mapping/Maps/SearchResultMap.cs b/NEW/src/JdeScoping.ExcelIO/Mapping/Maps/SearchResultMap.cs
index 12ba329..20e637d 100644
--- a/NEW/src/JdeScoping.ExcelIO/Mapping/Maps/SearchResultMap.cs
+++ b/NEW/src/JdeScoping.ExcelIO/Mapping/Maps/SearchResultMap.cs
@@ -8,6 +8,9 @@ namespace JdeScoping.ExcelIO.Mapping.Maps;
///
public sealed class SearchResultMap : ExcelClassMap
{
+ ///
+ /// Initializes a new instance of the SearchResultMap class.
+ ///
public SearchResultMap()
{
Table("Search_Results", "Search Results");
diff --git a/NEW/src/JdeScoping.ExcelIO/Parsing/ExcelParserService.cs b/NEW/src/JdeScoping.ExcelIO/Parsing/ExcelParserService.cs
index 1ea29d1..d2e4525 100644
--- a/NEW/src/JdeScoping.ExcelIO/Parsing/ExcelParserService.cs
+++ b/NEW/src/JdeScoping.ExcelIO/Parsing/ExcelParserService.cs
@@ -12,6 +12,10 @@ public class ExcelParserService : IExcelParserService
{
private readonly ILogger _logger;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The logger instance.
public ExcelParserService(ILogger logger)
{
_logger = logger;
diff --git a/NEW/src/JdeScoping.Infrastructure/Auth/LdapAuthService.cs b/NEW/src/JdeScoping.Infrastructure/Auth/LdapAuthService.cs
index b4b32f8..057e073 100644
--- a/NEW/src/JdeScoping.Infrastructure/Auth/LdapAuthService.cs
+++ b/NEW/src/JdeScoping.Infrastructure/Auth/LdapAuthService.cs
@@ -38,6 +38,11 @@ public sealed class LdapAuthService : IAuthenticationService
private readonly LdapOptions _options;
private readonly ILogger _logger;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The LDAP configuration options.
+ /// Logger for recording LDAP authentication events.
public LdapAuthService(
IOptions options,
ILogger logger)
diff --git a/NEW/src/JdeScoping.Infrastructure/Security/RsaKeyService.cs b/NEW/src/JdeScoping.Infrastructure/Security/RsaKeyService.cs
index f68283b..8acd9dd 100644
--- a/NEW/src/JdeScoping.Infrastructure/Security/RsaKeyService.cs
+++ b/NEW/src/JdeScoping.Infrastructure/Security/RsaKeyService.cs
@@ -56,6 +56,9 @@ public class RsaKeyService : IRsaKeyService, IDisposable
public byte[] Decrypt(byte[] ciphertext)
=> _rsa.Decrypt(ciphertext, RSAEncryptionPadding.OaepSHA256);
+ ///
+ /// Releases the RSA key resources.
+ ///
public void Dispose()
{
_rsa.Dispose();
diff --git a/NEW/src/JdeScoping.Infrastructure/Security/SecretsMigrator.cs b/NEW/src/JdeScoping.Infrastructure/Security/SecretsMigrator.cs
index 5c801aa..5807241 100644
--- a/NEW/src/JdeScoping.Infrastructure/Security/SecretsMigrator.cs
+++ b/NEW/src/JdeScoping.Infrastructure/Security/SecretsMigrator.cs
@@ -22,6 +22,13 @@ public class SecretsMigrator
public const string ExcelCriteriaPasswordKey = "ExcelExport:CriteriaSheetPassword";
public const string ExcelDataPasswordKey = "ExcelExport:DataSheetPassword";
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Service for secure secret storage.
+ /// Application configuration containing existing secrets.
+ /// Options controlling secret migration behavior.
+ /// Logger for recording migration operations.
public SecretsMigrator(
ISecureStoreService secureStore,
IConfiguration configuration,
diff --git a/NEW/src/JdeScoping.Infrastructure/Security/SecureStoreRsaKeyService.cs b/NEW/src/JdeScoping.Infrastructure/Security/SecureStoreRsaKeyService.cs
index f7de386..c80e195 100644
--- a/NEW/src/JdeScoping.Infrastructure/Security/SecureStoreRsaKeyService.cs
+++ b/NEW/src/JdeScoping.Infrastructure/Security/SecureStoreRsaKeyService.cs
@@ -22,6 +22,8 @@ public class SecureStoreRsaKeyService : IRsaKeyService, IDisposable
///
/// Creates a new SecureStore-backed RSA key service.
///
+ /// Service for storing keys securely.
+ /// Logger for key service operations.
public SecureStoreRsaKeyService(
ISecureStoreService secureStore,
ILogger logger)
@@ -61,6 +63,9 @@ public class SecureStoreRsaKeyService : IRsaKeyService, IDisposable
return _rsa.Decrypt(ciphertext, RSAEncryptionPadding.OaepSHA256);
}
+ ///
+ /// Releases resources used by the RSA key service.
+ ///
public void Dispose()
{
if (_disposed) return;
diff --git a/NEW/src/JdeScoping.Infrastructure/Security/SecureStoreService.cs b/NEW/src/JdeScoping.Infrastructure/Security/SecureStoreService.cs
index bb37c83..595cde1 100644
--- a/NEW/src/JdeScoping.Infrastructure/Security/SecureStoreService.cs
+++ b/NEW/src/JdeScoping.Infrastructure/Security/SecureStoreService.cs
@@ -22,6 +22,8 @@ public class SecureStoreService : ISecureStoreService
///
/// Creates a new SecureStoreService instance.
///
+ /// The SecureStore configuration options.
+ /// The logger instance.
public SecureStoreService(IOptions options, ILogger logger)
{
_logger = logger;
@@ -160,6 +162,9 @@ public class SecureStoreService : ISecureStoreService
///
public IEnumerable Keys => _keys.ToList().AsReadOnly();
+ ///
+ /// Disposes the secure store and saves any pending changes.
+ ///
public void Dispose()
{
if (_disposed) return;
diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/Models/ConfigModel.cs b/NEW/src/Utils/JdeScoping.ConfigManager/Models/ConfigModel.cs
index 7a19289..076458e 100644
--- a/NEW/src/Utils/JdeScoping.ConfigManager/Models/ConfigModel.cs
+++ b/NEW/src/Utils/JdeScoping.ConfigManager/Models/ConfigModel.cs
@@ -7,69 +7,226 @@ namespace JdeScoping.ConfigManager.Models;
///
public class ConfigModel
{
+ ///
+ /// Gets or sets the data synchronization configuration.
+ ///
public DataSyncSection DataSync { get; set; } = new();
+
+ ///
+ /// Gets or sets the data access configuration.
+ ///
public DataAccessSection DataAccess { get; set; } = new();
+
+ ///
+ /// Gets or sets the authentication configuration.
+ ///
public AuthSection Auth { get; set; } = new();
+
+ ///
+ /// Gets or sets the LDAP directory configuration.
+ ///
public LdapSection Ldap { get; set; } = new();
+
+ ///
+ /// Gets or sets the search processing configuration.
+ ///
public SearchSection Search { get; set; } = new();
+
+ ///
+ /// Gets or sets the Excel export configuration.
+ ///
public ExcelExportSection ExcelExport { get; set; } = new();
+
+ ///
+ /// Gets or sets the connection strings for external data sources.
+ ///
public Dictionary ConnectionStrings { get; set; } = new();
}
public class DataSyncSection
{
+ ///
+ /// Gets or sets the interval between successive data sync checks.
+ ///
public TimeSpan CheckInterval { get; set; } = TimeSpan.FromMinutes(1);
+
+ ///
+ /// Gets or sets the maximum degree of parallelism for sync operations.
+ ///
public int MaxDegreeOfParallelism { get; set; } = 4;
+
+ ///
+ /// Gets or sets the batch size for data sync operations.
+ ///
public int BatchSize { get; set; } = 50000;
+
+ ///
+ /// Gets or sets the batch size for bulk copy operations.
+ ///
public int BulkCopyBatchSize { get; set; } = 5000;
+
+ ///
+ /// Gets or sets the lookback multiplier for data sync delta calculations.
+ ///
public double LookbackMultiplier { get; set; } = 1.5;
+
+ ///
+ /// Gets or sets the number of days to retain synced data before purging.
+ ///
public int PurgeRetentionDays { get; set; } = 90;
+
+ ///
+ /// Gets or sets the timeout in seconds for sync operations.
+ ///
public int SyncTimeoutSeconds { get; set; } = 3600;
+
+ ///
+ /// Gets or sets a value indicating whether data synchronization is enabled.
+ ///
public bool Enabled { get; set; } = true;
}
public class DataAccessSection
{
+ ///
+ /// Gets or sets the default timeout in seconds for database queries.
+ ///
public int DefaultTimeoutSeconds { get; set; } = 30;
+
+ ///
+ /// Gets or sets the timeout in seconds for lot usage queries.
+ ///
public int LotUsageTimeoutSeconds { get; set; } = 120;
+
+ ///
+ /// Gets or sets the timeout in seconds for MIS data queries.
+ ///
public int MisDataTimeoutSeconds { get; set; } = 300;
+
+ ///
+ /// Gets or sets the schema name for production data.
+ ///
public string ProductionSchema { get; set; } = "prod";
+
+ ///
+ /// Gets or sets the schema name for archive data.
+ ///
public string ArchiveSchema { get; set; } = "archive";
+
+ ///
+ /// Gets or sets the schema name for staging data.
+ ///
public string StageSchema { get; set; } = "stage";
+
+ ///
+ /// Gets or sets a value indicating whether detailed query logging is enabled.
+ ///
public bool EnableDetailedLogging { get; set; } = false;
}
public class AuthSection
{
+ ///
+ /// Gets or sets the name of the authentication cookie.
+ ///
public string CookieName { get; set; } = ".JdeScoping.Auth";
+
+ ///
+ /// Gets or sets the cookie expiration time in minutes.
+ ///
public int CookieExpirationMinutes { get; set; } = 480;
}
public class LdapSection
{
+ ///
+ /// Gets or sets the LDAP server URLs to connect to.
+ ///
public string[] ServerUrls { get; set; } = [];
+
+ ///
+ /// Gets or sets the distinguished name of the LDAP group for authorization.
+ ///
public string GroupDn { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the base distinguished name for LDAP searches.
+ ///
public string SearchBase { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the connection timeout in seconds for LDAP operations.
+ ///
public int ConnectionTimeoutSeconds { get; set; } = 30;
+
+ ///
+ /// Gets or sets a value indicating whether to use fake authentication instead of LDAP.
+ ///
public bool UseFakeAuth { get; set; } = false;
+
+ ///
+ /// Gets or sets an array of user names that bypass group membership validation.
+ ///
public string[] AdminBypassUsers { get; set; } = [];
}
public class SearchSection
{
+ ///
+ /// Gets or sets the maximum number of result rows returned by a search.
+ ///
public int MaxResultRows { get; set; } = 100000;
+
+ ///
+ /// Gets or sets the timeout in seconds for search operations.
+ ///
public int TimeoutSeconds { get; set; } = 300;
+
+ ///
+ /// Gets or sets the maximum number of concurrent search operations allowed.
+ ///
public int MaxConcurrentSearches { get; set; } = 5;
}
public class ExcelExportSection
{
+ ///
+ /// Gets or sets the password for protecting the criteria worksheet.
+ ///
public string CriteriaSheetPassword { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the password for protecting the data worksheet.
+ ///
public string DataSheetPassword { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the maximum number of rows per Excel worksheet.
+ ///
public int MaxRowsPerSheet { get; set; } = 1000000;
+
+ ///
+ /// Gets or sets the default date format for Excel exports.
+ ///
public string DefaultDateFormat { get; set; } = "yyyy-MM-dd HH:mm:ss";
+
+ ///
+ /// Gets or sets a value indicating whether to write debug output to files.
+ ///
public bool DebugWriteToFile { get; set; } = false;
+
+ ///
+ /// Gets or sets the directory path for debug output files.
+ ///
public string DebugOutputDirectory { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the time zone identifier for date/time conversions.
+ ///
public string TimezoneId { get; set; } = "America/Chicago";
+
+ ///
+ /// Gets or sets the time zone abbreviation for display purposes.
+ ///
public string TimezoneAbbreviation { get; set; } = "CT";
}
diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/Models/PipelineModel.cs b/NEW/src/Utils/JdeScoping.ConfigManager/Models/PipelineModel.cs
index 43a5401..325f6e5 100644
--- a/NEW/src/Utils/JdeScoping.ConfigManager/Models/PipelineModel.cs
+++ b/NEW/src/Utils/JdeScoping.ConfigManager/Models/PipelineModel.cs
@@ -5,56 +5,144 @@ namespace JdeScoping.ConfigManager.Models;
///
public class PipelinesConfigModel
{
+ ///
+ /// Gets or sets the pipeline settings.
+ ///
public PipelineSettings Settings { get; set; } = new();
+
+ ///
+ /// Gets or sets the default schedules for all pipelines.
+ ///
public ScheduleDefaults ScheduleDefaults { get; set; } = new();
+
+ ///
+ /// Gets or sets the collection of named pipelines.
+ ///
public Dictionary Pipelines { get; set; } = new();
}
public class PipelineSettings
{
+ ///
+ /// Gets or sets the timezone for scheduling operations.
+ ///
public string Timezone { get; set; } = "UTC";
}
public class ScheduleDefaults
{
+ ///
+ /// Gets or sets the default mass data refresh schedule.
+ ///
public ScheduleModel Mass { get; set; } = new() { Enabled = true, IntervalMinutes = 10080, PrePurge = true, ReIndex = true };
+
+ ///
+ /// Gets or sets the default daily data refresh schedule.
+ ///
public ScheduleModel Daily { get; set; } = new() { Enabled = true, IntervalMinutes = 1440 };
+
+ ///
+ /// Gets or sets the default hourly data refresh schedule.
+ ///
public ScheduleModel Hourly { get; set; } = new() { Enabled = true, IntervalMinutes = 60 };
}
public class PipelineModel
{
+ ///
+ /// Gets or sets the source configuration for data extraction.
+ ///
public PipelineSource Source { get; set; } = new();
+
+ ///
+ /// Gets or sets the schedule configurations for this pipeline.
+ ///
public PipelineSchedules Schedules { get; set; } = new();
+
+ ///
+ /// Gets or sets the destination configuration for data loading.
+ ///
public PipelineDestination Destination { get; set; } = new();
+
+ ///
+ /// Gets or sets optional scripts to execute after pipeline completion.
+ ///
public string[]? PostScripts { get; set; }
}
public class PipelineSource
{
+ ///
+ /// Gets or sets the source database connection name.
+ ///
public string Connection { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the query to extract data from the source.
+ ///
public string Query { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the optional mass query for full data extraction.
+ ///
public string? MassQuery { get; set; }
+
+ ///
+ /// Gets or sets the query parameters and their definitions.
+ ///
public Dictionary Parameters { get; set; } = new();
}
public class ParameterDefinition
{
+ ///
+ /// Gets or sets the parameter name.
+ ///
public string Name { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the optional parameter format string.
+ ///
public string? Format { get; set; }
+
+ ///
+ /// Gets or sets the optional parameter source or derivation logic.
+ ///
public string? Source { get; set; }
}
public class PipelineSchedules
{
+ ///
+ /// Gets or sets the mass refresh schedule for this pipeline.
+ ///
public ScheduleModel? Mass { get; set; }
+
+ ///
+ /// Gets or sets the daily refresh schedule for this pipeline.
+ ///
public ScheduleModel? Daily { get; set; }
+
+ ///
+ /// Gets or sets the hourly refresh schedule for this pipeline.
+ ///
public ScheduleModel? Hourly { get; set; }
}
public class PipelineDestination
{
+ ///
+ /// Gets or sets the destination table name.
+ ///
public string Table { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the columns used to match existing records for updates.
+ ///
public string[] MatchColumns { get; set; } = [];
+
+ ///
+ /// Gets or sets the columns to exclude from update operations.
+ ///
public string[] ExcludeFromUpdate { get; set; } = [];
}
diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/Models/ScheduleModel.cs b/NEW/src/Utils/JdeScoping.ConfigManager/Models/ScheduleModel.cs
index f36413d..bf6f845 100644
--- a/NEW/src/Utils/JdeScoping.ConfigManager/Models/ScheduleModel.cs
+++ b/NEW/src/Utils/JdeScoping.ConfigManager/Models/ScheduleModel.cs
@@ -5,8 +5,23 @@ namespace JdeScoping.ConfigManager.Models;
///
public class ScheduleModel
{
+ ///
+ /// Gets or sets a value indicating whether the scheduled task is enabled.
+ ///
public bool Enabled { get; set; } = true;
+
+ ///
+ /// Gets or sets the interval in minutes between scheduled task executions.
+ ///
public int IntervalMinutes { get; set; } = 60;
+
+ ///
+ /// Gets or sets a value indicating whether to purge data before task execution.
+ ///
public bool PrePurge { get; set; } = false;
+
+ ///
+ /// Gets or sets a value indicating whether to reindex after task execution.
+ ///
public bool ReIndex { get; set; } = false;
}
diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/Program.cs b/NEW/src/Utils/JdeScoping.ConfigManager/Program.cs
index da77ac8..73b8a23 100644
--- a/NEW/src/Utils/JdeScoping.ConfigManager/Program.cs
+++ b/NEW/src/Utils/JdeScoping.ConfigManager/Program.cs
@@ -4,10 +4,18 @@ namespace JdeScoping.ConfigManager;
class Program
{
+ ///
+ /// The entry point of the application.
+ ///
+ /// Command-line arguments.
[STAThread]
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
+ ///
+ /// Builds the Avalonia application builder with platform and font configuration.
+ ///
+ /// A configured AppBuilder ready for application startup.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure()
.UsePlatformDetect()
diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/Services/AutoDiscoveryService.cs b/NEW/src/Utils/JdeScoping.ConfigManager/Services/AutoDiscoveryService.cs
index 5e2f0c8..a95520d 100644
--- a/NEW/src/Utils/JdeScoping.ConfigManager/Services/AutoDiscoveryService.cs
+++ b/NEW/src/Utils/JdeScoping.ConfigManager/Services/AutoDiscoveryService.cs
@@ -17,12 +17,22 @@ public class AutoDiscoveryService : IAutoDiscoveryService
private const string EnvVarName = "JDESCOPING_CONFIG_PATH";
private const string AppSettingsFileName = "appsettings.json";
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The file system abstraction to use for directory and file checks.
+ /// Optional logger for recording discovery process information.
public AutoDiscoveryService(IFileSystem fileSystem, ILogger? logger = null)
{
_fileSystem = fileSystem;
_logger = logger;
}
+ ///
+ /// Finds the configuration folder using a prioritized search strategy.
+ ///
+ /// Cancellation token for the async operation.
+ /// The path to a valid configuration folder, or null if none is found.
public Task FindConfigFolderAsync(CancellationToken ct = default)
{
// 1. Check environment variable
diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/Services/BackupService.cs b/NEW/src/Utils/JdeScoping.ConfigManager/Services/BackupService.cs
index 264431e..5bec3ff 100644
--- a/NEW/src/Utils/JdeScoping.ConfigManager/Services/BackupService.cs
+++ b/NEW/src/Utils/JdeScoping.ConfigManager/Services/BackupService.cs
@@ -12,12 +12,24 @@ public class BackupService : IBackupService
private readonly ILogger? _logger;
private const string TimestampFormat = "yyyy-MM-dd_HHmmss";
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The file system abstraction for file operations.
+ /// Optional logger for diagnostic messages.
public BackupService(IFileSystem fileSystem, ILogger? logger = null)
{
_fileSystem = fileSystem;
_logger = logger;
}
+ ///
+ /// Creates a backup copy of the specified file with a timestamp suffix.
+ ///
+ /// The path of the file to backup.
+ /// Cancellation token for the operation.
+ /// The path of the created backup file.
+ /// Thrown when the source file does not exist.
public async Task CreateBackupAsync(string filePath, CancellationToken ct = default)
{
if (!_fileSystem.FileExists(filePath))
@@ -34,6 +46,12 @@ public class BackupService : IBackupService
return backupPath;
}
+ ///
+ /// Retrieves a list of existing backups for the specified file, sorted by timestamp descending.
+ ///
+ /// The original file path to find backups for.
+ /// Cancellation token for the operation.
+ /// A read-only list of backup information sorted by timestamp.
public async Task> GetBackupsAsync(string filePath, CancellationToken ct = default)
{
var directory = _fileSystem.GetDirectoryName(filePath);
@@ -59,12 +77,24 @@ public class BackupService : IBackupService
return backups.OrderByDescending(b => b.Timestamp).ToList();
}
+ ///
+ /// Restores a backup file by copying it to the target location.
+ ///
+ /// The path of the backup file to restore from.
+ /// The target path where the backup should be restored.
+ /// Cancellation token for the operation.
public async Task RestoreBackupAsync(string backupPath, string targetPath, CancellationToken ct = default)
{
_logger?.LogInformation("Restoring backup from {BackupPath} to {TargetPath}", backupPath, targetPath);
await _fileSystem.CopyFileAsync(backupPath, targetPath, ct);
}
+ ///
+ /// Removes old backup files, keeping only the most recent backups.
+ ///
+ /// The original file path to find backups for.
+ /// The number of most recent backups to retain (default: 10).
+ /// Cancellation token for the operation.
public async Task CleanupOldBackupsAsync(string filePath, int keepCount = 10, CancellationToken ct = default)
{
var backups = await GetBackupsAsync(filePath, ct);
diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/Services/ConfigFileService.cs b/NEW/src/Utils/JdeScoping.ConfigManager/Services/ConfigFileService.cs
index a11c952..020d1cf 100644
--- a/NEW/src/Utils/JdeScoping.ConfigManager/Services/ConfigFileService.cs
+++ b/NEW/src/Utils/JdeScoping.ConfigManager/Services/ConfigFileService.cs
@@ -21,12 +21,24 @@ public class ConfigFileService : IConfigFileService
PropertyNameCaseInsensitive = true
};
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The file system abstraction for file operations.
+ /// Optional logger for diagnostic messages.
public ConfigFileService(IFileSystem fileSystem, ILogger? logger = null)
{
_fileSystem = fileSystem;
_logger = logger;
}
+ ///
+ /// Loads the application settings configuration from the specified file path.
+ ///
+ /// The file path to load appsettings from.
+ /// Cancellation token for the operation.
+ /// The loaded configuration model or a new empty model if deserialization fails.
+ /// Thrown when the JSON cannot be parsed.
public async Task LoadAppSettingsAsync(string path, CancellationToken ct = default)
{
_logger?.LogInformation("Loading appsettings from {Path}", path);
@@ -43,6 +55,13 @@ public class ConfigFileService : IConfigFileService
}
}
+ ///
+ /// Loads the pipelines configuration from the specified file path.
+ ///
+ /// The file path to load pipelines from.
+ /// Cancellation token for the operation.
+ /// The loaded pipelines configuration model or a new empty model if deserialization fails.
+ /// Thrown when the JSON cannot be parsed.
public async Task LoadPipelinesAsync(string path, CancellationToken ct = default)
{
_logger?.LogInformation("Loading pipelines from {Path}", path);
@@ -59,6 +78,12 @@ public class ConfigFileService : IConfigFileService
}
}
+ ///
+ /// Saves the application settings configuration to the specified file path.
+ ///
+ /// The file path to save appsettings to.
+ /// The configuration model to save.
+ /// Cancellation token for the operation.
public async Task SaveAppSettingsAsync(string path, ConfigModel config, CancellationToken ct = default)
{
_logger?.LogInformation("Saving appsettings to {Path}", path);
@@ -66,6 +91,12 @@ public class ConfigFileService : IConfigFileService
await _fileSystem.WriteAllTextAsync(path, json, ct);
}
+ ///
+ /// Saves the pipelines configuration to the specified file path.
+ ///
+ /// The file path to save pipelines to.
+ /// The pipelines configuration model to save.
+ /// Cancellation token for the operation.
public async Task SavePipelinesAsync(string path, PipelinesConfigModel config, CancellationToken ct = default)
{
_logger?.LogInformation("Saving pipelines to {Path}", path);
diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/Services/ConfigLoadException.cs b/NEW/src/Utils/JdeScoping.ConfigManager/Services/ConfigLoadException.cs
index 12a78de..c0d6f8b 100644
--- a/NEW/src/Utils/JdeScoping.ConfigManager/Services/ConfigLoadException.cs
+++ b/NEW/src/Utils/JdeScoping.ConfigManager/Services/ConfigLoadException.cs
@@ -5,8 +5,17 @@ namespace JdeScoping.ConfigManager.Services;
///
public class ConfigLoadException : Exception
{
+ ///
+ /// Gets the path to the configuration file that failed to load.
+ ///
public string FilePath { get; }
+ ///
+ /// Initializes a new instance of the ConfigLoadException class.
+ ///
+ /// The path to the configuration file that failed to load.
+ /// The error message describing the failure.
+ /// The inner exception that caused this exception, if any.
public ConfigLoadException(string filePath, string message, Exception? inner = null)
: base(message, inner)
{
diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/Services/DiffService.cs b/NEW/src/Utils/JdeScoping.ConfigManager/Services/DiffService.cs
index b5974a5..7235c49 100644
--- a/NEW/src/Utils/JdeScoping.ConfigManager/Services/DiffService.cs
+++ b/NEW/src/Utils/JdeScoping.ConfigManager/Services/DiffService.cs
@@ -9,6 +9,12 @@ namespace JdeScoping.ConfigManager.Services;
///
public class DiffService : IDiffService
{
+ ///
+ /// Generates a diff between original and modified text content.
+ ///
+ /// The original text content.
+ /// The modified text content.
+ /// A diff result containing added, removed, and unchanged lines with counts.
public DiffResult GenerateDiff(string original, string modified)
{
var diffBuilder = new InlineDiffBuilder(new Differ());
diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/Services/FileSystem.cs b/NEW/src/Utils/JdeScoping.ConfigManager/Services/FileSystem.cs
index 00f5de1..dcc5c18 100644
--- a/NEW/src/Utils/JdeScoping.ConfigManager/Services/FileSystem.cs
+++ b/NEW/src/Utils/JdeScoping.ConfigManager/Services/FileSystem.cs
@@ -5,36 +5,96 @@ namespace JdeScoping.ConfigManager.Services;
///
public class FileSystem : IFileSystem
{
+ ///
+ /// Determines whether the specified file exists.
+ ///
+ /// The file path to check.
+ /// True if the file exists; otherwise, false.
public bool FileExists(string path) => File.Exists(path);
+ ///
+ /// Determines whether the specified directory exists.
+ ///
+ /// The directory path to check.
+ /// True if the directory exists; otherwise, false.
public bool DirectoryExists(string path) => Directory.Exists(path);
+ ///
+ /// Reads all text from the specified file asynchronously.
+ ///
+ /// The file path to read from.
+ /// Cancellation token for the operation.
+ /// The file contents as a string.
public async Task ReadAllTextAsync(string path, CancellationToken ct = default)
=> await File.ReadAllTextAsync(path, ct);
+ ///
+ /// Writes all text to the specified file asynchronously, overwriting if it exists.
+ ///
+ /// The file path to write to.
+ /// The text content to write.
+ /// Cancellation token for the operation.
public async Task WriteAllTextAsync(string path, string content, CancellationToken ct = default)
=> await File.WriteAllTextAsync(path, content, ct);
+ ///
+ /// Gets an array of file paths matching the pattern in the specified directory.
+ ///
+ /// The directory path to search in.
+ /// The search pattern to match files.
+ /// Cancellation token for the operation.
+ /// An array of file paths matching the pattern.
public Task GetFilesAsync(string directory, string pattern, CancellationToken ct = default)
=> Task.FromResult(Directory.GetFiles(directory, pattern));
+ ///
+ /// Copies a file from source to destination asynchronously.
+ ///
+ /// The source file path.
+ /// The destination file path.
+ /// Cancellation token for the operation.
public async Task CopyFileAsync(string source, string destination, CancellationToken ct = default)
{
var content = await File.ReadAllBytesAsync(source, ct);
await File.WriteAllBytesAsync(destination, content, ct);
}
+ ///
+ /// Deletes the specified file asynchronously.
+ ///
+ /// The file path to delete.
+ /// Cancellation token for the operation.
public Task DeleteFileAsync(string path, CancellationToken ct = default)
{
File.Delete(path);
return Task.CompletedTask;
}
+ ///
+ /// Returns the directory name for the specified path.
+ ///
+ /// The file or directory path.
+ /// The directory name, or an empty string if not available.
public string GetDirectoryName(string path) => Path.GetDirectoryName(path) ?? string.Empty;
+ ///
+ /// Returns the file name and extension for the specified path.
+ ///
+ /// The file path.
+ /// The file name with extension.
public string GetFileName(string path) => Path.GetFileName(path);
+ ///
+ /// Returns the file name without the extension for the specified path.
+ ///
+ /// The file path.
+ /// The file name without extension.
public string GetFileNameWithoutExtension(string path) => Path.GetFileNameWithoutExtension(path);
+ ///
+ /// Combines multiple path components into a single path.
+ ///
+ /// The path components to combine.
+ /// The combined path.
public string Combine(params string[] paths) => Path.Combine(paths);
}
diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/Services/IBackupService.cs b/NEW/src/Utils/JdeScoping.ConfigManager/Services/IBackupService.cs
index f93cb82..fcfc101 100644
--- a/NEW/src/Utils/JdeScoping.ConfigManager/Services/IBackupService.cs
+++ b/NEW/src/Utils/JdeScoping.ConfigManager/Services/IBackupService.cs
@@ -5,8 +5,19 @@ namespace JdeScoping.ConfigManager.Services;
///
public class BackupInfo
{
+ ///
+ /// Gets the full path to the backup file.
+ ///
public required string Path { get; init; }
+
+ ///
+ /// Gets the timestamp when the backup was created.
+ ///
public required DateTime Timestamp { get; init; }
+
+ ///
+ /// Gets the file size in bytes.
+ ///
public required long Size { get; init; }
}
@@ -15,8 +26,35 @@ public class BackupInfo
///
public interface IBackupService
{
+ ///
+ /// Creates a backup copy of the specified file with a timestamp suffix.
+ ///
+ /// The path of the file to backup.
+ /// Cancellation token for the operation.
+ /// The path of the created backup file.
Task CreateBackupAsync(string filePath, CancellationToken ct = default);
+
+ ///
+ /// Retrieves a list of existing backups for the specified file, sorted by timestamp descending.
+ ///
+ /// The original file path to find backups for.
+ /// Cancellation token for the operation.
+ /// A read-only list of backup information sorted by timestamp.
Task> GetBackupsAsync(string filePath, CancellationToken ct = default);
+
+ ///
+ /// Restores a backup file by copying it to the target location.
+ ///
+ /// The path of the backup file to restore from.
+ /// The target path where the backup should be restored.
+ /// Cancellation token for the operation.
Task RestoreBackupAsync(string backupPath, string targetPath, CancellationToken ct = default);
+
+ ///
+ /// Removes old backup files, keeping only the most recent backups.
+ ///
+ /// The original file path to find backups for.
+ /// The number of most recent backups to retain (default: 10).
+ /// Cancellation token for the operation.
Task CleanupOldBackupsAsync(string filePath, int keepCount = 10, CancellationToken ct = default);
}
diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/Services/IConfigFileService.cs b/NEW/src/Utils/JdeScoping.ConfigManager/Services/IConfigFileService.cs
index c532253..797fa11 100644
--- a/NEW/src/Utils/JdeScoping.ConfigManager/Services/IConfigFileService.cs
+++ b/NEW/src/Utils/JdeScoping.ConfigManager/Services/IConfigFileService.cs
@@ -7,8 +7,35 @@ namespace JdeScoping.ConfigManager.Services;
///
public interface IConfigFileService
{
+ ///
+ /// Loads the application settings configuration from the specified file path.
+ ///
+ /// The file path to load appsettings from.
+ /// Cancellation token for the operation.
+ /// The loaded configuration model or a new empty model if deserialization fails.
Task LoadAppSettingsAsync(string path, CancellationToken ct = default);
+
+ ///
+ /// Loads the pipelines configuration from the specified file path.
+ ///
+ /// The file path to load pipelines from.
+ /// Cancellation token for the operation.
+ /// The loaded pipelines configuration model or a new empty model if deserialization fails.
Task LoadPipelinesAsync(string path, CancellationToken ct = default);
+
+ ///
+ /// Saves the application settings configuration to the specified file path.
+ ///
+ /// The file path to save appsettings to.
+ /// The configuration model to save.
+ /// Cancellation token for the operation.
Task SaveAppSettingsAsync(string path, ConfigModel config, CancellationToken ct = default);
+
+ ///
+ /// Saves the pipelines configuration to the specified file path.
+ ///
+ /// The file path to save pipelines to.
+ /// The pipelines configuration model to save.
+ /// Cancellation token for the operation.
Task SavePipelinesAsync(string path, PipelinesConfigModel config, CancellationToken ct = default);
}
diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/Services/IDiffService.cs b/NEW/src/Utils/JdeScoping.ConfigManager/Services/IDiffService.cs
index 502edaa..8d0ef61 100644
--- a/NEW/src/Utils/JdeScoping.ConfigManager/Services/IDiffService.cs
+++ b/NEW/src/Utils/JdeScoping.ConfigManager/Services/IDiffService.cs
@@ -5,9 +5,24 @@ namespace JdeScoping.ConfigManager.Services;
///
public class DiffLine
{
+ ///
+ /// Gets the line number in the original text, or null for added lines.
+ ///
public required int? OldLineNumber { get; init; }
+
+ ///
+ /// Gets the line number in the modified text, or null for removed lines.
+ ///
public required int? NewLineNumber { get; init; }
+
+ ///
+ /// Gets the text content of the line.
+ ///
public required string Text { get; init; }
+
+ ///
+ /// Gets the type of change for this line (added, removed, or unchanged).
+ ///
public required DiffLineType Type { get; init; }
}
@@ -23,9 +38,24 @@ public enum DiffLineType
///
public class DiffResult
{
+ ///
+ /// Gets a value indicating whether the diff contains any changes.
+ ///
public bool HasChanges { get; init; }
+
+ ///
+ /// Gets the list of lines representing the diff result.
+ ///
public List Lines { get; init; } = [];
+
+ ///
+ /// Gets the number of lines added in the modification.
+ ///
public int Insertions { get; init; }
+
+ ///
+ /// Gets the number of lines removed in the modification.
+ ///
public int Deletions { get; init; }
}
@@ -34,5 +64,11 @@ public class DiffResult
///
public interface IDiffService
{
+ ///
+ /// Generates a diff between original and modified text content.
+ ///
+ /// The original text content.
+ /// The modified text content.
+ /// A diff result containing added, removed, and unchanged lines with counts.
DiffResult GenerateDiff(string original, string modified);
}
diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/Services/IFileSystem.cs b/NEW/src/Utils/JdeScoping.ConfigManager/Services/IFileSystem.cs
index b5d265f..cbee86e 100644
--- a/NEW/src/Utils/JdeScoping.ConfigManager/Services/IFileSystem.cs
+++ b/NEW/src/Utils/JdeScoping.ConfigManager/Services/IFileSystem.cs
@@ -5,15 +5,85 @@ namespace JdeScoping.ConfigManager.Services;
///
public interface IFileSystem
{
+ ///
+ /// Determines whether the specified file exists.
+ ///
+ /// The file path to check.
+ /// True if the file exists; otherwise, false.
bool FileExists(string path);
+
+ ///
+ /// Determines whether the specified directory exists.
+ ///
+ /// The directory path to check.
+ /// True if the directory exists; otherwise, false.
bool DirectoryExists(string path);
+
+ ///
+ /// Reads all text from the specified file asynchronously.
+ ///
+ /// The file path to read from.
+ /// Cancellation token for the operation.
+ /// The file contents as a string.
Task ReadAllTextAsync(string path, CancellationToken ct = default);
+
+ ///
+ /// Writes all text to the specified file asynchronously, overwriting if it exists.
+ ///
+ /// The file path to write to.
+ /// The text content to write.
+ /// Cancellation token for the operation.
Task WriteAllTextAsync(string path, string content, CancellationToken ct = default);
+
+ ///
+ /// Gets an array of file paths matching the pattern in the specified directory.
+ ///
+ /// The directory path to search in.
+ /// The search pattern to match files.
+ /// Cancellation token for the operation.
+ /// An array of file paths matching the pattern.
Task GetFilesAsync(string directory, string pattern, CancellationToken ct = default);
+
+ ///
+ /// Copies a file from source to destination asynchronously.
+ ///
+ /// The source file path.
+ /// The destination file path.
+ /// Cancellation token for the operation.
Task CopyFileAsync(string source, string destination, CancellationToken ct = default);
+
+ ///
+ /// Deletes the specified file asynchronously.
+ ///
+ /// The file path to delete.
+ /// Cancellation token for the operation.
Task DeleteFileAsync(string path, CancellationToken ct = default);
+
+ ///
+ /// Returns the directory name for the specified path.
+ ///
+ /// The file or directory path.
+ /// The directory name, or an empty string if not available.
string GetDirectoryName(string path);
+
+ ///
+ /// Returns the file name and extension for the specified path.
+ ///
+ /// The file path.
+ /// The file name with extension.
string GetFileName(string path);
+
+ ///
+ /// Returns the file name without the extension for the specified path.
+ ///
+ /// The file path.
+ /// The file name without extension.
string GetFileNameWithoutExtension(string path);
+
+ ///
+ /// Combines multiple path components into a single path.
+ ///
+ /// The path components to combine.
+ /// The combined path.
string Combine(params string[] paths);
}
diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/Services/IValidationService.cs b/NEW/src/Utils/JdeScoping.ConfigManager/Services/IValidationService.cs
index 1cb4499..44337fd 100644
--- a/NEW/src/Utils/JdeScoping.ConfigManager/Services/IValidationService.cs
+++ b/NEW/src/Utils/JdeScoping.ConfigManager/Services/IValidationService.cs
@@ -7,11 +7,31 @@ namespace JdeScoping.ConfigManager.Services;
///
public class ValidationResult
{
+ ///
+ /// Gets a value indicating whether the validation succeeded (no errors).
+ ///
public bool IsValid => Errors.Count == 0;
+
+ ///
+ /// Gets the list of validation errors encountered.
+ ///
public List Errors { get; } = [];
+
+ ///
+ /// Gets the list of validation warnings encountered.
+ ///
public List Warnings { get; } = [];
+ ///
+ /// Adds an error message to the validation result.
+ ///
+ /// The error message to add.
public void AddError(string message) => Errors.Add(message);
+
+ ///
+ /// Adds a warning message to the validation result.
+ ///
+ /// The warning message to add.
public void AddWarning(string message) => Warnings.Add(message);
}
@@ -20,6 +40,17 @@ public class ValidationResult
///
public interface IValidationService
{
+ ///
+ /// Validates the application settings configuration.
+ ///
+ /// The configuration model to validate.
+ /// A validation result containing any errors or warnings found.
ValidationResult ValidateAppSettings(ConfigModel config);
+
+ ///
+ /// Validates the pipelines configuration.
+ ///
+ /// The pipelines configuration model to validate.
+ /// A validation result containing any errors or warnings found.
ValidationResult ValidatePipelines(PipelinesConfigModel config);
}
diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/Services/ValidationService.cs b/NEW/src/Utils/JdeScoping.ConfigManager/Services/ValidationService.cs
index 753c6e9..1c1211c 100644
--- a/NEW/src/Utils/JdeScoping.ConfigManager/Services/ValidationService.cs
+++ b/NEW/src/Utils/JdeScoping.ConfigManager/Services/ValidationService.cs
@@ -9,6 +9,11 @@ public class ValidationService : IValidationService
{
private static readonly string[] ValidConnections = ["jde", "cms", "giw", "lotfinderdb"];
+ ///
+ /// Validates the application settings configuration.
+ ///
+ /// The configuration model to validate.
+ /// A validation result containing any errors or warnings found.
public ValidationResult ValidateAppSettings(ConfigModel config)
{
var result = new ValidationResult();
@@ -50,6 +55,11 @@ public class ValidationService : IValidationService
return result;
}
+ ///
+ /// Validates the pipelines configuration.
+ ///
+ /// The pipelines configuration model to validate.
+ /// A validation result containing any errors or warnings found.
public ValidationResult ValidatePipelines(PipelinesConfigModel config)
{
var result = new ValidationResult();
diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/ViewModels/AsyncRelayCommand.cs b/NEW/src/Utils/JdeScoping.ConfigManager/ViewModels/AsyncRelayCommand.cs
index 33b0592..d8bbb25 100644
--- a/NEW/src/Utils/JdeScoping.ConfigManager/ViewModels/AsyncRelayCommand.cs
+++ b/NEW/src/Utils/JdeScoping.ConfigManager/ViewModels/AsyncRelayCommand.cs
@@ -12,20 +12,38 @@ public class AsyncRelayCommand : ICommand
private bool _isExecuting;
private EventHandler? _canExecuteChanged;
+ ///
+ /// Occurs when the result of has changed.
+ ///
public event EventHandler? CanExecuteChanged
{
add => _canExecuteChanged += value;
remove => _canExecuteChanged -= value;
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The async action to execute when the command is invoked.
+ /// An optional predicate to determine if the command can execute.
+ /// Thrown when is null.
public AsyncRelayCommand(Func execute, Func? canExecute = null)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
+ ///
+ /// Determines whether the command can execute in its current state.
+ ///
+ /// Unused parameter required by interface.
+ /// False if the command is currently executing; otherwise returns the result of the canExecute predicate.
public bool CanExecute(object? parameter) => !_isExecuting && (_canExecute?.Invoke() ?? true);
+ ///
+ /// Executes the async command, preventing concurrent execution.
+ ///
+ /// Unused parameter required by interface.
public async void Execute(object? parameter)
{
if (!CanExecute(parameter)) return;
@@ -44,5 +62,8 @@ public class AsyncRelayCommand : ICommand
}
}
+ ///
+ /// Raises the event to notify command bindings of state changes.
+ ///
public void RaiseCanExecuteChanged() => _canExecuteChanged?.Invoke(this, EventArgs.Empty);
}
diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/ViewModels/RelayCommand.cs b/NEW/src/Utils/JdeScoping.ConfigManager/ViewModels/RelayCommand.cs
index 076536e..2b1ef7f 100644
--- a/NEW/src/Utils/JdeScoping.ConfigManager/ViewModels/RelayCommand.cs
+++ b/NEW/src/Utils/JdeScoping.ConfigManager/ViewModels/RelayCommand.cs
@@ -11,26 +11,52 @@ public class RelayCommand : ICommand
private readonly Predicate