add forms, logic interfaces and implements, controller

fix storage implements, contracts
full lab6
This commit is contained in:
DavidMakarov 2024-04-18 22:03:18 +04:00
parent d74d872e8a
commit 1726a3c9d7
27 changed files with 1333 additions and 62 deletions

View File

@ -0,0 +1,172 @@
namespace FlowerShopView
{
partial class FormImplementer
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
FioTextBox = new TextBox();
FioLabel = new Label();
PasswordTextBox = new TextBox();
PasswordLabel = new Label();
WorkExperienceLabel = new Label();
WorkExperienceNumericUpDown = new NumericUpDown();
QualificationNumericUpDown = new NumericUpDown();
QualificationLabel = new Label();
CancelButton = new Button();
SaveButton = new Button();
((System.ComponentModel.ISupportInitialize)WorkExperienceNumericUpDown).BeginInit();
((System.ComponentModel.ISupportInitialize)QualificationNumericUpDown).BeginInit();
SuspendLayout();
//
// FioTextBox
//
FioTextBox.Location = new Point(137, 9);
FioTextBox.Margin = new Padding(3, 2, 3, 2);
FioTextBox.Name = "FioTextBox";
FioTextBox.Size = new Size(335, 23);
FioTextBox.TabIndex = 3;
//
// FioLabel
//
FioLabel.AutoSize = true;
FioLabel.Location = new Point(10, 12);
FioLabel.Name = "FioLabel";
FioLabel.Size = new Size(112, 15);
FioLabel.TabIndex = 2;
FioLabel.Text = "ФИО исполнителя:";
//
// PasswordTextBox
//
PasswordTextBox.Location = new Point(137, 40);
PasswordTextBox.Margin = new Padding(3, 2, 3, 2);
PasswordTextBox.Name = "PasswordTextBox";
PasswordTextBox.Size = new Size(335, 23);
PasswordTextBox.TabIndex = 5;
//
// PasswordLabel
//
PasswordLabel.AutoSize = true;
PasswordLabel.Location = new Point(10, 43);
PasswordLabel.Name = "PasswordLabel";
PasswordLabel.Size = new Size(52, 15);
PasswordLabel.TabIndex = 4;
PasswordLabel.Text = "Пароль:";
//
// WorkExperienceLabel
//
WorkExperienceLabel.AutoSize = true;
WorkExperienceLabel.Location = new Point(10, 75);
WorkExperienceLabel.Name = "WorkExperienceLabel";
WorkExperienceLabel.Size = new Size(84, 15);
WorkExperienceLabel.TabIndex = 6;
WorkExperienceLabel.Text = "Опыт работы:";
//
// WorkExperienceNumericUpDown
//
WorkExperienceNumericUpDown.Location = new Point(137, 73);
WorkExperienceNumericUpDown.Margin = new Padding(3, 2, 3, 2);
WorkExperienceNumericUpDown.Name = "WorkExperienceNumericUpDown";
WorkExperienceNumericUpDown.Size = new Size(108, 23);
WorkExperienceNumericUpDown.TabIndex = 8;
//
// QualificationNumericUpDown
//
QualificationNumericUpDown.Location = new Point(137, 106);
QualificationNumericUpDown.Margin = new Padding(3, 2, 3, 2);
QualificationNumericUpDown.Name = "QualificationNumericUpDown";
QualificationNumericUpDown.Size = new Size(108, 23);
QualificationNumericUpDown.TabIndex = 10;
//
// QualificationLabel
//
QualificationLabel.AutoSize = true;
QualificationLabel.Location = new Point(10, 108);
QualificationLabel.Name = "QualificationLabel";
QualificationLabel.Size = new Size(91, 15);
QualificationLabel.TabIndex = 9;
QualificationLabel.Text = "Квалификация:";
//
// CancelButton
//
CancelButton.Location = new Point(353, 142);
CancelButton.Margin = new Padding(3, 2, 3, 2);
CancelButton.Name = "CancelButton";
CancelButton.Size = new Size(119, 30);
CancelButton.TabIndex = 12;
CancelButton.Text = "Отмена";
CancelButton.UseVisualStyleBackColor = true;
CancelButton.Click += CancelButton_Click;
//
// SaveButton
//
SaveButton.Location = new Point(233, 142);
SaveButton.Margin = new Padding(3, 2, 3, 2);
SaveButton.Name = "SaveButton";
SaveButton.Size = new Size(114, 30);
SaveButton.TabIndex = 11;
SaveButton.Text = "Сохранить";
SaveButton.UseVisualStyleBackColor = true;
SaveButton.Click += SaveButton_Click;
//
// FormImplementer
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(482, 183);
Controls.Add(CancelButton);
Controls.Add(SaveButton);
Controls.Add(QualificationNumericUpDown);
Controls.Add(QualificationLabel);
Controls.Add(WorkExperienceNumericUpDown);
Controls.Add(WorkExperienceLabel);
Controls.Add(PasswordTextBox);
Controls.Add(PasswordLabel);
Controls.Add(FioTextBox);
Controls.Add(FioLabel);
Margin = new Padding(3, 2, 3, 2);
Name = "FormImplementer";
Text = "Исполнитель";
Load += FormImplementer_Load;
((System.ComponentModel.ISupportInitialize)WorkExperienceNumericUpDown).EndInit();
((System.ComponentModel.ISupportInitialize)QualificationNumericUpDown).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
private TextBox FioTextBox;
private Label FioLabel;
private TextBox PasswordTextBox;
private Label PasswordLabel;
private Label WorkExperienceLabel;
private NumericUpDown WorkExperienceNumericUpDown;
private NumericUpDown QualificationNumericUpDown;
private Label QualificationLabel;
private Button CancelButton;
private Button SaveButton;
}
}

