full lab7

This commit is contained in:
DavidMakarov 2024-05-02 19:55:52 +04:00
parent b92c24b8d3
commit aab70b809b
43 changed files with 1644 additions and 203 deletions

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="SmtpClientHost" value="smtp.gmail.com" />
<add key="SmtpClientPort" value="587" />
<add key="PopHost" value="pop.gmail.com" />
<add key="PopPort" value="995" />
<add key="MailLogin" value="labworker83@gmail.com" />
<add key="MailPassword" value="wpxc drvx lhqb uqpe" />
</appSettings>
</configuration>

View File

@ -0,0 +1,68 @@
namespace FlowerShopView
{
partial class FormMail
{
/// <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()
{
dataGridView = new DataGridView();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout();
//
// DataGridView
//
dataGridView.AllowUserToAddRows = false;
dataGridView.AllowUserToDeleteRows = false;
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Dock = DockStyle.Fill;
dataGridView.Location = new Point(0, 0);
dataGridView.Margin = new Padding(3, 2, 3, 2);
dataGridView.Name = "DataGridView";
dataGridView.ReadOnly = true;
dataGridView.RowHeadersWidth = 51;
dataGridView.RowTemplate.Height = 29;
dataGridView.Size = new Size(1084, 456);
dataGridView.TabIndex = 0;
//
// FormMail
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(1084, 456);
Controls.Add(dataGridView);
Margin = new Padding(3, 2, 3, 2);
Name = "FormMail";
Text = "Письма";
Load += FormMail_Load;
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
ResumeLayout(false);
}
#endregion
private DataGridView dataGridView;
}
}

View File

