PIBD-22. Denisov V.D. LabWork_3 #4

Closed
kisame wants to merge 3 commits from LabWork_3 into LabWork_2
28 changed files with 1930 additions and 37 deletions

View File

@ -34,8 +34,4 @@ public class Doctor
SpecializationLevel = specializationLevel
};
}
}

View File

@ -1,4 +1,4 @@
 using ProjectPolyclinic.Entities.Enums;
using ProjectPolyclinic.Entities.Enums;
using System;
using System.Collections.Generic;
using System.Linq;

View File

@ -9,9 +9,6 @@ namespace ProjectPolyclinic.Entities;
public class MedicalHistory
{
public int Id { get; private set; }
public int PatientId { get; private set; }
@ -38,4 +35,20 @@ public class MedicalHistory
};
}
public static MedicalHistory CreateEntity(TempMedicalHistory tempMedicalHistory,
IEnumerable<DrugMedHistory> drugMedHistory)
{
return new MedicalHistory
{
Id = tempMedicalHistory.Id,
PatientId = tempMedicalHistory.PatientId,
DoctorId = tempMedicalHistory.DoctorId,
VisitDate = tempMedicalHistory.VisitDate,
Status = (Status)tempMedicalHistory.Status,
DrugMedHistory = drugMedHistory
};
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ProjectPolyclinic.Entities;
public class TempMedicalHistory
{
public int Id { get; set; }
public int PatientId { get; set; }
public int DoctorId { get; set; }
public DateTime VisitDate { get; set; }
public int Status { get; set; }
public int DrugId { get; set; }
public int Count { get; set; }
}

View File

@ -37,6 +37,9 @@
MedHistoryToolStripMenuItem = new ToolStripMenuItem();
DoctorPayToolStripMenuItem = new ToolStripMenuItem();
otchetsToolStripMenuItem = new ToolStripMenuItem();
DirectoryReportToolStripMenuItem = new ToolStripMenuItem();
DoctorPayReportToolStripMenuItem = new ToolStripMenuItem();
DrugCountToolStripMenuItem = new ToolStripMenuItem();
menuStrip1.SuspendLayout();
SuspendLayout();
//
@ -59,21 +62,21 @@
// DoctorsToolStripMenuItem
//
DoctorsToolStripMenuItem.Name = "DoctorsToolStripMenuItem";
DoctorsToolStripMenuItem.Size = new Size(180, 22);
DoctorsToolStripMenuItem.Size = new Size(130, 22);
DoctorsToolStripMenuItem.Text = "Врачи";
DoctorsToolStripMenuItem.Click += DoctorsToolStripMenuItem_Click;
//
// PacientsToolStripMenuItem
//
PacientsToolStripMenuItem.Name = "PacientsToolStripMenuItem";
PacientsToolStripMenuItem.Size = new Size(180, 22);
PacientsToolStripMenuItem.Size = new Size(130, 22);
PacientsToolStripMenuItem.Text = "Пациенты";
PacientsToolStripMenuItem.Click += PacientsToolStripMenuItem_Click;
//
// DrugsToolStripMenuItem
//
DrugsToolStripMenuItem.Name = "DrugsToolStripMenuItem";
DrugsToolStripMenuItem.Size = new Size(180, 22);
DrugsToolStripMenuItem.Size = new Size(130, 22);
DrugsToolStripMenuItem.Text = "Лекарства";
DrugsToolStripMenuItem.Click += DrugsToolStripMenuItem_Click;
//
@ -87,23 +90,48 @@
// MedHistoryToolStripMenuItem
//
MedHistoryToolStripMenuItem.Name = "MedHistoryToolStripMenuItem";
MedHistoryToolStripMenuItem.Size = new Size(180, 22);
MedHistoryToolStripMenuItem.Size = new Size(162, 22);
MedHistoryToolStripMenuItem.Text = "Учет мед. карты";
MedHistoryToolStripMenuItem.Click += MedHistoryToolStripMenuItem_Click;
//
// DoctorPayToolStripMenuItem
//
DoctorPayToolStripMenuItem.Name = "DoctorPayToolStripMenuItem";
DoctorPayToolStripMenuItem.Size = new Size(180, 22);
DoctorPayToolStripMenuItem.Size = new Size(162, 22);
DoctorPayToolStripMenuItem.Text = "Оплата врачу";
DoctorPayToolStripMenuItem.Click += DoctorPayToolStripMenuItem_Click;
//
// otchetsToolStripMenuItem
//
otchetsToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { DirectoryReportToolStripMenuItem, DoctorPayReportToolStripMenuItem, DrugCountToolStripMenuItem });
otchetsToolStripMenuItem.Name = "otchetsToolStripMenuItem";
otchetsToolStripMenuItem.Size = new Size(60, 20);
otchetsToolStripMenuItem.Text = "Отчеты";
//
// DirectoryReportToolStripMenuItem
//
DirectoryReportToolStripMenuItem.Name = "DirectoryReportToolStripMenuItem";
DirectoryReportToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.W;
DirectoryReportToolStripMenuItem.Size = new Size(280, 22);
DirectoryReportToolStripMenuItem.Text = "Документ со справочниками";
DirectoryReportToolStripMenuItem.Click += DirectoryReportToolStripMenuItem_Click;
//
// DoctorPayReportToolStripMenuItem
//
DoctorPayReportToolStripMenuItem.Name = "DoctorPayReportToolStripMenuItem";
DoctorPayReportToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.E;
DoctorPayReportToolStripMenuItem.Size = new Size(280, 22);
DoctorPayReportToolStripMenuItem.Text = "Оплаты врачам";
DoctorPayReportToolStripMenuItem.Click += DoctorPayReportToolStripMenuItem_Click;
//
// DrugCountToolStripMenuItem
//
DrugCountToolStripMenuItem.Name = "DrugCountToolStripMenuItem";
DrugCountToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.P;
DrugCountToolStripMenuItem.Size = new Size(280, 22);
DrugCountToolStripMenuItem.Text = "Распределение лекарств";
DrugCountToolStripMenuItem.Click += DrugCountToolStripMenuItem_Click;
//
// FormPolyclinic
//
AutoScaleDimensions = new SizeF(7F, 15F);
@ -134,5 +162,8 @@
private ToolStripMenuItem MedHistoryToolStripMenuItem;
private ToolStripMenuItem otchetsToolStripMenuItem;
private ToolStripMenuItem DoctorPayToolStripMenuItem;
private ToolStripMenuItem DirectoryReportToolStripMenuItem;
private ToolStripMenuItem DoctorPayReportToolStripMenuItem;
private ToolStripMenuItem DrugCountToolStripMenuItem;
}
}

