diff --git a/RenovationWork/RenovationWork/FormMain.Designer.cs b/RenovationWork/RenovationWork/FormMain.Designer.cs index 08bd3d0..9987d1f 100644 --- a/RenovationWork/RenovationWork/FormMain.Designer.cs +++ b/RenovationWork/RenovationWork/FormMain.Designer.cs @@ -40,6 +40,7 @@ buttonOrderReady = new Button(); buttonIssuedOrder = new Button(); buttonRef = new Button(); + SalesToolStripMenuItem = new ToolStripMenuItem(); menuStrip.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit(); SuspendLayout(); @@ -55,7 +56,7 @@ // // refbooksToolStripMenuItem // - refbooksToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { componentsToolStripMenuItem, JobTypeToolStripMenuItem, ShopsToolStripMenuItem, SupplyToolStripMenuItem }); + refbooksToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { componentsToolStripMenuItem, JobTypeToolStripMenuItem, ShopsToolStripMenuItem, SupplyToolStripMenuItem, SalesToolStripMenuItem }); refbooksToolStripMenuItem.Name = "refbooksToolStripMenuItem"; refbooksToolStripMenuItem.Size = new Size(94, 20); refbooksToolStripMenuItem.Text = "Справочники"; @@ -148,6 +149,13 @@ buttonRef.UseVisualStyleBackColor = true; buttonRef.Click += buttonRef_Click; // + // SalesToolStripMenuItem + // + SalesToolStripMenuItem.Name = "SalesToolStripMenuItem"; + SalesToolStripMenuItem.Size = new Size(198, 22); + SalesToolStripMenuItem.Text = "Продажи"; + SalesToolStripMenuItem.Click += SalesToolStripMenuItem_Click; + // // FormMain // AutoScaleDimensions = new SizeF(7F, 15F); @@ -185,5 +193,6 @@ private Button buttonRef; private ToolStripMenuItem ShopsToolStripMenuItem; private ToolStripMenuItem SupplyToolStripMenuItem; + private ToolStripMenuItem SalesToolStripMenuItem; } } \ No newline at end of file diff --git a/RenovationWork/RenovationWork/FormMain.cs b/RenovationWork/RenovationWork/FormMain.cs index 22b2ef0..24293da 100644 --- a/RenovationWork/RenovationWork/FormMain.cs +++ b/RenovationWork/RenovationWork/FormMain.cs @@ -172,6 +172,15 @@ namespace RenovationWorkView form.ShowDialog(); } } + + private void SalesToolStripMenuItem_Click(object sender, EventArgs e) + { + var service = Program.ServiceProvider?.GetService(typeof(FormSell)); + if (service is FormSell form) + { + form.ShowDialog(); + } + } } } diff --git a/RenovationWork/RenovationWork/FormSell.Designer.cs b/RenovationWork/RenovationWork/FormSell.Designer.cs new file mode 100644 index 0000000..4d8eb05 --- /dev/null +++ b/RenovationWork/RenovationWork/FormSell.Designer.cs @@ -0,0 +1,118 @@ +namespace RenovationWorkView +{ + 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() + { + buttonSave = new Button(); + buttonCancel = new Button(); + labelRepair = new Label(); + labelCount = new Label(); + textBoxCount = new TextBox(); + comboBoxRepair = new ComboBox(); + SuspendLayout(); + // + // buttonSave + // + buttonSave.Location = new Point(233, 74); + buttonSave.Name = "buttonSave"; + buttonSave.Size = new Size(75, 23); + buttonSave.TabIndex = 0; + buttonSave.Text = "Сохранить"; + buttonSave.UseVisualStyleBackColor = true; + buttonSave.Click += buttonSave_Click; + // + // buttonCancel + // + buttonCancel.Location = new Point(314, 74); + buttonCancel.Name = "buttonCancel"; + buttonCancel.Size = new Size(75, 23); + buttonCancel.TabIndex = 1; + buttonCancel.Text = "Отмена"; + buttonCancel.UseVisualStyleBackColor = true; + buttonCancel.Click += buttonCancel_Click; + // + // labelRepair + // + labelRepair.AutoSize = true; + labelRepair.Location = new Point(12, 9); + labelRepair.Name = "labelRepair"; + labelRepair.Size = new Size(56, 15); + labelRepair.TabIndex = 2; + labelRepair.Text = "Изделие:"; + // + // labelCount + // + labelCount.AutoSize = true; + labelCount.Location = new Point(12, 46); + labelCount.Name = "labelCount"; + labelCount.Size = new Size(75, 15); + labelCount.TabIndex = 3; + labelCount.Text = "Количество:"; + // + // textBoxCount + // + textBoxCount.Location = new Point(100, 38); + textBoxCount.Name = "textBoxCount"; + textBoxCount.Size = new Size(107, 23); + textBoxCount.TabIndex = 4; + // + // comboBoxRepair + // + comboBoxRepair.FormattingEnabled = true; + comboBoxRepair.Location = new Point(100, 6); + comboBoxRepair.Name = "comboBoxRepair"; + comboBoxRepair.Size = new Size(289, 23); + comboBoxRepair.TabIndex = 5; + // + // FormSell + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(401, 109); + Controls.Add(comboBoxRepair); + Controls.Add(textBoxCount); + Controls.Add(labelCount); + Controls.Add(labelRepair); + Controls.Add(buttonCancel); + Controls.Add(buttonSave); + Name = "FormSell"; + Text = "Продажи"; + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private Button buttonSave; + private Button buttonCancel; + private Label labelRepair; + private Label labelCount; + private TextBox textBoxCount; + private ComboBox comboBoxRepair; + } +} \ No newline at end of file diff --git a/RenovationWork/RenovationWork/FormSell.cs b/RenovationWork/RenovationWork/FormSell.cs new file mode 100644 index 0000000..df6d478 --- /dev/null +++ b/RenovationWork/RenovationWork/FormSell.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using RenovationWorkContracts.ViewModels; +using RenovationWorkDataModels.Models; +using Microsoft.Extensions.Logging; +using RenovationWorkContracts.BusinessLogicsContracts; +using RenovationWorkBusinessLogic.BusinessLogics; + +namespace RenovationWorkView +{ + public partial class FormSell : Form + { + private readonly List? _repairList; + IShopLogic _shopLogic; + IRepairLogic _repairLogic; + public FormSell(IRepairLogic repairLogic, IShopLogic shopLogic) + { + InitializeComponent(); + _shopLogic = shopLogic; + _repairLogic = repairLogic; + _repairList = repairLogic.ReadList(null); + if (_repairList != null) + { + comboBoxRepair.DisplayMember = "RepairName"; + comboBoxRepair.ValueMember = "Id"; + comboBoxRepair.DataSource = _repairList; + comboBoxRepair.SelectedItem = null; + } + } + public int RepairId + { + get + { + return Convert.ToInt32(comboBoxRepair.SelectedValue); + } + set + { + comboBoxRepair.SelectedValue = value; + } + } + public IRepairModel? RepairModel + { + get + { + if (_repairList == null) + { + return null; + } + foreach (var elem in _repairList) + { + if (elem.Id == RepairId) + { + return elem; + } + } + return null; + } + } + public int Count + { + get { return Convert.ToInt32(textBoxCount.Text); } + set + { textBoxCount.Text = value.ToString(); } + } + + private void buttonSave_Click(object sender, EventArgs e) + { + if (string.IsNullOrEmpty(textBoxCount.Text)) + { + MessageBox.Show("Заполните поле Количество", "Ошибка", + MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + if (comboBoxRepair.SelectedValue == null) + { + MessageBox.Show("Выберите изделие", "Ошибка", + MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + try + { + int count = Convert.ToInt32(textBoxCount.Text); + var manufacture = _repairLogic.ReadElement(new() { Id = Convert.ToInt32(comboBoxRepair.SelectedValue) }); + if (manufacture == null) + { + throw new ApplicationException("Ошибка при продаже. Ошибка получения данных об элементе."); + } + if (!_shopLogic.SellRepairs(manufacture, count)) + { + throw new ApplicationException("Ошибка при продаже. Недостаточно изделий данного типа в магазинах."); + } + MessageBox.Show("Продажа прошла успешно"); + DialogResult = DialogResult.OK; + Close(); + } + catch (Exception) + { + MessageBox.Show("Ошибка при продаже."); + return; + } + } + + private void buttonCancel_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + } + } +} diff --git a/RenovationWork/RenovationWork/FormSell.resx b/RenovationWork/RenovationWork/FormSell.resx new file mode 100644 index 0000000..af32865 --- /dev/null +++ b/RenovationWork/RenovationWork/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/RenovationWork/RenovationWork/FormShop.Designer.cs b/RenovationWork/RenovationWork/FormShop.Designer.cs index e41cc84..616aaf3 100644 --- a/RenovationWork/RenovationWork/FormShop.Designer.cs +++ b/RenovationWork/RenovationWork/FormShop.Designer.cs @@ -41,7 +41,10 @@ ColumnCount = new DataGridViewTextBoxColumn(); buttonSave = new Button(); buttonCancel = new Button(); + labelCapancy = new Label(); + CapacityUpDown = new NumericUpDown(); ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit(); + ((System.ComponentModel.ISupportInitialize)CapacityUpDown).BeginInit(); SuspendLayout(); // // labelName @@ -96,10 +99,10 @@ // dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; dataGridView.Columns.AddRange(new DataGridViewColumn[] { ColumnId, ColumnName, ColumnPrice, ColumnCount }); - dataGridView.Location = new Point(12, 108); + dataGridView.Location = new Point(12, 126); dataGridView.Name = "dataGridView"; dataGridView.RowTemplate.Height = 25; - dataGridView.Size = new Size(770, 250); + dataGridView.Size = new Size(770, 232); dataGridView.TabIndex = 6; // // ColumnId @@ -149,11 +152,29 @@ buttonCancel.UseVisualStyleBackColor = true; buttonCancel.Click += buttonCancel_Click; // + // labelCapancy + // + labelCapancy.AutoSize = true; + labelCapancy.Location = new Point(12, 99); + labelCapancy.Name = "labelCapancy"; + labelCapancy.Size = new Size(83, 15); + labelCapancy.TabIndex = 9; + labelCapancy.Text = "Вместимость:"; + // + // CapacityUpDown + // + CapacityUpDown.Location = new Point(106, 97); + CapacityUpDown.Name = "CapacityUpDown"; + CapacityUpDown.Size = new Size(229, 23); + CapacityUpDown.TabIndex = 10; + // // FormShop // AutoScaleDimensions = new SizeF(7F, 15F); AutoScaleMode = AutoScaleMode.Font; ClientSize = new Size(790, 411); + Controls.Add(CapacityUpDown); + Controls.Add(labelCapancy); Controls.Add(buttonCancel); Controls.Add(buttonSave); Controls.Add(dataGridView); @@ -167,6 +188,7 @@ Text = "Магазин"; Load += FormShop_Load; ((System.ComponentModel.ISupportInitialize)dataGridView).EndInit(); + ((System.ComponentModel.ISupportInitialize)CapacityUpDown).EndInit(); ResumeLayout(false); PerformLayout(); } @@ -186,5 +208,7 @@ private DataGridViewTextBoxColumn ColumnCount; private Button buttonSave; private Button buttonCancel; + private Label labelCapancy; + private NumericUpDown CapacityUpDown; } } \ No newline at end of file diff --git a/RenovationWork/RenovationWork/FormShop.cs b/RenovationWork/RenovationWork/FormShop.cs index de327df..53c2cfd 100644 --- a/RenovationWork/RenovationWork/FormShop.cs +++ b/RenovationWork/RenovationWork/FormShop.cs @@ -45,7 +45,8 @@ namespace RenovationWorkView textBoxName.Text = shop.ShopName; textBoxAddress.Text = shop.Address; dateTimePicker.Text = shop.OpeningDate.ToString(); - _repairs = shop.ShopRepairs; + _repairs = shop.ShopRepairs ?? new Dictionary(); + CapacityUpDown.Value = shop.MaxCapacity; } LoadData(); } @@ -101,7 +102,7 @@ namespace RenovationWorkView ShopName = textBoxName.Text, Address = textBoxAddress.Text, OpeningDate = dateTimePicker.Value.Date, - ShopRepairs = _repairs + MaxCapacity = Convert.ToInt32(CapacityUpDown.Value) }; var operationResult = _id.HasValue ? _logic.Update(model) : _logic.Create(model); if (!operationResult) diff --git a/RenovationWork/RenovationWork/FormSupply.cs b/RenovationWork/RenovationWork/FormSupply.cs index 723394b..2473bb3 100644 --- a/RenovationWork/RenovationWork/FormSupply.cs +++ b/RenovationWork/RenovationWork/FormSupply.cs @@ -100,7 +100,7 @@ namespace RenovationWorkView } if (comboBoxRepair.SelectedValue == null) { - MessageBox.Show("Выберите кузнечное изделие", "Ошибка", + MessageBox.Show("Выберите ремонтное изделие", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } diff --git a/RenovationWork/RenovationWork/Program.cs b/RenovationWork/RenovationWork/Program.cs index d6149c9..2d0079c 100644 --- a/RenovationWork/RenovationWork/Program.cs +++ b/RenovationWork/RenovationWork/Program.cs @@ -52,6 +52,7 @@ namespace RenovationWorkView services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); } } } \ No newline at end of file diff --git a/RenovationWork/RenovationWorkBusinessLogic/BusinessLogics/OrderLogic.cs b/RenovationWork/RenovationWorkBusinessLogic/BusinessLogics/OrderLogic.cs index b34651d..b09d8a2 100644 --- a/RenovationWork/RenovationWorkBusinessLogic/BusinessLogics/OrderLogic.cs +++ b/RenovationWork/RenovationWorkBusinessLogic/BusinessLogics/OrderLogic.cs @@ -9,6 +9,7 @@ using RenovationWorkContracts.SearchModels; using RenovationWorkContracts.StoragesContracts; using RenovationWorkContracts.ViewModels; using RenovationWorkDataModels.Enums; +using RenovationWorkDataModels.Models; using Microsoft.Extensions.Logging; namespace RenovationWorkBusinessLogic.BusinessLogics @@ -17,10 +18,17 @@ namespace RenovationWorkBusinessLogic.BusinessLogics { private readonly ILogger _logger; private readonly IOrderStorage _orderStorage; - public OrderLogic(ILogger logger, IOrderStorage orderStorage) + private readonly IShopLogic _shopLogic; + private readonly IRepairStorage _repairStorage; + private readonly IShopStorage _shopStorage; + public OrderLogic(ILogger logger, IOrderStorage orderStorage, + IRepairStorage repairStorage, IShopLogic shopLogic, IShopStorage shopStorage) { _logger = logger; _orderStorage = orderStorage; + _repairStorage = repairStorage; + _shopLogic = shopLogic; + _shopStorage = shopStorage; } public bool CreateOrder(OrderBindingModel model) { @@ -39,31 +47,38 @@ namespace RenovationWorkBusinessLogic.BusinessLogics } return true; } - public bool StatusUpdate(OrderBindingModel model, OrderStatus newStatus) + private bool StatusUpdate(OrderBindingModel model, OrderStatus status) { - var viewModel = _orderStorage.GetElement(new OrderSearchModel { Id = model.Id }); - if (viewModel == null) + CheckModel(model); + var element = _orderStorage.GetElement(new OrderSearchModel { Id = model.Id }); + if (element == null) { - throw new ArgumentNullException(nameof(model)); - } - if (viewModel.Status + 1 != newStatus) - { - _logger.LogWarning("Update operation failed. Order status incorrect."); + _logger.LogWarning("Read operation failed"); return false; } - model.Status = newStatus; - if (model.Status == OrderStatus.Готов) model.DateImplement = DateTime.Now; - else + if (element.Status != status - 1) { - model.DateImplement = viewModel.DateImplement; + _logger.LogWarning("Status change operation failed"); + throw new InvalidOperationException("Текущий статус заказа не может быть переведен в выбранный"); } - CheckModel(model, false); - if (_orderStorage.Update(model) == null) + if (element.Status == OrderStatus.Готов) { - model.Status--; - _logger.LogWarning("Update operation failed"); - return false; + var manufacture = _repairStorage.GetElement(new RepairSearchModel() { Id = model.RepairId }); + if (manufacture == null) + { + _logger.LogWarning("Status update to " + status.ToString() + " operation failed. Document not found."); + return false; + } + if (CheckSupply(manufacture, model.Count) == false) + { + _logger.LogWarning("Status update to " + status.ToString() + " operation failed. Shop supply error."); + return false; + } } + model.Status = status; + if (model.Status == OrderStatus.Выдан) + model.DateImplement = DateTime.Now; + _orderStorage.Update(model); return true; } public bool DeliveryOrder(OrderBindingModel model) @@ -115,5 +130,60 @@ namespace RenovationWorkBusinessLogic.BusinessLogics } _logger.LogInformation("Order. Count: {Count}. Sum: {Sum}. Id: {Id}", model.Count, model.Sum, model.Id); } + private bool CheckSupply(IRepairModel repair, int count) + { + if (count <= 0) + { + _logger.LogWarning("Check then supply operation error. Repair count < 0."); + return false; + } + int sumCapacity = 0; + int sumCount = 0; + sumCapacity = _shopStorage.GetFullList().Select(x => x.MaxCapacity).Sum(); + sumCount = _shopStorage.GetFullList().Select(x => x.ShopRepairs.Select(y => y.Value.Item2).Sum()).Sum(); + int freeSpace = sumCapacity - sumCount; + if (freeSpace - count < 0) + { + _logger.LogWarning("Check then supply operation error. There's no place for new Repair in shops."); + return false; + } + foreach (var shop in _shopStorage.GetFullList()) + { + freeSpace = shop.MaxCapacity; + foreach (var doc in shop.ShopRepairs) + { + freeSpace -= doc.Value.Item2; + } + if (freeSpace == 0) + { + continue; + } + if (freeSpace - count >= 0) + { + if (_shopLogic.ReplenishRepairs(new() { Id = shop.Id }, repair, count)) + count = 0; + else + { + _logger.LogWarning("Supply error"); + return false; + } + } + if (freeSpace - count < 0) + { + if (_shopLogic.ReplenishRepairs(new() { Id = shop.Id }, repair, freeSpace)) + count -= freeSpace; + else + { + _logger.LogWarning("Supply error"); + return false; + } + } + if (count <= 0) + { + return true; + } + } + return false; + } } } \ No newline at end of file diff --git a/RenovationWork/RenovationWorkBusinessLogic/BusinessLogics/ShopLogic.cs b/RenovationWork/RenovationWorkBusinessLogic/BusinessLogics/ShopLogic.cs index 7e3960a..53ffe56 100644 --- a/RenovationWork/RenovationWorkBusinessLogic/BusinessLogics/ShopLogic.cs +++ b/RenovationWork/RenovationWorkBusinessLogic/BusinessLogics/ShopLogic.cs @@ -84,44 +84,61 @@ namespace RenovationWorkBusinessLogic.BusinessLogics } public bool ReplenishRepairs(ShopSearchModel model, IRepairModel repair, int count) { - _logger.LogInformation("Try to replenish repairs. ShopName:{ShopName}. Id:{Id}", model.ShopName, model.Id); - if (model == null) - throw new ArgumentNullException(nameof(model)); - ShopViewModel? curModel = ReadElement(model); - if (curModel == null) { - _logger.LogWarning("Read operation failed"); - return false; + _logger.LogInformation("Try to replenish repairs. ShopName:{ShopName}. Id:{Id}", model.ShopName, model.Id); + if (model == null) + { + _logger.LogWarning("Read operation failed"); + throw new ArgumentNullException(nameof(model)); + } + ShopViewModel? curModel = ReadElement(model); + if (curModel == null) + { + _logger.LogWarning("Read operation failed"); + throw new ArgumentNullException(nameof(curModel)); + } + if (repair == null) + { + _logger.LogWarning("Read operation failed"); + throw new ArgumentNullException(nameof(repair)); + } + if (count <= 0) + { + _logger.LogWarning("Read operation failed"); + throw new ArgumentException("Количество должно быть положительным"); + } + int countItems = curModel.ShopRepairs.Select(x => x.Value.Item2).Sum(); + if (curModel.MaxCapacity - countItems >= count) + { + if (curModel.ShopRepairs.TryGetValue(repair.Id, out var sameDocument)) + { + curModel.ShopRepairs[repair.Id] = (repair, sameDocument.Item2 + count); + _logger.LogInformation("Same repair found by supply. Added {0} of {1} in {2} shop", count, repair.RepairName, curModel.ShopName); + } + else + { + curModel.ShopRepairs[repair.Id] = (repair, count); + _logger.LogInformation("New repair added by supply. Added {0} of {1} in {2} shop", count, repair.RepairName, curModel.ShopName); + } + _shopStorage.Update(new() + { + Id = curModel.Id, + ShopName = curModel.ShopName, + Address = curModel.Address, + OpeningDate = curModel.OpeningDate, + ShopRepairs = curModel.ShopRepairs, + MaxCapacity = curModel.MaxCapacity + }); + } + else + { + _logger.LogWarning("Required shop is overflowed"); + return false; + } + return true; } - if (repair == null) - throw new ArgumentNullException(nameof(repair)); - if (count <= 0) - throw new ArgumentException("Количество должно быть положительным числом"); - - //попытка найти информацию о товаре в магазине по его идентификатору в словаре - //найден и добавляется - if (curModel.ShopRepairs.TryGetValue(repair.Id, out var pair)) - { - curModel.ShopRepairs[repair.Id] = (pair.Item1, pair.Item2 + count); - } - //не найден и добавляется - else - { - curModel.ShopRepairs.Add(repair.Id, (repair, count)); - } - Update(new() - { - Id = curModel.Id, - ShopName = curModel.ShopName, - OpeningDate = curModel.OpeningDate, - Address = curModel.Address, - ShopRepairs = curModel.ShopRepairs, - }); - _logger.LogInformation("Success. RepairName:{RepairName}. Id:{Id}. Replenish:{count}", - repair.RepairName, repair.Id, count); - return true; } - private void CheckModel(ShopBindingModel model, bool withParams = true) + private void CheckModel(ShopBindingModel model, bool withParams = true) { if (model == null) { @@ -150,6 +167,10 @@ namespace RenovationWorkBusinessLogic.BusinessLogics throw new InvalidOperationException("Магазин с таким названием уже есть"); } } + public bool SellRepairs(IRepairModel repair, int count) + { + return _shopStorage.SellRepairs(repair, count); + } } } diff --git a/RenovationWork/RenovationWorkContracts/BindingModels/ShopBindingModel.cs b/RenovationWork/RenovationWorkContracts/BindingModels/ShopBindingModel.cs index 9c22402..0965645 100644 --- a/RenovationWork/RenovationWorkContracts/BindingModels/ShopBindingModel.cs +++ b/RenovationWork/RenovationWorkContracts/BindingModels/ShopBindingModel.cs @@ -13,6 +13,7 @@ namespace RenovationWorkContracts.BindingModels public string ShopName { get; set; } = string.Empty; public string Address { get; set; } = string.Empty; public DateTime OpeningDate { get; set; } + public int MaxCapacity { get; set; } public Dictionary ShopRepairs { get; set; } = new(); } } diff --git a/RenovationWork/RenovationWorkContracts/BusinessLogicsContracts/IShopLogic.cs b/RenovationWork/RenovationWorkContracts/BusinessLogicsContracts/IShopLogic.cs index 391f396..110d4f6 100644 --- a/RenovationWork/RenovationWorkContracts/BusinessLogicsContracts/IShopLogic.cs +++ b/RenovationWork/RenovationWorkContracts/BusinessLogicsContracts/IShopLogic.cs @@ -18,5 +18,6 @@ namespace RenovationWorkContracts.BusinessLogicsContracts bool Update(ShopBindingModel model); bool Delete(ShopBindingModel model); bool ReplenishRepairs(ShopSearchModel shop, IRepairModel repair, int count); + bool SellRepairs(IRepairModel repair, int count); } } diff --git a/RenovationWork/RenovationWorkContracts/StoragesContracts/IShopStorage.cs b/RenovationWork/RenovationWorkContracts/StoragesContracts/IShopStorage.cs index ed014d5..71441ba 100644 --- a/RenovationWork/RenovationWorkContracts/StoragesContracts/IShopStorage.cs +++ b/RenovationWork/RenovationWorkContracts/StoragesContracts/IShopStorage.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using RenovationWorkContracts.BindingModels; using RenovationWorkContracts.SearchModels; using RenovationWorkContracts.ViewModels; +using RenovationWorkDataModels.Models; namespace RenovationWorkContracts.StoragesContracts { @@ -17,5 +18,6 @@ namespace RenovationWorkContracts.StoragesContracts ShopViewModel? Insert(ShopBindingModel model); ShopViewModel? Update(ShopBindingModel model); ShopViewModel? Delete(ShopBindingModel model); + public bool SellRepairs(IRepairModel model, int count); } } \ No newline at end of file diff --git a/RenovationWork/RenovationWorkContracts/ViewModels/ShopViewModel.cs b/RenovationWork/RenovationWorkContracts/ViewModels/ShopViewModel.cs index 8785459..8e78456 100644 --- a/RenovationWork/RenovationWorkContracts/ViewModels/ShopViewModel.cs +++ b/RenovationWork/RenovationWorkContracts/ViewModels/ShopViewModel.cs @@ -17,6 +17,8 @@ namespace RenovationWorkContracts.ViewModels public string Address { get; set; } = string.Empty; [DisplayName("Дата открытия")] public DateTime OpeningDate { get; set; } + [DisplayName("Вместимость")] + public int MaxCapacity { get; set; } public Dictionary ShopRepairs { get; set; } = new(); } } diff --git a/RenovationWork/RenovationWorkDataModels/Models/IShopModel.cs b/RenovationWork/RenovationWorkDataModels/Models/IShopModel.cs index 5b61a19..bd597ad 100644 --- a/RenovationWork/RenovationWorkDataModels/Models/IShopModel.cs +++ b/RenovationWork/RenovationWorkDataModels/Models/IShopModel.cs @@ -11,6 +11,7 @@ namespace RenovationWorkDataModels.Models string ShopName { get; } string Address { get; } DateTime OpeningDate { get; } + int MaxCapacity { get; } Dictionary ShopRepairs { get; } } } diff --git a/RenovationWork/RenovationWorkFileImplement/DataFileSingleton.cs b/RenovationWork/RenovationWorkFileImplement/DataFileSingleton.cs index 687b0be..4dff837 100644 --- a/RenovationWork/RenovationWorkFileImplement/DataFileSingleton.cs +++ b/RenovationWork/RenovationWorkFileImplement/DataFileSingleton.cs @@ -15,6 +15,8 @@ namespace RenovationWorkFileImplement private readonly string ComponentFileName = "Component.xml"; private readonly string OrderFileName = "Order.xml"; private readonly string RepairFileName = "Repair.xml"; + private readonly string ShopFileName = "Shops.xml"; + public List Shops { get; private set; } public List Components { get; private set; } public List Orders { get; private set; } public List Repairs { get; private set; } @@ -27,10 +29,10 @@ namespace RenovationWorkFileImplement } return instance; } - public void SaveComponents() => SaveData(Components, ComponentFileName, "Components", x => x.GetXElement); public void SaveRepairs() => SaveData(Repairs, RepairFileName, "Repairs", x => x.GetXElement); public void SaveOrders() => SaveData(Orders, OrderFileName, "Orders", x => x.GetXElement); + public void SaveShops() => SaveData(Shops, ShopFileName,"Shops", x => x.GetXElement); private DataFileSingleton() { Components = LoadData(ComponentFileName, "Component", x => @@ -39,6 +41,8 @@ namespace RenovationWorkFileImplement Repair.Create(x)!)!; Orders = LoadData(OrderFileName, "Order", x => Order.Create(x)!)!; + Shops = LoadData(ShopFileName, "Shop", x => + Shop.Create(x)!)!; } private static List? LoadData(string filename, string xmlNodeName, Func selectFunction) { diff --git a/RenovationWork/RenovationWorkFileImplement/Implements/ShopStorage.cs b/RenovationWork/RenovationWorkFileImplement/Implements/ShopStorage.cs new file mode 100644 index 0000000..5df01af --- /dev/null +++ b/RenovationWork/RenovationWorkFileImplement/Implements/ShopStorage.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using RenovationWorkFileImplement; +using RenovationWorkContracts.BindingModels; +using RenovationWorkContracts.SearchModels; +using RenovationWorkContracts.StoragesContracts; +using RenovationWorkContracts.ViewModels; +using RenovationWorkDataModels.Models; +using RenovationWorkFileImplement.Models; + +namespace RenovationWorkFileImplement.Implements +{ + public class ShopStorage : IShopStorage + { + private readonly DataFileSingleton _source; + public ShopStorage() + { + _source = DataFileSingleton.GetInstance(); + } + public List GetFullList() + { + return _source.Shops + .Select(x => x.GetViewModel) + .ToList(); + } + public List GetFilteredList(ShopSearchModel + model) + { + if (string.IsNullOrEmpty(model.ShopName)) + { + return new(); + } + return _source.Shops + .Where(x => x.ShopName.Contains(model.ShopName)) + .Select(x => x.GetViewModel) + .ToList(); ; + } + public ShopViewModel? GetElement(ShopSearchModel model) + { + if (string.IsNullOrEmpty(model.ShopName) && !model.Id.HasValue) + { + return null; + } + return _source.Shops + .FirstOrDefault(x => (!string.IsNullOrEmpty(model.ShopName) && x.ShopName == + model.ShopName) || (model.Id.HasValue && x.Id == model.Id))?.GetViewModel; + } + public ShopViewModel? Insert(ShopBindingModel model) + { + model.Id = _source.Shops.Count > 0 ? _source.Shops.Max(x => + x.Id) + 1 : 1; + var newShop = Shop.Create(model); + if (newShop == null) + { + return null; + } + _source.Shops.Add(newShop); + _source.SaveShops(); + return newShop.GetViewModel; + } + public ShopViewModel? Update(ShopBindingModel model) + { + var component = _source.Shops.FirstOrDefault(x => x.Id == + model.Id); + if (component == null) + { + return null; + } + component.Update(model); + _source.SaveShops(); + return component.GetViewModel; + } + public ShopViewModel? Delete(ShopBindingModel model) + { + var element = _source.Shops.FirstOrDefault(x => x.Id == + model.Id); + if (element != null) + { + _source.Shops.Remove(element); + _source.SaveShops(); + return element.GetViewModel; + } + return null; + } + private bool CheckSell(int RepairId, int count) + { + count -= _source.Shops.Select(x => x.ShopRepairs.Select(y => + (y.Value.Item1.Id == RepairId ? y.Value.Item2 : 0)).Sum()).Sum(); + return count <= 0; + } + public bool SellRepairs(IRepairModel model, int count) + { + var neededRepair = _source.Repairs.FirstOrDefault(x => x.Id == model.Id); + if (neededRepair == null || !CheckSell(neededRepair.Id, count)) + { + return false; + } + for (int i = 0; i < _source.Shops.Count; i++) + { + var shop = _source.Shops[i]; + var assortment = shop.ShopRepairs; + foreach (var repair in assortment.Where(x => x.Value.Item1.Id == neededRepair.Id)) + { + var min = Math.Min(repair.Value.Item2, count); + assortment[repair.Value.Item1.Id] = (repair.Value.Item1, repair.Value.Item2 - min); + count -= min; + if (count <= 0) + { + break; + } + } + shop.Update(new ShopBindingModel + { + Id = shop.Id, + ShopName = shop.ShopName, + Address = shop.Address, + OpeningDate = shop.OpeningDate, + MaxCapacity = shop.MaxCapacity, + ShopRepairs = assortment + }); + } + _source.SaveShops(); + return true; + } + } +} diff --git a/RenovationWork/RenovationWorkFileImplement/Models/Shop.cs b/RenovationWork/RenovationWorkFileImplement/Models/Shop.cs new file mode 100644 index 0000000..adbbbe0 --- /dev/null +++ b/RenovationWork/RenovationWorkFileImplement/Models/Shop.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using RenovationWorkFileImplement; +using RenovationWorkContracts.BindingModels; +using RenovationWorkContracts.ViewModels; +using RenovationWorkDataModels.Models; +using System.Xml.Linq; + +namespace RenovationWorkFileImplement.Models +{ + public class Shop : IShopModel + { + public int Id { get; private set; } + public string ShopName { get; private set; } = string.Empty; + public string Address { get; private set; } = string.Empty; + public DateTime OpeningDate { get; private set; } + public int MaxCapacity { get; private set; } + public Dictionary Repairs { get; private set; } = new(); + private Dictionary? _shopRepairs = null; + public Dictionary ShopRepairs + { + get + { + if (_shopRepairs == null) + { + var source = DataFileSingleton.GetInstance(); + _shopRepairs = Repairs.ToDictionary(x => x.Key, y => + ((source.Repairs.FirstOrDefault(z => z.Id == y.Key) as IRepairModel)!, + y.Value)); + } + return _shopRepairs; + } + } + public static Shop? Create(ShopBindingModel model) + { + if (model == null) + return null; + return new Shop() + { + Id = model.Id, + ShopName = model.ShopName, + Address = model.Address, + OpeningDate = model.OpeningDate, + MaxCapacity = model.MaxCapacity, + Repairs = model.ShopRepairs.ToDictionary(x => x.Key, x => x.Value.Item2) + }; + } + public static Shop? Create(XElement element) + { + if (element == null) + { + return null; + } + return new Shop() + { + Id = Convert.ToInt32(element.Attribute("Id")!.Value), + ShopName = element.Element("ShopName")!.Value, + Address = element.Element("Address")!.Value, + MaxCapacity = Convert.ToInt32(element.Element("MaxCapacity")!.Value), + OpeningDate = Convert.ToDateTime(element.Element("DateOpen")!.Value), + Repairs = element.Element("ShopRepairs")!.Elements("ShopRepair") + .ToDictionary(x => + Convert.ToInt32(x.Element("Key")?.Value), x => + Convert.ToInt32(x.Element("Value")?.Value)) + }; + } + public void Update(ShopBindingModel model) + { + if (model == null) + { + return; + } + ShopName = model.ShopName; + Address = model.Address; + OpeningDate = model.OpeningDate; + MaxCapacity = model.MaxCapacity; + if (model.ShopRepairs.Count > 0) + { + Repairs = model.ShopRepairs.ToDictionary(x => x.Key, x => x.Value.Item2); + _shopRepairs = null; + } + } + public ShopViewModel GetViewModel => new() + { + Id = Id, + ShopName = ShopName, + Address = Address, + OpeningDate = OpeningDate, + MaxCapacity = MaxCapacity, + ShopRepairs = ShopRepairs + }; + public XElement GetXElement => new("Shop", + new XAttribute("Id", Id), + new XElement("ShopName", ShopName), + new XElement("Address", Address), + new XElement("DateOpen", OpeningDate), + new XElement("MaxCapacity", MaxCapacity), + new XElement("ShopRepairs", Repairs + .Select(x => new XElement("ShopRepair", + new XElement("Key", x.Key), + new XElement("Value", x.Value)) + ).ToArray())); + } +} diff --git a/RenovationWork/RenovationWorkListImplement/Implements/ShopStorage.cs b/RenovationWork/RenovationWorkListImplement/Implements/ShopStorage.cs index 67bfde4..ffc1e95 100644 --- a/RenovationWork/RenovationWorkListImplement/Implements/ShopStorage.cs +++ b/RenovationWork/RenovationWorkListImplement/Implements/ShopStorage.cs @@ -7,6 +7,7 @@ using RenovationWorkContracts.BindingModels; using RenovationWorkContracts.SearchModels; using RenovationWorkContracts.StoragesContracts; using RenovationWorkContracts.ViewModels; +using RenovationWorkDataModels.Models; using RenovationWorkListImplement.Models; namespace RenovationWorkListImplement.Implements @@ -103,5 +104,9 @@ namespace RenovationWorkListImplement.Implements } return null; } + public bool SellRepairs(IRepairModel model, int count) + { + throw new NotImplementedException(); + } } } diff --git a/RenovationWork/RenovationWorkListImplement/Models/Shop.cs b/RenovationWork/RenovationWorkListImplement/Models/Shop.cs index 6839e2b..577942f 100644 --- a/RenovationWork/RenovationWorkListImplement/Models/Shop.cs +++ b/RenovationWork/RenovationWorkListImplement/Models/Shop.cs @@ -50,5 +50,6 @@ namespace RenovationWorkListImplement.Models OpeningDate = OpeningDate, ShopRepairs = ShopRepairs }; + public int MaxCapacity => throw new NotImplementedException(); } }