feat(dashboard): expose KPI counts (SH-353)

This commit is contained in:
Alexandre Brandizzi 2026-09-16 19:19:10 -03:00
parent 9d7efa34a6
commit 7947e2e77d
4 changed files with 86 additions and 0 deletions

View file

@ -88,6 +88,70 @@ namespace SeaHaven.DataServices.Implementation
.ToListAsync(cancellationToken);
}
public async Task<DashboardKpiCounts> GetKpiCountsAsync(
int? accountId,
string? dispatcherId,
DateOnly today,
CancellationToken cancellationToken)
{
var tomorrow = today.AddDays(1);
var dayAfterTomorrow = tomorrow.AddDays(1);
var workOrders = WorkOrderBoardQueryFilters.ApplyBaseScope(_context.workOrders.AsNoTracking());
if (accountId is int scopedAccountId)
workOrders = WorkOrderBoardQueryFilters.ApplyAccountScope(workOrders, scopedAccountId);
if (dispatcherId != null)
workOrders = workOrders.Where(w => w.AssignTo == dispatcherId);
var scheduledTomorrow = await workOrders
.Where(w => w.ScheduledDate >= tomorrow.ToDateTime(TimeOnly.MinValue)
&& w.ScheduledDate < dayAfterTomorrow.ToDateTime(TimeOnly.MinValue))
.CountAsync(cancellationToken);
var avetaPending = await workOrders
.Where(w => w.ScheduledDate >= today.ToDateTime(TimeOnly.MinValue)
&& w.ScheduledDate < dayAfterTomorrow.ToDateTime(TimeOnly.MinValue)
&& w.AvetaRequired
&& w.LifecycleStatus != LifecycleStatus.Completed
&& w.LifecycleStatus != LifecycleStatus.Canceled
&& (w.LifecycleStatus != null
|| ((w.LegacyStatus ?? w.Status) != "Done"
&& (w.LegacyStatus ?? w.Status) != "Completed"
&& (w.LegacyStatus ?? w.Status) != "Complete"
&& (w.LegacyStatus ?? w.Status) != "Closed"
&& (w.LegacyStatus ?? w.Status) != "Canceled"
&& (w.LegacyStatus ?? w.Status) != "Cancelled"))
&& !w.workOrderAttachments!.Any(attachment =>
(attachment.IsDeleted == null || attachment.IsDeleted == false)
&& attachment.Category == WorkOrderMediaCategory.Aveta))
.CountAsync(cancellationToken);
var pendingUplifts = _context.DispatchUpliftRequests
.AsNoTracking()
.Where(request => request.Status == "Pending"
&& (request.IsDeleted == null || request.IsDeleted == false)
&& request.Dispatch != null
&& (request.Dispatch.IsDeleted == null || request.Dispatch.IsDeleted == false));
if (accountId is int account)
{
pendingUplifts = pendingUplifts.Where(request =>
(request.Dispatch!.WorkOrder != null && request.Dispatch.WorkOrder.AccountId == account)
|| request.Dispatch.DispatchWorkOrders!.Any(link =>
link.WorkOrder != null && link.WorkOrder.AccountId == account));
}
if (dispatcherId != null)
{
pendingUplifts = pendingUplifts.Where(request =>
(request.Dispatch!.WorkOrder != null && request.Dispatch.WorkOrder.AssignTo == dispatcherId)
|| request.Dispatch.DispatchWorkOrders!.Any(link =>
link.WorkOrder != null && link.WorkOrder.AssignTo == dispatcherId));
}
return new DashboardKpiCounts(
scheduledTomorrow,
await pendingUplifts.CountAsync(cancellationToken),
avetaPending);
}
public async Task<IReadOnlyList<DashboardDispatcherWorkload>> GetDispatcherWorkloadAsync(
int? accountId,
string? dispatcherId,

View file

@ -8,6 +8,12 @@ namespace SeaHaven.DataServices.Interfaces
int? accountId,
CancellationToken cancellationToken);
Task<DashboardKpiCounts> GetKpiCountsAsync(
int? accountId,
string? dispatcherId,
DateOnly today,
CancellationToken cancellationToken);
Task<IReadOnlyList<DashboardWorkOrder>> GetDashboardWorkOrdersAsync(
int? accountId,
string? dispatcherId,
@ -53,4 +59,9 @@ namespace SeaHaven.DataServices.Interfaces
public int NotDispatched { get; set; }
public int Completed { get; set; }
}
public sealed record DashboardKpiCounts(
int ScheduledTomorrow,
int PendingUplifts,
int AvetaPending);
}

View file

@ -100,6 +100,9 @@ namespace SeaHaven.Services.DTOs
public int Open { get; set; }
public int NotDispatched { get; set; }
public int Completed { get; set; }
public int ScheduledTomorrow { get; set; }
public int PendingUplifts { get; set; }
public int AvetaPending { get; set; }
public DashboardBreakdownDTO Breakdown { get; set; } = new();
public int DueCount { get; set; }
public int CompletedDueCount { get; set; }

View file

@ -35,6 +35,11 @@ namespace SeaHaven.Services.Implementation
throw new WorkOrderBoardValidationException("Forbidden", "Dispatcher identity is required.");
var counts = await _dataService.GetWorkOrderCountsAsync(accountId, cancellationToken);
var kpis = await _dataService.GetKpiCountsAsync(
accountId,
dispatcherId,
DashboardBusinessTime.Today(),
cancellationToken);
var workOrders = await _dataService.GetDashboardWorkOrdersAsync(
accountId,
dispatcherId,
@ -51,6 +56,9 @@ namespace SeaHaven.Services.Implementation
Open = useMetrics ? metrics.Open : counts.Open,
NotDispatched = useMetrics ? metrics.NotDispatched : counts.NotDispatched,
Completed = useMetrics ? metrics.Completed : counts.Completed,
ScheduledTomorrow = kpis.ScheduledTomorrow,
PendingUplifts = kpis.PendingUplifts,
AvetaPending = kpis.AvetaPending,
Breakdown = metrics.Breakdown,
DueCount = metrics.DueCount,
CompletedDueCount = metrics.CompletedDueCount,