View File

@ -78,4 +78,48 @@ public partial class FormPolyclinic : Form
MessageBox.Show(ex.Message, "Îøèáêà ïðè çàãðóçêå", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void DirectoryReporToolStripMenuItem_Click(object sender, EventArgs e)
{
}
private void DirectoryReportToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
_container.Resolve<FormDirectoryReport>().ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Îøèáêà ïðè çàãðóçêå",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void DoctorPayReportToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
_container.Resolve<FormDoctorPayReport>().ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Îøèáêà ïðè çàãðóçêå",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void DrugCountToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
_container.Resolve<DrugsCountReport>().ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Îøèáêà ïðè çàãðóçêå",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}

View File

@ -0,0 +1,108 @@
namespace ProjectPolyclinic.Forms
{
partial class DrugsCountReport
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
dateTimePicker = new DateTimePicker();
labelDate = new Label();
labelFileName = new Label();
buttonSelectFileName = new Button();
buttonBuild = new Button();
SuspendLayout();
//
// dateTimePicker
//
dateTimePicker.Location = new Point(87, 83);
dateTimePicker.Name = "dateTimePicker";
dateTimePicker.Size = new Size(200, 23);
dateTimePicker.TabIndex = 4;
//
// labelDate
//
labelDate.AutoSize = true;
labelDate.Location = new Point(35, 86);
labelDate.Name = "labelDate";
labelDate.Size = new Size(32, 15);
labelDate.TabIndex = 5;
labelDate.Text = "Дата";
//
// labelFileName
//
labelFileName.AutoSize = true;
labelFileName.Location = new Point(116, 26);
labelFileName.Name = "labelFileName";
labelFileName.Size = new Size(36, 15);
labelFileName.TabIndex = 7;
labelFileName.Text = "Файл";
//
// buttonSelectFileName
//
buttonSelectFileName.Location = new Point(35, 22);
buttonSelectFileName.Name = "buttonSelectFileName";
buttonSelectFileName.Size = new Size(75, 23);
buttonSelectFileName.TabIndex = 6;
buttonSelectFileName.Text = "Выбрать";
buttonSelectFileName.UseVisualStyleBackColor = true;
buttonSelectFileName.Click += buttonSelectFileName_Click;
//
// buttonBuild
//
buttonBuild.Location = new Point(35, 145);
buttonBuild.Name = "buttonBuild";
buttonBuild.Size = new Size(238, 48);
buttonBuild.TabIndex = 8;
buttonBuild.Text = "Сформировать";
buttonBuild.UseVisualStyleBackColor = true;
buttonBuild.Click += buttonBuild_Click;
//
// DrugsCountReport
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(314, 207);
Controls.Add(buttonBuild);
Controls.Add(labelFileName);
Controls.Add(buttonSelectFileName);
Controls.Add(labelDate);
Controls.Add(dateTimePicker);
Name = "DrugsCountReport";
StartPosition = FormStartPosition.CenterScreen;
Text = "Распределение лекарств";
ResumeLayout(false);
PerformLayout();
}
#endregion
private DateTimePicker dateTimePicker;
private Label labelDate;
private Label labelFileName;
private Button buttonSelectFileName;
private Button buttonBuild;
}
}

View File