View File

@ -0,0 +1,105 @@
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.BusinessLogicsContracts;
using FlowerShopContracts.SearchModels;
using Microsoft.Extensions.Logging;
namespace FlowerShopView
{
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<FormImplementer> 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)
{
FioTextBox.Text = View.ImplementerFIO;
PasswordTextBox.Text = View.Password;
WorkExperienceNumericUpDown.Value = View.WorkExperience;
QualificationNumericUpDown.Value = View.Qualification;
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка получения исполнителя");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void SaveButton_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(FioTextBox.Text))
{
MessageBox.Show("Заполните ФИО", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (string.IsNullOrEmpty(PasswordTextBox.Text))
{
MessageBox.Show("Заполните пароль", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
_logger.LogInformation("Сохранение исполнителя");
try
{
var Model = new ImplementerBindingModel
{
Id = _id ?? 0,
ImplementerFIO = FioTextBox.Text,
Password = PasswordTextBox.Text,
WorkExperience = (int)WorkExperienceNumericUpDown.Value,
Qualification = (int)QualificationNumericUpDown.Value
};
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 CancelButton_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
Close();
}
}
}

View File

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

View File

@ -0,0 +1,135 @@
namespace FlowerShopView
{
partial class FormImplementers
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
ToolsPanel = new Panel();
RefreshButton = new Button();
DeleteButton = new Button();
UpdateButton = new Button();
AddButton = new Button();
DataGridView = new DataGridView();
ToolsPanel.SuspendLayout();
((System.ComponentModel.ISupportInitialize)DataGridView).BeginInit();
SuspendLayout();
//
// ToolsPanel
//
ToolsPanel.Controls.Add(RefreshButton);
ToolsPanel.Controls.Add(DeleteButton);
ToolsPanel.Controls.Add(UpdateButton);
ToolsPanel.Controls.Add(AddButton);
ToolsPanel.Location = new Point(532, 9);
ToolsPanel.Margin = new Padding(3, 2, 3, 2);
ToolsPanel.Name = "ToolsPanel";
ToolsPanel.Size = new Size(116, 320);
ToolsPanel.TabIndex = 3;
//
// RefreshButton
//
RefreshButton.Location = new Point(3, 126);
RefreshButton.Margin = new Padding(3, 2, 3, 2);
RefreshButton.Name = "RefreshButton";
RefreshButton.Size = new Size(110, 27);
RefreshButton.TabIndex = 3;
RefreshButton.Text = "Обновить";
RefreshButton.UseVisualStyleBackColor = true;
RefreshButton.Click += RefreshButton_Click;
//
// DeleteButton
//
DeleteButton.Location = new Point(3, 84);
DeleteButton.Margin = new Padding(3, 2, 3, 2);
DeleteButton.Name = "DeleteButton";
DeleteButton.Size = new Size(110, 27);
DeleteButton.TabIndex = 2;
DeleteButton.Text = "Удалить";
DeleteButton.UseVisualStyleBackColor = true;
DeleteButton.Click += DeleteButton_Click;
//
// UpdateButton
//
UpdateButton.Location = new Point(3, 42);
UpdateButton.Margin = new Padding(3, 2, 3, 2);
UpdateButton.Name = "UpdateButton";
UpdateButton.Size = new Size(110, 27);
UpdateButton.TabIndex = 1;
UpdateButton.Text = "Изменить";
UpdateButton.UseVisualStyleBackColor = true;
UpdateButton.Click += UpdateButton_Click;
//
// AddButton
//
AddButton.Location = new Point(3, 2);
AddButton.Margin = new Padding(3, 2, 3, 2);
AddButton.Name = "AddButton";
AddButton.Size = new Size(110, 27);
AddButton.TabIndex = 0;
AddButton.Text = "Добавить";
AddButton.UseVisualStyleBackColor = true;
AddButton.Click += AddButton_Click;
//
// DataGridView
//
DataGridView.AllowUserToAddRows = false;
DataGridView.AllowUserToDeleteRows = false;
DataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
DataGridView.Location = new Point(10, 9);
DataGridView.Margin = new Padding(3, 2, 3, 2);
DataGridView.Name = "DataGridView";
DataGridView.ReadOnly = true;
DataGridView.RowHeadersWidth = 51;
DataGridView.RowTemplate.Height = 29;
DataGridView.Size = new Size(516, 320);
DataGridView.TabIndex = 2;
//
// FormImplementers
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(653, 338);
Controls.Add(ToolsPanel);
Controls.Add(DataGridView);
Margin = new Padding(3, 2, 3, 2);
Name = "FormImplementers";
Text = "Исполнители";
Load += FormImplementers_Load;
ToolsPanel.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)DataGridView).EndInit();
ResumeLayout(false);
}
#endregion
private Panel ToolsPanel;
private Button RefreshButton;
private Button DeleteButton;
private Button UpdateButton;
private Button AddButton;
private DataGridView DataGridView;
}
}