@ -0,0 +1,47 @@
using FlowerShopContracts.BusinessLogicsContracts;
using Microsoft.Extensions.Logging;
namespace FlowerShopView
{
public partial class FormMail : Form
{
private readonly ILogger _logger;
private readonly IMessageInfoLogic _messageLogic;
public FormMail(ILogger<FormMail> Logger, IMessageInfoLogic MessageLogic)
{
InitializeComponent();
_logger = Logger;
_messageLogic = MessageLogic;
}
private void LoadData()
{
try
{
var List = _messageLogic.ReadList(null);
if (List != null)
{
dataGridView.DataSource = List;
dataGridView.Columns["MessageId"].Visible = false;
dataGridView.Columns["ClientId"].Visible = false;
dataGridView.Columns["Body"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
_logger.LogInformation("Загрузка почтовых собщений");
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка загрузки почтовых сообщений");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void FormMail_Load(object sender, EventArgs e)
{
LoadData();
}
}
}

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

@ -20,184 +20,192 @@
base.Dispose(disposing); base.Dispose(disposing);
} }
#region Windows Form Designer generated code #region Windows Form Designer generated code
/// <summary> /// <summary>
/// Required method for Designer support - do not modify /// Required method for Designer support - do not modify
/// the contents of this method with the code editor. /// the contents of this method with the code editor.
/// </summary> /// </summary>
private void InitializeComponent() private void InitializeComponent()
{ {
menuStrip1 = new MenuStrip(); menuStrip1 = new MenuStrip();
справочникиToolStripMenuItem = new ToolStripMenuItem(); справочникиToolStripMenuItem = new ToolStripMenuItem();
ЦветыToolStripMenuItem = new ToolStripMenuItem(); ЦветыToolStripMenuItem = new ToolStripMenuItem();
КомпонентыToolStripMenuItem = new ToolStripMenuItem(); КомпонентыToolStripMenuItem = new ToolStripMenuItem();
клиентыToolStripMenuItem = new ToolStripMenuItem(); клиентыToolStripMenuItem = new ToolStripMenuItem();
исполнителиToolStripMenuItem = new ToolStripMenuItem(); исполнителиToolStripMenuItem = new ToolStripMenuItem();
отчётыToolStripMenuItem = new ToolStripMenuItem(); отчётыToolStripMenuItem = new ToolStripMenuItem();
списокЦветковToolStripMenuItem = new ToolStripMenuItem(); списокЦветковToolStripMenuItem = new ToolStripMenuItem();
компонентыПоЦветамToolStripMenuItem = new ToolStripMenuItem(); компонентыПоЦветамToolStripMenuItem = new ToolStripMenuItem();
списокЗаказовToolStripMenuItem = new ToolStripMenuItem(); списокЗаказовToolStripMenuItem = new ToolStripMenuItem();
запускToolStripMenuItem = new ToolStripMenuItem(); запускToolStripMenuItem = new ToolStripMenuItem();
dataGridView = new DataGridView(); dataGridView = new DataGridView();
buttonCreateOrder = new Button(); buttonCreateOrder = new Button();
buttonIssuedOrder = new Button(); buttonIssuedOrder = new Button();
buttonRef = new Button(); buttonRef = new Button();
menuStrip1.SuspendLayout(); письмаToolStripMenuItem = new ToolStripMenuItem();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit(); menuStrip1.SuspendLayout();
SuspendLayout(); ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
// SuspendLayout();
// menuStrip1 //
// // menuStrip1
menuStrip1.ImageScalingSize = new Size(20, 20); //
menuStrip1.Items.AddRange(new ToolStripItem[] { справочникиToolStripMenuItem, отчётыToolStripMenuItem, запускToolStripMenuItem }); menuStrip1.ImageScalingSize = new Size(20, 20);
menuStrip1.Location = new Point(0, 0); menuStrip1.Items.AddRange(new ToolStripItem[] { справочникиToolStripMenuItem, отчётыToolStripMenuItem, запускToolStripMenuItem, письмаToolStripMenuItem });
menuStrip1.Name = "menuStrip1"; menuStrip1.Location = new Point(0, 0);
menuStrip1.Padding = new Padding(7, 3, 0, 3); menuStrip1.Name = "menuStrip1";
menuStrip1.Size = new Size(1102, 30); menuStrip1.Padding = new Padding(7, 3, 0, 3);
menuStrip1.TabIndex = 0; menuStrip1.Size = new Size(1102, 30);
menuStrip1.Text = "menuStrip1"; menuStrip1.TabIndex = 0;
// menuStrip1.Text = "menuStrip1";
// справочникиToolStripMenuItem //
// // справочникиToolStripMenuItem
справочникиToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { ЦветыToolStripMenuItem, КомпонентыToolStripMenuItem, клиентыToolStripMenuItem, исполнителиToolStripMenuItem }); //
справочникиToolStripMenuItem.Name = "справочникиToolStripMenuItem"; справочникиToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { ЦветыToolStripMenuItem, КомпонентыToolStripMenuItem, клиентыToolStripMenuItem, исполнителиToolStripMenuItem });
справочникиToolStripMenuItem.Size = new Size(117, 24); справочникиToolStripMenuItem.Name = "справочникиToolStripMenuItem";
справочникиToolStripMenuItem.Text = "Справочники"; справочникиToolStripMenuItem.Size = new Size(117, 24);
// справочникиToolStripMenuItem.Text = "Справочники";
// ЦветыToolStripMenuItem //
// // ЦветыToolStripMenuItem
ЦветыToolStripMenuItem.Name = "ЦветыToolStripMenuItem"; //
ЦветыToolStripMenuItem.Size = new Size(185, 26); ЦветыToolStripMenuItem.Name = "ЦветыToolStripMenuItem";
ЦветыToolStripMenuItem.Text = "Цветы"; ЦветыToolStripMenuItem.Size = new Size(224, 26);
ЦветыToolStripMenuItem.Click += ЦветыToolStripMenuItem_Click; ЦветыToolStripMenuItem.Text = "Цветы";
// ЦветыToolStripMenuItem.Click += ЦветыToolStripMenuItem_Click;
// КомпонентыToolStripMenuItem //
// // КомпонентыToolStripMenuItem
КомпонентыToolStripMenuItem.Name = "КомпонентыToolStripMenuItem"; //
КомпонентыToolStripMenuItem.Size = new Size(185, 26); КомпонентыToolStripMenuItem.Name = "КомпонентыToolStripMenuItem";
КомпонентыToolStripMenuItem.Text = "Компоненты"; КомпонентыToolStripMenuItem.Size = new Size(224, 26);
КомпонентыToolStripMenuItem.Click += КомпонентыToolStripMenuItem_Click; КомпонентыToolStripMenuItem.Text = "Компоненты";
// КомпонентыToolStripMenuItem.Click += КомпонентыToolStripMenuItem_Click;
// клиентыToolStripMenuItem //
// // клиентыToolStripMenuItem
клиентыToolStripMenuItem.Name = "клиентыToolStripMenuItem"; //
клиентыToolStripMenuItem.Size = new Size(185, 26); клиентыToolStripMenuItem.Name = "клиентыToolStripMenuItem";
клиентыToolStripMenuItem.Text = "Клиенты"; клиентыToolStripMenuItem.Size = new Size(224, 26);
клиентыToolStripMenuItem.Click += клиентыToolStripMenuItem_Click; клиентыToolStripMenuItem.Text = "Клиенты";
// клиентыToolStripMenuItem.Click += клиентыToolStripMenuItem_Click;
// исполнителиToolStripMenuItem //
// // исполнителиToolStripMenuItem
исполнителиToolStripMenuItem.Name = сполнителиToolStripMenuItem"; //
исполнителиToolStripMenuItem.Size = new Size(185, 26); исполнителиToolStripMenuItem.Name = сполнителиToolStripMenuItem";
исполнителиToolStripMenuItem.Text = "Исполнители"; исполнителиToolStripMenuItem.Size = new Size(224, 26);
исполнителиToolStripMenuItem.Click += исполнителиToolStripMenuItem_Click; исполнителиToolStripMenuItem.Text = "Исполнители";
// исполнителиToolStripMenuItem.Click += исполнителиToolStripMenuItem_Click;
// отчётыToolStripMenuItem //
// // отчётыToolStripMenuItem
отчётыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { списокЦветковToolStripMenuItem, компонентыПоЦветамToolStripMenuItem, списокЗаказовToolStripMenuItem }); //
отчётыToolStripMenuItem.Name = "отчётыToolStripMenuItem"; отчётыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { списокЦветковToolStripMenuItem, компонентыПоЦветамToolStripMenuItem, списокЗаказовToolStripMenuItem });
отчётыToolStripMenuItem.Size = new Size(73, 24); отчётыToolStripMenuItem.Name = "отчётыToolStripMenuItem";
отчётыToolStripMenuItem.Text = "Отчёты"; отчётыToolStripMenuItem.Size = new Size(73, 24);
// отчётыToolStripMenuItem.Text = "Отчёты";
// списокЦветковToolStripMenuItem //
// // списокЦветковToolStripMenuItem
списокЦветковToolStripMenuItem.Name = "списокЦветковToolStripMenuItem"; //
списокЦветковToolStripMenuItem.Size = new Size(258, 26); списокЦветковToolStripMenuItem.Name = "списокЦветковToolStripMenuItem";
списокЦветковToolStripMenuItem.Text = "Список цветков"; списокЦветковToolStripMenuItem.Size = new Size(258, 26);
списокЦветковToolStripMenuItem.Click += списокЦветковToolStripMenuItem_Click; списокЦветковToolStripMenuItem.Text = "Список цветков";
// списокЦветковToolStripMenuItem.Click += списокЦветковToolStripMenuItem_Click;
// компонентыПоЦветамToolStripMenuItem //
// // компонентыПоЦветамToolStripMenuItem
компонентыПоЦветамToolStripMenuItem.Name = омпонентыПоЦветамToolStripMenuItem"; //
компонентыПоЦветамToolStripMenuItem.Size = new Size(258, 26); компонентыПоЦветамToolStripMenuItem.Name = омпонентыПоЦветамToolStripMenuItem";
компонентыПоЦветамToolStripMenuItem.Text = "Компоненты по цветам"; компонентыПоЦветамToolStripMenuItem.Size = new Size(258, 26);
компонентыПоЦветамToolStripMenuItem.Click += компонентыПоЦветамToolStripMenuItem_Click; компонентыПоЦветамToolStripMenuItem.Text = "Компоненты по цветам";
// компонентыПоЦветамToolStripMenuItem.Click += компонентыПоЦветамToolStripMenuItem_Click;
// списокЗаказовToolStripMenuItem //
// // списокЗаказовToolStripMenuItem
списокЗаказовToolStripMenuItem.Name = "списокЗаказовToolStripMenuItem"; //
списокЗаказовToolStripMenuItem.Size = new Size(258, 26); списокЗаказовToolStripMenuItem.Name = "списокЗаказовToolStripMenuItem";
списокЗаказовToolStripMenuItem.Text = "Список заказов"; списокЗаказовToolStripMenuItem.Size = new Size(258, 26);
списокЗаказовToolStripMenuItem.Click += списокЗаказовToolStripMenuItem_Click; списокЗаказовToolStripMenuItem.Text = "Список заказов";
// списокЗаказовToolStripMenuItem.Click += списокЗаказовToolStripMenuItem_Click;
// запускToolStripMenuItem //
// // запускToolStripMenuItem
запускToolStripMenuItem.Name = апускToolStripMenuItem"; //
запускToolStripMenuItem.Size = new Size(114, 24); запускToolStripMenuItem.Name = апускToolStripMenuItem";
запускToolStripMenuItem.Text = "Запуск работ"; запускToolStripMenuItem.Size = new Size(114, 24);
запускToolStripMenuItem.Click += запускToolStripMenuItem_Click; запускToolStripMenuItem.Text = "Запуск работ";
// запускToolStripMenuItem.Click += запускToolStripMenuItem_Click;
// dataGridView //
// // dataGridView
dataGridView.BackgroundColor = Color.White; //
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; dataGridView.BackgroundColor = Color.White;
dataGridView.Location = new Point(14, 36); dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView.Margin = new Padding(3, 4, 3, 4); dataGridView.Location = new Point(14, 36);
dataGridView.Name = "dataGridView"; dataGridView.Margin = new Padding(3, 4, 3, 4);
dataGridView.RowHeadersWidth = 51; dataGridView.Name = "dataGridView";
dataGridView.RowTemplate.Height = 25; dataGridView.RowHeadersWidth = 51;
dataGridView.Size = new Size(845, 548); dataGridView.RowTemplate.Height = 25;
dataGridView.TabIndex = 1; dataGridView.Size = new Size(845, 548);
// dataGridView.TabIndex = 1;
// buttonCreateOrder //
// // buttonCreateOrder
buttonCreateOrder.Location = new Point(886, 73); //
buttonCreateOrder.Margin = new Padding(3, 4, 3, 4); buttonCreateOrder.Location = new Point(886, 73);
buttonCreateOrder.Name = "buttonCreateOrder"; buttonCreateOrder.Margin = new Padding(3, 4, 3, 4);
buttonCreateOrder.Size = new Size(181, 43); buttonCreateOrder.Name = "buttonCreateOrder";
buttonCreateOrder.TabIndex = 2; buttonCreateOrder.Size = new Size(181, 43);
buttonCreateOrder.Text = "Создать заказ"; buttonCreateOrder.TabIndex = 2;
buttonCreateOrder.UseVisualStyleBackColor = true; buttonCreateOrder.Text = "Создать заказ";
buttonCreateOrder.Click += ButtonCreateOrder_Click; buttonCreateOrder.UseVisualStyleBackColor = true;
// buttonCreateOrder.Click += ButtonCreateOrder_Click;
// buttonIssuedOrder //
// // buttonIssuedOrder
buttonIssuedOrder.Location = new Point(886, 147); //
buttonIssuedOrder.Margin = new Padding(3, 4, 3, 4); buttonIssuedOrder.Location = new Point(886, 147);
buttonIssuedOrder.Name = "buttonIssuedOrder"; buttonIssuedOrder.Margin = new Padding(3, 4, 3, 4);
buttonIssuedOrder.Size = new Size(181, 43); buttonIssuedOrder.Name = "buttonIssuedOrder";
buttonIssuedOrder.TabIndex = 3; buttonIssuedOrder.Size = new Size(181, 43);
buttonIssuedOrder.Text = "Заказ выдан"; buttonIssuedOrder.TabIndex = 3;
buttonIssuedOrder.UseVisualStyleBackColor = true; buttonIssuedOrder.Text = "Заказ выдан";
buttonIssuedOrder.Click += ButtonIssuedOrder_Click; buttonIssuedOrder.UseVisualStyleBackColor = true;
// buttonIssuedOrder.Click += ButtonIssuedOrder_Click;
// buttonRef //
// // buttonRef
buttonRef.Location = new Point(886, 220); //
buttonRef.Margin = new Padding(3, 4, 3, 4); buttonRef.Location = new Point(886, 220);
buttonRef.Name = "buttonRef"; buttonRef.Margin = new Padding(3, 4, 3, 4);
buttonRef.Size = new Size(181, 43); buttonRef.Name = "buttonRef";
buttonRef.TabIndex = 6; buttonRef.Size = new Size(181, 43);
buttonRef.Text = "Обновить список"; buttonRef.TabIndex = 6;
buttonRef.UseVisualStyleBackColor = true; buttonRef.Text = "Обновить список";
buttonRef.Click += ButtonRef_Click; buttonRef.UseVisualStyleBackColor = true;
// buttonRef.Click += ButtonRef_Click;
// FormMain //
// // письмаToolStripMenuItem
AutoScaleDimensions = new SizeF(8F, 20F); //
AutoScaleMode = AutoScaleMode.Font; письмаToolStripMenuItem.Name = "письмаToolStripMenuItem";
ClientSize = new Size(1102, 600); письмаToolStripMenuItem.Size = new Size(77, 24);
Controls.Add(buttonRef); письмаToolStripMenuItem.Text = "Письма";
Controls.Add(buttonIssuedOrder); письмаToolStripMenuItem.Click += письмаToolStripMenuItem_Click;
Controls.Add(buttonCreateOrder); //
Controls.Add(dataGridView); // FormMain
Controls.Add(menuStrip1); //
MainMenuStrip = menuStrip1; AutoScaleDimensions = new SizeF(8F, 20F);
Margin = new Padding(3, 4, 3, 4); AutoScaleMode = AutoScaleMode.Font;
Name = "FormMain"; ClientSize = new Size(1102, 600);
Text = "Цветочный магазин"; Controls.Add(buttonRef);
Load += FormMain_Load; Controls.Add(buttonIssuedOrder);
menuStrip1.ResumeLayout(false); Controls.Add(buttonCreateOrder);
menuStrip1.PerformLayout(); Controls.Add(dataGridView);
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit(); Controls.Add(menuStrip1);
ResumeLayout(false); MainMenuStrip = menuStrip1;
PerformLayout(); Margin = new Padding(3, 4, 3, 4);
} Name = "FormMain";
Text = "Цветочный магазин";
Load += FormMain_Load;
menuStrip1.ResumeLayout(false);
menuStrip1.PerformLayout();
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion #endregion
private MenuStrip menuStrip1; private MenuStrip menuStrip1;
private ToolStripMenuItem справочникиToolStripMenuItem; private ToolStripMenuItem справочникиToolStripMenuItem;
private ToolStripMenuItem ЦветыToolStripMenuItem; private ToolStripMenuItem ЦветыToolStripMenuItem;
private ToolStripMenuItem КомпонентыToolStripMenuItem; private ToolStripMenuItem КомпонентыToolStripMenuItem;
@ -212,5 +220,6 @@
private ToolStripMenuItem клиентыToolStripMenuItem; private ToolStripMenuItem клиентыToolStripMenuItem;
private ToolStripMenuItem исполнителиToolStripMenuItem; private ToolStripMenuItem исполнителиToolStripMenuItem;
private ToolStripMenuItem запускToolStripMenuItem; private ToolStripMenuItem запускToolStripMenuItem;
private ToolStripMenuItem письмаToolStripMenuItem;
} }
} }

