diff --git a/Confectionery/ConfectioneryView/FormPastry.Designer.cs b/Confectionery/ConfectioneryView/FormPastry.Designer.cs
index bd84ac9..8e229a3 100644
--- a/Confectionery/ConfectioneryView/FormPastry.Designer.cs
+++ b/Confectionery/ConfectioneryView/FormPastry.Designer.cs
@@ -28,12 +28,56 @@
         /// </summary>
         private void InitializeComponent()
         {
-            this.components = new System.ComponentModel.Container();
+            this.textBoxName = new System.Windows.Forms.TextBox();
+            this.textBoxPrice = new System.Windows.Forms.TextBox();
+            this.dataGridView = new System.Windows.Forms.DataGridView();
+            ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // textBoxName
+            // 
+            this.textBoxName.Location = new System.Drawing.Point(281, 12);
+            this.textBoxName.Name = "textBoxName";
+            this.textBoxName.Size = new System.Drawing.Size(125, 27);
+            this.textBoxName.TabIndex = 0;
+            // 
+            // textBoxPrice
+            // 
+            this.textBoxPrice.Location = new System.Drawing.Point(281, 62);
+            this.textBoxPrice.Name = "textBoxPrice";
+            this.textBoxPrice.Size = new System.Drawing.Size(125, 27);
+            this.textBoxPrice.TabIndex = 1;
+            // 
+            // dataGridView
+            // 
+            this.dataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+            this.dataGridView.Location = new System.Drawing.Point(12, 250);
+            this.dataGridView.Name = "dataGridView";
+            this.dataGridView.RowHeadersWidth = 51;
+            this.dataGridView.RowTemplate.Height = 29;
+            this.dataGridView.Size = new System.Drawing.Size(300, 188);
+            this.dataGridView.TabIndex = 2;
+            // 
+            // FormPastry
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-            this.ClientSize = new System.Drawing.Size(800, 450);
+            this.ClientSize = new System.Drawing.Size(1025, 450);
+            this.Controls.Add(this.dataGridView);
+            this.Controls.Add(this.textBoxPrice);
+            this.Controls.Add(this.textBoxName);
+            this.Name = "FormPastry";
             this.Text = "FormPastry";
+            ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).EndInit();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
         }
 
         #endregion
+
+        private TextBox textBoxName;
+        private TextBox textBoxPrice;
+        private DataGridView dataGridView;
     }
 }