View File

@ -0,0 +1,111 @@
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.BusinessLogicsContracts;
using Microsoft.Extensions.Logging;
namespace FlowerShopView
{
public partial class FormImplementers : Form
{
private readonly ILogger _logger;
private readonly IImplementerLogic _implementerLogic;
public FormImplementers(ILogger<FormImplementers> Logger, IImplementerLogic ImplementerLogic)
{
InitializeComponent();
_logger = Logger;
_implementerLogic = ImplementerLogic;
}
private void LoadData()
{
try
{
var List = _implementerLogic.ReadList(null);
if (List != null)
{
DataGridView.DataSource = List;
DataGridView.Columns["Id"].Visible = false;
DataGridView.Columns["ImplementerFIO"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
_logger.LogInformation("Загрузка исполнителей");
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка загрузки исполнителей");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void FormImplementers_Load(object sender, EventArgs e)
{
LoadData();
}
private void AddButton_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 UpdateButton_Click(object sender, EventArgs e)
{
if (DataGridView.SelectedRows.Count == 1)
{
var service = Program.ServiceProvider?.GetService(typeof(FormImplementers));
if (service is FormImplementer Form)
{
Form.Id = Convert.ToInt32(DataGridView.SelectedRows[0].Cells["Id"].Value);
if (Form.ShowDialog() == DialogResult.OK)
{
LoadData();
}
}
}
}
private void DeleteButton_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 (!_implementerLogic.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 RefreshButton_Click(object sender, EventArgs e)
{
LoadData();
}
}
}

View File

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

View File

@ -32,6 +32,8 @@
справочникиToolStripMenuItem = new ToolStripMenuItem();
ЦветыToolStripMenuItem = new ToolStripMenuItem();
КомпонентыToolStripMenuItem = new ToolStripMenuItem();
клиентыToolStripMenuItem = new ToolStripMenuItem();
исполнителиToolStripMenuItem = new ToolStripMenuItem();
отчётыToolStripMenuItem = new ToolStripMenuItem();
списокЦветковToolStripMenuItem = new ToolStripMenuItem();
компонентыПоЦветамToolStripMenuItem = new ToolStripMenuItem();
@ -39,17 +41,15 @@
dataGridView = new DataGridView();
buttonCreateOrder = new Button();
buttonTakeOrderInWork = new Button();
buttonOrderReady = new Button();
buttonIssuedOrder = new Button();
buttonRef = new Button();
клиентыToolStripMenuItem = new ToolStripMenuItem();
запускToolStripMenuItem = new ToolStripMenuItem();
menuStrip1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
SuspendLayout();
//
// menuStrip1
//
menuStrip1.Items.AddRange(new ToolStripItem[] { справочникиToolStripMenuItem, отчётыToolStripMenuItem });
menuStrip1.Items.AddRange(new ToolStripItem[] { справочникиToolStripMenuItem, отчётыToolStripMenuItem, запускToolStripMenuItem });
menuStrip1.Location = new Point(0, 0);
menuStrip1.Name = "menuStrip1";
menuStrip1.Size = new Size(964, 24);
@ -58,7 +58,7 @@
//
// справочникиToolStripMenuItem
//
справочникиToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { ЦветыToolStripMenuItem, КомпонентыToolStripMenuItem, клиентыToolStripMenuItem });
справочникиToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { ЦветыToolStripMenuItem, КомпонентыToolStripMenuItem, клиентыToolStripMenuItem, исполнителиToolStripMenuItem });
справочникиToolStripMenuItem.Name = "справочникиToolStripMenuItem";
справочникиToolStripMenuItem.Size = new Size(94, 20);
справочникиToolStripMenuItem.Text = "Справочники";
@ -77,6 +77,20 @@
КомпонентыToolStripMenuItem.Text = "Компоненты";
КомпонентыToolStripMenuItem.Click += КомпонентыToolStripMenuItem_Click;
//
// клиентыToolStripMenuItem
//
клиентыToolStripMenuItem.Name = "клиентыToolStripMenuItem";
клиентыToolStripMenuItem.Size = new Size(180, 22);
клиентыToolStripMenuItem.Text = "Клиенты";
клиентыToolStripMenuItem.Click += клиентыToolStripMenuItem_Click;
//
// исполнителиToolStripMenuItem
//
исполнителиToolStripMenuItem.Name = сполнителиToolStripMenuItem";
исполнителиToolStripMenuItem.Size = new Size(180, 22);
исполнителиToolStripMenuItem.Text = "Исполнители";
исполнителиToolStripMenuItem.Click += исполнителиToolStripMenuItem_Click;
//
// отчётыToolStripMenuItem
//
отчётыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { списокЦветковToolStripMenuItem, компонентыПоЦветамToolStripMenuItem, списокЗаказовToolStripMenuItem });
@ -129,48 +143,28 @@
//
buttonTakeOrderInWork.Location = new Point(775, 110);
buttonTakeOrderInWork.Name = "buttonTakeOrderInWork";
buttonTakeOrderInWork.Size = new Size(158, 34);
buttonTakeOrderInWork.Size = new Size(158, 32);
buttonTakeOrderInWork.TabIndex = 3;
buttonTakeOrderInWork.Text = "Отдать на выполнение";
buttonTakeOrderInWork.UseVisualStyleBackColor = true;
buttonTakeOrderInWork.Click += ButtonTakeOrderInWork_Click;
//
// buttonOrderReady
//
buttonOrderReady.Location = new Point(775, 168);
buttonOrderReady.Name = "buttonOrderReady";
buttonOrderReady.Size = new Size(158, 34);
buttonOrderReady.TabIndex = 4;
buttonOrderReady.Text = "Заказ готов";
buttonOrderReady.UseVisualStyleBackColor = true;
buttonOrderReady.Click += ButtonOrderReady_Click;
//
// buttonIssuedOrder
//
buttonIssuedOrder.Location = new Point(775, 230);
buttonIssuedOrder.Name = "buttonIssuedOrder";
buttonIssuedOrder.Size = new Size(158, 34);
buttonIssuedOrder.TabIndex = 5;
buttonIssuedOrder.Text = "Заказ выдан";
buttonIssuedOrder.UseVisualStyleBackColor = true;
buttonIssuedOrder.Click += ButtonIssuedOrder_Click;
//
// buttonRef
//
buttonRef.Location = new Point(775, 289);
buttonRef.Location = new Point(775, 165);
buttonRef.Name = "buttonRef";
buttonRef.Size = new Size(158, 34);
buttonRef.Size = new Size(158, 32);
buttonRef.TabIndex = 6;
buttonRef.Text = "Обновить список";
buttonRef.UseVisualStyleBackColor = true;
buttonRef.Click += ButtonRef_Click;
//
// клиентыToolStripMenuItem
// запускToolStripMenuItem
//
клиентыToolStripMenuItem.Name = "клиентыToolStripMenuItem";
клиентыToolStripMenuItem.Size = new Size(180, 22);
клиентыToolStripMenuItem.Text = "Клиенты";
клиентыToolStripMenuItem.Click += клиентыToolStripMenuItem_Click;
запускToolStripMenuItem.Name = апускToolStripMenuItem";
запускToolStripMenuItem.Size = new Size(92, 20);
запускToolStripMenuItem.Text = "Запуск работ";
запускToolStripMenuItem.Click += запускToolStripMenuItem_Click;
//
// FormMain
//
@ -178,8 +172,6 @@
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(964, 450);
Controls.Add(buttonRef);
Controls.Add(buttonIssuedOrder);
Controls.Add(buttonOrderReady);
Controls.Add(buttonTakeOrderInWork);
Controls.Add(buttonCreateOrder);
Controls.Add(dataGridView);
@ -204,13 +196,13 @@
private DataGridView dataGridView;
private Button buttonCreateOrder;
private Button buttonTakeOrderInWork;
private Button buttonOrderReady;
private Button buttonIssuedOrder;
private Button buttonRef;
private ToolStripMenuItem отчётыToolStripMenuItem;
private ToolStripMenuItem списокЦветковToolStripMenuItem;
private ToolStripMenuItem компонентыПоЦветамToolStripMenuItem;
private ToolStripMenuItem списокЗаказовToolStripMenuItem;
private ToolStripMenuItem клиентыToolStripMenuItem;
private ToolStripMenuItem исполнителиToolStripMenuItem;
private ToolStripMenuItem запускToolStripMenuItem;
}
}