@ -0,0 +1,69 @@
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 DrugsCountReport : Form
{
private string _fileName = string.Empty;
private readonly IUnityContainer _container;
public DrugsCountReport(IUnityContainer container)
{
InitializeComponent();
_container = container ??
throw new ArgumentNullException(nameof(container));
}
private void buttonBuild_Click(object sender, EventArgs e)
{
try
{
if (string.IsNullOrWhiteSpace(_fileName))
{
throw new Exception("Отсутствует имя файла для отчета");
}
if
(_container.Resolve<ChartReport>().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);
}
}
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);
}
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,100 @@
namespace ProjectPolyclinic.Forms
{
partial class FormDirectoryReport
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
checkBoxDoctors = new CheckBox();
checkBoxPatients = new CheckBox();
checkBoxDrugs = new CheckBox();
buttonBuild = new Button();
SuspendLayout();
//
// checkBoxDoctors
//
checkBoxDoctors.AutoSize = true;
checkBoxDoctors.Location = new Point(12, 12);
checkBoxDoctors.Name = "checkBoxDoctors";
checkBoxDoctors.Size = new Size(60, 19);
checkBoxDoctors.TabIndex = 0;
checkBoxDoctors.Text = "Врачи";
checkBoxDoctors.UseVisualStyleBackColor = true;
//
// checkBoxPatients
//
checkBoxPatients.AutoSize = true;
checkBoxPatients.Location = new Point(12, 49);
checkBoxPatients.Name = "checkBoxPatients";
checkBoxPatients.Size = new Size(82, 19);
checkBoxPatients.TabIndex = 1;
checkBoxPatients.Text = "Пациенты";
checkBoxPatients.UseVisualStyleBackColor = true;
//
// checkBoxDrugs
//
checkBoxDrugs.AutoSize = true;
checkBoxDrugs.Location = new Point(12, 90);
checkBoxDrugs.Name = "checkBoxDrugs";
checkBoxDrugs.Size = new Size(82, 19);
checkBoxDrugs.TabIndex = 2;
checkBoxDrugs.Text = "Лекарства";
checkBoxDrugs.UseVisualStyleBackColor = true;
//
// buttonBuild
//
buttonBuild.Location = new Point(178, 22);
buttonBuild.Name = "buttonBuild";
buttonBuild.Size = new Size(172, 71);
buttonBuild.TabIndex = 3;
buttonBuild.Text = "Сформировать";
buttonBuild.UseVisualStyleBackColor = true;
buttonBuild.Click += buttonBuild_Click;
//
// FormDirectoryReport
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(375, 127);
Controls.Add(buttonBuild);
Controls.Add(checkBoxDrugs);
Controls.Add(checkBoxPatients);
Controls.Add(checkBoxDoctors);
Name = "FormDirectoryReport";
StartPosition = FormStartPosition.CenterScreen;
Text = "Выгрузка справочников";
ResumeLayout(false);
PerformLayout();
}
#endregion
private CheckBox checkBoxDoctors;
private CheckBox checkBoxPatients;
private CheckBox checkBoxDrugs;
private Button buttonBuild;
}
}

View File

