From 4662c2e508522f398765df078bc40ed30b0a600a Mon Sep 17 00:00:00 2001 From: qkrlnt Date: Mon, 9 Dec 2024 00:41:55 +0400 Subject: [PATCH] lab 3 done --- .../FormFuelAccounting.Designer.cs | 16 ++- .../FuelAccounting/FormFuelAccounting.cs | 13 ++ .../FormKilometersDrivenReport.Designer.cs | 108 ++++++++++++++++ .../Forms/FormKilometersDrivenReport.cs | 68 ++++++++++ .../Forms/FormKilometersDrivenReport.resx | 120 ++++++++++++++++++ .../FuelAccounting/FuelAccounting.csproj | 1 + .../FuelAccounting/Reports/ChartReport.cs | 47 +++++++ .../FuelAccounting/Reports/PdfBuilder.cs | 87 +++++++++++++ 8 files changed, 457 insertions(+), 3 deletions(-) create mode 100644 FuelAccounting/FuelAccounting/Forms/FormKilometersDrivenReport.Designer.cs create mode 100644 FuelAccounting/FuelAccounting/Forms/FormKilometersDrivenReport.cs create mode 100644 FuelAccounting/FuelAccounting/Forms/FormKilometersDrivenReport.resx create mode 100644 FuelAccounting/FuelAccounting/Reports/ChartReport.cs create mode 100644 FuelAccounting/FuelAccounting/Reports/PdfBuilder.cs diff --git a/FuelAccounting/FuelAccounting/FormFuelAccounting.Designer.cs b/FuelAccounting/FuelAccounting/FormFuelAccounting.Designer.cs index bf07b7a..4b8ba8a 100644 --- a/FuelAccounting/FuelAccounting/FormFuelAccounting.Designer.cs +++ b/FuelAccounting/FuelAccounting/FormFuelAccounting.Designer.cs @@ -40,6 +40,7 @@ отчетыToolStripMenuItem = new ToolStripMenuItem(); directoryReportToolStripMenuItem = new ToolStripMenuItem(); CarSummaryToolStripMenuItem = new ToolStripMenuItem(); + kilometersDrovenToolStripMenuItem = new ToolStripMenuItem(); menuStrip.SuspendLayout(); SuspendLayout(); // @@ -97,20 +98,20 @@ // выездToolStripMenuItem // выездToolStripMenuItem.Name = "выездToolStripMenuItem"; - выездToolStripMenuItem.Size = new Size(125, 22); + выездToolStripMenuItem.Size = new Size(180, 22); выездToolStripMenuItem.Text = "Выезд"; выездToolStripMenuItem.Click += EquipageToolStripMenuItem_Click; // // заправкаToolStripMenuItem // заправкаToolStripMenuItem.Name = "заправкаToolStripMenuItem"; - заправкаToolStripMenuItem.Size = new Size(125, 22); + заправкаToolStripMenuItem.Size = new Size(180, 22); заправкаToolStripMenuItem.Text = "Заправка"; заправкаToolStripMenuItem.Click += RefuelingToolStripMenuItem_Click; // // отчетыToolStripMenuItem // - отчетыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { directoryReportToolStripMenuItem, CarSummaryToolStripMenuItem }); + отчетыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { directoryReportToolStripMenuItem, CarSummaryToolStripMenuItem, kilometersDrovenToolStripMenuItem }); отчетыToolStripMenuItem.Name = "отчетыToolStripMenuItem"; отчетыToolStripMenuItem.Size = new Size(60, 20); отчетыToolStripMenuItem.Text = "Отчеты"; @@ -131,6 +132,14 @@ CarSummaryToolStripMenuItem.Text = "Сводка по автомобилям"; CarSummaryToolStripMenuItem.Click += CarSummaryToolStripMenuItem_Click; // + // kilometersDrovenToolStripMenuItem + // + kilometersDrovenToolStripMenuItem.Name = "kilometersDrovenToolStripMenuItem"; + kilometersDrovenToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.P; + kilometersDrovenToolStripMenuItem.Size = new Size(280, 22); + kilometersDrovenToolStripMenuItem.Text = "Сводка по километражу"; + kilometersDrovenToolStripMenuItem.Click += KilometersDrovenToolStripMenuItem_Click; + // // FormFuelAccounting // AutoScaleDimensions = new SizeF(7F, 15F); @@ -163,5 +172,6 @@ private ToolStripMenuItem отчетыToolStripMenuItem; private ToolStripMenuItem directoryReportToolStripMenuItem; private ToolStripMenuItem CarSummaryToolStripMenuItem; + private ToolStripMenuItem kilometersDrovenToolStripMenuItem; } } \ No newline at end of file diff --git a/FuelAccounting/FuelAccounting/FormFuelAccounting.cs b/FuelAccounting/FuelAccounting/FormFuelAccounting.cs index 1ce58ce..4d6a28e 100644 --- a/FuelAccounting/FuelAccounting/FormFuelAccounting.cs +++ b/FuelAccounting/FuelAccounting/FormFuelAccounting.cs @@ -132,5 +132,18 @@ namespace FuelAccounting MessageBoxButtons.OK, MessageBoxIcon.Error); } } + + private void KilometersDrovenToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + _container.Resolve().ShowDialog(); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "Ошибка при загрузке", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } } } diff --git a/FuelAccounting/FuelAccounting/Forms/FormKilometersDrivenReport.Designer.cs b/FuelAccounting/FuelAccounting/Forms/FormKilometersDrivenReport.Designer.cs new file mode 100644 index 0000000..9690781 --- /dev/null +++ b/FuelAccounting/FuelAccounting/Forms/FormKilometersDrivenReport.Designer.cs @@ -0,0 +1,108 @@ +namespace FuelAccounting.Forms +{ + partial class FormKilometersDrivenReport + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + buttonSelectFilePath = new Button(); + labelFileName = new Label(); + label2 = new Label(); + dateTimePicker = new DateTimePicker(); + buttonBuild = new Button(); + SuspendLayout(); + // + // buttonSelectFilePath + // + buttonSelectFilePath.Location = new Point(25, 22); + buttonSelectFilePath.Name = "buttonSelectFilePath"; + buttonSelectFilePath.Size = new Size(98, 35); + buttonSelectFilePath.TabIndex = 0; + buttonSelectFilePath.Text = "Выбрать"; + buttonSelectFilePath.UseVisualStyleBackColor = true; + buttonSelectFilePath.Click += ButtonSelectFilePath_Click; + // + // labelFileName + // + labelFileName.AutoSize = true; + labelFileName.Location = new Point(150, 32); + labelFileName.Name = "labelFileName"; + labelFileName.Size = new Size(36, 15); + labelFileName.TabIndex = 1; + labelFileName.Text = "Файл"; + // + // label2 + // + label2.AutoSize = true; + label2.Location = new Point(25, 81); + label2.Name = "label2"; + label2.Size = new Size(38, 15); + label2.TabIndex = 2; + label2.Text = "Дата: "; + // + // dateTimePicker + // + dateTimePicker.Location = new Point(69, 75); + dateTimePicker.Name = "dateTimePicker"; + dateTimePicker.Size = new Size(200, 23); + dateTimePicker.TabIndex = 3; + // + // buttonBuild + // + buttonBuild.Location = new Point(25, 116); + buttonBuild.Name = "buttonBuild"; + buttonBuild.Size = new Size(244, 46); + buttonBuild.TabIndex = 4; + buttonBuild.Text = "Сформировать"; + buttonBuild.UseVisualStyleBackColor = true; + buttonBuild.Click += ButtonBuild_Click; + // + // FormKilometersDrivenReport + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(293, 182); + Controls.Add(buttonBuild); + Controls.Add(dateTimePicker); + Controls.Add(label2); + Controls.Add(labelFileName); + Controls.Add(buttonSelectFilePath); + Name = "FormKilometersDrivenReport"; + StartPosition = FormStartPosition.CenterScreen; + Text = "Километров пройдено"; + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private Button buttonSelectFilePath; + private Label labelFileName; + private Label label2; + private DateTimePicker dateTimePicker; + private Button buttonBuild; + } +} \ No newline at end of file diff --git a/FuelAccounting/FuelAccounting/Forms/FormKilometersDrivenReport.cs b/FuelAccounting/FuelAccounting/Forms/FormKilometersDrivenReport.cs new file mode 100644 index 0000000..56d9010 --- /dev/null +++ b/FuelAccounting/FuelAccounting/Forms/FormKilometersDrivenReport.cs @@ -0,0 +1,68 @@ +using FuelAccounting.Reports; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Unity; + +namespace FuelAccounting.Forms +{ + public partial class FormKilometersDrivenReport : Form + { + private string _fileName = string.Empty; + + private readonly IUnityContainer _container; + + public FormKilometersDrivenReport(IUnityContainer container) + { + InitializeComponent(); + _container = container ?? + throw new ArgumentNullException(nameof(container)); + } + + private void ButtonSelectFilePath_Click(object sender, EventArgs e) + { + var sfd = new SaveFileDialog() + { + Filter = "Pdf Files | *.pdf" + }; + + if (sfd.ShowDialog() == DialogResult.OK) + { + _fileName = sfd.FileName; + labelFileName.Text = Path.GetFileName(_fileName); + } + } + + private void ButtonBuild_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(_fileName)) + { + throw new Exception("Отсутствует имя файла для отчета"); + } + + if (_container.Resolve().CreateChart(_fileName, dateTimePicker.Value)) + { + MessageBox.Show("Документ сформирован", "Формирование документа", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } + else + { + MessageBox.Show("Возникли ошибки при формировании документа (подробности в логах)", "Формирование документа", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "Ошибка при создании отчета", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } +} diff --git a/FuelAccounting/FuelAccounting/Forms/FormKilometersDrivenReport.resx b/FuelAccounting/FuelAccounting/Forms/FormKilometersDrivenReport.resx new file mode 100644 index 0000000..af32865 --- /dev/null +++ b/FuelAccounting/FuelAccounting/Forms/FormKilometersDrivenReport.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/FuelAccounting/FuelAccounting/FuelAccounting.csproj b/FuelAccounting/FuelAccounting/FuelAccounting.csproj index 62b2a29..f9436c8 100644 --- a/FuelAccounting/FuelAccounting/FuelAccounting.csproj +++ b/FuelAccounting/FuelAccounting/FuelAccounting.csproj @@ -16,6 +16,7 @@ + diff --git a/FuelAccounting/FuelAccounting/Reports/ChartReport.cs b/FuelAccounting/FuelAccounting/Reports/ChartReport.cs new file mode 100644 index 0000000..04595da --- /dev/null +++ b/FuelAccounting/FuelAccounting/Reports/ChartReport.cs @@ -0,0 +1,47 @@ +using FuelAccounting.Repositories; +using Microsoft.Extensions.Logging; + +namespace FuelAccounting.Reports; + +internal class ChartReport +{ + private readonly IRefuelingRepository _refuelingRepository; + + private readonly ILogger _logger; + + public ChartReport(IRefuelingRepository refuelingRepository, ILogger logger) + { + _refuelingRepository = refuelingRepository ?? + throw new ArgumentNullException(nameof(refuelingRepository)); + _logger = logger ?? + throw new ArgumentNullException(nameof(logger)); + } + + public bool CreateChart(string filePath, DateTime dateTime) + { + try + { + new PdfBuilder(filePath) + .AddHeader("Подсчет километража") + .AddPieChart("Кол-во проезженных километров", GetData(dateTime)) + .Build(); + + return true; + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка при формировании документа"); + return false; + } + } + + private List<(string Caption, double Value)> GetData(DateTime dateTime) + { + return _refuelingRepository + .ReadRefuelings() + .Where(x => x.RefuelingDate == dateTime.Date) + .GroupBy(x => x.CarId, (key, group) => new { Id = key, Count = group.Sum(x => x.Kilometers) }) + .Select(x => (x.Id.ToString(), (double)x.Count)) + .ToList(); + } +} diff --git a/FuelAccounting/FuelAccounting/Reports/PdfBuilder.cs b/FuelAccounting/FuelAccounting/Reports/PdfBuilder.cs new file mode 100644 index 0000000..95bfab4 --- /dev/null +++ b/FuelAccounting/FuelAccounting/Reports/PdfBuilder.cs @@ -0,0 +1,87 @@ +using MigraDoc.DocumentObjectModel; +using MigraDoc.DocumentObjectModel.Shapes.Charts; +using MigraDoc.Rendering; +using System.Text; + +namespace FuelAccounting.Reports; + +internal class PdfBuilder +{ + private readonly string _filePath; + + private readonly Document _document; + + public PdfBuilder(string filePath) + { + if (string.IsNullOrWhiteSpace(filePath)) + { + throw new ArgumentNullException(nameof(filePath)); + } + + if (File.Exists(filePath)) + { + File.Delete(filePath); + } + + _filePath = filePath; + _document = new Document(); + DefineStyles(); + } + + public PdfBuilder AddHeader(string header) + { + _document.AddSection().AddParagraph(header, "NormalBold"); + return this; + } + + public PdfBuilder AddPieChart(string title, List<(string Caption, double Value)> data) + { + var chart = new Chart(ChartType.Pie2D); + var series = chart.SeriesCollection.AddSeries(); + series.Add(data.Select(x => x.Value).ToArray()); + + var xseries = chart.XValues.AddXSeries(); + xseries.Add(data.Select(x => x.Caption).ToArray()); + + chart.DataLabel.Type = DataLabelType.Percent; + chart.DataLabel.Position = DataLabelPosition.OutsideEnd; + + chart.Width = Unit.FromCentimeter(16); + chart.Height = Unit.FromCentimeter(12); + + chart.TopArea.AddParagraph(title); + + chart.XAxis.MajorTickMark = TickMarkType.Outside; + + chart.YAxis.MajorTickMark = TickMarkType.Outside; + chart.YAxis.HasMajorGridlines = true; + + chart.PlotArea.LineFormat.Width = 1; + chart.PlotArea.LineFormat.Visible = true; + + chart.TopArea.AddLegend(); + + _document.LastSection.Add(chart); + + return this; + } + + public void Build() + { + Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); + var renderer = new PdfDocumentRenderer(true) + { + Document = _document + }; + + renderer.RenderDocument(); + renderer.PdfDocument.Save(_filePath); + } + + private void DefineStyles() + { + var headerStyle = _document.Styles.AddStyle("NormalBold", "Normal"); + headerStyle.Font.Bold = true; + headerStyle.Font.Size = 14; + } +}