diff --git a/ProjectPolyclinic/ProjectPolyclinic/FormPolyclinic.Designer.cs b/ProjectPolyclinic/ProjectPolyclinic/FormPolyclinic.Designer.cs index 566fab5..335ca0b 100644 --- a/ProjectPolyclinic/ProjectPolyclinic/FormPolyclinic.Designer.cs +++ b/ProjectPolyclinic/ProjectPolyclinic/FormPolyclinic.Designer.cs @@ -39,6 +39,7 @@ отчетыToolStripMenuItem = new ToolStripMenuItem(); directoryReportToolStripMenuItem = new ToolStripMenuItem(); visitingReportToolStripMenuItem = new ToolStripMenuItem(); + повышениеКвалификацииToolStripMenuItem = new ToolStripMenuItem(); menuStrip1.SuspendLayout(); SuspendLayout(); // @@ -102,7 +103,7 @@ // // отчетыToolStripMenuItem // - отчетыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { directoryReportToolStripMenuItem, visitingReportToolStripMenuItem }); + отчетыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { directoryReportToolStripMenuItem, visitingReportToolStripMenuItem, повышениеКвалификацииToolStripMenuItem }); отчетыToolStripMenuItem.Name = "отчетыToolStripMenuItem"; отчетыToolStripMenuItem.Size = new Size(60, 20); отчетыToolStripMenuItem.Text = "Отчеты"; @@ -123,6 +124,14 @@ visitingReportToolStripMenuItem.Text = "Движение визитов"; visitingReportToolStripMenuItem.Click += VisitingReportToolStripMenuItem_Click; // + // повышениеКвалификацииToolStripMenuItem + // + повышениеКвалификацииToolStripMenuItem.Name = "повышениеКвалификацииToolStripMenuItem"; + повышениеКвалификацииToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.P; + повышениеКвалификацииToolStripMenuItem.Size = new Size(280, 22); + повышениеКвалификацииToolStripMenuItem.Text = "Повышение квалификации"; + повышениеКвалификацииToolStripMenuItem.Click += ProfessionalDevelopmentDistributionToolStripMenuItem_Click; + // // FormPolyclinic // AutoScaleDimensions = new SizeF(7F, 15F); @@ -154,5 +163,6 @@ private ToolStripMenuItem отчетыToolStripMenuItem; private ToolStripMenuItem directoryReportToolStripMenuItem; private ToolStripMenuItem visitingReportToolStripMenuItem; + private ToolStripMenuItem повышениеКвалификацииToolStripMenuItem; } } diff --git a/ProjectPolyclinic/ProjectPolyclinic/FormPolyclinic.cs b/ProjectPolyclinic/ProjectPolyclinic/FormPolyclinic.cs index 701ae4c..16cfa93 100644 --- a/ProjectPolyclinic/ProjectPolyclinic/FormPolyclinic.cs +++ b/ProjectPolyclinic/ProjectPolyclinic/FormPolyclinic.cs @@ -105,5 +105,18 @@ namespace ProjectPolyclinic MessageBoxButtons.OK, MessageBoxIcon.Error); } } + + private void ProfessionalDevelopmentDistributionToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + _container.Resolve().ShowDialog(); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, " ", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } } } diff --git a/ProjectPolyclinic/ProjectPolyclinic/Forms/FormProfessionalDevelopmentDistributionReport.Designer.cs b/ProjectPolyclinic/ProjectPolyclinic/Forms/FormProfessionalDevelopmentDistributionReport.Designer.cs new file mode 100644 index 0000000..e5c2918 --- /dev/null +++ b/ProjectPolyclinic/ProjectPolyclinic/Forms/FormProfessionalDevelopmentDistributionReport.Designer.cs @@ -0,0 +1,108 @@ +namespace ProjectPolyclinic.Forms +{ + partial class FormProfessionalDevelopmentDistributionReport + { + /// + /// 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(); + labelFileName = new Label(); + labelDate = new Label(); + buttonCreate = new Button(); + dateTimePicker = new DateTimePicker(); + SuspendLayout(); + // + // buttonSelectFileName + // + buttonSelectFileName.Location = new Point(46, 28); + buttonSelectFileName.Name = "buttonSelectFileName"; + buttonSelectFileName.Size = new Size(75, 23); + buttonSelectFileName.TabIndex = 0; + buttonSelectFileName.Text = "Выбрать"; + buttonSelectFileName.UseVisualStyleBackColor = true; + buttonSelectFileName.Click += ButtonSelectFileName_Click; + // + // labelFileName + // + labelFileName.AutoSize = true; + labelFileName.Location = new Point(152, 32); + labelFileName.Name = "labelFileName"; + labelFileName.Size = new Size(36, 15); + labelFileName.TabIndex = 1; + labelFileName.Text = "Файл"; + // + // labelDate + // + labelDate.AutoSize = true; + labelDate.Location = new Point(46, 79); + labelDate.Name = "labelDate"; + labelDate.Size = new Size(38, 15); + labelDate.TabIndex = 2; + labelDate.Text = "Дата :"; + // + // buttonCreate + // + buttonCreate.Location = new Point(113, 133); + buttonCreate.Name = "buttonCreate"; + buttonCreate.Size = new Size(101, 23); + buttonCreate.TabIndex = 3; + buttonCreate.Text = "Сформировать"; + buttonCreate.UseVisualStyleBackColor = true; + buttonCreate.Click += ButtonCreate_Click; + // + // dateTimePicker + // + dateTimePicker.Location = new Point(113, 79); + dateTimePicker.Name = "dateTimePicker"; + dateTimePicker.Size = new Size(200, 23); + dateTimePicker.TabIndex = 4; + // + // FormProfessionalDevelopmentDistributionReport + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(349, 178); + Controls.Add(dateTimePicker); + Controls.Add(buttonCreate); + Controls.Add(labelDate); + Controls.Add(labelFileName); + Controls.Add(buttonSelectFileName); + Name = "FormProfessionalDevelopmentDistributionReport"; + StartPosition = FormStartPosition.CenterParent; + Text = "Повышение квалификации"; + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private Button buttonSelectFileName; + private Label labelFileName; + private Label labelDate; + private Button buttonCreate; + private DateTimePicker dateTimePicker; + } +} \ No newline at end of file diff --git a/ProjectPolyclinic/ProjectPolyclinic/Forms/FormProfessionalDevelopmentDistributionReport.cs b/ProjectPolyclinic/ProjectPolyclinic/Forms/FormProfessionalDevelopmentDistributionReport.cs new file mode 100644 index 0000000..4d7c4ab --- /dev/null +++ b/ProjectPolyclinic/ProjectPolyclinic/Forms/FormProfessionalDevelopmentDistributionReport.cs @@ -0,0 +1,72 @@ +using ProjectPolyclinic.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 ProjectPolyclinic.Forms +{ + public partial class FormProfessionalDevelopmentDistributionReport : Form + { + private string _fileName = string.Empty; + private readonly IUnityContainer _container; + + public FormProfessionalDevelopmentDistributionReport(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/ProjectPolyclinic/ProjectPolyclinic/Forms/FormProfessionalDevelopmentDistributionReport.resx b/ProjectPolyclinic/ProjectPolyclinic/Forms/FormProfessionalDevelopmentDistributionReport.resx new file mode 100644 index 0000000..8b2ff64 --- /dev/null +++ b/ProjectPolyclinic/ProjectPolyclinic/Forms/FormProfessionalDevelopmentDistributionReport.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/ProjectPolyclinic/ProjectPolyclinic/Forms/FormVisitingReport.Designer.cs b/ProjectPolyclinic/ProjectPolyclinic/Forms/FormVisitingReport.Designer.cs index 7f43134..491b0fd 100644 --- a/ProjectPolyclinic/ProjectPolyclinic/Forms/FormVisitingReport.Designer.cs +++ b/ProjectPolyclinic/ProjectPolyclinic/Forms/FormVisitingReport.Designer.cs @@ -143,7 +143,8 @@ Controls.Add(dateTimePickerDateEnd); Controls.Add(dateTimePickerDateBegin); Name = "FormVisitingReport"; - Text = "FormVisitingReport"; + StartPosition = FormStartPosition.CenterParent; + Text = "Отчет по визитам"; ResumeLayout(false); PerformLayout(); } diff --git a/ProjectPolyclinic/ProjectPolyclinic/ProjectPolyclinic.csproj b/ProjectPolyclinic/ProjectPolyclinic/ProjectPolyclinic.csproj index 9c16bea..3cd7071 100644 --- a/ProjectPolyclinic/ProjectPolyclinic/ProjectPolyclinic.csproj +++ b/ProjectPolyclinic/ProjectPolyclinic/ProjectPolyclinic.csproj @@ -16,6 +16,7 @@ + diff --git a/ProjectPolyclinic/ProjectPolyclinic/Reports/ChartReport.cs b/ProjectPolyclinic/ProjectPolyclinic/Reports/ChartReport.cs new file mode 100644 index 0000000..218ff97 --- /dev/null +++ b/ProjectPolyclinic/ProjectPolyclinic/Reports/ChartReport.cs @@ -0,0 +1,52 @@ +using Microsoft.Extensions.Logging; +using ProjectPolyclinic.Repositories; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ProjectPolyclinic.Reports; + +internal class ChartReport +{ + private readonly IProfessionalDevelopmentRepository _professionalDevelopmentRepository; + //private readonly IDoctorRepository _doctorRepository; + private readonly ILogger _logger; + public ChartReport(IProfessionalDevelopmentRepository professionalDevelopmentRepository, + IDoctorRepository doctorRepository, + ILogger logger) + { + _professionalDevelopmentRepository = professionalDevelopmentRepository ?? + throw new ArgumentNullException(nameof(professionalDevelopmentRepository)); + //_doctorRepository = doctorRepository ?? + // throw new ArgumentNullException(nameof(doctorRepository)); + _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 _professionalDevelopmentRepository + .ReadProfessionalDevelopment() + .Where(x => x.ProfessionalDevelopmentTime.Date == dateTime.Date) + .GroupBy(x => x.DoctorId, (key, group) => new { Id = key, Count = group.Count() }) + .Select(x => (x.Id.ToString(), (double)x.Count)) + .ToList(); + } +} diff --git a/ProjectPolyclinic/ProjectPolyclinic/Reports/ExcelBuilder.cs b/ProjectPolyclinic/ProjectPolyclinic/Reports/ExcelBuilder.cs index 83f41b2..5622f64 100644 --- a/ProjectPolyclinic/ProjectPolyclinic/Reports/ExcelBuilder.cs +++ b/ProjectPolyclinic/ProjectPolyclinic/Reports/ExcelBuilder.cs @@ -34,7 +34,7 @@ internal class ExcelBuilder } public ExcelBuilder AddHeader(string header, int startIndex, int count) { - CreateCell(startIndex, _rowIndex, header,StyleIndex.SimpleTextWithoutBorder); + CreateCell(startIndex, _rowIndex, header,StyleIndex.BoldTextWithoutBorder); for (int i = startIndex + 1; i < startIndex + count; ++i) { CreateCell(i, _rowIndex, "", @@ -80,7 +80,7 @@ internal class ExcelBuilder for (var j = 0; j < data.First().Length; ++j) { CreateCell(j, _rowIndex, data.First()[j], - StyleIndex.SimpleTextWithoutBorder); + StyleIndex.BoldTextWithBorder); } _rowIndex++; for (var i = 1; i < data.Count - 1; ++i) @@ -95,7 +95,7 @@ internal class ExcelBuilder for (var j = 0; j < data.Last().Length; ++j) { CreateCell(j, _rowIndex, data.Last()[j], - StyleIndex.SimpleTextWithoutBorder); + StyleIndex.BoldTextWithBorder); } _rowIndex++; return this; diff --git a/ProjectPolyclinic/ProjectPolyclinic/Reports/PdfBuilder.cs b/ProjectPolyclinic/ProjectPolyclinic/Reports/PdfBuilder.cs new file mode 100644 index 0000000..ad10441 --- /dev/null +++ b/ProjectPolyclinic/ProjectPolyclinic/Reports/PdfBuilder.cs @@ -0,0 +1,91 @@ + +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; +using Color = MigraDoc.DocumentObjectModel.Color; + +namespace ProjectPolyclinic.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.AddStyle("NormalBold", "Normal"); + headerStyle.Font.Bold = true; + headerStyle.Font.Size = 14; + headerStyle.Font.Color = Colors.DeepPink; + } +} + +