@ -0,0 +1,65 @@
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 FormDirectoryReport : Form
{
private readonly IUnityContainer _container;
public FormDirectoryReport(IUnityContainer container)
{
InitializeComponent();
_container = container ??
throw new ArgumentNullException(nameof(container));
}
private void buttonBuild_Click(object sender, EventArgs e)
{
try
{
if (!checkBoxDoctors.Checked && !checkBoxPatients.Checked && !checkBoxDrugs.Checked)
{
throw new Exception("Не выбран ни один справочник для выгрузки");
}
var sfd = new SaveFileDialog()
{
Filter = "Docx Files | *.docx"
};
if (sfd.ShowDialog() != DialogResult.OK)
{
throw new Exception("Не выбран файл для отчета");
}
if
(_container.Resolve<DocReport>().CreateDoc(sfd.FileName, checkBoxDoctors.Checked,
checkBoxPatients.Checked, checkBoxDrugs.Checked))
{
MessageBox.Show("Документ сформирован", "Формирование документа",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("Возникли ошибки при формировании документа. Подробности в логах", "Формирование документа",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при создании отчета",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -36,12 +36,6 @@ public partial class FormMedicalHistories : Form
private void FormMedicalHistories_Load(object sender, EventArgs e)
{
try

View File

@ -91,6 +91,9 @@ public partial class FormMedicalHistory : Form
Convert.ToInt32(row.Cells["ColumnCount"].Value)));
}
return list;
return list
.GroupBy(x => x.DrugId, x => x.Count, (drugId, counts) =>
DrugMedHistory.CreateEntity(0, drugId, 0, counts.Sum()))
.ToList();
}
}

View File

@ -0,0 +1,170 @@
namespace ProjectPolyclinic.Forms
{
partial class FormDoctorPayReport
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
buttonBuild = new Button();
textBoxFilePath = new TextBox();
buttonSelectFilePath = new Button();
comboBoxDoctor = new ComboBox();
dateTimePickerDateEnd = new DateTimePicker();
dateTimePickerDateBegin = new DateTimePicker();
labelDateEnd = new Label();
labelDateStart = new Label();
labelAthlete = new Label();
labelFilePath = new Label();
SuspendLayout();
//
// buttonBuild
//
buttonBuild.Location = new Point(104, 230);
buttonBuild.Name = "buttonBuild";
buttonBuild.Size = new Size(144, 45);
buttonBuild.TabIndex = 4;
buttonBuild.Text = "Сформировать";
buttonBuild.UseVisualStyleBackColor = true;
buttonBuild.Click += buttonBuild_Click;
//
// textBoxFilePath
//
textBoxFilePath.Location = new Point(144, 26);
textBoxFilePath.Name = "textBoxFilePath";
textBoxFilePath.ReadOnly = true;
textBoxFilePath.Size = new Size(165, 23);
textBoxFilePath.TabIndex = 8;
//
// buttonSelectFilePath
//
buttonSelectFilePath.Location = new Point(315, 27);
buttonSelectFilePath.Name = "buttonSelectFilePath";
buttonSelectFilePath.Size = new Size(22, 22);
buttonSelectFilePath.TabIndex = 9;
buttonSelectFilePath.Text = "..";
buttonSelectFilePath.UseVisualStyleBackColor = true;
buttonSelectFilePath.Click += buttonSelectFilePath_Click;
//
// comboBoxDoctor
//
comboBoxDoctor.DropDownStyle = ComboBoxStyle.DropDownList;
comboBoxDoctor.FormattingEnabled = true;
comboBoxDoctor.Location = new Point(144, 71);
comboBoxDoctor.Name = "comboBoxDoctor";
comboBoxDoctor.Size = new Size(193, 23);
comboBoxDoctor.TabIndex = 10;
//
// dateTimePickerDateEnd
//
dateTimePickerDateEnd.CustomFormat = "MMMM yyyy";
dateTimePickerDateEnd.Format = DateTimePickerFormat.Custom;
dateTimePickerDateEnd.Location = new Point(144, 163);
dateTimePickerDateEnd.Margin = new Padding(3, 2, 3, 2);
dateTimePickerDateEnd.Name = "dateTimePickerDateEnd";
dateTimePickerDateEnd.Size = new Size(193, 23);
dateTimePickerDateEnd.TabIndex = 23;
//
// dateTimePickerDateBegin
//
dateTimePickerDateBegin.CustomFormat = "MMMM yyyy";
dateTimePickerDateBegin.Format = DateTimePickerFormat.Custom;
dateTimePickerDateBegin.Location = new Point(144, 117);
dateTimePickerDateBegin.Margin = new Padding(3, 2, 3, 2);
dateTimePickerDateBegin.Name = "dateTimePickerDateBegin";
dateTimePickerDateBegin.Size = new Size(193, 23);
dateTimePickerDateBegin.TabIndex = 24;
//
// labelDateEnd
//
labelDateEnd.AutoSize = true;
labelDateEnd.Location = new Point(12, 169);
labelDateEnd.Name = "labelDateEnd";
labelDateEnd.Size = new Size(79, 15);
labelDateEnd.TabIndex = 28;
labelDateEnd.Text = "Месяц конца";
//
// labelDateStart
//
labelDateStart.AutoSize = true;
labelDateStart.Location = new Point(12, 123);
labelDateStart.Name = "labelDateStart";
labelDateStart.Size = new Size(85, 15);
labelDateStart.TabIndex = 27;
labelDateStart.Text = "Месяц начала";
//
// labelAthlete
//
labelAthlete.AutoSize = true;
labelAthlete.Location = new Point(12, 74);
labelAthlete.Name = "labelAthlete";
labelAthlete.Size = new Size(34, 15);
labelAthlete.TabIndex = 26;
labelAthlete.Text = "Врач";
//
// labelFilePath
//
labelFilePath.AutoSize = true;
labelFilePath.Location = new Point(12, 29);
labelFilePath.Name = "labelFilePath";
labelFilePath.Size = new Size(87, 15);
labelFilePath.TabIndex = 25;
labelFilePath.Text = "Путь до файла";
//
// FormDoctorPayReport
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(369, 295);
Controls.Add(labelDateEnd);
Controls.Add(labelDateStart);
Controls.Add(labelAthlete);
Controls.Add(labelFilePath);
Controls.Add(dateTimePickerDateBegin);
Controls.Add(dateTimePickerDateEnd);
Controls.Add(comboBoxDoctor);
Controls.Add(buttonSelectFilePath);
Controls.Add(textBoxFilePath);
Controls.Add(buttonBuild);
Name = "FormDoctorPayReport";
StartPosition = FormStartPosition.CenterScreen;
Text = "Отчет по работе врача";
ResumeLayout(false);
PerformLayout();
}
#endregion
private Button buttonBuild;
private TextBox textBoxFilePath;
private Button buttonSelectFilePath;
private ComboBox comboBoxDoctor;
private DateTimePicker dateTimePickerDateEnd;
private DateTimePicker dateTimePickerDateBegin;
private Label labelDateEnd;
private Label labelDateStart;
private Label labelAthlete;
private Label labelFilePath;
}
}

View File