View File

@ -10,12 +10,14 @@ namespace FlowerShopView
private readonly ILogger _logger;
private readonly IOrderLogic _orderLogic;
private readonly IReportLogic _reportLogic;
public FormMain(ILogger<FormMain> logger, IOrderLogic orderLogic, IReportLogic reportLogic)
private readonly IWorkProcess _workProcess;
public FormMain(ILogger<FormMain> logger, IOrderLogic orderLogic, IReportLogic reportLogic, IWorkProcess workProcess)
{
InitializeComponent();
_logger = logger;
_orderLogic = orderLogic;
_reportLogic = reportLogic;
_workProcess = workProcess;
}
private void FormMain_Load(object sender, EventArgs e)
{
@ -32,8 +34,10 @@ namespace FlowerShopView
dataGridView.DataSource = list;
dataGridView.Columns["FlowerId"].Visible = false;
dataGridView.Columns["ClientId"].Visible = false;
dataGridView.Columns["ImplementerId"].Visible = false;
dataGridView.Columns["FlowerName"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridView.Columns["ClientFIO"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridView.Columns["ImplementerFIO"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
}
catch (Exception ex)
@ -179,11 +183,26 @@ namespace FlowerShopView
private void клиентыToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormClients)) ;
var service = Program.ServiceProvider?.GetService(typeof(FormClients));
if (service is FormClients form)
{
form.ShowDialog();
}
}
private void исполнителиToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormImplementers));
if (service is FormImplementers form)
{
form.ShowDialog();
}
}
private void запускToolStripMenuItem_Click(object sender, EventArgs e)
{
_workProcess.DoWork((Program.ServiceProvider?.GetService(typeof(IImplementerLogic)) as IImplementerLogic)!, _orderLogic);
MessageBox.Show("Процесс обработки запущен", "Сообщение",MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}

View File

@ -39,12 +39,15 @@ namespace FlowerShopView
services.AddTransient<IOrderStorage, OrderStorage>();
services.AddTransient<IFlowerStorage, FlowerStorage>();
services.AddTransient<IClientStorage, ClientStorage>();
services.AddTransient<IImplementerStorage, ImplementerStorage>();
services.AddTransient<IComponentLogic, ComponentLogic>();
services.AddTransient<IOrderLogic, OrderLogic>();
services.AddTransient<IFlowerLogic, FlowerLogic>();
services.AddTransient<IReportLogic, ReportLogic>();
services.AddTransient<IClientLogic, ClientLogic>();
services.AddTransient<IImplementerLogic, ImplementerLogic>();
services.AddTransient<IWorkProcess, WorkModeling>();
services.AddTransient<AbstractSaveToExcel, SaveToExcel>();
services.AddTransient<AbstractSaveToPdf, SaveToPdf>();
@ -60,6 +63,8 @@ namespace FlowerShopView
services.AddTransient<FormReportOrders>();
services.AddTransient<FormReportFlowerComponents>();
services.AddTransient<FormClients>();
services.AddTransient<FormImplementer>();
services.AddTransient<FormImplementers>();
}
}
}

