using System; using System.Collections.Generic; using System.Linq; using Avalonia; using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Markup.Xaml; using dmeo040225.Models; using dmeo040225.Services; using OxyPlot; using OxyPlot.Avalonia; using OxyPlot.Series; using OxyPlot.Axes; using PdfSharpCore.Drawing; using PdfSharpCore.Pdf; using LineSeries = OxyPlot.Series.LineSeries; namespace dmeo040225; public class ServicePerDay { public DateTime Date { get; set; } public int CountServices {get; set; } } public class ServiceOrdersPerDay { public DateTime Date { get; set; } public string ServiceName { get; set; } public int OrderCount { get; set; } } public partial class ReportWindow : Window { public List ServicesPerDayList { get; set; } public List ServicesOrdersPerDayList { get; set; } public List OrdersPerDayList { get; set; } public ReportWindow() { InitializeComponent(); TimerService.Instance.TimeUpdated += UpdateTimerText; TimerService.Instance.TimerExpired += LogoutUser; TimerService.Instance.Start(); } private void GenerateReport(object? sender, RoutedEventArgs e) { if (StartPicker.SelectedDate == null || EndPicker.SelectedDate == null) { Console.WriteLine("Выберите начальную и конечную дату!"); return; } DateTime startDate = StartPicker.SelectedDate.Value.DateTime; DateTime endDate = EndPicker.SelectedDate.Value.DateTime; if (startDate > endDate) { Console.WriteLine("Начальная дата не может быть позже конечной!"); return; } using var context = new DatabaseContext(); ServicesPerDayList = GetServicesPerDay(context, startDate, endDate); ServicesOrdersPerDayList = GetServiceOrdersPerDay(context, startDate, endDate); OrdersPerDayList = GetOrdersPerDay(context, startDate, endDate); CreatePdfWithTableAndGraph(); foreach (var service in ServicesOrdersPerDayList) { Console.WriteLine($"{service.Date.ToShortDateString()} | {service.ServiceName} | {service.OrderCount}"); } } private PlotModel CreateServiceGraph() { var plotModel = new PlotModel { Title = "График по сервисам" }; var series = new LineSeries { Title = "Количество сервисов", MarkerType = MarkerType.Circle, MarkerSize = 4, Color = OxyColors.SkyBlue }; foreach (var item in ServicesPerDayList) { series.Points.Add(new DataPoint(OxyPlot.Axes.DateTimeAxis.ToDouble(item.Date), item.CountServices)); } plotModel.Series.Add(series); return plotModel; } private void CreatePdfWithTableAndGraph() { // Создаем новый PDF документ PdfDocument document = new PdfDocument(); document.Info.Title = "Отчет"; // Создаем страницу PdfPage page = document.AddPage(); // Создаем XGraphics для рисования XGraphics gfx = XGraphics.FromPdfPage(page); XFont font = new XFont("Arial", 12, XFontStyle.Regular); // Добавление таблицы в PDF int yPos = 40; // gfx.DrawString("Список сервисов:", font, XBrushes.Black, new XPoint(40, yPos)); // yPos += 20; // // foreach (var service in ServicesPerDayList) // { // gfx.DrawString($"{service.Date.ToShortDateString()} | {service.CountServices} сервисов", font, XBrushes.Black, new XPoint(40, yPos)); // yPos += 20; // } // Добавление графика в PDF var plotModel = CreateServiceGraph(); var pngStream = new System.IO.MemoryStream(); var pngExporter = new OxyPlot.ImageSharp.PngExporter(400, 300); try { pngExporter.Export(plotModel, pngStream); pngStream.Seek(0, System.IO.SeekOrigin.Begin); // Убедитесь, что поток начнется с первого байта var image = XImage.FromStream(() => pngStream); gfx.DrawImage(image, 40, yPos); } catch (Exception ex) { Console.WriteLine($"Ошибка при экспортировании изображения: {ex.Message}"); } // Сохраняем PDF string filename = "report.pdf"; document.Save(filename); Console.WriteLine($"PDF сохранен в {filename}"); } private List GetServicesPerDay(DatabaseContext context, DateTime startDate, DateTime endDate) { return context.Orders .Where(order => order.Orderdata.Date >= startDate && order.Orderdata.Date <= endDate) .SelectMany(order => order.OrdersServices) .GroupBy(os => os.Order.Orderdata.Date) .Select(g => new ServicePerDay { Date = g.Key, CountServices = g.Count() }) .OrderBy(spd => spd.Date) .ToList(); } private List GetServiceOrdersPerDay(DatabaseContext context, DateTime startDate, DateTime endDate) { return context.Orders .Where(order => order.Orderdata.Date >= startDate.Date && order.Orderdata.Date <= endDate.Date) .SelectMany(order => order.OrdersServices, (order, os) => new { order.Orderdata, os.Service }) .GroupBy(o => new { o.Orderdata.Date, o.Service.Name }) .Select(g => new ServiceOrdersPerDay { Date = g.Key.Date, ServiceName = g.Key.Name, OrderCount = g.Count() }) .OrderBy(spd => spd.Date) .ThenBy(spd => spd.ServiceName) .ToList(); } private List GetOrdersPerDay(DatabaseContext context, DateTime startDate, DateTime endDate) { return context.Orders .Where(order => order.Orderdata.Date >= startDate.Date && order.Orderdata.Date <= endDate.Date) .GroupBy(order => order.Orderdata.Date) .Select(g => new ServicePerDay { Date = g.Key, CountServices = g.Count() }) .OrderBy(spd => spd.Date) .ToList(); } private void Graph_Pdf() { } private void Table_Pdf() { } private void GraphXTable_Pdf() { } private void Back_OnClick(object? sender, RoutedEventArgs e) { TimerService.Instance.Reset(); Close(); } private void UpdateTimerText(TimeSpan time) { TimerText.Text = $"Осталось: {time:mm\\:ss}"; } private void LogoutUser() { Close(); var mainWindow = new MainWindow(); mainWindow.Show(); } protected override void OnClosed(EventArgs e) { TimerService.Instance.TimeUpdated -= UpdateTimerText; TimerService.Instance.TimerExpired -= LogoutUser; base.OnClosed(e); } }