From 1bf503cc9231c7eb79f3720ffbce2976eafd4f2f Mon Sep 17 00:00:00 2001 From: maxnes3 <112558334+maxnes3@users.noreply.github.com> Date: Sun, 23 Apr 2023 22:59:36 +0400 Subject: [PATCH] =?UTF-8?q?=D0=BD=D0=B0=D1=87=D0=B0=D0=BB=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BusinessLogics/OrderLogic.cs | 25 +++- .../BusinessLogics/ShopLogic.cs | 73 +++++++++- .../BindingModels/ShopBindingModel.cs | 3 +- .../{IStoreLogic.cs => IShopLogic.cs} | 4 +- .../StoragesContracts/IShopStorage.cs | 4 +- .../ViewModels/ShopViewModel.cs | 4 +- .../Models/IShopModel.cs | 4 +- .../DataFileSingleton.cs | 12 +- .../Implements/ShopStorage.cs | 125 ++++++++++++++++++ .../ComputersShopFileImplement/Models/Shop.cs | 108 +++++++++++++++ .../Implements/ShopStorage.cs | 8 +- .../ComputersShopListImplement/Models/Shop.cs | 4 +- 12 files changed, 353 insertions(+), 21 deletions(-) rename ComputersShop/ComputersShopContracts/BusinessLogicContracts/{IStoreLogic.cs => IShopLogic.cs} (83%) create mode 100644 ComputersShop/ComputersShopFileImplement/Implements/ShopStorage.cs create mode 100644 ComputersShop/ComputersShopFileImplement/Models/Shop.cs diff --git a/ComputersShop/ComputersShopBusinessLogic/BusinessLogics/OrderLogic.cs b/ComputersShop/ComputersShopBusinessLogic/BusinessLogics/OrderLogic.cs index 17fc279..ff9403e 100644 --- a/ComputersShop/ComputersShopBusinessLogic/BusinessLogics/OrderLogic.cs +++ b/ComputersShop/ComputersShopBusinessLogic/BusinessLogics/OrderLogic.cs @@ -17,10 +17,14 @@ namespace ComputersShopBusinessLogic.BusinessLogics { private readonly ILogger _logger; private readonly IOrderStorage _orderStorage; - public OrderLogic(ILogger logger, IOrderStorage orderStorage) + private readonly IShopLogic _shopLogic; + private readonly IComputerStorage _computerStorage; + public OrderLogic(ILogger logger, IOrderStorage orderStorage, IShopLogic shopLogic, IComputerStorage computerStorage) { _logger = logger; _orderStorage = orderStorage; + _shopLogic = shopLogic; + _computerStorage = computerStorage; } public bool CreateOrder(OrderBindingModel model) { @@ -52,16 +56,29 @@ namespace ComputersShopBusinessLogic.BusinessLogics return false; } model.Status = newStatus; - if (model.Status == OrderStatus.Готов) model.DateImplement = DateTime.Now; + if (model.Status == OrderStatus.Готов) + { + + model.DateImplement = DateTime.Now; + var computer = _computerStorage.GetElement(new() { Id = viewModel.ComputerId }); + if (computer == null) + { + throw new ArgumentNullException(nameof(computer)); + } + if (!_shopLogic.AddComputers(computer, viewModel.Count)) + { + throw new Exception($"AddComputers operation failed - нет места"); + } + } else { model.DateImplement = viewModel.DateImplement; } - CheckModel(model); + CheckModel(model, false); if (_orderStorage.Update(model) == null) { model.Status--; - _logger.LogWarning("Update operation failed"); + _logger.LogWarning("Change status operation failed"); return false; } return true; diff --git a/ComputersShop/ComputersShopBusinessLogic/BusinessLogics/ShopLogic.cs b/ComputersShop/ComputersShopBusinessLogic/BusinessLogics/ShopLogic.cs index eb93147..b33660f 100644 --- a/ComputersShop/ComputersShopBusinessLogic/BusinessLogics/ShopLogic.cs +++ b/ComputersShop/ComputersShopBusinessLogic/BusinessLogics/ShopLogic.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Text; using System.Threading.Tasks; @@ -43,9 +44,12 @@ namespace ComputersShopBusinessLogic.BusinessLogics return false; } - _logger.LogInformation("AddComputerInShop find. Id:{Id}", element.Id); + if (element.Capacity - element.Computers.Select(x => x.Value.Item2).Sum() < quantity) + { + throw new ArgumentNullException("В магазине не хватает места", nameof(quantity)); + } - if (element.Computers.TryGetValue(computer.Id, out var pair)) + if (element.Computers.TryGetValue(computer.Id, out var pair)) { element.Computers[computer.Id] = (computer, quantity + pair.Item2); _logger.LogInformation("AddComputerInShop. Has been added {quantity} {Computer} in {ShopName}", quantity, computer.ComputerName, element.ShopName); @@ -62,12 +66,64 @@ namespace ComputersShopBusinessLogic.BusinessLogics ShopAddress = element.ShopAddress, ShopName = element.ShopName, DateOpening = element.DateOpening, - Computers = element.Computers - }); + Computers = element.Computers, + Capacity = element.Capacity, + }); return true; } - public bool Create(ShopBindingModel model) + public bool AddComputers(IComputerModel computer, int quantity) + { + if (computer == null) + { + throw new ArgumentNullException(nameof(computer)); + } + if (quantity <= 0) + { + throw new ArgumentException("Количество документов должно быть больше 0", nameof(quantity)); + } + _logger.LogInformation("AddComputers. ShopName:{ShopName}. Id:{Id}", computer.ComputerName, computer.Id); + var allFreeQuantity = _shopStorage.GetFullList().Select(x => x.Capacity - x.Computers.Select(x => x.Value.Item2).Sum()).Sum(); + if (allFreeQuantity < quantity) + { + _logger.LogWarning("AddComputers operation failed."); + return false; + } + foreach (var shop in _shopStorage.GetFullList()) + { + int freeQuantity = shop.Capacity - shop.Computers.Select(x => x.Value.Item2).Sum(); + if (freeQuantity <= 0) + { + continue; + } + if (freeQuantity < quantity) + { + if (!AddComputer(new() { Id = shop.Id }, computer, freeQuantity)) + { + _logger.LogWarning("AddComputers operation failed."); + return false; + } + quantity -= freeQuantity; + } + else + { + if (!AddComputer(new() { Id = shop.Id }, computer, quantity)) + { + _logger.LogWarning("AddComputers operation failed."); + return false; + } + quantity = 0; + } + if (quantity == 0) + { + return true; + } + } + _logger.LogWarning("AddComputers operation failed."); + return false; + } + + public bool Create(ShopBindingModel model) { CheckModel(model); model.Computers = new(); @@ -131,7 +187,12 @@ namespace ComputersShopBusinessLogic.BusinessLogics return list; } - public bool Update(ShopBindingModel model) + public bool SellComputers(IComputerModel computer, int quantity) + { + return _shopStorage.SellComputers(computer, quantity); + } + + public bool Update(ShopBindingModel model) { CheckModel(model, false); diff --git a/ComputersShop/ComputersShopContracts/BindingModels/ShopBindingModel.cs b/ComputersShop/ComputersShopContracts/BindingModels/ShopBindingModel.cs index 9917239..f154e9d 100644 --- a/ComputersShop/ComputersShopContracts/BindingModels/ShopBindingModel.cs +++ b/ComputersShop/ComputersShopContracts/BindingModels/ShopBindingModel.cs @@ -14,5 +14,6 @@ namespace ComputersShopContracts.BindingModels public string ShopAddress { get; set; } = string.Empty; public DateTime DateOpening { get; set; } = DateTime.Now; public Dictionary Computers { get; set; } = new(); - } + public int Capacity { get; set; } + } } diff --git a/ComputersShop/ComputersShopContracts/BusinessLogicContracts/IStoreLogic.cs b/ComputersShop/ComputersShopContracts/BusinessLogicContracts/IShopLogic.cs similarity index 83% rename from ComputersShop/ComputersShopContracts/BusinessLogicContracts/IStoreLogic.cs rename to ComputersShop/ComputersShopContracts/BusinessLogicContracts/IShopLogic.cs index 192fa4a..e2690a2 100644 --- a/ComputersShop/ComputersShopContracts/BusinessLogicContracts/IStoreLogic.cs +++ b/ComputersShop/ComputersShopContracts/BusinessLogicContracts/IShopLogic.cs @@ -18,5 +18,7 @@ namespace ComputersShopContracts.BusinessLogicContracts bool Update(ShopBindingModel model); bool Delete(ShopBindingModel model); bool AddComputer(ShopSearchModel model, IComputerModel computer, int quantity); - } + bool AddComputers(IComputerModel computer, int quantity); + bool SellComputers(IComputerModel computer, int quantity); + } } diff --git a/ComputersShop/ComputersShopContracts/StoragesContracts/IShopStorage.cs b/ComputersShop/ComputersShopContracts/StoragesContracts/IShopStorage.cs index 4f68769..9b1979f 100644 --- a/ComputersShop/ComputersShopContracts/StoragesContracts/IShopStorage.cs +++ b/ComputersShop/ComputersShopContracts/StoragesContracts/IShopStorage.cs @@ -1,6 +1,7 @@ using ComputersShopContracts.BindingModels; using ComputersShopContracts.SearchModels; using ComputersShopContracts.ViewModels; +using ComputersShopDataModels.Models; using System; using System.Collections.Generic; using System.Linq; @@ -17,5 +18,6 @@ namespace ComputersShopContracts.StoragesContracts ShopViewModel? Insert(ShopBindingModel model); ShopViewModel? Update(ShopBindingModel model); ShopViewModel? Delete(ShopBindingModel model); - } + bool SellComputers(IComputerModel model, int quantity); + } } diff --git a/ComputersShop/ComputersShopContracts/ViewModels/ShopViewModel.cs b/ComputersShop/ComputersShopContracts/ViewModels/ShopViewModel.cs index 4a03f7a..9b28754 100644 --- a/ComputersShop/ComputersShopContracts/ViewModels/ShopViewModel.cs +++ b/ComputersShop/ComputersShopContracts/ViewModels/ShopViewModel.cs @@ -19,5 +19,7 @@ namespace ComputersShopContracts.ViewModels public string ShopAddress { get; set; } = string.Empty; [DisplayName("Дата открытия")] public DateTime DateOpening { get; set; } = DateTime.Now; - } + [DisplayName("Вместимость магазина")] + public int Capacity { get; set; } + } } diff --git a/ComputersShop/ComputersShopDataModels/Models/IShopModel.cs b/ComputersShop/ComputersShopDataModels/Models/IShopModel.cs index 4767190..fdf703f 100644 --- a/ComputersShop/ComputersShopDataModels/Models/IShopModel.cs +++ b/ComputersShop/ComputersShopDataModels/Models/IShopModel.cs @@ -11,6 +11,8 @@ namespace ComputersShopDataModels.Models public string ShopName { get; } public string ShopAddress { get; } DateTime DateOpening { get; } - Dictionary Computers { get; } + + public int Capacity { get; } + Dictionary Computers { get; } } } diff --git a/ComputersShop/ComputersShopFileImplement/DataFileSingleton.cs b/ComputersShop/ComputersShopFileImplement/DataFileSingleton.cs index f59fd2a..783e35f 100644 --- a/ComputersShop/ComputersShopFileImplement/DataFileSingleton.cs +++ b/ComputersShop/ComputersShopFileImplement/DataFileSingleton.cs @@ -14,10 +14,12 @@ namespace ComputersShopFileImplement private readonly string ComponentFileName = "Component.xml"; private readonly string OrderFileName = "Order.xml"; private readonly string ComputerFileName = "Computer.xml"; - public List Components { get; private set; } + private readonly string ShopFileName = "Shop.xml"; + public List Components { get; private set; } public List Orders { get; private set; } public List Computers { get; private set; } - public static DataFileSingleton GetInstance() + public List Shops { get; private set; } + public static DataFileSingleton GetInstance() { if (instance == null) { @@ -28,12 +30,14 @@ namespace ComputersShopFileImplement public void SaveComponents() => SaveData(Components, ComponentFileName, "Components", x => x.GetXElement); public void SaveComputers() => SaveData(Computers, ComputerFileName, "Computers", x => x.GetXElement); public void SaveOrders() => SaveData(Orders, OrderFileName, "Orders", x => x.GetXElement); - private DataFileSingleton() + public void SaveShops() => SaveData(Shops, ShopFileName, "Shops", x => x.GetXElement); + private DataFileSingleton() { Components = LoadData(ComponentFileName, "Component", x => Component.Create(x)!)!; Computers = LoadData(ComputerFileName, "Computer", x => Computer.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) { if (File.Exists(filename)) diff --git a/ComputersShop/ComputersShopFileImplement/Implements/ShopStorage.cs b/ComputersShop/ComputersShopFileImplement/Implements/ShopStorage.cs new file mode 100644 index 0000000..88c9961 --- /dev/null +++ b/ComputersShop/ComputersShopFileImplement/Implements/ShopStorage.cs @@ -0,0 +1,125 @@ +using ComputersShopContracts.BindingModels; +using ComputersShopContracts.SearchModels; +using ComputersShopContracts.StoragesContracts; +using ComputersShopContracts.ViewModels; +using ComputersShopDataModels.Models; +using ComputersShopFileImplement.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ComputersShopFileImplement.Implements +{ + public class ShopStorage : IShopStorage + { + private readonly DataFileSingleton source; + + public ShopStorage() + { + source = DataFileSingleton.GetInstance(); + } + public ShopViewModel? Delete(ShopBindingModel model) + { + var shop = source.Shops.FirstOrDefault(x => x.Id == model.Id); + if (shop != null) + { + source.Shops.Remove(shop); + source.SaveShops(); + return shop.GetViewModel; + } + return null; + } + + 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 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 List GetFullList() + { + return source.Shops.Select(x => x.GetViewModel).ToList(); + } + + 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 bool SellComputers(IComputerModel model, int quantity) + { + int availableQuantity = source.Shops.Select(x => x.Computers.FirstOrDefault(y => y.Key == model.Id).Value.Item2).Sum(); + if (availableQuantity < quantity) + { + return false; + } + var shops = source.Shops.Where(x => x.Computers.ContainsKey(model.Id)); + foreach (var shop in shops) + { + int countInCurrentShop = shop.Computers[model.Id].Item2; + if (countInCurrentShop <= quantity) + { + shop.Computers[model.Id] = (shop.Computers[model.Id].Item1, 0); + quantity -= countInCurrentShop; + } + else + { + shop.Computers[model.Id] = (shop.Computers[model.Id].Item1, countInCurrentShop - quantity); + quantity = 0; + } + Update(new ShopBindingModel + { + Id = shop.Id, + ShopName = shop.ShopName, + ShopAddress = shop.ShopAddress, + DateOpening = shop.DateOpening, + Computers = shop.Computers, + Capacity = shop.Capacity + }); + if (quantity == 0) + { + return true; + } + } + return false; + } + + public ShopViewModel? Update(ShopBindingModel model) + { + var shop = source.Shops.FirstOrDefault(x => x.Id == model.Id); + if (shop == null) + { + return null; + } + shop.Update(model); + source.SaveShops(); + return shop.GetViewModel; + } + } +} diff --git a/ComputersShop/ComputersShopFileImplement/Models/Shop.cs b/ComputersShop/ComputersShopFileImplement/Models/Shop.cs new file mode 100644 index 0000000..c805b81 --- /dev/null +++ b/ComputersShop/ComputersShopFileImplement/Models/Shop.cs @@ -0,0 +1,108 @@ +using ComputersShopContracts.BindingModels; +using ComputersShopContracts.ViewModels; +using ComputersShopDataModels.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace ComputersShopFileImplement.Models +{ + public class Shop : IShopModel + { + public int Id { get; private set; } + public string ShopName { get; private set; } = string.Empty; + public string ShopAddress { get; private set; } = string.Empty; + public DateTime DateOpening { get; private set; } + public int Capacity { get; private set; } + public Dictionary ComputersCount = new(); + public Dictionary? _computers = null; + public Dictionary Computers + { + get + { + if (_computers == null) + { + var source = DataFileSingleton.GetInstance(); + _computers = ComputersCount.ToDictionary( + x => x.Key, + y => ((source.Computers.FirstOrDefault(z => z.Id == y.Key) as IComputerModel)!, + y.Value) + ); + } + return _computers; + } + } + public static Shop? Create(ShopBindingModel? model) + { + if (model == null) + { + return null; + } + return new Shop() + { + Id = model.Id, + ShopName = model.ShopName, + ShopAddress = model.ShopAddress, + DateOpening = model.DateOpening, + Capacity = model.Capacity, + ComputersCount = model.Computers.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, + ShopAddress = element.Element("Address")!.Value, + DateOpening = Convert.ToDateTime(element.Element("DateOpening")!.Value), + Capacity = Convert.ToInt32(element.Element("Capacity")!.Value), + ComputersCount = element.Element("Computers")!.Elements("Computer") + .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; + ShopAddress = model.ShopAddress; + DateOpening = model.DateOpening; + Capacity = model.Capacity; + ComputersCount = model.Computers.ToDictionary(x => x.Key, x => x.Value.Item2); + _computers = null; + + } + public ShopViewModel GetViewModel => new() + { + Id = Id, + ShopName = ShopName, + ShopAddress = ShopAddress, + DateOpening = DateOpening, + Capacity = Capacity, + Computers = Computers + }; + public XElement GetXElement => new("Shop", + new XAttribute("Id", Id), + new XElement("ShopName", ShopName), + new XElement("Address", ShopAddress), + new XElement("DateOpening", DateOpening.ToString()), + new XElement("Capacity", Capacity.ToString()), + new XElement("Documents", ComputersCount.Select(x => + new XElement("Document", + new XElement("Key", x.Key), + new XElement("Value", x.Value))) + .ToArray())); + } +} diff --git a/ComputersShop/ComputersShopListImplement/Implements/ShopStorage.cs b/ComputersShop/ComputersShopListImplement/Implements/ShopStorage.cs index 5a3ba72..a16bf18 100644 --- a/ComputersShop/ComputersShopListImplement/Implements/ShopStorage.cs +++ b/ComputersShop/ComputersShopListImplement/Implements/ShopStorage.cs @@ -2,6 +2,7 @@ using ComputersShopContracts.SearchModels; using ComputersShopContracts.StoragesContracts; using ComputersShopContracts.ViewModels; +using ComputersShopDataModels.Models; using ComputersShopListImplement.Models; using System; using System.Collections.Generic; @@ -107,7 +108,12 @@ namespace ComputersShopListImplement.Implements return newShop.GetViewModel; } - public ShopViewModel? Update(ShopBindingModel model) + public bool SellComputers(IComputerModel model, int quantity) + { + throw new NotImplementedException(); + } + + public ShopViewModel? Update(ShopBindingModel model) { foreach (var Shop in _source.Shops) { diff --git a/ComputersShop/ComputersShopListImplement/Models/Shop.cs b/ComputersShop/ComputersShopListImplement/Models/Shop.cs index 5f6aff8..41f480c 100644 --- a/ComputersShop/ComputersShopListImplement/Models/Shop.cs +++ b/ComputersShop/ComputersShopListImplement/Models/Shop.cs @@ -55,5 +55,7 @@ namespace ComputersShopListImplement.Models DateOpening = DateOpening, Computers = Computers }; - } + + public int Capacity => throw new NotImplementedException(); + } }