View File

@ -0,0 +1,128 @@
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.BusinessLogicsContracts;
using FlowerShopContracts.SearchModels;
using FlowerShopContracts.StoragesContracts;
using FlowerShopContracts.ViewModels;
using Microsoft.Extensions.Logging;
namespace FlowerShopBusinessLogic.BusinessLogics
{
public class ImplementerLogic : IImplementerLogic
{
private readonly ILogger _logger;
private readonly IImplementerStorage _implementerStorage;
public ImplementerLogic(ILogger<IImplementerLogic> Logger, IImplementerStorage ImplementerStorage)
{
_logger = Logger;
_implementerStorage = ImplementerStorage;
}
public List<ImplementerViewModel>? ReadList(ImplementerSearchModel? Model)
{
_logger.LogInformation("ReadList. ImplementerFIO: {ImplementerFIO}. Password: {Password}. Id: {Id}",
Model?.ImplementerFIO, Model?.Password?.Length, 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 is null)
{
throw new ArgumentNullException(nameof(Model));
}
_logger.LogInformation("ReadElement. ImplementerFIO: {ImplementerFIO}. Password: {Password}. Id: {Id}",
Model?.ImplementerFIO, Model?.Password?.Length, 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("Стаж должен быть неотрицательным целым числом", nameof(Model.WorkExperience));
if (Model.Qualification < 0)
throw new ArgumentNullException("Квалификация должна быть неотрицательным целым числом", 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 Implementer = _implementerStorage.GetElement(new ImplementerSearchModel
{
ImplementerFIO = Model.ImplementerFIO
});
if (Implementer != null && Implementer.Id != Model.Id)
{
throw new InvalidOperationException("Исполнитель с таким ФИО уже есть");
}
}
}
}

View File

@ -1,4 +1,5 @@
using FlowerShopContracts.BindingModels;
using DocumentFormat.OpenXml.EMMA;
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.BusinessLogicsContracts;
using FlowerShopContracts.SearchModels;
using FlowerShopContracts.StoragesContracts;
@ -12,6 +13,7 @@ namespace FlowerShopBusinessLogic.BusinessLogics
{
private readonly ILogger _logger;
private readonly IOrderStorage _orderStorage;
static readonly object _locker = new object();
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage)
{
_logger = logger;
@ -29,7 +31,28 @@ namespace FlowerShopBusinessLogic.BusinessLogics
_logger.LogInformation("ReadList. Count:{Count}", list.Count);
return list;
}
public bool CreateOrder(OrderBindingModel model)
public OrderViewModel? ReadElement(OrderSearchModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("ReadList. ClientId: {ClientId}. Status: {Status}. ImplementerId: {ImplementerId}. DateFrom: {DateFrom}. DateTo: {DateTo}. OrderId: {Id}",
model?.ClientId, model?.Status, model?.ImplementerId, model?.DateFrom, model?.DateTo, model?.Id);
var Order = _orderStorage.GetElement(model);
if (Order == null)
{
_logger.LogWarning("ReadElement element not found");
return null;
}
_logger.LogInformation("ReadElement find. Id: {Id}", Order.Id);
return Order;
}
public bool CreateOrder(OrderBindingModel model)
{
CheckModel(model);
if (model.Status != OrderStatus.Неизвестен)
@ -45,7 +68,10 @@ namespace FlowerShopBusinessLogic.BusinessLogics
}
public bool TakeOrderInWork(OrderBindingModel model)
{
return ToNextStatus(model, OrderStatus.Выполняется);
lock (_locker)
{
return ToNextStatus(model, OrderStatus.Выполняется);
}
}
public bool FinishOrder(OrderBindingModel model)
{
@ -71,7 +97,9 @@ namespace FlowerShopBusinessLogic.BusinessLogics
model.FlowerId = element.FlowerId;
model.DateCreate = element.DateCreate;
model.DateImplement = element.DateImplement;
model.Status = element.Status;
model.ClientId = element.ClientId;
model.ImplementerId = element.ImplementerId;
model.Status = element.Status;
model.Count = element.Count;
model.Sum = element.Sum;

View File

@ -0,0 +1,120 @@
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.BusinessLogicsContracts;
using FlowerShopContracts.SearchModels;
using FlowerShopContracts.ViewModels;
using FlowerShopDataModels.Enums;
using Microsoft.Extensions.Logging;
namespace FlowerShopBusinessLogic.BusinessLogics
{
public class WorkModeling : IWorkProcess
{
private readonly ILogger _logger;
private readonly Random _rnd;
private IOrderLogic? _orderLogic;
public WorkModeling(ILogger<WorkModeling> 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<OrderViewModel> 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
});
}
catch (InvalidOperationException ex)
{
_logger.LogWarning(ex, "Error try get work");
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while do work");
throw;
}
Thread.Sleep(implementer.Qualification * _rnd.Next(10, 100));
}
});
}
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;
}
}
}
}