@ -0,0 +1,92 @@
using ProjectPolyclinic.Reports;
using ProjectPolyclinic.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 ProjectPolyclinic.Forms
{
public partial class FormDoctorPayReport : Form
{
private readonly IUnityContainer _container;
public FormDoctorPayReport(IUnityContainer container, IDoctorRepository doctorRepository)
{
InitializeComponent();
_container = container ??
throw new ArgumentNullException(nameof(container));
comboBoxDoctor.DataSource = doctorRepository.ReadDoctors();
comboBoxDoctor.DisplayMember = "Last_Name";
comboBoxDoctor.ValueMember = "Id";
}
private void buttonBuild_Click(object sender, EventArgs e)
{
try
{
if (string.IsNullOrWhiteSpace(textBoxFilePath.Text))
{
throw new Exception("Отсутствует имя файла для отчета");
}
if (comboBoxDoctor.SelectedIndex < 0)
{
throw new Exception("Не выбран врач");
}
if (dateTimePickerDateEnd.Value <= dateTimePickerDateBegin.Value)
{
throw new Exception("Дата начала должна быть раньше даты окончания");
}
// Приведение дат к началу и концу месяца
var startDate = new DateTime(dateTimePickerDateBegin.Value.Year, dateTimePickerDateBegin.Value.Month, 1);
var endDate = new DateTime(dateTimePickerDateEnd.Value.Year, dateTimePickerDateEnd.Value.Month, 1).AddMonths(1).AddDays(-1);
if (_container.Resolve<TableReport>().CreateTable(
textBoxFilePath.Text,
(int)comboBoxDoctor.SelectedValue!,
startDate,
endDate))
{
MessageBox.Show("Документ сформирован", "Формирование документа",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("Возникли ошибки при формировании документа. Подробности в логах", "Формирование документа",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при создании отчета",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
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;
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -10,11 +10,13 @@
<ItemGroup>
<PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="DocumentFormat.OpenXml" Version="3.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Npgsql" Version="9.0.1" />
<PackageReference Include="PdfSharp.MigraDoc.Standard" Version="1.51.15" />
<PackageReference Include="Serilog" Version="4.1.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.4" />

View File

@ -0,0 +1,64 @@
using Microsoft.Extensions.Logging;
using ProjectPolyclinic.Reports;
using ProjectPolyclinic.Repositories;
public class ChartReport
{
private readonly IMedicalHistoryRepository _historyRepository;
private readonly ILogger<ChartReport> _logger;
public ChartReport(IMedicalHistoryRepository historyRepository, ILogger<ChartReport> logger)
{
_historyRepository = historyRepository ?? throw new ArgumentNullException(nameof(IMedicalHistoryRepository));
_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)
{
var medicalHistories = _historyRepository.ReadMedicalHistory(null, null, null, null);
var filteredHistories = medicalHistories
.Where(mh => mh.VisitDate.Date == dateTime.Date)
.Where(mh => mh.DrugMedHistory != null && mh.DrugMedHistory.Any())
.ToList();
var groupedData = filteredHistories
.GroupBy(
mh => mh.DoctorId,
(key, group) => new
{
DoctorId = key,
TotalDrugs = group
.SelectMany(mh => mh.DrugMedHistory)
.Sum(dmh => dmh.Count)
}
)
.ToList();
var result = groupedData
.Select(x => (x.DoctorId.ToString(), (double)x.TotalDrugs))
.ToList();
return result;
}
}

View File

@ -0,0 +1,97 @@
using Microsoft.Extensions.Logging;
using ProjectPolyclinic.Repositories;
namespace ProjectPolyclinic.Reports;
public class DocReport
{
private readonly IDoctorRepository _doctorRepository;
private readonly IPatientRepository _patientRepository;
private readonly IDrugRepository _drugRepository;
private readonly ILogger<DocReport> _logger;
public DocReport(IDoctorRepository doctorRepository,
IPatientRepository patientRepository, IDrugRepository drugRepository, ILogger<DocReport> logger)
{
_doctorRepository = doctorRepository ??
throw new ArgumentNullException(nameof(doctorRepository));
_patientRepository = patientRepository ??
throw new ArgumentNullException(nameof(patientRepository));
_drugRepository = drugRepository ??
throw new ArgumentNullException(nameof(drugRepository));
_logger = logger ??
throw new ArgumentNullException(nameof(logger));
}
public bool CreateDoc(string filePath, bool includeDoctors, bool includePatients, bool includeDrugs)
{
try
{
var worldBuilder = new WordBuilder(filePath).AddHeader("Документ со справочниками");
if (includeDoctors)
{
worldBuilder.AddParagraph("Врачи").AddTable([2400, 2400, 2000, 2000, 2000], GetDoctors());
}
if (includePatients)
{
worldBuilder.AddParagraph("Пациенты").AddTable([2400, 2400, 2400, 2400], GetPatients());
}
if (includeDrugs)
{
worldBuilder.AddParagraph("Лекарства").AddTable([2400, 2400, 2400], GetDrugs());
}
worldBuilder.Build();
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при формировании документа");
return false;
}
}
private List<string[]> GetDoctors()
{
return [
["Имя", "Фамилия", "Кабинет", "Специализация", "Уровень специализации"],
.. _doctorRepository
.ReadDoctors()
.Select(x => new string[]
{x.First_Name, x.Last_Name, x.Room.ToString(), x.Specialization.ToString(), x.SpecializationLevel.ToString()}),
];
}
private List<string[]> GetPatients()
{
return [
["Имя", "Фамилия", "Адресс", "Номер телефона"],
.. _patientRepository
.ReadPatient()
.Select(x => new string[]
{x.First_Name, x.Last_Name, x.Address, x.ContactNumber}),
];
}
private List<string[]> GetDrugs()
{
return [
["Список лекарств", "Грамовка", "Рецепт"],
.. _drugRepository
.ReadDrug()
.Select(x => new string[]
{x.drugsNames.ToString(), x.Grams.ToString(), x.Description}),
];
}
}

View File

@ -0,0 +1,327 @@
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
namespace ProjectPolyclinic.Reports;
public class ExcelBuilder
{
private readonly string _filePath;
private readonly SheetData _sheetData;
private readonly MergeCells _mergeCells;
private readonly Columns _columns;
private uint _rowIndex = 0;
public ExcelBuilder(string filePath)
{
if (string.IsNullOrWhiteSpace(filePath))
{
throw new ArgumentNullException(nameof(filePath));
}
if (File.Exists(filePath))
{
File.Delete(filePath);
}
_filePath = filePath;
_sheetData = new SheetData();
_mergeCells = new MergeCells();
_columns = new Columns();
_rowIndex = 1;
}
public ExcelBuilder AddHeader(string header, int startIndex, int count)
{
CreateCell(startIndex, _rowIndex, header, StyleIndex.BoldTextWithoutBorder);
for (int i = startIndex + 1; i < startIndex + count; ++i)
{
CreateCell(i, _rowIndex, "", StyleIndex.BoldTextWithoutBorder);
}
_mergeCells.Append(new MergeCell()
{
Reference = new StringValue($"{GetExcelColumnName(startIndex)}{_rowIndex}:{
GetExcelColumnName(startIndex + count - 1)}{_rowIndex}")});
_rowIndex++;
return this;
}
public ExcelBuilder AddParagraph(string text, int columnIndex)
{
CreateCell(columnIndex, _rowIndex++, text, StyleIndex.SimpleTextWithoutBorder);
return this;
}
public ExcelBuilder AddTable(int[] columnsWidths, List<string[]> data)
{
if (columnsWidths == null || columnsWidths.Length == 0)
{
throw new ArgumentNullException(nameof(columnsWidths));
}
if (data == null || data.Count == 0)
{
throw new ArgumentNullException(nameof(data));
}
if (data.Any(x => x.Length != columnsWidths.Length))
{
throw new InvalidOperationException("widths.Length != data.Length");
}
uint counter = 1;
int coef = 2;
_columns.Append(columnsWidths.Select(x => new Column
{
Min = counter,
Max = counter++,
Width = x * coef,
CustomWidth = true
}));
for (var j = 0; j < data.First().Length; ++j)
{
CreateCell(j, _rowIndex, data.First()[j], StyleIndex.BoldTextWithBorder);
}
_rowIndex++;
for (var i = 1; i < data.Count - 1; ++i)
{
for (var j = 0; j < data[i].Length; ++j)
{
CreateCell(j, _rowIndex, data[i][j], StyleIndex.SimpleTextWithBorder);
}
_rowIndex++;
}
for (var j = 0; j < data.Last().Length; ++j)
{
CreateCell(j, _rowIndex, data.Last()[j], StyleIndex.BoldTextWithBorder);
}
_rowIndex++;
return this;
}
public void Build()
{
using var spreadsheetDocument = SpreadsheetDocument.Create(_filePath,
SpreadsheetDocumentType.Workbook);
var workbookpart = spreadsheetDocument.AddWorkbookPart();
GenerateStyle(workbookpart);
workbookpart.Workbook = new Workbook();
var worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet();
if (_columns.HasChildren)
{
worksheetPart.Worksheet.Append(_columns);
}
worksheetPart.Worksheet.Append(_sheetData);
var sheets = spreadsheetDocument.WorkbookPart!.Workbook.AppendChild(new Sheets());
var sheet = new Sheet()
{
Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart),
SheetId = 1,
Name = "Лист 1"
};
sheets.Append(sheet);
if (_mergeCells.HasChildren)
{
worksheetPart.Worksheet.InsertAfter(_mergeCells,
worksheetPart.Worksheet.Elements<SheetData>().First());
}
}
private static void GenerateStyle(WorkbookPart workbookPart)
{
var workbookStylesPart = workbookPart.AddNewPart<WorkbookStylesPart>();
workbookStylesPart.Stylesheet = new Stylesheet();
var fonts = new Fonts() {Count = 2, KnownFonts = BooleanValue.FromBoolean(true)};
fonts.Append(new DocumentFormat.OpenXml.Spreadsheet.Font
{
FontSize = new FontSize() { Val = 11 },
FontName = new FontName() { Val = "Calibri" },
FontFamilyNumbering = new FontFamilyNumbering() { Val = 2 },
FontScheme = new FontScheme()
{
Val = new EnumValue<FontSchemeValues>(FontSchemeValues.Minor)
}
});
fonts.Append(new DocumentFormat.OpenXml.Spreadsheet.Font
{
FontSize = new FontSize() { Val = 11 },
FontName = new FontName() { Val = "Calibri" },
FontFamilyNumbering = new FontFamilyNumbering() { Val = 2 },
Bold = new Bold(),
FontScheme = new FontScheme()
{
Val = new EnumValue<FontSchemeValues>(FontSchemeValues.Minor)
}
});
workbookStylesPart.Stylesheet.Append(fonts);
var fills = new Fills() { Count = 1 };
fills.Append(new Fill
{
PatternFill = new PatternFill()
{
PatternType = new EnumValue<PatternValues>(PatternValues.None)
}
});
workbookStylesPart.Stylesheet.Append(fills);
var borders = new Borders() { Count = 2 };
borders.Append(new Border
{
LeftBorder = new LeftBorder(),
RightBorder = new RightBorder(),
TopBorder = new TopBorder(),
BottomBorder = new BottomBorder(),
DiagonalBorder = new DiagonalBorder()
});
borders.Append(new Border
{
LeftBorder = new LeftBorder { Style = BorderStyleValues.Thin },
RightBorder = new RightBorder { Style = BorderStyleValues.Thin },
TopBorder = new TopBorder { Style = BorderStyleValues.Thin },
BottomBorder = new BottomBorder { Style = BorderStyleValues.Thin },
DiagonalBorder = new DiagonalBorder()
});
workbookStylesPart.Stylesheet.Append(borders);
var cellFormats = new CellFormats() { Count = 4 };
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 0,
BorderId = 0,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Left,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 1,
BorderId = 1,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Left,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 0,
BorderId = 1,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Left,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 1,
BorderId = 0,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Left,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
workbookStylesPart.Stylesheet.Append(cellFormats);
}
private enum StyleIndex
{
SimpleTextWithoutBorder = 0,
BoldTextWithBorder = 1,
SimpleTextWithBorder = 2,
BoldTextWithoutBorder = 3
}
private void CreateCell(int columnIndex, uint rowIndex, string text, StyleIndex styleIndex)
{
var columnName = GetExcelColumnName(columnIndex);
var cellReference = columnName + rowIndex;
var row = _sheetData.Elements<Row>().FirstOrDefault(r => r.RowIndex! == rowIndex);
if (row == null)
{
row = new Row() { RowIndex = rowIndex };
_sheetData.Append(row);
}
var newCell = row.Elements<Cell>()
.FirstOrDefault(c => c.CellReference != null && c.CellReference.Value == columnName + rowIndex);
if (newCell == null)
{
Cell? refCell = null;
foreach (Cell cell in row.Elements<Cell>())
{
if (cell.CellReference?.Value != null &&
cell.CellReference.Value.Length == cellReference.Length)
{
if (string.Compare(cell.CellReference.Value, cellReference, true) > 0)
{
refCell = cell;
break;
}
}
}
newCell = new Cell() { CellReference = cellReference };
row.InsertBefore(newCell, refCell);
}
newCell.CellValue = new CellValue(text);
newCell.DataType = CellValues.String;
newCell.StyleIndex = (uint)styleIndex;
}
private static string GetExcelColumnName(int columnNumber)
{
columnNumber += 1;
int dividend = columnNumber;
string columnName = string.Empty;
int modulo;
while (dividend > 0)
{
modulo = (dividend - 1) % 26;
columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
dividend = (dividend - modulo) / 26;
}
return columnName;
}
}

View File

@ -0,0 +1,93 @@
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Shapes.Charts;
using MigraDoc.Rendering;
using System.Text;
namespace ProjectPolyclinic.Reports;
public 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 = 16;
}
}

View File

@ -0,0 +1,141 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using ProjectPolyclinic.Repositories;
namespace ProjectPolyclinic.Reports;
public class TableReport
{
private readonly IMedicalHistoryRepository _medicalHistoryRepository;
private readonly IDoctorPayRepository _doctorPayRepository;
private readonly ILogger<TableReport> _logger;
internal static readonly string[] item = ["Id врача", "Дата", "Количество пациентов", "Выплаты"];
public TableReport(IDoctorPayRepository doctorPayRepository,
IMedicalHistoryRepository medicalHistoryRepository, ILogger<TableReport> logger)
{
_doctorPayRepository = doctorPayRepository ??
throw new ArgumentNullException(nameof(IDoctorPayRepository));
_medicalHistoryRepository = medicalHistoryRepository ??
throw new ArgumentNullException(nameof(IMedicalHistoryRepository));
_logger = logger ??
throw new ArgumentNullException(nameof(logger));
}
public bool CreateTable(string filePath, int doctorId, DateTime startDate, DateTime endDate)
{
try
{
// Приведение дат к началу и концу месяцев
var startOfMonth = new DateTime(startDate.Year, startDate.Month, 1);
var endOfMonth = new DateTime(endDate.Year, endDate.Month, 1).AddMonths(1).AddDays(-1);
var excelBuilder = new ExcelBuilder(filePath)
.AddHeader("Сводка по оплате", 0, 3)
.AddParagraph($"За период с {startOfMonth:MM.yyyy} по {endOfMonth:MM.yyyy}", 0)
.AddParagraph($"Id врача: {doctorId}", 0)
.AddTable(new[] { 25, 25, 25 }, GetData(doctorId, startOfMonth, endOfMonth));
excelBuilder.AddParagraph("", 0);
excelBuilder
.AddHeader("Назначенные лекарства", 0, 2)
.AddTable(new[] { 25, 25 }, GetDrugData(doctorId, startOfMonth, endOfMonth));
excelBuilder.Build();
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при формировании документа");
return false;
}
}
private List<string[]> GetData(int doctorId, DateTime startOfMonth, DateTime endOfMonth)
{
var data = _doctorPayRepository
.ReadDoctorPayments()
.Where(x =>
{
var paymentMonth = DateTime.ParseExact(x.Month, "yyyy-MM", System.Globalization.CultureInfo.InvariantCulture);
return paymentMonth >= startOfMonth && paymentMonth <= endOfMonth && x.IdDoctor == doctorId;
})
.Select(x => new
{
Date = DateTime.ParseExact(x.Month, "yyyy-MM", System.Globalization.CultureInfo.InvariantCulture),
CountOfPatients = x.Count_Patient,
Payments = x.Payment
})
.OrderBy(x => x.Date);
var result = new List<string[]>
{
new[] { "Дата", "Количество пациентов", "Выплаты" }
}
.Union(data.Select(x => new string[]
{
x.Date.ToString("MMMM yyyy"),
x.CountOfPatients.ToString(),
x.Payments.ToString()
}))
.Union(new[]
{
new string[]
{
"Всего",
data.Sum(x => x.CountOfPatients).ToString(),
data.Sum(x => x.Payments).ToString()
}
})
.ToList();
return result;
}
private List<string[]> GetDrugData(int doctorId, DateTime startOfMonth, DateTime endOfMonth)
{
var medicalHistories = _medicalHistoryRepository
.ReadMedicalHistory(startOfMonth, endOfMonth, null, doctorId)
.Where(mh => mh.DoctorId == doctorId && mh.VisitDate >= startOfMonth && mh.VisitDate <= endOfMonth)
.ToList();
var result = new List<string[]>
{
new[] { "Дата", "Назначенные лекарства" }
};
var sortedDrugData = medicalHistories
.Where(mh => mh.DrugMedHistory != null && mh.DrugMedHistory.Any())
.SelectMany(mh => mh.DrugMedHistory.Select(drug => new
{
Date = mh.VisitDate,
Count = drug.Count
}))
.OrderBy(x => x.Date)
.ToList();
result.AddRange(sortedDrugData
.Select(item => new string[]
{
item.Date.ToString("dd.MM.yyyy"),
item.Count.ToString()
}));
var totalDrugs = sortedDrugData.Sum(x => x.Count);
result.Add(new[] { "Всего", totalDrugs.ToString() });
return result;
}
}

View File

@ -0,0 +1,105 @@
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml;
namespace ProjectPolyclinic.Reports;
public class WordBuilder
{
private readonly string _filePath;
private readonly Document _document;
private readonly Body _body;
public WordBuilder(string filePath)
{
if (string.IsNullOrWhiteSpace(filePath))
{
throw new ArgumentNullException(nameof(filePath));
}
if (File.Exists(filePath))
{
File.Delete(filePath);
}
_filePath = filePath;
_document = new Document();
_body = _document.AppendChild(new Body());
}
public WordBuilder AddHeader(string header)
{
var paragraph = _body.AppendChild(new Paragraph());
var run = paragraph.AppendChild(new Run());
var runProperties = run.AppendChild(new RunProperties());
runProperties.AppendChild(new Bold());
run.AppendChild(new Text(header));
return this;
}
public WordBuilder AddTable(int[] widths, List<string[]> data)
{
if (widths == null || widths.Length == 0)
{
throw new ArgumentNullException(nameof(widths));
}
if (data == null || data.Count == 0)
{
throw new ArgumentNullException(nameof(data));
}
if (data.Any(x => x.Length != widths.Length))
{
throw new InvalidOperationException("widths.Length != data.Length");
}
var table = new Table();
table.AppendChild(new TableProperties(
new TableBorders(
new TopBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new BottomBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new LeftBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new RightBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new InsideHorizontalBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new InsideVerticalBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 }
)
));
var tr = new TableRow();
for (var j = 0; j < widths.Length; ++j)
{
tr.Append(new TableCell(new TableCellProperties(new TableCellWidth()
{
Width = widths[j].ToString()
}),
new Paragraph(new Run(new RunProperties(new Bold()), new Text(data.First()[j])))));
}
table.Append(tr);
table.Append(data.Skip(1).Select(x => new TableRow(x.Select(y => new TableCell
(new Paragraph(new Run(new Text(y))))))));
_body.Append(table);
return this;
}
public WordBuilder AddParagraph(string text)
{
var paragraph = _body.AppendChild(new Paragraph());
var run = paragraph.AppendChild(new Run());
run.AppendChild(new Text(text));
return this;
}
public void Build()
{
using var wordDocument = WordprocessingDocument.Create(_filePath,
WordprocessingDocumentType.Document);
var mainPart = wordDocument.AddMainDocumentPart();
mainPart.Document = _document;
}
}

View File

@ -11,9 +11,8 @@ public interface IMedicalHistoryRepository
{
IEnumerable<MedicalHistory> ReadMedicalHistory(DateTime? dateForm = null, DateTime? dateTo = null, int? DoctorId = null, int? PatientId = null);
void CreateMedicalHistory(MedicalHistory medicalHistory);
void DeletemedicalHistory(int id);
}

View File

@ -53,8 +53,7 @@ public class DoctorRepository : IDoctorRepository
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
// Проверяем, существует ли запись
var existingDoctor = connection.QueryFirstOrDefault<Doctor>("SELECT * FROM Doctors WHERE id = @Id", new { doctor.Id });
if (existingDoctor == null)
{

View File

@ -76,7 +76,6 @@ public class MedicalHistoryRepository : IMedicalHistoryRepository
}
}
public void DeletemedicalHistory(int id)
{
_logger.LogInformation("Удаление объекта");
@ -93,20 +92,26 @@ public class MedicalHistoryRepository : IMedicalHistoryRepository
throw;
}
}
public IEnumerable<MedicalHistory> ReadMedicalHistory(DateTime? dateForm = null, DateTime? dateTo = null, int? PatientId = null, int? DoctorId = null)
public IEnumerable<MedicalHistory> ReadMedicalHistory(DateTime? dateForm = null, DateTime? dateTo = null, int? patientId = null, int? doctorId = null)
{
_logger.LogInformation("Получение всех объектов");
try
{
using var connection = new
NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = @"SELECT * FROM medical_history";
var visitings =
connection.Query<MedicalHistory>(querySelect);
_logger.LogDebug("Полученные объекты: {json}",
JsonConvert.SerializeObject(visitings));
return visitings;
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = @"
SELECT mh.*, dmh.drug_id AS DrugId, dmh.count AS Count
FROM medical_history mh
LEFT JOIN drug_med_history dmh ON mh.id = dmh.medical_history_id";
var tempHistories = connection.Query<TempMedicalHistory>(querySelect);
_logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(tempHistories));
return tempHistories.GroupBy(x => x.Id)
.Select(group => MedicalHistory.CreateEntity(
group.First(),
group.Select(d => DrugMedHistory.CreateEntity(0, d.DrugId, d.Id, d.Count))
)).ToList();
}
catch (Exception ex)
{

View File

@ -35,8 +35,6 @@ public class PatientRepository : IPatientRepository
{
var connection = new NpgsqlConnection(_connectionString.ConnectionString);
//var queryInsert = @"";
var queryInsert = @"
INSERT INTO patients (first_name, last_name, address, contactnumber)
VALUES (@First_Name, @Last_Name, @Address, @ContactNumber)";