AppCore.Helpers 1.0.13

dotnet add package AppCore.Helpers --version 1.0.13
                    
NuGet\Install-Package AppCore.Helpers -Version 1.0.13
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="AppCore.Helpers" Version="1.0.13" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="AppCore.Helpers" Version="1.0.13" />
                    
Directory.Packages.props
<PackageReference Include="AppCore.Helpers" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add AppCore.Helpers --version 1.0.13
                    
#r "nuget: AppCore.Helpers, 1.0.13"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package AppCore.Helpers@1.0.13
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=AppCore.Helpers&version=1.0.13
                    
Install as a Cake Addin
#tool nuget:?package=AppCore.Helpers&version=1.0.13
                    
Install as a Cake Tool
DatabaseService.Configure(
    "Server=ИМЯ_СЕРВЕРА;Database=toy_shop;User ID=ЛОГИН;Password=ПАРОЛЬ;TrustServerCertificate=True;");

UserSession.cs

    public static class UserSession
    {
        public static int UserId { get; set; }

        public static string Login { get; set; } = string.Empty;

        public static string FullName { get; set; } = "Гость";

        public static string Role { get; set; } = "Гость";

        public static void SetUser(int userId, string login, string fullName, string role)
        {
            UserId = userId;
            Login = login;
            FullName = fullName;
            Role = role;
        }

        public static void SetGuest()
        {
            UserId = 0;
            Login = "guest";
        }

        public static void Clear()
        {
            UserId = 0;
            Login = string.Empty;
            FullName = "Гость";
            Role = "Гость";
        }
    }

AuthService.cs

using AppCore.Helpers;
using Demo_Ex_8.Models;
using System.Data;

namespace Demo_Ex_8.Services
{
    public static class AuthService
    {
        public static bool Login(string login, string password)
        {
            try
            {
                if (!ValidationHelper.ValidateRequiredFields(new()
                {
                    { "Логин", login },
                    { "Пароль", password }
                }))
                {
                    return false;
                }

                string query = """
                    SELECT
                        u.id,
                        u.full_name,
                        u.login,
                        r.role_name
                    FROM users u
                    JOIN roles r ON r.id = u.role_id
                    WHERE u.login = @login
                      AND u.password = @password
                    """;

                DataTable table = DatabaseService.ExecuteSelect(
                    query,
                    new Dictionary<string, object>
                    {
                        { "@login", login },
                        { "@password", password }
                    });

                if (table.Rows.Count == 0)
                {
                    MessageBoxHelper.Warning("Неверный логин или пароль");
                    return false;
                }

                DataRow row = table.Rows[0];

                UserSession.SetUser(
                    Convert.ToInt32(row["id"]),
                    row["login"].ToString(),
                    row["full_name"].ToString(),
                    row["role_name"].ToString());

                return true;
            }
            catch (Exception ex)
            {
                MessageBoxHelper.ShowException(ex);
                return false;
            }
        }

        public static void LoginAsGuest()
        {
            UserSession.SetGuest();
        }

        public static void Logout()
        {
            UserSession.Clear();
        }
    }
}

ProductsService.cs

using AppCore.Helpers;
using System.Data;
using System.Text;

namespace Demo_Ex_8.Services
{
    public static class ProductsService
    {
        public static DataTable GetSuppliers()
        {
            return DatabaseService.ExecuteSelect(
                "SELECT id, supplier_name FROM suppliers ORDER BY supplier_name");
        }

        public static DataTable GetManufacturers()
        {
            return DatabaseService.ExecuteSelect(
                "SELECT id, manufacturer_name FROM manufacturers ORDER BY manufacturer_name");
        }

        public static DataTable GetUnits()
        {
            return DatabaseService.ExecuteSelect(
                "SELECT id, unit_name FROM units ORDER BY unit_name");
        }

        public static DataTable GetCategories()
        {
            return DatabaseService.ExecuteSelect(
                "SELECT id, category_name FROM categories ORDER BY category_name");
        }

        public static DataTable GetProductById(int productId)
        {
            return DatabaseService.ExecuteSelect(
                "SELECT * FROM products WHERE id = @id",
                new Dictionary<string, object>
                {
                    { "@id", productId }
                });
        }

        public static DataTable GetProducts(
            string search = "",
            int supplierId = 0,
            string sortType = "")
        {
            StringBuilder query = new("""
                SELECT
                    p.id,
                    p.article,
                    p.title,
                    u.unit_name,
                    p.price,
                    s.supplier_name,
                    m.manufacturer_name,
                    c.category_name,
                    p.discount,
                    p.quantity,
                    p.description,
                    p.picture_path
                FROM products p
                JOIN units u ON p.unit_id = u.id
                JOIN suppliers s ON p.supplier_id = s.id
                JOIN manufacturers m ON p.manufacturer_id = m.id
                JOIN categories c ON p.category_id = c.id
                WHERE 1 = 1
                """);

            Dictionary<string, object> parameters = new();

            QueryBuilderHelper.AddTextSearch(
                query,
                parameters,
                search,
                "p.title",
                "p.article",
                "p.description",
                "s.supplier_name",
                "m.manufacturer_name",
                "c.category_name");

            QueryBuilderHelper.AddExactFilter(
                query,
                parameters,
                "p.supplier_id",
                "@supplierId",
                supplierId,
                0);

            QueryBuilderHelper.AddOrderBy(
                query,
                sortType,
                new Dictionary<string, string>
                {
                    { "Цена по возрастанию", "p.price ASC" },
                    { "Цена по убыванию", "p.price DESC" },
                    { "Количество по возрастанию", "p.quantity ASC" },
                    { "Количество по убыванию", "p.quantity DESC" },
                    { "Скидка по возрастанию", "p.discount ASC" },
                    { "Скидка по убыванию", "p.discount DESC" },
                    { "Название А-Я", "p.title ASC" },
                    { "Название Я-А", "p.title DESC" }
                },
                "p.id ASC");

            return DatabaseService.ExecuteSelect(query.ToString(), parameters);
        }

        public static bool CreateProduct(
            string article,
            string title,
            int unitId,
            decimal price,
            int supplierId,
            int manufacturerId,
            int categoryId,
            int discount,
            int quantity,
            string description,
            string picturePath)
        {
            string query = """
                INSERT INTO products
                (
                    article,
                    title,
                    unit_id,
                    price,
                    supplier_id,
                    manufacturer_id,
                    category_id,
                    discount,
                    quantity,
                    description,
                    picture_path
                )
                VALUES
                (
                    @article,
                    @title,
                    @unitId,
                    @price,
                    @supplierId,
                    @manufacturerId,
                    @categoryId,
                    @discount,
                    @quantity,
                    @description,
                    @picturePath
                )
                """;

            return DatabaseService.ExecuteNonQuery(
                query,
                new Dictionary<string, object>
                {
                    { "@article", article },
                    { "@title", title },
                    { "@unitId", unitId },
                    { "@price", price },
                    { "@supplierId", supplierId },
                    { "@manufacturerId", manufacturerId },
                    { "@categoryId", categoryId },
                    { "@discount", discount },
                    { "@quantity", quantity },
                    { "@description", description },
                    { "@picturePath", picturePath }
                });
        }

        public static bool UpdateProduct(
            int id,
            string article,
            string title,
            int unitId,
            decimal price,
            int supplierId,
            int manufacturerId,
            int categoryId,
            int discount,
            int quantity,
            string description,
            string picturePath)
        {
            string query = """
                UPDATE products
                SET
                    article = @article,
                    title = @title,
                    unit_id = @unitId,
                    price = @price,
                    supplier_id = @supplierId,
                    manufacturer_id = @manufacturerId,
                    category_id = @categoryId,
                    discount = @discount,
                    quantity = @quantity,
                    description = @description,
                    picture_path = @picturePath
                WHERE id = @id
                """;

            return DatabaseService.ExecuteNonQuery(
                query,
                new Dictionary<string, object>
                {
                    { "@id", id },
                    { "@article", article },
                    { "@title", title },
                    { "@unitId", unitId },
                    { "@price", price },
                    { "@supplierId", supplierId },
                    { "@manufacturerId", manufacturerId },
                    { "@categoryId", categoryId },
                    { "@discount", discount },
                    { "@quantity", quantity },
                    { "@description", description },
                    { "@picturePath", picturePath }
                });
        }

        public static bool DeleteProduct(int id)
        {
            return DatabaseService.ExecuteNonQuery(
                "DELETE FROM products WHERE id = @id",
                new Dictionary<string, object>
                {
                    { "@id", id }
                });
        }

        public static bool ProductExistsInOrders(int productId)
        {
            object? result = DatabaseService.ExecuteScalar(
                """
                SELECT COUNT(*)
                FROM order_items
                WHERE product_id = @productId
                """,
                new Dictionary<string, object>
                {
                    { "@productId", productId }
                });

            return Convert.ToInt32(result) > 0;
        }
    }
}

OrdersService.cs

using AppCore.Helpers;
using System.Data;

namespace Demo_Ex_8.Services
{
    public static class OrdersService
    {
        public static DataTable GetOrders()
        {
            string query = """
                SELECT
                    o.id,
                    o.order_date,
                    o.delivery_date,
                    o.pickup_point_id,
                    o.user_id,
                    o.receipt_code,
                    o.status_id,
                    s.status_name,
                    u.full_name,
                    CONCAT(
                        pp.postal_code,
                        ', г. ',
                        c.city_name,
                        ', ',
                        pp.street,
                        ', ',
                        pp.house
                    ) AS pickup_point
                FROM orders o
                JOIN statuses s ON s.id = o.status_id
                JOIN users u ON u.id = o.user_id
                JOIN pickup_points pp ON pp.id = o.pickup_point_id
                JOIN cities c ON c.id = pp.city_id
                ORDER BY o.id DESC
                """;

            return DatabaseService.ExecuteSelect(query);
        }

        public static DataTable GetOrderById(int orderId)
        {
            string query = """
                SELECT
                    id,
                    order_date,
                    delivery_date,
                    pickup_point_id,
                    user_id,
                    receipt_code,
                    status_id
                FROM orders
                WHERE id = @id
                """;

            return DatabaseService.ExecuteSelect(
                query,
                new Dictionary<string, object>
                {
                    { "@id", orderId }
                });
        }