View File

@ -8,7 +8,7 @@ namespace FlowerShopContracts.BindingModels
public int Id { get; set; }
public int FlowerId { get; set; }
public int ClientId { get; set; }
public int ImplementerId { get; set; } = 0;
public int? ImplementerId { get; set; }
public int Count { get; set; }
public double Sum { get; set; }
public OrderStatus Status { get; set; } = OrderStatus.Неизвестен;

View File

@ -7,6 +7,7 @@ namespace FlowerShopContracts.BusinessLogicsContracts
public interface IOrderLogic
{
List<OrderViewModel>? ReadList(OrderSearchModel? model);
OrderViewModel? ReadElement(OrderSearchModel? model);
bool CreateOrder(OrderBindingModel model);
bool TakeOrderInWork(OrderBindingModel model);
bool FinishOrder(OrderBindingModel model);

View File

@ -0,0 +1,8 @@
namespace FlowerShopContracts.BusinessLogicsContracts
{
public interface IWorkProcess
{
void DoWork(IImplementerLogic implementerLogic, IOrderLogic orderLogic);
}
}

View File

@ -10,7 +10,7 @@ namespace FlowerShopContracts.ViewModels
public int Id { get; set; }
public int FlowerId { get; set; }
public int ClientId { get; set; }
public int ImplementerId { get; set; } = 0;
public int? ImplementerId { get; set; }
[DisplayName("Изделие")]
public string FlowerName { get; set; } = string.Empty;
[DisplayName("ФИО клиента")]

View File

@ -6,7 +6,7 @@ namespace FlowerShopDataModels.Models
{
int FlowerId { get; }
int ClientId { get; }
int ImplementerId { get; }
int? ImplementerId { get; }
int Count { get; }
double Sum { get; }
OrderStatus Status { get; }

View File

@ -21,8 +21,4 @@
<ProjectReference Include="..\FlowerShopDataModels\FlowerShopDataModels.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Migrations\" />
</ItemGroup>
</Project>

View File

@ -17,10 +17,6 @@ namespace FlowerShopDatabaseImplement.Implements
}
public List<OrderViewModel> GetFilteredList(OrderSearchModel model)
{
if (!model.Id.HasValue && !model.DateFrom.HasValue && !model.DateTo.HasValue && !model.ClientId.HasValue)
{
return new();
}
using var context = new FlowerShopDatabase();
if (model.DateFrom.HasValue)
return context.Orders

View File

@ -12,8 +12,8 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace FlowerShopDatabaseImplement.Migrations
{
[DbContext(typeof(FlowerShopDatabase))]
[Migration("20240404125520_initcreate")]
partial class initcreate
[Migration("20240418172148_InitCreate")]
partial class InitCreate
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
@ -115,6 +115,33 @@ namespace FlowerShopDatabaseImplement.Migrations
b.ToTable("FlowerComponents");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.Implementer", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ImplementerFIO")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Qualification")
.HasColumnType("integer");
b.Property<int>("WorkExperience")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("Implementers");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.Order", b =>
{
b.Property<int>("Id")
@ -138,6 +165,9 @@ namespace FlowerShopDatabaseImplement.Migrations
b.Property<int>("FlowerId")
.HasColumnType("integer");
b.Property<int?>("ImplementerId")
.HasColumnType("integer");
b.Property<int>("Status")
.HasColumnType("integer");
@ -148,6 +178,8 @@ namespace FlowerShopDatabaseImplement.Migrations
b.HasIndex("FlowerId");
b.HasIndex("ImplementerId");
b.ToTable("Orders");
});
@ -177,6 +209,10 @@ namespace FlowerShopDatabaseImplement.Migrations
.HasForeignKey("FlowerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("FlowerShopDatabaseImplement.Models.Implementer", null)
.WithMany("Order")
.HasForeignKey("ImplementerId");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.Component", b =>
@ -190,6 +226,11 @@ namespace FlowerShopDatabaseImplement.Migrations
b.Navigation("Orders");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.Implementer", b =>
{
b.Navigation("Order");
});
#pragma warning restore 612, 618
}
}

