From f2dcfe8ecaa5e906d9bc850236c122b64e95c6ef Mon Sep 17 00:00:00 2001 From: "leonteva.v" Date: Thu, 20 Jun 2024 20:05:04 +0400 Subject: [PATCH] =?UTF-8?q?=D1=81=D1=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Typography/Typography/App.config | 11 + Typography/Typography/FormMain.Designer.cs | 418 +++++++++--------- Typography/Typography/FormMain.cs | 307 +++++++------ Typography/Typography/FormMain.resx | 62 +-- .../Typography/FormMessages.Designer.cs | 65 +++ Typography/Typography/FormMessages.cs | 45 ++ Typography/Typography/FormMessages.resx | 60 +++ Typography/Typography/Program.cs | 39 +- .../BusinessLogics/ClientLogic.cs | 32 +- .../BusinessLogics/MessageInfoLogic.cs | 80 ++++ .../BusinessLogics/OrderLogic.cs | 279 +++++++----- .../MailWorker/AbstractMailWorker.cs | 79 ++++ .../MailWorker/MailKitWorker.cs | 78 ++++ .../TypographyBusinessLogic.csproj | 1 + .../Controllers/HomeController.cs | 11 +- .../Views/Home/Mails.cshtml | 54 +++ .../Views/Shared/_Layout.cshtml | 3 + .../BindingModels/MailConfigBindingModel.cs | 18 + .../BindingModels/MailSendInfoBindingModel.cs | 15 + .../BindingModels/MessageInfoBindingModel.cs | 19 + .../IMessageInfoLogic.cs | 17 + .../SearchModels/MessageInfoSearchModel.cs | 14 + .../StoragesContracts/IMessageInfoStorage.cs | 19 + .../ViewModels/MessageInfoViewModel.cs | 24 + .../ViewModels/OrderViewModel.cs | 3 +- .../Models/IMessageInfoModel.cs | 18 + .../Implements/ClientStorage.cs | 141 +++--- .../Implements/MessageInfoStorage.cs | 55 +++ ...signer.cs => 20240620155631_r.Designer.cs} | 43 +- ...0240525000632_r.cs => 20240620155631_r.cs} | 29 ++ .../TypographyDatabaseModelSnapshot.cs | 41 ++ .../Models/Client.cs | 8 +- .../Models/MessageInfo.cs | 48 ++ .../Models/Order.cs | 3 +- .../TypographyDatabase.cs | 5 +- .../DataFileSingleton.cs | 12 +- .../Implements/ClientStorage.cs | 5 +- .../Implements/MessageInfoStorage.cs | 56 +++ .../Implements/OrderStorage.cs | 35 +- .../Models/MessageInfo.cs | 65 +++ .../DataListSingleton.cs | 6 +- .../Implements/ClientStorage.cs | 5 +- .../Implements/MessageInfoStorage.cs | 68 +++ .../Implements/OrderStorage.cs | 3 +- .../Models/MessageInfo.cs | 46 ++ Typography/TypographyRestApi/ClientLogic.cs | 122 +++++ .../Controllers/ClientController.cs | 20 +- Typography/TypographyRestApi/Program.cs | 17 +- Typography/TypographyRestApi/appsettings.json | 9 +- 49 files changed, 1961 insertions(+), 652 deletions(-) create mode 100644 Typography/Typography/App.config create mode 100644 Typography/Typography/FormMessages.Designer.cs create mode 100644 Typography/Typography/FormMessages.cs create mode 100644 Typography/Typography/FormMessages.resx create mode 100644 Typography/TypographyBusinessLogic/BusinessLogics/MessageInfoLogic.cs create mode 100644 Typography/TypographyBusinessLogic/MailWorker/AbstractMailWorker.cs create mode 100644 Typography/TypographyBusinessLogic/MailWorker/MailKitWorker.cs create mode 100644 Typography/TypographyClientApp/Views/Home/Mails.cshtml create mode 100644 Typography/TypographyContracts/BindingModels/MailConfigBindingModel.cs create mode 100644 Typography/TypographyContracts/BindingModels/MailSendInfoBindingModel.cs create mode 100644 Typography/TypographyContracts/BindingModels/MessageInfoBindingModel.cs create mode 100644 Typography/TypographyContracts/BusinessLogicsContracts/IMessageInfoLogic.cs create mode 100644 Typography/TypographyContracts/SearchModels/MessageInfoSearchModel.cs create mode 100644 Typography/TypographyContracts/StoragesContracts/IMessageInfoStorage.cs create mode 100644 Typography/TypographyContracts/ViewModels/MessageInfoViewModel.cs create mode 100644 Typography/TypographyDataModels/Models/IMessageInfoModel.cs create mode 100644 Typography/TypographyDatabaseImplement/Implements/MessageInfoStorage.cs rename Typography/TypographyDatabaseImplement/Migrations/{20240525000632_r.Designer.cs => 20240620155631_r.Designer.cs} (85%) rename Typography/TypographyDatabaseImplement/Migrations/{20240525000632_r.cs => 20240620155631_r.cs} (85%) create mode 100644 Typography/TypographyDatabaseImplement/Models/MessageInfo.cs create mode 100644 Typography/TypographyFileImplement/Implements/MessageInfoStorage.cs create mode 100644 Typography/TypographyFileImplement/Models/MessageInfo.cs create mode 100644 Typography/TypographyListImplement/Implements/MessageInfoStorage.cs create mode 100644 Typography/TypographyListImplement/Models/MessageInfo.cs create mode 100644 Typography/TypographyRestApi/ClientLogic.cs diff --git a/Typography/Typography/App.config b/Typography/Typography/App.config new file mode 100644 index 0000000..001c99e --- /dev/null +++ b/Typography/Typography/App.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Typography/Typography/FormMain.Designer.cs b/Typography/Typography/FormMain.Designer.cs index 21272d6..c756755 100644 --- a/Typography/Typography/FormMain.Designer.cs +++ b/Typography/Typography/FormMain.Designer.cs @@ -1,212 +1,222 @@ namespace TypographyView { - partial class FormMain - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; + partial class FormMain + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } - #region Windows Form Designer generated code + #region Windows Form Designer generated code - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - dataGridViewOrders = new DataGridView(); - menuStrip = new MenuStrip(); - directoriesToolStripMenuItem = new ToolStripMenuItem(); - componentsToolStripMenuItem = new ToolStripMenuItem(); - printedsToolStripMenuItem = new ToolStripMenuItem(); - clientsToolStripMenuItem = new ToolStripMenuItem(); - implementersToolStripMenuItem = new ToolStripMenuItem(); - ReportsToolStripMenuItem = new ToolStripMenuItem(); - PrintedListToolStripMenuItem = new ToolStripMenuItem(); - PrintedComponentsToolStripMenuItem = new ToolStripMenuItem(); - ListOfOrdersToolStripMenuItem = new ToolStripMenuItem(); - workLaunchToolStripMenuItem = new ToolStripMenuItem(); - buttonCreateOrder = new Button(); - buttonIssuedOrder = new Button(); - buttonRef = new Button(); - ((System.ComponentModel.ISupportInitialize)dataGridViewOrders).BeginInit(); - menuStrip.SuspendLayout(); - SuspendLayout(); - // - // dataGridViewOrders - // - dataGridViewOrders.BackgroundColor = Color.White; - dataGridViewOrders.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; - dataGridViewOrders.Location = new Point(0, 31); - dataGridViewOrders.Name = "dataGridViewOrders"; - dataGridViewOrders.RowHeadersVisible = false; - dataGridViewOrders.RowHeadersWidth = 51; - dataGridViewOrders.RowTemplate.Height = 29; - dataGridViewOrders.SelectionMode = DataGridViewSelectionMode.FullRowSelect; - dataGridViewOrders.Size = new Size(1080, 424); - dataGridViewOrders.TabIndex = 3; - // - // menuStrip - // - menuStrip.ImageScalingSize = new Size(20, 20); - menuStrip.Items.AddRange(new ToolStripItem[] { directoriesToolStripMenuItem, ReportsToolStripMenuItem, workLaunchToolStripMenuItem }); - menuStrip.Location = new Point(0, 0); - menuStrip.Name = "menuStrip"; - menuStrip.Size = new Size(1331, 28); - menuStrip.TabIndex = 6; - menuStrip.Text = "menuStrip"; - // - // directoriesToolStripMenuItem - // - directoriesToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { componentsToolStripMenuItem, printedsToolStripMenuItem, clientsToolStripMenuItem, implementersToolStripMenuItem }); - directoriesToolStripMenuItem.Name = "directoriesToolStripMenuItem"; - directoriesToolStripMenuItem.Size = new Size(117, 24); - directoriesToolStripMenuItem.Text = "Справочники"; - // - // componentsToolStripMenuItem - // - componentsToolStripMenuItem.Name = "componentsToolStripMenuItem"; - componentsToolStripMenuItem.Size = new Size(237, 26); - componentsToolStripMenuItem.Text = "Компоненты"; - componentsToolStripMenuItem.Click += componentsToolStripMenuItem_Click; - // - // printedsToolStripMenuItem - // - printedsToolStripMenuItem.Name = "printedsToolStripMenuItem"; - printedsToolStripMenuItem.Size = new Size(237, 26); - printedsToolStripMenuItem.Text = "Печатная продукция"; - printedsToolStripMenuItem.Click += printedsToolStripMenuItem_Click; - // - // clientsToolStripMenuItem - // - clientsToolStripMenuItem.Name = "clientsToolStripMenuItem"; - clientsToolStripMenuItem.Size = new Size(237, 26); - clientsToolStripMenuItem.Text = "Клиенты"; - clientsToolStripMenuItem.Click += clientsToolStripMenuItem_Click; - // - // implementersToolStripMenuItem - // - implementersToolStripMenuItem.Name = "implementersToolStripMenuItem"; - implementersToolStripMenuItem.Size = new Size(237, 26); - implementersToolStripMenuItem.Text = "Исполнители"; - implementersToolStripMenuItem.Click += implementersToolStripMenuItem_Click; - // - // ReportsToolStripMenuItem - // - ReportsToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { PrintedListToolStripMenuItem, PrintedComponentsToolStripMenuItem, ListOfOrdersToolStripMenuItem }); - ReportsToolStripMenuItem.Name = "ReportsToolStripMenuItem"; - ReportsToolStripMenuItem.Size = new Size(73, 24); - ReportsToolStripMenuItem.Text = "Отчеты"; - // - // PrintedListToolStripMenuItem - // - PrintedListToolStripMenuItem.Name = "PrintedListToolStripMenuItem"; - PrintedListToolStripMenuItem.Size = new Size(332, 26); - PrintedListToolStripMenuItem.Text = "Список печатной продукции"; - PrintedListToolStripMenuItem.Click += PrintedListToolStripMenuItem_Click; - // - // PrintedComponentsToolStripMenuItem - // - PrintedComponentsToolStripMenuItem.Name = "PrintedComponentsToolStripMenuItem"; - PrintedComponentsToolStripMenuItem.Size = new Size(332, 26); - PrintedComponentsToolStripMenuItem.Text = "Компоненты печатной продукции"; - PrintedComponentsToolStripMenuItem.Click += PrintedComponentsToolStripMenuItem_Click; - // - // ListOfOrdersToolStripMenuItem - // - ListOfOrdersToolStripMenuItem.Name = "ListOfOrdersToolStripMenuItem"; - ListOfOrdersToolStripMenuItem.Size = new Size(332, 26); - ListOfOrdersToolStripMenuItem.Text = "Список заказов"; - ListOfOrdersToolStripMenuItem.Click += ListOfOrdersToolStripMenuItem_Click; - // - // workLaunchToolStripMenuItem - // - workLaunchToolStripMenuItem.Name = "workLaunchToolStripMenuItem"; - workLaunchToolStripMenuItem.Size = new Size(114, 24); - workLaunchToolStripMenuItem.Text = "Запуск работ"; - workLaunchToolStripMenuItem.Click += workLaunchToolStripMenuItem_Click; - // - // buttonCreateOrder - // - buttonCreateOrder.Location = new Point(1109, 42); - buttonCreateOrder.Name = "buttonCreateOrder"; - buttonCreateOrder.Size = new Size(195, 29); - buttonCreateOrder.TabIndex = 5; - buttonCreateOrder.Text = "Создать заказ"; - buttonCreateOrder.UseVisualStyleBackColor = true; - buttonCreateOrder.Click += buttonCreateOrder_Click; - // - // buttonIssuedOrder - // - buttonIssuedOrder.Location = new Point(1109, 108); - buttonIssuedOrder.Name = "buttonIssuedOrder"; - buttonIssuedOrder.Size = new Size(195, 29); - buttonIssuedOrder.TabIndex = 8; - buttonIssuedOrder.Text = "Заказ выдан"; - buttonIssuedOrder.UseVisualStyleBackColor = true; - buttonIssuedOrder.Click += buttonIssuedOrder_Click; - // - // buttonRef - // - buttonRef.Location = new Point(1109, 174); - buttonRef.Name = "buttonRef"; - buttonRef.Size = new Size(195, 29); - buttonRef.TabIndex = 9; - buttonRef.Text = "Обновить список"; - buttonRef.UseVisualStyleBackColor = true; - buttonRef.Click += buttonRef_Click; - // - // FormMain - // - AutoScaleDimensions = new SizeF(8F, 20F); - AutoScaleMode = AutoScaleMode.Font; - ClientSize = new Size(1331, 453); - Controls.Add(buttonRef); - Controls.Add(buttonIssuedOrder); - Controls.Add(buttonCreateOrder); - Controls.Add(dataGridViewOrders); - Controls.Add(menuStrip); - MainMenuStrip = menuStrip; - Name = "FormMain"; - Text = "Типография"; - Load += FormMain_Load; - ((System.ComponentModel.ISupportInitialize)dataGridViewOrders).EndInit(); - menuStrip.ResumeLayout(false); - menuStrip.PerformLayout(); - ResumeLayout(false); - PerformLayout(); - } + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + buttonCreateOrder = new Button(); + buttonIssuedOrder = new Button(); + dataGridViewOrders = new DataGridView(); + buttonRef = new Button(); + menuStrip = new MenuStrip(); + directoriesToolStripMenuItem = new ToolStripMenuItem(); + componentsToolStripMenuItem = new ToolStripMenuItem(); + printedsToolStripMenuItem = new ToolStripMenuItem(); + clientsToolStripMenuItem = new ToolStripMenuItem(); + implementersToolStripMenuItem = new ToolStripMenuItem(); + reportsToolStripMenuItem = new ToolStripMenuItem(); + printedsListToolStripMenuItem = new ToolStripMenuItem(); + componentPrintedsToolStripMenuItem = new ToolStripMenuItem(); + ordersListToolStripMenuItem = new ToolStripMenuItem(); + workLaunchToolStripMenuItem = new ToolStripMenuItem(); + messagesToolStripMenuItem = new ToolStripMenuItem(); + ((System.ComponentModel.ISupportInitialize)dataGridViewOrders).BeginInit(); + menuStrip.SuspendLayout(); + SuspendLayout(); + // + // buttonCreateOrder + // + buttonCreateOrder.Location = new Point(1267, 31); + buttonCreateOrder.Name = "buttonCreateOrder"; + buttonCreateOrder.Size = new Size(203, 29); + buttonCreateOrder.TabIndex = 0; + buttonCreateOrder.Text = "Создать заказ"; + buttonCreateOrder.UseVisualStyleBackColor = true; + buttonCreateOrder.Click += ButtonCreateOrder_Click; + // + // buttonIssuedOrder + // + buttonIssuedOrder.Location = new Point(1267, 66); + buttonIssuedOrder.Name = "buttonIssuedOrder"; + buttonIssuedOrder.Size = new Size(203, 29); + buttonIssuedOrder.TabIndex = 2; + buttonIssuedOrder.Text = "Заказ выдан"; + buttonIssuedOrder.UseVisualStyleBackColor = true; + buttonIssuedOrder.Click += ButtonIssuedOrder_Click; + // + // dataGridViewOrders + // + dataGridViewOrders.BackgroundColor = SystemColors.ControlLightLight; + dataGridViewOrders.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; + dataGridViewOrders.Location = new Point(0, 31); + dataGridViewOrders.Name = "dataGridViewOrders"; + dataGridViewOrders.RowHeadersVisible = false; + dataGridViewOrders.RowHeadersWidth = 51; + dataGridViewOrders.RowTemplate.Height = 29; + dataGridViewOrders.SelectionMode = DataGridViewSelectionMode.FullRowSelect; + dataGridViewOrders.Size = new Size(1252, 402); + dataGridViewOrders.TabIndex = 3; + // + // buttonRef + // + buttonRef.Location = new Point(1267, 101); + buttonRef.Name = "buttonRef"; + buttonRef.Size = new Size(203, 29); + buttonRef.TabIndex = 4; + buttonRef.Text = "Обновить список"; + buttonRef.UseVisualStyleBackColor = true; + buttonRef.Click += ButtonRef_Click; + // + // menuStrip + // + menuStrip.ImageScalingSize = new Size(20, 20); + menuStrip.Items.AddRange(new ToolStripItem[] { directoriesToolStripMenuItem, reportsToolStripMenuItem, workLaunchToolStripMenuItem, messagesToolStripMenuItem }); + menuStrip.Location = new Point(0, 0); + menuStrip.Name = "menuStrip"; + menuStrip.Size = new Size(1482, 28); + menuStrip.TabIndex = 6; + menuStrip.Text = "menuStrip1"; + // + // directoriesToolStripMenuItem + // + directoriesToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { componentsToolStripMenuItem, printedsToolStripMenuItem, clientsToolStripMenuItem, implementersToolStripMenuItem }); + directoriesToolStripMenuItem.Name = "directoriesToolStripMenuItem"; + directoriesToolStripMenuItem.Size = new Size(117, 24); + directoriesToolStripMenuItem.Text = "Справочники"; + // + // componentsToolStripMenuItem + // + componentsToolStripMenuItem.Name = "componentsToolStripMenuItem"; + componentsToolStripMenuItem.Size = new Size(237, 26); + componentsToolStripMenuItem.Text = "Компоненты"; + componentsToolStripMenuItem.Click += ComponentsToolStripMenuItem_Click; + // + // printedsToolStripMenuItem + // + printedsToolStripMenuItem.Name = "printedsToolStripMenuItem"; + printedsToolStripMenuItem.Size = new Size(237, 26); + printedsToolStripMenuItem.Text = "Печатная продукция"; + printedsToolStripMenuItem.Click += PrintedsToolStripMenuItem_Click; + // + // clientsToolStripMenuItem + // + clientsToolStripMenuItem.Name = "clientsToolStripMenuItem"; + clientsToolStripMenuItem.Size = new Size(237, 26); + clientsToolStripMenuItem.Text = "Клиенты"; + clientsToolStripMenuItem.Click += ClientsToolStripMenuItem_Click; + // + // implementersToolStripMenuItem + // + implementersToolStripMenuItem.Name = "implementersToolStripMenuItem"; + implementersToolStripMenuItem.Size = new Size(237, 26); + implementersToolStripMenuItem.Text = "Исполнители"; + implementersToolStripMenuItem.Click += ImplementersToolStripMenuItem_Click; + // + // reportsToolStripMenuItem + // + reportsToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { printedsListToolStripMenuItem, componentPrintedsToolStripMenuItem, ordersListToolStripMenuItem }); + reportsToolStripMenuItem.Name = "reportsToolStripMenuItem"; + reportsToolStripMenuItem.Size = new Size(73, 24); + reportsToolStripMenuItem.Text = "Отчеты"; + // + // printedsListToolStripMenuItem + // + printedsListToolStripMenuItem.Name = "printedsListToolStripMenuItem"; + printedsListToolStripMenuItem.Size = new Size(332, 26); + printedsListToolStripMenuItem.Text = "Список печатной продукции"; + printedsListToolStripMenuItem.Click += PrintedsListToolStripMenuItem_Click; + // + // componentPrintedsToolStripMenuItem + // + componentPrintedsToolStripMenuItem.Name = "componentPrintedsToolStripMenuItem"; + componentPrintedsToolStripMenuItem.Size = new Size(332, 26); + componentPrintedsToolStripMenuItem.Text = "Компоненты печатной продукции"; + componentPrintedsToolStripMenuItem.Click += ComponentPrintedsToolStripMenuItem_Click; + // + // ordersListToolStripMenuItem + // + ordersListToolStripMenuItem.Name = "ordersListToolStripMenuItem"; + ordersListToolStripMenuItem.Size = new Size(332, 26); + ordersListToolStripMenuItem.Text = "Список заказов"; + ordersListToolStripMenuItem.Click += OrdersListToolStripMenuItem_Click; + // + // workLaunchToolStripMenuItem + // + workLaunchToolStripMenuItem.Name = "workLaunchToolStripMenuItem"; + workLaunchToolStripMenuItem.Size = new Size(114, 24); + workLaunchToolStripMenuItem.Text = "Запуск работ"; + workLaunchToolStripMenuItem.Click += WorkLaunchToolStripMenuItem_Click; + // + // messagesToolStripMenuItem + // + messagesToolStripMenuItem.Name = "messagesToolStripMenuItem"; + messagesToolStripMenuItem.Size = new Size(77, 24); + messagesToolStripMenuItem.Text = "Письма"; + messagesToolStripMenuItem.Click += MessagesToolStripMenuItem_Click; + // + // FormMain + // + AutoScaleDimensions = new SizeF(8F, 20F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(1482, 433); + Controls.Add(buttonRef); + Controls.Add(dataGridViewOrders); + Controls.Add(buttonIssuedOrder); + Controls.Add(buttonCreateOrder); + Controls.Add(menuStrip); + MainMenuStrip = menuStrip; + Name = "FormMain"; + StartPosition = FormStartPosition.CenterScreen; + Text = "Типография"; + Load += FormMain_Load; + ((System.ComponentModel.ISupportInitialize)dataGridViewOrders).EndInit(); + menuStrip.ResumeLayout(false); + menuStrip.PerformLayout(); + ResumeLayout(false); + PerformLayout(); + } - #endregion + #endregion - private DataGridView dataGridViewOrders; - private MenuStrip menuStrip; - private ToolStripMenuItem directoriesToolStripMenuItem; - private ToolStripMenuItem componentsToolStripMenuItem; - private ToolStripMenuItem printedsToolStripMenuItem; - private Button buttonCreateOrder; - private Button buttonIssuedOrder; - private Button buttonRef; - private ToolStripMenuItem ReportsToolStripMenuItem; - private ToolStripMenuItem PrintedListToolStripMenuItem; - private ToolStripMenuItem PrintedComponentsToolStripMenuItem; - private ToolStripMenuItem ListOfOrdersToolStripMenuItem; - private ToolStripMenuItem clientsToolStripMenuItem; - private ToolStripMenuItem implementersToolStripMenuItem; - private ToolStripMenuItem workLaunchToolStripMenuItem; - } + private Button buttonCreateOrder; + private Button buttonIssuedOrder; + private DataGridView dataGridViewOrders; + private Button buttonRef; + private MenuStrip menuStrip; + private ToolStripMenuItem directoriesToolStripMenuItem; + private ToolStripMenuItem componentsToolStripMenuItem; + private ToolStripMenuItem printedsToolStripMenuItem; + private ToolStripMenuItem reportsToolStripMenuItem; + private ToolStripMenuItem printedsListToolStripMenuItem; + private ToolStripMenuItem componentPrintedsToolStripMenuItem; + private ToolStripMenuItem ordersListToolStripMenuItem; + private ToolStripMenuItem clientsToolStripMenuItem; + private ToolStripMenuItem implementersToolStripMenuItem; + private ToolStripMenuItem workLaunchToolStripMenuItem; + private ToolStripMenuItem messagesToolStripMenuItem; + } } \ No newline at end of file diff --git a/Typography/Typography/FormMain.cs b/Typography/Typography/FormMain.cs index 60a1ad4..a6a2d65 100644 --- a/Typography/Typography/FormMain.cs +++ b/Typography/Typography/FormMain.cs @@ -1,149 +1,170 @@ -using TypographyDataModels.Enums; -using TypographyContracts.BindingModels; +using TypographyContracts.BindingModels; using TypographyContracts.BusinessLogicsContracts; using Microsoft.Extensions.Logging; using Typography; -using TypographyContracts.BindingModels; -using TypographyBusinessLogic.BusinessLogics; namespace TypographyView { - public partial class FormMain : Form - { - private readonly ILogger _logger; - private readonly IOrderLogic _orderLogic; - private readonly IReportLogic _reportLogic; - private readonly IWorkProcess _workProcess; - public FormMain(ILogger logger, IOrderLogic orderLogic, IReportLogic reportLogic, IWorkProcess workProcess) - { - InitializeComponent(); - _logger = logger; - _orderLogic = orderLogic; - _reportLogic = reportLogic; - _workProcess = workProcess; - } - private void LoadData() - { - try - { - var list = _orderLogic.ReadList(null); - if (list != null) - { - dataGridViewOrders.DataSource = list; - dataGridViewOrders.Columns["ClientId"].Visible = false; - dataGridViewOrders.Columns["ImplementerId"].Visible = false; - dataGridViewOrders.Columns["PrintedId"].Visible = false; - dataGridViewOrders.Columns["PrintedName"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; - } - _logger.LogInformation("Загрузка заказов"); - } - catch (Exception ex) - { - _logger.LogError(ex, "Ошибка загрузки заказов"); - MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - private void componentsToolStripMenuItem_Click(object sender, EventArgs e) - { - var service = Program.ServiceProvider?.GetService(typeof(FormComponents)); - if (service is FormComponents form) - { - form.ShowDialog(); - } - } - private void printedsToolStripMenuItem_Click(object sender, EventArgs e) - { - var service = Program.ServiceProvider?.GetService(typeof(FormPrinteds)); - if (service is FormPrinteds form) - { - form.ShowDialog(); - } - } - private void buttonCreateOrder_Click(object sender, EventArgs e) - { - var service = Program.ServiceProvider?.GetService(typeof(FormCreateOrder)); - if (service is FormCreateOrder form) - { - form.ShowDialog(); - LoadData(); - } - } - private void buttonIssuedOrder_Click(object sender, EventArgs e) - { - if (dataGridViewOrders.SelectedRows.Count == 1) - { - int id = Convert.ToInt32(dataGridViewOrders.SelectedRows[0].Cells["Id"].Value); - _logger.LogInformation("Заказ №{id}. Меняется статус на 'Выдан'", id); - try - { - var operationResult = _orderLogic.DeliveryOrder(new OrderBindingModel { Id = id }); - if (!operationResult) - { - throw new Exception("Ошибка при сохранении. Дополнительная информация в логах."); - } - _logger.LogInformation("Заказ №{id} выдан", id); - LoadData(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Ошибка отметки о выдачи заказа"); - MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - } - private void buttonRef_Click(object sender, EventArgs e) - { - LoadData(); - } - private void FormMain_Load(object sender, EventArgs e) - { - LoadData(); - } - private void PrintedListToolStripMenuItem_Click(object sender, EventArgs e) - { - using var dialog = new SaveFileDialog { Filter = "docx|*.docx" }; - if (dialog.ShowDialog() == DialogResult.OK) - { - _reportLogic.SavePrintedsToWordFile(new ReportBindingModel { FileName = dialog.FileName }); - MessageBox.Show("Выполнено", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information); - } - } - private void PrintedComponentsToolStripMenuItem_Click(object sender, EventArgs e) - { - var service = Program.ServiceProvider?.GetService(typeof(FormReportPrintedComponents)); - if (service is FormReportPrintedComponents form) - { - form.ShowDialog(); - } - } - private void ListOfOrdersToolStripMenuItem_Click(object sender, EventArgs e) - { - var service = Program.ServiceProvider?.GetService(typeof(FormReportOrders)); - if (service is FormReportOrders form) - { - form.ShowDialog(); - } - } - private void clientsToolStripMenuItem_Click(object sender, EventArgs e) - { - var service = Program.ServiceProvider?.GetService(typeof(FormClients)); - if (service is FormClients form) - { - form.ShowDialog(); - } - } - private void implementersToolStripMenuItem_Click(object sender, EventArgs e) - { - var service = Program.ServiceProvider?.GetService(typeof(FormImplementers)); - if (service is FormImplementers form) - { - form.ShowDialog(); - } - } - private void workLaunchToolStripMenuItem_Click(object sender, EventArgs e) - { - _workProcess.DoWork((Program.ServiceProvider?.GetService(typeof(IImplementerLogic)) as IImplementerLogic)!, _orderLogic); - MessageBox.Show("Процесс обработки запущен", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information); - } - } -} + public partial class FormMain : Form + { + private readonly ILogger _logger; + private readonly IOrderLogic _orderLogic; + private readonly IReportLogic _reportLogic; + private readonly IWorkProcess _workProcess; + + public FormMain(ILogger logger, IOrderLogic orderLogic, IReportLogic reportLogic, IWorkProcess workProcess) + { + InitializeComponent(); + _logger = logger; + _orderLogic = orderLogic; + _reportLogic = reportLogic; + _workProcess = workProcess; + } + + private void FormMain_Load(object sender, EventArgs e) + { + LoadData(); + } + + private void LoadData() + { + try + { + var list = _orderLogic.ReadList(null); + if (list != null) + { + dataGridViewOrders.DataSource = list; + dataGridViewOrders.Columns["ClientId"].Visible = false; + dataGridViewOrders.Columns["ClientEmail"].Visible = false; + dataGridViewOrders.Columns["ImplementerId"].Visible = false; + dataGridViewOrders.Columns["PrintedId"].Visible = false; + dataGridViewOrders.Columns["PrintedName"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; + } + _logger.LogInformation("Загрузка заказов"); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка загрузки заказов"); + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void ComponentsToolStripMenuItem_Click(object sender, EventArgs e) + { + var service = Program.ServiceProvider?.GetService(typeof(FormComponents)); + if (service is FormComponents form) + { + form.ShowDialog(); + } + } + + private void PrintedsToolStripMenuItem_Click(object sender, EventArgs e) + { + var service = Program.ServiceProvider?.GetService(typeof(FormPrinteds)); + if (service is FormPrinteds form) + { + form.ShowDialog(); + } + } + + private void ClientsToolStripMenuItem_Click(object sender, EventArgs e) + { + var service = Program.ServiceProvider?.GetService(typeof(FormClients)); + if (service is FormClients form) + { + form.ShowDialog(); + } + } + + private void ImplementersToolStripMenuItem_Click(object sender, EventArgs e) + { + var service = Program.ServiceProvider?.GetService(typeof(FormImplementers)); + if (service is FormImplementers form) + { + form.ShowDialog(); + } + } + + private void PrintedsListToolStripMenuItem_Click(object sender, EventArgs e) + { + using var dialog = new SaveFileDialog { Filter = "docx|*.docx" }; + if (dialog.ShowDialog() == DialogResult.OK) + { + _reportLogic.SavePrintedsToWordFile(new ReportBindingModel { FileName = dialog.FileName }); + MessageBox.Show("Выполнено", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + } + + private void ComponentPrintedsToolStripMenuItem_Click(object sender, EventArgs e) + { + var service = Program.ServiceProvider?.GetService(typeof(FormReportPrintedComponents)); + if (service is FormReportPrintedComponents form) + { + form.ShowDialog(); + } + } + + private void OrdersListToolStripMenuItem_Click(object sender, EventArgs e) + { + var service = Program.ServiceProvider?.GetService(typeof(FormReportOrders)); + if (service is FormReportOrders form) + { + form.ShowDialog(); + } + } + + private void WorkLaunchToolStripMenuItem_Click(object sender, EventArgs e) + { + _workProcess.DoWork((Program.ServiceProvider?.GetService(typeof(IImplementerLogic)) as IImplementerLogic)!, _orderLogic); + MessageBox.Show("Процесс обработки запущен", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + private void MessagesToolStripMenuItem_Click(object sender, EventArgs e) + { + var service = Program.ServiceProvider?.GetService(typeof(FormMessages)); + if (service is FormMessages form) + { + form.ShowDialog(); + } + } + + private void ButtonCreateOrder_Click(object sender, EventArgs e) + { + var service = Program.ServiceProvider?.GetService(typeof(FormCreateOrder)); + if (service is FormCreateOrder form) + { + form.ShowDialog(); + LoadData(); + } + } + + private void ButtonIssuedOrder_Click(object sender, EventArgs e) + { + if (dataGridViewOrders.SelectedRows.Count == 1) + { + int id = Convert.ToInt32(dataGridViewOrders.SelectedRows[0].Cells["Id"].Value); + _logger.LogInformation("Заказ №{id}. Меняется статус на 'Выдан'", id); + try + { + var operationResult = _orderLogic.DeliveryOrder(new OrderBindingModel { Id = id }); + if (!operationResult) + { + throw new Exception("Ошибка при сохранении. Дополнительная информация в логах."); + } + _logger.LogInformation("Заказ №{id} выдан", id); + LoadData(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка отметки о выдачи заказа"); + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + + private void ButtonRef_Click(object sender, EventArgs e) + { + LoadData(); + } + } +} \ No newline at end of file diff --git a/Typography/Typography/FormMain.resx b/Typography/Typography/FormMain.resx index 6c82d08..81a9e3d 100644 --- a/Typography/Typography/FormMain.resx +++ b/Typography/Typography/FormMain.resx @@ -1,64 +1,4 @@ - - - + diff --git a/Typography/Typography/FormMessages.Designer.cs b/Typography/Typography/FormMessages.Designer.cs new file mode 100644 index 0000000..6bc7b1a --- /dev/null +++ b/Typography/Typography/FormMessages.Designer.cs @@ -0,0 +1,65 @@ +namespace TypographyView +{ + partial class FormMessages + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + dataGridViewMessages = new DataGridView(); + ((System.ComponentModel.ISupportInitialize)dataGridViewMessages).BeginInit(); + SuspendLayout(); + // + // dataGridViewMessages + // + dataGridViewMessages.BackgroundColor = SystemColors.ControlLightLight; + dataGridViewMessages.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; + dataGridViewMessages.Location = new Point(1, 1); + dataGridViewMessages.Name = "dataGridViewMessages"; + dataGridViewMessages.RowHeadersVisible = false; + dataGridViewMessages.RowHeadersWidth = 51; + dataGridViewMessages.RowTemplate.Height = 29; + dataGridViewMessages.SelectionMode = DataGridViewSelectionMode.FullRowSelect; + dataGridViewMessages.Size = new Size(979, 750); + dataGridViewMessages.TabIndex = 0; + // + // FormMessages + // + AutoScaleDimensions = new SizeF(8F, 20F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(982, 753); + Controls.Add(dataGridViewMessages); + Name = "FormMessages"; + Text = "Входящие письма"; + Load += FormMessages_Load; + ((System.ComponentModel.ISupportInitialize)dataGridViewMessages).EndInit(); + ResumeLayout(false); + } + + #endregion + + private DataGridView dataGridViewMessages; + } +} \ No newline at end of file diff --git a/Typography/Typography/FormMessages.cs b/Typography/Typography/FormMessages.cs new file mode 100644 index 0000000..fe66a35 --- /dev/null +++ b/Typography/Typography/FormMessages.cs @@ -0,0 +1,45 @@ +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.Extensions.Logging; +using TypographyContracts.BusinessLogicsContracts; + +namespace TypographyView +{ + public partial class FormMessages : Form + { + private readonly ILogger _logger; + private readonly IMessageInfoLogic _logic; + + public FormMessages(ILogger logger, IMessageInfoLogic logic) + { + InitializeComponent(); + _logger = logger; + _logic = logic; + } + + private void FormMessages_Load(object sender, EventArgs e) + { + LoadData(); + } + + private void LoadData() + { + try + { + var list = _logic.ReadList(null); + if (list != null) + { + dataGridViewMessages.DataSource = list; + dataGridViewMessages.Columns["MessageId"].Visible = false; + dataGridViewMessages.Columns["ClientId"].Visible = false; + dataGridViewMessages.Columns["Body"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; + } + _logger.LogInformation("Загрузка входящих писем"); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка загрузки входящих писем"); + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } +} \ No newline at end of file diff --git a/Typography/Typography/FormMessages.resx b/Typography/Typography/FormMessages.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/Typography/Typography/FormMessages.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Typography/Typography/Program.cs b/Typography/Typography/Program.cs index c265a3d..7d12560 100644 --- a/Typography/Typography/Program.cs +++ b/Typography/Typography/Program.cs @@ -1,4 +1,4 @@ -using TypographyBusinessLogic.BusinessLogics; +using TypographyBusinessLogic.BusinessLogics; using TypographyContracts.BusinessLogicsContracts; using TypographyContracts.StoragesContracts; using TypographyDatabaseImplement.Implements; @@ -8,6 +8,8 @@ using NLog.Extensions.Logging; using TypographyBusinessLogic.OfficePackage.Implements; using TypographyBusinessLogic.OfficePackage; using System; +using TypographyBusinessLogic.MailWorker; +using TypographyContracts.BindingModels; using Typography; namespace TypographyView @@ -29,7 +31,27 @@ namespace TypographyView var services = new ServiceCollection(); ConfigureServices(services); _serviceProvider = services.BuildServiceProvider(); - Application.Run(_serviceProvider.GetRequiredService()); + try + { + var mailSender = _serviceProvider.GetService(); + 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(); + logger?.LogError(ex, "Îøèáêà ðàáîòû ñ ïî÷òîé"); + } + Application.Run(_serviceProvider.GetRequiredService()); } private static void ConfigureServices(ServiceCollection services) { @@ -43,16 +65,19 @@ namespace TypographyView services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); - services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddSingleton(); - services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -68,6 +93,8 @@ namespace TypographyView services.AddTransient(); services.AddTransient(); services.AddTransient(); - } - } + services.AddTransient(); + } + private static void MailCheck(object obj) => ServiceProvider?.GetService()?.MailCheck(); + } } \ No newline at end of file diff --git a/Typography/TypographyBusinessLogic/BusinessLogics/ClientLogic.cs b/Typography/TypographyBusinessLogic/BusinessLogics/ClientLogic.cs index fd30050..4664b64 100644 --- a/Typography/TypographyBusinessLogic/BusinessLogics/ClientLogic.cs +++ b/Typography/TypographyBusinessLogic/BusinessLogics/ClientLogic.cs @@ -4,6 +4,7 @@ using TypographyContracts.SearchModels; using TypographyContracts.StoragesContracts; using TypographyContracts.ViewModels; using Microsoft.Extensions.Logging; +using System.Text.RegularExpressions; namespace TypographyBusinessLogic.BusinessLogics { @@ -91,16 +92,27 @@ namespace TypographyBusinessLogic.BusinessLogics { throw new ArgumentNullException("Нет ФИО клиента", nameof(model.ClientFIO)); } - if (string.IsNullOrEmpty(model.Email)) - { - throw new ArgumentNullException("Нет логина клиента", nameof(model.Email)); - } - if (string.IsNullOrEmpty(model.Password)) - { - throw new ArgumentNullException("Нет пароля клиента", nameof(model.Password)); - } - _logger.LogInformation("Client. Id: {Id}. ClientFIO: {ClientFIO}. Email: {Email}.", - model?.Id, model?.ClientFIO, model?.Email); + if (string.IsNullOrEmpty(model.Email)) + { + throw new ArgumentNullException("Нет электронной почты клиента", nameof(model.Email)); + } + if (string.IsNullOrEmpty(model.Password)) + { + throw new ArgumentNullException("Нет пароля клиента", nameof(model.Password)); + } + + if (!Regex.IsMatch(model.Email, @"^[-\w.]+@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,4}$")) + { + throw new ArgumentNullException("Введенное не является адресом электронной почты", nameof(model.Email)); + } + if (model.Password.Length < 10 || model.Password.Length > 50 || + !Regex.IsMatch(model.Password, @"^((\w+\d+\W+)|(\w+\W+\d+)|(\d+\w+\W+)|(\d+\W+\w+)|(\W+\w+\d+)|(\W+\d+\w+))[\w\d\W]*$")) + { + throw new ArgumentNullException("Пароль не соответсвует требованиям безопасности", nameof(model.Password)); + } + + _logger.LogInformation("Client. Id: {Id}. ClientFIO: {ClientFIO}. Email: {Email}.", + model?.Id, model?.ClientFIO, model?.Email); var element = _clientStorage.GetElement(new ClientSearchModel { Email = model.Email }); if (element != null && element.Id != model.Id) { diff --git a/Typography/TypographyBusinessLogic/BusinessLogics/MessageInfoLogic.cs b/Typography/TypographyBusinessLogic/BusinessLogics/MessageInfoLogic.cs new file mode 100644 index 0000000..957292f --- /dev/null +++ b/Typography/TypographyBusinessLogic/BusinessLogics/MessageInfoLogic.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using TypographyContracts.BindingModels; +using TypographyContracts.BusinessLogicsContracts; +using TypographyContracts.SearchModels; +using TypographyContracts.StoragesContracts; +using TypographyContracts.ViewModels; + +namespace TypographyBusinessLogic.BusinessLogics +{ + public class MessageInfoLogic : IMessageInfoLogic + { + private readonly ILogger _logger; + private readonly IMessageInfoStorage _messageInfoStorage; + private readonly IClientStorage _clientStorage; + public MessageInfoLogic(ILogger logger, IMessageInfoStorage messageInfoStorage, IClientStorage clientStorage) + { + _logger = logger; + _messageInfoStorage = messageInfoStorage; + _clientStorage = clientStorage; + } + public List? ReadList(MessageInfoSearchModel? model) + { + _logger.LogInformation("ReadList. Id: {MessageId}. ClientId: {ClientId}.", + model?.MessageId, model?.ClientId); + var list = model == null ? _messageInfoStorage.GetFullList() : _messageInfoStorage.GetFilteredList(model); + if (list == null) + { + _logger.LogWarning("ReadList return null list"); + return null; + } + _logger.LogInformation("ReadList. Count: {Count}", list.Count); + return list; + } + 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) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + 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.Body)); + } + _logger.LogInformation("MessageInfo. SenderName: {SenderName}. Subject: {Subject}. Body: {Body}. Id: {MessageId}", + model.SenderName, model.Subject, model.Body, model.MessageId); + var client = _clientStorage.GetElement(new ClientSearchModel { Email = model.SenderName }); + if (client != null) + { + model.ClientId = client.Id; + } + } + } +} \ No newline at end of file diff --git a/Typography/TypographyBusinessLogic/BusinessLogics/OrderLogic.cs b/Typography/TypographyBusinessLogic/BusinessLogics/OrderLogic.cs index 220ebfa..3a9d129 100644 --- a/Typography/TypographyBusinessLogic/BusinessLogics/OrderLogic.cs +++ b/Typography/TypographyBusinessLogic/BusinessLogics/OrderLogic.cs @@ -5,125 +5,168 @@ using TypographyContracts.StoragesContracts; using TypographyContracts.ViewModels; using Microsoft.Extensions.Logging; using TypographyDataModels.Enums; -using System.Xml.Linq; +using TypographyBusinessLogic.MailWorker; namespace TypographyBusinessLogic.BusinessLogics { - public class OrderLogic : IOrderLogic - { - private readonly ILogger _logger; - private readonly IOrderStorage _orderStorage; - static readonly object _locker = new object(); - public OrderLogic(ILogger logger, IOrderStorage orderStorage) - { - _logger = logger; - _orderStorage = orderStorage; - } - public OrderViewModel? ReadElement(OrderSearchModel model) - { - if (model == null) - { - throw new ArgumentNullException(nameof(model)); - } - _logger.LogInformation("ReadElement. ClientId: {ClientId}. ImplementerId: {ImplementerId}. Status: {Status}. DateFrom: {DateFrom}. DateTo: {DateTo}. Id: {Id}", - model.ClientId, model.ImplementerId, model.Status, model.DateFrom, model.DateTo, model.Id); - var element = _orderStorage.GetElement(model); - if (element == null) - { - _logger.LogWarning("ReadElement element not found"); - return null; - } - _logger.LogInformation("ReadElement find. Id: {Id}", element.Id); - return element; - } - public List? ReadList(OrderSearchModel? model) - { - _logger.LogInformation("ReadList. Id:{Id}", model?.Id); - var list = model == null ? _orderStorage.GetFullList() : _orderStorage.GetFilteredList(model); - if (list == null) - { - _logger.LogWarning("ReadList return null list"); - return null; - } - _logger.LogInformation("ReadList. Count: {Count}", list.Count); - return list; - } - public bool CreateOrder(OrderBindingModel model) - { - CheckModel(model); - if (model.Status != OrderStatus.Неизвестен) - { - _logger.LogWarning("Order status change failed"); - return false; - } - model.Status = OrderStatus.Принят; - - if (_orderStorage.Insert(model) == null) - { - _logger.LogWarning("Order creation failed"); - return false; - } - return true; - } - public bool TakeOrderInWork(OrderBindingModel model) - { - lock (_locker) - { - return ChangeOrderStatus(model, OrderStatus.Выполняется); - } - } - public bool FinishOrder(OrderBindingModel model) - { - return ChangeOrderStatus(model, OrderStatus.Готов); - } - public bool DeliveryOrder(OrderBindingModel model) - { - return ChangeOrderStatus(model, OrderStatus.Выдан); - } - private void CheckModel(OrderBindingModel model, bool withParams = true) - { - if (model == null) - { - throw new ArgumentNullException(nameof(model)); - } - if (!withParams) - { - return; - } - if (model.Count <= 0) - { - throw new ArgumentNullException("Кол-во печатных изделий в заказе должно быть больше 0", nameof(model.Count)); - } - if (model.Sum <= 0) - { - throw new ArgumentNullException("Сумма заказа должна быть больше 0", nameof(model.Sum)); - } - _logger.LogInformation("Order. Count: {Count}. Sum: {Sum} Id: {Id}", model.Count, model.Sum, model.Id); - } - private bool ChangeOrderStatus(OrderBindingModel model, OrderStatus newStatus) - { - CheckModel(model, false); - var orderView = _orderStorage.GetElement(new OrderSearchModel { Id = model.Id }); - - if (orderView == null || newStatus - orderView.Status != 1) - { - _logger.LogWarning("Order status change failed"); - return false; - } - model.Status = newStatus; - if (!model.ImplementerId.HasValue) - model.ImplementerId = orderView.ImplementerId; - model.DateImplement = orderView.DateImplement; - if (newStatus == OrderStatus.Готов) - { - model.DateImplement = DateTime.Now; - } - if (_orderStorage.Update(model) == null) - { - _logger.LogWarning("Order status change failed"); - return false; - } - return true; - } - } + public class OrderLogic : IOrderLogic + { + private readonly ILogger _logger; + private readonly IOrderStorage _orderStorage; + private readonly AbstractMailWorker _mailWorker; + private readonly IClientLogic _clientLogic; + static readonly object _locker = new object(); + public OrderLogic(ILogger logger, IOrderStorage orderStorage, AbstractMailWorker mailWorker, IClientLogic clientLogic) + { + _logger = logger; + _orderStorage = orderStorage; + _mailWorker = mailWorker; + _clientLogic = clientLogic; + } + public bool CreateOrder(OrderBindingModel model) + { + CheckModel(model); + if (model.Status != OrderStatus.Неизвестен) + { + _logger.LogWarning("Insert operation failed. Order status incorrect."); + return false; + } + model.Status = OrderStatus.Принят; + var result = _orderStorage.Insert(model); + if (result == null) + { + model.Status = OrderStatus.Неизвестен; + _logger.LogWarning("Insert operation failed"); + return false; + } + SendOrderStatusMail(result.ClientId, $"Новый заказ создан. Номер заказа #{result.Id}", $"Заказ #{result.Id} от {result.DateCreate} на сумму {result.Sum:0.00} принят"); + return true; + } + public bool StatusUpdate(OrderBindingModel rawModel, OrderStatus newStatus) + { + var viewModel = _orderStorage.GetElement(new OrderSearchModel + { + Id = rawModel.Id + }); + if (viewModel == null) + { + _logger.LogWarning("Order model not found"); + return false; + } + OrderBindingModel model = new OrderBindingModel + { + Id = viewModel.Id, + PrintedId = viewModel.PrintedId, + Status = viewModel.Status, + DateCreate = viewModel.DateCreate, + DateImplement = viewModel.DateImplement, + Count = viewModel.Count, + Sum = viewModel.Sum, + ImplementerId = viewModel.ImplementerId + }; + if (rawModel.ImplementerId.HasValue) + { + model.ImplementerId = rawModel.ImplementerId; + } + CheckModel(model, false); + if (model.Status + 1 != newStatus) + { + _logger.LogWarning("Status update to " + newStatus.ToString() + " operation failed. Order status incorrect."); + return false; + } + model.Status = newStatus; + if (model.Status == OrderStatus.Выдан) model.DateImplement = DateTime.Now; + var result = _orderStorage.Update(model); + if (result == null) + { + model.Status--; + _logger.LogWarning("Update operation failed"); + return false; + } + SendOrderStatusMail(result.ClientId, $"Изменен статус заказа #{result.Id}", $"Заказ #{result.Id} изменен статус на {result.Status}"); + return true; + } + public bool TakeOrderInWork(OrderBindingModel model) + { + lock (_locker) + { + return StatusUpdate(model, OrderStatus.Выполняется); + } + } + public bool FinishOrder(OrderBindingModel model) + { + return StatusUpdate(model, OrderStatus.Готов); + } + public bool DeliveryOrder(OrderBindingModel model) + { + return StatusUpdate(model, OrderStatus.Выдан); + } + public List? ReadList(OrderSearchModel? model) + { + _logger.LogInformation("Order. OrderID:{Id}", model?.Id); + var list = model == null ? _orderStorage.GetFullList() : _orderStorage.GetFilteredList(model); + if (list == null) + { + _logger.LogWarning("ReadList return null list"); + return null; + } + _logger.LogInformation("ReadList. Count:{Count}", list.Count); + return list; + } + public OrderViewModel? ReadElement(OrderSearchModel model) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + _logger.LogInformation("ReadElement. Id:{ Id}", model.Id); + var element = _orderStorage.GetElement(model); + if (element == null) + { + _logger.LogWarning("ReadElement element not found"); + return null; + } + _logger.LogInformation("ReadElement find. Id:{Id}", element.Id); + return element; + } + private bool SendOrderStatusMail(int clientId, string subject, string text) + { + var client = _clientLogic.ReadElement(new() { Id = clientId }); + if (client == null) + { + return false; + } + _mailWorker.MailSendAsync(new() + { + MailAddress = client.Email, + Subject = subject, + Text = text + }); + return true; + } + private void CheckModel(OrderBindingModel model, bool withParams = true) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + if (!withParams) + { + return; + } + if (model.PrintedId < 0) + { + throw new ArgumentNullException("Некорректный идентификатор документа", nameof(model.PrintedId)); + } + if (model.Count <= 0) + { + throw new ArgumentNullException("Количество документов в заказе должно быть больше 0", nameof(model.Count)); + } + if (model.Sum <= 0) + { + throw new ArgumentNullException("Сумма заказа должна быть больше 0", nameof(model.Sum)); + } + _logger.LogInformation("Order. OrderID:{Id}.Sum:{ Sum}. PrintedId: { PrintedtId}", model.Id, model.Sum, model.PrintedId); + } + } } \ No newline at end of file diff --git a/Typography/TypographyBusinessLogic/MailWorker/AbstractMailWorker.cs b/Typography/TypographyBusinessLogic/MailWorker/AbstractMailWorker.cs new file mode 100644 index 0000000..9769410 --- /dev/null +++ b/Typography/TypographyBusinessLogic/MailWorker/AbstractMailWorker.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using TypographyBusinessLogic.BusinessLogics; +using TypographyContracts.BindingModels; +using TypographyContracts.BusinessLogicsContracts; + +namespace TypographyBusinessLogic.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 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> ReceiveMailAsync(); + } +} \ No newline at end of file diff --git a/Typography/TypographyBusinessLogic/MailWorker/MailKitWorker.cs b/Typography/TypographyBusinessLogic/MailWorker/MailKitWorker.cs new file mode 100644 index 0000000..8842c45 --- /dev/null +++ b/Typography/TypographyBusinessLogic/MailWorker/MailKitWorker.cs @@ -0,0 +1,78 @@ +using TypographyContracts.BindingModels; +using TypographyContracts.BusinessLogicsContracts; +using MailKit.Net.Pop3; +using MailKit.Security; +using Microsoft.Extensions.Logging; +using System.Net; +using System.Net.Mail; +using System.Text; + +namespace TypographyBusinessLogic.MailWorker +{ + public class MailKitWorker : AbstractMailWorker + { + public MailKitWorker(ILogger 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> ReceiveMailAsync() + { + var list = new List(); + 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; + } + } +} \ No newline at end of file diff --git a/Typography/TypographyBusinessLogic/TypographyBusinessLogic.csproj b/Typography/TypographyBusinessLogic/TypographyBusinessLogic.csproj index e4e2a8f..53f3545 100644 --- a/Typography/TypographyBusinessLogic/TypographyBusinessLogic.csproj +++ b/Typography/TypographyBusinessLogic/TypographyBusinessLogic.csproj @@ -8,6 +8,7 @@ + diff --git a/Typography/TypographyClientApp/Controllers/HomeController.cs b/Typography/TypographyClientApp/Controllers/HomeController.cs index 2fc1138..3662bf4 100644 --- a/Typography/TypographyClientApp/Controllers/HomeController.cs +++ b/Typography/TypographyClientApp/Controllers/HomeController.cs @@ -130,5 +130,14 @@ namespace TypographyClientApp.Controllers var prod = APIClient.GetRequest($"api/main/getprinted?printedId={printed}"); return count * (prod?.Price ?? 1); } - } + [HttpGet] + public IActionResult Mails() + { + if (APIClient.Client == null) + { + return Redirect("~/Home/Enter"); + } + return View(APIClient.GetRequest>($"api/client/getmessages?clientId={APIClient.Client.Id}")); + } + } } \ No newline at end of file diff --git a/Typography/TypographyClientApp/Views/Home/Mails.cshtml b/Typography/TypographyClientApp/Views/Home/Mails.cshtml new file mode 100644 index 0000000..d0659cb --- /dev/null +++ b/Typography/TypographyClientApp/Views/Home/Mails.cshtml @@ -0,0 +1,54 @@ +@using TypographyContracts.ViewModels + +@model List + +@{ + ViewData["Title"] = "Mails"; +} + +
+