View File

@ -34,6 +34,7 @@ namespace FlowerShopView
dataGridView.DataSource = list; dataGridView.DataSource = list;
dataGridView.Columns["FlowerId"].Visible = false; dataGridView.Columns["FlowerId"].Visible = false;
dataGridView.Columns["ClientId"].Visible = false; dataGridView.Columns["ClientId"].Visible = false;
dataGridView.Columns["ClientEmail"].Visible = false;
dataGridView.Columns["ImplementerId"].Visible = false; dataGridView.Columns["ImplementerId"].Visible = false;
} }
} }
@ -150,7 +151,17 @@ namespace FlowerShopView
private void запускToolStripMenuItem_Click(object sender, EventArgs e) private void запускToolStripMenuItem_Click(object sender, EventArgs e)
{ {
_workProcess.DoWork((Program.ServiceProvider?.GetService(typeof(IImplementerLogic)) as IImplementerLogic)!, _orderLogic); _workProcess.DoWork((Program.ServiceProvider?.GetService(typeof(IImplementerLogic)) as IImplementerLogic)!, _orderLogic);
MessageBox.Show("Процесс обработки запущен", "Сообщение",MessageBoxButtons.OK, MessageBoxIcon.Information); MessageBox.Show("Процесс обработки запущен", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void письмаToolStripMenuItem_Click(object sender, EventArgs e)
{
var Service = Program.ServiceProvider?.GetService(typeof(FormMail));
if (Service is FormMail Form)
{
Form.ShowDialog();
}
} }
} }
} }

View File

@ -1,4 +1,4 @@
using FlowerShopBusinessLogic.BusinessLogics; using FlowerShopBusinessLogic.BusinessLogics;
using FlowerShopBusinessLogic.OfficePackage.Implements; using FlowerShopBusinessLogic.OfficePackage.Implements;
using FlowerShopBusinessLogic.OfficePackage; using FlowerShopBusinessLogic.OfficePackage;
using FlowerShopContracts.BusinessLogicsContracts; using FlowerShopContracts.BusinessLogicsContracts;
@ -7,6 +7,8 @@ using FlowerShopDatabaseImplement.Implements;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging; using NLog.Extensions.Logging;
using FlowerShopBusinessLogic.MailWorker;
using FlowerShopContracts.BindingModels;
namespace FlowerShopView namespace FlowerShopView
{ {
@ -26,6 +28,28 @@ namespace FlowerShopView
var services = new ServiceCollection(); var services = new ServiceCollection();
ConfigureServices(services); ConfigureServices(services);
_serviceProvider = services.BuildServiceProvider(); _serviceProvider = services.BuildServiceProvider();
try
{
var MailSender = _serviceProvider.GetService<AbstractMailWorker>();
MailSender?.MailConfig(new MailConfigBindingModel
{
MailLogin = System.Configuration.ConfigurationManager.AppSettings["MailLogin"] ?? string.Empty,
MailPassword = System.Configuration.ConfigurationManager.AppSettings["MailPassword"] ?? string.Empty,
SmtpClientHost = System.Configuration.ConfigurationManager.AppSettings["SmtpClientHost"] ?? string.Empty,
SmtpClientPort = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["SmtpClientPort"]),
PopHost = System.Configuration.ConfigurationManager.AppSettings["PopHost"] ?? string.Empty,
PopPort = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["PopPort"])
});
var Timer = new System.Threading.Timer(new TimerCallback(MailCheck!), null, 0, 100000);
}
catch (Exception ex)
{
var Logger = _serviceProvider.GetService<ILogger>();
Logger?.LogError(ex, "Ошибка загрузки писем");
}
Application.Run(_serviceProvider.GetRequiredService<FormMain>()); Application.Run(_serviceProvider.GetRequiredService<FormMain>());
} }
private static void ConfigureServices(ServiceCollection services) private static void ConfigureServices(ServiceCollection services)
@ -40,18 +64,21 @@ namespace FlowerShopView
services.AddTransient<IFlowerStorage, FlowerStorage>(); services.AddTransient<IFlowerStorage, FlowerStorage>();
services.AddTransient<IClientStorage, ClientStorage>(); services.AddTransient<IClientStorage, ClientStorage>();
services.AddTransient<IImplementerStorage, ImplementerStorage>(); services.AddTransient<IImplementerStorage, ImplementerStorage>();
services.AddTransient<IMessageInfoStorage, MessageInfoStorage>();
services.AddTransient<IComponentLogic, ComponentLogic>(); services.AddTransient<IComponentLogic, ComponentLogic>();
services.AddTransient<IOrderLogic, OrderLogic>(); services.AddTransient<IOrderLogic, OrderLogic>();
services.AddTransient<IFlowerLogic, FlowerLogic>(); services.AddTransient<IFlowerLogic, FlowerLogic>();
services.AddTransient<IReportLogic, ReportLogic>(); services.AddTransient<IReportLogic, ReportLogic>();
services.AddTransient<IClientLogic, ClientLogic>(); services.AddTransient<IClientLogic, ClientLogic>();
services.AddTransient<IImplementerLogic, ImplementerLogic>(); services.AddTransient<IImplementerLogic, ImplementerLogic>();
services.AddTransient<IWorkProcess, WorkModeling>(); services.AddTransient<IWorkProcess, WorkModeling>();
services.AddTransient<IMessageInfoLogic, MessageInfoLogic>();
services.AddTransient<AbstractSaveToExcel, SaveToExcel>(); services.AddTransient<AbstractSaveToExcel, SaveToExcel>();
services.AddTransient<AbstractSaveToPdf, SaveToPdf>(); services.AddTransient<AbstractSaveToPdf, SaveToPdf>();
services.AddTransient<AbstractSaveToWord, SaveToWord>(); services.AddTransient<AbstractSaveToWord, SaveToWord>();
services.AddSingleton<AbstractMailWorker, MailKitWorker>();
services.AddTransient<FormMain>(); services.AddTransient<FormMain>();
services.AddTransient<FormComponent>(); services.AddTransient<FormComponent>();
@ -65,6 +92,8 @@ namespace FlowerShopView
services.AddTransient<FormClients>(); services.AddTransient<FormClients>();
services.AddTransient<FormImplementer>(); services.AddTransient<FormImplementer>();
services.AddTransient<FormImplementers>(); services.AddTransient<FormImplementers>();
} services.AddTransient<FormMail>();
}
private static void MailCheck(object obj) => ServiceProvider?.GetService<AbstractMailWorker>()?.MailCheck();
} }
} }

View File