\ No newline at end of file
diff --git a/Confectionery/ConfectioneryView/FormPastry.cs b/Confectionery/ConfectioneryView/FormPastry.cs
index 3fd8072..dfd0549 100644
--- a/Confectionery/ConfectioneryView/FormPastry.cs
+++ b/Confectionery/ConfectioneryView/FormPastry.cs
@@ -1,4 +1,8 @@
-using Microsoft.Extensions.Logging;
+using ConfectioneryContracts.BusinessLogicsContracts;
+using ConfectioneryContracts.BindingModels;
+using ConfectioneryContracts.SearchModels;
+using ConfectioneryDataModels.Models;
+using Microsoft.Extensions.Logging;
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -14,10 +18,209 @@ namespace ConfectioneryView
     public partial class FormPastry : Form
     {
         private readonly ILogger _logger;
+        private readonly IPastryLogic _logic;
         private int? _id;
-        public FormPastry()
+        private Dictionary<int, (IComponentModel, int)> _pastryComponents;
+        public int Id { set { _id = value; } }
+
+        public FormPastry(ILogger<FormPastry> logger, IPastryLogic logic)
         {
             InitializeComponent();
+            _logger = logger;
+            _logic = logic;
+            _pastryComponents = new Dictionary<int, (IComponentModel, int)>();
+        }
+
+        private void FormProduct_Load(object sender, EventArgs e)
+        {
+            if (_id.HasValue)
+            {
+                _logger.LogInformation("Загрузка изделия");
+                try
+                {
+                    var view = _logic.ReadElement(new PastrySearchModel
+                    {
+                        Id = _id.Value
+                    });
+                    if (view != null)
+                    {
+                        textBoxName.Text = view.PastryName;
+                        textBoxPrice.Text = view.Price.ToString();
+                        _pastryComponents = view.PastryComponents ?? new
+                        Dictionary<int, (IComponentModel, int)>();
+                        LoadData();
+                    }
+                }
+                catch (Exception ex)
+                {
+                    _logger.LogError(ex, "Ошибка загрузки изделия");
+                    MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK,
+                    MessageBoxIcon.Error);
+                }
+            }
+        }
+
+        private void LoadData()
+        {
+            _logger.LogInformation("Загрузка компонент изделия");
+            try
+            {
+                if (_pastryComponents != null)
+                {
+                    dataGridView.Rows.Clear();
+                    foreach (var pc in _pastryComponents)
+                    {
+                        dataGridView.Rows.Add(new object[] { pc.Key, pc.Value.Item1.ComponentName, pc.Value.Item2 });
+                    }
+                    textBoxPrice.Text = CalcPrice().ToString();
+                }
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError(ex, "Ошибка загрузки компонент изделия");
+                MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK,
+               MessageBoxIcon.Error);
+            }
+        }
+
+        private void ButtonAdd_Click(object sender, EventArgs e)
+        {
+            var service =
+           Program.ServiceProvider?.GetService(typeof(FormPastryComponent));
+            if (service is FormPastryComponent form)
+            {
+                if (form.ShowDialog() == DialogResult.OK)
+                {
+                    if (form.ComponentModel == null)
+                    {
+                        return;
+                    }
+                    _logger.LogInformation("Добавление нового компонента: { ComponentName} - { Count}", form.ComponentModel.ComponentName, form.Count);
+                    if (_pastryComponents.ContainsKey(form.Id))
+                    {
+                        _pastryComponents[form.Id] = (form.ComponentModel,
+                       form.Count);
+                    }
+                    else
+                    {
+                        _pastryComponents.Add(form.Id, (form.ComponentModel,
+                       form.Count));
+                    }
+                    LoadData();
+                }
+            }
+        }
+
+        private void ButtonUpd_Click(object sender, EventArgs e)
+        {
+            if (dataGridView.SelectedRows.Count == 1)
+            {
+                var service =
+               Program.ServiceProvider?.GetService(typeof(FormPastryComponent));
+                if (service is FormPastryComponent form)
+                {
+                    int id =
+                   Convert.ToInt32(dataGridView.SelectedRows[0].Cells[0].Value);
+                    form.Id = id;
+                    form.Count = _pastryComponents[id].Item2;
+                    if (form.ShowDialog() == DialogResult.OK)
+                    {
+                        if (form.ComponentModel == null)
+                        {
+                            return;
+                        }
+                        _logger.LogInformation("Изменение компонента: { ComponentName} - { Count}", form.ComponentModel.ComponentName, form.Count);
+                        _pastryComponents[form.Id] = (form.ComponentModel, form.Count);
+                        LoadData();
+                    }
+                }
+            }
+        }
+
+        private void ButtonDel_Click(object sender, EventArgs e)
+        {
+            if (dataGridView.SelectedRows.Count == 1)
+            {
+                if (MessageBox.Show("Удалить запись?", "Вопрос",
+               MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
+                {
+                    try
+                    {
+                        _logger.LogInformation("Удаление компонента: { ComponentName} - { Count}", dataGridView.SelectedRows[0].Cells[1].Value);
+                        _pastryComponents?.Remove(Convert.ToInt32(dataGridView.SelectedRows[0].Cells[0].Value));
+                    }
+                    catch (Exception ex)
+                    {
+                        MessageBox.Show(ex.Message, "Ошибка",
+                       MessageBoxButtons.OK, MessageBoxIcon.Error);
+                    }
+                    LoadData();
+                }
+            }
+        }
+
+        private void ButtonSave_Click(object sender, EventArgs e)
+        {
+            if (string.IsNullOrEmpty(textBoxName.Text))
+            {
+                MessageBox.Show("Заполните название", "Ошибка",
+                MessageBoxButtons.OK, MessageBoxIcon.Error);
+                return;
+            }
+            if (string.IsNullOrEmpty(textBoxPrice.Text))
+            {
+                MessageBox.Show("Заполните цену", "Ошибка", MessageBoxButtons.OK,
+                MessageBoxIcon.Error);
+                return;
+            }
+            if (_pastryComponents == null || _pastryComponents.Count == 0)
+            {
+                MessageBox.Show("Заполните компоненты", "Ошибка",
+               MessageBoxButtons.OK, MessageBoxIcon.Error);
+                return;
+            }
+            _logger.LogInformation("Сохранение изделия");
+            try
+            {
+                var model = new PastryBindingModel
+                {
+                    Id = _id ?? 0,
+                    PastryName = textBoxName.Text,
+                    Price = Convert.ToDouble(textBoxPrice.Text),
+                    PastryComponents = _pastryComponents
+                };
+                var operationResult = _id.HasValue ? _logic.Update(model) :
+               _logic.Create(model);
+                if (!operationResult)
+                {
+                    throw new Exception("Ошибка при сохранении. Дополнительная информация в логах.");
+                }
+                MessageBox.Show("Сохранение прошло успешно", "Сообщение",
+                MessageBoxButtons.OK, MessageBoxIcon.Information);
+                DialogResult = DialogResult.OK;
+                Close();
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError(ex, "Ошибка сохранения изделия");
+                MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+            }
+        }
+
+        private void ButtonCancel_Click(object sender, EventArgs e)
+        {
+            DialogResult = DialogResult.Cancel;
+            Close();
+        }
+
+        private double CalcPrice()
+        {
+            double price = 0;
+            foreach (var elem in _pastryComponents)
+            {
+                price += ((elem.Value.Item1?.Cost ?? 0) * elem.Value.Item2);
+            }
+            return Math.Round(price * 1.1, 2);
         }
     }
 }
