diff --git a/SushiBar/FormMain.Designer.cs b/SushiBar/FormMain.Designer.cs index 070b5ab..254c452 100644 --- a/SushiBar/FormMain.Designer.cs +++ b/SushiBar/FormMain.Designer.cs @@ -40,6 +40,7 @@ buttonOrderIssued = new Button(); buttonRefreshOrders = new Button(); buttonAddSushiInShop = new Button(); + buttonSelling = new Button(); menuStrip1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit(); SuspendLayout(); @@ -136,7 +137,7 @@ // // buttonRefreshOrders // - buttonRefreshOrders.Location = new Point(923, 450); + buttonRefreshOrders.Location = new Point(923, 476); buttonRefreshOrders.Name = "buttonRefreshOrders"; buttonRefreshOrders.Size = new Size(171, 52); buttonRefreshOrders.TabIndex = 6; @@ -145,7 +146,7 @@ // // buttonAddSushiInShop // - buttonAddSushiInShop.Location = new Point(923, 359); + buttonAddSushiInShop.Location = new Point(923, 333); buttonAddSushiInShop.Name = "buttonAddSushiInShop"; buttonAddSushiInShop.Size = new Size(171, 52); buttonAddSushiInShop.TabIndex = 7; @@ -153,12 +154,23 @@ buttonAddSushiInShop.UseVisualStyleBackColor = true; buttonAddSushiInShop.Click += buttonAddSushiInShop_Click; // + // buttonSelling + // + buttonSelling.Location = new Point(923, 404); + buttonSelling.Name = "buttonSelling"; + buttonSelling.Size = new Size(171, 52); + buttonSelling.TabIndex = 8; + buttonSelling.Text = "Продать суши"; + buttonSelling.UseVisualStyleBackColor = true; + buttonSelling.Click += buttonSelling_Click; + // // FormMain // AutoScaleDimensions = new SizeF(8F, 20F); AutoScaleMode = AutoScaleMode.Font; BackColor = Color.FromArgb(210, 255, 210); ClientSize = new Size(1140, 540); + Controls.Add(buttonSelling); Controls.Add(buttonAddSushiInShop); Controls.Add(buttonRefreshOrders); Controls.Add(buttonOrderIssued); @@ -192,5 +204,6 @@ private ToolStripMenuItem сушиToolStripMenuItem; private ToolStripMenuItem магазиныToolStripMenuItem; private Button buttonAddSushiInShop; + private Button buttonSelling; } } \ No newline at end of file diff --git a/SushiBar/FormMain.cs b/SushiBar/FormMain.cs index 4b2f7cc..2c05316 100644 --- a/SushiBar/FormMain.cs +++ b/SushiBar/FormMain.cs @@ -103,7 +103,7 @@ namespace SushiBarView _logger.LogInformation("Заказ ${id}. Меняется статус на 'Готов'", id); try { - var operationResult = _orderLogic.FinishOrder(new OrderBindingModel { Id = id }); + var operationResult = _orderLogic.FinishOrder(new OrderBindingModel { Id = id, }); if (!operationResult) { throw new Exception("Ошибка при сохранении. Дополнительная информация в логах."); @@ -155,5 +155,14 @@ namespace SushiBarView form.ShowDialog(); } } + + private void buttonSelling_Click(object sender, EventArgs e) + { + var service = Program.ServiceProvider?.GetService(typeof(FormSell)); + if (service is FormSell form) + { + form.ShowDialog(); + } + } } } diff --git a/SushiBar/Program.cs b/SushiBar/Program.cs index 9ffdc31..bea7568 100644 --- a/SushiBar/Program.cs +++ b/SushiBar/Program.cs @@ -59,6 +59,7 @@ namespace SushiBar services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); } } } \ No newline at end of file diff --git a/SushiBar/Shops/FormSell.Designer.cs b/SushiBar/Shops/FormSell.Designer.cs new file mode 100644 index 0000000..b690675 --- /dev/null +++ b/SushiBar/Shops/FormSell.Designer.cs @@ -0,0 +1,128 @@ +namespace SushiBarView.Shops +{ + partial class FormSell + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + comboBoxSushis = new ComboBox(); + labelSushi = new Label(); + numericUpDownCountForSelling = new NumericUpDown(); + labelCountForSelling = new Label(); + buttonSell = new Button(); + buttonCancel = new Button(); + ((System.ComponentModel.ISupportInitialize)numericUpDownCountForSelling).BeginInit(); + SuspendLayout(); + // + // comboBoxSushis + // + comboBoxSushis.FormattingEnabled = true; + comboBoxSushis.Location = new Point(342, 41); + comboBoxSushis.Margin = new Padding(4); + comboBoxSushis.Name = "comboBoxSushis"; + comboBoxSushis.Size = new Size(206, 32); + comboBoxSushis.TabIndex = 0; + // + // labelSushi + // + labelSushi.AutoSize = true; + labelSushi.Location = new Point(45, 50); + labelSushi.Margin = new Padding(4, 0, 4, 0); + labelSushi.Name = "labelSushi"; + labelSushi.Size = new Size(56, 24); + labelSushi.TabIndex = 1; + labelSushi.Text = "Суши"; + // + // numericUpDownCountForSelling + // + numericUpDownCountForSelling.Location = new Point(342, 124); + numericUpDownCountForSelling.Margin = new Padding(4); + numericUpDownCountForSelling.Name = "numericUpDownCountForSelling"; + numericUpDownCountForSelling.Size = new Size(208, 32); + numericUpDownCountForSelling.TabIndex = 2; + // + // labelCountForSelling + // + labelCountForSelling.AutoSize = true; + labelCountForSelling.Location = new Point(45, 126); + labelCountForSelling.Margin = new Padding(4, 0, 4, 0); + labelCountForSelling.Name = "labelCountForSelling"; + labelCountForSelling.Size = new Size(229, 24); + labelCountForSelling.TabIndex = 3; + labelCountForSelling.Text = "Количество для продажи"; + // + // buttonSell + // + buttonSell.Location = new Point(60, 259); + buttonSell.Name = "buttonSell"; + buttonSell.Size = new Size(135, 51); + buttonSell.TabIndex = 4; + buttonSell.Text = "Продать"; + buttonSell.UseVisualStyleBackColor = true; + buttonSell.Click += buttonSell_Click; + // + // buttonCancel + // + buttonCancel.Location = new Point(515, 259); + buttonCancel.Name = "buttonCancel"; + buttonCancel.Size = new Size(160, 51); + buttonCancel.TabIndex = 5; + buttonCancel.Text = "Не продавать "; + buttonCancel.UseVisualStyleBackColor = true; + buttonCancel.Click += buttonCancel_Click; + // + // FormSell + // + AutoScaleDimensions = new SizeF(11F, 24F); + AutoScaleMode = AutoScaleMode.Font; + BackColor = Color.RosyBrown; + ClientSize = new Size(716, 369); + Controls.Add(buttonCancel); + Controls.Add(buttonSell); + Controls.Add(labelCountForSelling); + Controls.Add(numericUpDownCountForSelling); + Controls.Add(labelSushi); + Controls.Add(comboBoxSushis); + Font = new Font("Candara", 12F, FontStyle.Regular, GraphicsUnit.Point, 204); + Margin = new Padding(4); + Name = "FormSell"; + Text = "Продажа суши"; + Load += FormSell_Load; + ((System.ComponentModel.ISupportInitialize)numericUpDownCountForSelling).EndInit(); + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private ComboBox comboBoxSushis; + private Label labelSushi; + private NumericUpDown numericUpDownCountForSelling; + private Label labelCountForSelling; + private Button buttonSell; + private Button buttonCancel; + } +} \ No newline at end of file diff --git a/SushiBar/Shops/FormSell.cs b/SushiBar/Shops/FormSell.cs new file mode 100644 index 0000000..d804386 --- /dev/null +++ b/SushiBar/Shops/FormSell.cs @@ -0,0 +1,89 @@ +using Microsoft.Extensions.Logging; +using SushiBarContracts.BusinessLogicsContracts; +using SushiBarDataModels.Models; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace SushiBarView.Shops +{ + public partial class FormSell : Form + { + private readonly ISushiLogic _sushiLogic; + private readonly IShopLogic _shopLogic; + private readonly ILogger _logger; + public FormSell(ILogger logger, IShopLogic shopLogic, ISushiLogic sushiLogic) + { + _logger = logger; + _shopLogic = shopLogic; + _sushiLogic = sushiLogic; + InitializeComponent(); + } + + private void buttonSell_Click(object sender, EventArgs e) + { + if (numericUpDownCountForSelling.Value == 0) + { + MessageBox.Show("Мы не можем продать ноль изделий", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + if (comboBoxSushis.SelectedValue == null) + { + MessageBox.Show("Выберите изделие", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + _logger.LogInformation("Продажа изделий"); + try + { + var operationResult = _shopLogic.SellSushis(_sushiLogic.ReadElement(new() { Id = Convert.ToInt32(comboBoxSushis.SelectedValue) }), + Convert.ToInt32(numericUpDownCountForSelling.Value) + ); + 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 FormSell_Load(object sender, EventArgs e) + { + _logger.LogInformation("Загрузка изделий для продажи"); + try + { + var list = _sushiLogic.ReadList(null); + if (list != null) + { + comboBoxSushis.DisplayMember = "SushiName"; + comboBoxSushis.ValueMember = "Id"; + comboBoxSushis.DataSource = list; + comboBoxSushis.SelectedItem = null; + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Ошибка загрузки списка изделий"); + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void buttonCancel_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + } + } +} diff --git a/SushiBar/Shops/FormSell.resx b/SushiBar/Shops/FormSell.resx new file mode 100644 index 0000000..af32865 --- /dev/null +++ b/SushiBar/Shops/FormSell.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SushiBar/Shops/FormShop.Designer.cs b/SushiBar/Shops/FormShop.Designer.cs index b5c8502..066cf3b 100644 --- a/SushiBar/Shops/FormShop.Designer.cs +++ b/SushiBar/Shops/FormShop.Designer.cs @@ -34,7 +34,6 @@ labelAddress = new Label(); labelName = new Label(); dateTimePickerDateOpening = new DateTimePicker(); - labelDateOpening = new Label(); groupBoxComponents = new GroupBox(); buttonRefresh = new Button(); buttonDelete = new Button(); @@ -45,8 +44,12 @@ ColumnSushiName = new DataGridViewTextBoxColumn(); ColumnCount = new DataGridViewTextBoxColumn(); textBoxName = new TextBox(); + labelDateOpening = new Label(); + labelMaxCount = new Label(); + numericUpDownMaxCount = new NumericUpDown(); groupBoxComponents.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit(); + ((System.ComponentModel.ISupportInitialize)numericUpDownMaxCount).BeginInit(); SuspendLayout(); // // buttonCancel @@ -110,18 +113,6 @@ dateTimePickerDateOpening.Size = new Size(355, 27); dateTimePickerDateOpening.TabIndex = 12; // - // labelDateOpening - // - labelDateOpening.Anchor = AnchorStyles.None; - labelDateOpening.AutoSize = true; - labelDateOpening.Font = new Font("Candara", 12F); - labelDateOpening.Location = new Point(471, 6); - labelDateOpening.Margin = new Padding(4, 0, 4, 0); - labelDateOpening.Name = "labelDateOpening"; - labelDateOpening.Size = new Size(140, 24); - labelDateOpening.TabIndex = 13; - labelDateOpening.Text = "Дата открытия"; - // // groupBoxComponents // groupBoxComponents.Controls.Add(buttonRefresh); @@ -221,11 +212,42 @@ textBoxName.Size = new Size(330, 27); textBoxName.TabIndex = 19; // + // labelDateOpening + // + labelDateOpening.Anchor = AnchorStyles.None; + labelDateOpening.AutoSize = true; + labelDateOpening.Font = new Font("Candara", 12F); + labelDateOpening.Location = new Point(471, 6); + labelDateOpening.Margin = new Padding(4, 0, 4, 0); + labelDateOpening.Name = "labelDateOpening"; + labelDateOpening.Size = new Size(140, 24); + labelDateOpening.TabIndex = 13; + labelDateOpening.Text = "Дата открытия"; + // + // labelMaxCount + // + labelMaxCount.AutoSize = true; + labelMaxCount.Font = new Font("Candara", 12F, FontStyle.Regular, GraphicsUnit.Point, 204); + labelMaxCount.Location = new Point(471, 120); + labelMaxCount.Name = "labelMaxCount"; + labelMaxCount.Size = new Size(261, 24); + labelMaxCount.TabIndex = 20; + labelMaxCount.Text = "Сколько изделий максимум?"; + // + // numericUpDownMaxCount + // + numericUpDownMaxCount.Location = new Point(471, 154); + numericUpDownMaxCount.Name = "numericUpDownMaxCount"; + numericUpDownMaxCount.Size = new Size(355, 27); + numericUpDownMaxCount.TabIndex = 21; + // // FormShop // AutoScaleDimensions = new SizeF(8F, 20F); AutoScaleMode = AutoScaleMode.Font; ClientSize = new Size(849, 522); + Controls.Add(numericUpDownMaxCount); + Controls.Add(labelMaxCount); Controls.Add(textBoxName); Controls.Add(groupBoxComponents); Controls.Add(labelDateOpening); @@ -240,6 +262,7 @@ Load += FormShop_Load; groupBoxComponents.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)dataGridView).EndInit(); + ((System.ComponentModel.ISupportInitialize)numericUpDownMaxCount).EndInit(); ResumeLayout(false); PerformLayout(); } @@ -252,7 +275,6 @@ private Label labelAddress; private Label labelName; private DateTimePicker dateTimePickerDateOpening; - private Label labelDateOpening; private GroupBox groupBoxComponents; private Button buttonRefresh; private Button buttonDelete; @@ -263,5 +285,8 @@ private DataGridViewTextBoxColumn ColumnId; private DataGridViewTextBoxColumn ColumnSushiName; private DataGridViewTextBoxColumn ColumnCount; + private Label labelDateOpening; + private Label labelMaxCount; + private NumericUpDown numericUpDownMaxCount; } } \ No newline at end of file diff --git a/SushiBar/Shops/FormShop.cs b/SushiBar/Shops/FormShop.cs index 1cb7457..0131f54 100644 --- a/SushiBar/Shops/FormShop.cs +++ b/SushiBar/Shops/FormShop.cs @@ -39,6 +39,7 @@ namespace SushiBarView.Shops textBoxName.Text = view.ShopName; textBoxAddress.Text = view.Address; dateTimePickerDateOpening.Text = view.DateOpening.ToString(); + numericUpDownMaxCount.Value = view.MaxCountSushis; _shopSushis = view.ShopSushis ?? new Dictionary(); LoadData(); } @@ -99,6 +100,7 @@ namespace SushiBarView.Shops ShopName = textBoxName.Text, Address = textBoxAddress.Text, DateOpening = dateTimePickerDateOpening.Value.Date, + MaxCountSushis = Convert.ToInt32(numericUpDownMaxCount.Value), ShopSushis = _shopSushis }; var operationResult = _id.HasValue ? _logic.Update(model) : _logic.Create(model); diff --git a/SushiBarBusinessLogic/OrderLogic.cs b/SushiBarBusinessLogic/OrderLogic.cs index e3e3bbb..0432661 100644 --- a/SushiBarBusinessLogic/OrderLogic.cs +++ b/SushiBarBusinessLogic/OrderLogic.cs @@ -5,6 +5,8 @@ using SushiBarContracts.StoragesContracts; using SushiBarContracts.ViewModels; using Microsoft.Extensions.Logging; using SushiBarDataModels.Enums; +using SushiBarDataModels.Models; +using System.Xml.Linq; namespace SushiBarBusinessLogic.BusinessLogic { @@ -12,11 +14,19 @@ namespace SushiBarBusinessLogic.BusinessLogic { private readonly ILogger _logger; private readonly IOrderStorage _orderStorage; + private readonly IShopStorage _shopStorage; + private readonly IShopLogic _shopLogic; + private readonly ISushiStorage _sushiStorage; - public OrderLogic(ILogger logger, IOrderStorage orderStorage) + + public OrderLogic(ILogger logger, IOrderStorage orderStorage, + IShopLogic shopLogic, IShopStorage shopStorage, ISushiStorage sushiStorage) { _logger = logger; _orderStorage = orderStorage; + _shopStorage = shopStorage; + _shopLogic = shopLogic; + _sushiStorage = sushiStorage; } public List? ReadList(OrderSearchModel? model) @@ -63,7 +73,6 @@ namespace SushiBarBusinessLogic.BusinessLogic private bool ChangeStatus(OrderBindingModel model, OrderStatus orderStatus) { - CheckModel(model, false); var order = _orderStorage.GetElement(new OrderSearchModel { Id = model.Id }); if (order == null) { @@ -76,11 +85,20 @@ namespace SushiBarBusinessLogic.BusinessLogic orderStatus, order.Status); return false; } - - model.SushiId = order.SushiId; - model.Count = order.Count; - model.Sum = order.Sum; - model.DateCreate = order.DateCreate; + if(order.Status == OrderStatus.Готов) + { + var sushi = _sushiStorage.GetElement(new SushiSearchModel { Id = order.SushiId }); + if (sushi == null) + { + _logger.LogWarning("Status change error. Sushi not found"); + return false; + } + if (!CheckSupply(sushi, order.Count)) + { + _logger.LogWarning("Status change error. Shop is overflowed"); + return false; + } + } model.Status = orderStatus; if (model.Status == OrderStatus.Готов) @@ -121,5 +139,73 @@ namespace SushiBarBusinessLogic.BusinessLogic _logger.LogInformation("Sushi. SushiId:{SushiId}. Count:{ Count}. Sum:{ Sum}. Id: { Id}", model.SushiId, model.Count, model.Sum, model.Id); } + + public bool CheckSupply(ISushiModel model, int count) + { + if (count <= 0) + { + _logger.LogWarning("Check supply operation error. Planes count < 0"); + return false; + } + + int sumCapacity = _shopStorage.GetFullList().Select(x => x.MaxCountSushis).Sum(); + int sumCount = _shopStorage.GetFullList().Select(x => x.ShopSushis.Select(y => y.Value.Item2).Sum()).Sum(); + int free = sumCapacity - sumCount; + if (free < count) + { + _logger.LogWarning("Check supply error. No place for new sushis"); + return false; + } + + foreach (var shop in _shopStorage.GetFullList()) + { + free = shop.MaxCountSushis; + foreach (var sushi in shop.ShopSushis) + { + free -= sushi.Value.Item2; + } + + if (free == 0) + { + continue; + } + + if (free >= count) + { + if (_shopLogic.AddSushiInShop(new() + { + Id = shop.Id + }, model, count)) + { + count = 0; + } + else + { + _logger.LogWarning("Supply error"); + return false; + } + } + else + { + if (_shopLogic.AddSushiInShop(new() + { + Id = shop.Id + }, model, free)) + { + count -= free; + } + else + { + _logger.LogWarning("Supply error"); + return false; + } + } + if (count <= 0) + { + return true; + } + } + return false; + } } -} +} \ No newline at end of file diff --git a/SushiBarBusinessLogic/ShopLogic.cs b/SushiBarBusinessLogic/ShopLogic.cs index 81345ae..68672c4 100644 --- a/SushiBarBusinessLogic/ShopLogic.cs +++ b/SushiBarBusinessLogic/ShopLogic.cs @@ -122,7 +122,8 @@ namespace SushiBarBusinessLogic ShopName = element.ShopName, Address = element.Address, DateOpening = element.DateOpening, - ShopSushis = element.ShopSushis + ShopSushis = element.ShopSushis, + MaxCountSushis = element.MaxCountSushis, }); return true; diff --git a/SushiBarContracts/StoragesContracts/IShopStorage.cs b/SushiBarContracts/StoragesContracts/IShopStorage.cs index 17b007e..fb4fd71 100644 --- a/SushiBarContracts/StoragesContracts/IShopStorage.cs +++ b/SushiBarContracts/StoragesContracts/IShopStorage.cs @@ -13,9 +13,7 @@ namespace SushiBarContracts.StoragesContracts ShopViewModel? Insert(ShopBindingModel model); ShopViewModel? Update(ShopBindingModel model); ShopViewModel? Delete(ShopBindingModel model); - bool SellSushis(ISushiModel model, int count); - bool CheckCountSushi(ISushiModel model, int count); } } diff --git a/SushiBarFileImplement/Implements/SushiStorage.cs b/SushiBarFileImplement/Implements/SushiStorage.cs index 2845db6..b731300 100644 --- a/SushiBarFileImplement/Implements/SushiStorage.cs +++ b/SushiBarFileImplement/Implements/SushiStorage.cs @@ -31,7 +31,7 @@ namespace SushiBarFileImplement.Implements public SushiViewModel? GetElement(SushiSearchModel model) { - if (string.IsNullOrEmpty(model.SushiName) && !model.Id.HasValue) + if (!model.Id.HasValue) { return null; } diff --git a/SushiBarListImplements/Implements/ShopStorage.cs b/SushiBarListImplements/Implements/ShopStorage.cs index 17aec5a..851b3f4 100644 --- a/SushiBarListImplements/Implements/ShopStorage.cs +++ b/SushiBarListImplements/Implements/ShopStorage.cs @@ -2,7 +2,7 @@ using SushiBarContracts.SearchModel; using SushiBarContracts.StoragesContracts; using SushiBarContracts.ViewModels; -using SushiBarDataModels; +using SushiBarDataModels.Models; using SushiBarListImplement; using SushiBarListImplements.Models; @@ -108,12 +108,12 @@ namespace SushiBarListImplements.Implements return null; } - public bool SellSushis(IShopModel model, int count) + public bool SellSushis(ISushiModel model, int count) { return true; } - public bool CheckCountSushi(IShopModel model, int count) + public bool CheckCountSushi(ISushiModel model, int count) { return true; }