        public static DataTable GetStatuses()
        {
            return DatabaseService.ExecuteSelect(
                "SELECT id, status_name FROM statuses ORDER BY status_name");
        }

        public static DataTable GetUsers()
        {
            return DatabaseService.ExecuteSelect(
                "SELECT id, full_name FROM users ORDER BY full_name");
        }

        public static DataTable GetPickupPoints()
        {
            string query = """
                SELECT
                    pp.id,
                    CONCAT(
                        pp.postal_code,
                        ', г. ',
                        c.city_name,
                        ', ',
                        pp.street,
                        ', ',
                        pp.house
                    ) AS pickup_point
                FROM pickup_points pp
                JOIN cities c ON c.id = pp.city_id
                ORDER BY pp.id
                """;

            return DatabaseService.ExecuteSelect(query);
        }

        public static bool CreateOrder(
            DateTime orderDate,
            DateTime deliveryDate,
            int pickupPointId,
            int userId,
            string receiptCode,
            int statusId)
        {
            string query = """
                INSERT INTO orders
                (
                    order_date,
                    delivery_date,
                    pickup_point_id,
                    user_id,
                    receipt_code,
                    status_id
                )
                VALUES
                (
                    @orderDate,
                    @deliveryDate,
                    @pickupPointId,
                    @userId,
                    @receiptCode,
                    @statusId
                )
                """;

            return DatabaseService.ExecuteNonQuery(
                query,
                new Dictionary<string, object>
                {
                    { "@orderDate", orderDate },
                    { "@deliveryDate", deliveryDate },
                    { "@pickupPointId", pickupPointId },
                    { "@userId", userId },
                    { "@receiptCode", receiptCode },
                    { "@statusId", statusId }
                });
        }

        public static bool UpdateOrder(
            int id,
            DateTime orderDate,
            DateTime deliveryDate,
            int pickupPointId,
            int userId,
            string receiptCode,
            int statusId)
        {
            string query = """
                UPDATE orders
                SET
                    order_date = @orderDate,
                    delivery_date = @deliveryDate,
                    pickup_point_id = @pickupPointId,
                    user_id = @userId,
                    receipt_code = @receiptCode,
                    status_id = @statusId
                WHERE id = @id
                """;

            return DatabaseService.ExecuteNonQuery(
                query,
                new Dictionary<string, object>
                {
                    { "@id", id },
                    { "@orderDate", orderDate },
                    { "@deliveryDate", deliveryDate },
                    { "@pickupPointId", pickupPointId },
                    { "@userId", userId },
                    { "@receiptCode", receiptCode },
                    { "@statusId", statusId }
                });
        }

        public static bool DeleteOrder(int id)
        {
            string query = """
                DELETE FROM order_items WHERE order_id = @id;
                DELETE FROM orders WHERE id = @id;
                """;

            return DatabaseService.ExecuteNonQuery(
                query,
                new Dictionary<string, object>
                {
                    { "@id", id }
                });
        }
    }
}

ProductCard.cs

	public partial class ProductCard : UserControl
	{
			public int ProductId { get; private set; }

			private readonly int _discountLimit;
			private readonly Color _defaultColor;
			private readonly Color _discountColor;
			private readonly Color _outOfStockColor;

			public event EventHandler<int>? CardClicked;

			public ProductCard(
					DataRow row,
					int discountLimit,
					Color defaultColor,
					Color discountColor,
					Color outOfStockColor)
			{
					InitializeComponent();

					_discountLimit = discountLimit;
					_defaultColor = defaultColor;
					_discountColor = discountColor;
					_outOfStockColor = outOfStockColor;

					FillCard(row);
					AttachClickEvent(this);
			}

			private void ProductCard_Click(object? sender, EventArgs e)
			{
					CardClicked?.Invoke(this, ProductId);
			}

			public void FillCard(DataRow row)
			{
					try
					{
							ProductId = Convert.ToInt32(row["id"]);

							decimal price = Convert.ToDecimal(row["price"]);
							int discount = Convert.ToInt32(row["discount"]);
							int quantity = Convert.ToInt32(row["quantity"]);

							CategoryLabel.Text = row["category_name"].ToString();
							TitleLabel.Text = row["title"].ToString();
							DescriptionLabel.Text = row["description"].ToString();
							ManufacturerLabel.Text = row["manufacturer_name"].ToString();
							SupplierLabel.Text = row["supplier_name"].ToString();
							UnitLabel.Text = row["unit_name"].ToString();
							QuantityLabel.Text = quantity.ToString();
							DiscountLabel.Text = ProductViewHelper.FormatDiscount(discount);

							ProductPicture.Image = ImageHelper.LoadImageOrDefault(
									row["picture_path"].ToString(),
									@"C:Resourse\picture.png");

							ProductPicture.SizeMode = PictureBoxSizeMode.Zoom;

							ProductViewHelper.ApplyProductBackground(
									this,
									quantity,
									discount,
									_discountLimit,
									_defaultColor,
									_discountColor,
									_outOfStockColor);

							ProductViewHelper.ApplyPriceLabels(
									PriceLabel,
									FinalPriceLabel,
									price,
									discount,
									Color.Red,
									Color.Black);
					}
					catch (Exception ex)
					{
							MessageBoxHelper.ShowException(ex);
					}
			}

			private void AttachClickEvent(Control control)
			{
					control.Click -= ProductCard_Click;
					control.Click += ProductCard_Click;

					control.Cursor = Cursors.Hand;

					foreach (Control child in control.Controls)
					{
							AttachClickEvent(child);
					}
			}
	}


ProductCard.designer

namespace Demo_Ex_8.Cards
{
    partial class ProductCard
    {
        /// <summary> 
        /// Обязательная переменная конструктора.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary> 
        /// Освободить все используемые ресурсы.
        /// </summary>
        /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Код, автоматически созданный конструктором компонентов

        /// <summary> 
        /// Требуемый метод для поддержки конструктора — не изменяйте 
        /// содержимое этого метода с помощью редактора кода.
        /// </summary>
        private void InitializeComponent()
        {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ProductCard));
            ProductPicture = new PictureBox();
            TitleLabel = new Label();
            CategoryLabel = new Label();
            DescriptionLabel = new Label();
            ManufacturerLabel = new Label();
            SupplierLabel = new Label();
            PriceLabel = new Label();
            UnitLabel = new Label();
            QuantityLabel = new Label();
            DiscountLabel = new Label();
            FinalPriceLabel = new Label();
            ((System.ComponentModel.ISupportInitialize)ProductPicture).BeginInit();
            SuspendLayout();
            // 
            // ProductPicture
            // 
            ProductPicture.BorderStyle = BorderStyle.FixedSingle;
            ProductPicture.ErrorImage = (Image)resources.GetObject("ProductPicture.ErrorImage");
            ProductPicture.Location = new Point(15, 12);
            ProductPicture.Name = "ProductPicture";
            ProductPicture.Size = new Size(209, 200);
            ProductPicture.SizeMode = PictureBoxSizeMode.StretchImage;
            ProductPicture.TabIndex = 7;
            ProductPicture.TabStop = false;
            // 
            // TitleLabel
            // 
            TitleLabel.Font = new Font("Microsoft Sans Serif", 9.75F, FontStyle.Bold);
            TitleLabel.Location = new Point(234, 12);
            TitleLabel.Name = "TitleLabel";
            TitleLabel.Size = new Size(975, 34);
            TitleLabel.TabIndex = 8;
            TitleLabel.Text = "Название товара";
            // 
            // CategoryLabel
            // 
            CategoryLabel.AutoSize = true;
            CategoryLabel.Font = new Font("Microsoft Sans Serif", 9.75F, FontStyle.Bold);
            CategoryLabel.Location = new Point(234, 65);
            CategoryLabel.Name = "CategoryLabel";
            CategoryLabel.Size = new Size(141, 16);
            CategoryLabel.TabIndex = 9;
            CategoryLabel.Text = "Категория товара";
            // 
            // DescriptionLabel
            // 
            DescriptionLabel.Font = new Font("Microsoft Sans Serif", 9.75F);
            DescriptionLabel.Location = new Point(234, 93);
            DescriptionLabel.Name = "DescriptionLabel";
            DescriptionLabel.Size = new Size(500, 50);
            DescriptionLabel.TabIndex = 10;
            DescriptionLabel.Text = "Описание:";
            // 
            // ManufacturerLabel
            // 
            ManufacturerLabel.AutoSize = true;
            ManufacturerLabel.Font = new Font("Microsoft Sans Serif", 9.75F);
            ManufacturerLabel.Location = new Point(230, 196);
            ManufacturerLabel.Name = "ManufacturerLabel";
            ManufacturerLabel.Size = new Size(111, 16);
            ManufacturerLabel.TabIndex = 11;
            ManufacturerLabel.Text = "Производитель";
            // 
            // SupplierLabel
            // 
            SupplierLabel.AutoSize = true;
            SupplierLabel.Font = new Font("Microsoft Sans Serif", 9.75F);
            SupplierLabel.Location = new Point(447, 196);
            SupplierLabel.Name = "SupplierLabel";
            SupplierLabel.Size = new Size(79, 16);
            SupplierLabel.TabIndex = 12;
            SupplierLabel.Text = "Поставщик";
            // 
            // PriceLabel
            // 
            PriceLabel.AutoSize = true;
            PriceLabel.Font = new Font("Microsoft Sans Serif", 9.75F);
            PriceLabel.Location = new Point(1215, 104);
            PriceLabel.Name = "PriceLabel";
            PriceLabel.Size = new Size(43, 16);
            PriceLabel.TabIndex = 13;
            PriceLabel.Text = "Цена:";
            // 
            // UnitLabel
            // 
            UnitLabel.AutoSize = true;
            UnitLabel.Font = new Font("Microsoft Sans Serif", 9.75F);
            UnitLabel.Location = new Point(1270, 163);
            UnitLabel.Name = "UnitLabel";
            UnitLabel.Size = new Size(26, 16);
            UnitLabel.TabIndex = 14;
            UnitLabel.Text = "шт.";
            // 
            // QuantityLabel
            // 
            QuantityLabel.AutoSize = true;
            QuantityLabel.Font = new Font("Microsoft Sans Serif", 9.75F);
            QuantityLabel.Location = new Point(1215, 163);
            QuantityLabel.Name = "QuantityLabel";
            QuantityLabel.Size = new Size(28, 16);
            QuantityLabel.TabIndex = 15;
            QuantityLabel.Text = "100";
            // 
            // DiscountLabel
            // 
            DiscountLabel.AutoSize = true;
            DiscountLabel.Font = new Font("Microsoft Sans Serif", 9.75F);
            DiscountLabel.Location = new Point(1215, 12);
            DiscountLabel.Name = "DiscountLabel";
            DiscountLabel.Size = new Size(54, 16);
            DiscountLabel.TabIndex = 16;
            DiscountLabel.Text = "Скидка";
            // 
            // FinalPriceLabel
            // 
            FinalPriceLabel.AutoSize = true;
            FinalPriceLabel.Font = new Font("Microsoft Sans Serif", 12F, FontStyle.Regular, GraphicsUnit.Point, 204);
            FinalPriceLabel.Location = new Point(1215, 60);
            FinalPriceLabel.Name = "FinalPriceLabel";
            FinalPriceLabel.Size = new Size(52, 20);
            FinalPriceLabel.TabIndex = 18;
            FinalPriceLabel.Text = "Цена:";
            // 
            // ProductCard
            // 
            AutoScaleDimensions = new SizeF(7F, 15F);
            AutoScaleMode = AutoScaleMode.Font;
            Controls.Add(FinalPriceLabel);
            Controls.Add(DiscountLabel);
            Controls.Add(QuantityLabel);
            Controls.Add(UnitLabel);
            Controls.Add(PriceLabel);
            Controls.Add(SupplierLabel);
            Controls.Add(ManufacturerLabel);
            Controls.Add(DescriptionLabel);
            Controls.Add(CategoryLabel);
            Controls.Add(TitleLabel);
            Controls.Add(ProductPicture);
            Name = "ProductCard";
            Size = new Size(1450, 222);
            Click += ProductCard_Click;
            ((System.ComponentModel.ISupportInitialize)ProductPicture).EndInit();
            ResumeLayout(false);
            PerformLayout();
        }

        #endregion

        private PictureBox ProductPicture;
        private Label TitleLabel;
        private Label CategoryLabel;
        private Label DescriptionLabel;
        private Label ManufacturerLabel;
        private Label SupplierLabel;
        private Label PriceLabel;
        private Label UnitLabel;
        private Label QuantityLabel;
        private Label DiscountLabel;
        private Label FinalPriceLabel;
    }
}