View File

@ -6,7 +6,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace FlowerShopDatabaseImplement.Migrations
{
public partial class initcreate : Migration
public partial class InitCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
@ -53,6 +53,22 @@ namespace FlowerShopDatabaseImplement.Migrations
table.PrimaryKey("PK_Flowers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Implementers",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
ImplementerFIO = table.Column<string>(type: "text", nullable: false),
Password = table.Column<string>(type: "text", nullable: false),
WorkExperience = table.Column<int>(type: "integer", nullable: false),
Qualification = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Implementers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "FlowerComponents",
columns: table => new
@ -88,6 +104,7 @@ namespace FlowerShopDatabaseImplement.Migrations
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
FlowerId = table.Column<int>(type: "integer", nullable: false),
ClientId = table.Column<int>(type: "integer", nullable: false),
ImplementerId = table.Column<int>(type: "integer", nullable: true),
Count = table.Column<int>(type: "integer", nullable: false),
Sum = table.Column<double>(type: "double precision", nullable: false),
Status = table.Column<int>(type: "integer", nullable: false),
@ -103,6 +120,11 @@ namespace FlowerShopDatabaseImplement.Migrations
principalTable: "Flowers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Orders_Implementers_ImplementerId",
column: x => x.ImplementerId,
principalTable: "Implementers",
principalColumn: "Id");
});
migrationBuilder.CreateIndex(
@ -119,6 +141,11 @@ namespace FlowerShopDatabaseImplement.Migrations
name: "IX_Orders_FlowerId",
table: "Orders",
column: "FlowerId");
migrationBuilder.CreateIndex(
name: "IX_Orders_ImplementerId",
table: "Orders",
column: "ImplementerId");
}
protected override void Down(MigrationBuilder migrationBuilder)
@ -137,6 +164,9 @@ namespace FlowerShopDatabaseImplement.Migrations
migrationBuilder.DropTable(
name: "Flowers");
migrationBuilder.DropTable(
name: "Implementers");
}
}
}

View File

