diff --git a/NEW/src/JdeScoping.Api/Controllers/AuthController.cs b/NEW/src/JdeScoping.Api/Controllers/AuthController.cs index c8bd356..cc94c4a 100644 --- a/NEW/src/JdeScoping.Api/Controllers/AuthController.cs +++ b/NEW/src/JdeScoping.Api/Controllers/AuthController.cs @@ -2,7 +2,6 @@ using System.Security.Claims; using System.Text.Json; using JdeScoping.Api.Extensions; using JdeScoping.Core.ApiContracts; -using JdeScoping.Core.ApiContracts.Auth; using JdeScoping.Core.Interfaces; using JdeScoping.Core.Models; using JdeScoping.Core.Models.Auth; diff --git a/NEW/src/JdeScoping.Api/Controllers/PipelineController.cs b/NEW/src/JdeScoping.Api/Controllers/PipelineController.cs index c102ab5..92b0cb2 100644 --- a/NEW/src/JdeScoping.Api/Controllers/PipelineController.cs +++ b/NEW/src/JdeScoping.Api/Controllers/PipelineController.cs @@ -1,5 +1,5 @@ using JdeScoping.Core.ApiContracts; -using JdeScoping.Core.ApiContracts.Pipelines; +using JdeScoping.Core.Models.Pipelines; using JdeScoping.Core.Models.Enums; using JdeScoping.DataSync.Configuration; using JdeScoping.DataSync.Contracts; diff --git a/NEW/src/JdeScoping.Api/Controllers/RefreshStatusController.cs b/NEW/src/JdeScoping.Api/Controllers/RefreshStatusController.cs new file mode 100644 index 0000000..58b8fbf --- /dev/null +++ b/NEW/src/JdeScoping.Api/Controllers/RefreshStatusController.cs @@ -0,0 +1,71 @@ +using JdeScoping.Core.ApiContracts; +using JdeScoping.Core.Models.Infrastructure; +using JdeScoping.Core.Interfaces; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +namespace JdeScoping.Api.Controllers; + +/// +/// API endpoints for data refresh/cache sync status. +/// +[Route(ApiRoutes.RefreshStatus.Base)] +[ApiController] +[Authorize] +public class RefreshStatusController : ApiControllerBase +{ + private readonly ILotFinderRepository _repository; + + public RefreshStatusController(ILotFinderRepository repository) + { + _repository = repository; + } + + /// + /// Gets aggregated refresh status records within the specified date range. + /// + /// Start date filter. + /// End date filter. + /// Cancellation token. + [HttpGet] + [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] + public async Task>> GetRefreshStatus( + [FromQuery] DateTime minDT, + [FromQuery] DateTime maxDT, + CancellationToken ct) + { + // Get raw data updates from repository + var updates = await _repository.GetLastDataUpdatesAsync(ct); + + // Filter by date range + var filtered = updates + .Where(u => u.StartDt >= minDT && u.StartDt <= maxDT.AddDays(1)) + .ToList(); + + // Group by StartDt (rounded to minute) to aggregate multiple table updates into single rows + var aggregated = filtered + .GroupBy(u => new DateTime(u.StartDt.Year, u.StartDt.Month, u.StartDt.Day, u.StartDt.Hour, u.StartDt.Minute, 0)) + .Select(g => new DataUpdateDto + { + StartDt = g.Key, + EndDt = g.Max(u => u.EndDt), + WasSuccessful = g.All(u => u.WasSuccessful), + BranchRecords = (int)(g.FirstOrDefault(u => u.TableName == "Branch")?.NumberRecords ?? 0), + ProfitCenterRecords = (int)(g.FirstOrDefault(u => u.TableName == "ProfitCenter")?.NumberRecords ?? 0), + WorkCenterRecords = (int)(g.FirstOrDefault(u => u.TableName == "WorkCenter")?.NumberRecords ?? 0), + OrgHierarchyRecords = (int)(g.FirstOrDefault(u => u.TableName == "OrgHierarchy")?.NumberRecords ?? 0), + StatusCodeRecords = (int)(g.FirstOrDefault(u => u.TableName == "StatusCode")?.NumberRecords ?? 0), + UserRecords = (int)(g.FirstOrDefault(u => u.TableName == "JdeUser")?.NumberRecords ?? 0), + ItemRecords = (int)(g.FirstOrDefault(u => u.TableName == "Item")?.NumberRecords ?? 0), + LotRecords = (int)(g.FirstOrDefault(u => u.TableName == "Lot")?.NumberRecords ?? 0), + WorkOrderRecords = (int)(g.FirstOrDefault(u => u.TableName.Contains("WorkOrder_"))?.NumberRecords ?? 0), + WorkOrderStepRecords = (int)(g.FirstOrDefault(u => u.TableName.Contains("WorkOrderStep"))?.NumberRecords ?? 0), + WorkOrderComponentRecords = (int)(g.FirstOrDefault(u => u.TableName.Contains("WorkOrderComponent"))?.NumberRecords ?? 0) + }) + .OrderByDescending(d => d.StartDt) + .ToList(); + + return Ok(aggregated); + } +} diff --git a/NEW/src/JdeScoping.Api/Hubs/StatusHub.cs b/NEW/src/JdeScoping.Api/Hubs/StatusHub.cs index 6d8af25..fcb38fd 100644 --- a/NEW/src/JdeScoping.Api/Hubs/StatusHub.cs +++ b/NEW/src/JdeScoping.Api/Hubs/StatusHub.cs @@ -1,4 +1,4 @@ -using JdeScoping.Core.ApiContracts.SignalR; +using JdeScoping.Core.ViewModels; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; @@ -9,7 +9,7 @@ namespace JdeScoping.Api.Hubs; /// public class StatusHub : Hub { - private static StatusUpdateDto _cachedStatus = new() + private static StatusUpdateViewModel _cachedStatus = new() { Message = "Unknown", Timestamp = DateTime.UtcNow @@ -27,7 +27,7 @@ public class StatusHub : Hub /// Caches the update and broadcasts to all clients. /// /// Status update to broadcast - public async Task SetStatus(StatusUpdateDto statusUpdate) + public async Task SetStatus(StatusUpdateViewModel statusUpdate) { _cachedStatus = statusUpdate; await Clients.All.SendAsync("statusUpdate", statusUpdate); @@ -38,7 +38,7 @@ public class StatusHub : Hub /// Called by clients to get initial cached status on connection. /// /// The most recent status update - public StatusUpdateDto GetCachedStatus() + public StatusUpdateViewModel GetCachedStatus() { return _cachedStatus; } @@ -47,7 +47,7 @@ public class StatusHub : Hub /// Called by controllers/services to broadcast search updates. /// /// Search update to broadcast - public async Task PublishSearchUpdate(SearchUpdateDto searchUpdate) + public async Task PublishSearchUpdate(SearchUpdateViewModel searchUpdate) { await Clients.All.SendAsync("searchUpdate", searchUpdate); _logger.LogDebug("Search update published: ID={Id}, Status={Status}", searchUpdate.Id, searchUpdate.Status); diff --git a/NEW/src/JdeScoping.Api/Services/SearchNotificationService.cs b/NEW/src/JdeScoping.Api/Services/SearchNotificationService.cs index 45e6d52..169ba96 100644 --- a/NEW/src/JdeScoping.Api/Services/SearchNotificationService.cs +++ b/NEW/src/JdeScoping.Api/Services/SearchNotificationService.cs @@ -1,7 +1,7 @@ using JdeScoping.Api.Hubs; -using JdeScoping.Core.ApiContracts.SignalR; using JdeScoping.Core.Interfaces; using JdeScoping.Core.Models.Search; +using JdeScoping.Core.ViewModels; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; @@ -34,7 +34,7 @@ public class SearchNotificationService : ISearchNotificationService { try { - var update = SearchUpdateDto.FromSearch(search); + var update = SearchUpdateViewModel.FromSearch(search); await _hubContext.Clients.All.SendAsync("searchUpdate", update, ct); _logger.LogDebug( "Search update notification sent: Id={SearchId}, Status={Status}", @@ -56,7 +56,7 @@ public class SearchNotificationService : ISearchNotificationService { try { - var update = StatusUpdateDto.Create(status); + var update = StatusUpdateViewModel.Create(status); await _hubContext.Clients.All.SendAsync("statusUpdate", update, ct); _logger.LogDebug("Status notification sent: {Status}", status); } diff --git a/NEW/src/JdeScoping.Client/Auth/AuthStateProvider.cs b/NEW/src/JdeScoping.Client/Auth/AuthStateProvider.cs index ce39beb..e43d902 100644 --- a/NEW/src/JdeScoping.Client/Auth/AuthStateProvider.cs +++ b/NEW/src/JdeScoping.Client/Auth/AuthStateProvider.cs @@ -1,6 +1,6 @@ using System.Net.Http.Json; using System.Security.Claims; -using JdeScoping.Core.ApiContracts.Auth; +using JdeScoping.Core.Models.Auth; using Microsoft.AspNetCore.Components.Authorization; namespace JdeScoping.Client.Auth; diff --git a/NEW/src/JdeScoping.Client/Auth/IUserStorageService.cs b/NEW/src/JdeScoping.Client/Auth/IUserStorageService.cs index 1cc9eb5..2eaa4e0 100644 --- a/NEW/src/JdeScoping.Client/Auth/IUserStorageService.cs +++ b/NEW/src/JdeScoping.Client/Auth/IUserStorageService.cs @@ -1,4 +1,4 @@ -using JdeScoping.Core.ApiContracts.Auth; +using JdeScoping.Core.Models.Auth; namespace JdeScoping.Client.Auth; diff --git a/NEW/src/JdeScoping.Client/Auth/UserStorageService.cs b/NEW/src/JdeScoping.Client/Auth/UserStorageService.cs index 11cf690..e365ba3 100644 --- a/NEW/src/JdeScoping.Client/Auth/UserStorageService.cs +++ b/NEW/src/JdeScoping.Client/Auth/UserStorageService.cs @@ -1,5 +1,5 @@ using System.Text.Json; -using JdeScoping.Core.ApiContracts.Auth; +using JdeScoping.Core.Models.Auth; using Microsoft.JSInterop; namespace JdeScoping.Client.Auth; diff --git a/NEW/src/JdeScoping.Client/Components/Admin/PipelineScheduleSection.razor b/NEW/src/JdeScoping.Client/Components/Admin/PipelineScheduleSection.razor index 1786111..818ea12 100644 --- a/NEW/src/JdeScoping.Client/Components/Admin/PipelineScheduleSection.razor +++ b/NEW/src/JdeScoping.Client/Components/Admin/PipelineScheduleSection.razor @@ -1,5 +1,5 @@ @namespace JdeScoping.Client.Components.Admin -@using JdeScoping.Core.ApiContracts.Pipelines +@using JdeScoping.Core.Models.Pipelines @using JdeScoping.Core.Models.Enums diff --git a/NEW/src/JdeScoping.Client/Pages/Admin/PipelineViewer.razor b/NEW/src/JdeScoping.Client/Pages/Admin/PipelineViewer.razor index 7549519..c0101c0 100644 --- a/NEW/src/JdeScoping.Client/Pages/Admin/PipelineViewer.razor +++ b/NEW/src/JdeScoping.Client/Pages/Admin/PipelineViewer.razor @@ -1,7 +1,7 @@ @page "/admin/pipeline-viewer" @attribute [Authorize] @using JdeScoping.Core.ApiContracts -@using JdeScoping.Core.ApiContracts.Pipelines +@using JdeScoping.Core.Models.Pipelines @using JdeScoping.Core.Models.Enums @inject IPipelineApiClient PipelineApi diff --git a/NEW/src/JdeScoping.Client/Pages/RefreshStatus.razor b/NEW/src/JdeScoping.Client/Pages/RefreshStatus.razor index 0370678..9ab81f8 100644 --- a/NEW/src/JdeScoping.Client/Pages/RefreshStatus.razor +++ b/NEW/src/JdeScoping.Client/Pages/RefreshStatus.razor @@ -31,31 +31,31 @@ } else { - - + - + - - - - - - - - - - - - + + + + + + + + + + + +