OrderCard.cs

	public partial class OrderCard : UserControl
	{
			public int OrderId { get; private set; }

			public event EventHandler<int>? CardClicked;

			public OrderCard(DataRow row)
			{
					InitializeComponent();

					FillCard(row);
					AttachClickEvent(this);
			}

			private void FillCard(DataRow row)
			{
					try
					{
							OrderId = Convert.ToInt32(row["id"]);

							string status = row["status_name"].ToString();
							string pickupPoint = row["pickup_point"].ToString();

							DateTime orderDate = Convert.ToDateTime(row["order_date"]);
							DateTime deliveryDate = Convert.ToDateTime(row["delivery_date"]);

							ArticleLabel.Text = "Артикул заказа: " + OrderId;
							StatusLabel.Text = "Статус заказа: " + status;
							PickupPointLabel.Text = "Адрес пункта выдачи: " + pickupPoint;
							OrderDateLabel.Text = "Дата заказа: " + orderDate.ToString("dd.MM.yyyy");
							DeliveryDateLabel.Text = "Дата доставки: " + deliveryDate.ToString("dd.MM.yyyy");
					}
					catch (Exception ex)
					{
							MessageBoxHelper.ShowException(ex);
					}
			}

			private void AttachClickEvent(Control control)
			{
					control.Click -= OrderCard_Click;
					control.Click += OrderCard_Click;

					control.Cursor = Cursors.Hand;

					foreach (Control child in control.Controls)
					{
							AttachClickEvent(child);
					}
			}

			private void OrderCard_Click(object? sender, EventArgs e)
			{
					CardClicked?.Invoke(this, OrderId);
			}
	}


OrderCard.designer

namespace Demo_Ex_8.Cards
{
    partial class OrderCard
    {
        /// <summary> 
        /// Обязательная переменная конструктора.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary> 
        /// Освободить все используемые ресурсы.
        /// </summary>
        /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Код, автоматически созданный конструктором компонентов

        /// <summary> 
        /// Требуемый метод для поддержки конструктора — не изменяйте 
        /// содержимое этого метода с помощью редактора кода.
        /// </summary>
        private void InitializeComponent()
        {
            ArticleLabel = new Label();
            StatusLabel = new Label();
            PickupPointLabel = new Label();
            OrderDateLabel = new Label();
            DeliveryDateLabel = new Label();
            SuspendLayout();
            // 
            // ArticleLabel
            // 
            ArticleLabel.AutoSize = true;
            ArticleLabel.Font = new Font("Segoe UI", 12F, FontStyle.Bold, GraphicsUnit.Point, 204);
            ArticleLabel.Location = new Point(28, 13);
            ArticleLabel.Margin = new Padding(4, 0, 4, 0);
            ArticleLabel.Name = "ArticleLabel";
            ArticleLabel.Size = new Size(131, 21);
            ArticleLabel.TabIndex = 0;
            ArticleLabel.Text = "Артикул заказа";
            // 
            // StatusLabel
            // 
            StatusLabel.AutoSize = true;
            StatusLabel.Location = new Point(28, 55);
            StatusLabel.Margin = new Padding(4, 0, 4, 0);
            StatusLabel.Name = "StatusLabel";
            StatusLabel.Size = new Size(107, 21);
            StatusLabel.TabIndex = 1;
            StatusLabel.Text = "Статус заказа";
            // 
            // PickupPointLabel
            // 
            PickupPointLabel.AutoSize = true;
            PickupPointLabel.Location = new Point(28, 94);
            PickupPointLabel.Margin = new Padding(4, 0, 4, 0);
            PickupPointLabel.Name = "PickupPointLabel";
            PickupPointLabel.Size = new Size(164, 21);
            PickupPointLabel.TabIndex = 2;
            PickupPointLabel.Text = "Адрес пункта выдачи";
            // 
            // OrderDateLabel
            // 
            OrderDateLabel.AutoSize = true;
            OrderDateLabel.Location = new Point(28, 139);
            OrderDateLabel.Margin = new Padding(4, 0, 4, 0);
            OrderDateLabel.Name = "OrderDateLabel";
            OrderDateLabel.Size = new Size(94, 21);
            OrderDateLabel.TabIndex = 3;
            OrderDateLabel.Text = "Дата заказа";
            // 
            // DeliveryDateLabel
            // 
            DeliveryDateLabel.AutoSize = true;
            DeliveryDateLabel.Location = new Point(794, 69);
            DeliveryDateLabel.Margin = new Padding(4, 0, 4, 0);
            DeliveryDateLabel.Name = "DeliveryDateLabel";
            DeliveryDateLabel.Size = new Size(94, 21);
            DeliveryDateLabel.TabIndex = 4;
            DeliveryDateLabel.Text = "Дата заказа";
            // 
            // OrderCard
            // 
            AutoScaleDimensions = new SizeF(9F, 21F);
            AutoScaleMode = AutoScaleMode.Font;
            BorderStyle = BorderStyle.FixedSingle;
            Controls.Add(DeliveryDateLabel);
            Controls.Add(OrderDateLabel);
            Controls.Add(PickupPointLabel);
            Controls.Add(StatusLabel);
            Controls.Add(ArticleLabel);
            Font = new Font("Segoe UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 204);
            Margin = new Padding(4);
            Name = "OrderCard";
            Size = new Size(941, 176);
            ResumeLayout(false);
            PerformLayout();
        }

        #endregion

        private Label ArticleLabel;
        private Label StatusLabel;
        private Label PickupPointLabel;
        private Label OrderDateLabel;
        private Label DeliveryDateLabel;
    }
}


CatalogForm.cs

	using AppCore.Helpers;
using Demo_Ex_8.Cards;
using Demo_Ex_8.Models;
using Demo_Ex_8.Services;
using System.Data;

namespace Demo_Ex_8.Forms
{
    public partial class CatalogForm : Form
    {
        private bool _isLoading = false;

        public CatalogForm()
        {
            InitializeComponent();

            FormHelper.Configure(this, "Каталог", "C:\\Users\\eleskov\\Desktop\\Подготовка к ДЭ\\Demo_Ex_8\\Demo_Ex_8\\Resourse\\icon.ico");

            LoadData();
        }

        private void LoadData()
        {
            _isLoading = true;

            LoadUserInfo();
            LoadSuppliers();
            LoadSortTypes();

            _isLoading = false;

            LoadProducts();
        }

        private void LoadUserInfo()
        {
            FullNameLabel.Text = UserSession.FullName;
            RoleLabel.Text = UserSession.Role;
        }

        private void LoadSuppliers()
        {
            ComboBoxHelper.LoadWithDefaultItem(
                SupplierComboBox,
                ProductsService.GetSuppliers(),
                "supplier_name",
                "id",
                "Все поставщики");
        }

        private void LoadSortTypes()
        {
            SortComboBox.Items.Clear();

            SortComboBox.Items.Add("По умолчанию");
            SortComboBox.Items.Add("Цена по возрастанию");
            SortComboBox.Items.Add("Цена по убыванию");
            SortComboBox.Items.Add("Количество по возрастанию");
            SortComboBox.Items.Add("Количество по убыванию");
            SortComboBox.Items.Add("Скидка по возрастанию");
            SortComboBox.Items.Add("Скидка по убыванию");
            SortComboBox.Items.Add("Название А-Я");
            SortComboBox.Items.Add("Название Я-А");

            SortComboBox.SelectedIndex = 0;
        }

        private void LoadProducts()
        {
            try
            {
                string search = SearchTextBox.Text.Trim();
                string sortType = SortComboBox.Text;

                int supplierId = 0;

                if (ComboBoxHelper.HasSelectedValue(SupplierComboBox))
                {
                    supplierId = ComboBoxHelper.GetSelectedIntValue(SupplierComboBox);
                }

                DataTable table = ProductsService.GetProducts(
                    search,
                    supplierId,
                    sortType);

                CardPanelHelper.Clear(ProductsPanel);

                foreach (DataRow row in table.Rows)
                {   
                    ProductCard card = new(
                        row,
                        17,
                        Color.White,
                        ColorTranslator.FromHtml("#F5DEB3"),
                        Color.LightBlue);

                    card.CardClicked += Product_Click;

                    CardPanelHelper.AddCard(ProductsPanel, card);
                }

                if (!CardPanelHelper.HasCards(ProductsPanel))
                {
                    CardPanelHelper.ShowEmptyMessage(
                        ProductsPanel,
                        "Товары не найдены");
                }
            }
            catch (Exception ex)
            {
                MessageBoxHelper.ShowException(ex);
            }
        }