diff --git a/Confectionery/ConfectioneryView/FormPastry.resx b/Confectionery/ConfectioneryView/FormPastry.resx
index 1af7de1..f298a7b 100644
--- a/Confectionery/ConfectioneryView/FormPastry.resx
+++ b/Confectionery/ConfectioneryView/FormPastry.resx
@@ -1,64 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<root>
-  <!-- 
-    Microsoft ResX Schema 
-    
-    Version 2.0
-    
-    The primary goals of this format is to allow a simple XML format 
-    that is mostly human readable. The generation and parsing of the 
-    various data types are done through the TypeConverter classes 
-    associated with the data types.
-    
-    Example:
-    
-    ... ado.net/XML headers & schema ...
-    <resheader name="resmimetype">text/microsoft-resx</resheader>
-    <resheader name="version">2.0</resheader>
-    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
-    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
-    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
-    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
-    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
-        <value>[base64 mime encoded serialized .NET Framework object]</value>
-    </data>
-    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
-        <comment>This is a comment</comment>
-    </data>
-                
-    There are any number of "resheader" rows that contain simple 
-    name/value pairs.
-    
-    Each data row contains a name, and value. The row also contains a 
-    type or mimetype. Type corresponds to a .NET class that support 
-    text/value conversion through the TypeConverter architecture. 
-    Classes that don't support this are serialized and stored with the 
-    mimetype set.
-    
-    The mimetype is used for serialized objects, and tells the 
-    ResXResourceReader how to depersist the object. This is currently not 
-    extensible. For a given mimetype the value must be set accordingly:
-    
-    Note - application/x-microsoft.net.object.binary.base64 is the format 
-    that the ResXResourceWriter will generate, however the reader can 
-    read any of the formats listed below.
-    
-    mimetype: application/x-microsoft.net.object.binary.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
-            : and then encoded with base64 encoding.
-    
-    mimetype: application/x-microsoft.net.object.soap.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
-            : and then encoded with base64 encoding.
-
-    mimetype: application/x-microsoft.net.object.bytearray.base64
-    value   : The object must be serialized into a byte array 
-            : using a System.ComponentModel.TypeConverter
-            : and then encoded with base64 encoding.
-    -->
+<root>
   <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
     <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
     <xsd:element name="root" msdata:IsDataSet="true">