/
kochkatech
/
Queue
Обзор
Документация
Войти
/
kochkatech
/
Queue
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
master
src/Queue.Admin/ViewModels/ReportsViewModel.cs
137 строк
5 KB
kochkareal
init: Начальная структура проекта и панель администратора
24 июл 2026, 21:42
24 июл 2026, 21:42
cd5152a
Код
Авторство
О чём код?
using System; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Microsoft.EntityFrameworkCore; using Queue.Core.Enums; using Queue.Data; namespace Queue.Admin.ViewModels; public class ServiceReportRow { public string ServiceName { get; init; } = string.Empty; public int TotalTickets { get; init; } public int Served { get; init; } public int NoShow { get; init; } public int Cancelled { get; init; } public double AverageWaitMinutes { get; init; } public double AverageServiceMinutes { get; init; } } public partial class ReportsViewModel : ObservableObject { private readonly QueueDbContextFactory _dbContextFactory; public ObservableCollection<ServiceReportRow> Rows { get; } = new(); [ObservableProperty] private DateTime? fromDate = DateTime.Today.AddDays(-6); [ObservableProperty] private DateTime? toDate = DateTime.Today; [ObservableProperty] private int totalTickets; [ObservableProperty] private int totalServed; [ObservableProperty] private int totalNoShow; [ObservableProperty] private int totalCancelled; [ObservableProperty] private double averageWaitMinutes; [ObservableProperty] private double averageServiceMinutes; public ReportsViewModel(QueueDbContextFactory dbContextFactory) { _dbContextFactory = dbContextFactory; _ = BuildReportAsync(); } [RelayCommand] private async Task BuildReportAsync() { using var db = _dbContextFactory.CreateDbContext(); var from = (FromDate ?? DateTime.Today.AddDays(-6)).Date; var to = (ToDate ?? DateTime.Today).Date.AddDays(1); // включительно по конец дня var tickets = await db.Tickets .Where(t => t.CreatedAt >= from && t.CreatedAt < to) .ToListAsync(); var services = await db.Services.ToListAsync(); var serviceNames = services.ToDictionary(s => s.Id, s => s.Name); TotalTickets = tickets.Count; TotalServed = tickets.Count(t => t.Status == TicketStatus.Served); TotalNoShow = tickets.Count(t => t.Status == TicketStatus.NoShow); TotalCancelled = tickets.Count(t => t.Status == TicketStatus.Cancelled); var waitSamples = tickets.Where(t => t.CalledAt.HasValue) .Select(t => (t.CalledAt!.Value - t.CreatedAt).TotalMinutes) .ToList(); AverageWaitMinutes = waitSamples.Count > 0 ? Math.Round(waitSamples.Average(), 1) : 0; var serviceDurationSamples = tickets.Where(t => t.StartedAt.HasValue && t.FinishedAt.HasValue) .Select(t => (t.FinishedAt!.Value - t.StartedAt!.Value).TotalMinutes) .ToList(); AverageServiceMinutes = serviceDurationSamples.Count > 0 ? Math.Round(serviceDurationSamples.Average(), 1) : 0; Rows.Clear(); foreach (var group in tickets.GroupBy(t => t.ServiceId) .OrderBy(g => serviceNames.TryGetValue(g.Key, out var n) ? n : string.Empty)) { var groupTickets = group.ToList(); var groupWait = groupTickets.Where(t => t.CalledAt.HasValue) .Select(t => (t.CalledAt!.Value - t.CreatedAt).TotalMinutes).ToList(); var groupService = groupTickets.Where(t => t.StartedAt.HasValue && t.FinishedAt.HasValue) .Select(t => (t.FinishedAt!.Value - t.StartedAt!.Value).TotalMinutes).ToList(); Rows.Add(new ServiceReportRow { ServiceName = serviceNames.TryGetValue(group.Key, out var name) ? name : "—", TotalTickets = groupTickets.Count, Served = groupTickets.Count(t => t.Status == TicketStatus.Served), NoShow = groupTickets.Count(t => t.Status == TicketStatus.NoShow), Cancelled = groupTickets.Count(t => t.Status == TicketStatus.Cancelled), AverageWaitMinutes = groupWait.Count > 0 ? Math.Round(groupWait.Average(), 1) : 0, AverageServiceMinutes = groupService.Count > 0 ? Math.Round(groupService.Average(), 1) : 0 }); } } [RelayCommand] private void ExportCsv() { var dialog = new Microsoft.Win32.SaveFileDialog { FileName = $"queue-report-{FromDate:yyyy-MM-dd}_{ToDate:yyyy-MM-dd}.csv", Filter = "CSV файлы (*.csv)|*.csv" }; if (dialog.ShowDialog() != true) { return; } var sb = new StringBuilder(); sb.AppendLine("Услуга;Талонов;Обслужено;Неявка;Отменено;Ср. ожидание (мин);Ср. обслуживание (мин)"); foreach (var row in Rows) { sb.AppendLine($"{row.ServiceName};{row.TotalTickets};{row.Served};{row.NoShow};{row.Cancelled};{row.AverageWaitMinutes};{row.AverageServiceMinutes}"); } System.IO.File.WriteAllText(dialog.FileName, sb.ToString(), Encoding.UTF8); } }