        private void Product_Click(object? sender, int productId)
        {
            FormHelper.OpenSingleDialog(
                () => new ProductEditForm(productId),
                LoadProducts);
        }

        private void SearchTextBox_TextChanged(object sender, EventArgs e)
        {
            if (_isLoading)
                return;

            LoadProducts();
        }

        private void SupplierComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (_isLoading)
                return;

            LoadProducts();
        }

        private void SortComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (_isLoading)
                return;

            LoadProducts();
        }

        private void AddProductBtn_Click(object sender, EventArgs e)
        {
            FormHelper.OpenSingleDialog(
                () => new ProductEditForm(),
                LoadProducts);
        }

        private void OrdersBtn_Click(object sender, EventArgs e)
        {
            FormHelper.OpenSingleDialog(
                () => new OrderForm());
        }

        private void ExitBtn_Click(object sender, EventArgs e)
        {
            AuthService.Logout();
            FormHelper.ExitApplication();
        }

        private void BackBtn_Click(object sender, EventArgs e)
        {
            AuthService.Logout();
            FormHelper.Back(this);
        }
    }
}

CatalogForm.designer

	namespace Demo_Ex_8.Forms
{
    partial class CatalogForm
    {
        /// <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()
        {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CatalogForm));
            RoleLabel = new Label();
            FullNameLabel = new Label();
            SortComboBox = new ComboBox();
            SupplierComboBox = new ComboBox();
            SearchTextBox = new TextBox();
            LogoutBtn = new Button();
            ProductsPanel = new FlowLayoutPanel();
            CreateProductBtn = new Button();
            pictureBox1 = new PictureBox();
            label2 = new Label();
            groupBox1 = new GroupBox();
            label3 = new Label();
            label1 = new Label();
            OrdersForm = new Button();
            BackBtn = new Button();
            ((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit();
            groupBox1.SuspendLayout();
            SuspendLayout();
            // 
            // RoleLabel
            // 
            RoleLabel.AutoSize = true;
            RoleLabel.Location = new Point(1415, 35);
            RoleLabel.Margin = new Padding(4, 0, 4, 0);
            RoleLabel.Name = "RoleLabel";
            RoleLabel.Size = new Size(49, 21);
            RoleLabel.TabIndex = 1;
            RoleLabel.Text = "Гость";
            // 
            // FullNameLabel
            // 
            FullNameLabel.AutoSize = true;
            FullNameLabel.Location = new Point(1415, 9);
            FullNameLabel.Margin = new Padding(4, 0, 4, 0);
            FullNameLabel.Name = "FullNameLabel";
            FullNameLabel.Size = new Size(49, 21);
            FullNameLabel.TabIndex = 0;
            FullNameLabel.Text = "Гость";
            // 
            // SortComboBox
            // 
            SortComboBox.FormattingEnabled = true;
            SortComboBox.Location = new Point(7, 50);
            SortComboBox.Margin = new Padding(4);
            SortComboBox.Name = "SortComboBox";
            SortComboBox.Size = new Size(275, 29);
            SortComboBox.TabIndex = 2;
            SortComboBox.SelectedIndexChanged += SortComboBox_SelectedIndexChanged;
            // 
            // SupplierComboBox
            // 
            SupplierComboBox.FormattingEnabled = true;
            SupplierComboBox.Location = new Point(7, 123);
            SupplierComboBox.Margin = new Padding(4);
            SupplierComboBox.Name = "SupplierComboBox";
            SupplierComboBox.Size = new Size(275, 29);
            SupplierComboBox.TabIndex = 1;
            SupplierComboBox.SelectedIndexChanged += SupplierComboBox_SelectedIndexChanged;
            // 
            // SearchTextBox
            // 
            SearchTextBox.Location = new Point(645, 21);
            SearchTextBox.Margin = new Padding(4);
            SearchTextBox.Name = "SearchTextBox";
            SearchTextBox.PlaceholderText = "Поиск товаров по названию, поставщику, ";
            SearchTextBox.Size = new Size(709, 29);
            SearchTextBox.TabIndex = 0;
            SearchTextBox.TextChanged += SearchTextBox_TextChanged;
            // 
            // LogoutBtn
            // 
            LogoutBtn.Location = new Point(1697, 13);
            LogoutBtn.Margin = new Padding(4);
            LogoutBtn.Name = "LogoutBtn";
            LogoutBtn.Size = new Size(96, 43);
            LogoutBtn.TabIndex = 3;
            LogoutBtn.Text = "Выход";
            LogoutBtn.UseVisualStyleBackColor = true;
            LogoutBtn.Click += ExitBtn_Click;
            // 
            // ProductsPanel
            // 
            ProductsPanel.AutoScroll = true;
            ProductsPanel.Location = new Point(311, 115);
            ProductsPanel.Margin = new Padding(4);
            ProductsPanel.Name = "ProductsPanel";
            ProductsPanel.Size = new Size(1491, 881);
            ProductsPanel.TabIndex = 4;
            // 
            // CreateProductBtn
            // 
            CreateProductBtn.Location = new Point(7, 218);
            CreateProductBtn.Margin = new Padding(4);
            CreateProductBtn.Name = "CreateProductBtn";
            CreateProductBtn.Size = new Size(275, 41);
            CreateProductBtn.TabIndex = 5;
            CreateProductBtn.Text = "Добавить товар";
            CreateProductBtn.UseVisualStyleBackColor = true;
            CreateProductBtn.Click += AddProductBtn_Click;
            // 
            // pictureBox1
            // 
            pictureBox1.Image = (Image)resources.GetObject("pictureBox1.Image");
            pictureBox1.Location = new Point(13, 9);
            pictureBox1.Margin = new Padding(4);
            pictureBox1.Name = "pictureBox1";
            pictureBox1.Size = new Size(102, 99);
            pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
            pictureBox1.TabIndex = 6;
            pictureBox1.TabStop = false;
            // 
            // label2
            // 
            label2.AutoSize = true;
            label2.Font = new Font("Segoe UI", 15.75F, FontStyle.Regular, GraphicsUnit.Point, 204);
            label2.Location = new Point(123, 9);
            label2.Margin = new Padding(4, 0, 4, 0);
            label2.Name = "label2";
            label2.Size = new Size(171, 30);
            label2.TabIndex = 7;
            label2.Text = "Каталог товаров";
            // 
            // groupBox1
            // 
            groupBox1.Controls.Add(label3);
            groupBox1.Controls.Add(label1);
            groupBox1.Controls.Add(SortComboBox);
            groupBox1.Controls.Add(SupplierComboBox);
            groupBox1.Controls.Add(CreateProductBtn);
            groupBox1.Location = new Point(12, 115);
            groupBox1.Name = "groupBox1";
            groupBox1.Size = new Size(292, 268);
            groupBox1.TabIndex = 8;
            groupBox1.TabStop = false;
            // 
            // label3
            // 
            label3.AutoSize = true;
            label3.Font = new Font("Segoe UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 204);
            label3.Location = new Point(7, 98);
            label3.Margin = new Padding(4, 0, 4, 0);
            label3.Name = "label3";
            label3.Size = new Size(90, 21);
            label3.TabIndex = 10;
            label3.Text = "Поставщик";
            // 
            // label1
            // 
            label1.AutoSize = true;
            label1.Font = new Font("Segoe UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 204);
            label1.Location = new Point(7, 25);
            label1.Margin = new Padding(4, 0, 4, 0);
            label1.Name = "label1";
            label1.Size = new Size(96, 21);
            label1.TabIndex = 9;
            label1.Text = "Сортировка";
            // 
            // OrdersForm
            // 
            OrdersForm.Location = new Point(12, 956);
            OrdersForm.Margin = new Padding(4);
            OrdersForm.Name = "OrdersForm";
            OrdersForm.Size = new Size(184, 33);
            OrdersForm.TabIndex = 11;
            OrdersForm.Text = "Форма с заказами";
            OrdersForm.UseVisualStyleBackColor = true;
            OrdersForm.Click += OrdersBtn_Click;
            // 
            // BackBtn
            // 
            BackBtn.Location = new Point(123, 42);
            BackBtn.Name = "BackBtn";
            BackBtn.Size = new Size(93, 30);
            BackBtn.TabIndex = 12;
            BackBtn.Text = "Назад";
            BackBtn.UseVisualStyleBackColor = true;
            BackBtn.Click += BackBtn_Click;
            // 
            // CatalogForm
            // 
            AutoScaleDimensions = new SizeF(9F, 21F);
            AutoScaleMode = AutoScaleMode.Font;
            ClientSize = new Size(1815, 1002);
            Controls.Add(BackBtn);
            Controls.Add(OrdersForm);
            Controls.Add(groupBox1);
            Controls.Add(label2);
            Controls.Add(RoleLabel);
            Controls.Add(FullNameLabel);
            Controls.Add(pictureBox1);
            Controls.Add(ProductsPanel);
            Controls.Add(SearchTextBox);
            Controls.Add(LogoutBtn);
            Font = new Font("Segoe UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 204);
            Icon = (Icon)resources.GetObject("$this.Icon");
            Margin = new Padding(4);
            Name = "CatalogForm";
            Text = "CatalogForm";
            ((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit();
            groupBox1.ResumeLayout(false);
            groupBox1.PerformLayout();
            ResumeLayout(false);
            PerformLayout();
        }

        #endregion
        private Label RoleLabel;
        private Label FullNameLabel;
        private TextBox SearchTextBox;
        private Button LogoutBtn;
        private ComboBox SupplierComboBox;
        private ComboBox SortComboBox;
        private FlowLayoutPanel ProductsPanel;
        private Button CreateProductBtn;
        private PictureBox pictureBox1;
        private Label label2;
        private GroupBox groupBox1;
        private Label label3;
        private Label label1;
        private Button OrdersForm;
        private Button BackBtn;
    }
}

LoginForm.cs

public partial class Login : Form
{
    public Login()
    {
        InitializeComponent();
        FormHelper.Configure(this, "Форма входа", "C:Resourse\\icon.ico");
    }

    private void loginBtn_Click(object sender, EventArgs e)
    {
        bool isLoginSuccess = AuthService.Login(LoginTextBox.Text, PasswordTextBox.Text);

        if (!isLoginSuccess)
        {
            return;
        }

        OpenCatalogForm();
    }

    private void loginAsGuestBtn_Click(object sender, EventArgs e)
    {
        AuthService.LoginAsGuest();

        OpenCatalogForm();
    }

    public void OpenCatalogForm()
    {
        FormHelper.HideCurrentAndOpen(this, new CatalogForm());
    }
}

ProductEditForm.cs

using AppCore.Helpers;
using Demo_Ex_8.Services;
using System.Data;

namespace Demo_Ex_8.Forms
{
    public partial class ProductEditForm : Form
    {
        private readonly int? _productId;

        private string _currentPicturePath = string.Empty;
        private string _selectedPicturePath = string.Empty;

        private const int MaxImageWidth = 300;
        private const int MaxImageHeight = 200;

        private const string ProductImagesFolder =
            @"C:\Users\eleskov\Desktop\Подготовка к ДЭ\Demo_Ex_8\Demo_Ex_8\Resourse";

        private const string DefaultPicturePath =
            @"C:\Users\eleskov\Desktop\Подготовка к ДЭ\Demo_Ex_8\Demo_Ex_8\Resourse\picture.png";

        private const string IconPath =
            @"C:\Users\eleskov\Desktop\Подготовка к ДЭ\Demo_Ex_8\Demo_Ex_8\Resourse\icon.ico";

        public bool IsSaved { get; private set; }

        public ProductEditForm()
        {
            InitializeComponent();

            FormHelper.Configure(this, "Создание товара", IconPath);

            ConfigureCreateMode();
            LoadComboBoxes();

            ProductPictureBox.Image = ImageHelper.LoadImageOrDefault(
                string.Empty,
                DefaultPicturePath);

            ProductPictureBox.SizeMode = PictureBoxSizeMode.Zoom;
        }

        public ProductEditForm(int productId)
        {
            InitializeComponent();

            _productId = productId;

            FormHelper.Configure(this, "Редактирование товара", IconPath);

            ConfigureEditMode();
            LoadComboBoxes();
            LoadProductData(productId);
        }

        private void ConfigureCreateMode()
        {
            CreateBtn.Visible = true;
            SaveBtn.Visible = false;
            DeleteBtn.Visible = false;
        }

        private void ConfigureEditMode()
        {
            CreateBtn.Visible = false;
            SaveBtn.Visible = true;
            DeleteBtn.Visible = true;
        }

        private void LoadComboBoxes()
        {
            ComboBoxHelper.Load(
                UnitComboBox,
                ProductsService.GetUnits(),
                "unit_name",
                "id");

            ComboBoxHelper.Load(
                SupplierComboBox,
                ProductsService.GetSuppliers(),
                "supplier_name",
                "id");

            ComboBoxHelper.Load(
                ManufacturerComboBox,
                ProductsService.GetManufacturers(),
                "manufacturer_name",
                "id");

            ComboBoxHelper.Load(
                CategoryComboBox,
                ProductsService.GetCategories(),
                "category_name",
                "id");
        }

        private void LoadProductData(int productId)
        {
            DataTable table = ProductsService.GetProductById(productId);

            if (table.Rows.Count == 0)
            {
                MessageBoxHelper.Warning("Товар не найден");
                Close();
                return;
            }

            DataRow row = table.Rows[0];

            ArticleTextBox.Text = row["article"].ToString();
            TitleTextBox.Text = row["title"].ToString();
            PriceTextBox.Text = row["price"].ToString();
            QuantityTextBox.Text = row["quantity"].ToString();
            DiscountTextBox.Text = row["discount"].ToString();
            DescriptionTextBox.Text = row["description"].ToString();

            UnitComboBox.SelectedValue = Convert.ToInt32(row["unit_id"]);
            SupplierComboBox.SelectedValue = Convert.ToInt32(row["supplier_id"]);
            ManufacturerComboBox.SelectedValue = Convert.ToInt32(row["manufacturer_id"]);
            CategoryComboBox.SelectedValue = Convert.ToInt32(row["category_id"]);

            _currentPicturePath = row["picture_path"].ToString();
            _selectedPicturePath = string.Empty;

            ProductPictureBox.Image = ImageHelper.LoadImageOrDefault(
                _currentPicturePath,
                DefaultPicturePath);

            ProductPictureBox.SizeMode = PictureBoxSizeMode.Zoom;
        }

        private bool ValidateForm(
            out decimal price,
            out int quantity,
            out int discount)
        {
            price = 0;
            quantity = 0;
            discount = 0;

            if (!ValidationHelper.ValidateRequiredFields(new()
            {
                { "Артикул", ArticleTextBox.Text },
                { "Название", TitleTextBox.Text },
                { "Цена", PriceTextBox.Text },
                { "Количество на складе", QuantityTextBox.Text },
                { "Скидка", DiscountTextBox.Text },
                { "Описание", DescriptionTextBox.Text }
            }))
            {
                return false;
            }

            if (!decimal.TryParse(PriceTextBox.Text, out price))
            {
                MessageBoxHelper.Warning("Цена должна быть числом");
                return false;
            }

            if (price < 0)
            {
                MessageBoxHelper.Warning("Цена не может быть меньше нуля");
                return false;
            }

            if (!int.TryParse(QuantityTextBox.Text, out quantity))
            {
                MessageBoxHelper.Warning("Количество должно быть целым числом");
                return false;
            }

            if (quantity < 0)
            {
                MessageBoxHelper.Warning("Количество на складе не может быть меньше нуля");
                return false;
            }

            if (!int.TryParse(DiscountTextBox.Text, out discount))
            {
                MessageBoxHelper.Warning("Скидка должна быть целым числом");
                return false;
            }

            if (discount < 0 || discount > 100)
            {
                MessageBoxHelper.Warning("Скидка должна быть от 0 до 100");
                return false;
            }

            if (UnitComboBox.SelectedValue == null)
            {
                MessageBoxHelper.Warning("Выберите единицу измерения");
                return false;
            }

            if (SupplierComboBox.SelectedValue == null)
            {
                MessageBoxHelper.Warning("Выберите поставщика");
                return false;
            }

            if (ManufacturerComboBox.SelectedValue == null)
            {
                MessageBoxHelper.Warning("Выберите производителя");
                return false;
            }

            if (CategoryComboBox.SelectedValue == null)
            {
                MessageBoxHelper.Warning("Выберите категорию");
                return false;
            }

            return true;
        }

        private void CreateBtn_Click(object sender, EventArgs e)
        {
            if (!ValidateForm(out decimal price, out int quantity, out int discount))
                return;

            string savedPicturePath = string.Empty;

            if (!string.IsNullOrWhiteSpace(_selectedPicturePath))
            {
                savedPicturePath = ImageHelper.CopyImageToFolder(
                    _selectedPicturePath,
                    ProductImagesFolder);
            }

            bool result = ProductsService.CreateProduct(
                ArticleTextBox.Text.Trim(),
                TitleTextBox.Text.Trim(),
                Convert.ToInt32(UnitComboBox.SelectedValue),
                price,
                Convert.ToInt32(SupplierComboBox.SelectedValue),
                Convert.ToInt32(ManufacturerComboBox.SelectedValue),
                Convert.ToInt32(CategoryComboBox.SelectedValue),
                discount,
                quantity,
                DescriptionTextBox.Text.Trim(),
                savedPicturePath);

            if (result)
            {
                IsSaved = true;
                MessageBoxHelper.Info("Товар успешно создан");
                Close();
            }
        }

        private void SaveBtn_Click(object sender, EventArgs e)
        {
            if (!_productId.HasValue)
            {
                MessageBoxHelper.Warning("Не выбран товар для редактирования");
                return;
            }

            if (!ValidateForm(out decimal price, out int quantity, out int discount))
                return;

            string picturePathForDb = _currentPicturePath;

            if (!string.IsNullOrWhiteSpace(_selectedPicturePath))
            {
                string copiedPicturePath = ImageHelper.CopyImageToFolder(
                    _selectedPicturePath,
                    ProductImagesFolder);

                if (!string.IsNullOrWhiteSpace(copiedPicturePath))
                {
                    ImageHelper.DeleteImage(
                        _currentPicturePath,
                        DefaultPicturePath);

                    picturePathForDb = copiedPicturePath;
                }
            }

            bool result = ProductsService.UpdateProduct(
                _productId.Value,
                ArticleTextBox.Text.Trim(),
                TitleTextBox.Text.Trim(),
                Convert.ToInt32(UnitComboBox.SelectedValue),
                price,
                Convert.ToInt32(SupplierComboBox.SelectedValue),
                Convert.ToInt32(ManufacturerComboBox.SelectedValue),
                Convert.ToInt32(CategoryComboBox.SelectedValue),
                discount,
                quantity,
                DescriptionTextBox.Text.Trim(),
                picturePathForDb);

            if (result)
            {
                IsSaved = true;
                MessageBoxHelper.Info("Товар успешно сохранён");
                Close();
            }
        }

        private void DeleteBtn_Click(object sender, EventArgs e)
        {
            if (!_productId.HasValue)
            {
                MessageBoxHelper.Warning("Не выбран товар для удаления");
                return;
            }

            if (!MessageBoxHelper.Confirm("Удалить выбранный товар?"))
                return;

            if (ProductsService.ProductExistsInOrders(_productId.Value))
            {
                MessageBoxHelper.Warning("Нельзя удалить товар, который присутствует в заказе");
                return;
            }

            bool result = ProductsService.DeleteProduct(_productId.Value);

            if (result)
            {
                ImageHelper.DeleteImage(
                    _currentPicturePath,
                    DefaultPicturePath);

                IsSaved = true;
                MessageBoxHelper.Info("Товар успешно удалён");
                Close();
            }
        }

        private void ProductPictureBox_Click(object sender, EventArgs e)
        {
            string selectedPath = ImageHelper.SelectImageFile();

            if (string.IsNullOrWhiteSpace(selectedPath))
                return;

            if (!ImageHelper.ValidateImageSize(
                selectedPath,
                MaxImageWidth,
                MaxImageHeight))
            {
                return;
            }

            _selectedPicturePath = selectedPath;

            ProductPictureBox.Image = ImageHelper.LoadImageOrDefault(
                _selectedPicturePath,
                DefaultPicturePath);

            ProductPictureBox.SizeMode = PictureBoxSizeMode.Zoom;
        }

        private void BackBtn_Click(object sender, EventArgs e)
        {
            FormHelper.Back(this);
        }
    }
}

ProductEditForm.designer

namespace Demo_Ex_8.Forms
{
    partial class ProductEditForm
    {
        /// <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()
        {
            label1 = new Label();
            label2 = new Label();
            ProductPictureBox = new PictureBox();
            TitleTextBox = new TextBox();
            ArticleTextBox = new TextBox();
            DescriptionTextBox = new TextBox();
            label3 = new Label();
            PriceTextBox = new TextBox();
            label4 = new Label();
            label5 = new Label();
            label6 = new Label();
            UnitComboBox = new ComboBox();
            SupplierComboBox = new ComboBox();
            label7 = new Label();
            ManufacturerComboBox = new ComboBox();
            label8 = new Label();
            CategoryComboBox = new ComboBox();
            label9 = new Label();
            DiscountTextBox = new TextBox();
            label10 = new Label();
            QuantityTextBox = new TextBox();
            label11 = new Label();
            DeleteBtn = new Button();
            SaveBtn = new Button();
            CreateBtn = new Button();
            BackBtn = new Button();
            ((System.ComponentModel.ISupportInitialize)ProductPictureBox).BeginInit();
            SuspendLayout();
            // 
            // label1
            // 
            label1.AutoSize = true;
            label1.Location = new Point(331, 12);
            label1.Name = "label1";
            label1.Size = new Size(53, 15);
            label1.TabIndex = 0;
            label1.Text = "Артикль";
            // 
            // label2
            // 
            label2.AutoSize = true;
            label2.Location = new Point(331, 56);
            label2.Name = "label2";
            label2.Size = new Size(59, 15);
            label2.TabIndex = 1;
            label2.Text = "Название";
            // 
            // ProductPictureBox
            // 
            ProductPictureBox.Location = new Point(82, 9);
            ProductPictureBox.Name = "ProductPictureBox";
            ProductPictureBox.Size = new Size(243, 200);
            ProductPictureBox.SizeMode = PictureBoxSizeMode.StretchImage;
            ProductPictureBox.TabIndex = 6;
            ProductPictureBox.TabStop = false;
            ProductPictureBox.Click += ProductPictureBox_Click;
            // 
            // TitleTextBox
            // 
            TitleTextBox.Location = new Point(331, 74);
            TitleTextBox.Name = "TitleTextBox";
            TitleTextBox.Size = new Size(421, 23);
            TitleTextBox.TabIndex = 7;
            // 
            // ArticleTextBox
            // 
            ArticleTextBox.Location = new Point(331, 30);
            ArticleTextBox.Name = "ArticleTextBox";
            ArticleTextBox.Size = new Size(204, 23);
            ArticleTextBox.TabIndex = 8;
            // 
            // DescriptionTextBox
            // 
            DescriptionTextBox.Location = new Point(12, 247);
            DescriptionTextBox.Multiline = true;
            DescriptionTextBox.Name = "DescriptionTextBox";
            DescriptionTextBox.Size = new Size(421, 80);
            DescriptionTextBox.TabIndex = 10;
            // 
            // label3
            // 
            label3.AutoSize = true;
            label3.Location = new Point(12, 229);
            label3.Name = "label3";
            label3.Size = new Size(62, 15);
            label3.TabIndex = 9;
            label3.Text = "Описание";
            // 
            // PriceTextBox
            // 
            PriceTextBox.Location = new Point(331, 120);
            PriceTextBox.Name = "PriceTextBox";
            PriceTextBox.Size = new Size(156, 23);
            PriceTextBox.TabIndex = 12;
            // 
            // label4
            // 
            label4.AutoSize = true;
            label4.Location = new Point(331, 102);
            label4.Name = "label4";
            label4.Size = new Size(35, 15);
            label4.TabIndex = 11;
            label4.Text = "Цена";
            // 
            // label5
            // 
            label5.AutoSize = true;
            label5.Location = new Point(485, 126);
            label5.Name = "label5";
            label5.Size = new Size(30, 15);
            label5.TabIndex = 13;
            label5.Text = "руб.";
            // 
            // label6
            // 
            label6.AutoSize = true;
            label6.Location = new Point(790, 9);
            label6.Name = "label6";
            label6.Size = new Size(116, 15);
            label6.TabIndex = 14;
            label6.Text = "Единица измерения";
            // 
            // UnitComboBox
            // 
            UnitComboBox.FormattingEnabled = true;
            UnitComboBox.Location = new Point(790, 34);
            UnitComboBox.Name = "UnitComboBox";
            UnitComboBox.Size = new Size(116, 23);
            UnitComboBox.TabIndex = 15;
            // 
            // SupplierComboBox
            // 
            SupplierComboBox.FormattingEnabled = true;
            SupplierComboBox.Location = new Point(790, 99);
            SupplierComboBox.Name = "SupplierComboBox";
            SupplierComboBox.Size = new Size(116, 23);
            SupplierComboBox.TabIndex = 17;
            // 
            // label7
            // 
            label7.AutoSize = true;
            label7.Location = new Point(790, 74);
            label7.Name = "label7";
            label7.Size = new Size(70, 15);
            label7.TabIndex = 16;
            label7.Text = "Поставщик";
            // 
            // ManufacturerComboBox
            // 
            ManufacturerComboBox.FormattingEnabled = true;
            ManufacturerComboBox.Location = new Point(790, 161);
            ManufacturerComboBox.Name = "ManufacturerComboBox";
            ManufacturerComboBox.Size = new Size(116, 23);
            ManufacturerComboBox.TabIndex = 19;
            // 
            // label8
            // 
            label8.AutoSize = true;
            label8.Location = new Point(790, 136);
            label8.Name = "label8";
            label8.Size = new Size(92, 15);
            label8.TabIndex = 18;
            label8.Text = "Производитель";
            // 
            // CategoryComboBox
            // 
            CategoryComboBox.FormattingEnabled = true;
            CategoryComboBox.Location = new Point(790, 222);
            CategoryComboBox.Name = "CategoryComboBox";
            CategoryComboBox.Size = new Size(116, 23);
            CategoryComboBox.TabIndex = 21;
            // 
            // label9
            // 
            label9.AutoSize = true;
            label9.Location = new Point(790, 197);
            label9.Name = "label9";
            label9.Size = new Size(63, 15);
            label9.TabIndex = 20;
            label9.Text = "Категория";
            // 
            // DiscountTextBox
            // 
            DiscountTextBox.Location = new Point(331, 164);
            DiscountTextBox.Name = "DiscountTextBox";
            DiscountTextBox.Size = new Size(156, 23);
            DiscountTextBox.TabIndex = 23;
            // 
            // label10
            // 
            label10.AutoSize = true;
            label10.Location = new Point(331, 146);
            label10.Name = "label10";
            label10.Size = new Size(46, 15);
            label10.TabIndex = 22;
            label10.Text = "Скидка";
            // 
            // QuantityTextBox
            // 
            QuantityTextBox.Location = new Point(548, 120);
            QuantityTextBox.Name = "QuantityTextBox";
            QuantityTextBox.Size = new Size(156, 23);
            QuantityTextBox.TabIndex = 25;
            // 
            // label11
            // 
            label11.AutoSize = true;
            label11.Location = new Point(548, 102);
            label11.Name = "label11";
            label11.Size = new Size(128, 15);
            label11.TabIndex = 24;
            label11.Text = "Количество на складе";
            // 
            // DeleteBtn
            // 
            DeleteBtn.Location = new Point(12, 339);
            DeleteBtn.Name = "DeleteBtn";
            DeleteBtn.Size = new Size(90, 30);
            DeleteBtn.TabIndex = 26;
            DeleteBtn.Text = "Удалить";
            DeleteBtn.UseVisualStyleBackColor = true;
            DeleteBtn.Click += DeleteBtn_Click;
            // 
            // SaveBtn
            // 
            SaveBtn.Location = new Point(720, 339);
            SaveBtn.Name = "SaveBtn";
            SaveBtn.Size = new Size(90, 30);
            SaveBtn.TabIndex = 27;
            SaveBtn.Text = "Сохранить";
            SaveBtn.UseVisualStyleBackColor = true;
            SaveBtn.Click += SaveBtn_Click;
            // 
            // CreateBtn
            // 
            CreateBtn.Location = new Point(816, 339);
            CreateBtn.Name = "CreateBtn";
            CreateBtn.Size = new Size(90, 30);
            CreateBtn.TabIndex = 28;
            CreateBtn.Text = "Создать";
            CreateBtn.UseVisualStyleBackColor = true;
            CreateBtn.Click += CreateBtn_Click;
            // 
            // BackBtn
            // 
            BackBtn.Location = new Point(12, 9);
            BackBtn.Name = "BackBtn";
            BackBtn.Size = new Size(64, 28);
            BackBtn.TabIndex = 29;
            BackBtn.Text = "Назад";
            BackBtn.UseVisualStyleBackColor = true;
            BackBtn.Click += BackBtn_Click;
            // 
            // ProductEditForm
            // 
            AutoScaleDimensions = new SizeF(7F, 15F);
            AutoScaleMode = AutoScaleMode.Font;
            AutoSizeMode = AutoSizeMode.GrowAndShrink;
            ClientSize = new Size(920, 385);
            Controls.Add(BackBtn);
            Controls.Add(CreateBtn);
            Controls.Add(SaveBtn);
            Controls.Add(DeleteBtn);
            Controls.Add(QuantityTextBox);
            Controls.Add(label11);
            Controls.Add(DiscountTextBox);
            Controls.Add(label10);
            Controls.Add(CategoryComboBox);
            Controls.Add(label9);
            Controls.Add(ManufacturerComboBox);
            Controls.Add(label8);
            Controls.Add(SupplierComboBox);
            Controls.Add(label7);
            Controls.Add(UnitComboBox);
            Controls.Add(label6);
            Controls.Add(label5);
            Controls.Add(PriceTextBox);
            Controls.Add(label4);
            Controls.Add(DescriptionTextBox);
            Controls.Add(label3);
            Controls.Add(ArticleTextBox);
            Controls.Add(TitleTextBox);
            Controls.Add(ProductPictureBox);
            Controls.Add(label2);
            Controls.Add(label1);
            Name = "ProductEditForm";
            Text = "ProductEditForm";
            ((System.ComponentModel.ISupportInitialize)ProductPictureBox).EndInit();
            ResumeLayout(false);
            PerformLayout();
        }

        #endregion

        private Label label1;
        private Label label2;
        private PictureBox ProductPictureBox;
        private TextBox TitleTextBox;
        private TextBox ArticleTextBox;
        private TextBox DescriptionTextBox;
        private Label label3;
        private TextBox PriceTextBox;
        private Label label4;
        private Label label5;
        private Label label6;
        private ComboBox UnitComboBox;
        private ComboBox SupplierComboBox;
        private Label label7;
        private ComboBox ManufacturerComboBox;
        private Label label8;
        private ComboBox CategoryComboBox;
        private Label label9;
        private TextBox DiscountTextBox;
        private Label label10;
        private TextBox QuantityTextBox;
        private Label label11;
        private Button DeleteBtn;
        private Button SaveBtn;
        private Button CreateBtn;
        private Button BackBtn;
    }
}


OrdersForm.cs

using AppCore.Helpers;
using Demo_Ex_8.Cards;
using Demo_Ex_8.Services;
using System.Data;

namespace Demo_Ex_8.Forms
{
    public partial class OrderForm : Form
    {
        private const string IconPath =
            @"C:\Users\eleskov\Desktop\Подготовка к ДЭ\Demo_Ex_8\Demo_Ex_8\Resourse\icon.ico";

        public OrderForm()
        {
            InitializeComponent();

            FormHelper.Configure(this, "Заказы", IconPath);

            LoadOrders();
        }

        private void LoadOrders()
        {
            DataTable table = OrdersService.GetOrders();

            CardPanelHelper.Clear(OrdersPanel);

            foreach (DataRow row in table.Rows)
            {
                OrderCard card = new(row);

                card.Width = OrdersPanel.Width - 25;
                card.CardClicked += OrderCard_Click;

                CardPanelHelper.AddCard(OrdersPanel, card);
            }

            if (!CardPanelHelper.HasCards(OrdersPanel))
            {
                CardPanelHelper.ShowEmptyMessage(
                    OrdersPanel,
                    "Заказы не найдены");
            }
        }

        private void OrderCard_Click(object? sender, int orderId)
        {
            FormHelper.OpenSingleDialog(
                () => new OrderEditForm(orderId),
                LoadOrders);
        }

        private void AddOrderBtn_Click(object sender, EventArgs e)
        {
            FormHelper.OpenSingleDialog(
                () => new OrderEditForm(),
                LoadOrders);
        }

        private void BackBtn_Click(object sender, EventArgs e)
        {
            FormHelper.Back(this);
        }
    }
}


OrderEditForm.cs

using AppCore.Helpers;
using Demo_Ex_8.Services;
using System.Data;

namespace Demo_Ex_8.Forms
{
    public partial class OrderEditForm : Form
    {
        private readonly int? _orderId;

        private const string IconPath =
            @"C:\Users\eleskov\Desktop\Подготовка к ДЭ\Demo_Ex_8\Demo_Ex_8\Resourse\icon.ico";

        public bool IsSaved { get; private set; }

        public OrderEditForm()
        {
            InitializeComponent();

            FormHelper.Configure(this, "Создание заказа", IconPath);

            ConfigureCreateMode();
            LoadComboBoxes();
        }

        public OrderEditForm(int orderId)
        {
            InitializeComponent();

            _orderId = orderId;

            FormHelper.Configure(this, "Редактирование заказа", IconPath);

            ConfigureEditMode();
            LoadComboBoxes();
            LoadOrderData(orderId);
        }

        private void ConfigureCreateMode()
        {
            OrderNumber.Text = "Новый";

            CreateBtn.Visible = true;
            SaveBtn.Visible = false;
            DeleteBtn.Visible = false;

            OrderDate.Value = DateTime.Today;
            DeliveryDate.Value = DateTime.Today;
        }

        private void ConfigureEditMode()
        {
            CreateBtn.Visible = false;
            SaveBtn.Visible = true;
            DeleteBtn.Visible = true;
        }

        private void LoadComboBoxes()
        {
            ComboBoxHelper.Load(
                StatusComboBox,
                OrdersService.GetStatuses(),
                "status_name",
                "id");

            ComboBoxHelper.Load(
                PickupPointAddressComboBox,
                OrdersService.GetPickupPoints(),
                "pickup_point",
                "id");

            ComboBoxHelper.Load(
                UserComboBox,
                OrdersService.GetUsers(),
                "full_name",
                "id");
        }

        private void LoadOrderData(int orderId)
        {
            DataTable table = OrdersService.GetOrderById(orderId);

            if (table.Rows.Count == 0)
            {
                MessageBoxHelper.Warning("Заказ не найден");
                Close();
                return;
            }

            DataRow row = table.Rows[0];

            OrderNumber.Text = row["id"].ToString();

            OrderDate.Value = Convert.ToDateTime(row["order_date"]);
            DeliveryDate.Value = Convert.ToDateTime(row["delivery_date"]);

            ReceiptCode.Text = row["receipt_code"].ToString();

            PickupPointAddressComboBox.SelectedValue = Convert.ToInt32(row["pickup_point_id"]);
            UserComboBox.SelectedValue = Convert.ToInt32(row["user_id"]);
            StatusComboBox.SelectedValue = Convert.ToInt32(row["status_id"]);
        }

        private bool ValidateForm()
        {
            if (!ValidationHelper.ValidateRequiredField(ReceiptCode.Text, "Код получения"))
            {
                return false;
            }

            if (!ValidationHelper.ValidateComboBoxSelected(StatusComboBox, "Статус заказа"))
            {
                return false;
            }

            if (!ValidationHelper.ValidateComboBoxSelected(PickupPointAddressComboBox, "Адрес пункта выдачи"))
            {
                return false;
            }

            if (!ValidationHelper.ValidateComboBoxSelected(UserComboBox, "Пользователь"))
            {
                return false;
            }

            if (!ValidationHelper.ValidateDateRange(
                OrderDate.Value.Date,
                DeliveryDate.Value.Date))
            {
                return false;
            }

            return true;
        }

        private void CreateBtn_Click(object sender, EventArgs e)
        {
            if (!ValidateForm())
            {
                return;
            }

            bool result = OrdersService.CreateOrder(
                OrderDate.Value.Date,
                DeliveryDate.Value.Date,
                ComboBoxHelper.GetSelectedIntValue(PickupPointAddressComboBox),
                ComboBoxHelper.GetSelectedIntValue(UserComboBox),
                ReceiptCode.Text.Trim(),
                ComboBoxHelper.GetSelectedIntValue(StatusComboBox));

            if (result)
            {
                IsSaved = true;
                MessageBoxHelper.Info("Заказ успешно создан");
                Close();
            }
        }

        private void SaveBtn_Click(object sender, EventArgs e)
        {
            if (!_orderId.HasValue)
            {
                MessageBoxHelper.Warning("Не выбран заказ для редактирования");
                return;
            }

            if (!ValidateForm())
            {
                return;
            }

            bool result = OrdersService.UpdateOrder(
                _orderId.Value,
                OrderDate.Value.Date,
                DeliveryDate.Value.Date,
                ComboBoxHelper.GetSelectedIntValue(PickupPointAddressComboBox),
                ComboBoxHelper.GetSelectedIntValue(UserComboBox),
                ReceiptCode.Text.Trim(),
                ComboBoxHelper.GetSelectedIntValue(StatusComboBox));

            if (result)
            {
                IsSaved = true;
                MessageBoxHelper.Info("Заказ успешно сохранён");
                Close();
            }
        }

        private void DeleteBtn_Click(object sender, EventArgs e)
        {
            if (!_orderId.HasValue)
            {
                MessageBoxHelper.Warning("Не выбран заказ для удаления");
                return;
            }

            if (!MessageBoxHelper.Confirm("Удалить выбранный заказ?"))
            {
                return;
            }

            bool result = OrdersService.DeleteOrder(_orderId.Value);

            if (result)
            {
                IsSaved = true;
                MessageBoxHelper.Info("Заказ успешно удалён");
                Close();
            }
        }

        private void BackBtn_Click(object sender, EventArgs e)
        {
            FormHelper.Back(this);
        }
    }
}

OrderEditForm.designer

namespace Demo_Ex_8.Forms
{
    partial class OrderEditForm
    {
        /// <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()
        {
            CreateBtn = new Button();
            SaveBtn = new Button();
            DeleteBtn = new Button();
            label1 = new Label();
            label2 = new Label();
            label3 = new Label();
            StatusComboBox = new ComboBox();
            PickupPointAddressComboBox = new ComboBox();
            label4 = new Label();
            label5 = new Label();
            label6 = new Label();
            DeliveryDate = new DateTimePicker();
            OrderDate = new DateTimePicker();
            OrderNumber = new Label();
            UserComboBox = new ComboBox();
            OrderUser = new Label();
            label8 = new Label();
            ReceiptCode = new TextBox();
            BackBtn = new Button();
            SuspendLayout();
            // 
            // CreateBtn
            // 
            CreateBtn.Location = new Point(712, 267);
            CreateBtn.Name = "CreateBtn";
            CreateBtn.Size = new Size(90, 30);
            CreateBtn.TabIndex = 31;
            CreateBtn.Text = "Создать";
            CreateBtn.UseVisualStyleBackColor = true;
            CreateBtn.Click += CreateBtn_Click;
            // 
            // SaveBtn
            // 
            SaveBtn.Location = new Point(600, 267);
            SaveBtn.Name = "SaveBtn";
            SaveBtn.Size = new Size(106, 30);
            SaveBtn.TabIndex = 30;
            SaveBtn.Text = "Сохранить";
            SaveBtn.UseVisualStyleBackColor = true;
            SaveBtn.Click += SaveBtn_Click;
            // 
            // DeleteBtn
            // 
            DeleteBtn.Location = new Point(12, 267);
            DeleteBtn.Name = "DeleteBtn";
            DeleteBtn.Size = new Size(90, 30);
            DeleteBtn.TabIndex = 29;
            DeleteBtn.Text = "Удалить";
            DeleteBtn.UseVisualStyleBackColor = true;
            DeleteBtn.Click += DeleteBtn_Click;
            // 
            // label1
            // 
            label1.AutoSize = true;
            label1.Location = new Point(12, 47);
            label1.Name = "label1";
            label1.Size = new Size(108, 21);
            label1.TabIndex = 33;
            label1.Text = "Номер заказа";
            // 
            // label2
            // 
            label2.AutoSize = true;
            label2.Location = new Point(12, 118);
            label2.Name = "label2";
            label2.Size = new Size(107, 21);
            label2.TabIndex = 35;
            label2.Text = "Статус заказа";
            // 
            // label3
            // 
            label3.AutoSize = true;
            label3.Location = new Point(207, 43);
            label3.Name = "label3";
            label3.Size = new Size(164, 21);
            label3.TabIndex = 37;
            label3.Text = "Адрес пункта выдачи";
            // 
            // StatusComboBox
            // 
            StatusComboBox.FormattingEnabled = true;
            StatusComboBox.Location = new Point(12, 142);
            StatusComboBox.Name = "StatusComboBox";
            StatusComboBox.Size = new Size(164, 29);
            StatusComboBox.TabIndex = 38;
            // 
            // PickupPointAddressComboBox
            // 
            PickupPointAddressComboBox.FormattingEnabled = true;
            PickupPointAddressComboBox.Location = new Point(207, 71);
            PickupPointAddressComboBox.Name = "PickupPointAddressComboBox";
            PickupPointAddressComboBox.Size = new Size(291, 29);
            PickupPointAddressComboBox.TabIndex = 39;
            // 
            // label4
            // 
            label4.AutoSize = true;
            label4.Location = new Point(526, 118);
            label4.Name = "label4";
            label4.Size = new Size(0, 21);
            label4.TabIndex = 40;
            // 
            // label5
            // 
            label5.AutoSize = true;
            label5.Location = new Point(526, 118);
            label5.Name = "label5";
            label5.Size = new Size(94, 21);
            label5.TabIndex = 43;
            label5.Text = "Дата заказа";
            // 
            // label6
            // 
            label6.AutoSize = true;
            label6.Location = new Point(526, 43);
            label6.Name = "label6";
            label6.Size = new Size(113, 21);
            label6.TabIndex = 45;
            label6.Text = "Дата доставки";
            // 
            // DeliveryDate
            // 
            DeliveryDate.Location = new Point(526, 71);
            DeliveryDate.Name = "DeliveryDate";
            DeliveryDate.Size = new Size(200, 29);
            DeliveryDate.TabIndex = 46;
            // 
            // OrderDate
            // 
            OrderDate.Location = new Point(526, 142);
            OrderDate.Name = "OrderDate";
            OrderDate.Size = new Size(200, 29);
            OrderDate.TabIndex = 47;
            // 
            // OrderNumber
            // 
            OrderNumber.AutoSize = true;
            OrderNumber.Location = new Point(12, 74);
            OrderNumber.Name = "OrderNumber";
            OrderNumber.Size = new Size(19, 21);
            OrderNumber.TabIndex = 48;
            OrderNumber.Text = "0";
            // 
            // UserComboBox
            // 
            UserComboBox.FormattingEnabled = true;
            UserComboBox.Location = new Point(207, 142);
            UserComboBox.Name = "UserComboBox";
            UserComboBox.Size = new Size(291, 29);
            UserComboBox.TabIndex = 50;
            // 
            // OrderUser
            // 
            OrderUser.AutoSize = true;
            OrderUser.Location = new Point(207, 118);
            OrderUser.Name = "OrderUser";
            OrderUser.Size = new Size(109, 21);
            OrderUser.TabIndex = 49;
            OrderUser.Text = "Пользователь";
            // 
            // label8
            // 
            label8.AutoSize = true;
            label8.Location = new Point(12, 189);
            label8.Name = "label8";
            label8.Size = new Size(118, 21);
            label8.TabIndex = 51;
            label8.Text = "Код получения";
            // 
            // ReceiptCode
            // 
            ReceiptCode.Location = new Point(12, 213);
            ReceiptCode.Name = "ReceiptCode";
            ReceiptCode.Size = new Size(164, 29);
            ReceiptCode.TabIndex = 52;
            // 
            // BackBtn
            // 
            BackBtn.Location = new Point(12, 12);
            BackBtn.Name = "BackBtn";
            BackBtn.Size = new Size(82, 29);
            BackBtn.TabIndex = 53;
            BackBtn.Text = "Назад";
            BackBtn.UseVisualStyleBackColor = true;
            BackBtn.Click += BackBtn_Click;
            // 
            // OrderEditForm
            // 
            AutoScaleDimensions = new SizeF(9F, 21F);
            AutoScaleMode = AutoScaleMode.Font;
            ClientSize = new Size(814, 305);
            Controls.Add(BackBtn);
            Controls.Add(ReceiptCode);
            Controls.Add(label8);
            Controls.Add(UserComboBox);
            Controls.Add(OrderUser);
            Controls.Add(OrderNumber);
            Controls.Add(OrderDate);
            Controls.Add(DeliveryDate);
            Controls.Add(label6);
            Controls.Add(label5);
            Controls.Add(label4);
            Controls.Add(PickupPointAddressComboBox);
            Controls.Add(StatusComboBox);
            Controls.Add(label3);
            Controls.Add(label2);
            Controls.Add(label1);
            Controls.Add(CreateBtn);
            Controls.Add(SaveBtn);
            Controls.Add(DeleteBtn);
            Font = new Font("Segoe UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 204);
            Margin = new Padding(4);
            Name = "OrderEditForm";
            Text = "OrderEditForm";
            ResumeLayout(false);
            PerformLayout();
        }

        #endregion

        private Button CreateBtn;
        private Button SaveBtn;
        private Button DeleteBtn;
        private Label label1;
        private Label label2;
        private Label label3;
        private ComboBox StatusComboBox;
        private ComboBox PickupPointAddressComboBox;
        private Label label4;
        private Label label5;
        private Label label6;
        private DateTimePicker DeliveryDate;
        private DateTimePicker OrderDate;
        private Label OrderNumber;
        private ComboBox UserComboBox;
        private Label OrderUser;
        private Label label8;
        private TextBox ReceiptCode;
        private Button BackBtn;
    }
}


Sql

CREATE TABLE roles (
	id INT PRIMARY KEY IDENTITY,
	role_name NVARCHAR(100) NOT NULL UNIQUE
);

CREATE TABLE units (
	id INT PRIMARY KEY IDENTITY,
	unit_name NVARCHAR(100) NOT NULL UNIQUE
);

CREATE TABLE suppliers (
	id INT PRIMARY KEY IDENTITY,
	supplier_name NVARCHAR(100) NOT NULL UNIQUE
);

CREATE TABLE manufacturers (
	id INT PRIMARY KEY IDENTITY,
	manufacturer_name NVARCHAR(100) NOT NULL UNIQUE
);

CREATE TABLE categories (
	id INT PRIMARY KEY IDENTITY,
	category_name NVARCHAR(100) NOT NULL UNIQUE
);

CREATE TABLE statuses (
	id INT PRIMARY KEY IDENTITY,
	status_name NVARCHAR(100) NOT NULL UNIQUE
);

CREATE TABLE cities (
	id INT PRIMARY KEY IDENTITY,
	city_name NVARCHAR(100) NOT NULL UNIQUE
);


CREATE TABLE users (
	id INT PRIMARY KEY IDENTITY,
	role_id INT NOT NULL,
	full_name NVARCHAR(255) NOT NULL,
	login NVARCHAR(255) NOT NULL UNIQUE,
	password NVARCHAR(255) NOT NULL
);

CREATE TABLE products (
	id INT PRIMARY KEY IDENTITY,
	article NVARCHAR(50) NOT NULL UNIQUE,
	title NVARCHAR(255) NOT NULL,
	unit_id INT NOT NULL,
	price DECIMAL NOT NULL,
	supplier_id INT NOT NULL,
	manufacturer_id INT NOT NULL,
	category_id INT NOT NULL,
	discount INT NOT NULL DEFAULT 0,
	quantity INT NOT NULL DEFAULT 0,
	description NVARCHAR(1000) NULL,
	picture_path NVARCHAR(500) NULL,

	CONSTRAINT CK_products_price
	CHECK (price >= 0),

	CONSTRAINT CK_products_discount
	CHECK (discount >= 0 AND discount <= 100),

	
	CONSTRAINT CK_products_quantity
	CHECK (quantity >= 0)
);

CREATE TABLE pickup_points (
	id INT PRIMARY KEY IDENTITY,
	postal_code NVARCHAR(30) NOT NULL,
	city_id INT,
	street NVARCHAR(100) NOT NULL,
	house NVARCHAR(30)	 NOT NULL
);

CREATE TABLE orders (
	id INT PRIMARY KEY IDENTITY,
	order_date DATE NOT NULL DEFAULT CAST(GETDATE() AS DATE),
	delivery_date DATE NOT NULL,
	pickup_point_id INT NOT NULL,
	user_id INT NOT NULL,
	receipt_code NVARCHAR(20) NOT NULL,
	status_id INT,

	CONSTRAINT CK_orders_dates
    CHECK (delivery_date >= order_date)
);

CREATE TABLE order_items (
	order_id INT NOT NULL,
	product_id INT NOT NULL,
	quantity INT NOT NULL,

	CONSTRAINT CK_order_items_quantity
    CHECK (quantity > 0)
);
Product Compatible and additional computed target framework versions.
.NET net8.0-windows7.0 is compatible.  net9.0-windows was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.13 130 6/14/2026
1.0.12 106 6/14/2026
1.0.11 110 6/13/2026
1.0.10 111 6/13/2026
1.0.9 105 6/13/2026
1.0.8 114 6/13/2026
1.0.7 117 6/12/2026
1.0.6 109 6/10/2026
1.0.5 107 6/8/2026
1.0.4 114 6/7/2026
1.0.3 110 6/6/2026
1.0.2 110 6/6/2026
1.0.1 113 6/4/2026