From e461145e652ffebe2ebc86c3c803b9d0b423764a Mon Sep 17 00:00:00 2001 From: pnevmoslon1 Date: Wed, 25 Dec 2024 03:43:10 +0400 Subject: [PATCH] lab3 --- .../ProjectHotel/Entities/PlacingAthlete.cs | 10 ++ .../Entities/TempAthletePlacingAthlete.cs | 17 ++ .../Forms/FormHotelForAthletes.Designer.cs | 20 ++- .../Forms/FormHotelForAthletes.cs | 26 +++ .../Forms/FormHotelReport.Designer.cs | 163 ++++++++++++++++++ .../ProjectHotel/Forms/FormHotelReport.cs | 80 +++++++++ .../ProjectHotel/Forms/FormHotelReport.resx | 120 +++++++++++++ .../FormPlacingRoomDistribution.Designer.cs | 95 ++++++++++ .../Forms/FormPlacingRoomDistribution.cs | 69 ++++++++ .../Forms/FormPlacingRoomDistribution.resx | 120 +++++++++++++ .../ProjectHotel/Reports/ChartReport.cs | 52 ++++++ .../ProjectHotel/Reports/PdfBuilder.cs | 98 +++++++++++ .../ProjectHotel/Reports/TableReport.cs | 107 +++++++----- .../PlacingAthleteRepository.cs | 12 +- 14 files changed, 945 insertions(+), 44 deletions(-) create mode 100644 ProjectHotel/ProjectHotel/Entities/TempAthletePlacingAthlete.cs create mode 100644 ProjectHotel/ProjectHotel/Forms/FormHotelReport.Designer.cs create mode 100644 ProjectHotel/ProjectHotel/Forms/FormHotelReport.cs create mode 100644 ProjectHotel/ProjectHotel/Forms/FormHotelReport.resx create mode 100644 ProjectHotel/ProjectHotel/Forms/FormPlacingRoomDistribution.Designer.cs create mode 100644 ProjectHotel/ProjectHotel/Forms/FormPlacingRoomDistribution.cs create mode 100644 ProjectHotel/ProjectHotel/Forms/FormPlacingRoomDistribution.resx create mode 100644 ProjectHotel/ProjectHotel/Reports/ChartReport.cs create mode 100644 ProjectHotel/ProjectHotel/Reports/PdfBuilder.cs diff --git a/ProjectHotel/ProjectHotel/Entities/PlacingAthlete.cs b/ProjectHotel/ProjectHotel/Entities/PlacingAthlete.cs index 13df528..01de0be 100644 --- a/ProjectHotel/ProjectHotel/Entities/PlacingAthlete.cs +++ b/ProjectHotel/ProjectHotel/Entities/PlacingAthlete.cs @@ -27,4 +27,14 @@ public class PlacingAthlete }; } + public static PlacingAthlete CreateOpeartion(TempAthletePlacingAthlete tempAthletePlacingAthlete, IEnumerable athletePlacingAthletes) + { + return new PlacingAthlete + { + Id = tempAthletePlacingAthlete.Id, + RoomId = tempAthletePlacingAthlete.RoomId, + PlacingDate = DateTime.Now, + AthletePlacingAthletes = athletePlacingAthletes + }; + } } diff --git a/ProjectHotel/ProjectHotel/Entities/TempAthletePlacingAthlete.cs b/ProjectHotel/ProjectHotel/Entities/TempAthletePlacingAthlete.cs new file mode 100644 index 0000000..fb98623 --- /dev/null +++ b/ProjectHotel/ProjectHotel/Entities/TempAthletePlacingAthlete.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ProjectHotel.Entities; + +public class TempAthletePlacingAthlete +{ + public int Id { get; private set; } + public int RoomId { get; private set; } + public DateTime PlacingDate { get; private set; } + public int AthleteId { get; private set; } + public int PlacingAthleteId { get; private set; } + public int LengthOfStay { get; private set; } +} diff --git a/ProjectHotel/ProjectHotel/Forms/FormHotelForAthletes.Designer.cs b/ProjectHotel/ProjectHotel/Forms/FormHotelForAthletes.Designer.cs index 5418fb0..a95752f 100644 --- a/ProjectHotel/ProjectHotel/Forms/FormHotelForAthletes.Designer.cs +++ b/ProjectHotel/ProjectHotel/Forms/FormHotelForAthletes.Designer.cs @@ -38,6 +38,8 @@ CleaningRoomToolStripMenuItem = new ToolStripMenuItem(); ReportsToolStripMenuItem = new ToolStripMenuItem(); DirectoryReportToolStripMenuItem = new ToolStripMenuItem(); + HotelToolStripMenuItem = new ToolStripMenuItem(); + DiagramToolStripMenuItem = new ToolStripMenuItem(); menuStrip1.SuspendLayout(); SuspendLayout(); // @@ -101,7 +103,7 @@ // // ReportsToolStripMenuItem // - ReportsToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { DirectoryReportToolStripMenuItem }); + ReportsToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { DirectoryReportToolStripMenuItem, HotelToolStripMenuItem, DiagramToolStripMenuItem }); ReportsToolStripMenuItem.Name = "ReportsToolStripMenuItem"; ReportsToolStripMenuItem.Size = new Size(60, 20); ReportsToolStripMenuItem.Text = "Отчеты"; @@ -114,6 +116,20 @@ DirectoryReportToolStripMenuItem.Text = "Документ со справочниками"; DirectoryReportToolStripMenuItem.Click += DirectoryReportToolStripMenuItem_Click; // + // HotelToolStripMenuItem + // + HotelToolStripMenuItem.Name = "HotelToolStripMenuItem"; + HotelToolStripMenuItem.Size = new Size(280, 22); + HotelToolStripMenuItem.Text = "Отчет о проживающих в отеле"; + HotelToolStripMenuItem.Click += RoomToolStripMenuItem_Click; + // + // DiagramToolStripMenuItem + // + DiagramToolStripMenuItem.Name = "DiagramToolStripMenuItem"; + DiagramToolStripMenuItem.Size = new Size(280, 22); + DiagramToolStripMenuItem.Text = "Диаграмма"; + DiagramToolStripMenuItem.Click += DiagramToolStripMenuItem_Click; + // // FormHotelForAthletes // AutoScaleDimensions = new SizeF(7F, 15F); @@ -144,5 +160,7 @@ private ToolStripMenuItem ReportsToolStripMenuItem; private ToolStripMenuItem CleaningRoomToolStripMenuItem; private ToolStripMenuItem DirectoryReportToolStripMenuItem; + private ToolStripMenuItem HotelToolStripMenuItem; + private ToolStripMenuItem DiagramToolStripMenuItem; } } diff --git a/ProjectHotel/ProjectHotel/Forms/FormHotelForAthletes.cs b/ProjectHotel/ProjectHotel/Forms/FormHotelForAthletes.cs index 9870ea2..ac2036f 100644 --- a/ProjectHotel/ProjectHotel/Forms/FormHotelForAthletes.cs +++ b/ProjectHotel/ProjectHotel/Forms/FormHotelForAthletes.cs @@ -93,4 +93,30 @@ public partial class FormHotelForAthletes : Form MessageBoxButtons.OK, MessageBoxIcon.Error); } } + + private void RoomToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + _container.Resolve().ShowDialog(); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, " ", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void DiagramToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + _container.Resolve().ShowDialog(); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, " ", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } } diff --git a/ProjectHotel/ProjectHotel/Forms/FormHotelReport.Designer.cs b/ProjectHotel/ProjectHotel/Forms/FormHotelReport.Designer.cs new file mode 100644 index 0000000..c2de59a --- /dev/null +++ b/ProjectHotel/ProjectHotel/Forms/FormHotelReport.Designer.cs @@ -0,0 +1,163 @@ +namespace ProjectHotel.Forms +{ + partial class FormHotelReport + { + /// + /// 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() + { + dateTimePickerDateBegin = new DateTimePicker(); + dateTimePickerDateEnd = new DateTimePicker(); + comboBoxHotel = new ComboBox(); + label1 = new Label(); + label2 = new Label(); + label3 = new Label(); + label4 = new Label(); + textBoxFilePath = new TextBox(); + buttonSelectFilePath = new Button(); + buttonMakeReport = new Button(); + SuspendLayout(); + // + // dateTimePickerDateBegin + // + dateTimePickerDateBegin.Location = new Point(107, 143); + dateTimePickerDateBegin.Name = "dateTimePickerDateBegin"; + dateTimePickerDateBegin.Size = new Size(200, 23); + dateTimePickerDateBegin.TabIndex = 0; + // + // dateTimePickerDateEnd + // + dateTimePickerDateEnd.Location = new Point(107, 185); + dateTimePickerDateEnd.Name = "dateTimePickerDateEnd"; + dateTimePickerDateEnd.Size = new Size(200, 23); + dateTimePickerDateEnd.TabIndex = 1; + // + // comboBoxHotel + // + comboBoxHotel.FormattingEnabled = true; + comboBoxHotel.Location = new Point(107, 108); + comboBoxHotel.Name = "comboBoxHotel"; + comboBoxHotel.Size = new Size(200, 23); + comboBoxHotel.TabIndex = 2; + // + // label1 + // + label1.AutoSize = true; + label1.Location = new Point(8, 68); + label1.Name = "label1"; + label1.Size = new Size(87, 15); + label1.TabIndex = 3; + label1.Text = "Путь до файла"; + // + // label2 + // + label2.AutoSize = true; + label2.Location = new Point(9, 111); + label2.Name = "label2"; + label2.Size = new Size(40, 15); + label2.TabIndex = 4; + label2.Text = "Отель"; + // + // label3 + // + label3.AutoSize = true; + label3.Location = new Point(8, 149); + label3.Name = "label3"; + label3.Size = new Size(74, 15); + label3.TabIndex = 5; + label3.Text = "Дата начала"; + // + // label4 + // + label4.AutoSize = true; + label4.Location = new Point(8, 191); + label4.Name = "label4"; + label4.Size = new Size(68, 15); + label4.TabIndex = 6; + label4.Text = "Дата конца"; + // + // textBoxFilePath + // + textBoxFilePath.Location = new Point(107, 65); + textBoxFilePath.Name = "textBoxFilePath"; + textBoxFilePath.Size = new Size(200, 23); + textBoxFilePath.TabIndex = 7; + // + // buttonSelectFilePath + // + buttonSelectFilePath.Location = new Point(323, 64); + buttonSelectFilePath.Name = "buttonSelectFilePath"; + buttonSelectFilePath.Size = new Size(25, 23); + buttonSelectFilePath.TabIndex = 8; + buttonSelectFilePath.Text = ". ."; + buttonSelectFilePath.UseVisualStyleBackColor = true; + buttonSelectFilePath.Click += buttonSelectFilePath_Click; + // + // buttonMakeReport + // + buttonMakeReport.Location = new Point(107, 292); + buttonMakeReport.Name = "buttonMakeReport"; + buttonMakeReport.Size = new Size(128, 26); + buttonMakeReport.TabIndex = 9; + buttonMakeReport.Text = "сформировать"; + buttonMakeReport.UseVisualStyleBackColor = true; + buttonMakeReport.Click += buttonMakeReport_Click; + // + // FormRoomReport + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(374, 330); + Controls.Add(buttonMakeReport); + Controls.Add(buttonSelectFilePath); + Controls.Add(textBoxFilePath); + Controls.Add(label4); + Controls.Add(label3); + Controls.Add(label2); + Controls.Add(label1); + Controls.Add(comboBoxHotel); + Controls.Add(dateTimePickerDateEnd); + Controls.Add(dateTimePickerDateBegin); + Name = "FormRoomReport"; + StartPosition = FormStartPosition.CenterParent; + Text = "FormRoomReport"; + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private DateTimePicker dateTimePickerDateBegin; + private DateTimePicker dateTimePickerDateEnd; + private ComboBox comboBoxHotel; + private Label label1; + private Label label2; + private Label label3; + private Label label4; + private TextBox textBoxFilePath; + private Button buttonSelectFilePath; + private Button buttonMakeReport; + } +} \ No newline at end of file diff --git a/ProjectHotel/ProjectHotel/Forms/FormHotelReport.cs b/ProjectHotel/ProjectHotel/Forms/FormHotelReport.cs new file mode 100644 index 0000000..1a01c21 --- /dev/null +++ b/ProjectHotel/ProjectHotel/Forms/FormHotelReport.cs @@ -0,0 +1,80 @@ +using ProjectHotel.Reports; +using ProjectHotel.Repositories; +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 ProjectHotel.Forms; + +public partial class FormHotelReport : Form +{ + private readonly IUnityContainer _container; + public FormHotelReport(IUnityContainer container, IHotelRepository hotelRepository) + { + InitializeComponent(); + _container = container ?? + throw new ArgumentNullException(nameof(container)); + comboBoxHotel.DataSource = hotelRepository.ReadHotels(); + comboBoxHotel.DisplayMember = "Name"; + comboBoxHotel.ValueMember = "Id"; + } + private void buttonSelectFilePath_Click(object sender, EventArgs e) + { + var sfd = new SaveFileDialog() + { + Filter = "Excel Files | *.xlsx" + }; + if (sfd.ShowDialog() != DialogResult.OK) + { + return; + } + textBoxFilePath.Text = sfd.FileName; + } + private void buttonMakeReport_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textBoxFilePath.Text)) + { + throw new Exception("Отсутствует имя файла для отчета"); + } + if (comboBoxHotel.SelectedIndex < 0) + { + throw new Exception("Не выбран отель"); + } + if (dateTimePickerDateEnd.Value <= + dateTimePickerDateBegin.Value) + { + throw new Exception("Дата начала должна быть раньше даты окончания"); + } + if + (_container.Resolve().CreateTable(textBoxFilePath.Text, + (int)comboBoxHotel.SelectedValue!, + dateTimePickerDateBegin.Value, dateTimePickerDateEnd.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/ProjectHotel/ProjectHotel/Forms/FormHotelReport.resx b/ProjectHotel/ProjectHotel/Forms/FormHotelReport.resx new file mode 100644 index 0000000..af32865 --- /dev/null +++ b/ProjectHotel/ProjectHotel/Forms/FormHotelReport.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/ProjectHotel/ProjectHotel/Forms/FormPlacingRoomDistribution.Designer.cs b/ProjectHotel/ProjectHotel/Forms/FormPlacingRoomDistribution.Designer.cs new file mode 100644 index 0000000..c062f95 --- /dev/null +++ b/ProjectHotel/ProjectHotel/Forms/FormPlacingRoomDistribution.Designer.cs @@ -0,0 +1,95 @@ +namespace ProjectHotel.Forms +{ + partial class FormPlacingRoomDistribution + { + /// + /// 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() + { + buttonSelectFileName = new Button(); + dateTimePicker = new DateTimePicker(); + buttonCreate = new Button(); + labelFileName = new Label(); + SuspendLayout(); + // + // buttonSelectFileName + // + buttonSelectFileName.Location = new Point(12, 31); + buttonSelectFileName.Name = "buttonSelectFileName"; + buttonSelectFileName.Size = new Size(71, 23); + buttonSelectFileName.TabIndex = 0; + buttonSelectFileName.Text = "Выбрать "; + buttonSelectFileName.UseVisualStyleBackColor = true; + buttonSelectFileName.Click += buttonSelectFileName_Click; + // + // dateTimePicker + // + dateTimePicker.Location = new Point(75, 90); + dateTimePicker.Name = "dateTimePicker"; + dateTimePicker.Size = new Size(200, 23); + dateTimePicker.TabIndex = 2; + // + // buttonCreate + // + buttonCreate.Location = new Point(75, 130); + buttonCreate.Name = "buttonCreate"; + buttonCreate.Size = new Size(200, 62); + buttonCreate.TabIndex = 3; + buttonCreate.Text = "Сформировать"; + buttonCreate.UseVisualStyleBackColor = true; + buttonCreate.Click += buttonCreate_Click; + // + // labelFileName + // + labelFileName.AutoSize = true; + labelFileName.Location = new Point(89, 35); + labelFileName.Name = "labelFileName"; + labelFileName.Size = new Size(36, 15); + labelFileName.TabIndex = 4; + labelFileName.Text = "Файл"; + // + // FormPlacingRoomDistribution + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(329, 217); + Controls.Add(labelFileName); + Controls.Add(buttonCreate); + Controls.Add(dateTimePicker); + Controls.Add(buttonSelectFileName); + Name = "FormPlacingRoomDistribution"; + Text = "FormPlacingRoomDistribution"; + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private Button buttonSelectFileName; + private DateTimePicker dateTimePicker; + private Button buttonCreate; + private Label labelFileName; + } +} \ No newline at end of file diff --git a/ProjectHotel/ProjectHotel/Forms/FormPlacingRoomDistribution.cs b/ProjectHotel/ProjectHotel/Forms/FormPlacingRoomDistribution.cs new file mode 100644 index 0000000..0719579 --- /dev/null +++ b/ProjectHotel/ProjectHotel/Forms/FormPlacingRoomDistribution.cs @@ -0,0 +1,69 @@ +using ProjectHotel.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 ProjectHotel.Forms; + +public partial class FormPlacingRoomDistribution : Form +{ + + private string _fileName = string.Empty; + private readonly IUnityContainer _container; + public FormPlacingRoomDistribution(IUnityContainer container) + { + InitializeComponent(); + _container = container ?? + throw new ArgumentNullException(nameof(container)); + } + private void buttonSelectFileName_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 buttonCreate_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/ProjectHotel/ProjectHotel/Forms/FormPlacingRoomDistribution.resx b/ProjectHotel/ProjectHotel/Forms/FormPlacingRoomDistribution.resx new file mode 100644 index 0000000..af32865 --- /dev/null +++ b/ProjectHotel/ProjectHotel/Forms/FormPlacingRoomDistribution.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/ProjectHotel/ProjectHotel/Reports/ChartReport.cs b/ProjectHotel/ProjectHotel/Reports/ChartReport.cs new file mode 100644 index 0000000..b0e4076 --- /dev/null +++ b/ProjectHotel/ProjectHotel/Reports/ChartReport.cs @@ -0,0 +1,52 @@ +using Microsoft.Extensions.Logging; +using ProjectHotel.Repositories; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ProjectHotel.Reports; + +internal class ChartReport +{ + private readonly IPlacingAthleteRepository _placingAthleteRepository; + private readonly ILogger _logger; + public ChartReport(IPlacingAthleteRepository placingAthleteRepository, + ILogger logger) + { + _placingAthleteRepository = placingAthleteRepository ?? + throw new + ArgumentNullException(nameof(placingAthleteRepository)); + _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 _placingAthleteRepository + .ReadPlacingAthlete() + .Where(x => x.PlacingDate.Date == dateTime.Date) + .GroupBy(x => x.RoomId, (key, group) => new { + Id = key, + Count = group.Sum(x => x.AthletePlacingAthletes.Count()) + }) + .Select(x => (x.Id.ToString(), (double)x.Count)) + .ToList(); + } +} diff --git a/ProjectHotel/ProjectHotel/Reports/PdfBuilder.cs b/ProjectHotel/ProjectHotel/Reports/PdfBuilder.cs new file mode 100644 index 0000000..2f6a732 --- /dev/null +++ b/ProjectHotel/ProjectHotel/Reports/PdfBuilder.cs @@ -0,0 +1,98 @@ +using MigraDoc.DocumentObjectModel; +using MigraDoc.DocumentObjectModel.Shapes.Charts; +using MigraDoc.Rendering; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ProjectHotel.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) + { + if (data == null || data.Count == 0) + { + return this; + } + + 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; + } +} diff --git a/ProjectHotel/ProjectHotel/Reports/TableReport.cs b/ProjectHotel/ProjectHotel/Reports/TableReport.cs index a73342b..3fd6e6d 100644 --- a/ProjectHotel/ProjectHotel/Reports/TableReport.cs +++ b/ProjectHotel/ProjectHotel/Reports/TableReport.cs @@ -15,7 +15,7 @@ internal class TableReport private readonly IRoomRepository _roomRepository; private readonly ILogger _logger; - internal static readonly string[] item = ["Комната", "Дата", "Проживает сейчас", "Проживало за период"]; + internal static readonly string[] item = ["Комната", "Дата", "Заселено", "Выселено"]; public TableReport(IPlacingAthleteRepository placingAthleteRepository, IRoomRepository roomRepository, ILogger logger) { _placingAthleteRepository = placingAthleteRepository ?? throw new ArgumentNullException(nameof(placingAthleteRepository)); @@ -23,14 +23,14 @@ internal class TableReport _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } - public bool CreateTable(string filePath, int roomId, DateTime startDate, DateTime endDate) + public bool CreateTable(string filePath, int hotelId, DateTime startDate, DateTime endDate) { try { new ExcelBuilder(filePath) - .AddHeader("Сводка о количестве жильцов в комнате", 0, 4) + .AddHeader("Сводка о количестве жильцов в отеле", 0, 4) .AddParagraph("за период", 0) - .AddTable([10, 10, 15, 15], GetData(roomId, startDate, endDate)) + .AddTable([10, 10, 15, 15], GetData(hotelId, startDate, endDate)) .Build(); return true; } @@ -40,42 +40,69 @@ internal class TableReport return false; } } - private List GetData(int athleteId, DateTime startDate, DateTime endDate) + + private List GetData(int hotelId, DateTime startDate, DateTime endDate) { - var data = _placingAthleteRepository - .ReadPlacingAthlete() - .Where(x => x.PlacingDate >= startDate && x.AthletePlacingAthletes.Any(y => new DateTime(x.PlacingDate.Year, x.PlacingDate.Month, y.LengthOfStay + x.PlacingDate.Day) <= endDate)) - .Select(x => new - { - x.RoomId, - Date = x.PlacingDate, - CountIn = x.AthletePlacingAthletes.FirstOrDefault(y => y.AthleteId == athleteId).Count, - CountOut = (int?)null - }) - .Union( - _feedingAnimalRepository - .ReadFeedingAnimals() - .Where(x => x.FeedingDate >= startDate && - x.FeedingDate <= endDate && x.FeedId == feedId) - .Select(x => new - { - x.EmployeeId, - Date = - x.FeedingDate, - CountIn = (int?)null, - CountOut = (int?)x.Ration - })) - .OrderBy(x => x.Date); - return - new List() { item } - .Union( - data - .Select(x => new string[] { -x.EmployeeId.ToString(), x.Date.ToString(), x.CountIn?.ToString() ?? -string.Empty, x.CountOut?.ToString() ?? string.Empty})) - .Union( - [["Всего", "", data.Sum(x => x.CountIn ?? 0).ToString(), -data.Sum(x => x.CountOut ?? 0).ToString()]]) - .ToList(); + var rooms = _roomRepository.ReadRooms().Where(r => r.HotelId == hotelId).ToList(); + var placingAthletes = _placingAthleteRepository.ReadPlacingAthlete().ToList(); + + var athletePlacements = placingAthletes + .SelectMany(pa => pa.AthletePlacingAthletes, (pa, apa) => new + { + PlacingAthleteId = pa.Id, + RoomId = pa.RoomId, + PlacingDate = pa.PlacingDate.Date, + LengthOfStay = apa.LengthOfStay, + CheckoutDate = pa.PlacingDate.AddDays(apa.LengthOfStay).Date + }) + .Where(ap => rooms.Any(r => r.Id == ap.RoomId)) + .ToList(); + + var placementSummary = athletePlacements + .Where(ap => ap.PlacingDate >= startDate.Date && ap.PlacingDate <= endDate.Date) + .GroupBy(ap => new { ap.RoomId, ap.PlacingDate }) + .Select(g => new + { + RoomId = g.Key.RoomId, + Date = g.Key.PlacingDate, + CheckedIn = (int?)g.Count(), + CheckedOut = (int?)null + }) + .Union( + athletePlacements + .Where(ap => ap.CheckoutDate >= startDate.Date && ap.CheckoutDate <= endDate.Date) + .GroupBy(ap => new { ap.RoomId, ap.CheckoutDate }) + .Select(g => new + { + RoomId = g.Key.RoomId, + Date = g.Key.CheckoutDate, + CheckedIn = (int?)null, + CheckedOut = (int?)g.Count() + }) + ) + .ToList(); + + var result = placementSummary + .GroupBy(ps => new { ps.RoomId, ps.Date }) + .Select(g => new + { + RoomId = g.Key.RoomId, + Date = g.Key.Date, + CheckedIn = g.Sum(ps => ps.CheckedIn), + CheckedOut = g.Sum(ps => ps.CheckedOut) + }).OrderBy(r => r.Date) + .ThenBy(r => r.RoomId) + .ToList(); + + return new List() + .Union(result.Select(x => new string[] { + x.RoomId.ToString(), + x.Date.ToString("yyyy-MM-dd"), + x.CheckedIn?.ToString() ?? string.Empty, + x.CheckedOut?.ToString() ?? string.Empty + })) + .Union(new List { new string[] { "Всего", "", result.Sum(x => x.CheckedIn).ToString() ?? "0", result.Sum(x => x.CheckedOut).ToString() ?? "0" } }) + .ToList(); } + } diff --git a/ProjectHotel/ProjectHotel/Repositories/Implementations/PlacingAthleteRepository.cs b/ProjectHotel/ProjectHotel/Repositories/Implementations/PlacingAthleteRepository.cs index b660e12..1867f25 100644 --- a/ProjectHotel/ProjectHotel/Repositories/Implementations/PlacingAthleteRepository.cs +++ b/ProjectHotel/ProjectHotel/Repositories/Implementations/PlacingAthleteRepository.cs @@ -11,6 +11,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; + namespace ProjectHotel.Repositories.Implementations; internal class PlacingAthleteRepository : IPlacingAthleteRepository @@ -88,10 +89,15 @@ internal class PlacingAthleteRepository : IPlacingAthleteRepository try { using var connection = new NpgsqlConnection(_connectionString.ConnectionString); - var querySelect = @"SELECT * FROM PlacingAthlete"; - var placingAthletes = connection.Query(querySelect); + var querySelect = @"SELECT pa.*,apa.* + FROM PlacingAthlete pa + INNER JOIN AthletePlacingAthlete apa ON apa.PlacingAthleteId = pa.Id + "; + var placingAthletes = connection.Query(querySelect); _logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(placingAthletes)); - return placingAthletes; + return placingAthletes.GroupBy(x => x.Id, y => y, (key, value) => + PlacingAthlete.CreateOpeartion(value.First(), value.Select(z => + AthletePlacingAthlete.CreateElement(0, z.AthleteId, z.LengthOfStay)))).ToList(); } catch (Exception ex) {