From 644b5668ab0376ba869d0e7b8dd5b71706037371 Mon Sep 17 00:00:00 2001 From: the Date: Sat, 22 Jun 2024 18:13:07 +0400 Subject: [PATCH] =?UTF-8?q?=D0=9B=D0=BE=D0=B3=D0=B8=D0=BA=D0=B0,=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1=82=D1=8B,=20=D0=BA?= =?UTF-8?q?=D1=80=D1=83=D0=B4=20=D0=BA=D0=BE=D1=80=D0=BE=D1=87=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BusinessLogic/BusinessLogic/ProductLogic.cs | 90 +++++++++- BusinessLogic/BusinessLogic/SupplierLogic.cs | 114 +++++++++++++ BusinessLogic/BusinessLogic/SupplyLogic.cs | 105 ++++++++++++ Contracts/SearchModels/ProductSearchModel.cs | 2 + Contracts/SearchModels/SupplySearchModel.cs | 1 + Contracts/ViewModels/ProductViewModel.cs | 2 +- .../Implements/ProductStorage.cs | 161 ++++++++++++++++++ DatabaseImplement/Models/Product.cs | 36 +++- 8 files changed, 502 insertions(+), 9 deletions(-) create mode 100644 BusinessLogic/BusinessLogic/SupplierLogic.cs create mode 100644 BusinessLogic/BusinessLogic/SupplyLogic.cs create mode 100644 DatabaseImplement/Implements/ProductStorage.cs diff --git a/BusinessLogic/BusinessLogic/ProductLogic.cs b/BusinessLogic/BusinessLogic/ProductLogic.cs index a177c19..e10985d 100644 --- a/BusinessLogic/BusinessLogic/ProductLogic.cs +++ b/BusinessLogic/BusinessLogic/ProductLogic.cs @@ -15,33 +15,111 @@ namespace BusinessLogic.BusinessLogic public class ProductLogic : IProductLogic { private readonly IProductStorage _productStorage; - public ProductLogic(IProductStorage productStorage) + private readonly ILogger _logger; + public ProductLogic(IProductStorage productStorage, ILogger logger) { _productStorage = productStorage; + _logger = logger; } public bool Create(ProductBindingModel model) { - throw new NotImplementedException(); + CheckModel(model); + if (_productStorage.Insert(model) == null) + { + _logger.LogWarning("Insert operation failed"); + return false; + } + return true; } public bool Delete(ProductBindingModel model) { - throw new NotImplementedException(); + CheckModel(model, false); + _logger.LogInformation("Delete. Id:{Id}", model.Id); + if (_productStorage.Delete(model) == null) + { + _logger.LogWarning("Delete operation failed"); + return false; + } + return true; } public ProductViewModel? ReadElement(ProductSearchModel model) { - throw new NotImplementedException(); + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + _logger.LogInformation("ReadElement. Name:{Name}.Id:{ Id}", model.Name, model.Id); + var element = _productStorage.GetElement(model); + if (element == null) + { + _logger.LogWarning("ReadElement element not found"); + return null; + } + _logger.LogInformation("ReadElement find. Id:{Id}", element.Id); + return element; } public List? ReadList(ProductSearchModel? model) { - throw new NotImplementedException(); + _logger.LogInformation("ReadList. Name:{Name}.Id:{ Id}", model?.Name, model?.Id); + var list = model == null ? _productStorage.GetFullList() : _productStorage.GetFilteredList(model); + if (list == null) + { + _logger.LogWarning("ReadList return null list"); + return null; + } + _logger.LogInformation("ReadList. Count:{Count}", list.Count); + return list; } public bool Update(ProductBindingModel model) { - throw new NotImplementedException(); + CheckModel(model); + if (_productStorage.Update(model) == null) + { + _logger.LogWarning("Update operation failed"); + return false; + } + return true; + } + + private void CheckModel(ProductBindingModel model, bool withParams = true) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + if (!withParams) + { + return; + } + if (string.IsNullOrEmpty(model.Name)) + { + throw new ArgumentNullException("Нет названия продукта", nameof(model.Name)); + } + if (model.Price < 0) + { + throw new Exception("Цена продукта не может быть ниже нуля"); + } + if (model.Amount < 0) + { + throw new Exception("Кол-во продуктов не может быть ниже нуля"); + } + if (model.Rate < 0.0 || model.Rate > 5.0) + { + throw new Exception("Рейтинг продукта должен быть в пределах от 0.0 до 5.0"); + } + _logger.LogInformation("Product. ProductName:{Name}.Price:{ Price}. Id: { Id}", model.Name, model.Price, model.Id); + var element = _productStorage.GetElement(new ProductSearchModel + { + Name = model.Name + }); + if (element != null && element.Id != model.Id) + { + throw new InvalidOperationException("Продукт с таким названием уже есть"); + } } } } diff --git a/BusinessLogic/BusinessLogic/SupplierLogic.cs b/BusinessLogic/BusinessLogic/SupplierLogic.cs new file mode 100644 index 0000000..e71654e --- /dev/null +++ b/BusinessLogic/BusinessLogic/SupplierLogic.cs @@ -0,0 +1,114 @@ +using Contracts.BindingModels; +using Contracts.BusinessLogicContracts; +using Contracts.SearchModels; +using Contracts.StorageContracts; +using Contracts.ViewModels; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BusinessLogic.BusinessLogic +{ + public class SupplierLogic : ISupplierLogic + { + private readonly ISupplierStorage _supplierStorage; + private readonly ILogger _logger; + public SupplierLogic(ISupplierStorage supplierStorage, ILogger logger) + { + _supplierStorage = supplierStorage; + _logger = logger; + } + public bool Create(SupplierBindingModel model) + { + CheckModel(model); + if (_supplierStorage.Insert(model) == null) + { + _logger.LogWarning("Insert operation failed"); + return false; + } + return true; + } + + public bool Delete(SupplierBindingModel model) + { + CheckModel(model, false); + _logger.LogInformation("Delete. Id:{Id}", model.Id); + if (_supplierStorage.Delete(model) == null) + { + _logger.LogWarning("Delete operation failed"); + return false; + } + return true; + } + + public SupplierViewModel? ReadElement(SupplierSearchModel model) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + _logger.LogInformation("ReadElement. Name:{Name}.Id:{ Id}", model.Name, model.Id); + var element = _supplierStorage.GetElement(model); + if (element == null) + { + _logger.LogWarning("ReadElement element not found"); + return null; + } + _logger.LogInformation("ReadElement find. Id:{Id}", element.Id); + return element; + } + + public List? ReadList(SupplierSearchModel? model) + { + _logger.LogInformation("ReadList. Name:{Name}.Id:{ Id}", model?.Name, model?.Id); + var list = model == null ? _supplierStorage.GetFullList() : _supplierStorage.GetFilteredList(model); + if (list == null) + { + _logger.LogWarning("ReadList return null list"); + return null; + } + _logger.LogInformation("ReadList. Count:{Count}", list.Count); + return list; + } + + public bool Update(SupplierBindingModel model) + { + CheckModel(model); + if (_supplierStorage.Update(model) == null) + { + _logger.LogWarning("Update operation failed"); + return false; + } + return true; + } + private void CheckModel(SupplierBindingModel model, bool withParams = true) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + if (!withParams) + { + return; + } + if (string.IsNullOrEmpty(model.Name)) + { + throw new ArgumentNullException("Нет названия поставщика", nameof(model.Name)); + } + if (model.Deals < 0) + { + throw new Exception("Кол-во сделок не может быть меньше нуля"); + } + foreach(var item in model.AvailibleProducts.Values) + { + if (item.Item2 < 0) + { + throw new Exception("Кол-во доступных продуктов не должно быть отрицательным"); + } + } + } + } +} diff --git a/BusinessLogic/BusinessLogic/SupplyLogic.cs b/BusinessLogic/BusinessLogic/SupplyLogic.cs new file mode 100644 index 0000000..63a40d9 --- /dev/null +++ b/BusinessLogic/BusinessLogic/SupplyLogic.cs @@ -0,0 +1,105 @@ +using Contracts.BindingModels; +using Contracts.BusinessLogicContracts; +using Contracts.SearchModels; +using Contracts.StorageContracts; +using Contracts.ViewModels; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BusinessLogic.BusinessLogic +{ + public class SupplyLogic : ISupplyLogic + { + private readonly ISupplyStorage _supplyStorage; + private readonly ILogger _logger; + public SupplyLogic(ISupplyStorage supplyStorage, ILogger logger) + { + _supplyStorage = supplyStorage; + _logger = logger; + } + + public bool Create(SupplyBindingModel model) + { + CheckModel(model); + if (_supplyStorage.Insert(model) == null) + { + _logger.LogWarning("Insert operation failed"); + return false; + } + return true; + } + + public bool Delete(SupplyBindingModel model) + { + CheckModel(model, false); + _logger.LogInformation("Delete. Id:{Id}", model.Id); + if (_supplyStorage.Delete(model) == null) + { + _logger.LogWarning("Delete operation failed"); + return false; + } + return true; + } + + public SupplyViewModel? ReadElement(SupplySearchModel model) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + _logger.LogInformation("ReadElement. Name:{Name}.Id:{ Id}", model.Name, model.Id); + var element = _supplyStorage.GetElement(model); + if (element == null) + { + _logger.LogWarning("ReadElement element not found"); + return null; + } + _logger.LogInformation("ReadElement find. Id:{Id}", element.Id); + return element; + } + + public List? ReadList(SupplySearchModel? model) + { + _logger.LogInformation("ReadList. Name:{Name}.Id:{ Id}", model?.Name, model?.Id); + var list = model == null ? _supplyStorage.GetFullList() : _supplyStorage.GetFilteredList(model); + if (list == null) + { + _logger.LogWarning("ReadList return null list"); + return null; + } + _logger.LogInformation("ReadList. Count:{Count}", list.Count); + return list; + } + + public bool Update(SupplyBindingModel model) + { + CheckModel(model); + if (_supplyStorage.Update(model) == null) + { + _logger.LogWarning("Update operation failed"); + return false; + } + return true; + } + + private void CheckModel(SupplyBindingModel model, bool withParams = true) + { + if (model == null) + { + throw new ArgumentNullException(nameof(model)); + } + if (!withParams) + { + return; + } + if (string.IsNullOrEmpty(model.Name)) + { + throw new ArgumentNullException("Нет названия поставки", nameof(model.Name)); + } + } + } +} diff --git a/Contracts/SearchModels/ProductSearchModel.cs b/Contracts/SearchModels/ProductSearchModel.cs index a6527dd..1759010 100644 --- a/Contracts/SearchModels/ProductSearchModel.cs +++ b/Contracts/SearchModels/ProductSearchModel.cs @@ -12,5 +12,7 @@ namespace Contracts.SearchModels public string? Name { get; set; } public double? Price { get; set; } public double? Rate { get; set; } + public int? Amount { get; set; } + public bool? IsBeingSold { get; set; } } } diff --git a/Contracts/SearchModels/SupplySearchModel.cs b/Contracts/SearchModels/SupplySearchModel.cs index 6fd24c8..dee63a8 100644 --- a/Contracts/SearchModels/SupplySearchModel.cs +++ b/Contracts/SearchModels/SupplySearchModel.cs @@ -10,6 +10,7 @@ namespace Contracts.SearchModels public class SupplySearchModel { public Guid? Id { get; set; } + public string Name { get; set; } = string.Empty; public SupplyStatus? Status { get; set; } public DateTime? DateStart { get; set; } public DateTime? DateEnd { get; set; } diff --git a/Contracts/ViewModels/ProductViewModel.cs b/Contracts/ViewModels/ProductViewModel.cs index 1424a09..efb0338 100644 --- a/Contracts/ViewModels/ProductViewModel.cs +++ b/Contracts/ViewModels/ProductViewModel.cs @@ -11,7 +11,7 @@ namespace Contracts.ViewModels { public Guid Id { get; set; } public string Name { get; set; } = string.Empty; - public int Price { get; set; } + public double Price { get; set; } public double Rating { get; set; } public bool IsBeingSold { get; set; } public int Amount { get; set; } diff --git a/DatabaseImplement/Implements/ProductStorage.cs b/DatabaseImplement/Implements/ProductStorage.cs new file mode 100644 index 0000000..feb9fc5 --- /dev/null +++ b/DatabaseImplement/Implements/ProductStorage.cs @@ -0,0 +1,161 @@ +using Contracts.BindingModels; +using Contracts.SearchModels; +using Contracts.StorageContracts; +using Contracts.ViewModels; +using DatabaseImplement.Models; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DatabaseImplement.Implements +{ + public class ProductStorage : IProductStorage + { + public ProductViewModel? Delete(ProductBindingModel model) + { + using var context = new Database(); + var element = context.Products + .Include(x => x.Name) + .Include(x => x.Price) + .Include(x => x.IsBeingSold) + .Include(x => x.Rate) + .Include(x => x.Amount) + .FirstOrDefault(rec => rec.Id == model.Id); + if (element != null) + { + context.Products.Remove(element); + context.SaveChanges(); + return element.GetViewModel; + } + return null; + } + + public ProductViewModel? GetElement(ProductSearchModel model) + { + if (!model.Id.HasValue) + { + return null; + } + using var context = new Database(); + return context.Products + .Include(x => x.Name) + .Include(x => x.Price) + .Include(x => x.IsBeingSold) + .Include(x => x.Rate) + .Include(x => x.Amount) + .FirstOrDefault(x => (model.Id.HasValue && x.Id == model.Id))?.GetViewModel; + } + + public List GetFilteredList(ProductSearchModel model) + { + if (!model.IsBeingSold.HasValue && !model.Price.HasValue && !model.Rate.HasValue && !model.Amount.HasValue && string.IsNullOrEmpty(model.Name)) + { + return new(); + } + using var context = new Database(); + if (model.Price.HasValue) + { + return context.Products + .Include(x => x.Name) + .Include(x => x.Price) + .Include(x => x.IsBeingSold) + .Include(x => x.Rate) + .Include(x => x.Amount) + .Where(x => x.Price <= model.Price) + .ToList() + .Select(x => x.GetViewModel) + .ToList(); + } + if (model.Rate.HasValue) + { + return context.Products + .Include(x => x.Name) + .Include(x => x.Price) + .Include(x => x.IsBeingSold) + .Include(x => x.Rate) + .Include(x => x.Amount) + .Where(x => x.Rate <= model.Rate) + .ToList() + .Select(x => x.GetViewModel) + .ToList(); + } + if (model.Amount.HasValue && model.IsBeingSold.HasValue) + { + return context.Products + .Include(x => x.Name) + .Include(x => x.Price) + .Include(x => x.IsBeingSold) + .Include(x => x.Rate) + .Include(x => x.Amount) + .Where(x => x.IsBeingSold == model.IsBeingSold && x.Amount >= model.Amount) + .ToList() + .Select(x => x.GetViewModel) + .ToList(); + } + return context.Products + .Include(x => x.Name) + .Include(x => x.Price) + .Include(x => x.IsBeingSold) + .Include(x => x.Rate) + .Include(x => x.Amount) + .Where(x => x.Name == model.Name) + .ToList() + .Select(x => x.GetViewModel) + .ToList(); + } + + public List GetFullList() + { + using var context = new Database(); + return context.Products + .Include(x => x.Name) + .Include(x => x.Price) + .Include(x => x.IsBeingSold) + .Include(x => x.Rate) + .Include(x => x.Amount) + .ToList() + .Select(x => x.GetViewModel) + .ToList(); + } + + public ProductViewModel? Insert(ProductBindingModel model) + { + using var context = new Database(); + var newProduct = Product.Create(context, model); + if (newProduct == null) + { + return null; + } + context.Products.Add(newProduct); + context.SaveChanges(); + return newProduct.GetViewModel; + } + + public ProductViewModel? Update(ProductBindingModel model) + { + using var context = new Database(); + using var transaction = context.Database.BeginTransaction(); + try + { + var product = context.Products.FirstOrDefault(rec => + rec.Id == model.Id); + if (product == null) + { + return null; + } + product.Update(model); + context.SaveChanges(); + transaction.Commit(); + return product.GetViewModel; + } + catch + { + transaction.Rollback(); + throw; + } + } + } +} diff --git a/DatabaseImplement/Models/Product.cs b/DatabaseImplement/Models/Product.cs index bc14d3e..7edb9f4 100644 --- a/DatabaseImplement/Models/Product.cs +++ b/DatabaseImplement/Models/Product.cs @@ -7,6 +7,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; +using static System.Runtime.InteropServices.JavaScript.JSType; namespace DatabaseImplement.Models { @@ -55,7 +56,21 @@ namespace DatabaseImplement.Models Amount = model.Amount }; - public void Update(ProductBindingModel model, Product product) + public static Product Create(Database context, ProductBindingModel model) + { + return new Product() + { + Id = model.Id, + Name = model.Name, + Price = model.Price, + Rate = model.Rate, + IsBeingSold = model.IsBeingSold, + Amount = model.Amount + }; + } + + + public void Update(ProductBindingModel model) { if (model is null) { @@ -68,5 +83,22 @@ namespace DatabaseImplement.Models IsBeingSold = model.IsBeingSold; Amount = model.Amount; } - } + + public ProductViewModel GetViewModel + { + get + { + var context = new Database(); + return new() + { + Id = Id, + Name = Name, + Price = Price, + IsBeingSold = IsBeingSold, + Rating = Rate, + Amount = Amount + }; + } + } + } }