diff --git a/PlumbingRepair/PlumbingRepair/FormComponents.cs b/PlumbingRepair/PlumbingRepair/FormComponents.cs index 3b86239..c85334e 100644 --- a/PlumbingRepair/PlumbingRepair/FormComponents.cs +++ b/PlumbingRepair/PlumbingRepair/FormComponents.cs @@ -13,6 +13,7 @@ namespace PlumbingRepairView InitializeComponent(); _logger = logger; _logic = logic; + LoadData(); } private void FormComponents_Load(object sender, EventArgs e) { diff --git a/PlumbingRepair/PlumbingRepairBusinessLogic/BusinessLogics/OrderLogic.cs b/PlumbingRepair/PlumbingRepairBusinessLogic/BusinessLogics/OrderLogic.cs index 5fc5c55..e9ea620 100644 --- a/PlumbingRepair/PlumbingRepairBusinessLogic/BusinessLogics/OrderLogic.cs +++ b/PlumbingRepair/PlumbingRepairBusinessLogic/BusinessLogics/OrderLogic.cs @@ -17,11 +17,15 @@ namespace PlumbingRepairBusinessLogic.BusinessLogics { private readonly ILogger _logger; private readonly IOrderStorage _orderStorage; + private readonly IStoreLogic _storeLogic; + private readonly IWorkStorage _workStorage; public OrderLogic(ILogger logger, IOrderStorage - orderStorage) + orderStorage, IStoreLogic storeLogic, IWorkStorage workStorage) { _logger = logger; _orderStorage = orderStorage; + _storeLogic = storeLogic; + _workStorage = workStorage; } public List? ReadList(OrderSearchModel? model) { @@ -74,8 +78,12 @@ namespace PlumbingRepairBusinessLogic.BusinessLogics } public bool StatusUpdate(OrderBindingModel model, OrderStatus newStatus) { - CheckModel(model); - if (model.Status + 1 != newStatus) + var viewModel = _orderStorage.GetElement(new OrderSearchModel { Id = model.Id }); + if (viewModel == null) + { + throw new ArgumentNullException(nameof(model)); + } + if (viewModel.Status + 1 != newStatus) { _logger.LogWarning("Status update to " + newStatus.ToString() + " operation failed. Order status incorrect."); return false; @@ -83,8 +91,27 @@ namespace PlumbingRepairBusinessLogic.BusinessLogics model.Status = newStatus; - if (model.Status == OrderStatus.Выдан) + if (model.Status == OrderStatus.Готов) + { model.DateImplement = DateTime.Now; + var work = _workStorage.GetElement(new() { Id = viewModel.WorkId }); + + if (work == null) + { + throw new ArgumentNullException(nameof(work)); + } + + if (!_storeLogic.AddWork(work, viewModel.Count)) + { + throw new Exception($"AddWork operation failed. Store is full."); + } + } + else + { + model.DateImplement = viewModel.DateImplement; + } + + CheckModel(model, false); if (_orderStorage.Update(model) == null) { diff --git a/PlumbingRepair/PlumbingRepairBusinessLogic/BusinessLogics/StoreLogic.cs b/PlumbingRepair/PlumbingRepairBusinessLogic/BusinessLogics/StoreLogic.cs index fe8c78e..4b53a19 100644 --- a/PlumbingRepair/PlumbingRepairBusinessLogic/BusinessLogics/StoreLogic.cs +++ b/PlumbingRepair/PlumbingRepairBusinessLogic/BusinessLogics/StoreLogic.cs @@ -31,29 +31,30 @@ namespace PlumbingRepairBusinessLogic.BusinessLogics if (quantity <= 0) { - throw new ArgumentException("Количество добавляемого изделия должно быть больше 0", nameof(quantity)); + throw new ArgumentException("Количество изделий должно быть больше 0", nameof(quantity)); } - _logger.LogInformation("AddWorkInStore. StoreName:{StoreName}.Id:{ Id}", model.StoreName, model.Id); + _logger.LogInformation("AddWork. StoreName:{StoreName}.Id:{ Id}", model.StoreName, model.Id); var element = _storeStorage.GetElement(model); if (element == null) { - _logger.LogWarning("AddWorkInStore element not found"); + _logger.LogWarning("AddWork element not found"); return false; } - - _logger.LogInformation("AddWorkInStore find. Id:{Id}", element.Id); - - if (element.Works.TryGetValue(work.Id, out var pair)) + if (element.WorkMaxCount - element.StoreWorks.Select(x => x.Value.Item2).Sum() < quantity) { - element.Works[work.Id] = (work, quantity + pair.Item2); - _logger.LogInformation("AddWorkInStore. Has been added {quantity} {work} in {StoreName}", quantity, work.WorkName, element.StoreName); + throw new ArgumentNullException("Магазин переполнен", nameof(quantity)); + } + if (element.StoreWorks.TryGetValue(work.Id, out var pair)) + { + element.StoreWorks[work.Id] = (work, quantity + pair.Item2); + _logger.LogInformation("AddWork. Added {quantity} {work} to '{StoreName}' store", quantity, work.WorkName, element.StoreName); } else { - element.Works[work.Id] = (work, quantity); - _logger.LogInformation("AddWorkInShop. Has been added {quantity} new Work {work} in {StoreName}", quantity, work.WorkName, element.StoreName); + element.StoreWorks[work.Id] = (work, quantity); + _logger.LogInformation("AddWork. Added {quantity} new package {package} to '{StoreName}' store", quantity, work.WorkName, element.StoreName); } _storeStorage.Update(new() @@ -62,15 +63,63 @@ namespace PlumbingRepairBusinessLogic.BusinessLogics StoreAdress = element.StoreAdress, StoreName = element.StoreName, OpeningDate = element.OpeningDate, - Works = element.Works + WorkMaxCount = element.WorkMaxCount, + StoreWorks = element.StoreWorks }); return true; } + public bool AddWork(IWorkModel work, int quantity) + { + if (work == null) + { + throw new ArgumentNullException(nameof(work)); + } + + if (quantity <= 0) + { + throw new ArgumentException("Количество добавляемого изделия должно быть больше 0", nameof(quantity)); + } + + var freePlaces = _storeStorage.GetFullList() + .Select(x => x.WorkMaxCount - x.StoreWorks + .Select(p => p.Value.Item2).Sum()).Sum() - quantity; + + if (freePlaces < 0) + { + _logger.LogInformation("AddWork. Failed to add work to store. It's full."); + return false; + } + + foreach (var store in _storeStorage.GetFullList()) + { + var temp = Math.Min(quantity, store.WorkMaxCount - store.StoreWorks.Select(x => x.Value.Item2).Sum()); + + if (temp <= 0) + { + continue; + } + + if (!AddWork(new() { Id = store.Id }, work, temp)) + { + _logger.LogWarning("An error occurred while adding work to stores"); + return false; + } + + quantity -= temp; + + if (quantity == 0) + { + return true; + } + } + return true; + } + public bool Create(StoreBindingModel model) { CheckModel(model); - model.Works = new(); + model.StoreWorks = new(); if (_storeStorage.Insert(model) == null) { @@ -130,6 +179,10 @@ namespace PlumbingRepairBusinessLogic.BusinessLogics _logger.LogInformation("ReadList. Count:{Count}", list.Count); return list; } + public bool SellWork(IWorkModel work, int quantity) + { + return _storeStorage.SellWork(work, quantity); + } public bool Update(StoreBindingModel model) { @@ -165,6 +218,11 @@ namespace PlumbingRepairBusinessLogic.BusinessLogics throw new ArgumentNullException("Нет названия магазина", nameof(model.StoreName)); } + if (model.WorkMaxCount < 0) + { + throw new ArgumentException("Максимальное количество изделий в магазине не может быть меньше нуля", nameof(model.WorkMaxCount)); + } + _logger.LogInformation("Store. StoreName:{0}.StoreAdress:{1}. Id: {2}", model.StoreName, model.StoreAdress, model.Id); var element = _storeStorage.GetElement(new StoreSearchModel { diff --git a/PlumbingRepair/PlumbingRepairContracts/BindingModels/StoreBindingModel.cs b/PlumbingRepair/PlumbingRepairContracts/BindingModels/StoreBindingModel.cs index 6bc3243..82e6fd9 100644 --- a/PlumbingRepair/PlumbingRepairContracts/BindingModels/StoreBindingModel.cs +++ b/PlumbingRepair/PlumbingRepairContracts/BindingModels/StoreBindingModel.cs @@ -13,6 +13,7 @@ namespace PlumbingRepairContracts.BindingModels public string StoreName { get; set; } = string.Empty; public string StoreAdress { get; set; } = string.Empty; public DateTime OpeningDate { get; set; } = DateTime.Now; - public Dictionary Works { get; set; } = new(); + public Dictionary StoreWorks { get; set; } = new(); + public int WorkMaxCount { get; set; } } } diff --git a/PlumbingRepair/PlumbingRepairContracts/BusinessLogicsContracts/IStoreLogic.cs b/PlumbingRepair/PlumbingRepairContracts/BusinessLogicsContracts/IStoreLogic.cs index c6d3511..0c2cc70 100644 --- a/PlumbingRepair/PlumbingRepairContracts/BusinessLogicsContracts/IStoreLogic.cs +++ b/PlumbingRepair/PlumbingRepairContracts/BusinessLogicsContracts/IStoreLogic.cs @@ -18,5 +18,7 @@ namespace PlumbingRepairContracts.BusinessLogicsContracts bool Update(StoreBindingModel model); bool Delete(StoreBindingModel model); bool AddWork(StoreSearchModel model, IWorkModel work, int quantity); + bool AddWork(IWorkModel package, int quantity); + bool SellWork(IWorkModel package, int quantity); } } diff --git a/PlumbingRepair/PlumbingRepairContracts/StoragesContracts/IStoreStorage.cs b/PlumbingRepair/PlumbingRepairContracts/StoragesContracts/IStoreStorage.cs index f3225c1..fad8027 100644 --- a/PlumbingRepair/PlumbingRepairContracts/StoragesContracts/IStoreStorage.cs +++ b/PlumbingRepair/PlumbingRepairContracts/StoragesContracts/IStoreStorage.cs @@ -1,6 +1,7 @@ using PlumbingRepairContracts.BindingModels; using PlumbingRepairContracts.SearchModels; using PlumbingRepairContracts.ViewModels; +using PlumbingRepairDataModels.Models; using System; using System.Collections.Generic; using System.Linq; @@ -17,5 +18,6 @@ namespace PlumbingRepairContracts.StoragesContracts StoreViewModel? Insert(StoreBindingModel model); StoreViewModel? Update(StoreBindingModel model); StoreViewModel? Delete(StoreBindingModel model); + bool SellWork(IWorkModel model, int quantity); } } diff --git a/PlumbingRepair/PlumbingRepairContracts/ViewModels/StoreViewModel.cs b/PlumbingRepair/PlumbingRepairContracts/ViewModels/StoreViewModel.cs index c7944fb..f9812c6 100644 --- a/PlumbingRepair/PlumbingRepairContracts/ViewModels/StoreViewModel.cs +++ b/PlumbingRepair/PlumbingRepairContracts/ViewModels/StoreViewModel.cs @@ -10,7 +10,7 @@ namespace PlumbingRepairContracts.ViewModels { public class StoreViewModel : IStoreModel { - public Dictionary Works { get; set; } = new(); + public Dictionary StoreWorks { get; set; } = new(); public int Id { get; set; } [DisplayName("Название магазина")] @@ -19,5 +19,7 @@ namespace PlumbingRepairContracts.ViewModels public string StoreAdress { get; set; } = string.Empty; [DisplayName("Дата открытия")] public DateTime OpeningDate { get; set; } = DateTime.Now; + [DisplayName("Вместимость магазина")] + public int WorkMaxCount { get; set; } } } diff --git a/PlumbingRepair/PlumbingRepairDataModels/Models/IStoreModel.cs b/PlumbingRepair/PlumbingRepairDataModels/Models/IStoreModel.cs index e3b83bc..9e83ae0 100644 --- a/PlumbingRepair/PlumbingRepairDataModels/Models/IStoreModel.cs +++ b/PlumbingRepair/PlumbingRepairDataModels/Models/IStoreModel.cs @@ -11,6 +11,7 @@ namespace PlumbingRepairDataModels.Models string StoreName { get; } string StoreAdress { get; } DateTime OpeningDate { get; } - Dictionary Works { get; } + Dictionary StoreWorks { get; } + public int WorkMaxCount { get; } } } diff --git a/PlumbingRepair/PlumbingRepairFileImplement/DataFileSingleton.cs b/PlumbingRepair/PlumbingRepairFileImplement/DataFileSingleton.cs index 3fbf29f..4c8d7e2 100644 --- a/PlumbingRepair/PlumbingRepairFileImplement/DataFileSingleton.cs +++ b/PlumbingRepair/PlumbingRepairFileImplement/DataFileSingleton.cs @@ -14,9 +14,11 @@ namespace PlumbingRepairFileImplement private readonly string ComponentFileName = "Component.xml"; private readonly string OrderFileName = "Order.xml"; private readonly string WorkFileName = "Work.xml"; + private readonly string StoreFileName = "Store.xml"; public List Components { get; private set; } public List Orders { get; private set; } public List Works { get; private set; } + public List Stores { get; private set; } public static DataFileSingleton GetInstance() { if (instance == null) @@ -31,6 +33,8 @@ namespace PlumbingRepairFileImplement "Works", x => x.GetXElement); public void SaveOrders() => SaveData(Orders, OrderFileName, "Orders", x => x.GetXElement); + public void SaveStores() => SaveData(Stores, StoreFileName, + "Stores", x => x.GetXElement); private DataFileSingleton() { Components = LoadData(ComponentFileName, "Component", x => @@ -38,6 +42,7 @@ namespace PlumbingRepairFileImplement Works = LoadData(WorkFileName, "Work", x => Work.Create(x)!)!; Orders = LoadData(OrderFileName, "Order", x => Order.Create(x)!)!; + Stores = LoadData(StoreFileName, "Store", x => Store.Create(x)!)!; } private static List? LoadData(string filename, string xmlNodeName, Func selectFunction) diff --git a/PlumbingRepair/PlumbingRepairFileImplement/Implements/StoreStorage.cs b/PlumbingRepair/PlumbingRepairFileImplement/Implements/StoreStorage.cs new file mode 100644 index 0000000..b0e3593 --- /dev/null +++ b/PlumbingRepair/PlumbingRepairFileImplement/Implements/StoreStorage.cs @@ -0,0 +1,114 @@ +using PlumbingRepairContracts.BindingModels; +using PlumbingRepairContracts.SearchModels; +using PlumbingRepairContracts.StoragesContracts; +using PlumbingRepairContracts.ViewModels; +using PlumbingRepairDataModels.Models; +using PlumbingRepairFileImplement.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PlumbingRepairFileImplement.Implements +{ + public class StoreStorage : IStoreStorage + { + private readonly DataFileSingleton source; + + public StoreStorage() + { + source = DataFileSingleton.GetInstance(); + } + + public StoreViewModel? GetElement(StoreSearchModel model) + { + if (string.IsNullOrEmpty(model.StoreName) && !model.Id.HasValue) + { + return null; + } + return source.Stores.FirstOrDefault(x => + (!string.IsNullOrEmpty(model.StoreName) && x.StoreName == + model.StoreName) || (model.Id.HasValue && x.Id == model.Id))?.GetViewModel; + } + + public List GetFilteredList(StoreSearchModel model) + { + if (string.IsNullOrEmpty(model.StoreName)) + { + return new(); + } + return source.Stores.Where(x => + x.StoreName.Contains(model.StoreName)).Select(x => x.GetViewModel).ToList(); + } + + public List GetFullList() + { + return source.Stores.Select(x => x.GetViewModel).ToList(); + } + + public StoreViewModel? Insert(StoreBindingModel model) + { + model.Id = source.Stores.Count > 0 ? source.Stores.Max(x => x.Id) + 1 : 1; + var newStore = Store.Create(model); + if (newStore == null) + { + return null; + } + source.Stores.Add(newStore); + source.SaveStores(); + return newStore.GetViewModel; + } + + public StoreViewModel? Update(StoreBindingModel model) + { + var store = source.Stores.FirstOrDefault(x => x.Id == model.Id); + if (store == null) + { + return null; + } + store.Update(model); + source.SaveStores(); + return store.GetViewModel; + } + + public StoreViewModel? Delete(StoreBindingModel model) + { + var element = source.Stores.FirstOrDefault(x => x.Id == model.Id); + if (element != null) + { + source.Stores.Remove(element); + source.SaveStores(); + return element.GetViewModel; + } + return null; + } + + public bool SellWork(IWorkModel model, int quantity) + { + if (source.Stores.Select(x => x.StoreWorks.FirstOrDefault(y => y.Key == model.Id).Value.Item2).Sum() < quantity) + { + return false; + } + foreach (var store in source.Stores.Where(x => x.StoreWorks.ContainsKey(model.Id))) + { + int QuantityInCurrentShop = store.StoreWorks[model.Id].Item2; + if (QuantityInCurrentShop <= quantity) + { + store.StoreWorks.Remove(model.Id); + quantity -= QuantityInCurrentShop; + } + else + { + store.StoreWorks[model.Id] = (store.StoreWorks[model.Id].Item1, QuantityInCurrentShop - quantity); + quantity = 0; + } + if (quantity == 0) + { + return true; + } + } + return false; + } + } +} diff --git a/PlumbingRepair/PlumbingRepairFileImplement/Models/Store.cs b/PlumbingRepair/PlumbingRepairFileImplement/Models/Store.cs new file mode 100644 index 0000000..793e55f --- /dev/null +++ b/PlumbingRepair/PlumbingRepairFileImplement/Models/Store.cs @@ -0,0 +1,108 @@ +using PlumbingRepairContracts.BindingModels; +using PlumbingRepairContracts.ViewModels; +using PlumbingRepairDataModels.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace PlumbingRepairFileImplement.Models +{ + public class Store : IStoreModel + { + public string StoreName { get; private set; } = string.Empty; + public string StoreAdress { get; private set; } = string.Empty; + + public DateTime OpeningDate { get; private set; } + public Dictionary Works { get; private set; } = new(); + + public Dictionary _storeWorks = null; + + public int Id { get; private set; } + + public int WorkMaxCount { get; private set; } + + public Dictionary StoreWorks + { + get + { + if (_storeWorks == null) + { + var source = DataFileSingleton.GetInstance(); + _storeWorks = Works.ToDictionary(x => x.Key, y => ((source.Works.FirstOrDefault(z => z.Id == y.Key) as IWorkModel)!, y.Value)); + } + return _storeWorks; + } + } + + public static Store? Create(StoreBindingModel? model) + { + if (model == null) + { + return null; + } + return new Store() + { + Id = model.Id, + StoreName = model.StoreName, + StoreAdress = model.StoreAdress, + WorkMaxCount = model.WorkMaxCount, + OpeningDate = model.OpeningDate, + Works = model.StoreWorks.ToDictionary(x => x.Key, x => x.Value.Item2) + }; + } + public static Store? Create(XElement element) + { + if (element == null) + { + return null; + } + return new() + { + Id = Convert.ToInt32(element.Attribute("Id")!.Value), + StoreName = element.Element("StoreName")!.Value, + StoreAdress = element.Element("StoreAdress")!.Value, + OpeningDate = Convert.ToDateTime(element.Element("OpeningDate")!.Value), + WorkMaxCount = Convert.ToInt32(element.Element("WorkMaxCount")!.Value), + Works = element.Element("StoreWorks")!.Elements("Work").ToDictionary( + x => Convert.ToInt32(x.Element("Key")?.Value), + x => Convert.ToInt32(x.Element("Value")?.Value)) + }; + } + public void Update(StoreBindingModel? model) + { + if (model == null) + { + return; + } + StoreName = model.StoreName; + StoreAdress = model.StoreAdress; + OpeningDate = model.OpeningDate; + WorkMaxCount = model.WorkMaxCount; + Works = model.StoreWorks.ToDictionary(x => x.Key, x => x.Value.Item2); + _storeWorks = null; + } + public StoreViewModel GetViewModel => new() + { + Id = Id, + StoreName = StoreName, + StoreAdress = StoreAdress, + StoreWorks = StoreWorks, + OpeningDate = OpeningDate, + WorkMaxCount = WorkMaxCount, + }; + public XElement GetXElement => new("Store", + new XAttribute("Id", Id), + new XElement("StoreName", StoreName), + new XElement("StoreAdress", StoreAdress), + new XElement("OpeningDate", OpeningDate), + new XElement("WorkMaxCount", WorkMaxCount), + new XElement("StoreWorks", Works + .Select(x => new XElement("Work", + new XElement("Key", x.Key), + new XElement("Value", x.Value)) + ).ToArray())); + } +} diff --git a/PlumbingRepair/PlumbingRepairListImplement/Implements/StoreStorage.cs b/PlumbingRepair/PlumbingRepairListImplement/Implements/StoreStorage.cs index 8beea22..07fcdfc 100644 --- a/PlumbingRepair/PlumbingRepairListImplement/Implements/StoreStorage.cs +++ b/PlumbingRepair/PlumbingRepairListImplement/Implements/StoreStorage.cs @@ -2,6 +2,7 @@ using PlumbingRepairContracts.SearchModels; using PlumbingRepairContracts.StoragesContracts; using PlumbingRepairContracts.ViewModels; +using PlumbingRepairDataModels.Models; using PlumbingRepairListImplement.Models; using System; using System.Collections.Generic; @@ -105,7 +106,10 @@ namespace PlumbingRepairListImplement.Implements return newStore.GetViewModel; } - + public bool SellWork(IWorkModel model, int quantity) + { + throw new NotImplementedException(); + } public StoreViewModel? Update(StoreBindingModel model) { foreach (var store in _source.Stores) diff --git a/PlumbingRepair/PlumbingRepairListImplement/Models/Store.cs b/PlumbingRepair/PlumbingRepairListImplement/Models/Store.cs index 984e300..7530094 100644 --- a/PlumbingRepair/PlumbingRepairListImplement/Models/Store.cs +++ b/PlumbingRepair/PlumbingRepairListImplement/Models/Store.cs @@ -16,7 +16,7 @@ namespace PlumbingRepairListImplement.Models public DateTime OpeningDate { get; private set; } - public Dictionary Works { get; private set; } = new(); + public Dictionary StoreWorks { get; private set; } = new(); public int Id { get; private set; } @@ -32,7 +32,7 @@ namespace PlumbingRepairListImplement.Models StoreName = model.StoreName, StoreAdress = model.StoreAdress, OpeningDate = model.OpeningDate, - Works = new() + StoreWorks = new() }; } @@ -45,7 +45,7 @@ namespace PlumbingRepairListImplement.Models StoreName = model.StoreName; StoreAdress = model.StoreAdress; OpeningDate = model.OpeningDate; - Works = model.Works; + StoreWorks = model.StoreWorks; } public StoreViewModel GetViewModel => new() @@ -54,7 +54,8 @@ namespace PlumbingRepairListImplement.Models StoreName = StoreName, StoreAdress = StoreAdress, OpeningDate = OpeningDate, - Works = Works + StoreWorks = StoreWorks }; + public int WorkMaxCount => throw new NotImplementedException(); } }