From dabd68f1112adb73d09dd23f0b1906a3fab66b40 Mon Sep 17 00:00:00 2001 From: May Date: Sat, 25 May 2024 21:25:00 +0400 Subject: [PATCH] PIbd22_Kamcharova_K.A_lab6 --- .../RenovationWorkContracts.dll | Bin 0 -> 30720 bytes .../RenovationWorkDataModels.dll | Bin 0 -> 6144 bytes .../RenovationWorkDatabaseImplement.dll | Bin 0 -> 75776 bytes .../RenovationWorkFileImplement.dll | Bin 0 -> 40448 bytes .../RenovationWorkListImplement.dll | Bin 0 -> 26624 bytes RenovationWork/FormImplementer.Designer.cs | 162 +++++++ RenovationWork/FormImplementer.cs | 103 +++++ RenovationWork/FormImplementer.resx | 120 +++++ RenovationWork/FormImplementers.Designer.cs | 113 +++++ RenovationWork/FormImplementers.cs | 118 +++++ RenovationWork/FormImplementers.resx | 120 +++++ RenovationWork/FormMain.Designer.cs | 434 +++++++++--------- RenovationWork/FormMain.cs | 368 ++++++++------- RenovationWork/Program.cs | 9 +- .../BusinessLogics/ImplementerLogic.cs | 126 +++++ .../BusinessLogics/OrderLogic.cs | 55 ++- .../BusinessLogics/WorkModeling.cs | 136 ++++++ .../BindingModels/ImplementerBindingModel.cs | 18 + .../BindingModels/OrderBindingModel.cs | 1 + .../IImplementerLogic.cs | 20 + .../BusinessLogicsContracts/IOrderLogic.cs | 2 +- .../BusinessLogicsContracts/IWorkProcess.cs | 13 + .../SearchModels/ImplementerSearchModel.cs | 15 + .../SearchModels/OrderSearchModel.cs | 5 +- .../StoragesContracts/IImplementerStorage.cs | 21 + .../ViewModels/ImplementerViewModel.cs | 23 + .../ViewModels/OrderViewModel.cs | 3 + .../Models/IImplementerModel.cs | 17 + .../Models/IOrderModel.cs | 1 + .../Implements/ImplementerStorage.cs | 82 ++++ .../Implements/OrderStorage.cs | 18 +- ...40501150513_addingImplementors.Designer.cs | 257 +++++++++++ .../20240501150513_addingImplementors.cs | 67 +++ .../RenovationWorkDatabaseModelSnapshot.cs | 43 ++ .../Models/Implementer.cs | 66 +++ .../Models/Order.cs | 7 + .../RenovationWorkDatabase.cs | 6 +- .../DataFileSingleton.cs | 5 + .../Implements/ImplementerStorage.cs | 79 ++++ .../Implements/OrderStorage.cs | 40 +- .../Models/Implementer.cs | 76 +++ RenovationWorkFileImplement/Models/Order.cs | 5 + .../DataListSingleton.cs | 2 + .../Implements/ImplementerStorage.cs | 102 ++++ .../Implements/OrderStorage.cs | 32 +- .../Models/Implementer.cs | 54 +++ RenovationWorkListImplement/Models/Order.cs | 12 +- .../Controllers/ImplementerController.cs | 103 +++++ 48 files changed, 2605 insertions(+), 454 deletions(-) create mode 100644 ImplementationExtensions/RenovationWorkContracts.dll create mode 100644 ImplementationExtensions/RenovationWorkDataModels.dll create mode 100644 ImplementationExtensions/RenovationWorkDatabaseImplement.dll create mode 100644 ImplementationExtensions/RenovationWorkFileImplement.dll create mode 100644 ImplementationExtensions/RenovationWorkListImplement.dll create mode 100644 RenovationWork/FormImplementer.Designer.cs create mode 100644 RenovationWork/FormImplementer.cs create mode 100644 RenovationWork/FormImplementer.resx create mode 100644 RenovationWork/FormImplementers.Designer.cs create mode 100644 RenovationWork/FormImplementers.cs create mode 100644 RenovationWork/FormImplementers.resx create mode 100644 RenovationWorkBusinessLogic/BusinessLogics/ImplementerLogic.cs create mode 100644 RenovationWorkBusinessLogic/BusinessLogics/WorkModeling.cs create mode 100644 RenovationWorkContracts/BindingModels/ImplementerBindingModel.cs create mode 100644 RenovationWorkContracts/BusinessLogicsContracts/IImplementerLogic.cs create mode 100644 RenovationWorkContracts/BusinessLogicsContracts/IWorkProcess.cs create mode 100644 RenovationWorkContracts/SearchModels/ImplementerSearchModel.cs create mode 100644 RenovationWorkContracts/StoragesContracts/IImplementerStorage.cs create mode 100644 RenovationWorkContracts/ViewModels/ImplementerViewModel.cs create mode 100644 RenovationWorkDataModels/Models/IImplementerModel.cs create mode 100644 RenovationWorkDatabaseImplement/Implements/ImplementerStorage.cs create mode 100644 RenovationWorkDatabaseImplement/Migrations/20240501150513_addingImplementors.Designer.cs create mode 100644 RenovationWorkDatabaseImplement/Migrations/20240501150513_addingImplementors.cs create mode 100644 RenovationWorkDatabaseImplement/Models/Implementer.cs create mode 100644 RenovationWorkFileImplement/Implements/ImplementerStorage.cs create mode 100644 RenovationWorkFileImplement/Models/Implementer.cs create mode 100644 RenovationWorkListImplement/Implements/ImplementerStorage.cs create mode 100644 RenovationWorkListImplement/Models/Implementer.cs create mode 100644 RenovationWorkRestApi/Controllers/ImplementerController.cs diff --git a/ImplementationExtensions/RenovationWorkContracts.dll b/ImplementationExtensions/RenovationWorkContracts.dll new file mode 100644 index 0000000000000000000000000000000000000000..357af358b80adfec3e355cdc18468dea5b0596ff GIT binary patch literal 30720 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 HE$}}8KsnD3 literal 0 HcmV?d00001 diff --git a/ImplementationExtensions/RenovationWorkDataModels.dll b/ImplementationExtensions/RenovationWorkDataModels.dll new file mode 100644 index 0000000000000000000000000000000000000000..93f5a999be4c9bdddcfea1e7c4e9f6c6d6392da0 GIT binary patch literal 6144 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 J`+qY7{|E59pFscs literal 0 HcmV?d00001 diff --git a/RenovationWork/FormImplementer.Designer.cs b/RenovationWork/FormImplementer.Designer.cs new file mode 100644 index 0000000..2c02b30 --- /dev/null +++ b/RenovationWork/FormImplementer.Designer.cs @@ -0,0 +1,162 @@ +namespace RenovationWorkView +{ + partial class FormImplementer + { + /// + /// 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() + { + textBoxFIO = new TextBox(); + textBoxPassword = new TextBox(); + textBoxQualification = new TextBox(); + textBoxWorkExperience = new TextBox(); + buttonSave = new Button(); + buttonCancel = new Button(); + labelFio = new Label(); + labelPassword = new Label(); + labelQualification = new Label(); + labelExperience = new Label(); + SuspendLayout(); + // + // textBoxFIO + // + textBoxFIO.Location = new Point(107, 6); + textBoxFIO.Name = "textBoxFIO"; + textBoxFIO.Size = new Size(384, 23); + textBoxFIO.TabIndex = 0; + // + // textBoxPassword + // + textBoxPassword.Location = new Point(107, 35); + textBoxPassword.Name = "textBoxPassword"; + textBoxPassword.Size = new Size(384, 23); + textBoxPassword.TabIndex = 1; + // + // textBoxQualification + // + textBoxQualification.Location = new Point(107, 64); + textBoxQualification.Name = "textBoxQualification"; + textBoxQualification.Size = new Size(384, 23); + textBoxQualification.TabIndex = 2; + // + // textBoxWorkExperience + // + textBoxWorkExperience.Location = new Point(107, 93); + textBoxWorkExperience.Name = "textBoxWorkExperience"; + textBoxWorkExperience.Size = new Size(384, 23); + textBoxWorkExperience.TabIndex = 3; + // + // buttonSave + // + buttonSave.Location = new Point(308, 124); + buttonSave.Name = "buttonSave"; + buttonSave.Size = new Size(75, 23); + buttonSave.TabIndex = 4; + buttonSave.Text = "Сохранить"; + buttonSave.UseVisualStyleBackColor = true; + buttonSave.Click += buttonSave_Click; + // + // buttonCancel + // + buttonCancel.Location = new Point(389, 124); + buttonCancel.Name = "buttonCancel"; + buttonCancel.Size = new Size(75, 23); + buttonCancel.TabIndex = 5; + buttonCancel.Text = "Отмена"; + buttonCancel.UseVisualStyleBackColor = true; + buttonCancel.Click += buttonCancel_Click; + // + // labelFio + // + labelFio.AutoSize = true; + labelFio.Location = new Point(12, 6); + labelFio.Name = "labelFio"; + labelFio.Size = new Size(37, 15); + labelFio.TabIndex = 6; + labelFio.Text = "ФИО:"; + // + // labelPassword + // + labelPassword.AutoSize = true; + labelPassword.Location = new Point(12, 35); + labelPassword.Name = "labelPassword"; + labelPassword.Size = new Size(52, 15); + labelPassword.TabIndex = 7; + labelPassword.Text = "Пароль:"; + // + // labelQualification + // + labelQualification.AutoSize = true; + labelQualification.Location = new Point(10, 64); + labelQualification.Name = "labelQualification"; + labelQualification.Size = new Size(91, 15); + labelQualification.TabIndex = 8; + labelQualification.Text = "Квалификация:"; + // + // labelExperience + // + labelExperience.AutoSize = true; + labelExperience.Location = new Point(12, 93); + labelExperience.Name = "labelExperience"; + labelExperience.Size = new Size(82, 15); + labelExperience.TabIndex = 9; + labelExperience.Text = "Стаж работы:"; + // + // FormImplementer + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(500, 155); + Controls.Add(labelExperience); + Controls.Add(labelQualification); + Controls.Add(labelPassword); + Controls.Add(labelFio); + Controls.Add(buttonCancel); + Controls.Add(buttonSave); + Controls.Add(textBoxWorkExperience); + Controls.Add(textBoxQualification); + Controls.Add(textBoxPassword); + Controls.Add(textBoxFIO); + Name = "FormImplementer"; + Text = "Исполнитель"; + Load += FormImplementer_Load; + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private TextBox textBoxFIO; + private TextBox textBoxPassword; + private TextBox textBoxQualification; + private TextBox textBoxWorkExperience; + private Button buttonSave; + private Button buttonCancel; + private Label labelFio; + private Label labelPassword; + private Label labelQualification; + private Label labelExperience; + } +} \ No newline at end of file diff --git a/RenovationWork/FormImplementer.cs b/RenovationWork/FormImplementer.cs new file mode 100644 index 0000000..a59f959 --- /dev/null +++ b/RenovationWork/FormImplementer.cs @@ -0,0 +1,103 @@ +using Microsoft.Extensions.Logging; +using RenovationWorkContracts.BindingModels; +using RenovationWorkContracts.BusinessLogicsContracts; +using RenovationWorkContracts.SearchModels; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace RenovationWorkView +{ + public partial class FormImplementer : Form + { + private readonly ILogger _logger; + private readonly IImplementerLogic _logic; + private int? _id; + public int Id { set { _id = value; } } + public FormImplementer(ILogger logger, IImplementerLogic logic) + { + InitializeComponent(); + _logger = logger; + _logic = logic; + } + + private void FormImplementer_Load(object sender, EventArgs e) + { + if (_id.HasValue) + { + try + { + _logger.LogInformation("Получение исполнителя"); + var view = _logic.ReadElement(new ImplementerSearchModel + { + Id = _id.Value + }); + if (view != null) + { + textBoxFIO.Text = view.ImplementerFIO; + textBoxPassword.Text = view.Password; + textBoxQualification.Text = view.Qualification.ToString(); + textBoxWorkExperience.Text = view.WorkExperience.ToString(); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка получения исполнителя"); + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, + MessageBoxIcon.Error); + } + } + } + + private void buttonSave_Click(object sender, EventArgs e) + { + if (string.IsNullOrEmpty(textBoxFIO.Text)) + { + MessageBox.Show("Заполните ФИО", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + if (string.IsNullOrEmpty(textBoxPassword.Text)) + { + MessageBox.Show("Заполните пароль", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + _logger.LogInformation("Сохранение компонента"); + try + { + var model = new ImplementerBindingModel + { + Id = _id ?? 0, + ImplementerFIO = textBoxFIO.Text, + Password = textBoxPassword.Text, + Qualification = Convert.ToInt32(textBoxQualification.Text), + WorkExperience = Convert.ToInt32(textBoxWorkExperience.Text), + }; + var operationResult = _id.HasValue ? _logic.Update(model) : _logic.Create(model); + if (!operationResult) + { + throw new Exception("Ошибка при сохранении. Дополнительная информация в логах."); + } + MessageBox.Show("Сохранение прошло успешно", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information); + DialogResult = DialogResult.OK; + Close(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка сохранения исполнителя"); + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void buttonCancel_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + } + } +} diff --git a/RenovationWork/FormImplementer.resx b/RenovationWork/FormImplementer.resx new file mode 100644 index 0000000..af32865 --- /dev/null +++ b/RenovationWork/FormImplementer.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/RenovationWork/FormImplementers.Designer.cs b/RenovationWork/FormImplementers.Designer.cs new file mode 100644 index 0000000..3767e72 --- /dev/null +++ b/RenovationWork/FormImplementers.Designer.cs @@ -0,0 +1,113 @@ +namespace RenovationWorkView +{ + partial class FormImplementers + { + /// + /// 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() + { + dataGridView = new DataGridView(); + buttonCreate = new Button(); + buttonChange = new Button(); + buttonDelete = new Button(); + buttonRefresh = new Button(); + ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit(); + SuspendLayout(); + // + // dataGridView + // + dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; + dataGridView.Location = new Point(12, 12); + dataGridView.Name = "dataGridView"; + dataGridView.RowTemplate.Height = 25; + dataGridView.Size = new Size(597, 332); + dataGridView.TabIndex = 0; + // + // buttonCreate + // + buttonCreate.Location = new Point(636, 12); + buttonCreate.Name = "buttonCreate"; + buttonCreate.Size = new Size(122, 23); + buttonCreate.TabIndex = 1; + buttonCreate.Text = "Создать"; + buttonCreate.UseVisualStyleBackColor = true; + buttonCreate.Click += buttonCreate_Click; + // + // buttonChange + // + buttonChange.Location = new Point(636, 41); + buttonChange.Name = "buttonChange"; + buttonChange.Size = new Size(122, 23); + buttonChange.TabIndex = 2; + buttonChange.Text = "Изменить"; + buttonChange.UseVisualStyleBackColor = true; + buttonChange.Click += buttonChange_Click; + // + // buttonDelete + // + buttonDelete.Location = new Point(636, 70); + buttonDelete.Name = "buttonDelete"; + buttonDelete.Size = new Size(122, 23); + buttonDelete.TabIndex = 3; + buttonDelete.Text = "Удалить"; + buttonDelete.UseVisualStyleBackColor = true; + buttonDelete.Click += buttonDelete_Click; + // + // buttonRefresh + // + buttonRefresh.Location = new Point(636, 99); + buttonRefresh.Name = "buttonRefresh"; + buttonRefresh.Size = new Size(122, 23); + buttonRefresh.TabIndex = 4; + buttonRefresh.Text = "Обновить"; + buttonRefresh.UseVisualStyleBackColor = true; + buttonRefresh.Click += buttonRefresh_Click; + // + // FormImplementers + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(779, 356); + Controls.Add(buttonRefresh); + Controls.Add(buttonDelete); + Controls.Add(buttonChange); + Controls.Add(buttonCreate); + Controls.Add(dataGridView); + Name = "FormImplementers"; + Text = "Исполнители"; + Load += FormImplementers_Load; + ((System.ComponentModel.ISupportInitialize)dataGridView).EndInit(); + ResumeLayout(false); + } + + #endregion + + private DataGridView dataGridView; + private Button buttonCreate; + private Button buttonChange; + private Button buttonDelete; + private Button buttonRefresh; + } +} \ No newline at end of file diff --git a/RenovationWork/FormImplementers.cs b/RenovationWork/FormImplementers.cs new file mode 100644 index 0000000..3e99842 --- /dev/null +++ b/RenovationWork/FormImplementers.cs @@ -0,0 +1,118 @@ +using Microsoft.Extensions.Logging; +using RenovationWorkContracts.BindingModels; +using RenovationWorkContracts.BusinessLogicsContracts; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace RenovationWorkView +{ + public partial class FormImplementers : Form + { + private readonly ILogger _logger; + private readonly IImplementerLogic _logic; + public FormImplementers(ILogger logger, IImplementerLogic logic) + { + InitializeComponent(); + _logger = logger; + _logic = logic; + } + + private void FormImplementers_Load(object sender, EventArgs e) + { + LoadData(); + } + private void LoadData() + { + try + { + var list = _logic.ReadList(null); + if (list != null) + { + dataGridView.DataSource = list; + dataGridView.Columns["Id"].Visible = false; + dataGridView.Columns["ImplementerFIO"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; + dataGridView.Columns["Password"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; + dataGridView.Columns["Qualification"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; + dataGridView.Columns["WorkExperience"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; + } + _logger.LogInformation("Загрузка компонентов"); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка загрузки исполнителей"); + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void buttonCreate_Click(object sender, EventArgs e) + { + var service = Program.ServiceProvider?.GetService(typeof(FormImplementer)); + if (service is FormImplementer form) + { + if (form.ShowDialog() == DialogResult.OK) + { + LoadData(); + } + } + } + + private void buttonChange_Click(object sender, EventArgs e) + { + if (dataGridView.SelectedRows.Count == 1) + { + var service = + Program.ServiceProvider?.GetService(typeof(FormImplementer)); + if (service is FormImplementer form) + { + form.Id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); + if (form.ShowDialog() == DialogResult.OK) + { + LoadData(); + } + } + } + } + + private void buttonDelete_Click(object sender, EventArgs e) + { + if (dataGridView.SelectedRows.Count == 1) + { + if (MessageBox.Show("Удалить запись?", "Вопрос", + MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); + _logger.LogInformation("Удаление компонента"); + try + { + if (!_logic.Delete(new ImplementerBindingModel + { + Id = id + })) + { + throw new Exception("Ошибка при удалении. Дополнительная информация в логах."); + } + LoadData(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка удаления исполнителя"); + MessageBox.Show(ex.Message, "Ошибка", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + } + + private void buttonRefresh_Click(object sender, EventArgs e) + { + LoadData(); + } + } +} diff --git a/RenovationWork/FormImplementers.resx b/RenovationWork/FormImplementers.resx new file mode 100644 index 0000000..af32865 --- /dev/null +++ b/RenovationWork/FormImplementers.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/RenovationWork/FormMain.Designer.cs b/RenovationWork/FormMain.Designer.cs index 62f16dc..011ff15 100644 --- a/RenovationWork/FormMain.Designer.cs +++ b/RenovationWork/FormMain.Designer.cs @@ -1,216 +1,234 @@ namespace RenovationWorkView { - 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() - { - menuStrip = new MenuStrip(); - refbooksToolStripMenuItem = new ToolStripMenuItem(); - componentsToolStripMenuItem = new ToolStripMenuItem(); - JobTypeToolStripMenuItem = new ToolStripMenuItem(); - ClientsToolStripMenuItem = new ToolStripMenuItem(); - отчетыToolStripMenuItem = new ToolStripMenuItem(); - listComponentsToolStripMenuItem = new ToolStripMenuItem(); - componentRepairsПоИзделиямToolStripMenuItem = new ToolStripMenuItem(); - OrdersToolStripMenuItem = new ToolStripMenuItem(); - dataGridView = new DataGridView(); - buttonCreateOrder = new Button(); - buttonTakeOrderInWork = new Button(); - buttonOrderReady = new Button(); - buttonIssuedOrder = new Button(); - buttonRef = new Button(); - menuStrip.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit(); - SuspendLayout(); - // - // menuStrip - // - menuStrip.Items.AddRange(new ToolStripItem[] { refbooksToolStripMenuItem, отчетыToolStripMenuItem }); - menuStrip.Location = new Point(0, 0); - menuStrip.Name = "menuStrip"; - menuStrip.Size = new Size(1028, 24); - menuStrip.TabIndex = 0; - menuStrip.Text = "menuStrip1"; - // - // refbooksToolStripMenuItem - // - refbooksToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { componentsToolStripMenuItem, JobTypeToolStripMenuItem, ClientsToolStripMenuItem }); - refbooksToolStripMenuItem.Name = "refbooksToolStripMenuItem"; - refbooksToolStripMenuItem.Size = new Size(94, 20); - refbooksToolStripMenuItem.Text = "Справочники"; - // - // componentsToolStripMenuItem - // - componentsToolStripMenuItem.Name = "componentsToolStripMenuItem"; - componentsToolStripMenuItem.Size = new Size(145, 22); - componentsToolStripMenuItem.Text = "Компоненты"; - componentsToolStripMenuItem.Click += componentsToolStripMenuItem_Click; - // - // JobTypeToolStripMenuItem - // - JobTypeToolStripMenuItem.Name = "JobTypeToolStripMenuItem"; - JobTypeToolStripMenuItem.Size = new Size(145, 22); - JobTypeToolStripMenuItem.Text = "Вид работы"; - JobTypeToolStripMenuItem.Click += JobTypeToolStripMenuItem_Click; - // - // ClientsToolStripMenuItem - // - ClientsToolStripMenuItem.Name = "ClientsToolStripMenuItem"; - ClientsToolStripMenuItem.Size = new Size(145, 22); - ClientsToolStripMenuItem.Text = "Клиенты"; - ClientsToolStripMenuItem.Click += ClientsToolStripMenuItem_Click; - // - // отчетыToolStripMenuItem - // - отчетыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { listComponentsToolStripMenuItem, componentRepairsПоИзделиямToolStripMenuItem, OrdersToolStripMenuItem }); - отчетыToolStripMenuItem.Name = "отчетыToolStripMenuItem"; - отчетыToolStripMenuItem.Size = new Size(60, 20); - отчетыToolStripMenuItem.Text = "Отчеты"; - // - // listComponentsToolStripMenuItem - // - listComponentsToolStripMenuItem.Name = "listComponentsToolStripMenuItem"; - listComponentsToolStripMenuItem.Size = new Size(218, 22); - listComponentsToolStripMenuItem.Text = "Список изделий"; - listComponentsToolStripMenuItem.Click += listComponentsToolStripMenuItem_Click; - // - // componentRepairsПоИзделиямToolStripMenuItem - // - componentRepairsПоИзделиямToolStripMenuItem.Name = "componentRepairsПоИзделиямToolStripMenuItem"; - componentRepairsПоИзделиямToolStripMenuItem.Size = new Size(218, 22); - componentRepairsПоИзделиямToolStripMenuItem.Text = "Компоненты по изделиям"; - componentRepairsПоИзделиямToolStripMenuItem.Click += componentRepairsПоИзделиямToolStripMenuItem_Click; - // - // OrdersToolStripMenuItem - // - OrdersToolStripMenuItem.Name = "OrdersToolStripMenuItem"; - OrdersToolStripMenuItem.Size = new Size(218, 22); - OrdersToolStripMenuItem.Text = "Список заказов"; - OrdersToolStripMenuItem.Click += OrdersToolStripMenuItem_Click; - // - // dataGridView - // - dataGridView.BackgroundColor = SystemColors.ControlLightLight; - dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; - dataGridView.Location = new Point(12, 27); - dataGridView.Name = "dataGridView"; - dataGridView.RowTemplate.Height = 25; - dataGridView.Size = new Size(853, 341); - dataGridView.TabIndex = 1; - // - // buttonCreateOrder - // - buttonCreateOrder.Location = new Point(871, 42); - buttonCreateOrder.Name = "buttonCreateOrder"; - buttonCreateOrder.Size = new Size(157, 23); - buttonCreateOrder.TabIndex = 2; - buttonCreateOrder.Text = "Создать заказ"; - buttonCreateOrder.UseVisualStyleBackColor = true; - buttonCreateOrder.Click += buttonCreateOrder_Click; - // - // buttonTakeOrderInWork - // - buttonTakeOrderInWork.Location = new Point(871, 71); - buttonTakeOrderInWork.Name = "buttonTakeOrderInWork"; - buttonTakeOrderInWork.Size = new Size(157, 23); - buttonTakeOrderInWork.TabIndex = 3; - buttonTakeOrderInWork.Text = "Отладить на выполнение"; - buttonTakeOrderInWork.UseVisualStyleBackColor = true; - buttonTakeOrderInWork.Click += buttonTakeOrderInWork_Click; - // - // buttonOrderReady - // - buttonOrderReady.Location = new Point(871, 100); - buttonOrderReady.Name = "buttonOrderReady"; - buttonOrderReady.Size = new Size(157, 23); - buttonOrderReady.TabIndex = 4; - buttonOrderReady.Text = "Заказ готов"; - buttonOrderReady.UseVisualStyleBackColor = true; - buttonOrderReady.Click += buttonOrderReady_Click; - // - // buttonIssuedOrder - // - buttonIssuedOrder.Location = new Point(871, 129); - buttonIssuedOrder.Name = "buttonIssuedOrder"; - buttonIssuedOrder.Size = new Size(157, 23); - buttonIssuedOrder.TabIndex = 5; - buttonIssuedOrder.Text = "Заказ выдан"; - buttonIssuedOrder.UseVisualStyleBackColor = true; - buttonIssuedOrder.Click += buttonIssuedOrder_Click; - // - // buttonRef - // - buttonRef.Location = new Point(871, 158); - buttonRef.Name = "buttonRef"; - buttonRef.Size = new Size(157, 23); - buttonRef.TabIndex = 6; - buttonRef.Text = "Обновить список"; - buttonRef.UseVisualStyleBackColor = true; - buttonRef.Click += buttonRef_Click; - // - // FormMain - // - AutoScaleDimensions = new SizeF(7F, 15F); - AutoScaleMode = AutoScaleMode.Font; - ClientSize = new Size(1028, 370); - Controls.Add(buttonRef); - Controls.Add(buttonIssuedOrder); - Controls.Add(buttonOrderReady); - Controls.Add(buttonTakeOrderInWork); - Controls.Add(buttonCreateOrder); - Controls.Add(dataGridView); - Controls.Add(menuStrip); - MainMenuStrip = menuStrip; - Name = "FormMain"; - Text = "Ремонтные работы"; - Load += FormMain_Load; - menuStrip.ResumeLayout(false); - menuStrip.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)dataGridView).EndInit(); - ResumeLayout(false); - PerformLayout(); - } + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + menuStrip = new MenuStrip(); + refbooksToolStripMenuItem = new ToolStripMenuItem(); + componentsToolStripMenuItem = new ToolStripMenuItem(); + JobTypeToolStripMenuItem = new ToolStripMenuItem(); + ClientsToolStripMenuItem = new ToolStripMenuItem(); + ImplementersToolStripMenuItem = new ToolStripMenuItem(); + отчетыToolStripMenuItem = new ToolStripMenuItem(); + listComponentsToolStripMenuItem = new ToolStripMenuItem(); + componentRepairsПоИзделиямToolStripMenuItem = new ToolStripMenuItem(); + OrdersToolStripMenuItem = new ToolStripMenuItem(); + StartWorkingToolStripMenuItem = new ToolStripMenuItem(); + dataGridView = new DataGridView(); + buttonCreateOrder = new Button(); + buttonTakeOrderInWork = new Button(); + buttonOrderReady = new Button(); + buttonIssuedOrder = new Button(); + buttonRef = new Button(); + menuStrip.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit(); + SuspendLayout(); + // + // menuStrip + // + menuStrip.Items.AddRange(new ToolStripItem[] { refbooksToolStripMenuItem, отчетыToolStripMenuItem, StartWorkingToolStripMenuItem }); + menuStrip.Location = new Point(0, 0); + menuStrip.Name = "menuStrip"; + menuStrip.Size = new Size(1129, 24); + menuStrip.TabIndex = 0; + menuStrip.Text = "menuStrip1"; + // + // refbooksToolStripMenuItem + // + refbooksToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { componentsToolStripMenuItem, JobTypeToolStripMenuItem, ClientsToolStripMenuItem, ImplementersToolStripMenuItem }); + refbooksToolStripMenuItem.Name = "refbooksToolStripMenuItem"; + refbooksToolStripMenuItem.Size = new Size(94, 20); + refbooksToolStripMenuItem.Text = "Справочники"; + // + // componentsToolStripMenuItem + // + componentsToolStripMenuItem.Name = "componentsToolStripMenuItem"; + componentsToolStripMenuItem.Size = new Size(149, 22); + componentsToolStripMenuItem.Text = "Компоненты"; + componentsToolStripMenuItem.Click += componentsToolStripMenuItem_Click; + // + // JobTypeToolStripMenuItem + // + JobTypeToolStripMenuItem.Name = "JobTypeToolStripMenuItem"; + JobTypeToolStripMenuItem.Size = new Size(149, 22); + JobTypeToolStripMenuItem.Text = "Вид работы"; + JobTypeToolStripMenuItem.Click += JobTypeToolStripMenuItem_Click; + // + // ClientsToolStripMenuItem + // + ClientsToolStripMenuItem.Name = "ClientsToolStripMenuItem"; + ClientsToolStripMenuItem.Size = new Size(149, 22); + ClientsToolStripMenuItem.Text = "Клиенты"; + ClientsToolStripMenuItem.Click += ClientsToolStripMenuItem_Click; + // + // ImplementersToolStripMenuItem + // + ImplementersToolStripMenuItem.Name = "ImplementersToolStripMenuItem"; + ImplementersToolStripMenuItem.Size = new Size(149, 22); + ImplementersToolStripMenuItem.Text = "Исполнители"; + ImplementersToolStripMenuItem.Click += ImplementersToolStripMenuItem_Click; + // + // отчетыToolStripMenuItem + // + отчетыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { listComponentsToolStripMenuItem, componentRepairsПоИзделиямToolStripMenuItem, OrdersToolStripMenuItem }); + отчетыToolStripMenuItem.Name = "отчетыToolStripMenuItem"; + отчетыToolStripMenuItem.Size = new Size(60, 20); + отчетыToolStripMenuItem.Text = "Отчеты"; + // + // listComponentsToolStripMenuItem + // + listComponentsToolStripMenuItem.Name = "listComponentsToolStripMenuItem"; + listComponentsToolStripMenuItem.Size = new Size(218, 22); + listComponentsToolStripMenuItem.Text = "Список изделий"; + listComponentsToolStripMenuItem.Click += listComponentsToolStripMenuItem_Click; + // + // componentRepairsПоИзделиямToolStripMenuItem + // + componentRepairsПоИзделиямToolStripMenuItem.Name = "componentRepairsПоИзделиямToolStripMenuItem"; + componentRepairsПоИзделиямToolStripMenuItem.Size = new Size(218, 22); + componentRepairsПоИзделиямToolStripMenuItem.Text = "Компоненты по изделиям"; + componentRepairsПоИзделиямToolStripMenuItem.Click += componentRepairsПоИзделиямToolStripMenuItem_Click; + // + // OrdersToolStripMenuItem + // + OrdersToolStripMenuItem.Name = "OrdersToolStripMenuItem"; + OrdersToolStripMenuItem.Size = new Size(218, 22); + OrdersToolStripMenuItem.Text = "Список заказов"; + OrdersToolStripMenuItem.Click += OrdersToolStripMenuItem_Click; + // + // StartWorkingToolStripMenuItem + // + StartWorkingToolStripMenuItem.Name = "StartWorkingToolStripMenuItem"; + StartWorkingToolStripMenuItem.Size = new Size(92, 20); + StartWorkingToolStripMenuItem.Text = "Запуск работ"; + StartWorkingToolStripMenuItem.Click += StartWorkingToolStripMenuItem_Click_1; + // + // dataGridView + // + dataGridView.BackgroundColor = SystemColors.ControlLightLight; + dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; + dataGridView.Location = new Point(12, 27); + dataGridView.Name = "dataGridView"; + dataGridView.RowTemplate.Height = 25; + dataGridView.Size = new Size(942, 341); + dataGridView.TabIndex = 1; + // + // buttonCreateOrder + // + buttonCreateOrder.Location = new Point(960, 42); + buttonCreateOrder.Name = "buttonCreateOrder"; + buttonCreateOrder.Size = new Size(157, 23); + buttonCreateOrder.TabIndex = 2; + buttonCreateOrder.Text = "Создать заказ"; + buttonCreateOrder.UseVisualStyleBackColor = true; + buttonCreateOrder.Click += buttonCreateOrder_Click; + // + // buttonTakeOrderInWork + // + buttonTakeOrderInWork.Location = new Point(960, 71); + buttonTakeOrderInWork.Name = "buttonTakeOrderInWork"; + buttonTakeOrderInWork.Size = new Size(157, 23); + buttonTakeOrderInWork.TabIndex = 3; + buttonTakeOrderInWork.Text = "Отладить на выполнение"; + buttonTakeOrderInWork.UseVisualStyleBackColor = true; + buttonTakeOrderInWork.Click += buttonTakeOrderInWork_Click; + // + // buttonOrderReady + // + buttonOrderReady.Location = new Point(960, 100); + buttonOrderReady.Name = "buttonOrderReady"; + buttonOrderReady.Size = new Size(157, 23); + buttonOrderReady.TabIndex = 4; + buttonOrderReady.Text = "Заказ готов"; + buttonOrderReady.UseVisualStyleBackColor = true; + buttonOrderReady.Click += buttonOrderReady_Click; + // + // buttonIssuedOrder + // + buttonIssuedOrder.Location = new Point(960, 129); + buttonIssuedOrder.Name = "buttonIssuedOrder"; + buttonIssuedOrder.Size = new Size(157, 23); + buttonIssuedOrder.TabIndex = 5; + buttonIssuedOrder.Text = "Заказ выдан"; + buttonIssuedOrder.UseVisualStyleBackColor = true; + buttonIssuedOrder.Click += buttonIssuedOrder_Click; + // + // buttonRef + // + buttonRef.Location = new Point(960, 158); + buttonRef.Name = "buttonRef"; + buttonRef.Size = new Size(157, 23); + buttonRef.TabIndex = 6; + buttonRef.Text = "Обновить список"; + buttonRef.UseVisualStyleBackColor = true; + buttonRef.Click += buttonRef_Click; + // + // FormMain + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(1129, 370); + Controls.Add(buttonRef); + Controls.Add(buttonIssuedOrder); + Controls.Add(buttonOrderReady); + Controls.Add(buttonTakeOrderInWork); + Controls.Add(buttonCreateOrder); + Controls.Add(dataGridView); + Controls.Add(menuStrip); + MainMenuStrip = menuStrip; + Name = "FormMain"; + Text = "Ремонтные работы"; + Load += FormMain_Load; + menuStrip.ResumeLayout(false); + menuStrip.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)dataGridView).EndInit(); + ResumeLayout(false); + PerformLayout(); + } - #endregion + #endregion - private MenuStrip menuStrip; - private ToolStripMenuItem refbooksToolStripMenuItem; - private ToolStripMenuItem componentsToolStripMenuItem; - private ToolStripMenuItem JobTypeToolStripMenuItem; - private DataGridView dataGridView; - private Button buttonCreateOrder; - private Button buttonTakeOrderInWork; - private Button buttonOrderReady; - private Button buttonIssuedOrder; - private Button buttonRef; - private ToolStripMenuItem отчетыToolStripMenuItem; - private ToolStripMenuItem listComponentsToolStripMenuItem; - private ToolStripMenuItem componentRepairsПоИзделиямToolStripMenuItem; - private ToolStripMenuItem OrdersToolStripMenuItem; - private ToolStripMenuItem ClientsToolStripMenuItem; - } + private MenuStrip menuStrip; + private ToolStripMenuItem refbooksToolStripMenuItem; + private ToolStripMenuItem componentsToolStripMenuItem; + private ToolStripMenuItem JobTypeToolStripMenuItem; + private DataGridView dataGridView; + private Button buttonCreateOrder; + private Button buttonTakeOrderInWork; + private Button buttonOrderReady; + private Button buttonIssuedOrder; + private Button buttonRef; + private ToolStripMenuItem отчетыToolStripMenuItem; + private ToolStripMenuItem listComponentsToolStripMenuItem; + private ToolStripMenuItem componentRepairsПоИзделиямToolStripMenuItem; + private ToolStripMenuItem OrdersToolStripMenuItem; + private ToolStripMenuItem ClientsToolStripMenuItem; + private ToolStripMenuItem ImplementersToolStripMenuItem; + private ToolStripMenuItem StartWorkingToolStripMenuItem; + } } \ No newline at end of file diff --git a/RenovationWork/FormMain.cs b/RenovationWork/FormMain.cs index 66c5d10..7f92ffd 100644 --- a/RenovationWork/FormMain.cs +++ b/RenovationWork/FormMain.cs @@ -14,191 +14,211 @@ using RenovationWorkBusinessLogic.BusinessLogics; namespace RenovationWorkView { - public partial class FormMain : Form - { - private readonly ILogger _logger; - private readonly IOrderLogic _orderLogic; - private readonly IReportLogic _reportLogic; - public FormMain(ILogger logger, IOrderLogic orderLogic, IReportLogic reportLogic) - { - InitializeComponent(); - _logger = logger; - _orderLogic = orderLogic; - _reportLogic = reportLogic; - } + 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() - { - _logger.LogInformation("Загрузка заказов"); - try - { - var list = _orderLogic.ReadList(null); - if (list != null) - { - dataGridView.DataSource = list; - dataGridView.Columns["RepairId"].Visible = false; - dataGridView.Columns["RepairName"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; - dataGridView.Columns["ClientId"].Visible = false; - } - } - catch (Exception ex) - { - _logger.LogError(ex, "Ошибка загрузки заказов"); - MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } + private void FormMain_Load(object sender, EventArgs e) + { + LoadData(); + } + private void LoadData() + { + _logger.LogInformation("Загрузка заказов"); + try + { + var list = _orderLogic.ReadList(null); + if (list != null) + { + dataGridView.DataSource = list; + dataGridView.Columns["RepairId"].Visible = false; + dataGridView.Columns["ImplementerId"].Visible = false; + dataGridView.Columns["ClientId"].Visible = false; + dataGridView.Columns["RepairName"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; + dataGridView.Columns["ClientFIO"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; + dataGridView.Columns["ImplementerFIO"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; + } + } + 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 componentsToolStripMenuItem_Click(object sender, EventArgs e) + { + var service = Program.ServiceProvider?.GetService(typeof(FormComponents)); + if (service is FormComponents form) + { + form.ShowDialog(); + } + } - private void JobTypeToolStripMenuItem_Click(object sender, EventArgs e) - { - var service = Program.ServiceProvider?.GetService(typeof(FormRepairs)); - if (service is FormRepairs form) - { - form.ShowDialog(); - } - } + private void JobTypeToolStripMenuItem_Click(object sender, EventArgs e) + { + var service = Program.ServiceProvider?.GetService(typeof(FormRepairs)); + if (service is FormRepairs 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 buttonCreateOrder_Click(object sender, EventArgs e) + { + var service = Program.ServiceProvider?.GetService(typeof(FormCreateOrder)); + if (service is FormCreateOrder form) + { + form.ShowDialog(); + LoadData(); + } + } - private void buttonTakeOrderInWork_Click(object sender, EventArgs e) - { - if (dataGridView.SelectedRows.Count == 1) - { - int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); - _logger.LogInformation("Заказ №{id}. Меняется статус на 'В работе'", id); - try - { - var operationResult = _orderLogic.TakeOrderInWork(new OrderBindingModel { Id = id }); - if (!operationResult) - { - throw new Exception("Ошибка при сохранении. Дополнительная информация в логах."); - } - LoadData(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Ошибка передачи заказа в работу"); - MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - } + private void buttonTakeOrderInWork_Click(object sender, EventArgs e) + { + if (dataGridView.SelectedRows.Count == 1) + { + int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); + _logger.LogInformation("Заказ №{id}. Меняется статус на 'В работе'", id); + try + { + var operationResult = _orderLogic.TakeOrderInWork(new OrderBindingModel { Id = id }); + if (!operationResult) + { + throw new Exception("Ошибка при сохранении. Дополнительная информация в логах."); + } + LoadData(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка передачи заказа в работу"); + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } - private void buttonOrderReady_Click(object sender, EventArgs e) - { - if (dataGridView.SelectedRows.Count == 1) - { - int id = - Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); - _logger.LogInformation("Заказ №{id}. Меняется статус на 'Готов'", id); - try - { - var operationResult = _orderLogic.FinishOrder(new - OrderBindingModel - { Id = id }); - if (!operationResult) - { - throw new Exception("Ошибка при сохранении. Дополнительная информация в логах."); - } - LoadData(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Ошибка отметки о готовности заказа"); - MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - } + private void buttonOrderReady_Click(object sender, EventArgs e) + { + if (dataGridView.SelectedRows.Count == 1) + { + int id = + Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); + _logger.LogInformation("Заказ №{id}. Меняется статус на 'Готов'", id); + try + { + var operationResult = _orderLogic.FinishOrder(new + OrderBindingModel + { Id = id }); + if (!operationResult) + { + throw new Exception("Ошибка при сохранении. Дополнительная информация в логах."); + } + LoadData(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка отметки о готовности заказа"); + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } - private void buttonIssuedOrder_Click(object sender, EventArgs e) - { - if (dataGridView.SelectedRows.Count == 1) - { - int id = - Convert.ToInt32(dataGridView.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 buttonIssuedOrder_Click(object sender, EventArgs e) + { + if (dataGridView.SelectedRows.Count == 1) + { + int id = + Convert.ToInt32(dataGridView.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 buttonRef_Click(object sender, EventArgs e) + { + LoadData(); + } - private void listComponentsToolStripMenuItem_Click(object sender, EventArgs e) - { - using var dialog = new SaveFileDialog { Filter = "docx|*.docx" }; - if (dialog.ShowDialog() == DialogResult.OK) - { - _reportLogic.SaveRepairsToWordFile(new ReportBindingModel - { - FileName = dialog.FileName - }); - MessageBox.Show("Выполнено", "Успех", MessageBoxButtons.OK, - MessageBoxIcon.Information); - } - } + private void listComponentsToolStripMenuItem_Click(object sender, EventArgs e) + { + using var dialog = new SaveFileDialog { Filter = "docx|*.docx" }; + if (dialog.ShowDialog() == DialogResult.OK) + { + _reportLogic.SaveRepairsToWordFile(new ReportBindingModel + { + FileName = dialog.FileName + }); + MessageBox.Show("Выполнено", "Успех", MessageBoxButtons.OK, + MessageBoxIcon.Information); + } + } - private void componentRepairsПоИзделиямToolStripMenuItem_Click(object sender, EventArgs e) - { - var service = Program.ServiceProvider?.GetService(typeof(FormReportRepairComponents)); - if (service is FormReportRepairComponents form) - { - form.ShowDialog(); - } - } + private void componentRepairsПоИзделиямToolStripMenuItem_Click(object sender, EventArgs e) + { + var service = Program.ServiceProvider?.GetService(typeof(FormReportRepairComponents)); + if (service is FormReportRepairComponents form) + { + form.ShowDialog(); + } + } - private void OrdersToolStripMenuItem_Click(object sender, EventArgs e) - { - var service = Program.ServiceProvider?.GetService(typeof(FormReportOrders)); - if (service is FormReportOrders form) - { - form.ShowDialog(); - } - } + private void OrdersToolStripMenuItem_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 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 StartWorkingToolStripMenuItem_Click_1(object sender, EventArgs e) + { + _workProcess.DoWork((Program.ServiceProvider?.GetService(typeof(IImplementerLogic)) as IImplementerLogic)!, _orderLogic); + MessageBox.Show("Процесс обработки запущен", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + } } diff --git a/RenovationWork/Program.cs b/RenovationWork/Program.cs index 186cd33..a65e4c4 100644 --- a/RenovationWork/Program.cs +++ b/RenovationWork/Program.cs @@ -7,8 +7,8 @@ using RenovationWorkDatabaseImplement.Implements; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using NLog.Extensions.Logging; -using RenovationWorkBusinessLogic.OfficePackage.Implements; -using RenovationWorkBusinessLogic.OfficePackage; +using System; + namespace RenovationWorkView { @@ -49,6 +49,9 @@ namespace RenovationWorkView services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -59,6 +62,8 @@ namespace RenovationWorkView services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); } } } \ No newline at end of file diff --git a/RenovationWorkBusinessLogic/BusinessLogics/ImplementerLogic.cs b/RenovationWorkBusinessLogic/BusinessLogics/ImplementerLogic.cs new file mode 100644 index 0000000..188d483 --- /dev/null +++ b/RenovationWorkBusinessLogic/BusinessLogics/ImplementerLogic.cs @@ -0,0 +1,126 @@ +using RenovationWorkContracts.BindingModels; +using RenovationWorkContracts.BusinessLogicsContracts; +using RenovationWorkContracts.SearchModels; +using RenovationWorkContracts.StoragesContracts; +using RenovationWorkContracts.ViewModels; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RenovationWorkBusinessLogic.BusinessLogics +{ + public class ImplementerLogic : IImplementerLogic + { + private readonly ILogger _logger; + private readonly IImplementerStorage _implementerStorage; + public ImplementerLogic(ILogger logger, IImplementerStorage implementerStorage) + { + _logger = logger; + _implementerStorage = implementerStorage; + } + public List? ReadList(ImplementerSearchModel? model) + { + _logger.LogInformation("ReadList. ImplementerFIO:{ClientFIO}. Id:{ Id}", model?.ImplementerFIO, model?.Id); + var list = model == null ? _implementerStorage.GetFullList() : _implementerStorage.GetFilteredList(model); + if (list == null) + { + _logger.LogWarning("ReadList return null list"); + return null; + } + _logger.LogInformation("ReadList. Count:{Count}", list.Count); + return list; + } + public ImplementerViewModel? ReadElement(ImplementerSearchModel model) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + _logger.LogInformation("ReadElement. ImplementerFIO:{ImplementerFIO}.Id:{ Id}", model.ImplementerFIO, model.Id); + var element = _implementerStorage.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(ImplementerBindingModel model) + { + CheckModel(model); + if (_implementerStorage.Insert(model) == null) + { + _logger.LogWarning("Insert operation failed"); + return false; + } + return true; + } + public bool Update(ImplementerBindingModel model) + { + CheckModel(model); + if (_implementerStorage.Update(model) == null) + { + _logger.LogWarning("Update operation failed"); + return false; + } + return true; + } + public bool Delete(ImplementerBindingModel model) + { + CheckModel(model, false); + _logger.LogInformation("Delete. Id:{Id}", model.Id); + if (_implementerStorage.Delete(model) == null) + { + _logger.LogWarning("Delete operation failed"); + return false; + } + return true; + } + private void CheckModel(ImplementerBindingModel model, bool withParams = + true) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + if (!withParams) + { + return; + } + if (string.IsNullOrEmpty(model.ImplementerFIO)) + { + throw new ArgumentNullException("Нет ФИО исполнителя", + nameof(model.ImplementerFIO)); + } + if (string.IsNullOrEmpty(model.Password)) + { + throw new ArgumentNullException("Нет пароля клиента", + nameof(model.Password)); + } + if (model.WorkExperience < 0) + { + throw new ArgumentNullException("Стаж меньше 0", + nameof(model.WorkExperience)); + } + if (model.Qualification < 0) + { + throw new ArgumentException("Квалификация меньше 0", nameof(model.Qualification)); + } + _logger.LogInformation("Implementer. ImplementerFIO:{ImplementerFIO}." + + "Password:{ Password}. WorkExperience:{ WorkExperience}. Qualification:{ Qualification}. Id: { Id} ", + model.ImplementerFIO, model.Password, model.WorkExperience, model.Qualification, model.Id); + var element = _implementerStorage.GetElement(new ImplementerSearchModel + { + ImplementerFIO = model.ImplementerFIO, + }); + if (element != null && element.Id != model.Id) + { + throw new InvalidOperationException("Исполнитель с таким ФИО уже есть"); + } + } + } +} \ No newline at end of file diff --git a/RenovationWorkBusinessLogic/BusinessLogics/OrderLogic.cs b/RenovationWorkBusinessLogic/BusinessLogics/OrderLogic.cs index b34651d..671942f 100644 --- a/RenovationWorkBusinessLogic/BusinessLogics/OrderLogic.cs +++ b/RenovationWorkBusinessLogic/BusinessLogics/OrderLogic.cs @@ -17,6 +17,7 @@ namespace RenovationWorkBusinessLogic.BusinessLogics { private readonly ILogger _logger; private readonly IOrderStorage _orderStorage; + static readonly object locker = new object(); public OrderLogic(ILogger logger, IOrderStorage orderStorage) { _logger = logger; @@ -41,29 +42,24 @@ namespace RenovationWorkBusinessLogic.BusinessLogics } public bool StatusUpdate(OrderBindingModel model, OrderStatus newStatus) { - var viewModel = _orderStorage.GetElement(new OrderSearchModel { Id = model.Id }); - if (viewModel == null) + CheckModel(model, false); + var element = _orderStorage.GetElement(new OrderSearchModel { Id = model.Id }); + if (element == null) { - throw new ArgumentNullException(nameof(model)); - } - if (viewModel.Status + 1 != newStatus) - { - _logger.LogWarning("Update operation failed. Order status incorrect."); + _logger.LogWarning("Read operation failed"); return false; } + if (element.Status != newStatus - 1) + { + _logger.LogWarning("Status change operation failed"); + throw new InvalidOperationException("Текущий статус заказа не может быть переведен в выбранный"); + } model.Status = newStatus; - if (model.Status == OrderStatus.Готов) model.DateImplement = DateTime.Now; - else - { - model.DateImplement = viewModel.DateImplement; - } - CheckModel(model, false); - if (_orderStorage.Update(model) == null) - { - model.Status--; - _logger.LogWarning("Update operation failed"); - return false; - } + if (model.Status == OrderStatus.Выдан) + model.DateImplement = DateTime.Now; + if (element.ImplementerId.HasValue) + model.ImplementerId = element.ImplementerId; + _orderStorage.Update(model); return true; } public bool DeliveryOrder(OrderBindingModel model) @@ -77,7 +73,26 @@ namespace RenovationWorkBusinessLogic.BusinessLogics } public bool TakeOrderInWork(OrderBindingModel model) { - return StatusUpdate(model, OrderStatus.Выполняется); + lock (locker) + { + return StatusUpdate(model, OrderStatus.Выполняется); + } + } + 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; } public List? ReadList(OrderSearchModel? model) { diff --git a/RenovationWorkBusinessLogic/BusinessLogics/WorkModeling.cs b/RenovationWorkBusinessLogic/BusinessLogics/WorkModeling.cs new file mode 100644 index 0000000..6a6cf85 --- /dev/null +++ b/RenovationWorkBusinessLogic/BusinessLogics/WorkModeling.cs @@ -0,0 +1,136 @@ +using Microsoft.Extensions.Logging; +using RenovationWorkContracts.BindingModels; +using RenovationWorkContracts.BusinessLogicsContracts; +using RenovationWorkContracts.SearchModels; +using RenovationWorkContracts.ViewModels; +using RenovationWorkDataModels.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RenovationWorkBusinessLogic.BusinessLogics +{ + public class WorkModeling : IWorkProcess + { + private readonly ILogger _logger; + private readonly Random _rnd; + private IOrderLogic? _orderLogic; + public WorkModeling(ILogger logger) + { + _logger = logger; + _rnd = new Random(1000); + } + public void DoWork(IImplementerLogic implementerLogic, IOrderLogic orderLogic) + { + _orderLogic = orderLogic; + var implementers = implementerLogic.ReadList(null); + if (implementers == null) + { + _logger.LogWarning("DoWork. Implementers is null"); + return; + } + var orders = _orderLogic.ReadList(new OrderSearchModel + { + Status = OrderStatus.Принят + }); + if (orders == null || orders.Count == 0) + { + _logger.LogWarning("DoWork. Orders is null or empty"); + return; + } + _logger.LogDebug("DoWork for {Count} orders", orders.Count); + foreach (var implementer in implementers) + { + Task.Run(() => WorkerWorkAsync(implementer, orders)); + } + } + /// Иммитация работы исполнителя + private async Task WorkerWorkAsync(ImplementerViewModel implementer, List orders) + { + if (_orderLogic == null || implementer == null) + { + return; + } + await RunOrderInWork(implementer); + await Task.Run(() => + { + foreach (var order in orders) + { + try + { + _logger.LogDebug("DoWork. Worker {Id} try get order { Order}", implementer.Id, order.Id); + // пытаемся назначить заказ на исполнителя + _orderLogic.TakeOrderInWork(new OrderBindingModel + { + Id = order.Id, + ImplementerId = implementer.Id + }); + // делаем работу + Thread.Sleep(implementer.WorkExperience * _rnd.Next(100,1000) * order.Count); + _logger.LogDebug("DoWork. Worker {Id} finish order { Order}", implementer.Id, order.Id); + _orderLogic.FinishOrder(new OrderBindingModel + { + Id = order.Id + }); + // отдыхаем + Thread.Sleep(implementer.Qualification * _rnd.Next(10, 100)); + } + // кто-то мог уже перехватить заказ, игнорируем ошибку + catch (InvalidOperationException ex) + { + _logger.LogWarning(ex, "Error try get work"); + } + // заканчиваем выполнение имитации в случае иной ошибки + catch (Exception ex) + { + _logger.LogError(ex, "Error while do work"); + throw; + } + } + }); + } + /// Ищем заказ, которые уже в работе (вдруг исполнителя прервали) + private async Task RunOrderInWork(ImplementerViewModel implementer) + { + if (_orderLogic == null || implementer == null) + { + return; + } + try + { + var runOrder = await Task.Run(() => _orderLogic.ReadElement(new OrderSearchModel + { + ImplementerId = implementer.Id, + Status = OrderStatus.Выполняется + })); + if (runOrder == null) + { + return; + } + _logger.LogDebug("DoWork. Worker {Id} back to order {Order}", implementer.Id, runOrder.Id); + // доделываем работу + Thread.Sleep(implementer.WorkExperience * _rnd.Next(100, 300) * runOrder.Count); + _logger.LogDebug("DoWork. Worker {Id} finish order {Order}", implementer.Id, runOrder.Id); + _orderLogic.FinishOrder(new OrderBindingModel + { + Id = runOrder.Id + }); + // отдыхаем + Thread.Sleep(implementer.Qualification * _rnd.Next(10, 100)); + } + // заказа может не быть, просто игнорируем ошибку + catch (InvalidOperationException ex) + { + _logger.LogWarning(ex, "Error try get work"); + } + // а может возникнуть иная ошибка, тогда просто заканчиваем выполнение имитации + catch (Exception ex) + { + _logger.LogError(ex, "Error while do work"); + throw; + } + } + } +} \ No newline at end of file diff --git a/RenovationWorkContracts/BindingModels/ImplementerBindingModel.cs b/RenovationWorkContracts/BindingModels/ImplementerBindingModel.cs new file mode 100644 index 0000000..9f8145c --- /dev/null +++ b/RenovationWorkContracts/BindingModels/ImplementerBindingModel.cs @@ -0,0 +1,18 @@ +using RenovationWorkDataModels.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RenovationWorkContracts.BindingModels +{ + public class ImplementerBindingModel : IImplementerModel + { + public int Id { get; set; } + public string ImplementerFIO { get; set; } = string.Empty; + public int WorkExperience { get; set; } = 0; + public int Qualification { get; set; } = 0; + public string Password { get; set; } = string.Empty; + } +} diff --git a/RenovationWorkContracts/BindingModels/OrderBindingModel.cs b/RenovationWorkContracts/BindingModels/OrderBindingModel.cs index 69ba6f7..13dc6d9 100644 --- a/RenovationWorkContracts/BindingModels/OrderBindingModel.cs +++ b/RenovationWorkContracts/BindingModels/OrderBindingModel.cs @@ -16,6 +16,7 @@ namespace RenovationWorkContracts.BindingModels public int ClientId { get; set; } public int Count { get; set; } public double Sum { get; set; } + public int? ImplementerId { get; set; } = null; public OrderStatus Status { get; set; } = OrderStatus.Неизвестен; public DateTime DateCreate { get; set; } = DateTime.Now; public DateTime? DateImplement { get; set; } diff --git a/RenovationWorkContracts/BusinessLogicsContracts/IImplementerLogic.cs b/RenovationWorkContracts/BusinessLogicsContracts/IImplementerLogic.cs new file mode 100644 index 0000000..38e3573 --- /dev/null +++ b/RenovationWorkContracts/BusinessLogicsContracts/IImplementerLogic.cs @@ -0,0 +1,20 @@ +using RenovationWorkContracts.BindingModels; +using RenovationWorkContracts.SearchModels; +using RenovationWorkContracts.ViewModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RenovationWorkContracts.BusinessLogicsContracts +{ + public interface IImplementerLogic + { + List? ReadList(ImplementerSearchModel? model); + ImplementerViewModel? ReadElement(ImplementerSearchModel model); + bool Create(ImplementerBindingModel model); + bool Update(ImplementerBindingModel model); + bool Delete(ImplementerBindingModel model); + } +} diff --git a/RenovationWorkContracts/BusinessLogicsContracts/IOrderLogic.cs b/RenovationWorkContracts/BusinessLogicsContracts/IOrderLogic.cs index ce60d67..0223937 100644 --- a/RenovationWorkContracts/BusinessLogicsContracts/IOrderLogic.cs +++ b/RenovationWorkContracts/BusinessLogicsContracts/IOrderLogic.cs @@ -16,6 +16,6 @@ namespace RenovationWorkContracts.BusinessLogicsContracts bool TakeOrderInWork(OrderBindingModel model); bool FinishOrder(OrderBindingModel model); bool DeliveryOrder(OrderBindingModel model); - + OrderViewModel? ReadElement(OrderSearchModel model); } } diff --git a/RenovationWorkContracts/BusinessLogicsContracts/IWorkProcess.cs b/RenovationWorkContracts/BusinessLogicsContracts/IWorkProcess.cs new file mode 100644 index 0000000..a15bf5e --- /dev/null +++ b/RenovationWorkContracts/BusinessLogicsContracts/IWorkProcess.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RenovationWorkContracts.BusinessLogicsContracts +{ + public interface IWorkProcess + { + void DoWork(IImplementerLogic implementerLogic, IOrderLogic orderLogic); + } +} \ No newline at end of file diff --git a/RenovationWorkContracts/SearchModels/ImplementerSearchModel.cs b/RenovationWorkContracts/SearchModels/ImplementerSearchModel.cs new file mode 100644 index 0000000..df42f8a --- /dev/null +++ b/RenovationWorkContracts/SearchModels/ImplementerSearchModel.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RenovationWorkContracts.SearchModels +{ + public class ImplementerSearchModel + { + public int? Id { get; set; } + public string? ImplementerFIO { get; set; } = string.Empty; + public string? Password { get; set; } = string.Empty; + } +} diff --git a/RenovationWorkContracts/SearchModels/OrderSearchModel.cs b/RenovationWorkContracts/SearchModels/OrderSearchModel.cs index 6db190e..41fbc09 100644 --- a/RenovationWorkContracts/SearchModels/OrderSearchModel.cs +++ b/RenovationWorkContracts/SearchModels/OrderSearchModel.cs @@ -1,4 +1,5 @@ -using System; +using RenovationWorkDataModels.Enums; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -12,6 +13,8 @@ namespace RenovationWorkContracts.SearchModels public DateTime? DateFrom { get; set; } public DateTime? DateTo { get; set; } public int? ClientId { get; set; } + public int? ImplementerId { get; set; } + public OrderStatus? Status { get; set; } } } diff --git a/RenovationWorkContracts/StoragesContracts/IImplementerStorage.cs b/RenovationWorkContracts/StoragesContracts/IImplementerStorage.cs new file mode 100644 index 0000000..f729d1b --- /dev/null +++ b/RenovationWorkContracts/StoragesContracts/IImplementerStorage.cs @@ -0,0 +1,21 @@ +using RenovationWorkContracts.BindingModels; +using RenovationWorkContracts.SearchModels; +using RenovationWorkContracts.ViewModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RenovationWorkContracts.StoragesContracts +{ + public interface IImplementerStorage + { + List GetFullList(); + List GetFilteredList(ImplementerSearchModel model); + ImplementerViewModel? GetElement(ImplementerSearchModel model); + ImplementerViewModel? Insert(ImplementerBindingModel model); + ImplementerViewModel? Update(ImplementerBindingModel model); + ImplementerViewModel? Delete(ImplementerBindingModel model); + } +} diff --git a/RenovationWorkContracts/ViewModels/ImplementerViewModel.cs b/RenovationWorkContracts/ViewModels/ImplementerViewModel.cs new file mode 100644 index 0000000..2f1cabd --- /dev/null +++ b/RenovationWorkContracts/ViewModels/ImplementerViewModel.cs @@ -0,0 +1,23 @@ +using RenovationWorkDataModels.Models; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RenovationWorkContracts.ViewModels +{ + public class ImplementerViewModel : IImplementerModel + { + public int Id { get; set; } + [DisplayName("ФИО исполнителя")] + public string ImplementerFIO { get; set; } = string.Empty; + [DisplayName("Стаж работы")] + public int WorkExperience { get; set; } = 0; + [DisplayName("Квалификация")] + public int Qualification { get; set; } = 0; + [DisplayName("Пароль")] + public string Password { get; set; } = string.Empty; + } +} diff --git a/RenovationWorkContracts/ViewModels/OrderViewModel.cs b/RenovationWorkContracts/ViewModels/OrderViewModel.cs index 2d488db..ff66fbf 100644 --- a/RenovationWorkContracts/ViewModels/OrderViewModel.cs +++ b/RenovationWorkContracts/ViewModels/OrderViewModel.cs @@ -14,6 +14,7 @@ namespace RenovationWorkContracts.ViewModels { [DisplayName("Номер")] public int Id { get; set; } + public int? ImplementerId { get; set; } = null; public int ClientId { get; set; } [DisplayName("Клиент")] public string ClientFIO { get; set; } = string.Empty; @@ -26,6 +27,8 @@ namespace RenovationWorkContracts.ViewModels public double Sum { get; set; } [DisplayName("Статус")] public OrderStatus Status { get; set; } = OrderStatus.Неизвестен; + [DisplayName("Исполнитель")] + public string ImplementerFIO { get; set; } = string.Empty; [DisplayName("Дата создания")] public DateTime DateCreate { get; set; } = DateTime.Now; [DisplayName("Дата выполнения")] diff --git a/RenovationWorkDataModels/Models/IImplementerModel.cs b/RenovationWorkDataModels/Models/IImplementerModel.cs new file mode 100644 index 0000000..ee8d5fa --- /dev/null +++ b/RenovationWorkDataModels/Models/IImplementerModel.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RenovationWorkDataModels.Models +{ + public interface IImplementerModel + { + string ImplementerFIO { get; } + string Password { get; } + int WorkExperience { get; } + int Qualification { get; } + + } +} diff --git a/RenovationWorkDataModels/Models/IOrderModel.cs b/RenovationWorkDataModels/Models/IOrderModel.cs index ada8324..3d137e0 100644 --- a/RenovationWorkDataModels/Models/IOrderModel.cs +++ b/RenovationWorkDataModels/Models/IOrderModel.cs @@ -13,6 +13,7 @@ namespace RenovationWorkDataModels.Models int ClientId { get; } int Count { get; } double Sum { get; } + int? ImplementerId { get; } OrderStatus Status { get; } DateTime DateCreate { get; } DateTime? DateImplement { get; } diff --git a/RenovationWorkDatabaseImplement/Implements/ImplementerStorage.cs b/RenovationWorkDatabaseImplement/Implements/ImplementerStorage.cs new file mode 100644 index 0000000..201b84e --- /dev/null +++ b/RenovationWorkDatabaseImplement/Implements/ImplementerStorage.cs @@ -0,0 +1,82 @@ +using RenovationWorkContracts.BindingModels; +using RenovationWorkContracts.SearchModels; +using RenovationWorkContracts.StoragesContracts; +using RenovationWorkContracts.ViewModels; +using RenovationWorkDatabaseImplement.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RenovationWorkDatabaseImplement.Implements +{ + public class ImplementerStorage : IImplementerStorage + { + public ImplementerViewModel? Delete(ImplementerBindingModel model) + { + using var context = new RenovationWorkDatabase(); + var res = context.Implementers.FirstOrDefault(x => x.Id == model.Id); + if (res != null) + { + context.Implementers.Remove(res); + context.SaveChanges(); + } + return res?.GetViewModel; + } + public ImplementerViewModel? GetElement(ImplementerSearchModel model) + { + if (string.IsNullOrEmpty(model.ImplementerFIO) && string.IsNullOrEmpty(model.Password) && + !model.Id.HasValue) + { + return null; + } + using var context = new RenovationWorkDatabase(); + return context.Implementers + .FirstOrDefault(x => (string.IsNullOrEmpty(model.ImplementerFIO) || x.ImplementerFIO == model.ImplementerFIO) && + (!model.Id.HasValue || x.Id == model.Id) && + (string.IsNullOrEmpty(model.Password) || x.Password == model.Password)) + ?.GetViewModel; + } + public List GetFilteredList(ImplementerSearchModel model) + { + if (model == null) + { + return new(); + } + if (model.Id.HasValue) + { + var res = GetElement(model); + return res != null ? new() { res } : new(); + } + return new(); + } + public List GetFullList() + { + using var context = new RenovationWorkDatabase(); + return context.Implementers.Select(x => x.GetViewModel).ToList(); + } + public ImplementerViewModel? Insert(ImplementerBindingModel model) + { + using var context = new RenovationWorkDatabase(); + var res = Implementer.Create(model); + if (res != null) + { + context.Implementers.Add(res); + context.SaveChanges(); + } + return res?.GetViewModel; + } + public ImplementerViewModel? Update(ImplementerBindingModel model) + { + using var context = new RenovationWorkDatabase(); + var res = context.Implementers.FirstOrDefault(x => x.Id == model.Id); + if (res != null) + { + res.Update(model); + context.SaveChanges(); + } + return res?.GetViewModel; + } + } +} \ No newline at end of file diff --git a/RenovationWorkDatabaseImplement/Implements/OrderStorage.cs b/RenovationWorkDatabaseImplement/Implements/OrderStorage.cs index c373bf3..d981203 100644 --- a/RenovationWorkDatabaseImplement/Implements/OrderStorage.cs +++ b/RenovationWorkDatabaseImplement/Implements/OrderStorage.cs @@ -20,6 +20,7 @@ namespace RenovationWorkDatabaseImplement.Implements return context.Orders .Include(x => x.Repair) .Include(x => x.Client) + .Include(x => x.Implementer) .Select(x => x.GetViewModel) .ToList(); } @@ -27,12 +28,12 @@ namespace RenovationWorkDatabaseImplement.Implements public List GetFilteredList(OrderSearchModel model) { using var context = new RenovationWorkDatabase(); - var result = context.Orders.Include(x => x.Repair).Include(x => x.Client).Where(x => ( + var result = context.Orders.Include(x => x.Repair).Include(x => x.Client).Include(x => x.Implementer).Where(x => ( (!model.Id.HasValue || x.Id == model.Id) && (!model.DateFrom.HasValue || x.DateCreate >= model.DateFrom) && (!model.DateTo.HasValue || x.DateCreate <= model.DateTo) && - (!model.ClientId.HasValue || x.ClientId == model.ClientId) - ) + (!model.ClientId.HasValue || x.ClientId == model.ClientId) && + (!model.Status.HasValue || x.Status == model.Status)) ) .Select(x => x.GetViewModel) .ToList(); @@ -46,7 +47,13 @@ namespace RenovationWorkDatabaseImplement.Implements return new(); } using var context = new RenovationWorkDatabase(); - return context.Orders.Include(x => x.Repair).Include(x => x.Client).FirstOrDefault(x => x.Id == model.Id)?.GetViewModel; + return context.Orders.Include(x => x.Repair).Include(x => x.Client) + .Include(x => x.Implementer) + .FirstOrDefault( + x => (model.Id.HasValue && x.Id == model.Id) || + (model.ImplementerId.HasValue && model.Status.HasValue && + x.ImplementerId == model.ImplementerId && x.Status == model.Status))? + .GetViewModel; } public OrderViewModel? Insert(OrderBindingModel model) @@ -69,6 +76,7 @@ namespace RenovationWorkDatabaseImplement.Implements using var context = new RenovationWorkDatabase(); var order = context.Orders.Include(x => x.Repair) .Include(x => x.Client) + .Include(x => x.Implementer) .FirstOrDefault(x => x.Id == model.Id); if (order == null) { @@ -85,6 +93,8 @@ namespace RenovationWorkDatabaseImplement.Implements var order = context.Orders .Include(x => x.Repair) .Include(x => x.Client) + .Include(x => x.Implementer) + .FirstOrDefault(rec => rec.Id == model.Id); if (order != null) { diff --git a/RenovationWorkDatabaseImplement/Migrations/20240501150513_addingImplementors.Designer.cs b/RenovationWorkDatabaseImplement/Migrations/20240501150513_addingImplementors.Designer.cs new file mode 100644 index 0000000..387a4e5 --- /dev/null +++ b/RenovationWorkDatabaseImplement/Migrations/20240501150513_addingImplementors.Designer.cs @@ -0,0 +1,257 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using RenovationWorkDatabaseImplement; + +#nullable disable + +namespace RenovationWorkDatabaseImplement_.Migrations +{ + [DbContext(typeof(RenovationWorkDatabase))] + [Migration("20240501150513_addingImplementors")] + partial class addingImplementors + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.17") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("RenovationWorkDatabaseImplement.Component", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ComponentName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Cost") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("Components"); + }); + + modelBuilder.Entity("RenovationWorkDatabaseImplement.Models.Client", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClientFIO") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Clients"); + }); + + modelBuilder.Entity("RenovationWorkDatabaseImplement.Models.Implementer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ImplementerFIO") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Qualification") + .HasColumnType("int"); + + b.Property("WorkExperience") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Implementers"); + }); + + modelBuilder.Entity("RenovationWorkDatabaseImplement.Models.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("DateCreate") + .HasColumnType("datetime2"); + + b.Property("DateImplement") + .HasColumnType("datetime2"); + + b.Property("ImplementerId") + .HasColumnType("int"); + + b.Property("RepairId") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Sum") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.HasIndex("ImplementerId"); + + b.HasIndex("RepairId"); + + b.ToTable("Orders"); + }); + + modelBuilder.Entity("RenovationWorkDatabaseImplement.Models.Repair", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Price") + .HasColumnType("float"); + + b.Property("RepairName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Repairs"); + }); + + modelBuilder.Entity("RenovationWorkDatabaseImplement.Models.RepairComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ComponentId") + .HasColumnType("int"); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("RepairId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ComponentId"); + + b.HasIndex("RepairId"); + + b.ToTable("RepairComponents"); + }); + + modelBuilder.Entity("RenovationWorkDatabaseImplement.Models.Order", b => + { + b.HasOne("RenovationWorkDatabaseImplement.Models.Client", "Client") + .WithMany("Orders") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("RenovationWorkDatabaseImplement.Models.Implementer", "Implementer") + .WithMany("Orders") + .HasForeignKey("ImplementerId"); + + b.HasOne("RenovationWorkDatabaseImplement.Models.Repair", "Repair") + .WithMany("Orders") + .HasForeignKey("RepairId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Implementer"); + + b.Navigation("Repair"); + }); + + modelBuilder.Entity("RenovationWorkDatabaseImplement.Models.RepairComponent", b => + { + b.HasOne("RenovationWorkDatabaseImplement.Component", "Component") + .WithMany("RepairComponents") + .HasForeignKey("ComponentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("RenovationWorkDatabaseImplement.Models.Repair", "Repair") + .WithMany("Components") + .HasForeignKey("RepairId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Component"); + + b.Navigation("Repair"); + }); + + modelBuilder.Entity("RenovationWorkDatabaseImplement.Component", b => + { + b.Navigation("RepairComponents"); + }); + + modelBuilder.Entity("RenovationWorkDatabaseImplement.Models.Client", b => + { + b.Navigation("Orders"); + }); + + modelBuilder.Entity("RenovationWorkDatabaseImplement.Models.Implementer", b => + { + b.Navigation("Orders"); + }); + + modelBuilder.Entity("RenovationWorkDatabaseImplement.Models.Repair", b => + { + b.Navigation("Components"); + + b.Navigation("Orders"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/RenovationWorkDatabaseImplement/Migrations/20240501150513_addingImplementors.cs b/RenovationWorkDatabaseImplement/Migrations/20240501150513_addingImplementors.cs new file mode 100644 index 0000000..a0dfbbb --- /dev/null +++ b/RenovationWorkDatabaseImplement/Migrations/20240501150513_addingImplementors.cs @@ -0,0 +1,67 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace RenovationWorkDatabaseImplement_.Migrations +{ + /// + public partial class addingImplementors : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ImplementerId", + table: "Orders", + type: "int", + nullable: true); + + migrationBuilder.CreateTable( + name: "Implementers", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ImplementerFIO = table.Column(type: "nvarchar(max)", nullable: false), + Password = table.Column(type: "nvarchar(max)", nullable: false), + Qualification = table.Column(type: "int", nullable: false), + WorkExperience = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Implementers", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_Orders_ImplementerId", + table: "Orders", + column: "ImplementerId"); + + migrationBuilder.AddForeignKey( + name: "FK_Orders_Implementers_ImplementerId", + table: "Orders", + column: "ImplementerId", + principalTable: "Implementers", + principalColumn: "Id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Orders_Implementers_ImplementerId", + table: "Orders"); + + migrationBuilder.DropTable( + name: "Implementers"); + + migrationBuilder.DropIndex( + name: "IX_Orders_ImplementerId", + table: "Orders"); + + migrationBuilder.DropColumn( + name: "ImplementerId", + table: "Orders"); + } + } +} diff --git a/RenovationWorkDatabaseImplement/Migrations/RenovationWorkDatabaseModelSnapshot.cs b/RenovationWorkDatabaseImplement/Migrations/RenovationWorkDatabaseModelSnapshot.cs index f547c48..ad47729 100644 --- a/RenovationWorkDatabaseImplement/Migrations/RenovationWorkDatabaseModelSnapshot.cs +++ b/RenovationWorkDatabaseImplement/Migrations/RenovationWorkDatabaseModelSnapshot.cs @@ -67,6 +67,33 @@ namespace RenovationWorkDatabaseImplement_.Migrations b.ToTable("Clients"); }); + modelBuilder.Entity("RenovationWorkDatabaseImplement.Models.Implementer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ImplementerFIO") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Qualification") + .HasColumnType("int"); + + b.Property("WorkExperience") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Implementers"); + }); + modelBuilder.Entity("RenovationWorkDatabaseImplement.Models.Order", b => { b.Property("Id") @@ -87,6 +114,9 @@ namespace RenovationWorkDatabaseImplement_.Migrations b.Property("DateImplement") .HasColumnType("datetime2"); + b.Property("ImplementerId") + .HasColumnType("int"); + b.Property("RepairId") .HasColumnType("int"); @@ -100,6 +130,8 @@ namespace RenovationWorkDatabaseImplement_.Migrations b.HasIndex("ClientId"); + b.HasIndex("ImplementerId"); + b.HasIndex("RepairId"); b.ToTable("Orders"); @@ -159,6 +191,10 @@ namespace RenovationWorkDatabaseImplement_.Migrations .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + b.HasOne("RenovationWorkDatabaseImplement.Models.Implementer", "Implementer") + .WithMany("Orders") + .HasForeignKey("ImplementerId"); + b.HasOne("RenovationWorkDatabaseImplement.Models.Repair", "Repair") .WithMany("Orders") .HasForeignKey("RepairId") @@ -167,6 +203,8 @@ namespace RenovationWorkDatabaseImplement_.Migrations b.Navigation("Client"); + b.Navigation("Implementer"); + b.Navigation("Repair"); }); @@ -199,6 +237,11 @@ namespace RenovationWorkDatabaseImplement_.Migrations b.Navigation("Orders"); }); + modelBuilder.Entity("RenovationWorkDatabaseImplement.Models.Implementer", b => + { + b.Navigation("Orders"); + }); + modelBuilder.Entity("RenovationWorkDatabaseImplement.Models.Repair", b => { b.Navigation("Components"); diff --git a/RenovationWorkDatabaseImplement/Models/Implementer.cs b/RenovationWorkDatabaseImplement/Models/Implementer.cs new file mode 100644 index 0000000..1a26601 --- /dev/null +++ b/RenovationWorkDatabaseImplement/Models/Implementer.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using RenovationWorkContracts.BindingModels; +using RenovationWorkDatabaseImplement.Models; +using RenovationWorkContracts.ViewModels; +using RenovationWorkDataModels.Models; + +namespace RenovationWorkDatabaseImplement.Models +{ + public class Implementer : IImplementerModel + { + public int Id { get; private set; } + [Required] + public string ImplementerFIO { get; private set; } = string.Empty; + [Required] + public string Password { get; set; } = string.Empty; + [Required] + public int Qualification { get; set; } = 0; + [Required] + public int WorkExperience { get; set; } = 0; + [ForeignKey("ImplementerId")] + public virtual List Orders { get; set; } = new(); + public static Implementer? Create(ImplementerBindingModel model) + { + if (model == null) + { + return null; + } + return new() + { + Id = model.Id, + Password = model.Password, + Qualification = model.Qualification, + ImplementerFIO = model.ImplementerFIO, + WorkExperience = model.WorkExperience, + }; + } + + public void Update(ImplementerBindingModel model) + { + if (model == null) + { + return; + } + Password = model.Password; + Qualification = model.Qualification; + ImplementerFIO = model.ImplementerFIO; + WorkExperience = model.WorkExperience; + } + + public ImplementerViewModel GetViewModel => new() + { + Id = Id, + Password = Password, + Qualification = Qualification, + ImplementerFIO = ImplementerFIO, + WorkExperience = WorkExperience, + }; + } +} + diff --git a/RenovationWorkDatabaseImplement/Models/Order.cs b/RenovationWorkDatabaseImplement/Models/Order.cs index 2fc68f9..be11f25 100644 --- a/RenovationWorkDatabaseImplement/Models/Order.cs +++ b/RenovationWorkDatabaseImplement/Models/Order.cs @@ -29,6 +29,9 @@ namespace RenovationWorkDatabaseImplement.Models [Required] public DateTime DateCreate { get; private set; } = DateTime.Now; public DateTime? DateImplement { get; private set; } + public int? ImplementerId { get; private set; } = null; + public virtual Implementer? Implementer { get; private set; } + public static Order Create(RenovationWorkDatabase context, OrderBindingModel model) { return new Order() @@ -42,6 +45,7 @@ namespace RenovationWorkDatabaseImplement.Models DateCreate = model.DateCreate, DateImplement = model.DateImplement, ClientId = model.ClientId, + ImplementerId = model.ImplementerId, }; } @@ -53,6 +57,7 @@ namespace RenovationWorkDatabaseImplement.Models } Status = model.Status; DateImplement = model.DateImplement; + ImplementerId = model.ImplementerId; } public OrderViewModel GetViewModel => new() @@ -67,6 +72,8 @@ namespace RenovationWorkDatabaseImplement.Models DateImplement = DateImplement, ClientId = ClientId, ClientFIO = Client?.ClientFIO ?? string.Empty, + ImplementerId = ImplementerId, + ImplementerFIO = Implementer != null ? Implementer.ImplementerFIO : string.Empty }; } } \ No newline at end of file diff --git a/RenovationWorkDatabaseImplement/RenovationWorkDatabase.cs b/RenovationWorkDatabaseImplement/RenovationWorkDatabase.cs index 0324070..fac9f60 100644 --- a/RenovationWorkDatabaseImplement/RenovationWorkDatabase.cs +++ b/RenovationWorkDatabaseImplement/RenovationWorkDatabase.cs @@ -3,8 +3,9 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; using RenovationWorkDatabaseImplement.Models; +using RenovationWorkDataModels.Models; +using Microsoft.EntityFrameworkCore; namespace RenovationWorkDatabaseImplement { @@ -14,7 +15,7 @@ namespace RenovationWorkDatabaseImplement { if (!optionsBuilder.IsConfigured) { - optionsBuilder.UseSqlServer(@"Data Source=localhost\SQLEXPRESS;Initial Catalog=RenovationWorkDatabase;Integrated Security=True;MultipleActiveResultSets=True;;TrustServerCertificate=True"); + optionsBuilder.UseSqlServer(@"Data Source=localhost\SQLEXPRESS;Initial Catalog=RenovationWorkDatabase_6;Integrated Security=True;MultipleActiveResultSets=True;;TrustServerCertificate=True"); } base.OnConfiguring(optionsBuilder); } @@ -23,5 +24,6 @@ namespace RenovationWorkDatabaseImplement public virtual DbSet RepairComponents { set; get; } public virtual DbSet Orders { set; get; } public virtual DbSet Clients { set; get; } + public virtual DbSet Implementers { set; get; } } } diff --git a/RenovationWorkFileImplement/DataFileSingleton.cs b/RenovationWorkFileImplement/DataFileSingleton.cs index 957a7c1..9d96db7 100644 --- a/RenovationWorkFileImplement/DataFileSingleton.cs +++ b/RenovationWorkFileImplement/DataFileSingleton.cs @@ -16,10 +16,12 @@ namespace RenovationWorkFileImplement private readonly string OrderFileName = "Order.xml"; private readonly string RepairFileName = "Repair.xml"; private readonly string ClientFileName = "Client.xml"; + private readonly string ImplementerFileName = "Implementer.xml"; public List Components { get; private set; } public List Orders { get; private set; } public List Repairs { get; private set; } public List Clients { get; private set; } + public List Implementers { get; private set; } public static DataFileSingleton GetInstance() { @@ -34,6 +36,7 @@ namespace RenovationWorkFileImplement public void SaveRepairs() => SaveData(Repairs, RepairFileName, "Repairs", x => x.GetXElement); public void SaveOrders() => SaveData(Orders, OrderFileName, "Orders", x => x.GetXElement); public void SaveClients() => SaveData(Clients, ClientFileName, "Clients", x => x.GetXElement); + public void SaveImplementers() => SaveData(Implementers, ImplementerFileName,"Implementers", x => x.GetXElement); private DataFileSingleton() { Components = LoadData(ComponentFileName, "Component", x => @@ -44,6 +47,8 @@ namespace RenovationWorkFileImplement Order.Create(x)!)!; Clients = LoadData(ClientFileName, "Client", x => Client.Create(x)!)!; + Implementers = LoadData(ImplementerFileName, "Implementer", x => + Implementer.Create(x)!)!; } private static List? LoadData(string filename, string xmlNodeName, Func selectFunction) { diff --git a/RenovationWorkFileImplement/Implements/ImplementerStorage.cs b/RenovationWorkFileImplement/Implements/ImplementerStorage.cs new file mode 100644 index 0000000..5cd3b4e --- /dev/null +++ b/RenovationWorkFileImplement/Implements/ImplementerStorage.cs @@ -0,0 +1,79 @@ +using RenovationWorkFileImplement; +using RenovationWorkContracts.BindingModels; +using RenovationWorkContracts.SearchModels; +using RenovationWorkContracts.StoragesContracts; +using RenovationWorkContracts.ViewModels; +using RenovationWorkFileImplement.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RenovationWorkFileImplement.Implements +{ + public class ImplementerStorage : IImplementerStorage + { + private readonly DataFileSingleton source; + public ImplementerStorage() + { + source = DataFileSingleton.GetInstance(); + } + public List GetFullList() + { + return source.Implementers + .Select(x => x.GetViewModel) + .ToList(); + } + public List GetFilteredList(ImplementerSearchModel model) + { + if (string.IsNullOrEmpty(model.ImplementerFIO) && string.IsNullOrEmpty(model.Password)) + { + return new(); + } + return source.Implementers + .Where(x => (string.IsNullOrEmpty(model.ImplementerFIO) || + x.ImplementerFIO.Contains(model.ImplementerFIO)) && + (string.IsNullOrEmpty(model.Password) || x.Password.Contains(model.Password))) + .Select(x => x.GetViewModel) + .ToList(); + } + public ImplementerViewModel? GetElement(ImplementerSearchModel model) + { + return source.Implementers + .FirstOrDefault(x => (string.IsNullOrEmpty(model.ImplementerFIO) || x.ImplementerFIO == model.ImplementerFIO) && + (!model.Id.HasValue || x.Id == model.Id) && (string.IsNullOrEmpty(model.Password) || x.Password == model.Password))? + .GetViewModel; + } + public ImplementerViewModel? Insert(ImplementerBindingModel model) + { + model.Id = source.Implementers.Count > 0 ? source.Implementers.Max(x => x.Id) + 1 : 1; + var newImplementer = Implementer.Create(model); + if (newImplementer == null) + return null; + source.Implementers.Add(newImplementer); + source.SaveImplementers(); + return newImplementer.GetViewModel; + } + public ImplementerViewModel? Update(ImplementerBindingModel model) + { + var implementer = source.Implementers.FirstOrDefault(x => x.Id == model.Id); + if (implementer == null) + return null; + implementer.Update(model); + source.SaveImplementers(); + return implementer.GetViewModel; + } + public ImplementerViewModel? Delete(ImplementerBindingModel model) + { + var element = source.Implementers.FirstOrDefault(rec => rec.Id == model.Id); + if (element != null) + { + source.Implementers.Remove(element); + source.SaveImplementers(); + return element.GetViewModel; + } + return null; + } + } +} diff --git a/RenovationWorkFileImplement/Implements/OrderStorage.cs b/RenovationWorkFileImplement/Implements/OrderStorage.cs index 8aa68f4..ec339c6 100644 --- a/RenovationWorkFileImplement/Implements/OrderStorage.cs +++ b/RenovationWorkFileImplement/Implements/OrderStorage.cs @@ -25,15 +25,14 @@ namespace RenovationWorkFileImplement.Implements } public List GetFilteredList(OrderSearchModel model) { - return source.Orders - .Where(x => ( - (!model.Id.HasValue || x.Id == model.Id) && - (!model.DateFrom.HasValue || x.DateCreate >= model.DateFrom) && - (!model.DateTo.HasValue || x.DateCreate <= model.DateTo) && - (!model.ClientId.HasValue || x.ClientId == model.ClientId) - ) + return source.Orders.Where(x => + (!model.Id.HasValue || x.Id == model.Id) && + (!model.DateFrom.HasValue || x.DateCreate >= model.DateFrom) && + (!model.DateTo.HasValue || x.DateCreate <= model.DateTo) && + (!model.ClientId.HasValue || x.ClientId == model.ClientId) && + (!model.Status.HasValue || x.Status == model.Status) ) - .Select(x => AccessStorage(x.GetViewModel)) + .Select(x => AccessStorage(x.GetViewModel) ?? new()) .ToList(); } public OrderViewModel? GetElement(OrderSearchModel model) @@ -42,9 +41,12 @@ namespace RenovationWorkFileImplement.Implements { return null; } - return AccessStorage(source.Orders.FirstOrDefault( - x => (model.Id.HasValue && x.Id == model.Id))?.GetViewModel - ); + return AccessStorage(source.Orders + .FirstOrDefault( + x => (model.Id.HasValue && x.Id == model.Id) || + (model.ImplementerId.HasValue && model.Status.HasValue && + x.ImplementerId == model.ImplementerId && x.Status == model.Status))? + .GetViewModel ?? new()); } public OrderViewModel? Insert(OrderBindingModel model) { @@ -83,19 +85,15 @@ namespace RenovationWorkFileImplement.Implements } public OrderViewModel? AccessStorage(OrderViewModel model) { - if (model == null) - return null; + var repair = source.Repairs.FirstOrDefault(x => x.Id == model.Id); var client = source.Clients.FirstOrDefault(x => x.Id == model.Id); + var implementer = source.Implementers.FirstOrDefault(x => x.Id == model.ImplementerId); + if (repair != null) + model.RepairName = repair.RepairName; if (client != null) model.ClientFIO = client.ClientFIO; - foreach (var Repair in source.Repairs) - { - if (Repair.Id == model.RepairId) - { - model.RepairName = Repair.RepairName; - break; - } - } + if (implementer != null) + model.ImplementerFIO = implementer.ImplementerFIO; return model; } } diff --git a/RenovationWorkFileImplement/Models/Implementer.cs b/RenovationWorkFileImplement/Models/Implementer.cs new file mode 100644 index 0000000..1e2f88b --- /dev/null +++ b/RenovationWorkFileImplement/Models/Implementer.cs @@ -0,0 +1,76 @@ +using RenovationWorkContracts.BindingModels; +using RenovationWorkContracts.ViewModels; +using RenovationWorkDataModels.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace RenovationWorkFileImplement.Models +{ + public class Implementer : IImplementerModel + { + public int Id { get; private set; } + public string ImplementerFIO { get; private set; } = string.Empty; + public string Password { get; set; } = string.Empty; + public int Qualification { get; set; } = 0; + public int WorkExperience { get; set; } = 0; + public static Implementer? Create(ImplementerBindingModel model) + { + if (model == null) + { + return null; + } + return new Implementer() + { + Id = model.Id, + ImplementerFIO = model.ImplementerFIO, + Password = model.Password, + WorkExperience = model.WorkExperience, + Qualification = model.Qualification + }; + } + public void Update(ImplementerBindingModel model) + { + if (model == null) + { + return; + } + ImplementerFIO = model.ImplementerFIO; + Password = model.Password; + WorkExperience = model.WorkExperience; + Qualification = model.Qualification; + } + public ImplementerViewModel GetViewModel => new() + { + Id = Id, + ImplementerFIO = ImplementerFIO, + Password = Password, + WorkExperience = WorkExperience, + Qualification = Qualification + }; + public static Implementer? Create(XElement element) + { + if (element == null) + { + return null; + } + return new Implementer() + { + Id = Convert.ToInt32(element.Attribute("Id")!.Value), + ImplementerFIO = element.Element("ImplementerFIO")!.Value, + Password = element.Element("Password")!.Value, + Qualification = Convert.ToInt32(element.Element("Qualification")!.Value), + WorkExperience = Convert.ToInt32(element.Element("WorkExperience")!.Value) + }; + } + public XElement GetXElement => new("Implementer", + new XAttribute("Id", Id), + new XElement("ImplementerFIO", ImplementerFIO), + new XElement("Password", Password), + new XElement("Qualification", Qualification.ToString()), + new XElement("WorkExperience", WorkExperience.ToString())); + } +} diff --git a/RenovationWorkFileImplement/Models/Order.cs b/RenovationWorkFileImplement/Models/Order.cs index c46560f..ef95ff5 100644 --- a/RenovationWorkFileImplement/Models/Order.cs +++ b/RenovationWorkFileImplement/Models/Order.cs @@ -16,6 +16,7 @@ namespace RenovationWorkFileImplement.Models public int Id { get; private set; } public int RepairId { get; private set; } public int ClientId { get; private set; } + public int? ImplementerId { get; private set; } = null; public int Count { get; private set; } public double Sum { get; private set; } public OrderStatus Status { get; private set; } @@ -32,6 +33,7 @@ namespace RenovationWorkFileImplement.Models { Id = model.Id, RepairId = model.RepairId, + ImplementerId = model.ImplementerId, ClientId = model.ClientId, Count = model.Count, Sum = model.Sum, @@ -50,6 +52,7 @@ namespace RenovationWorkFileImplement.Models { Id = Convert.ToInt32(element.Attribute("Id")!.Value), RepairId = Convert.ToInt32(element.Element("RepairId")!.Value), + ImplementerId = Convert.ToInt32(element.Element("ImplementerId")!.Value), ClientId = Convert.ToInt32(element.Element("ClientId")!.Value), Count = Convert.ToInt32(element.Element("Count")!.Value), Sum = Convert.ToDouble(element.Element("Sum")!.Value), @@ -71,6 +74,7 @@ namespace RenovationWorkFileImplement.Models { Id = Id, RepairId = RepairId, + ImplementerId = ImplementerId, ClientId = ClientId, Count = Count, Sum = Sum, @@ -82,6 +86,7 @@ namespace RenovationWorkFileImplement.Models new XAttribute("Id", Id), new XElement("RepairId", RepairId), new XElement("ClientId", ClientId), + new XElement("ImplementerId", ImplementerId), new XElement("Sum", Sum.ToString()), new XElement("Count", Count), new XElement("Status", Status.ToString()), diff --git a/RenovationWorkListImplement/DataListSingleton.cs b/RenovationWorkListImplement/DataListSingleton.cs index 1f5465d..ce09a46 100644 --- a/RenovationWorkListImplement/DataListSingleton.cs +++ b/RenovationWorkListImplement/DataListSingleton.cs @@ -14,12 +14,14 @@ namespace RenovationWorkListImplement public List Orders { get; set; } public List Repairs { get; set; } public List Clients { get; set; } + public List Implementers { get; set; } private DataListSingleton() { Components = new List(); Orders = new List(); Repairs = new List(); Clients = new List(); + Implementers = new List(); } public static DataListSingleton GetInstance() { diff --git a/RenovationWorkListImplement/Implements/ImplementerStorage.cs b/RenovationWorkListImplement/Implements/ImplementerStorage.cs new file mode 100644 index 0000000..ed13ccd --- /dev/null +++ b/RenovationWorkListImplement/Implements/ImplementerStorage.cs @@ -0,0 +1,102 @@ +using RenovationWorkContracts.BindingModels; +using RenovationWorkContracts.SearchModels; +using RenovationWorkContracts.StoragesContracts; +using RenovationWorkContracts.ViewModels; +using RenovationWorkListImplement.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RenovationWorkListImplement.Implements +{ + public class ImplementerStorage : IImplementerStorage + { + private readonly DataListSingleton _source; + public ImplementerStorage() + { + _source = DataListSingleton.GetInstance(); + } + public List GetFullList() + { + var result = new List(); + foreach (var implementer in _source.Implementers) + { + result.Add(implementer.GetViewModel); + } + return result; + } + public List GetFilteredList(ImplementerSearchModel model) + { + var result = new List(); + if (string.IsNullOrEmpty(model.ImplementerFIO) && string.IsNullOrEmpty(model.Password)) + { + return result; + } + foreach (var implementer in _source.Implementers) + { + if (model.ImplementerFIO != null && implementer.ImplementerFIO.Contains(model.ImplementerFIO)) + { + result.Add(implementer.GetViewModel); + } + } + return result; + } + public ImplementerViewModel? GetElement(ImplementerSearchModel model) + { + foreach (var implementer in _source.Implementers) + { + if ((string.IsNullOrEmpty(model.ImplementerFIO) || implementer.ImplementerFIO == model.ImplementerFIO) && + (!model.Id.HasValue || implementer.Id == model.Id) && (string.IsNullOrEmpty(model.Password) || implementer.Password == model.Password)) + { + return implementer.GetViewModel; + } + } + return null; + } + public ImplementerViewModel? Insert(ImplementerBindingModel model) + { + model.Id = 1; + foreach (var implementer in _source.Implementers) + { + if (model.Id <= implementer.Id) + { + model.Id = implementer.Id + 1; + } + } + var newImplementer = Implementer.Create(model); + if (newImplementer == null) + { + return null; + } + _source.Implementers.Add(newImplementer); + return newImplementer.GetViewModel; + } + public ImplementerViewModel? Update(ImplementerBindingModel model) + { + foreach (var implementer in _source.Implementers) + { + if (model.Id == implementer.Id) + { + implementer.Update(model); + return implementer.GetViewModel; + } + } + return null; + } + public ImplementerViewModel? Delete(ImplementerBindingModel model) + { + for (int i = 0; i < _source.Implementers.Count; ++i) + { + if (_source.Implementers[i].Id == model.Id) + { + var element = _source.Implementers[i]; + _source.Implementers.RemoveAt(i); + return element.GetViewModel; + } + } + return null; + } + } +} diff --git a/RenovationWorkListImplement/Implements/OrderStorage.cs b/RenovationWorkListImplement/Implements/OrderStorage.cs index 9779a84..83cf16e 100644 --- a/RenovationWorkListImplement/Implements/OrderStorage.cs +++ b/RenovationWorkListImplement/Implements/OrderStorage.cs @@ -30,7 +30,8 @@ namespace RenovationWorkListImplement.Implements if ((!model.Id.HasValue || order.Id == model.Id) && (!model.DateFrom.HasValue || order.DateCreate >= model.DateFrom) && (!model.DateTo.HasValue || order.DateCreate <= model.DateTo) && - (!model.ClientId.HasValue || order.ClientId == model.ClientId)) + (!model.ClientId.HasValue || order.ClientId == model.ClientId) && + (!model.Status.HasValue || order.Status == model.Status)) { result.Add(AccessStorage(order.GetViewModel)); } @@ -45,13 +46,12 @@ namespace RenovationWorkListImplement.Implements } foreach (var order in _source.Orders) { - if ((model.Id.HasValue && order.Id == model.Id)) + if ((model.Id.HasValue && order.Id == model.Id) || + (model.ImplementerId.HasValue && model.Status.HasValue && + order.ImplementerId == model.ImplementerId && order.Status == model.Status)) { - OrderViewModel thisorder = order.GetViewModel; - Repair? repair = _source.Repairs.Find(x => x.Id == order.RepairId); - string repairName = repair?.RepairName ?? string.Empty; - thisorder.RepairName = repairName; - return thisorder; + return order.GetViewModel; + return AccessStorage(order.GetViewModel); } } return null; @@ -101,17 +101,17 @@ namespace RenovationWorkListImplement.Implements } public OrderViewModel AccessStorage(OrderViewModel model) { - var client = _source.Clients.FirstOrDefault(x => x.Id == model.ClientId); + if (model == null) + return null; + var repair = _source.Repairs.FirstOrDefault(x => x.Id == model.Id); + var client = _source.Clients.FirstOrDefault(x => x.Id == model.Id); + var implementer = _source.Implementers.FirstOrDefault(x => x.Id == model.ImplementerId); + if (repair != null) + model.RepairName = repair.RepairName; if (client != null) model.ClientFIO = client.ClientFIO; - foreach (var Manufacture in _source.Repairs) - { - if (Manufacture.Id == model.RepairId) - { - model.RepairName = Manufacture.RepairName; - break; - } - } + if (implementer != null) + model.ImplementerFIO = implementer.ImplementerFIO; return model; } } diff --git a/RenovationWorkListImplement/Models/Implementer.cs b/RenovationWorkListImplement/Models/Implementer.cs new file mode 100644 index 0000000..e8d57b8 --- /dev/null +++ b/RenovationWorkListImplement/Models/Implementer.cs @@ -0,0 +1,54 @@ +using RenovationWorkContracts.BindingModels; +using RenovationWorkContracts.ViewModels; +using RenovationWorkDataModels.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RenovationWorkListImplement.Models +{ + public class Implementer : IImplementerModel + { + public int Id { get; private set; } + public string ImplementerFIO { get; private set; } = string.Empty; + public string Password { get; set; } = string.Empty; + public int WorkExperience { get; set; } = 0; + public int Qualification { get; set; } = 0; + public static Implementer? Create(ImplementerBindingModel model) + { + if (model == null) + { + return null; + } + return new Implementer() + { + Id = model.Id, + ImplementerFIO = model.ImplementerFIO, + Password = model.Password, + WorkExperience = model.WorkExperience, + Qualification = model.Qualification + }; + } + public void Update(ImplementerBindingModel model) + { + if (model == null) + { + return; + } + ImplementerFIO = model.ImplementerFIO; + Password = model.Password; + WorkExperience = model.WorkExperience; + Qualification = model.Qualification; + } + public ImplementerViewModel GetViewModel => new() + { + Id = Id, + ImplementerFIO = ImplementerFIO, + Password = Password, + WorkExperience = WorkExperience, + Qualification = Qualification + }; + } +} diff --git a/RenovationWorkListImplement/Models/Order.cs b/RenovationWorkListImplement/Models/Order.cs index 899faea..e167db6 100644 --- a/RenovationWorkListImplement/Models/Order.cs +++ b/RenovationWorkListImplement/Models/Order.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Text; using System.Threading.Tasks; using RenovationWorkContracts.BindingModels; @@ -13,12 +14,10 @@ namespace RenovationWorkListImplement.Models public class Order : IOrderModel { public int Id { get; private set; } - public int RepairId { get; private set; } public int ClientId { get; private set; } - + public int? ImplementerId { get; private set; } public int Count { get; private set; } - public double Sum { get; private set; } public OrderStatus Status { get; set; } = OrderStatus.Неизвестен; @@ -42,7 +41,8 @@ namespace RenovationWorkListImplement.Models Sum = model.Sum, Status = model.Status, DateCreate = model.DateCreate, - DateImplement = model.DateImplement + DateImplement = model.DateImplement, + ImplementerId = model.ImplementerId }; } public void Update(OrderBindingModel? model) @@ -55,6 +55,7 @@ namespace RenovationWorkListImplement.Models if (model.DateImplement != null) { DateImplement = model.DateImplement; + ImplementerId = model.ImplementerId; } } public OrderViewModel GetViewModel => new() @@ -66,7 +67,8 @@ namespace RenovationWorkListImplement.Models Sum = Sum, Status = Status, DateCreate = DateCreate, - DateImplement = DateImplement + DateImplement = DateImplement, + ImplementerId = ImplementerId, }; } } diff --git a/RenovationWorkRestApi/Controllers/ImplementerController.cs b/RenovationWorkRestApi/Controllers/ImplementerController.cs new file mode 100644 index 0000000..c3be0d8 --- /dev/null +++ b/RenovationWorkRestApi/Controllers/ImplementerController.cs @@ -0,0 +1,103 @@ +using RenovationWorkContracts.BindingModels; +using RenovationWorkContracts.BusinessLogicsContracts; +using RenovationWorkContracts.SearchModels; +using RenovationWorkContracts.ViewModels; +using RenovationWorkDataModels.Enums; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System; + +namespace RenovationWorkRestApi.Controllers +{ + [Route("api/[controller]/[action]")] + [ApiController] + public class ImplementerController : ControllerBase + { + private readonly ILogger _logger; + private readonly IOrderLogic _order; + private readonly IImplementerLogic _logic; + public ImplementerController(IOrderLogic order, IImplementerLogic logic, ILogger logger) + { + _logger = logger; + _order = order; + _logic = logic; + } + [HttpGet] + public ImplementerViewModel? Login(string login, string password) + { + try + { + return _logic.ReadElement(new ImplementerSearchModel + { + ImplementerFIO = login, + Password = password + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка авторизации сотрудника"); + throw; + } + } + [HttpGet] + public List? GetNewOrders() + { + try + { + return _order.ReadList(new OrderSearchModel + { + Status = OrderStatus.Принят + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка получения новых заказов"); + throw; + } + } + [HttpGet] + public OrderViewModel? GetImplementerOrder(int implementerId) + { + try + { + return _order.ReadElement(new OrderSearchModel + { + ImplementerId = implementerId + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка получения текущего заказа исполнителя"); + + throw; + } + } + + [HttpPost] + public void TakeOrderInWork(OrderBindingModel model) + { + try + { + _order.TakeOrderInWork(model); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка перевода заказа с №{Id} в работу", model.Id); + throw; + } + } + [HttpPost] + public void FinishOrder(OrderBindingModel model) + { + try + { + _order.FinishOrder(model); + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка отметки о готовности заказа с №{ Id}", model.Id); + throw; + } + } + } +} \ No newline at end of file