From 276c84948ed2c78ec4c0c408aaa1e71829e4ade3 Mon Sep 17 00:00:00 2001 From: user Date: Mon, 31 Mar 2025 15:32:15 +0400 Subject: [PATCH 1/5] 12 --- Romashki/Romashki.sln | 6 ++++++ Romashki/RomashkiDatabase/Models/Buyer.cs | 16 +++++++++++++++ Romashki/RomashkiDatabase/Models/Discount.cs | 14 +++++++++++++ Romashki/RomashkiDatabase/Models/Post.cs | 16 +++++++++++++++ Romashki/RomashkiDatabase/Models/Product.cs | 20 +++++++++++++++++++ .../RomashkiDatabase/RomashkiDatabase.csproj | 13 ++++++++++++ 6 files changed, 85 insertions(+) create mode 100644 Romashki/RomashkiDatabase/Models/Buyer.cs create mode 100644 Romashki/RomashkiDatabase/Models/Discount.cs create mode 100644 Romashki/RomashkiDatabase/Models/Post.cs create mode 100644 Romashki/RomashkiDatabase/Models/Product.cs create mode 100644 Romashki/RomashkiDatabase/RomashkiDatabase.csproj diff --git a/Romashki/Romashki.sln b/Romashki/Romashki.sln index 9ee0b23..cad636a 100644 --- a/Romashki/Romashki.sln +++ b/Romashki/Romashki.sln @@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RomashkiTests", "RomashkiTe EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RomashkiBusinessLogic", "RomashkiBusinessLogic\RomashkiBusinessLogic.csproj", "{DDA1EFF5-DA12-43AD-96BD-56C2A7D26804}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RomashkiDatabase", "RomashkiDatabase\RomashkiDatabase.csproj", "{84381B2C-2FCF-4EFB-85AA-F959C81C0590}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,6 +29,10 @@ Global {DDA1EFF5-DA12-43AD-96BD-56C2A7D26804}.Debug|Any CPU.Build.0 = Debug|Any CPU {DDA1EFF5-DA12-43AD-96BD-56C2A7D26804}.Release|Any CPU.ActiveCfg = Release|Any CPU {DDA1EFF5-DA12-43AD-96BD-56C2A7D26804}.Release|Any CPU.Build.0 = Release|Any CPU + {84381B2C-2FCF-4EFB-85AA-F959C81C0590}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {84381B2C-2FCF-4EFB-85AA-F959C81C0590}.Debug|Any CPU.Build.0 = Debug|Any CPU + {84381B2C-2FCF-4EFB-85AA-F959C81C0590}.Release|Any CPU.ActiveCfg = Release|Any CPU + {84381B2C-2FCF-4EFB-85AA-F959C81C0590}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Romashki/RomashkiDatabase/Models/Buyer.cs b/Romashki/RomashkiDatabase/Models/Buyer.cs new file mode 100644 index 0000000..c0ed95c --- /dev/null +++ b/Romashki/RomashkiDatabase/Models/Buyer.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RomashkiDatabase.Models; + +class Buyer +{ + public string Id { get; private set; } + public string FIO { get; private set; } + public string Email { get; private set; } + public float TotalSpend { get; private set; } + public double DiscountSize { get; private set; } +} diff --git a/Romashki/RomashkiDatabase/Models/Discount.cs b/Romashki/RomashkiDatabase/Models/Discount.cs new file mode 100644 index 0000000..a8db35c --- /dev/null +++ b/Romashki/RomashkiDatabase/Models/Discount.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RomashkiDatabase.Models; + +class Discount +{ + public string BuyerId { get; private set; } + public DateTime DiscountDate { get; private set; } + public double DiscountSize { get; private set; } +} diff --git a/Romashki/RomashkiDatabase/Models/Post.cs b/Romashki/RomashkiDatabase/Models/Post.cs new file mode 100644 index 0000000..8502dec --- /dev/null +++ b/Romashki/RomashkiDatabase/Models/Post.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RomashkiDatabase.Models; + +class Post +{ + public string Id { get; private set; } = id; + public string PostName { get; private set; } = postName; + public PostType PostType { get; private set; } = postType; + public bool IsActual { get; private set; } = isActual; + public DateTime ChangeDate { get; private set; } = changeDate; +} diff --git a/Romashki/RomashkiDatabase/Models/Product.cs b/Romashki/RomashkiDatabase/Models/Product.cs new file mode 100644 index 0000000..30d0bbb --- /dev/null +++ b/Romashki/RomashkiDatabase/Models/Product.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using RomashkiContracts.Enums; + +namespace RomashkiDatabase.Models; + +class Product +{ + public required string Id { get; set; } + public required string ManufacturerId { get; set; } + public required string ProductName { get; set; } + public ProductType ProductType { get; set; } + public double Price { get; set; } + public bool IsDeleted { get; set; } + public string? PrevProductName { get; set; } + public string? PrevPrevProductName { get; set; } +} diff --git a/Romashki/RomashkiDatabase/RomashkiDatabase.csproj b/Romashki/RomashkiDatabase/RomashkiDatabase.csproj new file mode 100644 index 0000000..4af8c28 --- /dev/null +++ b/Romashki/RomashkiDatabase/RomashkiDatabase.csproj @@ -0,0 +1,13 @@ + + + + net9.0 + enable + enable + + + + + + + -- 2.25.1 From 8d8b952a82ef0546e71cea30466e64728e885281 Mon Sep 17 00:00:00 2001 From: Rinat Date: Sat, 12 Apr 2025 12:13:55 +0400 Subject: [PATCH 2/5] 1 --- .../RomashkiBusinessLogic.csproj | 1 + .../Exceptions/ElementDeletedException.cs | 12 ++ .../Infrastructure/IConfigurationDatabase.cs | 12 ++ .../RomashkiContract/RomashkiContract.csproj | 5 + .../Implementations/BuyerStorageContract.cs | 157 ++++++++++++++ .../Implementations/PostStorageContract.cs | 196 ++++++++++++++++++ .../Implementations/ProductStorageContract.cs | 177 ++++++++++++++++ Romashki/RomashkiDatabase/Models/Buyer.cs | 16 +- Romashki/RomashkiDatabase/Models/Discount.cs | 6 +- Romashki/RomashkiDatabase/Models/Post.cs | 15 +- Romashki/RomashkiDatabase/Models/Product.cs | 9 +- .../RomashkiDatabase/Models/ProductHistory.cs | 15 ++ Romashki/RomashkiDatabase/Models/Sale.cs | 27 +++ .../RomashkiDatabase/Models/SaleProduct.cs | 16 ++ Romashki/RomashkiDatabase/Models/Worker.cs | 21 ++ .../RomashkiDatabase/RomashkiDatabase.csproj | 6 + .../RomashkiDatabase/RomashkiDbContext.cs | 55 +++++ 17 files changed, 731 insertions(+), 15 deletions(-) create mode 100644 Romashki/RomashkiContract/Exceptions/ElementDeletedException.cs create mode 100644 Romashki/RomashkiContract/Infrastructure/IConfigurationDatabase.cs create mode 100644 Romashki/RomashkiDatabase/Implementations/BuyerStorageContract.cs create mode 100644 Romashki/RomashkiDatabase/Implementations/PostStorageContract.cs create mode 100644 Romashki/RomashkiDatabase/Implementations/ProductStorageContract.cs create mode 100644 Romashki/RomashkiDatabase/Models/ProductHistory.cs create mode 100644 Romashki/RomashkiDatabase/Models/Sale.cs create mode 100644 Romashki/RomashkiDatabase/Models/SaleProduct.cs create mode 100644 Romashki/RomashkiDatabase/Models/Worker.cs create mode 100644 Romashki/RomashkiDatabase/RomashkiDbContext.cs diff --git a/Romashki/RomashkiBusinessLogic/RomashkiBusinessLogic.csproj b/Romashki/RomashkiBusinessLogic/RomashkiBusinessLogic.csproj index e9c0dc3..ce3fff6 100644 --- a/Romashki/RomashkiBusinessLogic/RomashkiBusinessLogic.csproj +++ b/Romashki/RomashkiBusinessLogic/RomashkiBusinessLogic.csproj @@ -7,6 +7,7 @@ + diff --git a/Romashki/RomashkiContract/Exceptions/ElementDeletedException.cs b/Romashki/RomashkiContract/Exceptions/ElementDeletedException.cs new file mode 100644 index 0000000..f48b5ce --- /dev/null +++ b/Romashki/RomashkiContract/Exceptions/ElementDeletedException.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RomashkiContract.Exceptions; + +public class ElementDeletedException : Exception +{ + public ElementDeletedException(string id) : base($"Cannot modify a deleted item(id: { id})") { } +} diff --git a/Romashki/RomashkiContract/Infrastructure/IConfigurationDatabase.cs b/Romashki/RomashkiContract/Infrastructure/IConfigurationDatabase.cs new file mode 100644 index 0000000..972e4eb --- /dev/null +++ b/Romashki/RomashkiContract/Infrastructure/IConfigurationDatabase.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RomashkiContract.Infrastructure; + +public interface IConfigurationDatabase +{ + string ConnectionString { get; } +} diff --git a/Romashki/RomashkiContract/RomashkiContract.csproj b/Romashki/RomashkiContract/RomashkiContract.csproj index 125f4c9..c65d8e3 100644 --- a/Romashki/RomashkiContract/RomashkiContract.csproj +++ b/Romashki/RomashkiContract/RomashkiContract.csproj @@ -6,4 +6,9 @@ enable + + + + + diff --git a/Romashki/RomashkiDatabase/Implementations/BuyerStorageContract.cs b/Romashki/RomashkiDatabase/Implementations/BuyerStorageContract.cs new file mode 100644 index 0000000..787d956 --- /dev/null +++ b/Romashki/RomashkiDatabase/Implementations/BuyerStorageContract.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using AutoMapper; +using Microsoft.EntityFrameworkCore; +using Npgsql; +using RomashkiContract.Exceptions; +using RomashkiContract.StoragesContracts; +using RomashkiContracts.DataModels; +using RomashkiDatabase.Models; + +namespace RomashkiDatabase.Implementations; + +internal class BuyerStorageContract : IBuyerStorageContract +{ + private readonly RomashkiDbContext _dbContext; + private readonly Mapper _mapper; + public BuyerStorageContract(RomashkiDbContext dbContext) + { + _dbContext = dbContext; + var config = new MapperConfiguration(cfg => + { + cfg.CreateMap(); + cfg.CreateMap(); + }); + _mapper = new Mapper(config); + } + public List GetList() + { + try + { + return [.. _dbContext.Buyers.Select(x => +_mapper.Map(x))]; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + public BuyerDataModel? GetElementById(string id) + { + try + { + return _mapper.Map(GetBuyerById(id)); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + public BuyerDataModel? GetElementByFIO(string fio) + { + try + { + return + _mapper.Map(_dbContext.Buyers.FirstOrDefault(x => x.FIO == fio)); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + public BuyerDataModel? GetElementByEmail(string email) + { + try + { + return + _mapper.Map(_dbContext.Buyers.FirstOrDefault(x => x.Email == email)); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + public void AddElement(BuyerDataModel buyerDataModel) + { + try + { + _dbContext.Buyers.Add(_mapper.Map(buyerDataModel)); + _dbContext.SaveChanges(); + } + catch (InvalidOperationException ex) when (ex.TargetSite?.Name == + "ThrowIdentityConflict") + { + _dbContext.ChangeTracker.Clear(); + throw new ElementExistsException("Id", buyerDataModel.Id); + } + catch (DbUpdateException ex) when (ex.InnerException is + PostgresException { ConstraintName: "IX_Buyers_Email" }) + { + _dbContext.ChangeTracker.Clear(); + throw new ElementExistsException("Email", buyerDataModel.Email); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + public void UpdElement(BuyerDataModel buyerDataModel) + { + try + { + var element = GetBuyerById(buyerDataModel.Id) ?? throw new + ElementNotFoundException(buyerDataModel.Id); + _dbContext.Buyers.Update(_mapper.Map(buyerDataModel, + element)); + _dbContext.SaveChanges(); + } + catch (ElementNotFoundException) + { + + _dbContext.ChangeTracker.Clear(); + throw; + } + catch (DbUpdateException ex) when (ex.InnerException is + PostgresException { ConstraintName: "IX_Buyers_Email" }) + { + _dbContext.ChangeTracker.Clear(); + throw new ElementExistsException("Email",buyerDataModel.Email); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + public void DelElement(string id) + { + try + { + var element = GetBuyerById(id) ?? throw new + ElementNotFoundException(id); + _dbContext.Buyers.Remove(element); + _dbContext.SaveChanges(); + } + catch (ElementNotFoundException) + { + _dbContext.ChangeTracker.Clear(); + throw; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + private Buyer? GetBuyerById(string id) => + _dbContext.Buyers.FirstOrDefault(x => x.Id == id); +} + diff --git a/Romashki/RomashkiDatabase/Implementations/PostStorageContract.cs b/Romashki/RomashkiDatabase/Implementations/PostStorageContract.cs new file mode 100644 index 0000000..5aabb7e --- /dev/null +++ b/Romashki/RomashkiDatabase/Implementations/PostStorageContract.cs @@ -0,0 +1,196 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using AutoMapper; +using Microsoft.EntityFrameworkCore; +using Npgsql; +using RomashkiContract.Exceptions; +using RomashkiContract.StoragesContracts; +using RomashkiContracts.DataModels; +using RomashkiDatabase.Models; + +namespace RomashkiDatabase.Implementations; + + +internal class PostStorageContract : IPostStorageContract +{ + private readonly RomashkiDbContext _dbContext; + private readonly Mapper _mapper; + + public PostStorageContract(RomashkiDbContext dbContext) + { + _dbContext = dbContext; + var config = new MapperConfiguration(cfg => + { + cfg.CreateMap() + .ForMember(x => x.Id, x => x.MapFrom(src => src.PostId)); + cfg.CreateMap() + .ForMember(x => x.Id, x => x.Ignore()) + .ForMember(x => x.PostId, x => x.MapFrom(src => src.Id)) + .ForMember(x => x.IsActual, x => x.MapFrom(src => true)) + .ForMember(x => x.ChangeDate, x => x.MapFrom(src => DateTime.UtcNow)); + }); + _mapper = new Mapper(config); + } + + public List GetList(bool onlyActual = true) + { + try + { + var query = _dbContext.Posts.AsQueryable(); + if (onlyActual) + { + query = query.Where(x => x.IsActual); + } + return [.. query.Select(x => _mapper.Map(x))]; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public List GetPostWithHistory(string postId) + { + try + { + return [.. _dbContext.Posts.Where(x => x.PostId == postId).Select(x => _mapper.Map(x))]; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public PostDataModel? GetElementById(string id) + { + try + { + return _mapper.Map(_dbContext.Posts.FirstOrDefault(x => x.PostId == id && x.IsActual)); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public PostDataModel? GetElementByName(string name) + { + try + { + return _mapper.Map(_dbContext.Posts.FirstOrDefault(x => x.PostName == name && x.IsActual)); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void AddElement(PostDataModel postDataModel) + { + try + { + _dbContext.Posts.Add(_mapper.Map(postDataModel)); + _dbContext.SaveChanges(); + } + catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Posts_PostName_IsActual" }) + { + _dbContext.ChangeTracker.Clear(); + throw new ElementExistsException("PostName", postDataModel.PostName); + } + catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Posts_PostId_IsActual" }) + { + _dbContext.ChangeTracker.Clear(); + throw new ElementExistsException("PostId", postDataModel.Id); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void UpdElement(PostDataModel postDataModel) + { + try + { + var transaction = _dbContext.Database.BeginTransaction(); + try + { + var element = GetPostById(postDataModel.Id) ?? throw new ElementNotFoundException(postDataModel.Id); + if (!element.IsActual) + { + throw new ElementDeletedException(postDataModel.Id); + } + element.IsActual = false; + _dbContext.SaveChanges(); + var newElement = _mapper.Map(postDataModel); + _dbContext.Posts.Add(newElement); + _dbContext.SaveChanges(); + transaction.Commit(); + } + catch + { + transaction.Rollback(); + throw; + } + } + catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Posts_PostName_IsActual" }) + { + _dbContext.ChangeTracker.Clear(); + throw new ElementExistsException("PostName", postDataModel.PostName); + } + catch (Exception ex) when (ex is ElementDeletedException || ex is ElementNotFoundException) + { + _dbContext.ChangeTracker.Clear(); + throw; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void DelElement(string id) + { + try + { + var element = GetPostById(id) ?? throw new ElementNotFoundException(id); + if (!element.IsActual) + { + throw new ElementDeletedException(id); + } + element.IsActual = false; + _dbContext.SaveChanges(); + } + catch + { + _dbContext.ChangeTracker.Clear(); + throw; + } + } + + public void ResElement(string id) + { + try + { + var element = GetPostById(id) ?? throw new ElementNotFoundException(id); + element.IsActual = true; + _dbContext.SaveChanges(); + } + catch + { + _dbContext.ChangeTracker.Clear(); + throw; + } + } + + private Post? GetPostById(string id) => _dbContext.Posts.Where(x => x.PostId == id).OrderByDescending(x => x.ChangeDate).FirstOrDefault(); +} \ No newline at end of file diff --git a/Romashki/RomashkiDatabase/Implementations/ProductStorageContract.cs b/Romashki/RomashkiDatabase/Implementations/ProductStorageContract.cs new file mode 100644 index 0000000..dafb56f --- /dev/null +++ b/Romashki/RomashkiDatabase/Implementations/ProductStorageContract.cs @@ -0,0 +1,177 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using AutoMapper; +using Microsoft.EntityFrameworkCore; +using Npgsql; +using RomashkiContract.Exceptions; +using RomashkiContract.StoragesContracts; +using RomashkiContracts.DataModels; +using RomashkiDatabase.Models; + +namespace RomashkiDatabase.Implementations +{ + internal class ProductStorageContract : IProductStorageContract + { + private readonly RomashkiDbContext _dbContext; + private readonly Mapper _mapper; + + public ProductStorageContract(RomashkiDbContext dbContext) + { + _dbContext = dbContext; + var config = new MapperConfiguration(cfg => + { + cfg.CreateMap(); + cfg.CreateMap() + .ForMember(x => x.IsDeleted, x => x.MapFrom(src => false)); + cfg.CreateMap(); + }); + _mapper = new Mapper(config); + } + + public List GetList(bool onlyActive = true) + { + try + { + var query = _dbContext.Products.AsQueryable(); + if (onlyActive) + { + query = query.Where(x => !x.IsDeleted); + } + return [.. query.Select(x => _mapper.Map(x))]; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public List GetHistoryByProductId(string productId) + { + try + { + return [.. _dbContext.ProductHistories.Where(x => x.ProductId == productId).OrderByDescending(x => x.ChangeDate).Select(x => _mapper.Map(x))]; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public ProductDataModel? GetElementById(string id) + { + try + { + return _mapper.Map(GetProductById(id)); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public ProductDataModel? GetElementByName(string name) + { + try + { + return _mapper.Map(_dbContext.Products.FirstOrDefault(x => x.ProductName == name && !x.IsDeleted)); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void AddElement(ProductDataModel productDataModel) + { + try + { + _dbContext.Products.Add(_mapper.Map(productDataModel)); + _dbContext.SaveChanges(); + } + catch (InvalidOperationException ex) when (ex.TargetSite?.Name == "ThrowIdentityConflict") + { + _dbContext.ChangeTracker.Clear(); + throw new ElementExistsException("Id", productDataModel.Id); + } + catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Products_ProductName_IsDeleted" }) + { + _dbContext.ChangeTracker.Clear(); + throw new ElementExistsException("ProductName", productDataModel.ProductName); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void UpdElement(ProductDataModel productDataModel) + { + try + { + var transaction = _dbContext.Database.BeginTransaction(); + try + { + var element = GetProductById(productDataModel.Id) ?? throw new ElementNotFoundException(productDataModel.Id); + if (element.Price != productDataModel.Price) + { + _dbContext.ProductHistories.Add(new ProductHistory() { ProductId = element.Id, OldPrice = element.Price }); + _dbContext.SaveChanges(); + } + _dbContext.Products.Update(_mapper.Map(productDataModel, element)); + _dbContext.SaveChanges(); + transaction.Commit(); + } + catch + { + transaction.Rollback(); + throw; + } + } + catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Products_ProductName_IsDeleted" }) + { + _dbContext.ChangeTracker.Clear(); + throw new ElementExistsException("ProductName", productDataModel.ProductName); + } + catch (Exception ex) when (ex is ElementDeletedException || ex is ElementNotFoundException) + { + _dbContext.ChangeTracker.Clear(); + throw; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void DelElement(string id) + { + try + { + var element = GetProductById(id) ?? throw new ElementNotFoundException(id); + element.IsDeleted = true; + _dbContext.SaveChanges(); + } + catch (ElementNotFoundException ex) + { + _dbContext.ChangeTracker.Clear(); + throw; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + private Product? GetProductById(string id) => _dbContext.Products.FirstOrDefault(x => x.Id == id && !x.IsDeleted); + } +} diff --git a/Romashki/RomashkiDatabase/Models/Buyer.cs b/Romashki/RomashkiDatabase/Models/Buyer.cs index c0ed95c..1f84302 100644 --- a/Romashki/RomashkiDatabase/Models/Buyer.cs +++ b/Romashki/RomashkiDatabase/Models/Buyer.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -8,9 +9,14 @@ namespace RomashkiDatabase.Models; class Buyer { - public string Id { get; private set; } - public string FIO { get; private set; } - public string Email { get; private set; } - public float TotalSpend { get; private set; } - public double DiscountSize { get; private set; } + public required string Id { get; set; } = Guid.NewGuid().ToString(); + public string? FIO { get; set; } + public required string Email { get; set; } + public float TotalSpend { get; set; } + public double DiscountSize { get; set; } + + [ForeignKey("BuyerId")] + public List? Sales { get; set; } + + } diff --git a/Romashki/RomashkiDatabase/Models/Discount.cs b/Romashki/RomashkiDatabase/Models/Discount.cs index a8db35c..fb562c5 100644 --- a/Romashki/RomashkiDatabase/Models/Discount.cs +++ b/Romashki/RomashkiDatabase/Models/Discount.cs @@ -8,7 +8,7 @@ namespace RomashkiDatabase.Models; class Discount { - public string BuyerId { get; private set; } - public DateTime DiscountDate { get; private set; } - public double DiscountSize { get; private set; } + public required string BuyerId { get; set; } + public DateTime DiscountDate { get; set; } + public double DiscountSize { get; set; } } diff --git a/Romashki/RomashkiDatabase/Models/Post.cs b/Romashki/RomashkiDatabase/Models/Post.cs index 8502dec..56948cc 100644 --- a/Romashki/RomashkiDatabase/Models/Post.cs +++ b/Romashki/RomashkiDatabase/Models/Post.cs @@ -1,16 +1,21 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Text; using System.Threading.Tasks; +using RomashkiContracts.Enums; namespace RomashkiDatabase.Models; class Post { - public string Id { get; private set; } = id; - public string PostName { get; private set; } = postName; - public PostType PostType { get; private set; } = postType; - public bool IsActual { get; private set; } = isActual; - public DateTime ChangeDate { get; private set; } = changeDate; + public required string Id { get; set; } = Guid.NewGuid().ToString(); + public required string PostId { get; set; } + public required string PostName { get; set; } + public PostType PostType { get; set; } + public bool IsActual { get; set; } + public DateTime ChangeDate { get; set; } + [ForeignKey("WorkerId")] + public List? Workers { get; set; } } diff --git a/Romashki/RomashkiDatabase/Models/Product.cs b/Romashki/RomashkiDatabase/Models/Product.cs index 30d0bbb..c5db55e 100644 --- a/Romashki/RomashkiDatabase/Models/Product.cs +++ b/Romashki/RomashkiDatabase/Models/Product.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -9,12 +10,16 @@ namespace RomashkiDatabase.Models; class Product { - public required string Id { get; set; } - public required string ManufacturerId { get; set; } + public required string Id { get; set; } = Guid.NewGuid().ToString(); public required string ProductName { get; set; } public ProductType ProductType { get; set; } public double Price { get; set; } public bool IsDeleted { get; set; } public string? PrevProductName { get; set; } public string? PrevPrevProductName { get; set; } + + [ForeignKey("ProductId")] + public List? ProductHistories { get; set; } + [ForeignKey("ProductId")] + public List? SaleProducts { get; set; } } diff --git a/Romashki/RomashkiDatabase/Models/ProductHistory.cs b/Romashki/RomashkiDatabase/Models/ProductHistory.cs new file mode 100644 index 0000000..2e5bb2c --- /dev/null +++ b/Romashki/RomashkiDatabase/Models/ProductHistory.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RomashkiDatabase.Models; + +internal class ProductHistory +{ + public required string Id { get; set; } = Guid.NewGuid().ToString(); + public required string ProductId { get; set; } + public double OldPrice { get; set; } + public DateTime ChangeDate { get; set; } = DateTime.UtcNow; +} diff --git a/Romashki/RomashkiDatabase/Models/Sale.cs b/Romashki/RomashkiDatabase/Models/Sale.cs new file mode 100644 index 0000000..4655618 --- /dev/null +++ b/Romashki/RomashkiDatabase/Models/Sale.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using RomashkiContracts.Enums; + +namespace RomashkiDatabase.Models; + +internal class Sale +{ + public required string Id { get; set; } = Guid.NewGuid().ToString(); + public string? WorkerId { get; set; } + public string? BuyerId { get; set; } + public DateTime SaleDate { get; set; } + public double Sum { get; set; } + public DiscountType DiscountType { get; set; } + public double Discount { get; set; } + public bool IsCancel { get; set; } + public Worker? Worker { get; set; } + public Buyer? Buyer { get; set; } + + [ForeignKey("SaleId")] + public List? SaleProducts { get; set; } + +} diff --git a/Romashki/RomashkiDatabase/Models/SaleProduct.cs b/Romashki/RomashkiDatabase/Models/SaleProduct.cs new file mode 100644 index 0000000..2b8fa15 --- /dev/null +++ b/Romashki/RomashkiDatabase/Models/SaleProduct.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RomashkiDatabase.Models; + +internal class SaleProduct +{ + public required string SaleId { get; set; } + public required string ProductId { get; set; } + public int Count { get; set; } + public double Price { get; set; } + +} diff --git a/Romashki/RomashkiDatabase/Models/Worker.cs b/Romashki/RomashkiDatabase/Models/Worker.cs new file mode 100644 index 0000000..04773c6 --- /dev/null +++ b/Romashki/RomashkiDatabase/Models/Worker.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RomashkiDatabase.Models; + +internal class Worker +{ + public required string Id { get; set; } = Guid.NewGuid().ToString(); + public required string FIO { get; set; } + public required string PostId { get; set; } + public DateTime BirthDate { get; set; } + public DateTime EmploymentDate { get; set; } + public bool IsDeleted { get; set; } + + [ForeignKey("WorkerId")] + public List? Sales { get; set; } +} \ No newline at end of file diff --git a/Romashki/RomashkiDatabase/RomashkiDatabase.csproj b/Romashki/RomashkiDatabase/RomashkiDatabase.csproj index 4af8c28..5c325e5 100644 --- a/Romashki/RomashkiDatabase/RomashkiDatabase.csproj +++ b/Romashki/RomashkiDatabase/RomashkiDatabase.csproj @@ -6,6 +6,12 @@ enable + + + + + + diff --git a/Romashki/RomashkiDatabase/RomashkiDbContext.cs b/Romashki/RomashkiDatabase/RomashkiDbContext.cs new file mode 100644 index 0000000..84259c7 --- /dev/null +++ b/Romashki/RomashkiDatabase/RomashkiDbContext.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using RomashkiContract.Infrastructure; +using RomashkiDatabase.Models; + +namespace RomashkiDatabase; + +internal class RomashkiDbContext(IConfigurationDatabase configurationDatabase) +: DbContext +{ + private readonly IConfigurationDatabase? _configurationDatabase = + configurationDatabase; + protected override void OnConfiguring(DbContextOptionsBuilder + optionsBuilder) + { + optionsBuilder.UseNpgsql(_configurationDatabase?.ConnectionString, o + => o.SetPostgresVersion(12, 2)); + base.OnConfiguring(optionsBuilder); + } + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + modelBuilder.Entity().HasIndex(x => x.Email).IsUnique(); + modelBuilder.Entity() + .HasIndex(e => new { e.PostName, e.IsActual }) + .IsUnique() + .HasFilter($"\"{nameof(Post.IsActual)}\" = TRUE"); + modelBuilder.Entity() + .HasIndex(e => new { e.PostId, e.IsActual }) + .IsUnique() + .HasFilter($"\"{nameof(Post.IsActual)}\" = TRUE"); + modelBuilder.Entity() + .HasIndex(x => new { x.ProductName, x.IsDeleted }) + .IsUnique() + .HasFilter($"\"{nameof(Product.IsDeleted)}\" = FALSE"); + + + modelBuilder.Entity().HasKey(x => new { + x.SaleId, + x.ProductId + }); + } + public DbSet Buyers { get; set; } + public DbSet Posts { get; set; } + public DbSet Products { get; set; } + public DbSet ProductHistories { get; set; } + public DbSet Discounts { get; set; } + public DbSet Sales { get; set; } + public DbSet SaleProducts { get; set; } + public DbSet Workers { get; set; } +} \ No newline at end of file -- 2.25.1 From dbfb6a1fd2b0d58779c9cdaa3de13aab9e6f5993 Mon Sep 17 00:00:00 2001 From: Rinat Date: Sat, 12 Apr 2025 12:40:33 +0400 Subject: [PATCH 3/5] =?UTF-8?q?=D0=B1=D0=B5=D0=B7=20=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=BE=D0=B2=20=D0=B8=20=D1=81=D0=BA=D0=B8=D0=B4=D0=BA?= =?UTF-8?q?=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RomashkiBusinessLogic.csproj | 2 +- .../RomashkiContract/RomashkiContract.csproj | 1 - .../Implementations/SaleStorageContract.cs | 117 ++++++++++++++ .../Implementations/WorkerStorageContract.cs | 146 ++++++++++++++++++ .../RomashkiDatabase/Models/ProductHistory.cs | 3 +- 5 files changed, 266 insertions(+), 3 deletions(-) create mode 100644 Romashki/RomashkiDatabase/Implementations/SaleStorageContract.cs create mode 100644 Romashki/RomashkiDatabase/Implementations/WorkerStorageContract.cs diff --git a/Romashki/RomashkiBusinessLogic/RomashkiBusinessLogic.csproj b/Romashki/RomashkiBusinessLogic/RomashkiBusinessLogic.csproj index ce3fff6..f01077d 100644 --- a/Romashki/RomashkiBusinessLogic/RomashkiBusinessLogic.csproj +++ b/Romashki/RomashkiBusinessLogic/RomashkiBusinessLogic.csproj @@ -7,8 +7,8 @@ - + diff --git a/Romashki/RomashkiContract/RomashkiContract.csproj b/Romashki/RomashkiContract/RomashkiContract.csproj index c65d8e3..f85607b 100644 --- a/Romashki/RomashkiContract/RomashkiContract.csproj +++ b/Romashki/RomashkiContract/RomashkiContract.csproj @@ -7,7 +7,6 @@ - diff --git a/Romashki/RomashkiDatabase/Implementations/SaleStorageContract.cs b/Romashki/RomashkiDatabase/Implementations/SaleStorageContract.cs new file mode 100644 index 0000000..1b9b49a --- /dev/null +++ b/Romashki/RomashkiDatabase/Implementations/SaleStorageContract.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using AutoMapper; +using Microsoft.EntityFrameworkCore; +using RomashkiContract.Exceptions; +using RomashkiContract.StoragesContracts; +using RomashkiContracts.DataModels; +using RomashkiDatabase.Models; + +namespace RomashkiDatabase.Implementations; + +internal class SaleStorageContract : ISaleStorageContract +{ + private readonly RomashkiDbContext _dbContext; + private readonly Mapper _mapper; + + public SaleStorageContract(RomashkiDbContext dbContext) + { + _dbContext = dbContext; + var config = new MapperConfiguration(cfg => + { + cfg.CreateMap(); + cfg.CreateMap(); + cfg.CreateMap(); + cfg.CreateMap() + .ForMember(x => x.IsCancel, x => x.MapFrom(src => false)) + .ForMember(x => x.SaleProducts, x => x.MapFrom(src => src.Products)); + }); + _mapper = new Mapper(config); + } + + public List GetList(DateTime? startDate = null, DateTime? endDate = null, string? workerId = null, string? buyerId = null, string? productId = null) + { + try + { + var query = _dbContext.Sales.Include(x => x.SaleProducts).AsQueryable(); + if (startDate is not null && endDate is not null) + { + query = query.Where(x => x.SaleDate >= startDate && x.SaleDate < endDate); + } + if (workerId is not null) + { + query = query.Where(x => x.WorkerId == workerId); + } + if (buyerId is not null) + { + query = query.Where(x => x.BuyerId == buyerId); + } + if (productId is not null) + { + query = query.Where(x => x.SaleProducts!.Any(y => y.ProductId == productId)); + } + return [.. query.Select(x => _mapper.Map(x))]; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public SaleDataModel? GetElementById(string id) + { + try + { + return _mapper.Map(GetSaleById(id)); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void AddElement(SaleDataModel saleDataModel) + { + try + { + _dbContext.Sales.Add(_mapper.Map(saleDataModel)); + _dbContext.SaveChanges(); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void DelElement(string id) + { + try + { + var element = GetSaleById(id) ?? throw new ElementNotFoundException(id); + if (element.IsCancel) + { + throw new ElementDeletedException(id); + } + element.IsCancel = true; + _dbContext.SaveChanges(); + } + catch (Exception ex) when (ex is ElementDeletedException || ex is ElementNotFoundException) + { + _dbContext.ChangeTracker.Clear(); + throw; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + private Sale? GetSaleById(string id) => _dbContext.Sales.FirstOrDefault(x => x.Id == id); +} diff --git a/Romashki/RomashkiDatabase/Implementations/WorkerStorageContract.cs b/Romashki/RomashkiDatabase/Implementations/WorkerStorageContract.cs new file mode 100644 index 0000000..0b2469a --- /dev/null +++ b/Romashki/RomashkiDatabase/Implementations/WorkerStorageContract.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using AutoMapper; +using RomashkiContract.Exceptions; +using RomashkiContract.StoragesContracts; +using RomashkiContracts.DataModels; +using RomashkiDatabase.Models; + +namespace RomashkiDatabase.Implementations; + +internal class WorkerStorageContract : IWorkerStorageContract +{ + private readonly RomashkiDbContext _dbContext; + private readonly Mapper _mapper; + + public WorkerStorageContract(RomashkiDbContext dbContext) + { + _dbContext = dbContext; + var config = new MapperConfiguration(cfg => + { + cfg.CreateMap(); + cfg.CreateMap(); + }); + _mapper = new Mapper(config); + } + + public List GetList(bool onlyActive = true, string? postId = null, DateTime? fromBirthDate = null, DateTime? toBirthDate = null, DateTime? fromEmploymentDate = null, DateTime? toEmploymentDate = null) + { + try + { + var query = _dbContext.Workers.AsQueryable(); + if (onlyActive) + { + query = query.Where(x => !x.IsDeleted); + } + if (postId is not null) + { + query = query.Where(x => x.PostId == postId); + } + if (fromBirthDate is not null && toBirthDate is not null) + { + query = query.Where(x => x.BirthDate >= fromBirthDate && x.BirthDate <= toBirthDate); + } + if (fromEmploymentDate is not null && toEmploymentDate is not null) + { + query = query.Where(x => x.EmploymentDate >= fromEmploymentDate && x.EmploymentDate <= toEmploymentDate); + } + return [.. query.Select(x => _mapper.Map(x))]; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public WorkerDataModel? GetElementById(string id) + { + try + { + return _mapper.Map(GetWorkerById(id)); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public WorkerDataModel? GetElementByFIO(string fio) + { + try + { + return _mapper.Map(_dbContext.Workers.FirstOrDefault(x => x.FIO == fio)); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void AddElement(WorkerDataModel workerDataModel) + { + try + { + _dbContext.Workers.Add(_mapper.Map(workerDataModel)); + _dbContext.SaveChanges(); + } + catch (InvalidOperationException ex) when (ex.TargetSite?.Name == "ThrowIdentityConflict") + { + _dbContext.ChangeTracker.Clear(); + throw new ElementExistsException("Id", workerDataModel.Id); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void UpdElement(WorkerDataModel workerDataModel) + { + try + { + var element = GetWorkerById(workerDataModel.Id) ?? throw new ElementNotFoundException(workerDataModel.Id); + _dbContext.Workers.Update(_mapper.Map(workerDataModel, element)); + _dbContext.SaveChanges(); + } + catch (ElementNotFoundException) + { + _dbContext.ChangeTracker.Clear(); + throw; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void DelElement(string id) + { + try + { + var element = GetWorkerById(id) ?? throw new ElementNotFoundException(id); + element.IsDeleted = true; + _dbContext.SaveChanges(); + } + catch (ElementNotFoundException) + { + _dbContext.ChangeTracker.Clear(); + throw; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + private Worker? GetWorkerById(string id) => _dbContext.Workers.FirstOrDefault(x => x.Id == id && !x.IsDeleted); +} \ No newline at end of file diff --git a/Romashki/RomashkiDatabase/Models/ProductHistory.cs b/Romashki/RomashkiDatabase/Models/ProductHistory.cs index 2e5bb2c..947f468 100644 --- a/Romashki/RomashkiDatabase/Models/ProductHistory.cs +++ b/Romashki/RomashkiDatabase/Models/ProductHistory.cs @@ -8,8 +8,9 @@ namespace RomashkiDatabase.Models; internal class ProductHistory { - public required string Id { get; set; } = Guid.NewGuid().ToString(); + public string Id { get; set; } = Guid.NewGuid().ToString(); public required string ProductId { get; set; } public double OldPrice { get; set; } public DateTime ChangeDate { get; set; } = DateTime.UtcNow; + public Product? Product { get; set; } } -- 2.25.1 From 227a800d278fed6916d94ffc441f82d6f289760f Mon Sep 17 00:00:00 2001 From: Rinat Date: Mon, 14 Apr 2025 12:06:51 +0400 Subject: [PATCH 4/5] =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DataModels/PostDataModel.cs | 12 +- .../DiscountStorageContract.cs | 61 ++++ Romashki/RomashkiDatabase/Models/Discount.cs | 1 + Romashki/RomashkiDatabase/Models/Post.cs | 9 +- Romashki/RomashkiDatabase/Models/Sale.cs | 7 +- .../RomashkiDatabase/Models/SaleProduct.cs | 4 +- .../ConfigurationDatabaseTest.cs | 14 + .../BaseStorageContractTest.cs | 31 ++ .../BuyerStorageContractTests.cs | 218 ++++++++++++ .../DiscountStorageContractTests.cs | 153 +++++++++ .../PostStorageContractTests.cs | 323 ++++++++++++++++++ .../ProductStorageContractTests.cs | 315 +++++++++++++++++ .../SaleStorageContractTests.cs | 308 +++++++++++++++++ 13 files changed, 1439 insertions(+), 17 deletions(-) create mode 100644 Romashki/RomashkiDatabase/Implementations/DiscountStorageContract.cs create mode 100644 Romashki/RomashkiTests/Infrastructure/ConfigurationDatabaseTest.cs create mode 100644 Romashki/RomashkiTests/Infrastructure/StoragesContracts/BaseStorageContractTest.cs create mode 100644 Romashki/RomashkiTests/Infrastructure/StoragesContracts/BuyerStorageContractTests.cs create mode 100644 Romashki/RomashkiTests/Infrastructure/StoragesContracts/DiscountStorageContractTests.cs create mode 100644 Romashki/RomashkiTests/Infrastructure/StoragesContracts/PostStorageContractTests.cs create mode 100644 Romashki/RomashkiTests/Infrastructure/StoragesContracts/ProductStorageContractTests.cs create mode 100644 Romashki/RomashkiTests/Infrastructure/StoragesContracts/SaleStorageContractTests.cs diff --git a/Romashki/RomashkiContract/DataModels/PostDataModel.cs b/Romashki/RomashkiContract/DataModels/PostDataModel.cs index 92be896..7908ecf 100644 --- a/Romashki/RomashkiContract/DataModels/PostDataModel.cs +++ b/Romashki/RomashkiContract/DataModels/PostDataModel.cs @@ -11,25 +11,27 @@ using RomashkiContracts.Exceptions; namespace RomashkiContracts.DataModels; -public class PostDataModel(string id, string postName, - PostType postType, bool isActual, DateTime changeDate) : IValidation - +public class PostDataModel(string postId, string postName, PostType postType, + bool isActual, DateTime changeDate) : IValidation { - public string Id { get; private set; } = id; + public string Id { get; private set; } = postId; public string PostName { get; private set; } = postName; public PostType PostType { get; private set; } = postType; public bool IsActual { get; private set; } = isActual; public DateTime ChangeDate { get; private set; } = changeDate; + public void Validate() { if (Id.IsEmpty()) throw new ValidationException("Field Id is empty"); + if (!Id.IsGuid()) throw new ValidationException("The value in the field Id is not a unique identifier"); + if (PostName.IsEmpty()) throw new ValidationException("Field PostName is empty"); + if (PostType == PostType.None) throw new ValidationException("Field PostType is empty"); } } - diff --git a/Romashki/RomashkiDatabase/Implementations/DiscountStorageContract.cs b/Romashki/RomashkiDatabase/Implementations/DiscountStorageContract.cs new file mode 100644 index 0000000..99c2a2c --- /dev/null +++ b/Romashki/RomashkiDatabase/Implementations/DiscountStorageContract.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using AutoMapper; +using RomashkiContract.DataModels; +using RomashkiContract.Exceptions; +using RomashkiContract.StoragesContracts; +using RomashkiDatabase.Models; + +namespace RomashkiDatabase.Implementations; + +internal class DiscountStorageContract : IDiscountStorageContract +{ + private readonly RomashkiDbContext _dbContext; + private readonly Mapper _mapper; + + public DiscountStorageContract(RomashkiDbContext dbContext) + { + _dbContext = dbContext; + var config = new MapperConfiguration(cfg => + { + cfg.CreateMap(); + cfg.CreateMap(); + }); + _mapper = new Mapper(config); + } + + public List GetList(DateTime startDate, DateTime endDate, string? buyerId = null) + { + try + { + var query = _dbContext.Discounts.Where(x => x.DiscountDate >= startDate && x.DiscountDate <= endDate); + if (buyerId is not null) + { + query = query.Where(x => x.BuyerId == buyerId); + } + return [.. query.Select(x => _mapper.Map(x))]; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void AddElement(DiscountDataModel discountDataModel) + { + try + { + _dbContext.Discounts.Add(_mapper.Map(discountDataModel)); + _dbContext.SaveChanges(); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } +} diff --git a/Romashki/RomashkiDatabase/Models/Discount.cs b/Romashki/RomashkiDatabase/Models/Discount.cs index fb562c5..a636ab9 100644 --- a/Romashki/RomashkiDatabase/Models/Discount.cs +++ b/Romashki/RomashkiDatabase/Models/Discount.cs @@ -8,6 +8,7 @@ namespace RomashkiDatabase.Models; class Discount { + public string Id { get; set; } = Guid.NewGuid().ToString(); public required string BuyerId { get; set; } public DateTime DiscountDate { get; set; } public double DiscountSize { get; set; } diff --git a/Romashki/RomashkiDatabase/Models/Post.cs b/Romashki/RomashkiDatabase/Models/Post.cs index 56948cc..eb900cb 100644 --- a/Romashki/RomashkiDatabase/Models/Post.cs +++ b/Romashki/RomashkiDatabase/Models/Post.cs @@ -8,14 +8,13 @@ using RomashkiContracts.Enums; namespace RomashkiDatabase.Models; -class Post + +internal class Post { public required string Id { get; set; } = Guid.NewGuid().ToString(); public required string PostId { get; set; } public required string PostName { get; set; } public PostType PostType { get; set; } - public bool IsActual { get; set; } + public bool IsActual { get; set; } public DateTime ChangeDate { get; set; } - [ForeignKey("WorkerId")] - public List? Workers { get; set; } -} +} \ No newline at end of file diff --git a/Romashki/RomashkiDatabase/Models/Sale.cs b/Romashki/RomashkiDatabase/Models/Sale.cs index 4655618..95219d6 100644 --- a/Romashki/RomashkiDatabase/Models/Sale.cs +++ b/Romashki/RomashkiDatabase/Models/Sale.cs @@ -9,9 +9,8 @@ using RomashkiContracts.Enums; namespace RomashkiDatabase.Models; internal class Sale -{ - public required string Id { get; set; } = Guid.NewGuid().ToString(); - public string? WorkerId { get; set; } +{ public string Id { get; set; } = Guid.NewGuid().ToString(); + public required string WorkerId { get; set; } public string? BuyerId { get; set; } public DateTime SaleDate { get; set; } public double Sum { get; set; } @@ -20,8 +19,6 @@ internal class Sale public bool IsCancel { get; set; } public Worker? Worker { get; set; } public Buyer? Buyer { get; set; } - [ForeignKey("SaleId")] public List? SaleProducts { get; set; } - } diff --git a/Romashki/RomashkiDatabase/Models/SaleProduct.cs b/Romashki/RomashkiDatabase/Models/SaleProduct.cs index 2b8fa15..ec9cb5d 100644 --- a/Romashki/RomashkiDatabase/Models/SaleProduct.cs +++ b/Romashki/RomashkiDatabase/Models/SaleProduct.cs @@ -11,6 +11,6 @@ internal class SaleProduct public required string SaleId { get; set; } public required string ProductId { get; set; } public int Count { get; set; } - public double Price { get; set; } - + public Sale? Sale { get; set; } + public Product? Product { get; set; } } diff --git a/Romashki/RomashkiTests/Infrastructure/ConfigurationDatabaseTest.cs b/Romashki/RomashkiTests/Infrastructure/ConfigurationDatabaseTest.cs new file mode 100644 index 0000000..7f651f0 --- /dev/null +++ b/Romashki/RomashkiTests/Infrastructure/ConfigurationDatabaseTest.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using RomashkiContract.Infrastructure; + +namespace RomashkiTests.Infrastructure; + +internal class ConfigurationDatabaseTest : IConfigurationDatabase +{ + public string ConnectionString => "Host=127.0.0.1;Port=5432;Database=RomashkiTest;Username=postgres;Password=postgres;"; +} + diff --git a/Romashki/RomashkiTests/Infrastructure/StoragesContracts/BaseStorageContractTest.cs b/Romashki/RomashkiTests/Infrastructure/StoragesContracts/BaseStorageContractTest.cs new file mode 100644 index 0000000..db46521 --- /dev/null +++ b/Romashki/RomashkiTests/Infrastructure/StoragesContracts/BaseStorageContractTest.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using RomashkiDatabase; + + + +namespace RomashkiTests.Infrastructure.StoragesContracts; + +internal abstract class BaseStorageContractTest +{ + protected RomashkiDbContext RomashkiDbContext { get; private set; } + + [OneTimeSetUp] + public void OneTimeSetUp() + { + RomashkiDbContext = new RomashkiDbContext(new ConfigurationDatabaseTest()); + + RomashkiDbContext.Database.EnsureDeleted(); + RomashkiDbContext.Database.EnsureCreated(); + } + + [OneTimeTearDown] + public void OneTimeTearDown() + { + RomashkiDbContext.Database.EnsureDeleted(); + RomashkiDbContext.Dispose(); + } +} diff --git a/Romashki/RomashkiTests/Infrastructure/StoragesContracts/BuyerStorageContractTests.cs b/Romashki/RomashkiTests/Infrastructure/StoragesContracts/BuyerStorageContractTests.cs new file mode 100644 index 0000000..4952b91 --- /dev/null +++ b/Romashki/RomashkiTests/Infrastructure/StoragesContracts/BuyerStorageContractTests.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using RomashkiContract.Exceptions; +using RomashkiContracts.DataModels; +using RomashkiContracts.Enums; +using RomashkiDatabase.Implementations; +using RomashkiDatabase.Models; + +namespace RomashkiTests.Infrastructure.StoragesContracts; + + +[TestFixture] +internal class BuyerStorageContractTests : BaseStorageContractTest +{ + private BuyerStorageContract _buyerStorageContract; + + [SetUp] + public void SetUp() + { + _buyerStorageContract = new BuyerStorageContract(RomashkiDbContext); + } + + [TearDown] + public void TearDown() + { + RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Sales\" CASCADE;"); + RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Workers\" CASCADE;"); + RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Buyers\" CASCADE;"); + } + + [Test] + public void Try_GetList_WhenHaveRecords_Test() + { + var buyer = InsertBuyerToDatabaseAndReturn(Guid.NewGuid().ToString(), email: "test@1.com"); + InsertBuyerToDatabaseAndReturn(Guid.NewGuid().ToString(), email: "test@2.com"); + InsertBuyerToDatabaseAndReturn(Guid.NewGuid().ToString(), email: "test@3.com"); + var list = _buyerStorageContract.GetList(); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(3)); + AssertElement(list.First(x => x.Id == buyer.Id), buyer); + } + + [Test] + public void Try_GetList_WhenNoRecords_Test() + { + var list = _buyerStorageContract.GetList(); + Assert.That(list, Is.Not.Null); + Assert.That(list, Is.Empty); + } + + [Test] + public void Try_GetElementById_WhenHaveRecord_Test() + { + var buyer = InsertBuyerToDatabaseAndReturn(Guid.NewGuid().ToString()); + AssertElement(_buyerStorageContract.GetElementById(buyer.Id), buyer); + } + + [Test] + public void Try_GetElementById_WhenNoRecord_Test() + { + InsertBuyerToDatabaseAndReturn(Guid.NewGuid().ToString()); + Assert.That(() => _buyerStorageContract.GetElementById(Guid.NewGuid().ToString()), Is.Null); + } + + [Test] + public void Try_GetElementByFIO_WhenHaveRecord_Test() + { + var buyer = InsertBuyerToDatabaseAndReturn(Guid.NewGuid().ToString()); + AssertElement(_buyerStorageContract.GetElementByFIO(buyer.FIO), buyer); + } + + [Test] + public void Try_GetElementByFIO_WhenNoRecord_Test() + { + InsertBuyerToDatabaseAndReturn(Guid.NewGuid().ToString()); + Assert.That(() => _buyerStorageContract.GetElementByFIO("New Fio"), Is.Null); + } + + [Test] + public void Try_GetElementByEmail_WhenHaveRecord_Test() + { + var buyer = InsertBuyerToDatabaseAndReturn(Guid.NewGuid().ToString()); + AssertElement(_buyerStorageContract.GetElementByEmail(buyer.Email), buyer); + } + + [Test] + public void Try_GetElementByEmail_WhenNoRecord_Test() + { + InsertBuyerToDatabaseAndReturn(Guid.NewGuid().ToString()); + Assert.That(() => _buyerStorageContract.GetElementByEmail("test@4.com"), Is.Null); + } + + [Test] + public void Try_AddElement_Test() + { + var buyer = CreateModel(Guid.NewGuid().ToString()); + _buyerStorageContract.AddElement(buyer); + AssertElement(GetBuyerFromDatabase(buyer.Id), buyer); + } + + [Test] + public void Try_AddElement_WhenHaveRecordWithSameId_Test() + { + var buyer = CreateModel(Guid.NewGuid().ToString(), "New Fio", "test@1.com", 500); + InsertBuyerToDatabaseAndReturn(buyer.Id); + Assert.That(() => _buyerStorageContract.AddElement(buyer), Throws.TypeOf()); + } + + [Test] + public void Try_AddElement_WhenHaveRecordWithSameEmail_Test() + { + var buyer = CreateModel(Guid.NewGuid().ToString(), "New Fio", "test@1.com", 500); + InsertBuyerToDatabaseAndReturn(Guid.NewGuid().ToString(), email: buyer.Email); + Assert.That(() => _buyerStorageContract.AddElement(buyer), Throws.TypeOf()); + } + + [Test] + public void Try_UpdElement_Test() + { + var buyer = CreateModel(Guid.NewGuid().ToString(), "New Fio", "test@1.com", 500); + InsertBuyerToDatabaseAndReturn(buyer.Id); + _buyerStorageContract.UpdElement(buyer); + AssertElement(GetBuyerFromDatabase(buyer.Id), buyer); + } + + [Test] + public void Try_UpdElement_WhenNoRecordWithThisId_Test() + { + Assert.That(() => _buyerStorageContract.UpdElement(CreateModel(Guid.NewGuid().ToString())), Throws.TypeOf()); + } + + [Test] + public void Try_UpdElement_WhenHaveRecordWithSameEmail_Test() + { + var buyer = CreateModel(Guid.NewGuid().ToString(), "New Fio", "test@1.com", 500); + InsertBuyerToDatabaseAndReturn(buyer.Id, email: "test@3.com"); + InsertBuyerToDatabaseAndReturn(Guid.NewGuid().ToString(), email: buyer.Email); + Assert.That(() => _buyerStorageContract.UpdElement(buyer), Throws.TypeOf()); + } + + [Test] + public void Try_DelElement_Test() + { + var buyer = InsertBuyerToDatabaseAndReturn(Guid.NewGuid().ToString()); + _buyerStorageContract.DelElement(buyer.Id); + var element = GetBuyerFromDatabase(buyer.Id); + Assert.That(element, Is.Null); + } + + [Test] + public void Try_DelElement_WhenHaveSalesByThisBuyer_Test() + { + var buyer = InsertBuyerToDatabaseAndReturn(Guid.NewGuid().ToString()); + var workerId = Guid.NewGuid().ToString(); + RomashkiDbContext.Workers.Add(new Worker() { Id = workerId, FIO = "test", PostId = Guid.NewGuid().ToString() }); + RomashkiDbContext.Sales.Add(new Sale() { Id = Guid.NewGuid().ToString(), WorkerId = workerId, BuyerId = buyer.Id, Sum = 10, DiscountType = DiscountType.None, Discount = 0 }); + RomashkiDbContext.Sales.Add(new Sale() { Id = Guid.NewGuid().ToString(), WorkerId = workerId, BuyerId = buyer.Id, Sum = 10, DiscountType = DiscountType.None, Discount = 0 }); + RomashkiDbContext.SaveChanges(); + var salesBeforeDelete = RomashkiDbContext.Sales.Where(x => x.BuyerId == buyer.Id).ToArray(); + _buyerStorageContract.DelElement(buyer.Id); + var element = GetBuyerFromDatabase(buyer.Id); + var salesAfterDelete = RomashkiDbContext.Sales.Where(x => x.BuyerId == buyer.Id).ToArray(); + Assert.Multiple(() => + { + Assert.That(element, Is.Null); + Assert.That(salesBeforeDelete, Has.Length.EqualTo(2)); + Assert.That(salesAfterDelete, Is.Empty); + Assert.That(RomashkiDbContext.Sales.Count(), Is.EqualTo(2)); + }); + } + + [Test] + public void Try_DelElement_WhenNoRecordWithThisId_Test() + { + Assert.That(() => _buyerStorageContract.DelElement(Guid.NewGuid().ToString()), Throws.TypeOf()); + } + + private Buyer InsertBuyerToDatabaseAndReturn(string id, string fio = "test", string email = "test@test.com", double discountSize = 10) + { + var buyer = new Buyer() { Id = id, FIO = fio, Email = email, DiscountSize = discountSize }; + RomashkiDbContext.Buyers.Add(buyer); + RomashkiDbContext.SaveChanges(); + return buyer; + } + + private static void AssertElement(BuyerDataModel? actual, Buyer expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.Id, Is.EqualTo(expected.Id)); + Assert.That(actual.FIO, Is.EqualTo(expected.FIO)); + Assert.That(actual.Email, Is.EqualTo(expected.Email)); + Assert.That(actual.DiscountSize, Is.EqualTo(expected.DiscountSize)); + }); + } + + private static BuyerDataModel CreateModel(string id, string fio = "test", string email = "test@3.com",float totalSpend = 1000, double discountSize = 10) + => new(id, fio, email,totalSpend, discountSize); + + private Buyer? GetBuyerFromDatabase(string id) => RomashkiDbContext.Buyers.FirstOrDefault(x => x.Id == id); + + private static void AssertElement(Buyer? actual, BuyerDataModel expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.Id, Is.EqualTo(expected.Id)); + Assert.That(actual.FIO, Is.EqualTo(expected.FIO)); + Assert.That(actual.Email, Is.EqualTo(expected.Email)); + Assert.That(actual.DiscountSize, Is.EqualTo(expected.DiscountSize)); + }); + } +} \ No newline at end of file diff --git a/Romashki/RomashkiTests/Infrastructure/StoragesContracts/DiscountStorageContractTests.cs b/Romashki/RomashkiTests/Infrastructure/StoragesContracts/DiscountStorageContractTests.cs new file mode 100644 index 0000000..5f6977e --- /dev/null +++ b/Romashki/RomashkiTests/Infrastructure/StoragesContracts/DiscountStorageContractTests.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using RomashkiContract.DataModels; +using RomashkiDatabase.Implementations; +using RomashkiDatabase.Models; + +namespace RomashkiTests.Infrastructure.StoragesContracts; + +[TestFixture] +internal class DiscountStorageContractTests : BaseStorageContractTest +{ + private DiscountStorageContract _discountStorageContract; + private Buyer _buyer; + + [SetUp] + public void SetUp() + { + _discountStorageContract = new DiscountStorageContract(RomashkiDbContext); + _buyer = InsertBuyerToDatabaseAndReturn(); + } + + [TearDown] + public void TearDown() + { + RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Discounts\" CASCADE;"); + RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Buyers\" CASCADE;"); + } + + [Test] + public void Try_GetList_WhenHaveRecords_Test() + { + var discount = InsertDiscountToDatabaseAndReturn(_buyer.Id, discountSize: 10); + InsertDiscountToDatabaseAndReturn(_buyer.Id); + InsertDiscountToDatabaseAndReturn(_buyer.Id); + var list = _discountStorageContract.GetList(DateTime.UtcNow.AddDays(-10), DateTime.UtcNow.AddDays(10)); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(3)); + AssertElement(list.First(), discount); + } + + [Test] + public void Try_GetList_WhenNoRecords_Test() + { + var list = _discountStorageContract.GetList(DateTime.UtcNow.AddDays(-10), DateTime.UtcNow.AddDays(10)); + Assert.That(list, Is.Not.Null); + Assert.That(list, Is.Empty); + } + + [Test] + public void Try_GetList_OnlyInDatePeriod_Test() + { + InsertDiscountToDatabaseAndReturn(_buyer.Id, discountDate: DateTime.UtcNow.AddDays(-2)); + InsertDiscountToDatabaseAndReturn(_buyer.Id, discountDate: DateTime.UtcNow.AddDays(-1).AddMinutes(-5)); + InsertDiscountToDatabaseAndReturn(_buyer.Id, discountDate: DateTime.UtcNow.AddDays(-1).AddMinutes(5)); + InsertDiscountToDatabaseAndReturn(_buyer.Id, discountDate: DateTime.UtcNow.AddDays(1).AddMinutes(-5)); + InsertDiscountToDatabaseAndReturn(_buyer.Id, discountDate: DateTime.UtcNow.AddDays(1).AddMinutes(5)); + InsertDiscountToDatabaseAndReturn(_buyer.Id, discountDate: DateTime.UtcNow.AddDays(-2)); + var list = _discountStorageContract.GetList(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow.AddDays(1)); + Assert.That(list, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(list, Has.Count.EqualTo(2)); + }); + } + + [Test] + public void Try_GetList_ByBuyer_Test() + { + var buyer = InsertBuyerToDatabaseAndReturn("name 2"); + InsertDiscountToDatabaseAndReturn(_buyer.Id); + InsertDiscountToDatabaseAndReturn(_buyer.Id); + InsertDiscountToDatabaseAndReturn(buyer.Id); + var list = _discountStorageContract.GetList(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow.AddDays(1), _buyer.Id); + Assert.That(list, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(list, Has.Count.EqualTo(2)); + Assert.That(list.All(x => x.BuyerId == _buyer.Id)); + }); + } + + [Test] + public void Try_GetList_ByBuyerOnlyInDatePeriod_Test() + { + var buyer = InsertBuyerToDatabaseAndReturn("name 2"); + InsertDiscountToDatabaseAndReturn(_buyer.Id, discountDate: DateTime.UtcNow.AddDays(-2)); + InsertDiscountToDatabaseAndReturn(_buyer.Id, discountDate: DateTime.UtcNow.AddDays(-1).AddMinutes(5)); + InsertDiscountToDatabaseAndReturn(buyer.Id, discountDate: DateTime.UtcNow.AddDays(-1).AddMinutes(5)); + InsertDiscountToDatabaseAndReturn(_buyer.Id, discountDate: DateTime.UtcNow.AddDays(1).AddMinutes(-5)); + InsertDiscountToDatabaseAndReturn(buyer.Id, discountDate: DateTime.UtcNow.AddDays(1).AddMinutes(-5)); + InsertDiscountToDatabaseAndReturn(_buyer.Id, discountDate: DateTime.UtcNow.AddDays(-2)); + var list = _discountStorageContract.GetList(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow.AddDays(1), _buyer.Id); + Assert.That(list, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(list, Has.Count.EqualTo(2)); + Assert.That(list.All(x => x.BuyerId == _buyer.Id)); + }); + } + + [Test] + public void Try_AddElement_Test() + { + var discount = CreateModel(_buyer.Id); + _discountStorageContract.AddElement(discount); + AssertElement(GetDiscountFromDatabaseByBuyerId(_buyer.Id), discount); + } + + private Buyer InsertBuyerToDatabaseAndReturn(string buyerFIO = "fio") + { + var buyer = new Buyer() { Id = Guid.NewGuid().ToString(), FIO = buyerFIO,Email = $"test_{Guid.NewGuid()}@example.com" }; + RomashkiDbContext.Buyers.Add(buyer); + RomashkiDbContext.SaveChanges(); + return buyer; + } + + private Discount InsertDiscountToDatabaseAndReturn(string buyerId, double discountSize = 1, DateTime? discountDate = null) + { + var discount = new Discount() { BuyerId = buyerId, DiscountSize = discountSize, DiscountDate = discountDate ?? DateTime.UtcNow }; + RomashkiDbContext.Discounts.Add(discount); + RomashkiDbContext.SaveChanges(); + return discount; + } + + private static void AssertElement(DiscountDataModel? actual, Discount expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.BuyerId, Is.EqualTo(expected.BuyerId)); + Assert.That(actual.DiscountSize, Is.EqualTo(expected.DiscountSize)); + }); + } + + private static DiscountDataModel CreateModel(string buyerId, double buyerDiscount = 1, DateTime? discountDate = null) + => new(buyerId, discountDate ?? DateTime.UtcNow, buyerDiscount); + + private Discount? GetDiscountFromDatabaseByBuyerId(string id) => RomashkiDbContext.Discounts.FirstOrDefault(x => x.BuyerId == id); + + private static void AssertElement(Discount? actual, DiscountDataModel expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.BuyerId, Is.EqualTo(expected.BuyerId)); + Assert.That(actual.DiscountSize, Is.EqualTo(expected.DiscountSize)); + }); + } +} diff --git a/Romashki/RomashkiTests/Infrastructure/StoragesContracts/PostStorageContractTests.cs b/Romashki/RomashkiTests/Infrastructure/StoragesContracts/PostStorageContractTests.cs new file mode 100644 index 0000000..41ef460 --- /dev/null +++ b/Romashki/RomashkiTests/Infrastructure/StoragesContracts/PostStorageContractTests.cs @@ -0,0 +1,323 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using RomashkiContract.Exceptions; +using RomashkiContracts.DataModels; +using RomashkiContracts.Enums; +using RomashkiDatabase.Implementations; +using RomashkiDatabase.Models; + +namespace RomashkiTests.Infrastructure.StoragesContracts; + + +[TestFixture] +internal class PostStorageContractTests : BaseStorageContractTest +{ + private PostStorageContract _postStorageContract; + + [SetUp] + public void SetUp() + { + _postStorageContract = new PostStorageContract(RomashkiDbContext); + } + + [TearDown] + public void TearDown() + { + RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Posts\" CASCADE;"); + } + + [Test] + public void Try_GetList_WhenHaveRecords_Test() + { + var post = InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 1"); + InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 2"); + InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 3"); + var list = _postStorageContract.GetList(); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(3)); + AssertElement(list.First(x => x.Id == post.PostId), post); + } + + [Test] + public void Try_GetList_WhenNoRecords_Test() + { + var list = _postStorageContract.GetList(); + Assert.That(list, Is.Not.Null); + Assert.That(list, Is.Empty); + } + + [Test] + public void Try_GetList_OnlyActual_Test() + { + InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 1", isActual: true); + InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 2", isActual: true); + InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 3", isActual: false); + var list = _postStorageContract.GetList(onlyActual: true); + Assert.That(list, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(list, Has.Count.EqualTo(2)); + Assert.That(!list.Any(x => !x.IsActual)); + }); + } + + [Test] + public void Try_GetList_IncludeNoActual_Test() + { + InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 1", isActual: true); + InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 2", isActual: true); + InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 3", isActual: false); + var list = _postStorageContract.GetList(onlyActual: false); + Assert.That(list, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(list, Has.Count.EqualTo(3)); + Assert.That(list.Count(x => x.IsActual), Is.EqualTo(2)); + Assert.That(list.Count(x => !x.IsActual), Is.EqualTo(1)); + }); + } + + [Test] + public void Try_GetPostWithHistory_WhenHaveRecords_Test() + { + var postId = Guid.NewGuid().ToString(); + InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 1", isActual: true); + InsertPostToDatabaseAndReturn(postId, "name 2", isActual: true); + InsertPostToDatabaseAndReturn(postId, "name 2", isActual: false); + var list = _postStorageContract.GetPostWithHistory(postId); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(2)); + } + + [Test] + public void Try_GetPostWithHistory_WhenNoRecords_Test() + { + var postId = Guid.NewGuid().ToString(); + InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 1", isActual: true); + InsertPostToDatabaseAndReturn(postId, "name 2", isActual: true); + InsertPostToDatabaseAndReturn(postId, "name 2", isActual: false); + var list = _postStorageContract.GetPostWithHistory(Guid.NewGuid().ToString()); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(0)); + } + + [Test] + public void Try_GetElementById_WhenHaveRecord_Test() + { + var post = InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString()); + AssertElement(_postStorageContract.GetElementById(post.PostId), post); + } + + + [Test] + public void Try_GetElementById_WhenNoRecord_Test() + { + InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString()); + Assert.That(() => _postStorageContract.GetElementById(Guid.NewGuid().ToString()), Is.Null); + } + + [Test] + public void Try_GetElementById_WhenRecordHasDeleted_Test() + { + var post = InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString(), isActual: false); + Assert.That(() => _postStorageContract.GetElementById(post.PostId), Is.Null); + } + + [Test] + public void Try_GetElementById_WhenTrySearchById_Test() + { + var post = InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString()); + Assert.That(() => _postStorageContract.GetElementById(post.Id), Is.Null); + } + + [Test] + public void Try_GetElementByName_WhenHaveRecord_Test() + { + var post = InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString()); + AssertElement(_postStorageContract.GetElementByName(post.PostName), post); + } + + [Test] + public void Try_GetElementByName_WhenNoRecord_Test() + { + InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString()); + Assert.That(() => _postStorageContract.GetElementByName("name"), Is.Null); + } + + [Test] + public void Try_GetElementByName_WhenRecordHasDeleted_Test() + { + var post = InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString(), isActual: false); + Assert.That(() => _postStorageContract.GetElementById(post.PostName), Is.Null); + } + + [Test] + public void Try_AddElement_Test() + { + var post = CreateModel(Guid.NewGuid().ToString(), isActual: true); + _postStorageContract.AddElement(post); + AssertElement(GetPostFromDatabaseByPostId(post.Id), post); + } + + [Test] + public void Try_AddElement_WhenActualIsFalse_Test() + { + var post = CreateModel(Guid.NewGuid().ToString(), isActual: false); + Assert.That(() => _postStorageContract.AddElement(post), Throws.Nothing); + AssertElement(GetPostFromDatabaseByPostId(post.Id), CreateModel(post.Id, isActual: true)); + } + + [Test] + public void Try_AddElement_WhenHaveRecordWithSameName_Test() + { + var post = CreateModel(Guid.NewGuid().ToString(), "name unique", isActual: true); + InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString(), postName: post.PostName, isActual: true); + Assert.That(() => _postStorageContract.AddElement(post), Throws.TypeOf()); + } + + [Test] + public void Try_AddElement_WhenHaveRecordWithSamePostIdAndActualIsTrue_Test() + { + var post = CreateModel(Guid.NewGuid().ToString(), isActual: true); + InsertPostToDatabaseAndReturn(post.Id, isActual: true); + Assert.That(() => _postStorageContract.AddElement(post), Throws.TypeOf()); + } + + [Test] + public void Try_UpdElement_Test() + { + var post = CreateModel(Guid.NewGuid().ToString()); + InsertPostToDatabaseAndReturn(post.Id, isActual: true); + _postStorageContract.UpdElement(post); + var posts = RomashkiDbContext.Posts.Where(x => x.PostId == post.Id).OrderByDescending(x => x.ChangeDate); + Assert.That(posts.Count(), Is.EqualTo(2)); + AssertElement(posts.First(), CreateModel(post.Id, isActual: true)); + AssertElement(posts.Last(), CreateModel(post.Id, isActual: false)); + } + + [Test] + public void Try_UpdElement_WhenActualIsFalse_Test() + { + var post = CreateModel(Guid.NewGuid().ToString(), isActual: false); + InsertPostToDatabaseAndReturn(post.Id, isActual: true); + _postStorageContract.UpdElement(post); + AssertElement(GetPostFromDatabaseByPostId(post.Id), CreateModel(post.Id, isActual: true)); + } + + [Test] + public void Try_UpdElement_WhenNoRecordWithThisId_Test() + { + Assert.That(() => _postStorageContract.UpdElement(CreateModel(Guid.NewGuid().ToString())), Throws.TypeOf()); + } + + [Test] + public void Try_UpdElement_WhenHaveRecordWithSameName_Test() + { + var post = CreateModel(Guid.NewGuid().ToString(), "New Name"); + InsertPostToDatabaseAndReturn(post.Id, postName: "name"); + InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString(), postName: post.PostName); + Assert.That(() => _postStorageContract.UpdElement(post), Throws.TypeOf()); + } + + [Test] + public void Try_UpdElement_WhenRecordWasDeleted_Test() + { + var post = CreateModel(Guid.NewGuid().ToString()); + InsertPostToDatabaseAndReturn(post.Id, isActual: false); + Assert.That(() => _postStorageContract.UpdElement(post), Throws.TypeOf()); + } + + [Test] + public void Try_DelElement_Test() + { + var post = InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString(), isActual: true); + _postStorageContract.DelElement(post.PostId); + var element = GetPostFromDatabaseByPostId(post.PostId); + Assert.Multiple(() => + { + Assert.That(element, Is.Not.Null); + Assert.That(!element!.IsActual); + }); + } + + [Test] + public void Try_DelElement_WhenNoRecordWithThisId_Test() + { + Assert.That(() => _postStorageContract.DelElement(Guid.NewGuid().ToString()), Throws.TypeOf()); + } + + [Test] + public void Try_DelElement_WhenRecordWasDeleted_Test() + { + var post = InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString(), isActual: false); + Assert.That(() => _postStorageContract.DelElement(post.PostId), Throws.TypeOf()); + } + + [Test] + public void Try_ResElement_Test() + { + var post = InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString(), isActual: false); + _postStorageContract.ResElement(post.PostId); + var element = GetPostFromDatabaseByPostId(post.PostId); + Assert.Multiple(() => + { + Assert.That(element, Is.Not.Null); + Assert.That(element!.IsActual); + }); + } + + [Test] + public void Try_ResElement_WhenNoRecordWithThisId_Test() + { + Assert.That(() => _postStorageContract.ResElement(Guid.NewGuid().ToString()), Throws.TypeOf()); + } + + [Test] + public void Try_ResElement_WhenRecordNotWasDeleted_Test() + { + var post = InsertPostToDatabaseAndReturn(Guid.NewGuid().ToString(), isActual: true); + Assert.That(() => _postStorageContract.ResElement(post.PostId), Throws.Nothing); + } + + private Post InsertPostToDatabaseAndReturn(string id, string postName = "test", PostType postType = PostType.Assistant, bool isActual = true, DateTime? changeDate = null) + { + var post = new Post() { Id = Guid.NewGuid().ToString(), PostId = id, PostName = postName, PostType = postType, IsActual = isActual, ChangeDate = changeDate ?? DateTime.UtcNow }; + RomashkiDbContext.Posts.Add(post); + RomashkiDbContext.SaveChanges(); + return post; + } + + private static void AssertElement(PostDataModel? actual, Post expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.Id, Is.EqualTo(expected.PostId)); + Assert.That(actual.PostName, Is.EqualTo(expected.PostName)); + Assert.That(actual.PostType, Is.EqualTo(expected.PostType)); + Assert.That(actual.IsActual, Is.EqualTo(expected.IsActual)); + }); + } + //postId "8728ff2c-a826-45fa-92d1-007ef93eb2d4" + // id "9fe88fd4-67c7-4ff3-a86b-a35f28a8fce2" + private static PostDataModel CreateModel(string postId, string postName = "test", PostType postType = PostType.Assistant, bool isActual = false, DateTime? changeDate = null) + => new(postId, postName, postType, isActual, changeDate ?? DateTime.UtcNow); + + private Post? GetPostFromDatabaseByPostId(string id) => RomashkiDbContext.Posts.Where(x => x.PostId == id).OrderByDescending(x => x.ChangeDate).FirstOrDefault(); + + private static void AssertElement(Post? actual, PostDataModel expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.PostId, Is.EqualTo(expected.Id)); + Assert.That(actual.PostName, Is.EqualTo(expected.PostName)); + Assert.That(actual.PostType, Is.EqualTo(expected.PostType)); + Assert.That(actual.IsActual, Is.EqualTo(expected.IsActual)); + }); + } +} diff --git a/Romashki/RomashkiTests/Infrastructure/StoragesContracts/ProductStorageContractTests.cs b/Romashki/RomashkiTests/Infrastructure/StoragesContracts/ProductStorageContractTests.cs new file mode 100644 index 0000000..357c424 --- /dev/null +++ b/Romashki/RomashkiTests/Infrastructure/StoragesContracts/ProductStorageContractTests.cs @@ -0,0 +1,315 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using RomashkiContract.Exceptions; +using RomashkiContracts.DataModels; +using RomashkiContracts.Enums; +using RomashkiDatabase.Implementations; +using RomashkiDatabase.Models; + +namespace RomashkiTests.Infrastructure.StoragesContracts; + + +[TestFixture] +internal class ProductStorageContractTests : BaseStorageContractTest +{ + private ProductStorageContract _productStorageContract; + + [SetUp] + public void SetUp() + { + _productStorageContract = new ProductStorageContract(RomashkiDbContext); + } + + [TearDown] + public void TearDown() + { + RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Products\" CASCADE;"); + } + + [Test] + public void Try_GetList_WhenHaveRecords_Test() + { + var product = InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 1"); + InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 2"); + InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 3"); + var list = _productStorageContract.GetList(); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(3)); + AssertElement(list.First(x => x.Id == product.Id), product); + } + + [Test] + public void Try_GetList_WhenNoRecords_Test() + { + var list = _productStorageContract.GetList(); + Assert.That(list, Is.Not.Null); + Assert.That(list, Is.Empty); + } + + [Test] + public void Try_GetList_OnlyActual_Test() + { + InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 1", isDeleted: true); + InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 2", isDeleted: false); + InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 3", isDeleted: false); + var list = _productStorageContract.GetList(onlyActive: true); + Assert.That(list, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(list, Has.Count.EqualTo(2)); + Assert.That(!list.Any(x => x.IsDeleted)); + }); + } + + [Test] + public void Try_GetList_IncludeNoActual_Test() + { + InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 1", isDeleted: true); + InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 2", isDeleted: true); + InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 3", isDeleted: false); + var list = _productStorageContract.GetList(onlyActive: false); + Assert.That(list, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(list, Has.Count.EqualTo(3)); + Assert.That(list.Count(x => x.IsDeleted), Is.EqualTo(2)); + Assert.That(list.Count(x => !x.IsDeleted), Is.EqualTo(1)); + }); + } + + + + [Test] + public void Try_GetHistoryByProductId_WhenHaveRecords_Test() + { + var product = InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 1"); + InsertProductHistoryToDatabaseAndReturn(product.Id, 20, DateTime.UtcNow.AddDays(-1)); + InsertProductHistoryToDatabaseAndReturn(product.Id, 30, DateTime.UtcNow.AddMinutes(-10)); + InsertProductHistoryToDatabaseAndReturn(product.Id, 40, DateTime.UtcNow.AddDays(1)); + var list = _productStorageContract.GetHistoryByProductId(product.Id); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(3)); + } + + [Test] + public void Try_GetHistoryByProductId_WhenNoRecords_Test() + { + var product = InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), "name 1"); + InsertProductHistoryToDatabaseAndReturn(product.Id, 20, DateTime.UtcNow.AddDays(-1)); + InsertProductHistoryToDatabaseAndReturn(product.Id, 30, DateTime.UtcNow.AddMinutes(-10)); + InsertProductHistoryToDatabaseAndReturn(product.Id, 40, DateTime.UtcNow.AddDays(1)); + var list = _productStorageContract.GetHistoryByProductId(Guid.NewGuid().ToString()); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(0)); + } + + [Test] + public void Try_GetElementById_WhenHaveRecord_Test() + { + var product = InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString()); + AssertElement(_productStorageContract.GetElementById(product.Id), product); + } + + [Test] + public void Try_GetElementById_WhenNoRecord_Test() + { + InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString()); + Assert.That(() => _productStorageContract.GetElementById(Guid.NewGuid().ToString()), Is.Null); + } + + [Test] + public void Try_GetElementById_WhenRecordHasDeleted_Test() + { + var product = InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), isDeleted: true); + Assert.That(() => _productStorageContract.GetElementById(product.Id), Is.Null); + } + + [Test] + public void Try_GetElementByName_WhenHaveRecord_Test() + { + var product = InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString()); + AssertElement(_productStorageContract.GetElementByName(product.ProductName), product); + } + + [Test] + public void Try_GetElementByName_WhenNoRecord_Test() + { + InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString()); + Assert.That(() => _productStorageContract.GetElementByName("name"), Is.Null); + } + + [Test] + public void Try_GetElementByName_WhenRecordHasDeleted_Test() + { + var product = InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), isDeleted: true); + Assert.That(() => _productStorageContract.GetElementById(product.ProductName), Is.Null); + } + + [Test] + public void Try_AddElement_Test() + { + var product = CreateModel(Guid.NewGuid().ToString(), isDeleted: false); + _productStorageContract.AddElement(product); + AssertElement(GetProductFromDatabaseById(product.Id), product); + } + + [Test] + public void Try_AddElement_WhenIsDeletedIsTrue_Test() + { + var product = CreateModel(Guid.NewGuid().ToString(), isDeleted: true); + Assert.That(() => _productStorageContract.AddElement(product), Throws.Nothing); + AssertElement(GetProductFromDatabaseById(product.Id), CreateModel(product.Id, isDeleted: false)); + } + + [Test] + public void Try_AddElement_WhenHaveRecordWithSameId_Test() + { + var product = CreateModel(Guid.NewGuid().ToString()); + InsertProductToDatabaseAndReturn(product.Id, productName: "name unique"); + Assert.That(() => _productStorageContract.AddElement(product), Throws.TypeOf()); + } + + [Test] + public void Try_AddElement_WhenHaveRecordWithSameName_Test() + { + var product = CreateModel(Guid.NewGuid().ToString(), "name unique", isDeleted: false); + InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), productName: product.ProductName, isDeleted: false); + Assert.That(() => _productStorageContract.AddElement(product), Throws.TypeOf()); + } + + [Test] + public void Try_AddElement_WhenHaveRecordWithSameNameButOneWasDeleted_Test() + { + var product = CreateModel(Guid.NewGuid().ToString(), "name unique", isDeleted: false); + InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), productName: product.ProductName, isDeleted: true); + Assert.That(() => _productStorageContract.AddElement(product), Throws.Nothing); + } + + [Test] + public void Try_UpdElement_Test() + { + var product = CreateModel(Guid.NewGuid().ToString(), isDeleted: false); + InsertProductToDatabaseAndReturn(product.Id, isDeleted: false); + _productStorageContract.UpdElement(product); + AssertElement(GetProductFromDatabaseById(product.Id), product); + } + + [Test] + public void Try_UpdElement_WhenIsDeletedIsTrue_Test() + { + var product = CreateModel(Guid.NewGuid().ToString(), isDeleted: true); + InsertProductToDatabaseAndReturn(product.Id, isDeleted: false); + _productStorageContract.UpdElement(product); + AssertElement(GetProductFromDatabaseById(product.Id), CreateModel(product.Id, isDeleted: false)); + } + + [Test] + public void Try_UpdElement_WhenNoRecordWithThisId_Test() + { + Assert.That(() => _productStorageContract.UpdElement(CreateModel(Guid.NewGuid().ToString())), Throws.TypeOf()); + } + + [Test] + public void Try_UpdElement_WhenHaveRecordWithSameName_Test() + { + var product = CreateModel(Guid.NewGuid().ToString(), "name unique", isDeleted: false); + InsertProductToDatabaseAndReturn(product.Id, productName: "name"); + InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), productName: product.ProductName); + Assert.That(() => _productStorageContract.UpdElement(product), Throws.TypeOf()); + } + + [Test] + public void Try_UpdElement_WhenHaveRecordWithSameNameButOneWasDeleted_Test() + { + var product = CreateModel(Guid.NewGuid().ToString(), "name unique", isDeleted: false); + InsertProductToDatabaseAndReturn(product.Id, productName: "name"); + InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), productName: product.ProductName, isDeleted: true); + Assert.That(() => _productStorageContract.UpdElement(product), Throws.Nothing); + } + + [Test] + public void Try_UpdElement_WhenRecordWasDeleted_Test() + { + var product = CreateModel(Guid.NewGuid().ToString()); + InsertProductToDatabaseAndReturn(product.Id, isDeleted: true); + Assert.That(() => _productStorageContract.UpdElement(product), Throws.TypeOf()); + } + + [Test] + public void Try_DelElement_Test() + { + var product = InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), isDeleted: false); + _productStorageContract.DelElement(product.Id); + var element = GetProductFromDatabaseById(product.Id); + Assert.Multiple(() => + { + Assert.That(element, Is.Not.Null); + Assert.That(element!.IsDeleted); + }); + } + + [Test] + public void Try_DelElement_WhenNoRecordWithThisId_Test() + { + Assert.That(() => _productStorageContract.DelElement(Guid.NewGuid().ToString()), Throws.TypeOf()); + } + + [Test] + public void Try_DelElement_WhenRecordWasDeleted_Test() + { + var product = InsertProductToDatabaseAndReturn(Guid.NewGuid().ToString(), isDeleted: true); + Assert.That(() => _productStorageContract.DelElement(product.Id), Throws.TypeOf()); + } + + + private Product InsertProductToDatabaseAndReturn(string id, string productName = "test", ProductType productType = ProductType.Flower, double price = 1, bool isDeleted = false) + { + var product = new Product() { Id = id, ProductName = productName, ProductType = productType, Price = price, IsDeleted = isDeleted }; + RomashkiDbContext.Products.Add(product); + RomashkiDbContext.SaveChanges(); + return product; + } + + private ProductHistory InsertProductHistoryToDatabaseAndReturn(string productId, double price, DateTime changeDate) + { + var productHistory = new ProductHistory() { Id = Guid.NewGuid().ToString(), ProductId = productId, OldPrice = price, ChangeDate = changeDate }; + RomashkiDbContext.ProductHistories.Add(productHistory); + RomashkiDbContext.SaveChanges(); + return productHistory; + } + + private static void AssertElement(ProductDataModel? actual, Product expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.Id, Is.EqualTo(expected.Id)); + Assert.That(actual.ProductName, Is.EqualTo(expected.ProductName)); + Assert.That(actual.ProductType, Is.EqualTo(expected.ProductType)); + Assert.That(actual.Price, Is.EqualTo(expected.Price)); + Assert.That(actual.IsDeleted, Is.EqualTo(expected.IsDeleted)); + }); + } + + private static ProductDataModel CreateModel(string id, string productName = "test", ProductType productType = ProductType.Flower, double price = 1, bool isDeleted = false) + => new(id, productName, productType, price, isDeleted); + + private Product? GetProductFromDatabaseById(string id) => RomashkiDbContext.Products.FirstOrDefault(x => x.Id == id); + + private static void AssertElement(Product? actual, ProductDataModel expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.Id, Is.EqualTo(expected.Id)); + Assert.That(actual.ProductName, Is.EqualTo(expected.ProductName)); + Assert.That(actual.ProductType, Is.EqualTo(expected.ProductType)); + Assert.That(actual.Price, Is.EqualTo(expected.Price)); + Assert.That(actual.IsDeleted, Is.EqualTo(expected.IsDeleted)); + }); + } +} diff --git a/Romashki/RomashkiTests/Infrastructure/StoragesContracts/SaleStorageContractTests.cs b/Romashki/RomashkiTests/Infrastructure/StoragesContracts/SaleStorageContractTests.cs new file mode 100644 index 0000000..4f5a1bd --- /dev/null +++ b/Romashki/RomashkiTests/Infrastructure/StoragesContracts/SaleStorageContractTests.cs @@ -0,0 +1,308 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using RomashkiContract.Exceptions; +using RomashkiContracts.DataModels; +using RomashkiContracts.Enums; +using RomashkiDatabase.Implementations; +using RomashkiDatabase.Models; + +namespace RomashkiTests.Infrastructure.StoragesContracts; + +[TestFixture] +internal class SaleStorageContractTests : BaseStorageContractTest +{ + private SaleStorageContract _saletStorageContract; + private Buyer _buyer; + private Worker _worker; + private Product _product; + + +[SetUp] +public void SetUp() + { + _saletStorageContract = new SaleStorageContract(RomashkiDbContext); + _buyer = InsertBuyerToDatabaseAndReturn(); + _worker = InsertWorkerToDatabaseAndReturn(); + _product = InsertProductToDatabaseAndReturn(); + } + + + [TearDown] + public void TearDown() + { + RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Sales\" CASCADE;"); + RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Buyers\" CASCADE;"); + RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Workers\" CASCADE;"); + RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Products\" CASCADE;"); + } + + [Test] + public void Try_GetList_WhenHaveRecords_Test() + { + var sale = InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)]); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 5)]); + InsertSaleToDatabaseAndReturn(_worker.Id, null, products: [(_product.Id, 10)]); + var list = _saletStorageContract.GetList(); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(3)); + AssertElement(list.First(x => x.Id == sale.Id), sale); + } + + [Test] + public void Try_GetList_WhenNoRecords_Test() + { + var list = _saletStorageContract.GetList(); + Assert.That(list, Is.Not.Null); + Assert.That(list, Is.Empty); + } + + [Test] + public void Try_GetList_ByPeriod_Test() + { + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, saleDate: DateTime.UtcNow.AddDays(-1).AddMinutes(-3), products: [(_product.Id, 1)]); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, saleDate: DateTime.UtcNow.AddDays(-1).AddMinutes(3), products: [(_product.Id, 1)]); + InsertSaleToDatabaseAndReturn(_worker.Id, null, saleDate: DateTime.UtcNow.AddDays(1).AddMinutes(-3), products: [(_product.Id, 1)]); + InsertSaleToDatabaseAndReturn(_worker.Id, null, saleDate: DateTime.UtcNow.AddDays(1).AddMinutes(3), products: [(_product.Id, 1)]); + var list = _saletStorageContract.GetList(startDate: DateTime.UtcNow.AddDays(-1), endDate: DateTime.UtcNow.AddDays(1)); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(2)); + } + + [Test] + public void Try_GetList_ByWorkerId_Test() + { + var worker = InsertWorkerToDatabaseAndReturn("Other worker"); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)]); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)]); + InsertSaleToDatabaseAndReturn(worker.Id, null, products: [(_product.Id, 1)]); + var list = _saletStorageContract.GetList(workerId: _worker.Id); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(2)); + Assert.That(list.All(x => x.WorkerId == _worker.Id)); + } + + [Test] + public void Try_GetList_ByBuyerId_Test() + { + var buyer = InsertBuyerToDatabaseAndReturn("Other fio", "+8-888-888-88-88"); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)]); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)]); + InsertSaleToDatabaseAndReturn(_worker.Id, buyer.Id, products: [(_product.Id, 1)]); + InsertSaleToDatabaseAndReturn(_worker.Id, null, products: [(_product.Id, 1)]); + var list = _saletStorageContract.GetList(buyerId: _buyer.Id); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(2)); + Assert.That(list.All(x => x.BuyerId == _buyer.Id)); + } + + [Test] + public void Try_GetList_ByProductId_Test() + { + var product = InsertProductToDatabaseAndReturn("Other name"); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 5)]); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1), (product.Id, 4)]); + InsertSaleToDatabaseAndReturn(_worker.Id, null, products: [(product.Id, 1)]); + InsertSaleToDatabaseAndReturn(_worker.Id, null, products: [(product.Id, 1), (_product.Id, 1)]); + var list = _saletStorageContract.GetList(productId: _product.Id); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(3)); + Assert.That(list.All(x => x.Products.Any(y => y.ProductId == _product.Id))); + } + + [Test] + public void Try_GetList_ByAllParameters_Test() + { + var worker = InsertWorkerToDatabaseAndReturn("Other worker"); + var buyer = InsertBuyerToDatabaseAndReturn("Other fio", "+8-888-888-88-88"); + var product = InsertProductToDatabaseAndReturn("Other name"); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, saleDate: DateTime.UtcNow.AddDays(-1).AddMinutes(-3), products: [(_product.Id, 1)]); + InsertSaleToDatabaseAndReturn(worker.Id, null, saleDate: DateTime.UtcNow.AddDays(-1).AddMinutes(3), products: [(_product.Id, 1)]); + InsertSaleToDatabaseAndReturn(worker.Id, _buyer.Id, saleDate: DateTime.UtcNow.AddDays(-1).AddMinutes(3), products: [(_product.Id, 1)]); + InsertSaleToDatabaseAndReturn(worker.Id, _buyer.Id, saleDate: DateTime.UtcNow.AddDays(-1).AddMinutes(3), products: [(product.Id, 1)]); + InsertSaleToDatabaseAndReturn(_worker.Id, buyer.Id, saleDate: DateTime.UtcNow.AddDays(1).AddMinutes(-3), products: [(_product.Id, 1)]); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, saleDate: DateTime.UtcNow.AddDays(1).AddMinutes(-3), products: [(product.Id, 1)]); + InsertSaleToDatabaseAndReturn(worker.Id, null, saleDate: DateTime.UtcNow.AddDays(1).AddMinutes(-3), products: [(_product.Id, 1)]); + var list = _saletStorageContract.GetList(startDate: DateTime.UtcNow.AddDays(-1), endDate: DateTime.UtcNow.AddDays(1), workerId: _worker.Id, buyerId: _buyer.Id, productId: product.Id); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(1)); + } + + [Test] + public void Try_GetElementById_WhenHaveRecord_Test() + { + var sale = InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)]); + AssertElement(_saletStorageContract.GetElementById(sale.Id), sale); + } + + [Test] + public void Try_GetElementById_WhenNoRecord_Test() + { + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)]); + Assert.That(() => _saletStorageContract.GetElementById(Guid.NewGuid().ToString()), Is.Null); + } + + [Test] + public void Try_GetElementById_WhenRecordHasCanceled_Test() + { + var sale = InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)], isCancel: true); + AssertElement(_saletStorageContract.GetElementById(sale.Id), sale); + } + + [Test] + public void Try_AddElement_Test() + { + var sale = CreateModel(Guid.NewGuid().ToString(), _worker.Id, _buyer.Id, 1, DiscountType.RegularCustomer, 1, false, [_product.Id]); + _saletStorageContract.AddElement(sale); + AssertElement(GetSaleFromDatabaseById(sale.Id), sale); + } + + [Test] + public void Try_AddElement_WhenIsDeletedIsTrue_Test() + { + var sale = CreateModel(Guid.NewGuid().ToString(), _worker.Id, _buyer.Id, 1, DiscountType.RegularCustomer, 1, true, [_product.Id]); + Assert.That(() => _saletStorageContract.AddElement(sale), Throws.Nothing); + AssertElement(GetSaleFromDatabaseById(sale.Id), CreateModel(sale.Id, _worker.Id, _buyer.Id, 1, DiscountType.RegularCustomer, 1, false, [_product.Id])); + } + + [Test] + public void Try_DelElement_Test() + { + var sale = InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)], isCancel: false); + _saletStorageContract.DelElement(sale.Id); + var element = GetSaleFromDatabaseById(sale.Id); + Assert.Multiple(() => + { + Assert.That(element, Is.Not.Null); + Assert.That(element!.IsCancel); + }); + } + + [Test] + public void Try_DelElement_WhenNoRecordWithThisId_Test() + { + Assert.That(() => _saletStorageContract.DelElement(Guid.NewGuid().ToString()), Throws.TypeOf()); + } + + [Test] + public void Try_DelElement_WhenRecordWasCanceled_Test() + { + var sale = InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)], isCancel: true); + Assert.That(() => _saletStorageContract.DelElement(sale.Id), Throws.TypeOf()); + } + + private Buyer InsertBuyerToDatabaseAndReturn(string fio = "test", string email = "email@q.e") + { + var buyer = new Buyer() { Id = Guid.NewGuid().ToString(), FIO = fio, Email = email, DiscountSize = 10 }; + RomashkiDbContext.Buyers.Add(buyer); + RomashkiDbContext.SaveChanges(); + return buyer; + } + + private Worker InsertWorkerToDatabaseAndReturn(string fio = "test") + { + var worker = new Worker() { Id = Guid.NewGuid().ToString(), FIO = fio, PostId = Guid.NewGuid().ToString() }; + RomashkiDbContext.Workers.Add(worker); + RomashkiDbContext.SaveChanges(); + return worker; + } + + + private Product InsertProductToDatabaseAndReturn(string productName = "test", ProductType productType = ProductType.Flower, double price = 1, bool isDeleted = false) + { + var product = new Product() { Id = Guid.NewGuid().ToString(), ProductName = productName, ProductType = productType, Price = price, IsDeleted = isDeleted }; + RomashkiDbContext.Products.Add(product); + RomashkiDbContext.SaveChanges(); + return product; + } + + private Sale InsertSaleToDatabaseAndReturn(string workerId, string? buyerId, DateTime? saleDate = null, double sum = 1, DiscountType discountType = DiscountType.OnSale, double discount = 0, bool isCancel = false, List<(string, int)>? products = null) + { + var sale = new Sale() { WorkerId = workerId, BuyerId = buyerId, SaleDate = saleDate ?? DateTime.UtcNow, Sum = sum, DiscountType = discountType, Discount = discount, IsCancel = isCancel, SaleProducts = [] }; + if (products is not null) + { + foreach (var elem in products) + { + sale.SaleProducts.Add(new SaleProduct { ProductId = elem.Item1, SaleId = sale.Id, Count = elem.Item2 }); + } + } + RomashkiDbContext.Sales.Add(sale); + RomashkiDbContext.SaveChanges(); + return sale; + } + + private static void AssertElement(SaleDataModel? actual, Sale expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.Id, Is.EqualTo(expected.Id)); + Assert.That(actual.WorkerId, Is.EqualTo(expected.WorkerId)); + Assert.That(actual.BuyerId, Is.EqualTo(expected.BuyerId)); + Assert.That(actual.DiscountType, Is.EqualTo(expected.DiscountType)); + Assert.That(actual.Discount, Is.EqualTo(expected.Discount)); + Assert.That(actual.IsCancel, Is.EqualTo(expected.IsCancel)); + }); + + if (expected.SaleProducts is not null) + { + Assert.That(actual.Products, Is.Not.Null); + Assert.That(actual.Products, Has.Count.EqualTo(expected.SaleProducts.Count)); + for (int i = 0; i < actual.Products.Count; ++i) + { + Assert.Multiple(() => + { + Assert.That(actual.Products[i].ProductId, Is.EqualTo(expected.SaleProducts[i].ProductId)); + Assert.That(actual.Products[i].Count, Is.EqualTo(expected.SaleProducts[i].Count)); + }); + } + } + else + { + Assert.That(actual.Products, Is.Null); + } + } + + private static SaleDataModel CreateModel(string id, string workerId, string? buyerId, double sum, DiscountType discountType, double discount, bool isCancel, List productIds) + { + var products = productIds.Select(x => new SaleProductDataModel(id, x, 1)).ToList(); + return new(id, workerId, buyerId, sum, discountType, discount, isCancel, products); + } + + private Sale? GetSaleFromDatabaseById(string id) => RomashkiDbContext.Sales.Include(x => x.SaleProducts).FirstOrDefault(x => x.Id == id); + + private static void AssertElement(Sale? actual, SaleDataModel expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.Id, Is.EqualTo(expected.Id)); + Assert.That(actual.WorkerId, Is.EqualTo(expected.WorkerId)); + Assert.That(actual.BuyerId, Is.EqualTo(expected.BuyerId)); + Assert.That(actual.DiscountType, Is.EqualTo(expected.DiscountType)); + Assert.That(actual.Discount, Is.EqualTo(expected.Discount)); + Assert.That(actual.IsCancel, Is.EqualTo(expected.IsCancel)); + }); + + if (expected.Products is not null) + { + Assert.That(actual.SaleProducts, Is.Not.Null); + Assert.That(actual.SaleProducts, Has.Count.EqualTo(expected.Products.Count)); + for (int i = 0; i < actual.SaleProducts.Count; ++i) + { + Assert.Multiple(() => + { + Assert.That(actual.SaleProducts[i].ProductId, Is.EqualTo(expected.Products[i].ProductId)); + Assert.That(actual.SaleProducts[i].Count, Is.EqualTo(expected.Products[i].Count)); + }); + } + } + else + { + Assert.That(actual.SaleProducts, Is.Null); + } + } +} \ No newline at end of file -- 2.25.1 From 7842195715319c4f7a6b00922475c043d40b6f1f Mon Sep 17 00:00:00 2001 From: Rinat Date: Mon, 14 Apr 2025 20:04:36 +0400 Subject: [PATCH 5/5] final lab3 (100%) --- .../DataModels/SaleDataModel.cs | 15 +- .../DataModels/SaleProductDataModel.cs | 3 +- .../Implementations/BuyerStorageContract.cs | 3 +- .../Implementations/SaleStorageContract.cs | 38 +-- .../Implementations/WorkerStorageContract.cs | 3 +- Romashki/RomashkiDatabase/Models/Buyer.cs | 4 +- Romashki/RomashkiDatabase/Models/Sale.cs | 9 +- .../RomashkiDatabase/Models/SaleProduct.cs | 2 + Romashki/RomashkiDatabase/Models/Worker.cs | 4 +- .../RomashkiDatabase/RomashkiDatabase.csproj | 4 + .../DataModelsTests/BuyerDataModelTests.cs | 2 +- .../SaleStorageContractTests.cs | 281 +++++++++++------- .../WorkerStorageContractTests.cs | 267 +++++++++++++++++ Romashki/RomashkiTests/RomashkiTests.csproj | 2 + 14 files changed, 497 insertions(+), 140 deletions(-) create mode 100644 Romashki/RomashkiTests/Infrastructure/StoragesContracts/WorkerStorageContractTests.cs diff --git a/Romashki/RomashkiContract/DataModels/SaleDataModel.cs b/Romashki/RomashkiContract/DataModels/SaleDataModel.cs index dd2d2fb..34ba5c1 100644 --- a/Romashki/RomashkiContract/DataModels/SaleDataModel.cs +++ b/Romashki/RomashkiContract/DataModels/SaleDataModel.cs @@ -23,14 +23,15 @@ public class SaleDataModel : IValidation public bool IsCancel { get; private set; } public List? Products { get; private set; } public SaleDataModel(string id, string workerId, string? buyerId, - DiscountType discountType, bool isCancel, List products) + DiscountType discountType, bool isCancel, List + saleProducts) { Id = id; WorkerId = workerId; BuyerId = buyerId; DiscountType = discountType; IsCancel = isCancel; - Products = products; + Products = saleProducts; var percent = 0.0; foreach (DiscountType elem in Enum.GetValues()) { @@ -40,7 +41,7 @@ public class SaleDataModel : IValidation { case DiscountType.None: break; - case DiscountType.OnSale: + case DiscountType.OnSale: percent += 0.1; break; case DiscountType.RegularCustomer: @@ -61,15 +62,15 @@ public class SaleDataModel : IValidation throw new ValidationException("Field Id is empty"); if (!Id.IsGuid()) throw new ValidationException("The value in the field Id is not a unique identifier"); - if (WorkerId.IsEmpty()) + if (WorkerId.IsEmpty()) throw new ValidationException("Field WorkerId is empty"); if (!WorkerId.IsGuid()) throw new ValidationException("The value in the field WorkerId is not a unique identifier"); - if (!BuyerId?.IsGuid() ?? !BuyerId?.IsEmpty() ?? false) + if (!BuyerId?.IsGuid() ?? !BuyerId?.IsEmpty() ?? false) throw new ValidationException("The value in the field BuyerId is not a unique identifier"); - if (Sum <= 0) + if (Sum <= 0) throw new ValidationException("Field Sum is less than or equal to 0"); - if ((Products?.Count ?? 0) == 0) + if ((Products?.Count ?? 0) == 0) throw new ValidationException("The sale must include products"); } } diff --git a/Romashki/RomashkiContract/DataModels/SaleProductDataModel.cs b/Romashki/RomashkiContract/DataModels/SaleProductDataModel.cs index b8ec14c..bae9412 100644 --- a/Romashki/RomashkiContract/DataModels/SaleProductDataModel.cs +++ b/Romashki/RomashkiContract/DataModels/SaleProductDataModel.cs @@ -32,5 +32,4 @@ double price) : IValidation if (Price <= 0) throw new ValidationException("Field Price is less than or equal to 0"); } -} - +} \ No newline at end of file diff --git a/Romashki/RomashkiDatabase/Implementations/BuyerStorageContract.cs b/Romashki/RomashkiDatabase/Implementations/BuyerStorageContract.cs index 787d956..b6a4605 100644 --- a/Romashki/RomashkiDatabase/Implementations/BuyerStorageContract.cs +++ b/Romashki/RomashkiDatabase/Implementations/BuyerStorageContract.cs @@ -22,8 +22,7 @@ internal class BuyerStorageContract : IBuyerStorageContract _dbContext = dbContext; var config = new MapperConfiguration(cfg => { - cfg.CreateMap(); - cfg.CreateMap(); + cfg.AddMaps(typeof(Buyer)); }); _mapper = new Mapper(config); } diff --git a/Romashki/RomashkiDatabase/Implementations/SaleStorageContract.cs b/Romashki/RomashkiDatabase/Implementations/SaleStorageContract.cs index 1b9b49a..f7d0cec 100644 --- a/Romashki/RomashkiDatabase/Implementations/SaleStorageContract.cs +++ b/Romashki/RomashkiDatabase/Implementations/SaleStorageContract.cs @@ -16,7 +16,6 @@ internal class SaleStorageContract : ISaleStorageContract { private readonly RomashkiDbContext _dbContext; private readonly Mapper _mapper; - public SaleStorageContract(RomashkiDbContext dbContext) { _dbContext = dbContext; @@ -26,20 +25,25 @@ internal class SaleStorageContract : ISaleStorageContract cfg.CreateMap(); cfg.CreateMap(); cfg.CreateMap() - .ForMember(x => x.IsCancel, x => x.MapFrom(src => false)) - .ForMember(x => x.SaleProducts, x => x.MapFrom(src => src.Products)); + .ForMember(x => x.IsCancel, x => x.MapFrom(src => + false)) + .ForMember(x => x.SaleProducts, x => x.MapFrom(src => + src.Products)); }); _mapper = new Mapper(config); } - - public List GetList(DateTime? startDate = null, DateTime? endDate = null, string? workerId = null, string? buyerId = null, string? productId = null) + public List GetList(DateTime? startDate = null, DateTime? + endDate = null, string? workerId = null, string? buyerId = null, string? + productId = null) { try { - var query = _dbContext.Sales.Include(x => x.SaleProducts).AsQueryable(); + var query = _dbContext.Sales.Include(x => + x.SaleProducts).AsQueryable(); if (startDate is not null && endDate is not null) { - query = query.Where(x => x.SaleDate >= startDate && x.SaleDate < endDate); + query = query.Where(x => x.SaleDate >= startDate && + x.SaleDate < endDate); } if (workerId is not null) { @@ -51,7 +55,8 @@ internal class SaleStorageContract : ISaleStorageContract } if (productId is not null) { - query = query.Where(x => x.SaleProducts!.Any(y => y.ProductId == productId)); + query = query.Where(x => x.SaleProducts!.Any(y => + y.ProductId == productId)); } return [.. query.Select(x => _mapper.Map(x))]; } @@ -61,20 +66,18 @@ internal class SaleStorageContract : ISaleStorageContract throw new StorageException(ex); } } - public SaleDataModel? GetElementById(string id) { try { return _mapper.Map(GetSaleById(id)); } - catch (Exception ex) - { + catch (Exception ex) +{ _dbContext.ChangeTracker.Clear(); throw new StorageException(ex); } } - public void AddElement(SaleDataModel saleDataModel) { try @@ -88,12 +91,12 @@ internal class SaleStorageContract : ISaleStorageContract throw new StorageException(ex); } } - public void DelElement(string id) { try { - var element = GetSaleById(id) ?? throw new ElementNotFoundException(id); + var element = GetSaleById(id) ?? throw new + ElementNotFoundException(id); if (element.IsCancel) { throw new ElementDeletedException(id); @@ -101,7 +104,8 @@ internal class SaleStorageContract : ISaleStorageContract element.IsCancel = true; _dbContext.SaveChanges(); } - catch (Exception ex) when (ex is ElementDeletedException || ex is ElementNotFoundException) + catch (Exception ex) when (ex is ElementDeletedException || ex is + ElementNotFoundException) { _dbContext.ChangeTracker.Clear(); throw; @@ -112,6 +116,6 @@ internal class SaleStorageContract : ISaleStorageContract throw new StorageException(ex); } } - - private Sale? GetSaleById(string id) => _dbContext.Sales.FirstOrDefault(x => x.Id == id); + private Sale? GetSaleById(string id) => _dbContext.Sales.FirstOrDefault(x + => x.Id == id); } diff --git a/Romashki/RomashkiDatabase/Implementations/WorkerStorageContract.cs b/Romashki/RomashkiDatabase/Implementations/WorkerStorageContract.cs index 0b2469a..b72010b 100644 --- a/Romashki/RomashkiDatabase/Implementations/WorkerStorageContract.cs +++ b/Romashki/RomashkiDatabase/Implementations/WorkerStorageContract.cs @@ -21,8 +21,7 @@ internal class WorkerStorageContract : IWorkerStorageContract _dbContext = dbContext; var config = new MapperConfiguration(cfg => { - cfg.CreateMap(); - cfg.CreateMap(); + cfg.AddMaps(typeof(Worker)); }); _mapper = new Mapper(config); } diff --git a/Romashki/RomashkiDatabase/Models/Buyer.cs b/Romashki/RomashkiDatabase/Models/Buyer.cs index 1f84302..a66d543 100644 --- a/Romashki/RomashkiDatabase/Models/Buyer.cs +++ b/Romashki/RomashkiDatabase/Models/Buyer.cs @@ -4,9 +4,11 @@ using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Text; using System.Threading.Tasks; +using AutoMapper; +using RomashkiContracts.DataModels; namespace RomashkiDatabase.Models; - +[AutoMap(typeof(BuyerDataModel), ReverseMap = true)] class Buyer { public required string Id { get; set; } = Guid.NewGuid().ToString(); diff --git a/Romashki/RomashkiDatabase/Models/Sale.cs b/Romashki/RomashkiDatabase/Models/Sale.cs index 95219d6..472385b 100644 --- a/Romashki/RomashkiDatabase/Models/Sale.cs +++ b/Romashki/RomashkiDatabase/Models/Sale.cs @@ -4,12 +4,18 @@ using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Text; using System.Threading.Tasks; +using RomashkiContracts.DataModels; +using System.Xml; using RomashkiContracts.Enums; +using RomashkiContracts.Extensions; +using RomashkiContracts.Exceptions; namespace RomashkiDatabase.Models; + internal class Sale -{ public string Id { get; set; } = Guid.NewGuid().ToString(); +{ + public string Id { get; set; } = Guid.NewGuid().ToString(); public required string WorkerId { get; set; } public string? BuyerId { get; set; } public DateTime SaleDate { get; set; } @@ -21,4 +27,5 @@ internal class Sale public Buyer? Buyer { get; set; } [ForeignKey("SaleId")] public List? SaleProducts { get; set; } + } diff --git a/Romashki/RomashkiDatabase/Models/SaleProduct.cs b/Romashki/RomashkiDatabase/Models/SaleProduct.cs index ec9cb5d..e8dfca5 100644 --- a/Romashki/RomashkiDatabase/Models/SaleProduct.cs +++ b/Romashki/RomashkiDatabase/Models/SaleProduct.cs @@ -11,6 +11,8 @@ internal class SaleProduct public required string SaleId { get; set; } public required string ProductId { get; set; } public int Count { get; set; } + public double Price { get; set; } public Sale? Sale { get; set; } public Product? Product { get; set; } } + diff --git a/Romashki/RomashkiDatabase/Models/Worker.cs b/Romashki/RomashkiDatabase/Models/Worker.cs index 04773c6..1d9f613 100644 --- a/Romashki/RomashkiDatabase/Models/Worker.cs +++ b/Romashki/RomashkiDatabase/Models/Worker.cs @@ -4,9 +4,11 @@ using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Text; using System.Threading.Tasks; +using AutoMapper; +using RomashkiContracts.DataModels; namespace RomashkiDatabase.Models; - +[AutoMap(typeof(WorkerDataModel), ReverseMap = true)] internal class Worker { public required string Id { get; set; } = Guid.NewGuid().ToString(); diff --git a/Romashki/RomashkiDatabase/RomashkiDatabase.csproj b/Romashki/RomashkiDatabase/RomashkiDatabase.csproj index 5c325e5..5f70446 100644 --- a/Romashki/RomashkiDatabase/RomashkiDatabase.csproj +++ b/Romashki/RomashkiDatabase/RomashkiDatabase.csproj @@ -15,5 +15,9 @@ + + + + diff --git a/Romashki/RomashkiTests/DataModelsTests/BuyerDataModelTests.cs b/Romashki/RomashkiTests/DataModelsTests/BuyerDataModelTests.cs index 514e141..ad6b603 100644 --- a/Romashki/RomashkiTests/DataModelsTests/BuyerDataModelTests.cs +++ b/Romashki/RomashkiTests/DataModelsTests/BuyerDataModelTests.cs @@ -39,7 +39,7 @@ namespace RomashkiTests.DataModelsTests Assert.That(() => buyer.Validate(), Throws.TypeOf()); } [Test] - public void PhoneNumberIsIncorrectTest() + public void EmailIsIncorrectTest() { var buyer = CreateDataModel(Guid.NewGuid().ToString(), "fio", "email", 10, 10); Assert.That(() => buyer.Validate(), Throws.TypeOf()); diff --git a/Romashki/RomashkiTests/Infrastructure/StoragesContracts/SaleStorageContractTests.cs b/Romashki/RomashkiTests/Infrastructure/StoragesContracts/SaleStorageContractTests.cs index 4f5a1bd..80c5396 100644 --- a/Romashki/RomashkiTests/Infrastructure/StoragesContracts/SaleStorageContractTests.cs +++ b/Romashki/RomashkiTests/Infrastructure/StoragesContracts/SaleStorageContractTests.cs @@ -19,39 +19,36 @@ internal class SaleStorageContractTests : BaseStorageContractTest private Buyer _buyer; private Worker _worker; private Product _product; - - -[SetUp] -public void SetUp() + [SetUp] + public void SetUp() { _saletStorageContract = new SaleStorageContract(RomashkiDbContext); _buyer = InsertBuyerToDatabaseAndReturn(); _worker = InsertWorkerToDatabaseAndReturn(); _product = InsertProductToDatabaseAndReturn(); } - - [TearDown] public void TearDown() { - RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Sales\" CASCADE;"); - RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Buyers\" CASCADE;"); - RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Workers\" CASCADE;"); - RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Products\" CASCADE;"); + RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Sales\"CASCADE; "); + RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Buyers\"CASCADE; "); + RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Workers\"CASCADE; "); + RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Products\"CASCADE; "); } - [Test] public void Try_GetList_WhenHaveRecords_Test() { - var sale = InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)]); - InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 5)]); - InsertSaleToDatabaseAndReturn(_worker.Id, null, products: [(_product.Id, 10)]); + var sale = InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, + products: [(_product.Id, 1, 1.2)]); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: + [(_product.Id, 5, 1.2)]); + InsertSaleToDatabaseAndReturn(_worker.Id, null, products: + [(_product.Id, 10, 1.2)]); var list = _saletStorageContract.GetList(); Assert.That(list, Is.Not.Null); Assert.That(list, Has.Count.EqualTo(3)); AssertElement(list.First(x => x.Id == sale.Id), sale); } - [Test] public void Try_GetList_WhenNoRecords_Test() { @@ -59,119 +56,144 @@ public void SetUp() Assert.That(list, Is.Not.Null); Assert.That(list, Is.Empty); } - - [Test] +[Test] public void Try_GetList_ByPeriod_Test() { - InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, saleDate: DateTime.UtcNow.AddDays(-1).AddMinutes(-3), products: [(_product.Id, 1)]); - InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, saleDate: DateTime.UtcNow.AddDays(-1).AddMinutes(3), products: [(_product.Id, 1)]); - InsertSaleToDatabaseAndReturn(_worker.Id, null, saleDate: DateTime.UtcNow.AddDays(1).AddMinutes(-3), products: [(_product.Id, 1)]); - InsertSaleToDatabaseAndReturn(_worker.Id, null, saleDate: DateTime.UtcNow.AddDays(1).AddMinutes(3), products: [(_product.Id, 1)]); - var list = _saletStorageContract.GetList(startDate: DateTime.UtcNow.AddDays(-1), endDate: DateTime.UtcNow.AddDays(1)); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, saleDate: + DateTime.UtcNow.AddDays(-1).AddMinutes(-3), products: [(_product.Id, 1, 1.2)]); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, saleDate: + DateTime.UtcNow.AddDays(-1).AddMinutes(3), products: [(_product.Id, 1, 1.2)]); + InsertSaleToDatabaseAndReturn(_worker.Id, null, saleDate: + DateTime.UtcNow.AddDays(1).AddMinutes(-3), products: [(_product.Id, 1, 1.2)]); + InsertSaleToDatabaseAndReturn(_worker.Id, null, saleDate: + DateTime.UtcNow.AddDays(1).AddMinutes(3), products: [(_product.Id, 1, 1.2)]); + var list = _saletStorageContract.GetList(startDate: + DateTime.UtcNow.AddDays(-1), endDate: DateTime.UtcNow.AddDays(1)); Assert.That(list, Is.Not.Null); Assert.That(list, Has.Count.EqualTo(2)); } - [Test] public void Try_GetList_ByWorkerId_Test() { var worker = InsertWorkerToDatabaseAndReturn("Other worker"); - InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)]); - InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)]); - InsertSaleToDatabaseAndReturn(worker.Id, null, products: [(_product.Id, 1)]); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: + [(_product.Id, 1, 1.2)]); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: + [(_product.Id, 1, 1.2)]); + InsertSaleToDatabaseAndReturn(worker.Id, null, products: + [(_product.Id, 1, 1.2)]); var list = _saletStorageContract.GetList(workerId: _worker.Id); Assert.That(list, Is.Not.Null); Assert.That(list, Has.Count.EqualTo(2)); Assert.That(list.All(x => x.WorkerId == _worker.Id)); } - [Test] public void Try_GetList_ByBuyerId_Test() { - var buyer = InsertBuyerToDatabaseAndReturn("Other fio", "+8-888-888-88-88"); - InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)]); - InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)]); - InsertSaleToDatabaseAndReturn(_worker.Id, buyer.Id, products: [(_product.Id, 1)]); - InsertSaleToDatabaseAndReturn(_worker.Id, null, products: [(_product.Id, 1)]); + var buyer = InsertBuyerToDatabaseAndReturn("Other fio", "+8-888-888-88 - 88"); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: + [(_product.Id, 1, 1.2)]); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: + [(_product.Id, 1, 1.2)]); + InsertSaleToDatabaseAndReturn(_worker.Id, buyer.Id, products: + [(_product.Id, 1, 1.2)]); + InsertSaleToDatabaseAndReturn(_worker.Id, null, products: + [(_product.Id, 1, 1.2)]); var list = _saletStorageContract.GetList(buyerId: _buyer.Id); Assert.That(list, Is.Not.Null); Assert.That(list, Has.Count.EqualTo(2)); Assert.That(list.All(x => x.BuyerId == _buyer.Id)); } - [Test] public void Try_GetList_ByProductId_Test() { var product = InsertProductToDatabaseAndReturn("Other name"); - InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 5)]); - InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1), (product.Id, 4)]); - InsertSaleToDatabaseAndReturn(_worker.Id, null, products: [(product.Id, 1)]); - InsertSaleToDatabaseAndReturn(_worker.Id, null, products: [(product.Id, 1), (_product.Id, 1)]); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: + [(_product.Id, 5, 1.2)]); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: + [(_product.Id, 1, 1.2), (product.Id, 4, 1.2)]); + InsertSaleToDatabaseAndReturn(_worker.Id, null, products: + [(product.Id, 1, 1.2)]); + + InsertSaleToDatabaseAndReturn(_worker.Id, null, products: + [(product.Id, 1, 1.2), (_product.Id, 1, 1.2)]); var list = _saletStorageContract.GetList(productId: _product.Id); Assert.That(list, Is.Not.Null); Assert.That(list, Has.Count.EqualTo(3)); - Assert.That(list.All(x => x.Products.Any(y => y.ProductId == _product.Id))); + Assert.That(list.All(x => x.Products!.Any(y => y.ProductId == + _product.Id))); } - [Test] public void Try_GetList_ByAllParameters_Test() { var worker = InsertWorkerToDatabaseAndReturn("Other worker"); var buyer = InsertBuyerToDatabaseAndReturn("Other fio", "+8-888-888-88-88"); var product = InsertProductToDatabaseAndReturn("Other name"); - InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, saleDate: DateTime.UtcNow.AddDays(-1).AddMinutes(-3), products: [(_product.Id, 1)]); - InsertSaleToDatabaseAndReturn(worker.Id, null, saleDate: DateTime.UtcNow.AddDays(-1).AddMinutes(3), products: [(_product.Id, 1)]); - InsertSaleToDatabaseAndReturn(worker.Id, _buyer.Id, saleDate: DateTime.UtcNow.AddDays(-1).AddMinutes(3), products: [(_product.Id, 1)]); - InsertSaleToDatabaseAndReturn(worker.Id, _buyer.Id, saleDate: DateTime.UtcNow.AddDays(-1).AddMinutes(3), products: [(product.Id, 1)]); - InsertSaleToDatabaseAndReturn(_worker.Id, buyer.Id, saleDate: DateTime.UtcNow.AddDays(1).AddMinutes(-3), products: [(_product.Id, 1)]); - InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, saleDate: DateTime.UtcNow.AddDays(1).AddMinutes(-3), products: [(product.Id, 1)]); - InsertSaleToDatabaseAndReturn(worker.Id, null, saleDate: DateTime.UtcNow.AddDays(1).AddMinutes(-3), products: [(_product.Id, 1)]); - var list = _saletStorageContract.GetList(startDate: DateTime.UtcNow.AddDays(-1), endDate: DateTime.UtcNow.AddDays(1), workerId: _worker.Id, buyerId: _buyer.Id, productId: product.Id); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, saleDate: + DateTime.UtcNow.AddDays(-1).AddMinutes(-3), products: [(_product.Id, 1, 1.2)]); + InsertSaleToDatabaseAndReturn(worker.Id, null, saleDate: + DateTime.UtcNow.AddDays(-1).AddMinutes(3), products: [(_product.Id, 1, 1.2)]); + InsertSaleToDatabaseAndReturn(worker.Id, _buyer.Id, saleDate: + DateTime.UtcNow.AddDays(-1).AddMinutes(3), products: [(_product.Id, 1, 1.2)]); + InsertSaleToDatabaseAndReturn(worker.Id, _buyer.Id, saleDate: + DateTime.UtcNow.AddDays(-1).AddMinutes(3), products: [(product.Id, 1, 1.2)]); + InsertSaleToDatabaseAndReturn(_worker.Id, buyer.Id, saleDate: + DateTime.UtcNow.AddDays(1).AddMinutes(-3), products: [(_product.Id, 1, 1.2)]); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, saleDate: + DateTime.UtcNow.AddDays(1).AddMinutes(-3), products: [(product.Id, 1, 1.2)]); + InsertSaleToDatabaseAndReturn(worker.Id, null, saleDate: + DateTime.UtcNow.AddDays(1).AddMinutes(-3), products: [(_product.Id, 1, 1.2)]); + var list = _saletStorageContract.GetList(startDate: + DateTime.UtcNow.AddDays(-1), endDate: DateTime.UtcNow.AddDays(1), workerId: + _worker.Id, buyerId: _buyer.Id, productId: product.Id); Assert.That(list, Is.Not.Null); Assert.That(list, Has.Count.EqualTo(1)); } - [Test] public void Try_GetElementById_WhenHaveRecord_Test() { - var sale = InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)]); + var sale = InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, + products: [(_product.Id, 1, 1.2)]); AssertElement(_saletStorageContract.GetElementById(sale.Id), sale); } - [Test] public void Try_GetElementById_WhenNoRecord_Test() { - InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)]); - Assert.That(() => _saletStorageContract.GetElementById(Guid.NewGuid().ToString()), Is.Null); + InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: + [(_product.Id, 1, 1.2)]); + Assert.That(() => + _saletStorageContract.GetElementById(Guid.NewGuid().ToString()), Is.Null); } - [Test] public void Try_GetElementById_WhenRecordHasCanceled_Test() { - var sale = InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)], isCancel: true); + var sale = InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, + products: [(_product.Id, 1, 1.2)], isCancel: true); AssertElement(_saletStorageContract.GetElementById(sale.Id), sale); } - [Test] public void Try_AddElement_Test() - { - var sale = CreateModel(Guid.NewGuid().ToString(), _worker.Id, _buyer.Id, 1, DiscountType.RegularCustomer, 1, false, [_product.Id]); - _saletStorageContract.AddElement(sale); - AssertElement(GetSaleFromDatabaseById(sale.Id), sale); - } - - [Test] +{ +var sale = CreateModel(Guid.NewGuid().ToString(), _worker.Id, +_buyer.Id, DiscountType.RegularCustomer, false, [_product.Id]); + _saletStorageContract.AddElement(sale); +AssertElement(GetSaleFromDatabaseById(sale.Id), sale); +} +[Test] public void Try_AddElement_WhenIsDeletedIsTrue_Test() { - var sale = CreateModel(Guid.NewGuid().ToString(), _worker.Id, _buyer.Id, 1, DiscountType.RegularCustomer, 1, true, [_product.Id]); - Assert.That(() => _saletStorageContract.AddElement(sale), Throws.Nothing); - AssertElement(GetSaleFromDatabaseById(sale.Id), CreateModel(sale.Id, _worker.Id, _buyer.Id, 1, DiscountType.RegularCustomer, 1, false, [_product.Id])); + var sale = CreateModel(Guid.NewGuid().ToString(), _worker.Id, + _buyer.Id, DiscountType.RegularCustomer, true, [_product.Id]); + Assert.That(() => _saletStorageContract.AddElement(sale), + Throws.Nothing); + AssertElement(GetSaleFromDatabaseById(sale.Id), CreateModel(sale.Id, + _worker.Id, _buyer.Id, DiscountType.RegularCustomer, false, [_product.Id])); } - [Test] public void Try_DelElement_Test() { - var sale = InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)], isCancel: false); + var sale = InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, + products: [(_product.Id, 1, 1.2)], isCancel: false); _saletStorageContract.DelElement(sale.Id); var element = GetSaleFromDatabaseById(sale.Id); Assert.Multiple(() => @@ -180,60 +202,99 @@ public void SetUp() Assert.That(element!.IsCancel); }); } - [Test] public void Try_DelElement_WhenNoRecordWithThisId_Test() { - Assert.That(() => _saletStorageContract.DelElement(Guid.NewGuid().ToString()), Throws.TypeOf()); + Assert.That(() => + _saletStorageContract.DelElement(Guid.NewGuid().ToString()), + Throws.TypeOf()); } - [Test] public void Try_DelElement_WhenRecordWasCanceled_Test() { - var sale = InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, products: [(_product.Id, 1)], isCancel: true); - Assert.That(() => _saletStorageContract.DelElement(sale.Id), Throws.TypeOf()); + var sale = InsertSaleToDatabaseAndReturn(_worker.Id, _buyer.Id, + products: [(_product.Id, 1, 1.2)], isCancel: true); + Assert.That(() => _saletStorageContract.DelElement(sale.Id), + Throws.TypeOf()); } - - private Buyer InsertBuyerToDatabaseAndReturn(string fio = "test", string email = "email@q.e") + private Buyer InsertBuyerToDatabaseAndReturn(string fio = "test", string + email = "+7-777-777-77-77") { - var buyer = new Buyer() { Id = Guid.NewGuid().ToString(), FIO = fio, Email = email, DiscountSize = 10 }; + var buyer = new Buyer() + { + Id = Guid.NewGuid().ToString(), + FIO = fio, + Email = email, + DiscountSize = 10 + }; RomashkiDbContext.Buyers.Add(buyer); RomashkiDbContext.SaveChanges(); return buyer; } - private Worker InsertWorkerToDatabaseAndReturn(string fio = "test") { - var worker = new Worker() { Id = Guid.NewGuid().ToString(), FIO = fio, PostId = Guid.NewGuid().ToString() }; + var worker = new Worker() + { + Id = Guid.NewGuid().ToString(), + FIO = + fio, + PostId = Guid.NewGuid().ToString() + }; RomashkiDbContext.Workers.Add(worker); - RomashkiDbContext.SaveChanges(); + RomashkiDbContext.SaveChanges(); return worker; } - - - private Product InsertProductToDatabaseAndReturn(string productName = "test", ProductType productType = ProductType.Flower, double price = 1, bool isDeleted = false) + private Product InsertProductToDatabaseAndReturn(string productName = + "test", ProductType productType = ProductType.Flower, double price = 1, bool + isDeleted = false) { - var product = new Product() { Id = Guid.NewGuid().ToString(), ProductName = productName, ProductType = productType, Price = price, IsDeleted = isDeleted }; + var product = new Product() + { + Id = Guid.NewGuid().ToString(), + ProductName = productName, + ProductType = + productType, + Price = price, + IsDeleted = isDeleted + }; RomashkiDbContext.Products.Add(product); RomashkiDbContext.SaveChanges(); return product; } - - private Sale InsertSaleToDatabaseAndReturn(string workerId, string? buyerId, DateTime? saleDate = null, double sum = 1, DiscountType discountType = DiscountType.OnSale, double discount = 0, bool isCancel = false, List<(string, int)>? products = null) + private Sale InsertSaleToDatabaseAndReturn(string workerId, string? + buyerId, DateTime? saleDate = null, double sum = 1, DiscountType discountType = + DiscountType.OnSale, double discount = 0, bool isCancel = false, List<(string, + int, double)>? products = null) { - var sale = new Sale() { WorkerId = workerId, BuyerId = buyerId, SaleDate = saleDate ?? DateTime.UtcNow, Sum = sum, DiscountType = discountType, Discount = discount, IsCancel = isCancel, SaleProducts = [] }; + var sale = new Sale() + { + WorkerId = workerId, + BuyerId = buyerId, + SaleDate = saleDate ?? DateTime.UtcNow, + Sum = sum, + DiscountType = discountType, + Discount = discount, + IsCancel = isCancel, + SaleProducts = [] + }; if (products is not null) { foreach (var elem in products) { - sale.SaleProducts.Add(new SaleProduct { ProductId = elem.Item1, SaleId = sale.Id, Count = elem.Item2 }); + sale.SaleProducts.Add(new SaleProduct + { + ProductId = + elem.Item1, + SaleId = sale.Id, + Count = elem.Item2, + Price = elem.Item3 + }); } } RomashkiDbContext.Sales.Add(sale); RomashkiDbContext.SaveChanges(); return sale; } - private static void AssertElement(SaleDataModel? actual, Sale expected) { Assert.That(actual, Is.Not.Null); @@ -242,21 +303,24 @@ public void SetUp() Assert.That(actual.Id, Is.EqualTo(expected.Id)); Assert.That(actual.WorkerId, Is.EqualTo(expected.WorkerId)); Assert.That(actual.BuyerId, Is.EqualTo(expected.BuyerId)); - Assert.That(actual.DiscountType, Is.EqualTo(expected.DiscountType)); + Assert.That(actual.DiscountType, + Is.EqualTo(expected.DiscountType)); Assert.That(actual.Discount, Is.EqualTo(expected.Discount)); Assert.That(actual.IsCancel, Is.EqualTo(expected.IsCancel)); }); - if (expected.SaleProducts is not null) { Assert.That(actual.Products, Is.Not.Null); - Assert.That(actual.Products, Has.Count.EqualTo(expected.SaleProducts.Count)); + Assert.That(actual.Products, + Has.Count.EqualTo(expected.SaleProducts.Count)); for (int i = 0; i < actual.Products.Count; ++i) { Assert.Multiple(() => { - Assert.That(actual.Products[i].ProductId, Is.EqualTo(expected.SaleProducts[i].ProductId)); - Assert.That(actual.Products[i].Count, Is.EqualTo(expected.SaleProducts[i].Count)); + Assert.That(actual.Products[i].ProductId, + Is.EqualTo(expected.SaleProducts[i].ProductId)); + Assert.That(actual.Products[i].Count, + Is.EqualTo(expected.SaleProducts[i].Count)); }); } } @@ -265,15 +329,17 @@ public void SetUp() Assert.That(actual.Products, Is.Null); } } - - private static SaleDataModel CreateModel(string id, string workerId, string? buyerId, double sum, DiscountType discountType, double discount, bool isCancel, List productIds) + private static SaleDataModel CreateModel(string id, string workerId, + string? buyerId, DiscountType discountType, bool isCancel, List + productIds) { - var products = productIds.Select(x => new SaleProductDataModel(id, x, 1)).ToList(); - return new(id, workerId, buyerId, sum, discountType, discount, isCancel, products); + var products = productIds.Select(x => new SaleProductDataModel(id, x, + 1, 1.1)).ToList(); + return new(id, workerId, buyerId, discountType, isCancel, products); } - - private Sale? GetSaleFromDatabaseById(string id) => RomashkiDbContext.Sales.Include(x => x.SaleProducts).FirstOrDefault(x => x.Id == id); - + private Sale? GetSaleFromDatabaseById(string id) => + RomashkiDbContext.Sales.Include(x => x.SaleProducts).FirstOrDefault(x => x.Id + == id); private static void AssertElement(Sale? actual, SaleDataModel expected) { Assert.That(actual, Is.Not.Null); @@ -282,27 +348,30 @@ public void SetUp() Assert.That(actual.Id, Is.EqualTo(expected.Id)); Assert.That(actual.WorkerId, Is.EqualTo(expected.WorkerId)); Assert.That(actual.BuyerId, Is.EqualTo(expected.BuyerId)); - Assert.That(actual.DiscountType, Is.EqualTo(expected.DiscountType)); + Assert.That(actual.DiscountType, + Is.EqualTo(expected.DiscountType)); Assert.That(actual.Discount, Is.EqualTo(expected.Discount)); Assert.That(actual.IsCancel, Is.EqualTo(expected.IsCancel)); }); - if (expected.Products is not null) { Assert.That(actual.SaleProducts, Is.Not.Null); - Assert.That(actual.SaleProducts, Has.Count.EqualTo(expected.Products.Count)); + Assert.That(actual.SaleProducts, + Has.Count.EqualTo(expected.Products.Count)); for (int i = 0; i < actual.SaleProducts.Count; ++i) { Assert.Multiple(() => { - Assert.That(actual.SaleProducts[i].ProductId, Is.EqualTo(expected.Products[i].ProductId)); - Assert.That(actual.SaleProducts[i].Count, Is.EqualTo(expected.Products[i].Count)); + Assert.That(actual.SaleProducts[i].ProductId, + Is.EqualTo(expected.Products[i].ProductId)); + Assert.That(actual.SaleProducts[i].Count, + Is.EqualTo(expected.Products[i].Count)); }); } } else { - Assert.That(actual.SaleProducts, Is.Null); + Assert.That(actual.SaleProducts, Is.Null); } } -} \ No newline at end of file +} diff --git a/Romashki/RomashkiTests/Infrastructure/StoragesContracts/WorkerStorageContractTests.cs b/Romashki/RomashkiTests/Infrastructure/StoragesContracts/WorkerStorageContractTests.cs new file mode 100644 index 0000000..33f067e --- /dev/null +++ b/Romashki/RomashkiTests/Infrastructure/StoragesContracts/WorkerStorageContractTests.cs @@ -0,0 +1,267 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using RomashkiContract.Exceptions; +using RomashkiContracts.DataModels; +using RomashkiDatabase.Implementations; +using RomashkiDatabase.Models; + +namespace RomashkiTests.Infrastructure.StoragesContracts; + +[TestFixture] +internal class WorkerStorageContractTests : BaseStorageContractTest +{ + private WorkerStorageContract _workerStorageContract; +[SetUp] + public void SetUp() + { + _workerStorageContract = new + WorkerStorageContract(RomashkiDbContext); + } + [TearDown] + public void TearDown() + { + RomashkiDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Workers\"CASCADE; "); + } + [Test] + public void Try_GetList_WhenHaveRecords_Test() + { + var worker = + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString(), "fio 1"); + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString(), "fio 2"); + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString(), "fio 3"); + var list = _workerStorageContract.GetList(); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(3)); + AssertElement(list.First(), worker); + } + [Test] + public void Try_GetList_WhenNoRecords_Test() + { + var list = _workerStorageContract.GetList(); + Assert.That(list, Is.Not.Null); + Assert.That(list, Is.Empty); + } + [Test] + public void Try_GetList_ByPostId_Test() + { + var postId = Guid.NewGuid().ToString(); + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString(), "fio 1", + postId); + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString(), "fio 2", + postId); + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString(), "fio 3"); + var list = _workerStorageContract.GetList(postId: postId); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(2)); + Assert.That(list.All(x => x.PostId == postId)); + } + [Test] + public void Try_GetList_ByBirthDate_Test() + { + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString(), "fio 1", + birthDate: DateTime.UtcNow.AddYears(-25)); + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString(), "fio 2", + birthDate: DateTime.UtcNow.AddYears(-21)); + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString(), "fio 3", + birthDate: DateTime.UtcNow.AddYears(-20)); + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString(), "fio 4", + birthDate: DateTime.UtcNow.AddYears(-19)); + var list = _workerStorageContract.GetList(fromBirthDate: + DateTime.UtcNow.AddYears(-21).AddMinutes(-1), toBirthDate: + DateTime.UtcNow.AddYears(-20).AddMinutes(1)); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(2)); + } + [Test] + public void Try_GetList_ByEmploymentDate_Test() + { + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString(), "fio 1", + employmentDate: DateTime.UtcNow.AddDays(-2)); + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString(), "fio 2", + employmentDate: DateTime.UtcNow.AddDays(-1)); + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString(), "fio 3", + employmentDate: DateTime.UtcNow.AddDays(1)); + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString(), "fio 4", + employmentDate: DateTime.UtcNow.AddDays(2)); + var list = _workerStorageContract.GetList(fromEmploymentDate: + DateTime.UtcNow.AddDays(-1).AddMinutes(-1), toEmploymentDate: + DateTime.UtcNow.AddDays(1).AddMinutes(1)); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(2)); + } + [Test] + public void Try_GetList_ByAllParameters_Test() + { + var postId = Guid.NewGuid().ToString(); + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString(), "fio 1", + postId, birthDate: DateTime.UtcNow.AddYears(-25), employmentDate: + DateTime.UtcNow.AddDays(-2)); + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString(), "fio 2", + postId, birthDate: DateTime.UtcNow.AddYears(-22), employmentDate: + DateTime.UtcNow.AddDays(-1)); + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString(), "fio 3", + postId, birthDate: DateTime.UtcNow.AddYears(-21), employmentDate: + DateTime.UtcNow.AddDays(-1)); + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString(), "fio 4", + birthDate: DateTime.UtcNow.AddYears(-20), employmentDate: + DateTime.UtcNow.AddDays(1)); + var list = _workerStorageContract.GetList(postId: postId, + fromBirthDate: DateTime.UtcNow.AddYears(-21).AddMinutes(-1), toBirthDate: + DateTime.UtcNow.AddYears(-20).AddMinutes(1), fromEmploymentDate: + DateTime.UtcNow.AddDays(-1).AddMinutes(-1), toEmploymentDate: + DateTime.UtcNow.AddDays(1).AddMinutes(1)); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(1)); + } + [Test] + public void Try_GetElementById_WhenHaveRecord_Test() + { + var worker = + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString()); + AssertElement(_workerStorageContract.GetElementById(worker.Id), + worker); + } + [Test] + public void Try_GetElementById_WhenNoRecord_Test() + { + Assert.That(() => + _workerStorageContract.GetElementById(Guid.NewGuid().ToString()), Is.Null); + + } + [Test] + public void Try_GetElementByFIO_WhenHaveRecord_Test() + { + var worker = + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString()); + AssertElement(_workerStorageContract.GetElementByFIO(worker.FIO), + worker); + } + [Test] + public void Try_GetElementByFIO_WhenNoRecord_Test() + { + Assert.That(() => _workerStorageContract.GetElementByFIO("New Fio"), + Is.Null); + } + [Test] + public void Try_AddElement_Test() + { + var worker = CreateModel(Guid.NewGuid().ToString()); + _workerStorageContract.AddElement(worker); + AssertElement(GetWorkerFromDatabase(worker.Id), worker); + } + [Test] + public void Try_AddElement_WhenHaveRecordWithSameId_Test() + { + var worker = CreateModel(Guid.NewGuid().ToString()); + InsertWorkerToDatabaseAndReturn(worker.Id); + Assert.That(() => _workerStorageContract.AddElement(worker), + Throws.TypeOf()); + } + [Test] + public void Try_UpdElement_Test() + { + var worker = CreateModel(Guid.NewGuid().ToString(), "New Fio"); + InsertWorkerToDatabaseAndReturn(worker.Id); + _workerStorageContract.UpdElement(worker); + AssertElement(GetWorkerFromDatabase(worker.Id), worker); + } + [Test] + public void Try_UpdElement_WhenNoRecordWithThisId_Test() + { + Assert.That(() => + _workerStorageContract.UpdElement(CreateModel(Guid.NewGuid().ToString())), + Throws.TypeOf()); + } + [Test] + public void Try_UpdElement_WhenNoRecordWasDeleted_Test() + { + var worker = CreateModel(Guid.NewGuid().ToString()); + InsertWorkerToDatabaseAndReturn(worker.Id, isDeleted: true); + Assert.That(() => _workerStorageContract.UpdElement(worker), + Throws.TypeOf()); + } + [Test] + public void Try_DelElement_Test() + { + + var worker = + InsertWorkerToDatabaseAndReturn(Guid.NewGuid().ToString()); + _workerStorageContract.DelElement(worker.Id); + var element = GetWorkerFromDatabase(worker.Id); + Assert.That(element, Is.Not.Null); + Assert.That(element.IsDeleted); + } + [Test] + public void Try_DelElement_WhenNoRecordWithThisId_Test() + { + Assert.That(() => + _workerStorageContract.DelElement(Guid.NewGuid().ToString()), + Throws.TypeOf()); + } + [Test] + public void Try_DelElement_WhenNoRecordWasDeleted_Test() + { + var worker = CreateModel(Guid.NewGuid().ToString()); + InsertWorkerToDatabaseAndReturn(worker.Id, isDeleted: true); + Assert.That(() => _workerStorageContract.DelElement(worker.Id), + Throws.TypeOf()); + } + private Worker InsertWorkerToDatabaseAndReturn(string id, string fio = + "test", string? postId = null, DateTime? birthDate = null, DateTime? + employmentDate = null, bool isDeleted = false) + { + var worker = new Worker() + { + Id = id, + FIO = fio, + PostId = postId ?? + Guid.NewGuid().ToString(), + BirthDate = birthDate ?? DateTime.UtcNow.AddYears(- + 20), + EmploymentDate = employmentDate ?? DateTime.UtcNow, + IsDeleted = isDeleted + }; + RomashkiDbContext.Workers.Add(worker); + RomashkiDbContext.SaveChanges(); + return worker; + } + private static void AssertElement(WorkerDataModel? actual, Worker expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.Id, Is.EqualTo(expected.Id)); + Assert.That(actual.PostId, Is.EqualTo(expected.PostId)); + Assert.That(actual.FIO, Is.EqualTo(expected.FIO)); + Assert.That(actual.BirthDate, Is.EqualTo(expected.BirthDate)); + Assert.That(actual.EmploymentDate, + Is.EqualTo(expected.EmploymentDate)); + Assert.That(actual.IsDeleted, Is.EqualTo(expected.IsDeleted)); + }); + } + private static WorkerDataModel CreateModel(string id, string fio = "fio", + string? postId = null, DateTime? birthDate = null, DateTime? employmentDate = + null, bool isDeleted = false) => + new(id, fio, postId ?? Guid.NewGuid().ToString(), birthDate ?? + DateTime.UtcNow.AddYears(-20), employmentDate ?? DateTime.UtcNow, isDeleted); + private Worker? GetWorkerFromDatabase(string id) => + RomashkiDbContext.Workers.FirstOrDefault(x => x.Id == id); + private static void AssertElement(Worker? actual, WorkerDataModel expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.Id, Is.EqualTo(expected.Id)); + Assert.That(actual.PostId, Is.EqualTo(expected.PostId)); + Assert.That(actual.FIO, Is.EqualTo(expected.FIO)); + Assert.That(actual.BirthDate, Is.EqualTo(expected.BirthDate)); + Assert.That(actual.EmploymentDate, + Is.EqualTo(expected.EmploymentDate)); + Assert.That(actual.IsDeleted, Is.EqualTo(expected.IsDeleted)); + }); + } +} diff --git a/Romashki/RomashkiTests/RomashkiTests.csproj b/Romashki/RomashkiTests/RomashkiTests.csproj index 3008afd..bfd7c2b 100644 --- a/Romashki/RomashkiTests/RomashkiTests.csproj +++ b/Romashki/RomashkiTests/RomashkiTests.csproj @@ -20,11 +20,13 @@ + + -- 2.25.1