@ -1,9 +1,11 @@
using FlowerShopContracts.BindingModels; using DocumentFormat.OpenXml.EMMA;
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.BusinessLogicsContracts; using FlowerShopContracts.BusinessLogicsContracts;
using FlowerShopContracts.SearchModels; using FlowerShopContracts.SearchModels;
using FlowerShopContracts.StoragesContracts; using FlowerShopContracts.StoragesContracts;
using FlowerShopContracts.ViewModels; using FlowerShopContracts.ViewModels;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Text.RegularExpressions;
namespace FlowerShopBusinessLogic.BusinessLogics namespace FlowerShopBusinessLogic.BusinessLogics
{ {
@ -92,14 +94,13 @@ namespace FlowerShopBusinessLogic.BusinessLogics
throw new ArgumentNullException("Нет ФИО пользователя", throw new ArgumentNullException("Нет ФИО пользователя",
nameof(model.ClientFIO)); nameof(model.ClientFIO));
} }
if (string.IsNullOrEmpty(model.Email)) if (string.IsNullOrEmpty(model.Email) || !Regex.IsMatch(model.Email, @"^[a-z0-9._%+-]+\@([a-z0-9-]+\.)+[a-z]{2,4}$"))
{ {
throw new ArgumentNullException("Нет логина (почты) пользователя", throw new ArgumentException("Почта не соответствует требованиям", nameof(model.Email));
nameof(model.Email));
} }
if (string.IsNullOrEmpty(model.Password)) if (string.IsNullOrEmpty(model.Password) || !Regex.IsMatch(model.Password, @"^(?=.*[A-Za-z])(?=.*\d)(?=.*[^A-Za-z0-9\n]).{10,50}$"))
{ {
throw new ArgumentNullException("Нет пароля пользователя", nameof(model.Password)); throw new ArgumentNullException("Пароль не соответствует требованиям", nameof(model.Password));
} }
_logger.LogInformation("Client. ClientFIO:{ClientFIO}. Password:{ Password}. Email:{ Email}. Id: { Id}", model.ClientFIO, model.Password, model.Email, model.Id); _logger.LogInformation("Client. ClientFIO:{ClientFIO}. Password:{ Password}. Email:{ Email}. Id: { Id}", model.ClientFIO, model.Password, model.Email, model.Id);
var element = _clientStorage.GetElement(new ClientSearchModel var element = _clientStorage.GetElement(new ClientSearchModel

View File

@ -0,0 +1,85 @@
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.BusinessLogicsContracts;
using FlowerShopContracts.SearchModels;
using FlowerShopContracts.StoragesContracts;
using FlowerShopContracts.ViewModels;
using Microsoft.Extensions.Logging;
namespace FlowerShopBusinessLogic.BusinessLogics
{
public class MessageInfoLogic : IMessageInfoLogic
{
private readonly ILogger _logger;
private readonly IMessageInfoStorage _messageInfoStorage;
private readonly IClientStorage _clientStorage;
public MessageInfoLogic(ILogger<MessageInfoLogic> logger, IMessageInfoStorage messageInfoStorage, IClientStorage clientStorage)
{
_logger = logger;
_messageInfoStorage = messageInfoStorage;
_clientStorage = clientStorage;
}
public List<MessageInfoViewModel>? ReadList(MessageInfoSearchModel? model)
{
_logger.LogDebug("ReadList. MessageId: {MessageId}, ClientId: {ClientId}", model?.MessageId, model?.ClientId);
var result = model == null ? _messageInfoStorage.GetFullList() : _messageInfoStorage.GetFilteredList(model);
_logger.LogDebug("ReadList result. Count: {Count}", result.Count);
return result;
}
public bool Create(MessageInfoBindingModel model)
{
CheckModel(model);
if (_messageInfoStorage.Insert(model) == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
return true;
}
private void CheckModel(MessageInfoBindingModel model, bool withParams = true)
{
if (model == null)
throw new ArgumentNullException(nameof(model));
if (!withParams)
return;
if (string.IsNullOrEmpty(model.MessageId))
throw new ArgumentNullException("Не указан id сообщения", nameof(model.MessageId));
if (string.IsNullOrEmpty(model.SenderName))
throw new ArgumentNullException("Не указао почта", nameof(model.SenderName));
if (string.IsNullOrEmpty(model.Subject))
throw new ArgumentNullException("Не указана тема", nameof(model.Subject));
if (string.IsNullOrEmpty(model.Body))
throw new ArgumentNullException("Не указан текст сообщения", nameof(model.Subject));
_logger.LogInformation("MessageInfo. MessageId: {MessageId}. SenderName: {SenderName}. Subject: {Subject}. Body: {Body}",
model.MessageId, model.SenderName, model.Subject, model.Body);
var Element = _clientStorage.GetElement(new ClientSearchModel
{
Email = model.SenderName
});
if (Element == null)
{
_logger.LogWarning("Не удалось найти клиента, отправившего письмо с адреса {Email}", model.SenderName);
}
else
{
model.ClientId = Element.Id;
}
}
}
}

View File

@ -1,4 +1,5 @@
using FlowerShopContracts.BindingModels; using FlowerShopBusinessLogic.MailWorker;
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.BusinessLogicsContracts; using FlowerShopContracts.BusinessLogicsContracts;
using FlowerShopContracts.SearchModels; using FlowerShopContracts.SearchModels;
using FlowerShopContracts.StoragesContracts; using FlowerShopContracts.StoragesContracts;
@ -12,11 +13,13 @@ namespace FlowerShopBusinessLogic.BusinessLogics
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IOrderStorage _orderStorage; private readonly IOrderStorage _orderStorage;
static readonly object _locker = new object(); private readonly AbstractMailWorker _mailLogic;
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage) static readonly object _locker = new object();
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage, AbstractMailWorker mailLogic)
{ {
_logger = logger; _logger = logger;
_orderStorage = orderStorage; _orderStorage = orderStorage;
_mailLogic = mailLogic;
} }
public List<OrderViewModel>? ReadList(OrderSearchModel? model) public List<OrderViewModel>? ReadList(OrderSearchModel? model)
{ {
@ -57,14 +60,22 @@ namespace FlowerShopBusinessLogic.BusinessLogics
if (model.Status != OrderStatus.Неизвестен) if (model.Status != OrderStatus.Неизвестен)
return false; return false;
model.Status = OrderStatus.Принят; model.Status = OrderStatus.Принят;
if (_orderStorage.Insert(model) == null) var createdOrder = _orderStorage.Insert(model);
if (createdOrder == null)
{ {
model.Status = OrderStatus.Неизвестен; model.Status = OrderStatus.Неизвестен;
_logger.LogWarning("Insert operation failed"); _logger.LogWarning("Insert operation failed");
return false; return false;
} }
return true; Task.Run(() => _mailLogic.MailSendAsync(new MailSendInfoBindingModel
} {
MailAddress = createdOrder.ClientEmail,
Subject = $"Изменение статуса заказа номер {createdOrder.Id}",
Text = $"Ваш заказ №{createdOrder.Id} на покупку цветов {createdOrder.FlowerName} от {createdOrder.DateCreate} на сумму {createdOrder.Sum} принят."
}));
return true;
}
public bool TakeOrderInWork(OrderBindingModel model) public bool TakeOrderInWork(OrderBindingModel model)
{ {
lock (_locker) lock (_locker)
@ -120,7 +131,14 @@ namespace FlowerShopBusinessLogic.BusinessLogics
_logger.LogWarning("Changing status operation faled"); _logger.LogWarning("Changing status operation faled");
return false; return false;
} }
return true; string dateInfo = model.DateImplement.HasValue ? $"Дата выполнения: {model.DateImplement}" : "";
Task.Run(() => _mailLogic.MailSendAsync(new MailSendInfoBindingModel
{
MailAddress = element.ClientEmail,
Subject = $"Изменение статуса заказа номер {element.Id}",
Text = $"Ваш заказ №{element.Id} на покупку цветов {element.FlowerName} от {element.DateCreate} на сумму {element.Sum}. Статус изменен на {orderStatus}. {dateInfo}"
}));
return true;
} }
private void CheckModel(OrderBindingModel model, bool withParams = true) private void CheckModel(OrderBindingModel model, bool withParams = true)
{ {

View File

@ -8,6 +8,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="3.0.2" /> <PackageReference Include="DocumentFormat.OpenXml" Version="3.0.2" />
<PackageReference Include="MailKit" Version="4.5.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="MigraDocCore.DocumentObjectModel" Version="1.3.63" /> <PackageReference Include="MigraDocCore.DocumentObjectModel" Version="1.3.63" />
<PackageReference Include="MigraDocCore.Rendering" Version="1.3.63" /> <PackageReference Include="MigraDocCore.Rendering" Version="1.3.63" />

View File

@ -0,0 +1,76 @@
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.BusinessLogicsContracts;
using Microsoft.Extensions.Logging;
namespace FlowerShopBusinessLogic.MailWorker
{
public abstract class AbstractMailWorker
{
protected string _mailLogin = string.Empty;
protected string _mailPassword = string.Empty;
protected string _smtpClientHost = string.Empty;
protected int _smtpClientPort;
protected string _popHost = string.Empty;
protected int _popPort;
private readonly IMessageInfoLogic _messageInfoLogic;
private readonly ILogger _logger;
public AbstractMailWorker(ILogger<AbstractMailWorker> logger, IMessageInfoLogic messageInfoLogic)
{
_logger = logger;
_messageInfoLogic = messageInfoLogic;
}
public void MailConfig(MailConfigBindingModel config)
{
_mailLogin = config.MailLogin;
_mailPassword = config.MailPassword;
_smtpClientHost = config.SmtpClientHost;
_smtpClientPort = config.SmtpClientPort;
_popHost = config.PopHost;
_popPort = config.PopPort;
_logger.LogDebug("Config: {login}, {password}, {clientHost}, { clientPort}, { popHost}, { popPort} ", _mailLogin, _mailPassword, _smtpClientHost, _smtpClientPort, _popHost, _popPort);
}
public async void MailSendAsync(MailSendInfoBindingModel info)
{
if (string.IsNullOrEmpty(_mailLogin) ||
string.IsNullOrEmpty(_mailPassword))
{
return;
}
if (string.IsNullOrEmpty(_smtpClientHost) || _smtpClientPort == 0)
{
return;
}
if (string.IsNullOrEmpty(info.MailAddress) ||
string.IsNullOrEmpty(info.Subject) || string.IsNullOrEmpty(info.Text))
{
return;
}
_logger.LogDebug("Send Mail: {To}, {Subject}", info.MailAddress,
info.Subject);
await SendMailAsync(info);
}
public async void MailCheck()
{
if (string.IsNullOrEmpty(_mailLogin) || string.IsNullOrEmpty(_mailPassword))
{
return;
}
if (string.IsNullOrEmpty(_popHost) || _popPort == 0)
{
return;
}
if (_messageInfoLogic == null)
{
return;
}
var list = await ReceiveMailAsync();
_logger.LogDebug("Check Mail: {Count} new mails", list.Count);
foreach (var mail in list)
{
_messageInfoLogic.Create(mail);
}
}
protected abstract Task SendMailAsync(MailSendInfoBindingModel info);
protected abstract Task<List<MessageInfoBindingModel>> ReceiveMailAsync();
}
}

View File

@ -0,0 +1,74 @@
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.BusinessLogicsContracts;
using Microsoft.Extensions.Logging;
using MailKit.Net.Pop3;
using MailKit.Security;
using System.Net;
using System.Net.Mail;
using System.Text;
namespace FlowerShopBusinessLogic.MailWorker
{
public class MailKitWorker : AbstractMailWorker
{
public MailKitWorker(ILogger<MailKitWorker> logger, IMessageInfoLogic messageInfoLogic) : base(logger, messageInfoLogic) { }
protected override async Task SendMailAsync(MailSendInfoBindingModel info)
{
using var objMailMessage = new MailMessage();
using var objSmtpClient = new SmtpClient(_smtpClientHost, _smtpClientPort);
try
{
objMailMessage.From = new MailAddress(_mailLogin);
objMailMessage.To.Add(new MailAddress(info.MailAddress));
objMailMessage.Subject = info.Subject;
objMailMessage.Body = info.Text;
objMailMessage.SubjectEncoding = Encoding.UTF8;
objMailMessage.BodyEncoding = Encoding.UTF8;
objSmtpClient.UseDefaultCredentials = false;
objSmtpClient.EnableSsl = true;
objSmtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
objSmtpClient.Credentials = new NetworkCredential(_mailLogin, _mailPassword);
await Task.Run(() => objSmtpClient.Send(objMailMessage));
}
catch (Exception)
{
throw;
}
}
protected override async Task<List<MessageInfoBindingModel>> ReceiveMailAsync()
{
var list = new List<MessageInfoBindingModel>();
using var client = new Pop3Client();
await Task.Run(() =>
{
try
{
client.Connect(_popHost, _popPort, SecureSocketOptions.SslOnConnect);
client.Authenticate(_mailLogin, _mailPassword);
for (int i = 0; i < client.Count; i++)
{
var message = client.GetMessage(i);
foreach (var mail in message.From.Mailboxes)
{
list.Add(new MessageInfoBindingModel
{
DateDelivery = message.Date.DateTime,
MessageId = message.MessageId,
SenderName = mail.Address,
Subject = message.Subject,
Body = message.TextBody
});
}
}
}
catch (AuthenticationException) { }
finally
{
client.Disconnect(true);
}
});
return list;
}
}
}

View File

@ -2,6 +2,7 @@
using FlowerShopContracts.BindingModels; using FlowerShopContracts.BindingModels;
using FlowerShopContracts.ViewModels; using FlowerShopContracts.ViewModels;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.Diagnostics; using System.Diagnostics;
namespace FlowerShopClientApp.Controllers namespace FlowerShopClientApp.Controllers
@ -77,8 +78,7 @@ namespace FlowerShopClientApp.Controllers
{ {
throw new Exception("Введите логин и пароль"); throw new Exception("Введите логин и пароль");
} }
APIClient.Client = APIClient.Client = APIClient.GetRequest<ClientViewModel>($"api/Client/Login?login={login}&password={password}");
APIClient.GetRequest<ClientViewModel>($"api/Client/Login?login={login}&password={password}");
if (APIClient.Client == null) if (APIClient.Client == null)
{ {
throw new Exception("Неверный логин/пароль"); throw new Exception("Неверный логин/пароль");
@ -108,6 +108,16 @@ namespace FlowerShopClientApp.Controllers
return; return;
} }
[HttpGet] [HttpGet]
public IActionResult Mails()
{
if (APIClient.Client == null)
{
return Redirect("~/Home/Enter");
}
return
View(APIClient.GetRequest<List<MessageInfoViewModel>>($"api/client/getmessages?clientId={APIClient.Client.Id}"));
}
[HttpGet]
public IActionResult Create() public IActionResult Create()
{ {
ViewBag.Flowers = APIClient.GetRequest<List<FlowerViewModel>>("api/Main/GetFlowerList"); ViewBag.Flowers = APIClient.GetRequest<List<FlowerViewModel>>("api/Main/GetFlowerList");

View File

@ -0,0 +1,51 @@
@using FlowerShopContracts.ViewModels
@model List<MessageInfoViewModel>
@{
ViewData["Title"] = "Mails";
}
<div class="text-center">
<h1 class="display-4">Заказы</h1>
</div>
<div class="text-center">
@{
if (Model == null)
{
<h3 class="display-4">Авторизируйтесь</h3>
return;
}
<table class="table">
<thead>
<tr>
<th>
Дата письма
</th>
<th>
Заголовок
</th>
<th>
Текст
</th>
</tr>
</thead>
<tbody>
@foreach (var Item in Model)
{
<tr>
<td>
@Html.DisplayFor(ModelItem => Item.DateDelivery)
</td>
<td>
@Html.DisplayFor(ModelItem => Item.Subject)
</td>
<td>
@Html.DisplayFor(ModelItem => Item.Body)
</td>
</tr>
}
</tbody>
</table>
}
</div>

View File

@ -26,6 +26,9 @@
<li class="nav-item"> <li class="nav-item">
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Privacy">Личные данные</a> <a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Privacy">Личные данные</a>
</li> </li>
<li>
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Mails">Письма</a>
</li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Enter">Вход</a> <a class="nav-link text-dark" asparea="" asp-controller="Home" asp-action="Enter">Вход</a>
</li> </li>

View File

@ -0,0 +1,12 @@
namespace FlowerShopContracts.BindingModels
{
public class MailConfigBindingModel
{
public string MailLogin { get; set; } = string.Empty;
public string MailPassword { get; set; } = string.Empty;
public string SmtpClientHost { get; set; } = string.Empty;
public int SmtpClientPort { get; set; }
public string PopHost { get; set; } = string.Empty;
public int PopPort { get; set; }
}
}

View File

@ -0,0 +1,9 @@
namespace FlowerShopContracts.BindingModels
{
public class MailSendInfoBindingModel
{
public string MailAddress { get; set; } = string.Empty;
public string Subject { get; set; } = string.Empty;
public string Text { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,14 @@
using FlowerShopDataModels.Models;
namespace FlowerShopContracts.BindingModels
{
public class MessageInfoBindingModel : IMessageInfoModel
{
public string MessageId { get; set; } = string.Empty;
public int? ClientId { get; set; }
public string SenderName { get; set; } = string.Empty;
public DateTime DateDelivery { get; set; }
public string Subject { get; set; } = string.Empty;
public string Body { get; set; } = string.Empty;
}
}

View File

@ -0,0 +1,12 @@
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.SearchModels;
using FlowerShopContracts.ViewModels;
namespace FlowerShopContracts.BusinessLogicsContracts
{
public interface IMessageInfoLogic
{
List<MessageInfoViewModel>? ReadList(MessageInfoSearchModel? Model);
bool Create(MessageInfoBindingModel Model);
}
}

View File

@ -0,0 +1,8 @@
namespace FlowerShopContracts.SearchModels
{
public class MessageInfoSearchModel
{
public string? MessageId { get; set; }
public int? ClientId { get; set; }
}
}

View File

@ -0,0 +1,14 @@
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.SearchModels;
using FlowerShopContracts.ViewModels;
namespace FlowerShopContracts.StoragesContracts
{
public interface IMessageInfoStorage
{
List<MessageInfoViewModel> GetFullList();
List<MessageInfoViewModel> GetFilteredList(MessageInfoSearchModel Model);
MessageInfoViewModel? GetElement(MessageInfoSearchModel Model);
MessageInfoViewModel? Insert(MessageInfoBindingModel Model);
}
}

View File

@ -0,0 +1,19 @@
using FlowerShopDataModels.Models;
using System.ComponentModel;
namespace FlowerShopContracts.ViewModels
{
public class MessageInfoViewModel : IMessageInfoModel
{
public string MessageId { get; set; } = string.Empty;
public int? ClientId { get; set; }
[DisplayName("Отправитель")]
public string SenderName { get; set; } = string.Empty;
[DisplayName("Дата доставки")]
public DateTime DateDelivery { get; set; }
[DisplayName("Тема")]
public string Subject { get; set; } = string.Empty;
[DisplayName("Содержание")]
public string Body { get; set; } = string.Empty;
}
}

View File

@ -15,6 +15,8 @@ namespace FlowerShopContracts.ViewModels
public string FlowerName { get; set; } = string.Empty; public string FlowerName { get; set; } = string.Empty;
[DisplayName("ФИО клиента")] [DisplayName("ФИО клиента")]
public string ClientFIO { get; set; } = string.Empty; public string ClientFIO { get; set; } = string.Empty;
[DisplayName("Почта клиента")]
public string ClientEmail { get; set; } = string.Empty;
[DisplayName("ФИО исполнителя")] [DisplayName("ФИО исполнителя")]
public string ImplementerFIO { get; set; }=string.Empty; public string ImplementerFIO { get; set; }=string.Empty;
[DisplayName("Количество")] [DisplayName("Количество")]

View File

@ -0,0 +1,12 @@
namespace FlowerShopDataModels.Models
{
public interface IMessageInfoModel
{
string MessageId { get; }
int? ClientId { get; }
string SenderName { get; }
DateTime DateDelivery { get; }
string Subject { get; }
string Body { get; }
}
}

View File

@ -9,7 +9,7 @@ namespace FlowerShopDatabaseImplement
{ {
if (optionsBuilder.IsConfigured == false) if (optionsBuilder.IsConfigured == false)
{ {
optionsBuilder.UseNpgsql(@"Host=localhost;Database=FlowerShopDatabaseFull;Username=postgres;Password=postgres"); optionsBuilder.UseNpgsql(@"Host=localhost;Database=FlowerShopDatabaseTestFull;Username=postgres;Password=postgres");
} }
base.OnConfiguring(optionsBuilder); base.OnConfiguring(optionsBuilder);
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
@ -21,5 +21,6 @@ namespace FlowerShopDatabaseImplement
public virtual DbSet<Order> Orders { set; get; } public virtual DbSet<Order> Orders { set; get; }
public virtual DbSet<Client> Clients { set; get; } public virtual DbSet<Client> Clients { set; get; }
public virtual DbSet<Implementer> Implementers { set; get; } public virtual DbSet<Implementer> Implementers { set; get; }
public virtual DbSet<MessageInfo> MessageInfos { set; get; }
} }
} }

View File

@ -0,0 +1,56 @@
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.SearchModels;
using FlowerShopContracts.StoragesContracts;
using FlowerShopContracts.ViewModels;
using FlowerShopDatabaseImplement.Models;
namespace FlowerShopDatabaseImplement.Implements
{
public class MessageInfoStorage : IMessageInfoStorage
{
public List<MessageInfoViewModel> GetFullList()
{
using var Context = new FlowerShopDatabase();
return Context.MessageInfos
.Select(x => x.GetViewModel)
.ToList();
}
public List<MessageInfoViewModel> GetFilteredList(MessageInfoSearchModel Model)
{
using var Context = new FlowerShopDatabase();
return Context.MessageInfos
.Where(x => x.ClientId.HasValue && x.ClientId == Model.ClientId)
.Select(x => x.GetViewModel)
.ToList();
}
public MessageInfoViewModel? GetElement(MessageInfoSearchModel Model)
{
if (string.IsNullOrEmpty(Model.MessageId))
return null;
using var Context = new FlowerShopDatabase();
return Context.MessageInfos
.FirstOrDefault(x => x.MessageId == Model.MessageId)?
.GetViewModel;
}
public MessageInfoViewModel? Insert(MessageInfoBindingModel Model)
{
var NewMessageInfo = MessageInfo.Create(Model);
if (NewMessageInfo == null)
return null;
using var Context = new FlowerShopDatabase();
Context.MessageInfos.Add(NewMessageInfo);
Context.SaveChanges();
return NewMessageInfo.GetViewModel;
}
}
}

View File

@ -0,0 +1,279 @@
// <auto-generated />
using System;
using FlowerShopDatabaseImplement;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace FlowerShopDatabaseImplement.Migrations
{
[DbContext(typeof(FlowerShopDatabase))]
[Migration("20240502144838_test")]
partial class test
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.27")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.Client", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClientFIO")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Clients");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.Component", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ComponentName")
.IsRequired()
.HasColumnType("text");
b.Property<double>("Cost")
.HasColumnType("double precision");
b.HasKey("Id");
b.ToTable("Components");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.Flower", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("FlowerName")
.IsRequired()
.HasColumnType("text");
b.Property<double>("Price")
.HasColumnType("double precision");
b.HasKey("Id");
b.ToTable("Flowers");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.FlowerComponent", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("ComponentId")
.HasColumnType("integer");
b.Property<int>("Count")
.HasColumnType("integer");
b.Property<int>("FlowerId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("ComponentId");
b.HasIndex("FlowerId");
b.ToTable("FlowerComponents");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.Implementer", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ImplementerFIO")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Qualification")
.HasColumnType("integer");
b.Property<int>("WorkExperience")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("Implementers");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.MessageInfo", b =>
{
b.Property<string>("MessageId")
.HasColumnType("text");
b.Property<string>("Body")
.IsRequired()
.HasColumnType("text");
b.Property<int?>("ClientId")
.HasColumnType("integer");
b.Property<DateTime>("DateDelivery")
.HasColumnType("timestamp without time zone");
b.Property<string>("SenderName")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Subject")
.IsRequired()
.HasColumnType("text");
b.HasKey("MessageId");
b.ToTable("MessageInfos");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.Order", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("ClientId")
.HasColumnType("integer");
b.Property<int>("Count")
.HasColumnType("integer");
b.Property<DateTime>("DateCreate")
.HasColumnType("timestamp without time zone");
b.Property<DateTime?>("DateImplement")
.HasColumnType("timestamp without time zone");
b.Property<int>("FlowerId")
.HasColumnType("integer");
b.Property<int?>("ImplementerId")
.HasColumnType("integer");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<double>("Sum")
.HasColumnType("double precision");
b.HasKey("Id");
b.HasIndex("ClientId");
b.HasIndex("FlowerId");
b.HasIndex("ImplementerId");
b.ToTable("Orders");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.FlowerComponent", b =>
{
b.HasOne("FlowerShopDatabaseImplement.Models.Component", "Component")
.WithMany("FlowerComponents")
.HasForeignKey("ComponentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("FlowerShopDatabaseImplement.Models.Flower", "Flower")
.WithMany("Components")
.HasForeignKey("FlowerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Component");
b.Navigation("Flower");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.Order", b =>
{
b.HasOne("FlowerShopDatabaseImplement.Models.Client", "Client")
.WithMany()
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("FlowerShopDatabaseImplement.Models.Flower", "Flower")
.WithMany("Orders")
.HasForeignKey("FlowerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("FlowerShopDatabaseImplement.Models.Implementer", "Implementer")
.WithMany("Order")
.HasForeignKey("ImplementerId");
b.Navigation("Client");
b.Navigation("Flower");
b.Navigation("Implementer");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.Component", b =>
{
b.Navigation("FlowerComponents");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.Flower", b =>
{
b.Navigation("Components");
b.Navigation("Orders");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.Implementer", b =>
{
b.Navigation("Order");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,35 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace FlowerShopDatabaseImplement.Migrations
{
public partial class test : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "MessageInfos",
columns: table => new
{
MessageId = table.Column<string>(type: "text", nullable: false),
ClientId = table.Column<int>(type: "integer", nullable: true),
SenderName = table.Column<string>(type: "text", nullable: false),
DateDelivery = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
Subject = table.Column<string>(type: "text", nullable: false),
Body = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_MessageInfos", x => x.MessageId);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "MessageInfos");
}
}
}

View File

@ -140,6 +140,34 @@ namespace FlowerShopDatabaseImplement.Migrations
b.ToTable("Implementers"); b.ToTable("Implementers");
}); });
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.MessageInfo", b =>
{
b.Property<string>("MessageId")
.HasColumnType("text");
b.Property<string>("Body")
.IsRequired()
.HasColumnType("text");
b.Property<int?>("ClientId")
.HasColumnType("integer");
b.Property<DateTime>("DateDelivery")
.HasColumnType("timestamp without time zone");
b.Property<string>("SenderName")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Subject")
.IsRequired()
.HasColumnType("text");
b.HasKey("MessageId");
b.ToTable("MessageInfos");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.Order", b => modelBuilder.Entity("FlowerShopDatabaseImplement.Models.Order", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")

View File

@ -0,0 +1,44 @@
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.ViewModels;
using FlowerShopDataModels.Models;
using System.ComponentModel.DataAnnotations;
namespace FlowerShopDatabaseImplement.Models
{
public class MessageInfo : IMessageInfoModel
{
[Key]
public string MessageId { get; set; } = string.Empty;
public int? ClientId { get; set; }
public string SenderName { get; set; } = string.Empty;
public DateTime DateDelivery { get; set; }
public string Subject { get; set; } = string.Empty;
public string Body { get; set; } = string.Empty;
public static MessageInfo? Create(MessageInfoBindingModel? model)
{
if (model == null)
return null;
return new()
{
MessageId = model.MessageId,
ClientId = model.ClientId,
SenderName = model.SenderName,
DateDelivery = model.DateDelivery,
Subject = model.Subject,
Body = model.Body
};
}
public MessageInfoViewModel GetViewModel => new()
{
MessageId = MessageId,
ClientId = ClientId,
SenderName = SenderName,
DateDelivery = DateDelivery,
Subject = Subject,
Body = Body
};
}
}

View File

@ -61,6 +61,7 @@ namespace FlowerShopDatabaseImplement.Models
ImplementerId = ImplementerId, ImplementerId = ImplementerId,
FlowerName = Flower.FlowerName, FlowerName = Flower.FlowerName,
ClientFIO = Client.ClientFIO, ClientFIO = Client.ClientFIO,
ClientEmail = Client.Email,
ImplementerFIO = Implementer?.ImplementerFIO, ImplementerFIO = Implementer?.ImplementerFIO,
Count = Count, Count = Count,
Sum = Sum, Sum = Sum,

View File

@ -11,11 +11,13 @@ namespace FlowerShopFileImplement
private readonly string FlowerFileName = "Flower.xml"; private readonly string FlowerFileName = "Flower.xml";
private readonly string ClientFileName = "Client.xml"; private readonly string ClientFileName = "Client.xml";
private readonly string ImplementerFileName = "Implementer.xml"; private readonly string ImplementerFileName = "Implementer.xml";
private readonly string MessageInfoFileName = "MessageInfo.xml";
public List<Component> Components { get; private set; } public List<Component> Components { get; private set; }
public List<Order> Orders { get; private set; } public List<Order> Orders { get; private set; }
public List<Flower> Flowers { get; private set; } public List<Flower> Flowers { get; private set; }
public List<Client> Clients { get; private set; } public List<Client> Clients { get; private set; }
public List<Implementer> Implementers { get; private set; } public List<Implementer> Implementers { get; private set; }
public List<MessageInfo> MessageInfos { get; private set; }
public static DataFileSingleton GetInstance() public static DataFileSingleton GetInstance()
{ {
if (instance == null) if (instance == null)
@ -29,6 +31,7 @@ namespace FlowerShopFileImplement
public void SaveOrders() => SaveData(Orders, OrderFileName, "Orders", x => x.GetXElement); public void SaveOrders() => SaveData(Orders, OrderFileName, "Orders", x => x.GetXElement);
public void SaveClients() => SaveData(Clients, ClientFileName, "Clients", x => x.GetXElement); public void SaveClients() => SaveData(Clients, ClientFileName, "Clients", x => x.GetXElement);
public void SaveImplementers() => SaveData(Implementers, ImplementerFileName, "Implementers", x => x.GetXElement); public void SaveImplementers() => SaveData(Implementers, ImplementerFileName, "Implementers", x => x.GetXElement);
public void SaveMessageInfos() => SaveData(MessageInfos, MessageInfoFileName, "MessageInfos", x => x.GetXElement);
private DataFileSingleton() private DataFileSingleton()
{ {
Components = LoadData(ComponentFileName, "Component", x => Component.Create(x)!)!; Components = LoadData(ComponentFileName, "Component", x => Component.Create(x)!)!;
@ -36,6 +39,7 @@ namespace FlowerShopFileImplement
Orders = LoadData(OrderFileName, "Order", x => Order.Create(x)!)!; Orders = LoadData(OrderFileName, "Order", x => Order.Create(x)!)!;
Clients = LoadData(ClientFileName, "Client", x => Client.Create(x)!)!; Clients = LoadData(ClientFileName, "Client", x => Client.Create(x)!)!;
Implementers = LoadData(ImplementerFileName, "Implementer", x => Implementer.Create(x)!)!; Implementers = LoadData(ImplementerFileName, "Implementer", x => Implementer.Create(x)!)!;
MessageInfos = LoadData(MessageInfoFileName, "MessageInfo", x => MessageInfo.Create(x)!)!;
} }
private static List<T>? LoadData<T>(string filename, string xmlNodeName, Func<XElement, T> selectFunction) private static List<T>? LoadData<T>(string filename, string xmlNodeName, Func<XElement, T> selectFunction)
{ {

View File

@ -0,0 +1,56 @@
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.SearchModels;
using FlowerShopContracts.StoragesContracts;
using FlowerShopContracts.ViewModels;
using FlowerShopFileImplement.Models;
namespace FlowerShopFileImplement.Implements
{
public class MessageInfoStorage : IMessageInfoStorage
{
private readonly DataFileSingleton _source;
public MessageInfoStorage()
{
_source = DataFileSingleton.GetInstance();
}
public List<MessageInfoViewModel> GetFullList()
{
return _source.MessageInfos
.Select(x => x.GetViewModel)
.ToList();
}
public List<MessageInfoViewModel> GetFilteredList(MessageInfoSearchModel Model)
{
return _source.MessageInfos
.Where(x => x.ClientId.HasValue && x.ClientId == Model.ClientId)
.Select(x => x.GetViewModel)
.ToList();
}
public MessageInfoViewModel? GetElement(MessageInfoSearchModel Model)
{
if (string.IsNullOrEmpty(Model.MessageId))
return null;
return _source.MessageInfos
.FirstOrDefault(x => x.MessageId == Model.MessageId)?
.GetViewModel;
}
public MessageInfoViewModel? Insert(MessageInfoBindingModel Model)
{
var NewMessageInfo = MessageInfo.Create(Model);
if (NewMessageInfo == null)
return null;
_source.MessageInfos.Add(NewMessageInfo);
_source.SaveMessageInfos();
return NewMessageInfo.GetViewModel;
}
}
}

View File

@ -84,6 +84,7 @@ namespace FlowerShopFileImplement.Implements
var client = source.Clients.FirstOrDefault(x => x.Id == order.ClientId); var client = source.Clients.FirstOrDefault(x => x.Id == order.ClientId);
viewModel.FlowerName = flower?.FlowerName; viewModel.FlowerName = flower?.FlowerName;
viewModel.ClientFIO = client?.ClientFIO; viewModel.ClientFIO = client?.ClientFIO;
viewModel.ClientEmail = client?.Email;
return viewModel; return viewModel;
} }
} }

View File

@ -0,0 +1,74 @@
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.ViewModels;
using FlowerShopDataModels.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace FlowerShopFileImplement.Models
{
public class MessageInfo : IMessageInfoModel
{
public string MessageId { get; set; } = string.Empty;
public int? ClientId { get; set; }
public string SenderName { get; set; } = string.Empty;
public DateTime DateDelivery { get; set; }
public string Subject { get; set; } = string.Empty;
public string Body { get; set; } = string.Empty;
public static MessageInfo? Create(MessageInfoBindingModel? model)
{
if (model == null)
return null;
return new()
{
MessageId = model.MessageId,
ClientId = model.ClientId,
SenderName = model.SenderName,
DateDelivery = model.DateDelivery,
Subject = model.Subject,
Body = model.Body
};
}
public MessageInfoViewModel GetViewModel => new()
{
MessageId = MessageId,
ClientId = ClientId,
SenderName = SenderName,
DateDelivery = DateDelivery,
Subject = Subject,
Body = Body
};
public static MessageInfo? Create(XElement Element)
{
if (Element == null)
return null;
return new()
{
MessageId = Element.Attribute("MessageId")!.Value,
ClientId = Convert.ToInt32(Element.Attribute("ClientId")!.Value),
SenderName = Element.Attribute("SenderName")!.Value,
DateDelivery = Convert.ToDateTime(Element.Attribute("DateDelivery")!.Value),
Subject = Element.Attribute("Subject")!.Value,
Body = Element.Attribute("Body")!.Value,
};
}
public XElement GetXElement => new(
"MessageInfo",
new XAttribute("MessageId", MessageId),
new XAttribute("ClientId", ClientId),
new XAttribute("SenderName", SenderName),
new XAttribute("DateDelivery", DateDelivery),
new XAttribute("Subject", Subject),
new XAttribute("Body", Body)
);
}
}

View File

@ -10,6 +10,8 @@ namespace FlowerShopListImplement
public List<Flower> Flowers { get; set; } public List<Flower> Flowers { get; set; }
public List<Client> Clients { get; set; } public List<Client> Clients { get; set; }
public List<Implementer> Implementers { get; set; } public List<Implementer> Implementers { get; set; }
public List<MessageInfo> MessageInfos { get; set; }
private DataListSingleton() private DataListSingleton()
{ {
Components = new List<Component>(); Components = new List<Component>();
@ -17,6 +19,7 @@ namespace FlowerShopListImplement
Flowers = new List<Flower>(); Flowers = new List<Flower>();
Clients = new List<Client>(); Clients = new List<Client>();
Implementers = new List<Implementer>(); Implementers = new List<Implementer>();
MessageInfos = new List<MessageInfo>();
} }
public static DataListSingleton GetInstance() public static DataListSingleton GetInstance()
{ {

View File

@ -0,0 +1,54 @@
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.SearchModels;
using FlowerShopContracts.StoragesContracts;
using FlowerShopContracts.ViewModels;
using FlowerShopListImplement.Models;
namespace FlowerShopListImplement.Implements
{
public class MessageInfoStorage : IMessageInfoStorage
{
private readonly DataListSingleton _source;
public MessageInfoStorage()
{
_source = DataListSingleton.GetInstance();
}
public List<MessageInfoViewModel> GetFullList()
{
return _source.MessageInfos
.Select(x => x.GetViewModel)
.ToList();
}
public List<MessageInfoViewModel> GetFilteredList(MessageInfoSearchModel model)
{
return _source.MessageInfos
.Where(x => x.ClientId.HasValue && x.ClientId == model.ClientId)
.Select(x => x.GetViewModel)
.ToList();
}
public MessageInfoViewModel? GetElement(MessageInfoSearchModel model)
{
if (string.IsNullOrEmpty(model.MessageId))
return null;
return _source.MessageInfos
.FirstOrDefault(x => x.MessageId == model.MessageId)?
.GetViewModel;
}
public MessageInfoViewModel? Insert(MessageInfoBindingModel model)
{
var NewMessageInfo = MessageInfo.Create(model);
if (NewMessageInfo == null)
return null;
_source.MessageInfos.Add(NewMessageInfo);
return NewMessageInfo.GetViewModel;
}
}
}

View File

@ -114,6 +114,7 @@ namespace FlowerShopListImplement.Implements
if (client.Id == model.ClientId) if (client.Id == model.ClientId)
{ {
model.ClientFIO = client.ClientFIO; model.ClientFIO = client.ClientFIO;
model.ClientEmail = client.Email;
return model; return model;
} }
} }

View File

@ -0,0 +1,42 @@
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.ViewModels;
using FlowerShopDataModels.Models;
namespace FlowerShopListImplement.Models
{
public class MessageInfo : IMessageInfoModel
{
public string MessageId { get; set; } = string.Empty;
public int? ClientId { get; set; }
public string SenderName { get; set; } = string.Empty;
public DateTime DateDelivery { get; set; }
public string Subject { get; set; } = string.Empty;
public string Body { get; set; } = string.Empty;
public static MessageInfo? Create(MessageInfoBindingModel? model)
{
if (model == null)
return null;
return new()
{
MessageId = model.MessageId,
ClientId = model.ClientId,
SenderName = model.SenderName,
DateDelivery = model.DateDelivery,
Subject = model.Subject,
Body = model.Body
};
}
public MessageInfoViewModel GetViewModel => new()
{
MessageId = MessageId,
ClientId = ClientId,
SenderName = SenderName,
DateDelivery = DateDelivery,
Subject = Subject,
Body = Body
};
}
}

View File

@ -11,18 +11,20 @@ namespace FlowerShopRestApi.Controllers
public class ClientController : Controller public class ClientController : Controller
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IClientLogic _logic; private readonly IClientLogic _clientLogic;
public ClientController(IClientLogic logic, ILogger<ClientController> logger) private readonly IMessageInfoLogic _mailLogic;
public ClientController(IClientLogic clientLogic, IMessageInfoLogic mailLogic, ILogger<ClientController> logger)
{ {
_logger = logger; _logger = logger;
_logic = logic; _clientLogic = clientLogic;
_mailLogic = mailLogic;
} }
[HttpGet] [HttpGet]
public ClientViewModel? Login(string login, string password) public ClientViewModel? Login(string login, string password)
{ {
try try
{ {
return _logic.ReadElement(new ClientSearchModel return _clientLogic.ReadElement(new ClientSearchModel
{ {
Email = login, Email = login,
Password = password Password = password
@ -39,7 +41,7 @@ namespace FlowerShopRestApi.Controllers
{ {
try try
{ {
_logic.Create(model); _clientLogic.Create(model);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -52,7 +54,7 @@ namespace FlowerShopRestApi.Controllers
{ {
try try
{ {
_logic.Update(model); _clientLogic.Update(model);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -60,6 +62,23 @@ namespace FlowerShopRestApi.Controllers
throw; throw;
} }
} }
[HttpGet]
public List<MessageInfoViewModel>? GetMessages(int clientId)
{
try
{
return _mailLogic.ReadList(new MessageInfoSearchModel
{
ClientId = clientId
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка получения писем клиента");
throw;
}
}
} }
} }

View File

@ -1,4 +1,6 @@
using FlowerShopBusinessLogic.BusinessLogics; using FlowerShopBusinessLogic.BusinessLogics;
using FlowerShopBusinessLogic.MailWorker;
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.BusinessLogicsContracts; using FlowerShopContracts.BusinessLogicsContracts;
using FlowerShopContracts.StoragesContracts; using FlowerShopContracts.StoragesContracts;
using FlowerShopDatabaseImplement.Implements; using FlowerShopDatabaseImplement.Implements;
@ -13,10 +15,14 @@ builder.Logging.AddLog4Net("log4net.config");
builder.Services.AddTransient<IClientStorage, ClientStorage>(); builder.Services.AddTransient<IClientStorage, ClientStorage>();
builder.Services.AddTransient<IOrderStorage, OrderStorage>(); builder.Services.AddTransient<IOrderStorage, OrderStorage>();
builder.Services.AddTransient<IFlowerStorage, FlowerStorage>(); builder.Services.AddTransient<IFlowerStorage, FlowerStorage>();
builder.Services.AddTransient<IMessageInfoStorage, MessageInfoStorage>();
builder.Services.AddTransient<IOrderLogic, OrderLogic>(); builder.Services.AddTransient<IOrderLogic, OrderLogic>();
builder.Services.AddTransient<IClientLogic, ClientLogic>(); builder.Services.AddTransient<IClientLogic, ClientLogic>();
builder.Services.AddTransient<IFlowerLogic, FlowerLogic>(); builder.Services.AddTransient<IFlowerLogic, FlowerLogic>();
builder.Services.AddTransient<IMessageInfoLogic, MessageInfoLogic>();
builder.Services.AddSingleton<AbstractMailWorker, MailKitWorker>();
builder.Services.AddControllers(); builder.Services.AddControllers();
@ -32,6 +38,19 @@ builder.Services.AddSwaggerGen(c =>
var app = builder.Build(); var app = builder.Build();
var MailSender = app.Services.GetService<AbstractMailWorker>();
MailSender?.MailConfig(new MailConfigBindingModel
{
MailLogin = builder.Configuration?.GetSection("MailLogin")?.Value?.ToString() ?? string.Empty,
MailPassword = builder.Configuration?.GetSection("MailPassword")?.Value?.ToString() ?? string.Empty,
SmtpClientHost = builder.Configuration?.GetSection("SmtpClientHost")?.Value?.ToString() ?? string.Empty,
SmtpClientPort = Convert.ToInt32(builder.Configuration?.GetSection("SmtpClientPort")?.Value?.ToString()),
PopHost = builder.Configuration?.GetSection("PopHost")?.Value?.ToString() ?? string.Empty,
PopPort = Convert.ToInt32(builder.Configuration?.GetSection("PopPort")?.Value?.ToString())
});
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) if (app.Environment.IsDevelopment())
{ {

View File

@ -5,5 +5,13 @@
"Microsoft.AspNetCore": "Warning" "Microsoft.AspNetCore": "Warning"
} }
}, },
"AllowedHosts": "*" "AllowedHosts": "*",
"SmtpClientHost": "smtp.gmail.com",
"SmtpClientPort": "587",
"PopHost": "pop.gmail.com",
"PopPort": "995",
"MailLogin": "labworker83@gmail.com",
"MailPassword": "wpxc drvx lhqb uqpe"
} }