Заказы

+
+ + +
+ @{ + if (Model == null) + { +

Авторизируйтесь

+ return; + } + + + + + + + + + + + @foreach (var item in Model) + { + + + + + + } + +
+ Дата письма + + Заголовок + + Текст +
+ @Html.DisplayFor(modelItem => item.DateDelivery) + + @Html.DisplayFor(modelItem => item.Subject) + + @Html.DisplayFor(modelItem => item.Body) +
+ } +
diff --git a/Typography/TypographyClientApp/Views/Shared/_Layout.cshtml b/Typography/TypographyClientApp/Views/Shared/_Layout.cshtml index e62f8ff..638ddd2 100644 --- a/Typography/TypographyClientApp/Views/Shared/_Layout.cshtml +++ b/Typography/TypographyClientApp/Views/Shared/_Layout.cshtml @@ -28,6 +28,9 @@ + diff --git a/Typography/TypographyContracts/BindingModels/MailConfigBindingModel.cs b/Typography/TypographyContracts/BindingModels/MailConfigBindingModel.cs new file mode 100644 index 0000000..c73d9b6 --- /dev/null +++ b/Typography/TypographyContracts/BindingModels/MailConfigBindingModel.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TypographyContracts.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; } + } +} \ No newline at end of file diff --git a/Typography/TypographyContracts/BindingModels/MailSendInfoBindingModel.cs b/Typography/TypographyContracts/BindingModels/MailSendInfoBindingModel.cs new file mode 100644 index 0000000..484448b --- /dev/null +++ b/Typography/TypographyContracts/BindingModels/MailSendInfoBindingModel.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TypographyContracts.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; + } +} \ No newline at end of file diff --git a/Typography/TypographyContracts/BindingModels/MessageInfoBindingModel.cs b/Typography/TypographyContracts/BindingModels/MessageInfoBindingModel.cs new file mode 100644 index 0000000..894fc75 --- /dev/null +++ b/Typography/TypographyContracts/BindingModels/MessageInfoBindingModel.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TypographyDataModels.Models; + +namespace TypographyContracts.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 string Subject { get; set; } = string.Empty; + public string Body { get; set; } = string.Empty; + public DateTime DateDelivery { get; set; } + } +} \ No newline at end of file diff --git a/Typography/TypographyContracts/BusinessLogicsContracts/IMessageInfoLogic.cs b/Typography/TypographyContracts/BusinessLogicsContracts/IMessageInfoLogic.cs new file mode 100644 index 0000000..1b766d6 --- /dev/null +++ b/Typography/TypographyContracts/BusinessLogicsContracts/IMessageInfoLogic.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TypographyContracts.BindingModels; +using TypographyContracts.SearchModels; +using TypographyContracts.ViewModels; + +namespace TypographyContracts.BusinessLogicsContracts +{ + public interface IMessageInfoLogic + { + List? ReadList(MessageInfoSearchModel? model); + bool Create(MessageInfoBindingModel model); + } +} \ No newline at end of file diff --git a/Typography/TypographyContracts/SearchModels/MessageInfoSearchModel.cs b/Typography/TypographyContracts/SearchModels/MessageInfoSearchModel.cs new file mode 100644 index 0000000..68a7477 --- /dev/null +++ b/Typography/TypographyContracts/SearchModels/MessageInfoSearchModel.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TypographyContracts.SearchModels +{ + public class MessageInfoSearchModel + { + public int? ClientId { get; set; } + public string? MessageId { get; set; } + } +} \ No newline at end of file diff --git a/Typography/TypographyContracts/StoragesContracts/IMessageInfoStorage.cs b/Typography/TypographyContracts/StoragesContracts/IMessageInfoStorage.cs new file mode 100644 index 0000000..c1610aa --- /dev/null +++ b/Typography/TypographyContracts/StoragesContracts/IMessageInfoStorage.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TypographyContracts.BindingModels; +using TypographyContracts.SearchModels; +using TypographyContracts.ViewModels; + +namespace TypographyContracts.StoragesContracts +{ + public interface IMessageInfoStorage + { + List GetFullList(); + List GetFilteredList(MessageInfoSearchModel model); + MessageInfoViewModel? GetElement(MessageInfoSearchModel model); + MessageInfoViewModel? Insert(MessageInfoBindingModel model); + } +} \ No newline at end of file diff --git a/Typography/TypographyContracts/ViewModels/MessageInfoViewModel.cs b/Typography/TypographyContracts/ViewModels/MessageInfoViewModel.cs new file mode 100644 index 0000000..f87398b --- /dev/null +++ b/Typography/TypographyContracts/ViewModels/MessageInfoViewModel.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TypographyDataModels.Models; + +namespace TypographyContracts.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; + } +} \ No newline at end of file diff --git a/Typography/TypographyContracts/ViewModels/OrderViewModel.cs b/Typography/TypographyContracts/ViewModels/OrderViewModel.cs index a50ea9a..b7a3419 100644 --- a/Typography/TypographyContracts/ViewModels/OrderViewModel.cs +++ b/Typography/TypographyContracts/ViewModels/OrderViewModel.cs @@ -11,7 +11,8 @@ namespace TypographyContracts.ViewModels public int ClientId { get; set; } [DisplayName("Клиент")] public string ClientFIO { get; set; } = string.Empty; - public int? ImplementerId { get; set; } + public string ClientEmail { get; set; } = string.Empty; + public int? ImplementerId { get; set; } [DisplayName("Исполнитель")] public string? ImplementerFIO { get; set; } = string.Empty; public int PrintedId { get; set; } diff --git a/Typography/TypographyDataModels/Models/IMessageInfoModel.cs b/Typography/TypographyDataModels/Models/IMessageInfoModel.cs new file mode 100644 index 0000000..7f95db3 --- /dev/null +++ b/Typography/TypographyDataModels/Models/IMessageInfoModel.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TypographyDataModels.Models +{ + public interface IMessageInfoModel + { + string MessageId { get; } + int? ClientId { get; } + string SenderName { get; } + DateTime DateDelivery { get; } + string Subject { get; } + string Body { get; } + } +} \ No newline at end of file diff --git a/Typography/TypographyDatabaseImplement/Implements/ClientStorage.cs b/Typography/TypographyDatabaseImplement/Implements/ClientStorage.cs index 99e0a73..e3c25b0 100644 --- a/Typography/TypographyDatabaseImplement/Implements/ClientStorage.cs +++ b/Typography/TypographyDatabaseImplement/Implements/ClientStorage.cs @@ -8,74 +8,75 @@ namespace TypographyDatabaseImplement.Implements { public class ClientStorage : IClientStorage { - public List GetFullList() - { - using var context = new TypographyDatabase(); - return context.Clients - .Select(x => x.GetViewModel) - .ToList(); - } - public List GetFilteredList(ClientSearchModel model) - { - if (string.IsNullOrEmpty(model.ClientFIO) && string.IsNullOrEmpty(model.Email)) - { - return new(); - } - using var context = new TypographyDatabase(); - return context.Clients - .Where(x => (!string.IsNullOrEmpty(model.ClientFIO) && x.ClientFIO.Contains(model.ClientFIO)) || - (!string.IsNullOrEmpty(model.Email) && x.ClientFIO.Contains(model.Email))) - .Select(x => x.GetViewModel) - .ToList(); - } - public ClientViewModel? GetElement(ClientSearchModel model) - { - if (!model.Id.HasValue && string.IsNullOrEmpty(model.ClientFIO) && string.IsNullOrEmpty(model.Email) && string.IsNullOrEmpty(model.Password)) - { - return null; - } - using var context = new TypographyDatabase(); - return context.Clients - .FirstOrDefault(x => (model.Id.HasValue && x.Id == model.Id) || - (!string.IsNullOrEmpty(model.ClientFIO) && x.ClientFIO == model.ClientFIO) || - (!string.IsNullOrEmpty(model.Email) && !string.IsNullOrEmpty(model.Password) && x.Email == model.Email && x.Password == model.Password)) - ?.GetViewModel; - } - public ClientViewModel? Insert(ClientBindingModel model) - { - var newClient = Client.Create(model); - if (newClient == null) - { - return null; - } - using var context = new TypographyDatabase(); - context.Clients.Add(newClient); - context.SaveChanges(); - return newClient.GetViewModel; - } - public ClientViewModel? Update(ClientBindingModel model) - { - using var context = new TypographyDatabase(); - var client = context.Clients.FirstOrDefault(x => x.Id == model.Id); - if (client == null) - { - return null; - } - client.Update(model); - context.SaveChanges(); - return client.GetViewModel; - } - public ClientViewModel? Delete(ClientBindingModel model) - { - using var context = new TypographyDatabase(); - var element = context.Clients.FirstOrDefault(rec => rec.Id == model.Id); - if (element != null) - { - context.Clients.Remove(element); - context.SaveChanges(); - return element.GetViewModel; - } - return null; - } - } + public List GetFullList() + { + using var context = new TypographyDatabase(); + return context.Clients + .Select(x => x.GetViewModel) + .ToList(); + } + public List GetFilteredList(ClientSearchModel model) + { + if (string.IsNullOrEmpty(model.ClientFIO) && string.IsNullOrEmpty(model.Email)) + { + return new(); + } + using var context = new TypographyDatabase(); + return context.Clients + .Where(x => (!string.IsNullOrEmpty(model.ClientFIO) && x.ClientFIO.Contains(model.ClientFIO)) || + (!string.IsNullOrEmpty(model.Email) && x.ClientFIO.Contains(model.Email))) + .Select(x => x.GetViewModel) + .ToList(); + } + public ClientViewModel? GetElement(ClientSearchModel model) + { + if (!model.Id.HasValue && string.IsNullOrEmpty(model.ClientFIO) && string.IsNullOrEmpty(model.Email) && string.IsNullOrEmpty(model.Password)) + { + return null; + } + using var context = new TypographyDatabase(); + return context.Clients + .FirstOrDefault(x => (model.Id.HasValue && x.Id == model.Id) || + (!string.IsNullOrEmpty(model.ClientFIO) && x.ClientFIO == model.ClientFIO) || + (!string.IsNullOrEmpty(model.Email) && x.Email == model.Email) || + (!string.IsNullOrEmpty(model.Email) && !string.IsNullOrEmpty(model.Password) && x.Email == model.Email && x.Password == model.Password)) + ?.GetViewModel; + } + public ClientViewModel? Insert(ClientBindingModel model) + { + var newClient = Client.Create(model); + if (newClient == null) + { + return null; + } + using var context = new TypographyDatabase(); + context.Clients.Add(newClient); + context.SaveChanges(); + return newClient.GetViewModel; + } + public ClientViewModel? Update(ClientBindingModel model) + { + using var context = new TypographyDatabase(); + var client = context.Clients.FirstOrDefault(x => x.Id == model.Id); + if (client == null) + { + return null; + } + client.Update(model); + context.SaveChanges(); + return client.GetViewModel; + } + public ClientViewModel? Delete(ClientBindingModel model) + { + using var context = new TypographyDatabase(); + var element = context.Clients.FirstOrDefault(rec => rec.Id == model.Id); + if (element != null) + { + context.Clients.Remove(element); + context.SaveChanges(); + return element.GetViewModel; + } + return null; + } + } } \ No newline at end of file diff --git a/Typography/TypographyDatabaseImplement/Implements/MessageInfoStorage.cs b/Typography/TypographyDatabaseImplement/Implements/MessageInfoStorage.cs new file mode 100644 index 0000000..e61c236 --- /dev/null +++ b/Typography/TypographyDatabaseImplement/Implements/MessageInfoStorage.cs @@ -0,0 +1,55 @@ +using TypographyContracts.BindingModels; +using TypographyContracts.SearchModels; +using TypographyContracts.StoragesContracts; +using TypographyContracts.ViewModels; +using TypographyDatabaseImplement.Models; + +namespace TypographyDatabaseImplement.Implements +{ + public class MessageInfoStorage : IMessageInfoStorage + { + public List GetFullList() + { + using var context = new TypographyDatabase(); + return context.Messages + .Select(x => x.GetViewModel) + .ToList(); + } + public List GetFilteredList(MessageInfoSearchModel model) + { + if (!model.ClientId.HasValue) + { + return new(); + } + using var context = new TypographyDatabase(); + return context.Messages + .Where(x => x.ClientId == model.ClientId) + .Select(x => x.GetViewModel) + .ToList(); + } + public MessageInfoViewModel? GetElement(MessageInfoSearchModel model) + { + if (string.IsNullOrEmpty(model.MessageId) && !model.ClientId.HasValue) + { + return null; + } + using var context = new TypographyDatabase(); + return context.Messages + .FirstOrDefault(x => (!string.IsNullOrEmpty(model.MessageId) && x.MessageId == model.MessageId) || + (model.ClientId.HasValue && x.ClientId == model.ClientId))? + .GetViewModel; + } + public MessageInfoViewModel? Insert(MessageInfoBindingModel model) + { + var newMessageInfo = MessageInfo.Create(model); + if (newMessageInfo == null) + { + return null; + } + using var context = new TypographyDatabase(); + context.Messages.Add(newMessageInfo); + context.SaveChanges(); + return newMessageInfo.GetViewModel; + } + } +} \ No newline at end of file diff --git a/Typography/TypographyDatabaseImplement/Migrations/20240525000632_r.Designer.cs b/Typography/TypographyDatabaseImplement/Migrations/20240620155631_r.Designer.cs similarity index 85% rename from Typography/TypographyDatabaseImplement/Migrations/20240525000632_r.Designer.cs rename to Typography/TypographyDatabaseImplement/Migrations/20240620155631_r.Designer.cs index c2f4955..4ba2075 100644 --- a/Typography/TypographyDatabaseImplement/Migrations/20240525000632_r.Designer.cs +++ b/Typography/TypographyDatabaseImplement/Migrations/20240620155631_r.Designer.cs @@ -12,7 +12,7 @@ using TypographyDatabaseImplement; namespace TypographyDatabaseImplement.Migrations { [DbContext(typeof(TypographyDatabase))] - [Migration("20240525000632_r")] + [Migration("20240620155631_r")] partial class r { /// @@ -97,6 +97,36 @@ namespace TypographyDatabaseImplement.Migrations b.ToTable("Implementers"); }); + modelBuilder.Entity("TypographyDatabaseImplement.Models.MessageInfo", b => + { + b.Property("MessageId") + .HasColumnType("nvarchar(450)"); + + b.Property("Body") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("DateDelivery") + .HasColumnType("datetime2"); + + b.Property("SenderName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.ToTable("Messages"); + }); + modelBuilder.Entity("TypographyDatabaseImplement.Models.Order", b => { b.Property("Id") @@ -186,6 +216,15 @@ namespace TypographyDatabaseImplement.Migrations b.ToTable("PrintedComponents"); }); + modelBuilder.Entity("TypographyDatabaseImplement.Models.MessageInfo", b => + { + b.HasOne("TypographyDatabaseImplement.Models.Client", "Client") + .WithMany("ClientMessages") + .HasForeignKey("ClientId"); + + b.Navigation("Client"); + }); + modelBuilder.Entity("TypographyDatabaseImplement.Models.Order", b => { b.HasOne("TypographyDatabaseImplement.Models.Client", "Client") @@ -232,6 +271,8 @@ namespace TypographyDatabaseImplement.Migrations modelBuilder.Entity("TypographyDatabaseImplement.Models.Client", b => { + b.Navigation("ClientMessages"); + b.Navigation("ClientOrders"); }); diff --git a/Typography/TypographyDatabaseImplement/Migrations/20240525000632_r.cs b/Typography/TypographyDatabaseImplement/Migrations/20240620155631_r.cs similarity index 85% rename from Typography/TypographyDatabaseImplement/Migrations/20240525000632_r.cs rename to Typography/TypographyDatabaseImplement/Migrations/20240620155631_r.cs index 80efa95..19889df 100644 --- a/Typography/TypographyDatabaseImplement/Migrations/20240525000632_r.cs +++ b/Typography/TypographyDatabaseImplement/Migrations/20240620155631_r.cs @@ -70,6 +70,27 @@ namespace TypographyDatabaseImplement.Migrations table.PrimaryKey("PK_Printeds", x => x.Id); }); + migrationBuilder.CreateTable( + name: "Messages", + columns: table => new + { + MessageId = table.Column(type: "nvarchar(450)", nullable: false), + ClientId = table.Column(type: "int", nullable: true), + SenderName = table.Column(type: "nvarchar(max)", nullable: false), + DateDelivery = table.Column(type: "datetime2", nullable: false), + Subject = table.Column(type: "nvarchar(max)", nullable: false), + Body = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Messages", x => x.MessageId); + table.ForeignKey( + name: "FK_Messages_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id"); + }); + migrationBuilder.CreateTable( name: "Orders", columns: table => new @@ -134,6 +155,11 @@ namespace TypographyDatabaseImplement.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateIndex( + name: "IX_Messages_ClientId", + table: "Messages", + column: "ClientId"); + migrationBuilder.CreateIndex( name: "IX_Orders_ClientId", table: "Orders", @@ -163,6 +189,9 @@ namespace TypographyDatabaseImplement.Migrations /// protected override void Down(MigrationBuilder migrationBuilder) { + migrationBuilder.DropTable( + name: "Messages"); + migrationBuilder.DropTable( name: "Orders"); diff --git a/Typography/TypographyDatabaseImplement/Migrations/TypographyDatabaseModelSnapshot.cs b/Typography/TypographyDatabaseImplement/Migrations/TypographyDatabaseModelSnapshot.cs index 16842c9..a1e48fe 100644 --- a/Typography/TypographyDatabaseImplement/Migrations/TypographyDatabaseModelSnapshot.cs +++ b/Typography/TypographyDatabaseImplement/Migrations/TypographyDatabaseModelSnapshot.cs @@ -94,6 +94,36 @@ namespace TypographyDatabaseImplement.Migrations b.ToTable("Implementers"); }); + modelBuilder.Entity("TypographyDatabaseImplement.Models.MessageInfo", b => + { + b.Property("MessageId") + .HasColumnType("nvarchar(450)"); + + b.Property("Body") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("DateDelivery") + .HasColumnType("datetime2"); + + b.Property("SenderName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.ToTable("Messages"); + }); + modelBuilder.Entity("TypographyDatabaseImplement.Models.Order", b => { b.Property("Id") @@ -183,6 +213,15 @@ namespace TypographyDatabaseImplement.Migrations b.ToTable("PrintedComponents"); }); + modelBuilder.Entity("TypographyDatabaseImplement.Models.MessageInfo", b => + { + b.HasOne("TypographyDatabaseImplement.Models.Client", "Client") + .WithMany("ClientMessages") + .HasForeignKey("ClientId"); + + b.Navigation("Client"); + }); + modelBuilder.Entity("TypographyDatabaseImplement.Models.Order", b => { b.HasOne("TypographyDatabaseImplement.Models.Client", "Client") @@ -229,6 +268,8 @@ namespace TypographyDatabaseImplement.Migrations modelBuilder.Entity("TypographyDatabaseImplement.Models.Client", b => { + b.Navigation("ClientMessages"); + b.Navigation("ClientOrders"); }); diff --git a/Typography/TypographyDatabaseImplement/Models/Client.cs b/Typography/TypographyDatabaseImplement/Models/Client.cs index 97137a4..09da7cf 100644 --- a/Typography/TypographyDatabaseImplement/Models/Client.cs +++ b/Typography/TypographyDatabaseImplement/Models/Client.cs @@ -17,9 +17,11 @@ namespace TypographyDatabaseImplement.Models public string Password { get; set; } = string.Empty; [ForeignKey("ClientId")] public virtual List ClientOrders { get; set; } = new(); - public static Client? Create(ClientBindingModel model) - { - if (model == null) + [ForeignKey("ClientId")] + public virtual List ClientMessages { get; set; } = new(); + public static Client? Create(ClientBindingModel model) + { + if (model == null) { return null; } diff --git a/Typography/TypographyDatabaseImplement/Models/MessageInfo.cs b/Typography/TypographyDatabaseImplement/Models/MessageInfo.cs new file mode 100644 index 0000000..a21cc37 --- /dev/null +++ b/Typography/TypographyDatabaseImplement/Models/MessageInfo.cs @@ -0,0 +1,48 @@ +using TypographyContracts.BindingModels; +using TypographyContracts.ViewModels; +using TypographyDataModels.Models; +using System.ComponentModel.DataAnnotations; + +namespace TypographyDatabaseImplement.Models +{ + public class MessageInfo : IMessageInfoModel + { + [Key] + public string MessageId { get; private set; } = string.Empty; + public int? ClientId { get; private set; } + public virtual Client? Client { get; private set; } + [Required] + public string SenderName { get; private set; } = string.Empty; + [Required] + public DateTime DateDelivery { get; private set; } + [Required] + public string Subject { get; private set; } = string.Empty; + [Required] + public string Body { get; private set; } = string.Empty; + public static MessageInfo? Create(MessageInfoBindingModel? model) + { + if (model == null) + { + return null; + } + return new MessageInfo() + { + 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 + }; + } +} \ No newline at end of file diff --git a/Typography/TypographyDatabaseImplement/Models/Order.cs b/Typography/TypographyDatabaseImplement/Models/Order.cs index bcc406a..6abe678 100644 --- a/Typography/TypographyDatabaseImplement/Models/Order.cs +++ b/Typography/TypographyDatabaseImplement/Models/Order.cs @@ -67,7 +67,8 @@ namespace TypographyDatabaseImplement.Models Id = Id, ClientId = ClientId, ClientFIO = Client.ClientFIO, - ImplementerId = ImplementerId, + ClientEmail = Client.Email, + ImplementerId = ImplementerId, ImplementerFIO = Implementer != null ? Implementer.ImplementerFIO : null, PrintedId = PrintedId, PrintedName = Printed.PrintedName, diff --git a/Typography/TypographyDatabaseImplement/TypographyDatabase.cs b/Typography/TypographyDatabaseImplement/TypographyDatabase.cs index 02f8300..2158b3e 100644 --- a/Typography/TypographyDatabaseImplement/TypographyDatabase.cs +++ b/Typography/TypographyDatabaseImplement/TypographyDatabase.cs @@ -10,7 +10,7 @@ namespace TypographyDatabaseImplement { if (optionsBuilder.IsConfigured == false) { - optionsBuilder.UseSqlServer(@"Data Source=localhost\SQLEXPRESS;Initial Catalog=Typograph6;Integrated Security=True;MultipleActiveResultSets=True;;TrustServerCertificate=True"); + optionsBuilder.UseSqlServer(@"Data Source=localhost\SQLEXPRESS;Initial Catalog=Typographylab7rpp;Integrated Security=True;MultipleActiveResultSets=True;;TrustServerCertificate=True"); } base.OnConfiguring(optionsBuilder); } @@ -20,5 +20,6 @@ namespace TypographyDatabaseImplement public virtual DbSet Orders { set; get; } public virtual DbSet Clients { set; get; } public virtual DbSet Implementers { set; get; } - } + public virtual DbSet Messages { set; get; } + } } \ No newline at end of file diff --git a/Typography/TypographyFileImplement/DataFileSingleton.cs b/Typography/TypographyFileImplement/DataFileSingleton.cs index 4776a8d..bc56b29 100644 --- a/Typography/TypographyFileImplement/DataFileSingleton.cs +++ b/Typography/TypographyFileImplement/DataFileSingleton.cs @@ -12,12 +12,14 @@ namespace TypographyFileImplement private readonly string PrintedFileName = "Printed.xml"; private readonly string ClientFileName = "Client.xml"; private readonly string ImplementerFileName = "Implementer.xml"; - public List Components { get; private set; } + private readonly string MessageFileName = "Message.xml"; + public List Components { get; private set; } public List Orders { get; private set; } public List Printeds { get; private set; } public List Clients { get; private set; } public List Implementers { get; private set; } - public static DataFileSingleton GetInstance() + public List Messages { get; private set; } + public static DataFileSingleton GetInstance() { if (instance == null) { @@ -30,14 +32,16 @@ namespace TypographyFileImplement public void SaveOrders() => SaveData(Orders, OrderFileName, "Orders", x => x.GetXElement); public void SaveClients() => SaveData(Clients, ClientFileName, "Clients", x => x.GetXElement); public void SaveImplementers() => SaveData(Implementers, ImplementerFileName, "Implementers", x => x.GetXElement); - private DataFileSingleton() + public void SaveMessages() => SaveData(Messages, MessageFileName, "Messages", x => x.GetXElement); + private DataFileSingleton() { Components = LoadData(ComponentFileName, "Component", x => Component.Create(x)!)!; Printeds = LoadData(PrintedFileName, "Product", x => Printed.Create(x)!)!; Orders = LoadData(OrderFileName, "Order", x => Order.Create(x)!)!; Clients = LoadData(ClientFileName, "Client", x => Client.Create(x)!)!; Implementers = LoadData(ImplementerFileName, "Implementer", x => Implementer.Create(x)!)!; - } + Messages = LoadData(MessageFileName, "Message", x => MessageInfo.Create(x)!)!; + } private static List? LoadData(string filename, string xmlNodeName, Func selectFunction) { if (File.Exists(filename)) diff --git a/Typography/TypographyFileImplement/Implements/ClientStorage.cs b/Typography/TypographyFileImplement/Implements/ClientStorage.cs index 729f3fe..e4cba7f 100644 --- a/Typography/TypographyFileImplement/Implements/ClientStorage.cs +++ b/Typography/TypographyFileImplement/Implements/ClientStorage.cs @@ -40,8 +40,9 @@ namespace TypographyFileImplement.Implements return source.Clients .FirstOrDefault(x => (model.Id.HasValue && x.Id == model.Id) || (!string.IsNullOrEmpty(model.ClientFIO) && x.ClientFIO == model.ClientFIO) || - (!string.IsNullOrEmpty(model.Email) && !string.IsNullOrEmpty(model.Password) && x.Email == model.Email && x.Password == model.Password)) - ?.GetViewModel; + (!string.IsNullOrEmpty(model.Email) && x.Email == model.Email) || + (!string.IsNullOrEmpty(model.Email) && !string.IsNullOrEmpty(model.Password) && x.Email == model.Email && x.Password == model.Password)) + ?.GetViewModel; } public ClientViewModel? Insert(ClientBindingModel model) { diff --git a/Typography/TypographyFileImplement/Implements/MessageInfoStorage.cs b/Typography/TypographyFileImplement/Implements/MessageInfoStorage.cs new file mode 100644 index 0000000..7a844af --- /dev/null +++ b/Typography/TypographyFileImplement/Implements/MessageInfoStorage.cs @@ -0,0 +1,56 @@ +using TypographyContracts.BindingModels; +using TypographyContracts.SearchModels; +using TypographyContracts.StoragesContracts; +using TypographyContracts.ViewModels; +using TypographyFileImplement.Models; + +namespace TypographyFileImplement.Implements +{ + public class MessageInfoStorage : IMessageInfoStorage + { + private readonly DataFileSingleton source; + public MessageInfoStorage() + { + source = DataFileSingleton.GetInstance(); + } + public List GetFullList() + { + return source.Messages + .Select(x => x.GetViewModel) + .ToList(); + } + public List GetFilteredList(MessageInfoSearchModel model) + { + if (!model.ClientId.HasValue) + { + return new(); + } + return source.Messages + .Where(x => x.ClientId == model.ClientId) + .Select(x => x.GetViewModel) + .ToList(); + } + public MessageInfoViewModel? GetElement(MessageInfoSearchModel model) + { + if (string.IsNullOrEmpty(model.MessageId) && !model.ClientId.HasValue) + { + return null; + } + return source.Messages + .FirstOrDefault(x => (!string.IsNullOrEmpty(model.MessageId) && x.MessageId == model.MessageId) || + (model.ClientId.HasValue && x.ClientId == model.ClientId))? + .GetViewModel; + } + public MessageInfoViewModel? Insert(MessageInfoBindingModel model) + { + var newMessage = MessageInfo.Create(model); + if (newMessage == null) + { + return null; + } + source.Messages.Add(newMessage); + source.SaveMessages(); + return newMessage.GetViewModel; + } + } +} \ No newline at end of file diff --git a/Typography/TypographyFileImplement/Implements/OrderStorage.cs b/Typography/TypographyFileImplement/Implements/OrderStorage.cs index c14f0db..c1c41b0 100644 --- a/Typography/TypographyFileImplement/Implements/OrderStorage.cs +++ b/Typography/TypographyFileImplement/Implements/OrderStorage.cs @@ -21,23 +21,24 @@ namespace TypographyFileImplement.Implements } private OrderViewModel DefineOthersNames(OrderViewModel model) { - string? clientFIO = source.Clients.FirstOrDefault(x => model.ClientId == x.Id)?.ClientFIO; - string? implementerFIO = source.Implementers.FirstOrDefault(x => model.ImplementerId == x.Id)?.ImplementerFIO; - string? printedName = source.Printeds.FirstOrDefault(x => model.PrintedId == x.Id)?.PrintedName; - if (clientFIO != null) - { - model.ClientFIO = clientFIO; - } - if (implementerFIO != null) - { - model.ImplementerFIO = implementerFIO; - } - if (printedName != null) - { - model.PrintedName = printedName; - } - return model; - } + var client = source.Clients.FirstOrDefault(x => model.ClientId == x.Id); + string? implementerFIO = source.Implementers.FirstOrDefault(x => model.ImplementerId == x.Id)?.ImplementerFIO; + string? printedName = source.Printeds.FirstOrDefault(x => model.PrintedId == x.Id)?.PrintedName; + if (client != null) + { + model.ClientFIO = client.ClientFIO; + model.ClientEmail = client.Email; + } + if (implementerFIO != null) + { + model.ImplementerFIO = implementerFIO; + } + if (printedName != null) + { + model.PrintedName = printedName; + } + return model; + } public List GetFilteredList(OrderSearchModel model) { if ((!model.DateFrom.HasValue || !model.DateTo.HasValue) && !model.ClientId.HasValue && !model.Status.HasValue) diff --git a/Typography/TypographyFileImplement/Models/MessageInfo.cs b/Typography/TypographyFileImplement/Models/MessageInfo.cs new file mode 100644 index 0000000..0952518 --- /dev/null +++ b/Typography/TypographyFileImplement/Models/MessageInfo.cs @@ -0,0 +1,65 @@ +using TypographyContracts.BindingModels; +using TypographyContracts.ViewModels; +using TypographyDataModels.Models; +using System.Xml.Linq; + +namespace TypographyFileImplement.Models +{ + public class MessageInfo : IMessageInfoModel + { + public string MessageId { get; private set; } = string.Empty; + public int? ClientId { get; private set; } + public string SenderName { get; private set; } = string.Empty; + public DateTime DateDelivery { get; private set; } + public string Subject { get; private set; } = string.Empty; + public string Body { get; private set; } = string.Empty; + public static MessageInfo? Create(MessageInfoBindingModel model) + { + if (model == null) + { + return null; + } + return new MessageInfo() + { + MessageId = model.MessageId, + ClientId = model.ClientId, + SenderName = model.SenderName, + DateDelivery = model.DateDelivery, + Subject = model.Subject, + Body = model.Body + }; + } + public static MessageInfo? Create(XElement element) + { + if (element == null) + { + return null; + } + return new MessageInfo() + { + MessageId = element.Attribute("MessageId")!.Value, + ClientId = Convert.ToInt32(element.Element("ClientId")!.Value), + SenderName = element.Element("SenderName")!.Value, + DateDelivery = Convert.ToDateTime(element.Element("DateDelivery")!.Value), + Subject = element.Element("Subject")!.Value, + Body = element.Element("Body")!.Value, + }; + } + public MessageInfoViewModel GetViewModel => new() + { + MessageId = MessageId, + ClientId = ClientId, + SenderName = SenderName, + DateDelivery = DateDelivery, + Subject = Subject, + Body = Body + }; + public XElement GetXElement => new("Message", + new XAttribute("MessageId", MessageId), + new XElement("ClientId", ClientId), + new XElement("SenderName", SenderName), + new XElement("DateDelivery", DateDelivery.ToString()), + new XElement("Subject", Subject), + new XElement("Body", Body)); + } +} \ No newline at end of file diff --git a/Typography/TypographyListImplement/DataListSingleton.cs b/Typography/TypographyListImplement/DataListSingleton.cs index c64fa22..8c04175 100644 --- a/Typography/TypographyListImplement/DataListSingleton.cs +++ b/Typography/TypographyListImplement/DataListSingleton.cs @@ -10,14 +10,16 @@ namespace TypographyListImplement public List Printeds { get; set; } public List Clients { get; set; } public List Implementers { get; set; } - private DataListSingleton() + public List Messages { get; set; } + private DataListSingleton() { Components = new List(); Orders = new List(); Printeds = new List(); Clients = new List(); Implementers = new List(); - } + Messages = new List(); + } public static DataListSingleton GetInstance() { if (_instance == null) diff --git a/Typography/TypographyListImplement/Implements/ClientStorage.cs b/Typography/TypographyListImplement/Implements/ClientStorage.cs index 212a4d2..5ba4b7d 100644 --- a/Typography/TypographyListImplement/Implements/ClientStorage.cs +++ b/Typography/TypographyListImplement/Implements/ClientStorage.cs @@ -49,8 +49,9 @@ namespace TypographyListImplement.Implements { if ((model.Id.HasValue && client.Id == model.Id) || (!string.IsNullOrEmpty(model.ClientFIO) && client.ClientFIO == model.ClientFIO) || - (!string.IsNullOrEmpty(model.Email) && !string.IsNullOrEmpty(model.Password) && client.Email == model.Email && client.Password == model.Password)) - { + (!string.IsNullOrEmpty(model.Email) && client.Email == model.Email) || + (!string.IsNullOrEmpty(model.Email) && !string.IsNullOrEmpty(model.Password) && client.Email == model.Email && client.Password == model.Password)) + { return client.GetViewModel; } } diff --git a/Typography/TypographyListImplement/Implements/MessageInfoStorage.cs b/Typography/TypographyListImplement/Implements/MessageInfoStorage.cs new file mode 100644 index 0000000..bd9f8c6 --- /dev/null +++ b/Typography/TypographyListImplement/Implements/MessageInfoStorage.cs @@ -0,0 +1,68 @@ +using TypographyContracts.BindingModels; +using TypographyContracts.SearchModels; +using TypographyContracts.StoragesContracts; +using TypographyContracts.ViewModels; +using TypographyListImplement.Models; + +namespace TypographyListImplement.Implements +{ + public class MessageInfoStorage : IMessageInfoStorage + { + private readonly DataListSingleton _source; + public MessageInfoStorage() + { + _source = DataListSingleton.GetInstance(); + } + public List GetFullList() + { + var result = new List(); + foreach (var message in _source.Messages) + { + result.Add(message.GetViewModel); + } + return result; + } + public List GetFilteredList(MessageInfoSearchModel model) + { + var result = new List(); + if (!model.ClientId.HasValue) + { + return result; + } + foreach (var message in _source.Messages) + { + if (message.ClientId == model.ClientId) + { + result.Add(message.GetViewModel); + } + } + return result; + } + public MessageInfoViewModel? GetElement(MessageInfoSearchModel model) + { + if (string.IsNullOrEmpty(model.MessageId) && !model.ClientId.HasValue) + { + return null; + } + foreach (var message in _source.Messages) + { + if ((!string.IsNullOrEmpty(model.MessageId) && message.MessageId == model.MessageId) || + (model.ClientId.HasValue && message.ClientId == model.ClientId)) + { + return message.GetViewModel; + } + } + return null; + } + public MessageInfoViewModel? Insert(MessageInfoBindingModel model) + { + var newMessage = MessageInfo.Create(model); + if (newMessage == null) + { + return null; + } + _source.Messages.Add(newMessage); + return newMessage.GetViewModel; + } + } +} \ No newline at end of file diff --git a/Typography/TypographyListImplement/Implements/OrderStorage.cs b/Typography/TypographyListImplement/Implements/OrderStorage.cs index 647fb7d..9572170 100644 --- a/Typography/TypographyListImplement/Implements/OrderStorage.cs +++ b/Typography/TypographyListImplement/Implements/OrderStorage.cs @@ -30,7 +30,8 @@ namespace TypographyListImplement.Implements if (result.ClientId == client.Id) { result.ClientFIO = client.ClientFIO; - break; + result.ClientEmail = client.Email; + break; } } foreach (var implementer in _source.Implementers) diff --git a/Typography/TypographyListImplement/Models/MessageInfo.cs b/Typography/TypographyListImplement/Models/MessageInfo.cs new file mode 100644 index 0000000..11d8ca9 --- /dev/null +++ b/Typography/TypographyListImplement/Models/MessageInfo.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TypographyContracts.BindingModels; +using TypographyContracts.ViewModels; +using TypographyDataModels.Models; + +namespace TypographyListImplement.Models +{ + public class MessageInfo : IMessageInfoModel + { + public string MessageId { get; private set; } = string.Empty; + public int? ClientId { get; private set; } + public string SenderName { get; private set; } = string.Empty; + public DateTime DateDelivery { get; private set; } + public string Subject { get; private set; } = string.Empty; + public string Body { get; private set; } = string.Empty; + public static MessageInfo? Create(MessageInfoBindingModel? model) + { + if (model == null) + { + return null; + } + return new MessageInfo() + { + 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 + }; + } +} \ No newline at end of file diff --git a/Typography/TypographyRestApi/ClientLogic.cs b/Typography/TypographyRestApi/ClientLogic.cs new file mode 100644 index 0000000..942be18 --- /dev/null +++ b/Typography/TypographyRestApi/ClientLogic.cs @@ -0,0 +1,122 @@ +using TypographyContracts.BindingModels; +using TypographyContracts.BusinessLogicsContracts; +using TypographyContracts.SearchModels; +using TypographyContracts.StoragesContracts; +using TypographyContracts.ViewModels; +using Microsoft.Extensions.Logging; +using System.Text.RegularExpressions; + +namespace TypographyBusinessLogic.BusinessLogics +{ + public class ClientLogic : IClientLogic + { + private readonly ILogger _logger; + private readonly IClientStorage _clientStorage; + public ClientLogic(ILogger logger, IClientStorage clientStorage) + { + _logger = logger; + _clientStorage = clientStorage; + } + public List? ReadList(ClientSearchModel? model) + { + _logger.LogInformation("ReadList. Id: {Id}. ClientFIO: {ClientFIO}. Email: {Email}.", + model?.Id, model?.ClientFIO, model?.Email); + var list = model == null ? _clientStorage.GetFullList() : _clientStorage.GetFilteredList(model); + if (list == null) + { + _logger.LogWarning("ReadList return null list"); + return null; + } + _logger.LogInformation("ReadList. Count: {Count}", list.Count); + return list; + } + public ClientViewModel? ReadElement(ClientSearchModel model) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + _logger.LogInformation("ReadElement. Id: {Id}. ClientFIO: {ClientFIO}. Email: {Email}.", + model?.Id, model?.ClientFIO, model?.Email); + var element = _clientStorage.GetElement(model); + if (element == null) + { + _logger.LogWarning("ReadElement element not found"); + return null; + } + _logger.LogInformation("ReadElement find. Id: {Id}", element.Id); + return element; + } + public bool Create(ClientBindingModel model) + { + CheckModel(model); + if (_clientStorage.Insert(model) == null) + { + _logger.LogWarning("Insert operation failed"); + return false; + } + return true; + } + public bool Update(ClientBindingModel model) + { + CheckModel(model); + if (_clientStorage.Update(model) == null) + { + _logger.LogWarning("Update operation failed"); + return false; + } + return true; + } + public bool Delete(ClientBindingModel model) + { + CheckModel(model, false); + _logger.LogInformation("Delete. Id: {Id}", model.Id); + if (_clientStorage.Delete(model) == null) + { + _logger.LogWarning("Delete operation failed"); + return false; + } + return true; + } + private void CheckModel(ClientBindingModel model, bool withParams = true) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + if (!withParams) + { + return; + } + if (string.IsNullOrEmpty(model.ClientFIO)) + { + throw new ArgumentNullException("Нет ФИО клиента", nameof(model.ClientFIO)); + } + if (string.IsNullOrEmpty(model.Email)) + { + throw new ArgumentNullException("Нет электронной почты клиента", nameof(model.Email)); + } + if (string.IsNullOrEmpty(model.Password)) + { + throw new ArgumentNullException("Нет пароля клиента", nameof(model.Password)); + } + if (!Regex.IsMatch(model.Email, @"^[-\w.]+@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,4}$")) + { + throw new ArgumentNullException("Введенное не является адресом электронной почты", nameof(model.Email)); + } + if (model.Password.Length < 10 || model.Password.Length > 50 || + !Regex.IsMatch(model.Password, @"^((\w+\d+\W+)|(\w+\W+\d+)|(\d+\w+\W+)|(\d+\W+\w+)|(\W+\w+\d+)|(\W+\d+\w+))[\w\d\W]*$")) + { + throw new ArgumentNullException("Пароль не соответсвует требованиям безопасности", nameof(model.Password)); + } + + _logger.LogInformation("Client. Id: {Id}. ClientFIO: {ClientFIO}. Email: {Email}.", + model?.Id, model?.ClientFIO, model?.Email); + var element = _clientStorage.GetElement(new ClientSearchModel { Email = model.Email }); + if (element != null && element.Id != model.Id) + { + throw new InvalidOperationException("Клиент с таким логином уже есть"); + } + } + } +} \ No newline at end of file diff --git a/Typography/TypographyRestApi/Controllers/ClientController.cs b/Typography/TypographyRestApi/Controllers/ClientController.cs index e8ad0fa..6a2d716 100644 --- a/Typography/TypographyRestApi/Controllers/ClientController.cs +++ b/Typography/TypographyRestApi/Controllers/ClientController.cs @@ -12,11 +12,13 @@ namespace TypographyRestApi.Controllers { private readonly ILogger _logger; private readonly IClientLogic _logic; + private readonly IMessageInfoLogic _mailLogic; - public ClientController(IClientLogic logic, ILogger logger) + public ClientController(IClientLogic logic, ILogger logger, IMessageInfoLogic mailLogic) { _logger = logger; _logic = logic; + _mailLogic = mailLogic; } [HttpGet] @@ -64,5 +66,21 @@ namespace TypographyRestApi.Controllers throw; } } + [HttpGet] + public List? GetMessages(int clientId) + { + try + { + return _mailLogic.ReadList(new MessageInfoSearchModel + { + ClientId = clientId + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка получения писем клиента"); + throw; + } + } } } \ No newline at end of file diff --git a/Typography/TypographyRestApi/Program.cs b/Typography/TypographyRestApi/Program.cs index ded48e5..abc7336 100644 --- a/Typography/TypographyRestApi/Program.cs +++ b/Typography/TypographyRestApi/Program.cs @@ -3,6 +3,8 @@ using TypographyContracts.BusinessLogicsContracts; using TypographyContracts.StoragesContracts; using TypographyDatabaseImplement.Implements; using Microsoft.OpenApi.Models; +using TypographyBusinessLogic.MailWorker; +using TypographyContracts.BindingModels; var builder = WebApplication.CreateBuilder(args); @@ -14,11 +16,15 @@ builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); +builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); +builder.Services.AddTransient(); + +builder.Services.AddSingleton(); builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle @@ -29,7 +35,16 @@ builder.Services.AddSwaggerGen(c => }); var app = builder.Build(); - +var mailSender = app.Services.GetService(); +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. if (app.Environment.IsDevelopment()) { diff --git a/Typography/TypographyRestApi/appsettings.json b/Typography/TypographyRestApi/appsettings.json index 10f68b8..6a15f44 100644 --- a/Typography/TypographyRestApi/appsettings.json +++ b/Typography/TypographyRestApi/appsettings.json @@ -5,5 +5,12 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + + "SmtpClientHost": "smtp.gmail.com", + "SmtpClientPort": "587", + "PopHost": "pop.gmail.com", + "PopPort": "995", + "MailLogin": "lawfirmlab7@gmail.com", + "MailPassword": "logf arhv rtkk rqfe" }