diff --git a/COP/COP.sln b/COP/COP.sln
index 6433672..17e749e 100644
--- a/COP/COP.sln
+++ b/COP/COP.sln
@@ -5,7 +5,17 @@ VisualStudioVersion = 17.3.32825.248
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Components", "Components\Components.csproj", "{F22A3AAE-6F8D-4AEB-91B1-E8303166B5FF}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinFormsTest", "WinFormsTest\WinFormsTest.csproj", "{F589AB00-F69A-4826-BE33-662F14E39F25}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinFormsTest", "WinFormsTest\WinFormsTest.csproj", "{F589AB00-F69A-4826-BE33-662F14E39F25}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClientsDataModels", "ClientsDataModels\ClientsDataModels.csproj", "{9BE06619-49B5-4C59-984B-A70E7BF352D7}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClientsBusinessLogics", "ClientsBusinessLogics\ClientsBusinessLogics.csproj", "{BF3640B7-0602-4D4A-95CF-51E2DD9E1A9D}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClientsContracts", "ClientsContracts\ClientsContracts.csproj", "{8E8650C4-A930-442C-92CC-56082F3E072F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClientDataBaseImplement", "ClientDataBaseImplement\ClientDataBaseImplement.csproj", "{4FB19656-B4A9-4070-BAD4-D9649DBEFB40}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChubykinaComponents", "ChubykinaComponents\ChubykinaComponents.csproj", "{335CABB5-5AC4-4688-92DD-5B91FEB16192}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -21,6 +31,26 @@ Global
{F589AB00-F69A-4826-BE33-662F14E39F25}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F589AB00-F69A-4826-BE33-662F14E39F25}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F589AB00-F69A-4826-BE33-662F14E39F25}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9BE06619-49B5-4C59-984B-A70E7BF352D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9BE06619-49B5-4C59-984B-A70E7BF352D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9BE06619-49B5-4C59-984B-A70E7BF352D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9BE06619-49B5-4C59-984B-A70E7BF352D7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BF3640B7-0602-4D4A-95CF-51E2DD9E1A9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BF3640B7-0602-4D4A-95CF-51E2DD9E1A9D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BF3640B7-0602-4D4A-95CF-51E2DD9E1A9D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BF3640B7-0602-4D4A-95CF-51E2DD9E1A9D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8E8650C4-A930-442C-92CC-56082F3E072F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8E8650C4-A930-442C-92CC-56082F3E072F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8E8650C4-A930-442C-92CC-56082F3E072F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8E8650C4-A930-442C-92CC-56082F3E072F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4FB19656-B4A9-4070-BAD4-D9649DBEFB40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4FB19656-B4A9-4070-BAD4-D9649DBEFB40}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4FB19656-B4A9-4070-BAD4-D9649DBEFB40}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4FB19656-B4A9-4070-BAD4-D9649DBEFB40}.Release|Any CPU.Build.0 = Release|Any CPU
+ {335CABB5-5AC4-4688-92DD-5B91FEB16192}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {335CABB5-5AC4-4688-92DD-5B91FEB16192}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {335CABB5-5AC4-4688-92DD-5B91FEB16192}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {335CABB5-5AC4-4688-92DD-5B91FEB16192}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/COP/ChubykinaComponents/ChubykinaComponents.csproj b/COP/ChubykinaComponents/ChubykinaComponents.csproj
new file mode 100644
index 0000000..89d5eb4
--- /dev/null
+++ b/COP/ChubykinaComponents/ChubykinaComponents.csproj
@@ -0,0 +1,20 @@
+
+
+
+ net6.0
+ enable
+ true
+ enable
+ True
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/COP/ChubykinaComponents/Components/UserCheckedListBox.Designer.cs b/COP/ChubykinaComponents/Components/UserCheckedListBox.Designer.cs
new file mode 100644
index 0000000..251a25a
--- /dev/null
+++ b/COP/ChubykinaComponents/Components/UserCheckedListBox.Designer.cs
@@ -0,0 +1,58 @@
+namespace ChubykinaComponents.Components
+{
+ partial class UserCheckedListBox
+ {
+ ///
+ /// Обязательная переменная конструктора.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Освободить все используемые ресурсы.
+ ///
+ /// истинно, если управляемый ресурс должен быть удален; иначе ложно.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Код, автоматически созданный конструктором компонентов
+
+ ///
+ /// Требуемый метод для поддержки конструктора — не изменяйте
+ /// содержимое этого метода с помощью редактора кода.
+ ///
+ private void InitializeComponent()
+ {
+ this.checkedListBox = new System.Windows.Forms.CheckedListBox();
+ this.SuspendLayout();
+ //
+ // checkedListBox
+ //
+ this.checkedListBox.FormattingEnabled = true;
+ this.checkedListBox.Location = new System.Drawing.Point(0, 0);
+ this.checkedListBox.Name = "checkedListBox";
+ this.checkedListBox.Size = new System.Drawing.Size(150, 114);
+ this.checkedListBox.TabIndex = 0;
+ this.checkedListBox.SelectedIndexChanged += new System.EventHandler(this.checkedListBox_SelectedIndexChanged);
+ //
+ // UserCheckedListBox
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.checkedListBox);
+ this.Name = "UserCheckedListBox";
+ this.Size = new System.Drawing.Size(150, 115);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private CheckedListBox checkedListBox;
+ }
+}
\ No newline at end of file
diff --git a/COP/ChubykinaComponents/Components/UserCheckedListBox.cs b/COP/ChubykinaComponents/Components/UserCheckedListBox.cs
new file mode 100644
index 0000000..6162067
--- /dev/null
+++ b/COP/ChubykinaComponents/Components/UserCheckedListBox.cs
@@ -0,0 +1,62 @@
+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 ChubykinaComponents.Components
+{
+ public partial class UserCheckedListBox : UserControl
+ {
+ public UserCheckedListBox()
+ {
+ InitializeComponent();
+ }
+
+ public string? selectedItem
+ {
+ get
+ {
+ return checkedListBox.SelectedItem is null ? null : checkedListBox.SelectedItem.ToString();
+ }
+ set
+ {
+ if (value != null && checkedListBox.Items.Contains(value)) checkedListBox.SelectedItem = value;
+ }
+ }
+
+ public event Action SelectedItemChange;
+
+ public void addItems(List items)
+ {
+ foreach (string item in items)
+ {
+ checkedListBox.Items.Add(item);
+ }
+ }
+
+ public void clear()
+ {
+ checkedListBox.Items.Clear();
+ }
+
+ private void checkedListBox_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ if (checkedListBox.CheckedItems.Count > 1)
+ {
+ foreach (int index in checkedListBox.CheckedIndices)
+ {
+ if (index != checkedListBox.SelectedIndex)
+ {
+ checkedListBox.SetItemChecked(index, false);
+ }
+ }
+ }
+ SelectedItemChange?.Invoke(checkedListBox.SelectedItem.ToString());
+ }
+ }
+}
diff --git a/COP/ChubykinaComponents/Components/UserCheckedListBox.resx b/COP/ChubykinaComponents/Components/UserCheckedListBox.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/COP/ChubykinaComponents/Components/UserCheckedListBox.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/COP/ChubykinaComponents/Components/UserDatePicker.Designer.cs b/COP/ChubykinaComponents/Components/UserDatePicker.Designer.cs
new file mode 100644
index 0000000..255c5be
--- /dev/null
+++ b/COP/ChubykinaComponents/Components/UserDatePicker.Designer.cs
@@ -0,0 +1,56 @@
+namespace ChubykinaComponents.Components
+{
+ partial class UserDatePicker
+ {
+ ///
+ /// Обязательная переменная конструктора.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Освободить все используемые ресурсы.
+ ///
+ /// истинно, если управляемый ресурс должен быть удален; иначе ложно.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Код, автоматически созданный конструктором компонентов
+
+ ///
+ /// Требуемый метод для поддержки конструктора — не изменяйте
+ /// содержимое этого метода с помощью редактора кода.
+ ///
+ private void InitializeComponent()
+ {
+ this.dateTimePicker = new System.Windows.Forms.DateTimePicker();
+ this.SuspendLayout();
+ //
+ // dateTimePicker
+ //
+ this.dateTimePicker.Location = new System.Drawing.Point(3, 3);
+ this.dateTimePicker.Name = "dateTimePicker";
+ this.dateTimePicker.Size = new System.Drawing.Size(250, 27);
+ this.dateTimePicker.TabIndex = 0;
+ this.dateTimePicker.ValueChanged += new System.EventHandler(this.dateTimePicker_ValueChanged);
+ //
+ // UserDatePicker
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.dateTimePicker);
+ this.Name = "UserDatePicker";
+ this.Size = new System.Drawing.Size(257, 38);
+ this.ResumeLayout(false);
+ }
+
+ #endregion
+
+ private DateTimePicker dateTimePicker;
+ }
+}
diff --git a/COP/ChubykinaComponents/Components/UserDatePicker.cs b/COP/ChubykinaComponents/Components/UserDatePicker.cs
new file mode 100644
index 0000000..d5c4de3
--- /dev/null
+++ b/COP/ChubykinaComponents/Components/UserDatePicker.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using ChubykinaComponents.Exceptions;
+
+namespace ChubykinaComponents.Components
+{
+ public partial class UserDatePicker : UserControl
+ {
+ public UserDatePicker()
+ {
+ InitializeComponent();
+ }
+
+ public event Action DateChange;
+ private bool lowBoundrySet = false;
+ private bool highBoundrySet = false;
+
+ public bool BoundriesSet { get { return lowBoundrySet && highBoundrySet; } }
+
+ public DateTime? dateFrom
+ {
+ get
+ {
+ return lowBoundrySet ? dateTimePicker.MinDate : null;
+ }
+ set
+ {
+ if (value.HasValue)
+ {
+ dateTimePicker.MinDate = value.Value;
+ lowBoundrySet = true;
+ }
+ }
+ }
+
+ public DateTime? dateTo
+ {
+ get
+ {
+ return highBoundrySet ? dateTimePicker.MaxDate : null;
+ }
+ set
+ {
+ if (value.HasValue)
+ {
+ dateTimePicker.MaxDate = value.Value;
+ highBoundrySet = true;
+ }
+ }
+ }
+
+ public DateTime? Value
+ {
+ get
+ {
+ if (!lowBoundrySet || !highBoundrySet)
+ {
+ throw new DateBoundsNotSetException("Date bounds are not set.");
+ }
+ return dateTimePicker.Value;
+ }
+ set
+ {
+ if (lowBoundrySet && highBoundrySet && value.HasValue && value.Value >= dateFrom && value.Value <= dateTo) dateTimePicker.Value = value.Value;
+ }
+ }
+
+ private void dateTimePicker_ValueChanged(object sender, EventArgs e)
+ {
+ DateChange?.Invoke(dateTimePicker.Value);
+ }
+ }
+}
\ No newline at end of file
diff --git a/COP/ChubykinaComponents/Components/UserDatePicker.resx b/COP/ChubykinaComponents/Components/UserDatePicker.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/COP/ChubykinaComponents/Components/UserDatePicker.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/COP/ChubykinaComponents/Components/UserTreeView.Designer.cs b/COP/ChubykinaComponents/Components/UserTreeView.Designer.cs
new file mode 100644
index 0000000..1c07199
--- /dev/null
+++ b/COP/ChubykinaComponents/Components/UserTreeView.Designer.cs
@@ -0,0 +1,55 @@
+namespace ChubykinaComponents.Components
+{
+ partial class UserTreeView
+ {
+ ///
+ /// Обязательная переменная конструктора.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Освободить все используемые ресурсы.
+ ///
+ /// истинно, если управляемый ресурс должен быть удален; иначе ложно.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Код, автоматически созданный конструктором компонентов
+
+ ///
+ /// Требуемый метод для поддержки конструктора — не изменяйте
+ /// содержимое этого метода с помощью редактора кода.
+ ///
+ private void InitializeComponent()
+ {
+ this.treeView = new System.Windows.Forms.TreeView();
+ this.SuspendLayout();
+ //
+ // treeView
+ //
+ this.treeView.Location = new System.Drawing.Point(0, 0);
+ this.treeView.Name = "treeView";
+ this.treeView.Size = new System.Drawing.Size(295, 212);
+ this.treeView.TabIndex = 0;
+ //
+ // UserTreeView
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.treeView);
+ this.Name = "UserTreeView";
+ this.Size = new System.Drawing.Size(295, 212);
+ this.ResumeLayout(false);
+ }
+
+ #endregion
+
+ private TreeView treeView;
+ }
+}
diff --git a/COP/ChubykinaComponents/Components/UserTreeView.cs b/COP/ChubykinaComponents/Components/UserTreeView.cs
new file mode 100644
index 0000000..7f75c08
--- /dev/null
+++ b/COP/ChubykinaComponents/Components/UserTreeView.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement;
+
+namespace ChubykinaComponents.Components
+{
+ public partial class UserTreeView : UserControl
+ {
+ public UserTreeView()
+ {
+ InitializeComponent();
+ }
+ private List<(string, bool)> hierarchy = new List<(string, bool)>();
+
+ public int SelectedNodeIndex
+ {
+ get
+ {
+ return treeView.SelectedNode?.Index ?? -1;
+ }
+ set
+ {
+ if (treeView.SelectedNode == null) treeView.SelectedNode = value >= 0 && value < treeView.Nodes.Count ? treeView.Nodes[value] : treeView.SelectedNode;
+ else treeView.SelectedNode = value >= 0 && value < treeView.SelectedNode.Nodes.Count ? treeView.SelectedNode.Nodes[value] : treeView.SelectedNode;
+ }
+ }
+ public T? getSelecetedNodeValue()
+ {
+ if (treeView.SelectedNode == null || treeView.SelectedNode.Nodes.Count > 0) return default(T);
+ TreeNode? node = treeView.SelectedNode;
+ var type = typeof(T);
+ var fields = type.GetFields();
+ var item = Activator.CreateInstance(type);
+
+ while (node != null)
+ {
+ var field = fields.FirstOrDefault(x => x.Name == node.Name);
+ if (field != null)
+ {
+ field.SetValue(item, node.Text);
+ }
+ node = node.Parent;
+ }
+
+ return item != null ? (T)item : default(T);
+ }
+
+ public void setHierarchy(List<(string, bool)> fields)
+ {
+ hierarchy = fields;
+ }
+
+ public void addItems(List items)
+ {
+ var type = typeof(T);
+ var fields = type.GetFields();
+ foreach (T item in items)
+ {
+ TreeNodeCollection nodes = treeView.Nodes;
+ for (int i = 0; i < hierarchy.Count; i++)
+ {
+ var field = fields.FirstOrDefault(x => x.Name.Equals(hierarchy[i].Item1));
+ if (field is not null)
+ {
+ var node = nodes.Find(field.Name, false).FirstOrDefault(x => x.Text == field.GetValue(item).ToString());
+ if (node is not null && !hierarchy[i].Item2)
+ {
+ nodes = node.Nodes;
+ }
+ else
+ {
+ TreeNode newNode = nodes.Add(field.Name, field.GetValue(item).ToString());
+ nodes = newNode.Nodes;
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/COP/ChubykinaComponents/Components/UserTreeView.resx b/COP/ChubykinaComponents/Components/UserTreeView.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/COP/ChubykinaComponents/Components/UserTreeView.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/COP/ChubykinaComponents/Exceptions/DateBoundsNotSetException.cs b/COP/ChubykinaComponents/Exceptions/DateBoundsNotSetException.cs
new file mode 100644
index 0000000..ea9424e
--- /dev/null
+++ b/COP/ChubykinaComponents/Exceptions/DateBoundsNotSetException.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Runtime.Serialization;
+
+namespace ChubykinaComponents.Exceptions
+{
+ [Serializable]
+ public class DateBoundsNotSetException : ApplicationException
+ {
+ public DateBoundsNotSetException() : base() { }
+ public DateBoundsNotSetException(string message) : base(message) { }
+ public DateBoundsNotSetException(string message, Exception exception) : base(message, exception) { }
+ protected DateBoundsNotSetException(SerializationInfo info, StreamingContext contex) : base(info, contex) { }
+ }
+}
diff --git a/COP/ChubykinaComponents/Exceptions/DateOutOfBoundsException.cs b/COP/ChubykinaComponents/Exceptions/DateOutOfBoundsException.cs
new file mode 100644
index 0000000..91eafa0
--- /dev/null
+++ b/COP/ChubykinaComponents/Exceptions/DateOutOfBoundsException.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ChubykinaComponents.Exceptions
+{
+ public class DateOutOfBoundsException : ApplicationException
+ {
+ public DateOutOfBoundsException() : base() { }
+ public DateOutOfBoundsException(string message) : base(message) { }
+ public DateOutOfBoundsException(string message, Exception exception) : base(message, exception) { }
+ protected DateOutOfBoundsException(SerializationInfo info, StreamingContext contex) : base(info, contex) { }
+ }
+}
diff --git a/COP/ChubykinaComponents/LogicalComponents/DiagramLegendEnum.cs b/COP/ChubykinaComponents/LogicalComponents/DiagramLegendEnum.cs
new file mode 100644
index 0000000..217e6de
--- /dev/null
+++ b/COP/ChubykinaComponents/LogicalComponents/DiagramLegendEnum.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ChubykinaComponents.LogicalComponents
+{
+ public enum DiagramLegendEnum
+ {
+ TopLeft = 0,
+ TopRight = 1,
+ BottomRight = 2,
+ BottomLeft = 3,
+ }
+}
diff --git a/COP/ChubykinaComponents/LogicalComponents/ExcelDiagramComponent.Designer.cs b/COP/ChubykinaComponents/LogicalComponents/ExcelDiagramComponent.Designer.cs
new file mode 100644
index 0000000..4954a14
--- /dev/null
+++ b/COP/ChubykinaComponents/LogicalComponents/ExcelDiagramComponent.Designer.cs
@@ -0,0 +1,36 @@
+namespace ChubykinaComponents.LogicalComponents
+{
+ partial class ExcelDiagramComponent
+ {
+ ///
+ /// Обязательная переменная конструктора.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Освободить все используемые ресурсы.
+ ///
+ /// истинно, если управляемый ресурс должен быть удален; иначе ложно.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Код, автоматически созданный конструктором компонентов
+
+ ///
+ /// Требуемый метод для поддержки конструктора — не изменяйте
+ /// содержимое этого метода с помощью редактора кода.
+ ///
+ private void InitializeComponent()
+ {
+ components = new System.ComponentModel.Container();
+ }
+
+ #endregion
+ }
+}
diff --git a/COP/ChubykinaComponents/LogicalComponents/ExcelDiagramComponent.cs b/COP/ChubykinaComponents/LogicalComponents/ExcelDiagramComponent.cs
new file mode 100644
index 0000000..78d254e
--- /dev/null
+++ b/COP/ChubykinaComponents/LogicalComponents/ExcelDiagramComponent.cs
@@ -0,0 +1,117 @@
+using Microsoft.Office.Interop.Excel;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ChubykinaComponents.LogicalComponents
+{
+ public partial class ExcelDiagramComponent : Component
+ {
+ public ExcelDiagramComponent()
+ {
+ InitializeComponent();
+ }
+
+ public ExcelDiagramComponent(IContainer container)
+ {
+ container.Add(this);
+
+ InitializeComponent();
+ }
+ public bool createWithDiagram(string path, string title, string diagramTitle, DiagramLegendEnum diagramLegendAnchor, List data, string seriesNameField, string valueField)
+ {
+ var excelApp = new Microsoft.Office.Interop.Excel.Application { SheetsInNewWorkbook = 1 };
+ Workbook workbook = excelApp.Workbooks.Add(Type.Missing);
+ try
+ {
+ Worksheet worksheet = (Worksheet)workbook.Worksheets.get_Item(1);
+
+ FieldInfo? seriesName = typeof(T).GetField(seriesNameField);
+ FieldInfo? value = typeof(T).GetField(valueField);
+ if (seriesName == null || value == null) throw new ArgumentException("Переданного поля не существует");
+ int columnCount = 2;
+ foreach (var item in data)
+ {
+ var cell = worksheet.get_Range("A" + columnCount, "A" + columnCount);
+ cell.Font.Size = 14;
+ cell.Font.Name = "Times New Roman";
+ cell.ColumnWidth = 8;
+ cell.RowHeight = 25;
+ cell.HorizontalAlignment = Constants.xlCenter;
+ cell.VerticalAlignment = Constants.xlCenter;
+ cell.Value2 = seriesName.GetValue(item);
+
+ cell = worksheet.get_Range("B" + columnCount, "B" + columnCount);
+ cell.Font.Size = 14;
+ cell.Font.Name = "Times New Roman";
+ cell.ColumnWidth = 8;
+ cell.RowHeight = 25;
+ cell.HorizontalAlignment = Constants.xlCenter;
+ cell.VerticalAlignment = Constants.xlCenter;
+ cell.Value2 = value.GetValue(item);
+
+ columnCount++;
+ }
+
+ //header
+ var excelcells = worksheet.get_Range("A1", "A1");
+ excelcells.Font.Bold = true;
+ excelcells.Font.Size = 14;
+ excelcells.Font.Name = "Times New Roman";
+ excelcells.ColumnWidth = 8;
+ excelcells.RowHeight = 25;
+ excelcells.HorizontalAlignment = Constants.xlCenter;
+ excelcells.VerticalAlignment = Constants.xlCenter;
+ excelcells.Value2 = title;
+
+ var charts = worksheet.ChartObjects() as ChartObjects;
+ int chartWidth = 300;
+ int chartHeight = 300;
+ var chartObject = charts.Add(250, 10, chartWidth, chartHeight);
+ var chart = chartObject.Chart;
+ var range = worksheet.get_Range($"A2", $"B{columnCount - 1}");
+ chart.SetSourceData(range);
+ chart.ChartType = XlChartType.xlPie;
+ switch (diagramLegendAnchor)
+ {
+ case DiagramLegendEnum.TopLeft:
+ chart.Legend.Top = 0;
+ chart.Legend.Left = 0;
+ break;
+ case DiagramLegendEnum.TopRight:
+ chart.Legend.Top = 0;
+ chart.Legend.Left = chartWidth - chart.Legend.Width;
+ break;
+ case DiagramLegendEnum.BottomLeft:
+ chart.Legend.Top = chartHeight - chart.Legend.Height;
+ chart.Legend.Left = 0;
+ break;
+ case DiagramLegendEnum.BottomRight:
+ chart.Legend.Top = chartHeight - chart.Legend.Height;
+ chart.Legend.Left = chartWidth - chart.Legend.Width;
+ break;
+ }
+ chart.ChartWizard(Source: range, Title: diagramTitle);
+
+ object missing = System.Reflection.Missing.Value;
+ workbook.SaveAs(path, XlFileFormat.xlOpenXMLWorkbook, missing, missing, false, false, XlSaveAsAccessMode.xlNoChange,
+ XlSaveConflictResolution.xlUserResolution, true, missing, missing, missing);
+ workbook.Close();
+ excelApp.Quit();
+
+ return true;
+ }
+ catch (Exception)
+ {
+ workbook.Close();
+ excelApp.Quit();
+ throw;
+ }
+ }
+ }
+}
diff --git a/COP/ChubykinaComponents/LogicalComponents/ExcelDiagramComponent.resx b/COP/ChubykinaComponents/LogicalComponents/ExcelDiagramComponent.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/COP/ChubykinaComponents/LogicalComponents/ExcelDiagramComponent.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/COP/ChubykinaComponents/LogicalComponents/ExcelImageInfo.cs b/COP/ChubykinaComponents/LogicalComponents/ExcelImageInfo.cs
new file mode 100644
index 0000000..e72fea6
--- /dev/null
+++ b/COP/ChubykinaComponents/LogicalComponents/ExcelImageInfo.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ChubykinaComponents.LogicalComponents
+{
+ public class ExcelImageInfo
+ {
+ public ExcelImageInfo(string path, string title, string[] imagePaths)
+ {
+ this.path = path;
+ this.title = title;
+ this.imagePaths = imagePaths;
+ }
+
+ public string path;
+ public string title;
+ public string[] imagePaths;
+ }
+}
diff --git a/COP/ChubykinaComponents/LogicalComponents/ExcelImagesComponent.Designer.cs b/COP/ChubykinaComponents/LogicalComponents/ExcelImagesComponent.Designer.cs
new file mode 100644
index 0000000..df017a3
--- /dev/null
+++ b/COP/ChubykinaComponents/LogicalComponents/ExcelImagesComponent.Designer.cs
@@ -0,0 +1,36 @@
+namespace ChubykinaComponents.LogicalComponents
+{
+ partial class ExcelImagesComponent
+ {
+ ///
+ /// Обязательная переменная конструктора.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Освободить все используемые ресурсы.
+ ///
+ /// истинно, если управляемый ресурс должен быть удален; иначе ложно.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Код, автоматически созданный конструктором компонентов
+
+ ///
+ /// Требуемый метод для поддержки конструктора — не изменяйте
+ /// содержимое этого метода с помощью редактора кода.
+ ///
+ private void InitializeComponent()
+ {
+ components = new System.ComponentModel.Container();
+ }
+
+ #endregion
+ }
+}
diff --git a/COP/ChubykinaComponents/LogicalComponents/ExcelImagesComponent.cs b/COP/ChubykinaComponents/LogicalComponents/ExcelImagesComponent.cs
new file mode 100644
index 0000000..af5acad
--- /dev/null
+++ b/COP/ChubykinaComponents/LogicalComponents/ExcelImagesComponent.cs
@@ -0,0 +1,77 @@
+using Microsoft.Office.Core;
+using Microsoft.Office.Interop.Excel;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ChubykinaComponents.LogicalComponents
+{
+ public partial class ExcelImagesComponent : Component
+ {
+ public ExcelImagesComponent()
+ {
+ InitializeComponent();
+ }
+
+ public ExcelImagesComponent(IContainer container)
+ {
+ container.Add(this);
+
+ InitializeComponent();
+ }
+ public bool createWithImages(ExcelImageInfo info)
+ {
+ if (string.IsNullOrEmpty(info.path) || string.IsNullOrEmpty(info.title) || info.imagePaths == null || info.imagePaths.Length == 0)
+ {
+ throw new ArgumentException("Не все поля заполнены.");
+ }
+ var excelApp = new Microsoft.Office.Interop.Excel.Application { SheetsInNewWorkbook = 1 };
+ Workbook workbook = excelApp.Workbooks.Add(Type.Missing);
+ try
+ {
+ //create
+ Worksheet worksheet = (Worksheet)workbook.Worksheets.get_Item(1);
+
+ //header
+ var excelcells = worksheet.get_Range("A1", "D1");
+ excelcells.Merge(Type.Missing);
+ excelcells.Font.Bold = true;
+ excelcells.Font.Size = 14;
+ excelcells.Font.Name = "Times New Roman";
+ excelcells.ColumnWidth = 8;
+ excelcells.RowHeight = 25;
+ excelcells.HorizontalAlignment = Constants.xlCenter;
+ excelcells.VerticalAlignment = Constants.xlCenter;
+ excelcells.Value2 = info.title;
+
+ int topOffset = 25;
+ foreach (string path in info.imagePaths)
+ {
+ Bitmap bm = new Bitmap(path);
+ worksheet.Shapes.AddPicture2(path, MsoTriState.msoFalse, MsoTriState.msoCTrue, 0, topOffset, bm.Width, bm.Height, MsoPictureCompress.msoPictureCompressFalse);
+ topOffset += bm.Height;
+ bm.Dispose();
+ }
+
+ //save
+ object missing = System.Reflection.Missing.Value;
+ workbook.SaveAs(info.path, XlFileFormat.xlOpenXMLWorkbook, missing, missing, false, false, XlSaveAsAccessMode.xlNoChange,
+ XlSaveConflictResolution.xlUserResolution, true, missing, missing, missing);
+ workbook.Close();
+ excelApp.Quit();
+
+ return true;
+ }
+ catch (Exception)
+ {
+ workbook.Close();
+ excelApp.Quit();
+ return false;
+ }
+ }
+ }
+}
diff --git a/COP/ChubykinaComponents/LogicalComponents/ExcelTableComponent.Designer.cs b/COP/ChubykinaComponents/LogicalComponents/ExcelTableComponent.Designer.cs
new file mode 100644
index 0000000..9f0eca4
--- /dev/null
+++ b/COP/ChubykinaComponents/LogicalComponents/ExcelTableComponent.Designer.cs
@@ -0,0 +1,37 @@
+namespace ChubykinaComponents.LogicalComponents
+{
+ partial class ExcelTableComponent
+ {
+ ///
+ /// Обязательная переменная конструктора.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Освободить все используемые ресурсы.
+ ///
+ /// истинно, если управляемый ресурс должен быть удален; иначе ложно.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Код, автоматически созданный конструктором компонентов
+
+ ///
+ /// Требуемый метод для поддержки конструктора — не изменяйте
+ /// содержимое этого метода с помощью редактора кода.
+ ///
+ private void InitializeComponent()
+ {
+ components = new System.ComponentModel.Container();
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ }
+
+ #endregion
+ }
+}
diff --git a/COP/ChubykinaComponents/LogicalComponents/ExcelTableComponent.cs b/COP/ChubykinaComponents/LogicalComponents/ExcelTableComponent.cs
new file mode 100644
index 0000000..bbca81e
--- /dev/null
+++ b/COP/ChubykinaComponents/LogicalComponents/ExcelTableComponent.cs
@@ -0,0 +1,193 @@
+using Microsoft.Office.Interop.Excel;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace ChubykinaComponents.LogicalComponents
+{
+ public partial class ExcelTableComponent : UserControl
+ {
+ public ExcelTableComponent()
+ {
+ InitializeComponent();
+ }
+
+ public ExcelTableComponent(IContainer container)
+ {
+ container.Add(this);
+
+ InitializeComponent();
+ }
+ private string GetExcelColumnName(int columnNumber)
+ {
+ string columnName = "";
+
+ while (columnNumber > 0)
+ {
+ int modulo = (columnNumber - 1) % 26;
+ columnName = Convert.ToChar('A' + modulo) + columnName;
+ columnNumber = (columnNumber - modulo) / 26;
+ }
+
+ return columnName;
+ }
+
+ public bool createWithTable(string path, string title, List<(int, int)> merges, List heights, List<(string, string)> headers, List items)
+ {
+ if (merges.Count == 0 || heights.Count == 0 || headers.Count == 0 || items.Count == 0) throw new ArgumentException("Недостаточно данных");
+ int[] cellsArray = new int[heights.Count];
+ foreach (var merge in merges)
+ {
+ if (merge.Item1 >= merge.Item2) throw new ArgumentException("Неправильно заполнены объединения строк");
+ for (int i = merge.Item1; i < merge.Item2; i++)
+ {
+ cellsArray[i]++;
+ }
+ }
+ foreach (int cell in cellsArray)
+ {
+ if (cell > 1) throw new ArgumentException("Объединения заходят друг на друга");
+ }
+
+ var excelApp = new Microsoft.Office.Interop.Excel.Application { SheetsInNewWorkbook = 1 };
+ Workbook workbook = excelApp.Workbooks.Add(Type.Missing);
+ try
+ {
+ //create
+ Worksheet worksheet = (Worksheet)workbook.Worksheets.get_Item(1);
+
+ //header
+ var excelcells = worksheet.get_Range("A1", "A1");
+ excelcells.Font.Bold = true;
+ excelcells.Font.Size = 14;
+ excelcells.Font.Name = "Times New Roman";
+ excelcells.ColumnWidth = 8;
+ excelcells.RowHeight = 25;
+ excelcells.HorizontalAlignment = Constants.xlCenter;
+ excelcells.VerticalAlignment = Constants.xlCenter;
+ excelcells.Value2 = title;
+
+ //checks
+ List ranges = new List();
+ foreach (var merge in merges)
+ {
+ ranges.Add(worksheet.get_Range("A" + (merge.Item1 + 2), "A" + (merge.Item2 + 2)));
+ }
+
+ int rangeIndex = 0;
+ int headerIndex = 0;
+ List cellFields = new List();
+ var type = typeof(T);
+ for (int i = 0; i < heights.Count; i++)
+ {
+ if (cellsArray[i] == 1)
+ {
+ //work with merge
+ if (!string.IsNullOrEmpty(headers[headerIndex].Item1)) throw new ArgumentException("Заголовки и объединения строк не совпадают");
+
+ var groupRange = ranges[rangeIndex];
+ groupRange.Merge(Type.Missing);
+ groupRange.Font.Bold = true;
+ groupRange.Font.Size = 14;
+ groupRange.Font.Name = "Times New Roman";
+ groupRange.ColumnWidth = 20;
+ groupRange.HorizontalAlignment = Constants.xlCenter;
+ groupRange.VerticalAlignment = Constants.xlCenter;
+ groupRange.Value2 = headers[headerIndex].Item2;
+ headerIndex++;
+
+ //work with cells in merge
+ for (; i <= merges[rangeIndex].Item2; i++)
+ {
+ //work with cell
+ if (string.IsNullOrEmpty(headers[headerIndex].Item1)) throw new ArgumentException("Заголовки и объединения строк не совпадают");
+ var field = type.GetField(headers[headerIndex].Item1);
+ if (field == null) throw new ArgumentException("В заголовках указано поле, которого нет в переданном классе");
+ //format header
+ var range = worksheet.get_Range("B" + (i + 2), "B" + (i + 2));
+ range.Font.Bold = true;
+ range.Font.Size = 14;
+ range.Font.Name = "Times New Roman";
+ range.ColumnWidth = 20;
+ range.RowHeight = heights[i];
+ range.HorizontalAlignment = Constants.xlCenter;
+ range.VerticalAlignment = Constants.xlCenter;
+ range.Value2 = headers[headerIndex].Item2;
+
+ cellFields.Add(field);
+ headerIndex++;
+ }
+ i--;
+ rangeIndex++;
+ }
+ else
+ {
+ //work with cell
+ if (string.IsNullOrEmpty(headers[headerIndex].Item1)) throw new ArgumentException("Заголовки и объединения строк не совпадают");
+ var field = type.GetField(headers[headerIndex].Item1);
+ if (field == null) throw new ArgumentException("В заголовках указано поле, которого нет в переданном классе");
+ //format header
+ var range = worksheet.get_Range("A" + (i + 2), "B" + (i + 2));
+ range.Merge(Type.Missing);
+ range.Font.Bold = true;
+ range.Font.Size = 14;
+ range.Font.Name = "Times New Roman";
+ range.ColumnWidth = 40;
+ range.RowHeight = heights[i];
+ range.HorizontalAlignment = Constants.xlCenter;
+ range.VerticalAlignment = Constants.xlCenter;
+ range.Value2 = headers[headerIndex].Item2;
+
+ cellFields.Add(field);
+ headerIndex++;
+ }
+ }
+
+ int columnNum = 3;
+ foreach (T item in items)
+ {
+ string column = GetExcelColumnName(columnNum);
+ int rowNum = 2;
+ foreach (var cellField in cellFields)
+ {
+ var range = worksheet.get_Range(column + rowNum, column + rowNum);
+ range.Font.Size = 14;
+ range.Font.Name = "Times New Roman";
+ range.ColumnWidth = 20;
+ range.HorizontalAlignment = Constants.xlCenter;
+ range.VerticalAlignment = Constants.xlCenter;
+ range.Value2 = cellField.FieldType == typeof(bool) ? ((bool)cellField.GetValue(item) ? "Да" : "Нет") : cellField.GetValue(item);
+
+ rowNum++;
+ }
+ columnNum++;
+ }
+ var borderRange = worksheet.get_Range("A2", GetExcelColumnName(columnNum - 1) + (headerIndex - 1));
+ borderRange.Borders.LineStyle = XlLineStyle.xlContinuous;
+ borderRange.Borders.Weight = 2d;
+
+ //save
+ object missing = System.Reflection.Missing.Value;
+ workbook.SaveAs(path, XlFileFormat.xlOpenXMLWorkbook, missing, missing, false, false, XlSaveAsAccessMode.xlNoChange,
+ XlSaveConflictResolution.xlUserResolution, true, missing, missing, missing);
+ workbook.Close();
+ excelApp.Quit();
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ workbook.Close();
+ excelApp.Quit();
+ throw;
+ }
+ }
+ }
+}
diff --git a/COP/ChubykinaComponents/LogicalComponents/ExcelTableComponent.resx b/COP/ChubykinaComponents/LogicalComponents/ExcelTableComponent.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/COP/ChubykinaComponents/LogicalComponents/ExcelTableComponent.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/COP/ClientDataBaseImplement/ClientDataBaseImplement.csproj b/COP/ClientDataBaseImplement/ClientDataBaseImplement.csproj
new file mode 100644
index 0000000..f1c0ef6
--- /dev/null
+++ b/COP/ClientDataBaseImplement/ClientDataBaseImplement.csproj
@@ -0,0 +1,24 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
diff --git a/COP/ClientDataBaseImplement/ClientsDatabase.cs b/COP/ClientDataBaseImplement/ClientsDatabase.cs
new file mode 100644
index 0000000..b687ab6
--- /dev/null
+++ b/COP/ClientDataBaseImplement/ClientsDatabase.cs
@@ -0,0 +1,26 @@
+using Microsoft.EntityFrameworkCore;
+using ClientDataBaseImplement.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Principal;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ClientDataBaseImplement
+{
+ public class ClientsDatabase : DbContext
+ {
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ {
+ if (optionsBuilder.IsConfigured == false)
+ {
+ optionsBuilder.UseSqlServer(@"Data Source=DESKTOP-0CI5KVE\SQLEXPRESS;Initial Catalog=ClientDatabase;Integrated Security=True;MultipleActiveResultSets=True;;TrustServerCertificate=True");
+ }
+ base.OnConfiguring(optionsBuilder);
+ }
+
+ public virtual DbSet Clients { set; get; }
+ public virtual DbSet Categories { set; get; }
+ }
+}
diff --git a/COP/ClientDataBaseImplement/Implements/CategoryStorage.cs b/COP/ClientDataBaseImplement/Implements/CategoryStorage.cs
new file mode 100644
index 0000000..14b934b
--- /dev/null
+++ b/COP/ClientDataBaseImplement/Implements/CategoryStorage.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ClientsContracts.BindingModels;
+using ClientsContracts.SearchModels;
+using ClientsContracts.StorageContracts;
+using ClientsContracts.ViewModels;
+using ClientDataBaseImplement.Models;
+using Microsoft.EntityFrameworkCore;
+using System.Security.Principal;
+
+namespace ClientDataBaseImplement.Implements
+{
+ public class CategoryStorage : ICategoryStorage
+ {
+ public List GetFullList()
+ {
+ using var context = new ClientsDatabase();
+ return context.Categories
+ .Select(x => x.GetViewModel)
+ .ToList();
+ }
+ public List GetFilteredList(CategorySearchModel model)
+ {
+ if (!model.Id.HasValue)
+ {
+ return new();
+ }
+ using var context = new ClientsDatabase();
+ return context.Categories
+ .Where(x => x.Id == model.Id)
+ .Select(x => x.GetViewModel)
+ .ToList();
+ }
+ public CategoryViewModel? GetElement(CategorySearchModel model)
+ {
+ if (!model.Id.HasValue)
+ {
+ return null;
+ }
+ using var context = new ClientsDatabase();
+ return context.Categories
+ .FirstOrDefault(x => model.Id.HasValue && x.Id == model.Id)
+ ?.GetViewModel;
+ }
+ public CategoryViewModel? Insert(CategoryBindingModel model)
+ {
+ var newCategory = Category.Create(model);
+ if (newCategory == null)
+ {
+ return null;
+ }
+ using var context = new ClientsDatabase();
+ context.Categories.Add(newCategory);
+ context.SaveChanges();
+ return newCategory.GetViewModel;
+ }
+ public CategoryViewModel? Update(CategoryBindingModel model)
+ {
+ using var context = new ClientsDatabase();
+ var component = context.Categories.FirstOrDefault(x => x.Id == model.Id);
+ if (component == null)
+ {
+ return null;
+ }
+ component.Update(model);
+ context.SaveChanges();
+ return component.GetViewModel;
+ }
+ public CategoryViewModel? Delete(CategoryBindingModel model)
+ {
+ using var context = new ClientsDatabase();
+ var element = context.Categories.FirstOrDefault(rec => rec.Id == model.Id);
+ if (element != null)
+ {
+ context.Categories.Remove(element);
+ context.SaveChanges();
+ return element.GetViewModel;
+ }
+ return null;
+ }
+ }
+}
diff --git a/COP/ClientDataBaseImplement/Implements/ClientStorage.cs b/COP/ClientDataBaseImplement/Implements/ClientStorage.cs
new file mode 100644
index 0000000..6367a59
--- /dev/null
+++ b/COP/ClientDataBaseImplement/Implements/ClientStorage.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ClientsContracts.BindingModels;
+using ClientsContracts.SearchModels;
+using ClientsContracts.StorageContracts;
+using ClientsContracts.ViewModels;
+using ClientDataBaseImplement.Models;
+using Microsoft.EntityFrameworkCore;
+using System.Security.Principal;
+
+namespace ClientDataBaseImplement.Implements
+{
+ public class ClientStorage : IClientStorage
+ {
+ public List GetFullList()
+ {
+ using var context = new ClientsDatabase();
+ return context.Clients
+ .Include(x => x.Category)
+ .Select(x => x.GetViewModel)
+ .ToList();
+ }
+ public List GetFilteredList(ClientSearchModel model)
+ {
+ if (!model.Id.HasValue)
+ {
+ return new();
+ }
+
+ using var context = new ClientsDatabase();
+ return context.Clients
+ .Include(x => x.Category)
+ .Where(x => x.Id == model.Id)
+ .Select(x => x.GetViewModel)
+ .ToList();
+ }
+ public ClientViewModel? GetElement(ClientSearchModel model)
+ {
+ if (!model.Id.HasValue)
+ {
+ return null;
+ }
+
+ using var context = new ClientsDatabase();
+ return context.Clients
+ .Include(x => x.Category)
+ .FirstOrDefault(x => x.Id == model.Id)
+ ?.GetViewModel;
+ }
+ public ClientViewModel? Insert(ClientBindingModel model)
+ {
+ using var context = new ClientsDatabase();
+ var newClient = Client.Create(context, model);
+ if (newClient == null)
+ {
+ return null;
+ }
+ context.Clients.Add(newClient);
+ context.SaveChanges();
+ return newClient.GetViewModel;
+ }
+ public ClientViewModel? Update(ClientBindingModel model)
+ {
+ using var context = new ClientsDatabase();
+ var account = context.Clients.FirstOrDefault(x => x.Id == model.Id);
+ if (account == null)
+ {
+ return null;
+ }
+ account.Update(model, context);
+ context.SaveChanges();
+ return account.GetViewModel;
+ }
+ public ClientViewModel? Delete(ClientBindingModel model)
+ {
+ using var context = new ClientsDatabase();
+ var element = context.Clients
+ .Include(x => x.Category)
+ .FirstOrDefault(rec => rec.Id == model.Id);
+ if (element != null)
+ {
+ context.Clients.Remove(element);
+ context.SaveChanges();
+ return element.GetViewModel;
+ }
+ return null;
+ }
+ }
+}
diff --git a/COP/ClientDataBaseImplement/Migrations/20241028080342_InitialCreate.Designer.cs b/COP/ClientDataBaseImplement/Migrations/20241028080342_InitialCreate.Designer.cs
new file mode 100644
index 0000000..b181b10
--- /dev/null
+++ b/COP/ClientDataBaseImplement/Migrations/20241028080342_InitialCreate.Designer.cs
@@ -0,0 +1,87 @@
+//
+using ClientDataBaseImplement;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace ClientDataBaseImplement.Migrations
+{
+ [DbContext(typeof(ClientsDatabase))]
+ [Migration("20241028080342_InitialCreate")]
+ partial class InitialCreate
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "7.0.20")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("ClientDataBaseImplement.Models.Category", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.ToTable("Categories");
+ });
+
+ modelBuilder.Entity("ClientDataBaseImplement.Models.Client", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("CategoryId")
+ .HasColumnType("int");
+
+ b.Property("Email")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Fio")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Photo")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CategoryId");
+
+ b.ToTable("Clients");
+ });
+
+ modelBuilder.Entity("ClientDataBaseImplement.Models.Client", b =>
+ {
+ b.HasOne("ClientDataBaseImplement.Models.Category", "Category")
+ .WithMany()
+ .HasForeignKey("CategoryId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Category");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/COP/ClientDataBaseImplement/Migrations/20241028080342_InitialCreate.cs b/COP/ClientDataBaseImplement/Migrations/20241028080342_InitialCreate.cs
new file mode 100644
index 0000000..cca47bb
--- /dev/null
+++ b/COP/ClientDataBaseImplement/Migrations/20241028080342_InitialCreate.cs
@@ -0,0 +1,64 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace ClientDataBaseImplement.Migrations
+{
+ ///
+ public partial class InitialCreate : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "Categories",
+ columns: table => new
+ {
+ Id = table.Column(type: "int", nullable: false)
+ .Annotation("SqlServer:Identity", "1, 1"),
+ Name = table.Column(type: "nvarchar(max)", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Categories", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Clients",
+ columns: table => new
+ {
+ Id = table.Column(type: "int", nullable: false)
+ .Annotation("SqlServer:Identity", "1, 1"),
+ Fio = table.Column(type: "nvarchar(max)", nullable: false),
+ Email = table.Column(type: "nvarchar(max)", nullable: false),
+ CategoryId = table.Column(type: "int", nullable: false),
+ Photo = table.Column(type: "nvarchar(max)", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Clients", x => x.Id);
+ table.ForeignKey(
+ name: "FK_Clients_Categories_CategoryId",
+ column: x => x.CategoryId,
+ principalTable: "Categories",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Clients_CategoryId",
+ table: "Clients",
+ column: "CategoryId");
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "Clients");
+
+ migrationBuilder.DropTable(
+ name: "Categories");
+ }
+ }
+}
diff --git a/COP/ClientDataBaseImplement/Migrations/ClientsDatabaseModelSnapshot.cs b/COP/ClientDataBaseImplement/Migrations/ClientsDatabaseModelSnapshot.cs
new file mode 100644
index 0000000..1090e22
--- /dev/null
+++ b/COP/ClientDataBaseImplement/Migrations/ClientsDatabaseModelSnapshot.cs
@@ -0,0 +1,84 @@
+//
+using ClientDataBaseImplement;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace ClientDataBaseImplement.Migrations
+{
+ [DbContext(typeof(ClientsDatabase))]
+ partial class ClientsDatabaseModelSnapshot : ModelSnapshot
+ {
+ protected override void BuildModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "7.0.20")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("ClientDataBaseImplement.Models.Category", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.ToTable("Categories");
+ });
+
+ modelBuilder.Entity("ClientDataBaseImplement.Models.Client", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("CategoryId")
+ .HasColumnType("int");
+
+ b.Property("Email")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Fio")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Photo")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CategoryId");
+
+ b.ToTable("Clients");
+ });
+
+ modelBuilder.Entity("ClientDataBaseImplement.Models.Client", b =>
+ {
+ b.HasOne("ClientDataBaseImplement.Models.Category", "Category")
+ .WithMany()
+ .HasForeignKey("CategoryId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Category");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/COP/ClientDataBaseImplement/Models/Category.cs b/COP/ClientDataBaseImplement/Models/Category.cs
new file mode 100644
index 0000000..c8a72b8
--- /dev/null
+++ b/COP/ClientDataBaseImplement/Models/Category.cs
@@ -0,0 +1,54 @@
+using ClientsDataModels.Models;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Security.Principal;
+using System.Text;
+using System.Threading.Tasks;
+using ClientsContracts.BindingModels;
+using ClientsContracts.ViewModels;
+
+namespace ClientDataBaseImplement.Models
+{
+ public class Category : ICategoryModel
+ {
+ public int Id { get; private set; }
+ [Required]
+ public string Name { get; private set; } = string.Empty;
+
+ public static Category? Create(CategoryBindingModel? model)
+ {
+ if (model == null)
+ {
+ return null;
+ }
+ return new Category()
+ {
+ Id = model.Id,
+ Name = model.Name,
+ };
+ }
+ public static Category? Create(CategoryViewModel? model)
+ {
+ return new Category()
+ {
+ Id = model.Id,
+ Name = model.Name,
+ };
+ }
+ public void Update(CategoryBindingModel? model)
+ {
+ if (model == null)
+ {
+ return;
+ }
+ Name = model.Name;
+ }
+ public CategoryViewModel GetViewModel => new()
+ {
+ Id = Id,
+ Name = Name,
+ };
+ }
+}
diff --git a/COP/ClientDataBaseImplement/Models/Client.cs b/COP/ClientDataBaseImplement/Models/Client.cs
new file mode 100644
index 0000000..39937cf
--- /dev/null
+++ b/COP/ClientDataBaseImplement/Models/Client.cs
@@ -0,0 +1,68 @@
+using ClientsDataModels.Models;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Security.Principal;
+using System.Text;
+using System.Threading.Tasks;
+using ClientsContracts.BindingModels;
+using ClientsContracts.ViewModels;
+
+namespace ClientDataBaseImplement.Models
+{
+ public class Client : IClientModel
+ {
+ [Required]
+ public string Fio { get; set; } = string.Empty;
+ [Required]
+ public string Email { get; set; } = string.Empty;
+
+ public int Id { get; private set; }
+
+ public int CategoryId { get; set; }
+
+ public virtual Category Category { get; set; } = new();
+ [Required]
+ public string Photo { get; set; } = string.Empty;
+
+ public static Client? Create(ClientsDatabase context, ClientBindingModel? model)
+ {
+ if (model == null)
+ {
+ return null;
+ }
+ return new Client()
+ {
+ Id = model.Id,
+ Fio = model.Fio,
+ Email = model.Email,
+ CategoryId = model.CategoryId,
+ Category = context.Categories.First(x => x.Id == model.CategoryId),
+ Photo = model.Photo,
+ };
+ }
+
+ public void Update(ClientBindingModel? model, ClientsDatabase context)
+ {
+ if (model == null)
+ {
+ return;
+ }
+ Fio = model.Fio;
+ CategoryId = model.CategoryId;
+ Category = context.Categories.First(x => x.Id == model.CategoryId);
+ Photo = model.Photo;
+ }
+
+ public ClientViewModel GetViewModel => new()
+ {
+ Id = Id,
+ Fio = Fio,
+ Email = Email,
+ CategoryId = CategoryId,
+ CategoryName = Category.Name,
+ Photo = Photo,
+ };
+ }
+}
diff --git a/COP/ClientsBusinessLogics/BusinessLogics/CategoryLogic.cs b/COP/ClientsBusinessLogics/BusinessLogics/CategoryLogic.cs
new file mode 100644
index 0000000..f43806c
--- /dev/null
+++ b/COP/ClientsBusinessLogics/BusinessLogics/CategoryLogic.cs
@@ -0,0 +1,92 @@
+using ClientsContracts.BusinessLogicContracts;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ClientsContracts.StorageContracts;
+using ClientsContracts.ViewModels;
+using ClientsContracts.SearchModels;
+using ClientsContracts.BindingModels;
+
+namespace ClientsBusinessLogics.BusinessLogics
+{
+ public class CategoryLogic : ICategoryLogic
+ {
+ private readonly ICategoryStorage _categoryStorage;
+
+ public CategoryLogic(ICategoryStorage categoryStorage)
+ {
+ _categoryStorage = categoryStorage;
+ }
+
+ public List? ReadList(CategorySearchModel? model)
+ {
+ var list = model == null ? _categoryStorage.GetFullList() : _categoryStorage.GetFilteredList(model);
+ if (list == null)
+ {
+ return null;
+ }
+ return list;
+ }
+
+ public CategoryViewModel? ReadElement(CategorySearchModel model)
+ {
+ if (model == null)
+ {
+ throw new ArgumentNullException(nameof(model));
+ }
+ var element = _categoryStorage.GetElement(model);
+ if (element == null)
+ {
+ return null;
+ }
+ return element;
+ }
+
+ public bool Create(CategoryBindingModel model)
+ {
+ CheckModel(model);
+ if (_categoryStorage.Insert(model) == null)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public bool Update(CategoryBindingModel model)
+ {
+ CheckModel(model);
+ if (_categoryStorage.Update(model) == null)
+ {
+ return false;
+ }
+ return true;
+ }
+ public bool Delete(CategoryBindingModel model)
+ {
+ CheckModel(model, false);
+ if (_categoryStorage.Delete(model) == null)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private void CheckModel(CategoryBindingModel model, bool withParams = true)
+ {
+ if (model == null)
+ {
+ throw new ArgumentNullException(nameof(model));
+ }
+ if (!withParams)
+ {
+ return;
+ }
+ if (string.IsNullOrEmpty(model.Name))
+ {
+ throw new ArgumentNullException("Нет названия категории", nameof(model.Name));
+ }
+ }
+ }
+}
diff --git a/COP/ClientsBusinessLogics/BusinessLogics/ClientLogic.cs b/COP/ClientsBusinessLogics/BusinessLogics/ClientLogic.cs
new file mode 100644
index 0000000..da0afee
--- /dev/null
+++ b/COP/ClientsBusinessLogics/BusinessLogics/ClientLogic.cs
@@ -0,0 +1,96 @@
+using ClientsContracts.BusinessLogicContracts;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ClientsContracts.StorageContracts;
+using ClientsContracts.ViewModels;
+using ClientsContracts.SearchModels;
+using ClientsContracts.BindingModels;
+
+namespace ClientsBusinessLogics.BusinessLogics
+{
+ public class ClientLogic : IClientLogic
+ {
+ private readonly IClientStorage _clientStorage;
+
+ public ClientLogic(IClientStorage clientStorage)
+ {
+ _clientStorage = clientStorage;
+ }
+
+ public List? ReadList(ClientSearchModel? model)
+ {
+ var list = model == null ? _clientStorage.GetFullList() : _clientStorage.GetFilteredList(model);
+ if (list == null)
+ {
+ return null;
+ }
+ return list;
+ }
+
+ public ClientViewModel? ReadElement(ClientSearchModel model)
+ {
+ if (model == null)
+ {
+ throw new ArgumentNullException(nameof(model));
+ }
+ var element = _clientStorage.GetElement(model);
+ if (element == null)
+ {
+ return null;
+ }
+ return element;
+ }
+
+ public bool Create(ClientBindingModel model)
+ {
+ CheckModel(model);
+ if (_clientStorage.Insert(model) == null)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public bool Update(ClientBindingModel model)
+ {
+ CheckModel(model);
+ if (_clientStorage.Update(model) == null)
+ {
+ return false;
+ }
+ return true;
+ }
+ public bool Delete(ClientBindingModel model)
+ {
+ CheckModel(model, false);
+ if (_clientStorage.Delete(model) == null)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private void CheckModel(ClientBindingModel model, bool withParams = true)
+ {
+ if (model == null)
+ {
+ throw new ArgumentNullException(nameof(model));
+ }
+ if (!withParams)
+ {
+ return;
+ }
+ if (string.IsNullOrEmpty(model.Fio))
+ {
+ throw new ArgumentNullException("Нет имени клиента", nameof(model.Fio));
+ }
+ if (string.IsNullOrEmpty(model.Email))
+ {
+ throw new ArgumentNullException("Нет электронной почты пользователя", nameof(model.Email));
+ }
+ }
+ }
+}
diff --git a/COP/ClientsBusinessLogics/ClientsBusinessLogics.csproj b/COP/ClientsBusinessLogics/ClientsBusinessLogics.csproj
new file mode 100644
index 0000000..21d9b6c
--- /dev/null
+++ b/COP/ClientsBusinessLogics/ClientsBusinessLogics.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/COP/ClientsContracts/BindingModels/CategoryBindingModel.cs b/COP/ClientsContracts/BindingModels/CategoryBindingModel.cs
new file mode 100644
index 0000000..9f1d65e
--- /dev/null
+++ b/COP/ClientsContracts/BindingModels/CategoryBindingModel.cs
@@ -0,0 +1,16 @@
+using ClientsDataModels.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ClientsContracts.BindingModels
+{
+ public class CategoryBindingModel : ICategoryModel
+ {
+ public string Name { get; set; } = String.Empty;
+
+ public int Id { get; set; }
+ }
+}
diff --git a/COP/ClientsContracts/BindingModels/ClientBindingModel.cs b/COP/ClientsContracts/BindingModels/ClientBindingModel.cs
new file mode 100644
index 0000000..5b01141
--- /dev/null
+++ b/COP/ClientsContracts/BindingModels/ClientBindingModel.cs
@@ -0,0 +1,22 @@
+using ClientsDataModels.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ClientsContracts.BindingModels
+{
+ public class ClientBindingModel : IClientModel
+ {
+ public string Fio { get; set; } = string.Empty;
+
+ public string Email { get; set; } = string.Empty;
+
+ public int Id { get; set; }
+
+ public int CategoryId { get; set; }
+
+ public string Photo { get; set; }
+ }
+}
diff --git a/COP/ClientsContracts/BusinessLogicContracts/ICategoryLogic.cs b/COP/ClientsContracts/BusinessLogicContracts/ICategoryLogic.cs
new file mode 100644
index 0000000..2433c89
--- /dev/null
+++ b/COP/ClientsContracts/BusinessLogicContracts/ICategoryLogic.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ClientsContracts.ViewModels;
+using ClientsContracts.SearchModels;
+using ClientsContracts.BindingModels;
+
+namespace ClientsContracts.BusinessLogicContracts
+{
+ public interface ICategoryLogic
+ {
+ List? ReadList(CategorySearchModel? model);
+ CategoryViewModel? ReadElement(CategorySearchModel model);
+ bool Create(CategoryBindingModel model);
+ bool Update(CategoryBindingModel model);
+ bool Delete(CategoryBindingModel model);
+ }
+}
diff --git a/COP/ClientsContracts/BusinessLogicContracts/IClientLogic.cs b/COP/ClientsContracts/BusinessLogicContracts/IClientLogic.cs
new file mode 100644
index 0000000..84ab82c
--- /dev/null
+++ b/COP/ClientsContracts/BusinessLogicContracts/IClientLogic.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ClientsContracts.ViewModels;
+using ClientsContracts.BindingModels;
+using ClientsContracts.SearchModels;
+
+namespace ClientsContracts.BusinessLogicContracts
+{
+ public interface IClientLogic
+ {
+ List? ReadList(ClientSearchModel? model);
+ ClientViewModel? ReadElement(ClientSearchModel model);
+ bool Create(ClientBindingModel model);
+ bool Update(ClientBindingModel model);
+ bool Delete(ClientBindingModel model);
+ }
+}
diff --git a/COP/ClientsContracts/ClientsContracts.csproj b/COP/ClientsContracts/ClientsContracts.csproj
new file mode 100644
index 0000000..db532a4
--- /dev/null
+++ b/COP/ClientsContracts/ClientsContracts.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/COP/ClientsContracts/SearchModels/CategorySearchModel.cs b/COP/ClientsContracts/SearchModels/CategorySearchModel.cs
new file mode 100644
index 0000000..2bf04f8
--- /dev/null
+++ b/COP/ClientsContracts/SearchModels/CategorySearchModel.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ClientsContracts.SearchModels
+{
+ public class CategorySearchModel
+ {
+ public int? Id { get; set; }
+ }
+}
diff --git a/COP/ClientsContracts/SearchModels/ClientSearchModel.cs b/COP/ClientsContracts/SearchModels/ClientSearchModel.cs
new file mode 100644
index 0000000..f37858f
--- /dev/null
+++ b/COP/ClientsContracts/SearchModels/ClientSearchModel.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ClientsContracts.SearchModels
+{
+ public class ClientSearchModel
+ {
+ public int? Id { get; set; }
+ }
+}
diff --git a/COP/ClientsContracts/StorageContracts/ICategoryStorage.cs b/COP/ClientsContracts/StorageContracts/ICategoryStorage.cs
new file mode 100644
index 0000000..0aae5bc
--- /dev/null
+++ b/COP/ClientsContracts/StorageContracts/ICategoryStorage.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ClientsContracts.ViewModels;
+using ClientsContracts.BindingModels;
+using ClientsContracts.SearchModels;
+
+namespace ClientsContracts.StorageContracts
+{
+ public interface ICategoryStorage
+ {
+ List GetFullList();
+ List GetFilteredList(CategorySearchModel model);
+ CategoryViewModel? GetElement(CategorySearchModel model);
+ CategoryViewModel? Insert(CategoryBindingModel model);
+ CategoryViewModel? Update(CategoryBindingModel model);
+ CategoryViewModel? Delete(CategoryBindingModel model);
+ }
+}
diff --git a/COP/ClientsContracts/StorageContracts/IClientStorage.cs b/COP/ClientsContracts/StorageContracts/IClientStorage.cs
new file mode 100644
index 0000000..6dcaa27
--- /dev/null
+++ b/COP/ClientsContracts/StorageContracts/IClientStorage.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ClientsContracts.ViewModels;
+using ClientsContracts.BindingModels;
+using ClientsContracts.SearchModels;
+
+namespace ClientsContracts.StorageContracts
+{
+ public interface IClientStorage
+ {
+ List GetFullList();
+ List GetFilteredList(ClientSearchModel model);
+ ClientViewModel? GetElement(ClientSearchModel model);
+ ClientViewModel? Insert(ClientBindingModel model);
+ ClientViewModel? Update(ClientBindingModel model);
+ ClientViewModel? Delete(ClientBindingModel model);
+ }
+}
diff --git a/COP/ClientsContracts/ViewModels/CategoryViewModel.cs b/COP/ClientsContracts/ViewModels/CategoryViewModel.cs
new file mode 100644
index 0000000..88d04ba
--- /dev/null
+++ b/COP/ClientsContracts/ViewModels/CategoryViewModel.cs
@@ -0,0 +1,17 @@
+using ClientsDataModels.Models;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ClientsContracts.ViewModels
+{
+ public class CategoryViewModel : ICategoryModel
+ {
+ [DisplayName("Название")]
+ public string Name { get; set; } = string.Empty;
+ public int Id { get; set; }
+ }
+}
diff --git a/COP/ClientsContracts/ViewModels/ClientViewModel.cs b/COP/ClientsContracts/ViewModels/ClientViewModel.cs
new file mode 100644
index 0000000..85c0cb4
--- /dev/null
+++ b/COP/ClientsContracts/ViewModels/ClientViewModel.cs
@@ -0,0 +1,23 @@
+using ClientsContracts.BusinessLogicContracts;
+using ClientsDataModels.Models;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ClientsContracts.ViewModels
+{
+ public class ClientViewModel : IClientModel
+ {
+ [DisplayName("ФИО")]
+ public string Fio { get; set; } = string.Empty;
+ [DisplayName("Электронная почта")]
+ public string Email { get; set; } = string.Empty;
+ public int Id { get; set; }
+ public int CategoryId { get; set; }
+ public string CategoryName { get; set; } = string.Empty;
+ public string Photo { get; set; } = string.Empty;
+ }
+}
diff --git a/COP/ClientsDataModels/ClientsDataModels.csproj b/COP/ClientsDataModels/ClientsDataModels.csproj
new file mode 100644
index 0000000..6aa140a
--- /dev/null
+++ b/COP/ClientsDataModels/ClientsDataModels.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/COP/ClientsDataModels/IId.cs b/COP/ClientsDataModels/IId.cs
new file mode 100644
index 0000000..9c13d93
--- /dev/null
+++ b/COP/ClientsDataModels/IId.cs
@@ -0,0 +1,7 @@
+namespace ClientsDataModels
+{
+ public interface IId
+ {
+ int Id { get; }
+ }
+}
\ No newline at end of file
diff --git a/COP/ClientsDataModels/Models/ICategoryModel.cs b/COP/ClientsDataModels/Models/ICategoryModel.cs
new file mode 100644
index 0000000..c89b9af
--- /dev/null
+++ b/COP/ClientsDataModels/Models/ICategoryModel.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ClientsDataModels.Models
+{
+ public interface ICategoryModel : IId
+ {
+ string Name { get; }
+ }
+}
diff --git a/COP/ClientsDataModels/Models/IClientModel.cs b/COP/ClientsDataModels/Models/IClientModel.cs
new file mode 100644
index 0000000..d5b98f3
--- /dev/null
+++ b/COP/ClientsDataModels/Models/IClientModel.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ClientsDataModels.Models
+{
+ public interface IClientModel : IId
+ {
+ string Fio { get; }
+ string Email { get; }
+ public int CategoryId { get; }
+ public string Photo { get; }
+ }
+}
diff --git a/COP/Components/Components.csproj b/COP/Components/Components.csproj
index 57ac473..5ce4c2a 100644
--- a/COP/Components/Components.csproj
+++ b/COP/Components/Components.csproj
@@ -5,6 +5,7 @@
enable
true
enable
+ True
diff --git a/COP/WinFormsTest/FormCategories.Designer.cs b/COP/WinFormsTest/FormCategories.Designer.cs
new file mode 100644
index 0000000..ec75734
--- /dev/null
+++ b/COP/WinFormsTest/FormCategories.Designer.cs
@@ -0,0 +1,90 @@
+namespace WinFormsTest
+{
+ partial class FormCategories
+ {
+ ///
+ /// 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()
+ {
+ this.dataGridView = new System.Windows.Forms.DataGridView();
+ this.NameCol = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.Id = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).BeginInit();
+ this.SuspendLayout();
+ //
+ // dataGridView
+ //
+ this.dataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+ this.dataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
+ this.NameCol,
+ this.Id});
+ this.dataGridView.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.dataGridView.Location = new System.Drawing.Point(0, 0);
+ this.dataGridView.Name = "dataGridView";
+ this.dataGridView.RowHeadersWidth = 51;
+ this.dataGridView.RowTemplate.Height = 29;
+ this.dataGridView.Size = new System.Drawing.Size(613, 304);
+ this.dataGridView.TabIndex = 0;
+ this.dataGridView.CellValueChanged += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView_CellValueChanged);
+ this.dataGridView.UserDeletingRow += new System.Windows.Forms.DataGridViewRowCancelEventHandler(this.dataGridView_UserDeletingRow);
+ this.dataGridView.KeyUp += new System.Windows.Forms.KeyEventHandler(this.dataGridView_KeyUp);
+ //
+ // NameCol
+ //
+ this.NameCol.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
+ this.NameCol.HeaderText = "Название";
+ this.NameCol.MinimumWidth = 6;
+ this.NameCol.Name = "NameCol";
+ //
+ // Id
+ //
+ this.Id.HeaderText = "Id";
+ this.Id.MinimumWidth = 6;
+ this.Id.Name = "Id";
+ this.Id.Visible = false;
+ this.Id.Width = 125;
+ //
+ // FormCategories
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.Color.White;
+ this.ClientSize = new System.Drawing.Size(613, 304);
+ this.Controls.Add(this.dataGridView);
+ this.Name = "FormCategories";
+ this.Text = "Категории";
+ this.Load += new System.EventHandler(this.FormCategories_Load);
+ ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private DataGridView dataGridView;
+ private DataGridViewTextBoxColumn NameCol;
+ private DataGridViewTextBoxColumn Id;
+ }
+}
\ No newline at end of file
diff --git a/COP/WinFormsTest/FormCategories.cs b/COP/WinFormsTest/FormCategories.cs
new file mode 100644
index 0000000..4b85409
--- /dev/null
+++ b/COP/WinFormsTest/FormCategories.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using ClientsContracts.BindingModels;
+using ClientsContracts.BusinessLogicContracts;
+
+namespace WinFormsTest
+{
+ public partial class FormCategories : Form
+ {
+ private readonly ICategoryLogic _logic;
+ private bool loading = false;
+
+ public FormCategories(ICategoryLogic logic)
+ {
+ InitializeComponent();
+ _logic = logic;
+ }
+
+ private void FormCategories_Load(object sender, EventArgs e)
+ {
+ LoadData();
+ }
+
+ private void LoadData()
+ {
+ loading = true;
+ try
+ {
+ var list = _logic.ReadList(null);
+ if (list != null)
+ {
+ foreach (var interest in list)
+ {
+ int rowIndex = dataGridView.Rows.Add();
+ dataGridView.Rows[rowIndex].Cells[0].Value = interest.Name;
+ dataGridView.Rows[rowIndex].Cells[1].Value = interest.Id;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ finally
+ {
+ loading = false;
+ }
+ }
+
+ private void dataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
+ {
+ if (loading || e.RowIndex < 0 || e.ColumnIndex != 0) return;
+ if (dataGridView.Rows[e.RowIndex].Cells[1].Value != null && !string.IsNullOrEmpty(dataGridView.Rows[e.RowIndex].Cells[1].Value.ToString()))
+ {
+ var name = dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
+ if (name is null) return;
+ _logic.Update(new CategoryBindingModel { Id = Convert.ToInt32(dataGridView.Rows[e.RowIndex].Cells[1].Value), Name = name.ToString() });
+ }
+ else
+ {
+ var name = dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
+ if (name is null) return;
+ _logic.Create(new CategoryBindingModel { Id = 0, Name = name.ToString() });
+ int newCategoryId = _logic.ReadList(null).ToList().Last().Id;
+ dataGridView.Rows[e.RowIndex].Cells[1].Value = newCategoryId;
+ }
+ }
+
+ private void dataGridView_KeyUp(object sender, KeyEventArgs e)
+ {
+ switch (e.KeyCode)
+ {
+ case Keys.Insert:
+ dataGridView.Rows.Add();
+ break;
+ }
+ }
+
+ private void deleteRows(DataGridViewSelectedRowCollection rows)
+ {
+ for (int i = 0; i < rows.Count; i++)
+ {
+ DataGridViewRow row = rows[i];
+ if (!_logic.Delete(new CategoryBindingModel { Id = Convert.ToInt32(row.Cells[1].Value) })) continue;
+ dataGridView.Rows.Remove(row);
+ }
+ }
+
+ private void dataGridView_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
+ {
+ e.Cancel = true;
+ if (dataGridView.SelectedRows == null) return;
+ if (MessageBox.Show("Удалить записи?", "Подтвердите действие", MessageBoxButtons.YesNo) == DialogResult.No) return;
+ deleteRows(dataGridView.SelectedRows);
+ }
+ }
+}
diff --git a/COP/WinFormsTest/FormCategories.resx b/COP/WinFormsTest/FormCategories.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/COP/WinFormsTest/FormCategories.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/COP/WinFormsTest/FormClient.Designer.cs b/COP/WinFormsTest/FormClient.Designer.cs
new file mode 100644
index 0000000..ff44df7
--- /dev/null
+++ b/COP/WinFormsTest/FormClient.Designer.cs
@@ -0,0 +1,193 @@
+namespace WinFormsTest
+{
+ partial class FormClient
+ {
+ ///
+ /// 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()
+ {
+ this.label1 = new System.Windows.Forms.Label();
+ this.textBoxLogin = new System.Windows.Forms.TextBox();
+ this.textBoxPassword = new System.Windows.Forms.TextBox();
+ this.label2 = new System.Windows.Forms.Label();
+ this.label3 = new System.Windows.Forms.Label();
+ this.mailControl = new BulatovaComponents.Components.UserEmailTextBox();
+ this.UserCheckedListBox = new Components.Components.UserCheckedListBox();
+ this.label4 = new System.Windows.Forms.Label();
+ this.buttonSave = new System.Windows.Forms.Button();
+ this.buttonCancel = new System.Windows.Forms.Button();
+ this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
+ this.buttonAvatar = new System.Windows.Forms.Button();
+ this.SuspendLayout();
+ //
+ // label1
+ //
+ this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(12, 9);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(52, 20);
+ this.label1.TabIndex = 0;
+ this.label1.Text = "Логин";
+ //
+ // textBoxLogin
+ //
+ this.textBoxLogin.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
+ this.textBoxLogin.Location = new System.Drawing.Point(12, 32);
+ this.textBoxLogin.Name = "textBoxLogin";
+ this.textBoxLogin.Size = new System.Drawing.Size(389, 27);
+ this.textBoxLogin.TabIndex = 1;
+ //
+ // textBoxPassword
+ //
+ this.textBoxPassword.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
+ this.textBoxPassword.Location = new System.Drawing.Point(12, 86);
+ this.textBoxPassword.Name = "textBoxPassword";
+ this.textBoxPassword.Size = new System.Drawing.Size(389, 27);
+ this.textBoxPassword.TabIndex = 3;
+ //
+ // label2
+ //
+ this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(12, 63);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(62, 20);
+ this.label2.TabIndex = 2;
+ this.label2.Text = "Пароль";
+ //
+ // label3
+ //
+ this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
+ this.label3.AutoSize = true;
+ this.label3.Location = new System.Drawing.Point(12, 116);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(51, 20);
+ this.label3.TabIndex = 4;
+ this.label3.Text = "Почта";
+ //
+ // mailControl
+ //
+ this.mailControl.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
+ this.mailControl.Email = null;
+ this.mailControl.Location = new System.Drawing.Point(12, 139);
+ this.mailControl.Name = "mailControl";
+ this.mailControl.Size = new System.Drawing.Size(389, 42);
+ this.mailControl.TabIndex = 5;
+ this.mailControl.validateEmailRegex = null;
+ //
+ // UserCheckedListBox
+ //
+ this.UserCheckedListBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
+ this.UserCheckedListBox.Location = new System.Drawing.Point(12, 207);
+ this.UserCheckedListBox.Name = "UserCheckedListBox";
+ this.UserCheckedListBox.selectedItem = null;
+ this.UserCheckedListBox.Size = new System.Drawing.Size(389, 130);
+ this.UserCheckedListBox.TabIndex = 6;
+ //
+ // label4
+ //
+ this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
+ this.label4.AutoSize = true;
+ this.label4.Location = new System.Drawing.Point(12, 184);
+ this.label4.Name = "label4";
+ this.label4.Size = new System.Drawing.Size(78, 20);
+ this.label4.TabIndex = 7;
+ this.label4.Text = "Интересы";
+ //
+ // buttonSave
+ //
+ this.buttonSave.Location = new System.Drawing.Point(12, 420);
+ this.buttonSave.Name = "buttonSave";
+ this.buttonSave.Size = new System.Drawing.Size(94, 29);
+ this.buttonSave.TabIndex = 8;
+ this.buttonSave.Text = "Сохранить";
+ this.buttonSave.UseVisualStyleBackColor = true;
+ this.buttonSave.Click += new System.EventHandler(this.buttonSave_Click);
+ //
+ // buttonCancel
+ //
+ this.buttonCancel.Location = new System.Drawing.Point(307, 420);
+ this.buttonCancel.Name = "buttonCancel";
+ this.buttonCancel.Size = new System.Drawing.Size(94, 29);
+ this.buttonCancel.TabIndex = 9;
+ this.buttonCancel.Text = "Отмена";
+ this.buttonCancel.UseVisualStyleBackColor = true;
+ this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click);
+ //
+ // openFileDialog
+ //
+ this.openFileDialog.FileName = "openFileDialog1";
+ //
+ // buttonAvatar
+ //
+ this.buttonAvatar.Location = new System.Drawing.Point(12, 343);
+ this.buttonAvatar.Name = "buttonAvatar";
+ this.buttonAvatar.Size = new System.Drawing.Size(389, 29);
+ this.buttonAvatar.TabIndex = 10;
+ this.buttonAvatar.Text = "Выбрать аватар";
+ this.buttonAvatar.UseVisualStyleBackColor = true;
+ this.buttonAvatar.Click += new System.EventHandler(this.buttonAvatar_Click);
+ //
+ // FormAccount
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(413, 461);
+ this.Controls.Add(this.buttonAvatar);
+ this.Controls.Add(this.buttonCancel);
+ this.Controls.Add(this.buttonSave);
+ this.Controls.Add(this.label4);
+ this.Controls.Add(this.UserCheckedListBox);
+ this.Controls.Add(this.mailControl);
+ this.Controls.Add(this.label3);
+ this.Controls.Add(this.textBoxPassword);
+ this.Controls.Add(this.label2);
+ this.Controls.Add(this.textBoxLogin);
+ this.Controls.Add(this.label1);
+ this.Name = "FormClient";
+ this.Text = "Аккаунт";
+ this.Load += new System.EventHandler(this.FormClient_Load);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private Label label1;
+ private TextBox textBoxLogin;
+ private TextBox textBoxPassword;
+ private Label label2;
+ private Label label3;
+ private BulatovaComponents.Components.UserEmailTextBox mailControl;
+ private Components.Components.UserCheckedListBox UserCheckedListBox;
+ private Label label4;
+ private Button buttonSave;
+ private Button buttonCancel;
+ private OpenFileDialog openFileDialog;
+ private Button buttonAvatar;
+ }
+}
\ No newline at end of file
diff --git a/COP/WinFormsTest/FormClient.cs b/COP/WinFormsTest/FormClient.cs
new file mode 100644
index 0000000..1cd9ff0
--- /dev/null
+++ b/COP/WinFormsTest/FormClient.cs
@@ -0,0 +1,123 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using ClientsContracts.BusinessLogicContracts;
+using ClientsContracts.ViewModels;
+using ClientsContracts.SearchModels;
+using Components.Components;
+using ClientsContracts.BindingModels;
+
+namespace WinFormsTest
+{
+ public partial class FormClient : Form
+ {
+ private int? _id;
+ private readonly IClientLogic _logic;
+ private readonly ICategoryLogic _categoryLogic;
+ private List _categories;
+ private string? photo = null;
+ public int Id { set { _id = value; } }
+
+ public FormClient(IClientLogic logic, ICategoryLogic categoryLogic)
+ {
+ InitializeComponent();
+ _logic = logic;
+ _categoryLogic = categoryLogic;
+ _categories = new List();
+ }
+
+ private void FormClient_Load(object sender, EventArgs e)
+ {
+ _categories = _categoryLogic.ReadList(null);
+ UserCheckedListBox.addItems(_categories.Select(x => x.Name).ToList());
+ mailControl.validateEmailRegex = new System.Text.RegularExpressions.Regex(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$");
+ mailControl.setTooltipText("name@example.com");
+ if (_id.HasValue)
+ {
+ try
+ {
+ var view = _logic.ReadElement(new ClientSearchModel { Id = _id.Value });
+ if (view != null)
+ {
+ textBoxLogin.Text = view.Fio;
+ mailControl.Email = view.Email;
+ photo = view.Photo;
+
+ UserCheckedListBox.selectedItem = view.CategoryName;
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+
+ private void buttonCancel_Click(object sender, EventArgs e)
+ {
+ DialogResult = DialogResult.Cancel;
+ Close();
+ }
+
+ private void buttonSave_Click(object sender, EventArgs e)
+ {
+ if (string.IsNullOrEmpty(textBoxLogin.Text))
+ {
+ MessageBox.Show("Заполните название", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+ if (string.IsNullOrEmpty(mailControl.Email))
+ {
+ MessageBox.Show("Заполните почту или исправьте написание почты", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+ if (UserCheckedListBox.selectedItem == null)
+ {
+ MessageBox.Show("Заполните интересы", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+ if (photo == null)
+ {
+ MessageBox.Show("Выберите аватар", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+ try
+ {
+ var model = new ClientBindingModel
+ {
+ Id = _id ?? 0,
+ Fio = textBoxLogin.Text,
+ Email = mailControl.Email,
+ CategoryId = _categories.First(x => x.Name == UserCheckedListBox.selectedItem).Id,
+ Photo = photo
+ };
+ 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)
+ {
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ private void buttonAvatar_Click(object sender, EventArgs e)
+ {
+ if (openFileDialog.ShowDialog() != DialogResult.Cancel)
+ {
+ photo = openFileDialog.FileName;
+ }
+ }
+ }
+}
diff --git a/COP/WinFormsTest/FormClient.resx b/COP/WinFormsTest/FormClient.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/COP/WinFormsTest/FormClient.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/COP/WinFormsTest/FormMain.Designer.cs b/COP/WinFormsTest/FormMain.Designer.cs
new file mode 100644
index 0000000..af36509
--- /dev/null
+++ b/COP/WinFormsTest/FormMain.Designer.cs
@@ -0,0 +1,39 @@
+namespace WinFormsTest
+{
+ 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);
+ }
+
+ #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()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(800, 450);
+ this.Text = "FormMain";
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/COP/WinFormsTest/FormMain.cs b/COP/WinFormsTest/FormMain.cs
new file mode 100644
index 0000000..4a4ff40
--- /dev/null
+++ b/COP/WinFormsTest/FormMain.cs
@@ -0,0 +1,20 @@
+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 WinFormsTest
+{
+ public partial class FormMain : Form
+ {
+ public FormMain()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/COP/WinFormsTest/FormMain.resx b/COP/WinFormsTest/FormMain.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/COP/WinFormsTest/FormMain.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/COP/WinFormsTest/Program.cs b/COP/WinFormsTest/Program.cs
index 58dce58..8482fd7 100644
--- a/COP/WinFormsTest/Program.cs
+++ b/COP/WinFormsTest/Program.cs
@@ -1,7 +1,15 @@
+using Microsoft.Extensions.DependencyInjection;
+using ClientsContracts.BusinessLogicContracts;
+using ClientsContracts.StorageContracts;
+using ClientsBusinessLogics.BusinessLogics;
+using ClientDataBaseImplement.Implements;
+
namespace WinFormsTest
{
internal static class Program
{
+ private static ServiceProvider? _serviceProvider;
+ public static ServiceProvider? ServiceProvider => _serviceProvider;
///
/// The main entry point for the application.
///
@@ -11,7 +19,21 @@ namespace WinFormsTest
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
+ var services = new ServiceCollection();
+ ConfigureServices(services);
+ _serviceProvider = services.BuildServiceProvider();
Application.Run(new FormTest());
}
+
+ private static void ConfigureServices(ServiceCollection services)
+ {
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ }
}
}
\ No newline at end of file
diff --git a/COP/WinFormsTest/WinFormsTest.csproj b/COP/WinFormsTest/WinFormsTest.csproj
index a813ce4..7223cef 100644
--- a/COP/WinFormsTest/WinFormsTest.csproj
+++ b/COP/WinFormsTest/WinFormsTest.csproj
@@ -9,6 +9,18 @@
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtrsansitive
+
+
+
+
+
+