@ -113,6 +113,33 @@ namespace FlowerShopDatabaseImplement.Migrations
b.ToTable("FlowerComponents");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.Implementer", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ImplementerFIO")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Qualification")
.HasColumnType("integer");
b.Property<int>("WorkExperience")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("Implementers");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.Order", b =>
{
b.Property<int>("Id")
@ -136,6 +163,9 @@ namespace FlowerShopDatabaseImplement.Migrations
b.Property<int>("FlowerId")
.HasColumnType("integer");
b.Property<int?>("ImplementerId")
.HasColumnType("integer");
b.Property<int>("Status")
.HasColumnType("integer");
@ -146,6 +176,8 @@ namespace FlowerShopDatabaseImplement.Migrations
b.HasIndex("FlowerId");
b.HasIndex("ImplementerId");
b.ToTable("Orders");
});
@ -175,6 +207,10 @@ namespace FlowerShopDatabaseImplement.Migrations
.HasForeignKey("FlowerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("FlowerShopDatabaseImplement.Models.Implementer", null)
.WithMany("Order")
.HasForeignKey("ImplementerId");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.Component", b =>
@ -188,6 +224,11 @@ namespace FlowerShopDatabaseImplement.Migrations
b.Navigation("Orders");
});
modelBuilder.Entity("FlowerShopDatabaseImplement.Models.Implementer", b =>
{
b.Navigation("Order");
});
#pragma warning restore 612, 618
}
}

View File

@ -11,7 +11,7 @@ namespace FlowerShopDatabaseImplement.Models
public int Id { get; private set; }
public int FlowerId { get; private set; }
public int ClientId { get; private set; }
public int ImplementerId { get; private set; }
public int? ImplementerId { get; private set; }
[Required]
public int Count { get; set; }
[Required]
@ -32,6 +32,7 @@ namespace FlowerShopDatabaseImplement.Models
Id = model.Id,
FlowerId = model.FlowerId,
ClientId = model.ClientId,
ImplementerId = model.ImplementerId,
Count = model.Count,
Sum = model.Sum,
Status = model.Status,
@ -45,6 +46,7 @@ namespace FlowerShopDatabaseImplement.Models
{
return;
}
ImplementerId = model.ImplementerId;
Status = model.Status;
DateImplement = model.DateImplement;
}
@ -53,6 +55,7 @@ namespace FlowerShopDatabaseImplement.Models
Id = Id,
FlowerId = FlowerId,
ClientId = ClientId,
ImplementerId = ImplementerId,
Count = Count,
Sum = Sum,
Status = Status,

View File

@ -10,7 +10,7 @@ namespace FlowerShopFileImplement
private readonly string OrderFileName = "Order.xml";
private readonly string FlowerFileName = "Flower.xml";
private readonly string ClientFileName = "Client.xml";
private readonly string ImplementerFileName = "Implementer.xml"
private readonly string ImplementerFileName = "Implementer.xml";
public List<Component> Components { get; private set; }
public List<Order> Orders { get; private set; }
public List<Flower> Flowers { get; private set; }
@ -35,7 +35,7 @@ namespace FlowerShopFileImplement
Flowers = LoadData(FlowerFileName, "Flower", x => Flower.Create(x)!)!;
Orders = LoadData(OrderFileName, "Order", x => Order.Create(x)!)!;
Clients = LoadData(ClientFileName, "Client", x => Client.Create(x)!)!;
Implementers = LoadData(ImplementerFileName, "Implementer", x => Implementer.Create(x)!)!);
Implementers = LoadData(ImplementerFileName, "Implementer", x => Implementer.Create(x)!)!;
}
private static List<T>? LoadData<T>(string filename, string xmlNodeName, Func<XElement, T> selectFunction)
{

View File

@ -11,7 +11,7 @@ namespace FlowerShopFileImplement.Models
public int Id { get; private set; }
public int FlowerId { get; private set; }
public int ClientId { get; private set; }
public int ImplementerId { get; private set; }
public int? ImplementerId { get; private set; }
public int Count { get; private set; }
public double Sum { get; set; }
public OrderStatus Status { get; set; }

View File

@ -10,7 +10,7 @@ namespace FlowerShopListImplement.Models
public int Id { get; private set; }
public int FlowerId { get; private set; }
public int ClientId { get; private set; }
public int ImplementerId { get; private set; }
public int? ImplementerId { get; private set; }
public int Count { get; set; }
public double Sum { get; private set; }
public OrderStatus Status { get; set; }

View File

@ -0,0 +1,100 @@
using DocumentFormat.OpenXml.Office2010.Excel;
using FlowerShopContracts.BindingModels;
using FlowerShopContracts.BusinessLogicsContracts;
using FlowerShopContracts.SearchModels;
using FlowerShopContracts.ViewModels;
using FlowerShopDataModels.Enums;
using Microsoft.AspNetCore.Mvc;
namespace FlowerShopRestApi.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class ImplementerController : Controller
{
private readonly ILogger _logger;
private readonly IOrderLogic _order;
private readonly IImplementerLogic _logic;
public ImplementerController(IOrderLogic order, IImplementerLogic logic, ILogger<ImplementerController> 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<OrderViewModel>? 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;
}
}
}
}