From bfb906fc7bab3f4763b2dad1acfc8cc5359e3eca Mon Sep 17 00:00:00 2001 From: Pyro <732603@gmail.com> Date: Thu, 13 Mar 2025 09:57:43 +0400 Subject: [PATCH 1/5] =?UTF-8?q?=D0=9F=D1=80=D0=BE=D0=B5=D0=BA=D1=82=20?= =?UTF-8?q?=D0=B8=20=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TwoFromTheCaseDatabase/Models/Customer.cs | 15 +++++++++++ .../TwoFromTheCaseDatabase/Models/Post.cs | 20 ++++++++++++++ .../TwoFromTheCaseDatabase/Models/Premises.cs | 18 +++++++++++++ .../TwoFromTheCaseDatabase/Models/Salary.cs | 14 ++++++++++ .../TwoFromTheCaseDatabase/Models/Work.cs | 26 +++++++++++++++++++ .../Models/WorkHistory.cs | 14 ++++++++++ .../TwoFromTheCaseDatabase/Models/Worker.cs | 24 +++++++++++++++++ .../Models/WorkerWork.cs | 14 ++++++++++ .../TwoFromTheCaseDatabase.csproj | 13 ++++++++++ .../TwoFromTheCaseProject.sln | 6 +++++ 10 files changed, 164 insertions(+) create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Customer.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Post.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Premises.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Salary.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Work.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/WorkHistory.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Worker.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/WorkerWork.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDatabase.csproj diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Customer.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Customer.cs new file mode 100644 index 0000000..c899bb6 --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Customer.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace TwoFromTheCaseDatabase.Models; + +class Customer +{ + public required string Id { get; set; } + + public required string Name { get; set; } + + public required string PhoneNumber { get; set; } + + [ForeignKey("CustomerId")] + public List? Premises { get; set; } +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Post.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Post.cs new file mode 100644 index 0000000..098eadd --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Post.cs @@ -0,0 +1,20 @@ +using TwoFromTheCaseContracts.Enums; + +namespace TwoFromTheCaseDatabase.Models; + +class Post +{ + public required string Id { get; set; } + + public required string PostId { get; set; } + + public required string PostName { get; set; } + + public PostType PostType { get; set; } + + public double Salary { get; set; } + + public bool IsActual { get; set; } + + public DateTime ChangeDate { get; set; } +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Premises.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Premises.cs new file mode 100644 index 0000000..16fad86 --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Premises.cs @@ -0,0 +1,18 @@ +using TwoFromTheCaseContracts.Enums; + +namespace TwoFromTheCaseDatabase.Models; + +class Premises +{ + public required string Id { get; set; } + + public PremisesType PremisesType { get; set; } + + public required string CustomerId { get; set; } + + public bool IsDeleted { get; set; } + + public Work? Work { get; set; } + + public Customer? Customer { get; set; } +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Salary.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Salary.cs new file mode 100644 index 0000000..20dc977 --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Salary.cs @@ -0,0 +1,14 @@ +namespace TwoFromTheCaseDatabase.Models; + +class Salary +{ + public required string Id { get; set; } = Guid.NewGuid().ToString(); + + public required string WorkerId { get; set; } + + public DateTime SalaryDate { get; set; } + + public double WorkerSalary { get; set; } + + public Worker? Worker { get; set; } +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Work.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Work.cs new file mode 100644 index 0000000..3aad7b4 --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Work.cs @@ -0,0 +1,26 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace TwoFromTheCaseDatabase.Models; + +class Work +{ + public required string Id { get; set; } + + public required string PremisesId { get; set; } + + public required double Price { get; set; } + + public DateTime StartDate { get; set; } + + public DateTime FinishDate { get; set; } + + public bool IsCancel { get; set; } + + public Premises? Premises { get; set; } + + [ForeignKey("WorkId")] + public List? WorkHistories { get; set; } + + [ForeignKey("WorkId")] + public List? WorkerWorks { get; set; } +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/WorkHistory.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/WorkHistory.cs new file mode 100644 index 0000000..24f2c07 --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/WorkHistory.cs @@ -0,0 +1,14 @@ +namespace TwoFromTheCaseDatabase.Models; + +class WorkHistory +{ + public required string Id { get; set; } = Guid.NewGuid().ToString(); + + public required string WorkId { get; set; } + + public double OldPrice { get; set; } + + public DateTime ChangeDate { get; set; } + + public Work? Work { get; set; } +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Worker.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Worker.cs new file mode 100644 index 0000000..bc3f80f --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Worker.cs @@ -0,0 +1,24 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace TwoFromTheCaseDatabase.Models; + +class Worker +{ + public required string Id { get; set; } + + 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? WorkerWorks { get; set; } + + [ForeignKey("WorkerId")] + public List? Salaries { get; set; } +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/WorkerWork.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/WorkerWork.cs new file mode 100644 index 0000000..579ea22 --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/WorkerWork.cs @@ -0,0 +1,14 @@ +namespace TwoFromTheCaseDatabase.Models; + +class WorkerWork +{ + public required string WorkerId { get; set; } + + public required string WorkId { get; set; } + + public double Hours { get; set; } + + public Worker? Worker { get; set; } + + public Work? Work { get; set; } +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDatabase.csproj b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDatabase.csproj new file mode 100644 index 0000000..6d98732 --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDatabase.csproj @@ -0,0 +1,13 @@ + + + + net9.0 + enable + enable + + + + + + + diff --git a/TwoFromTheCaseProject/TwoFromTheCaseProject.sln b/TwoFromTheCaseProject/TwoFromTheCaseProject.sln index 7c1f11a..66e4292 100644 --- a/TwoFromTheCaseProject/TwoFromTheCaseProject.sln +++ b/TwoFromTheCaseProject/TwoFromTheCaseProject.sln @@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TwoFromTheCaseTests", "TwoF EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TwoFromTheCaseBusinessLogic", "TwoFromTheCaseBusinessLogic\TwoFromTheCaseBusinessLogic.csproj", "{D2F3B0B3-AFB0-405F-85A4-84BDF8C8A35E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TwoFromTheCaseDatabase", "TwoFromTheCaseDatabase\TwoFromTheCaseDatabase.csproj", "{2D6D00CB-BC4B-484C-AA68-F8CCB8DE0148}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,6 +29,10 @@ Global {D2F3B0B3-AFB0-405F-85A4-84BDF8C8A35E}.Debug|Any CPU.Build.0 = Debug|Any CPU {D2F3B0B3-AFB0-405F-85A4-84BDF8C8A35E}.Release|Any CPU.ActiveCfg = Release|Any CPU {D2F3B0B3-AFB0-405F-85A4-84BDF8C8A35E}.Release|Any CPU.Build.0 = Release|Any CPU + {2D6D00CB-BC4B-484C-AA68-F8CCB8DE0148}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2D6D00CB-BC4B-484C-AA68-F8CCB8DE0148}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2D6D00CB-BC4B-484C-AA68-F8CCB8DE0148}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2D6D00CB-BC4B-484C-AA68-F8CCB8DE0148}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE -- 2.25.1 From 9a529644a4f648b9698d11c055f818a7006b1839 Mon Sep 17 00:00:00 2001 From: Pyro <732603@gmail.com> Date: Thu, 13 Mar 2025 10:17:31 +0400 Subject: [PATCH 2/5] DbContext --- .../Infrastructure/IConfigurationDatabase.cs | 6 ++ .../TwoFromTheCaseDatabase.csproj | 5 ++ .../TwoFromTheCaseDbContext.cs | 63 +++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseContracts/Infrastructure/IConfigurationDatabase.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDbContext.cs diff --git a/TwoFromTheCaseProject/TwoFromTheCaseContracts/Infrastructure/IConfigurationDatabase.cs b/TwoFromTheCaseProject/TwoFromTheCaseContracts/Infrastructure/IConfigurationDatabase.cs new file mode 100644 index 0000000..409af74 --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseContracts/Infrastructure/IConfigurationDatabase.cs @@ -0,0 +1,6 @@ +namespace TwoFromTheCaseContracts.Infrastructure; + +public interface IConfigurationDatabase +{ + string ConnectionString { get; } +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDatabase.csproj b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDatabase.csproj index 6d98732..4b1bd18 100644 --- a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDatabase.csproj +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDatabase.csproj @@ -6,6 +6,11 @@ enable + + + + + diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDbContext.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDbContext.cs new file mode 100644 index 0000000..e03eb2e --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDbContext.cs @@ -0,0 +1,63 @@ +using Microsoft.EntityFrameworkCore; +using TwoFromTheCaseDatabase.Models; +using TwoFromTheCaseContracts.Infrastructure; +using System; + +namespace TwoFromTheCaseDatabase; + +class TwoFromTheCaseDbContext(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.PhoneNumber).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.Premises, x.IsCancel }) + .IsUnique() + .HasFilter($"\"{nameof(Work.IsCancel)}\" = FALSE"); + + modelBuilder + .Entity() + .HasOne(e => e.Premises) + .WithOne(e => e.Work) + .OnDelete(DeleteBehavior.Restrict); + + modelBuilder.Entity().HasKey(x => new { x.WorkerId, x.WorkId }); + } + + public DbSet Customers { get; set; } + + public DbSet Posts { get; set; } + + public DbSet Premises { get; set; } + + public DbSet Salaries { get; set; } + + public DbSet Works { get; set; } + + public DbSet Workers { get; set; } + + public DbSet WorkerWorks { get; set; } + + public DbSet WorkHistories { get; set; } +} -- 2.25.1 From d2b33efeeaebc42acd293cb8cf8db5b34fc3949f Mon Sep 17 00:00:00 2001 From: Pyro <732603@gmail.com> Date: Thu, 13 Mar 2025 10:46:23 +0400 Subject: [PATCH 3/5] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D0=B5?= =?UTF-8?q?=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Salary.cs | 2 +- .../TwoFromTheCaseDatabase/Models/WorkHistory.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Salary.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Salary.cs index 20dc977..2bbd8ca 100644 --- a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Salary.cs +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Salary.cs @@ -2,7 +2,7 @@ class Salary { - public required string Id { get; set; } = Guid.NewGuid().ToString(); + public string Id { get; set; } = Guid.NewGuid().ToString(); public required string WorkerId { get; set; } diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/WorkHistory.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/WorkHistory.cs index 24f2c07..bbf323c 100644 --- a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/WorkHistory.cs +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/WorkHistory.cs @@ -2,7 +2,7 @@ class WorkHistory { - public required string Id { get; set; } = Guid.NewGuid().ToString(); + public string Id { get; set; } = Guid.NewGuid().ToString(); public required string WorkId { get; set; } -- 2.25.1 From aad3477ef820c98e14fce5b529cc25fcb4159947 Mon Sep 17 00:00:00 2001 From: Pyro <732603@gmail.com> Date: Thu, 13 Mar 2025 11:05:34 +0400 Subject: [PATCH 4/5] =?UTF-8?q?=D0=9A=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA?= =?UTF-8?q?=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Exceptions/ElementDeletedException.cs | 6 + .../CustomerStrorageContract.cs | 149 ++++++++++++++ .../Implementations/PostStorageContract.cs | 190 ++++++++++++++++++ .../PremisesStorageContract.cs | 113 +++++++++++ .../Implementations/SalaryStorageContract.cs | 57 ++++++ .../Implementations/WorkStorageContract.cs | 159 +++++++++++++++ .../Implementations/WorkerStorageContract.cs | 141 +++++++++++++ .../TwoFromTheCaseDatabase.csproj | 1 + 8 files changed, 816 insertions(+) create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseContracts/Exceptions/ElementDeletedException.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/CustomerStrorageContract.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/PostStorageContract.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/PremisesStorageContract.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/SalaryStorageContract.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/WorkStorageContract.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/WorkerStorageContract.cs diff --git a/TwoFromTheCaseProject/TwoFromTheCaseContracts/Exceptions/ElementDeletedException.cs b/TwoFromTheCaseProject/TwoFromTheCaseContracts/Exceptions/ElementDeletedException.cs new file mode 100644 index 0000000..9e88170 --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseContracts/Exceptions/ElementDeletedException.cs @@ -0,0 +1,6 @@ +namespace TwoFromTheCaseContracts.Exceptions; + +public class ElementDeletedException : Exception +{ + public ElementDeletedException(string id) : base($"Cannot modify a deleted item (id: {id})") { } +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/CustomerStrorageContract.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/CustomerStrorageContract.cs new file mode 100644 index 0000000..7cacbe4 --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/CustomerStrorageContract.cs @@ -0,0 +1,149 @@ +using AutoMapper; +using Microsoft.EntityFrameworkCore; +using Npgsql; +using TwoFromTheCaseContracts.DataModels; +using TwoFromTheCaseContracts.Exceptions; +using TwoFromTheCaseContracts.StoragesContracts; +using TwoFromTheCaseDatabase.Models; + +namespace TwoFromTheCaseDatabase.Implementations; + +class CustomerStrorageContract : ICustomerStrorageContract +{ + private readonly TwoFromTheCaseDbContext _dbContext; + private readonly Mapper _mapper; + + public CustomerStrorageContract(TwoFromTheCaseDbContext twoFromTheCaseDbContext) + { + _dbContext = twoFromTheCaseDbContext; + var config = new MapperConfiguration(cfg => + { + cfg.CreateMap(); + cfg.CreateMap(); + }); + _mapper = new Mapper(config); + } + + public List GetList() + { + try + { + return [.. _dbContext.Customers.Select(x => _mapper.Map(x))]; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public CustomerDataModel? GetElementById(string id) + { + try + { + return _mapper.Map(GetCustomerById(id)); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public CustomerDataModel? GetElementByName(string name) + { + try + { + return _mapper.Map(_dbContext.Customers.FirstOrDefault(x => x.Name == name)); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public CustomerDataModel? GetElementByPhoneNumber(string phoneNumber) + { + try + { + return _mapper.Map(_dbContext.Customers.FirstOrDefault(x => x.PhoneNumber == phoneNumber)); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void AddElement(CustomerDataModel customerDataModel) + { + try + { + _dbContext.Customers.Add(_mapper.Map(customerDataModel)); + _dbContext.SaveChanges(); + } + catch (InvalidOperationException ex) when (ex.TargetSite?.Name == "ThrowIdentityConflict") + { + _dbContext.ChangeTracker.Clear(); + throw new ElementExistsException("Id", customerDataModel.Id); + } + catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Customers_PhoneNumber" }) + { + _dbContext.ChangeTracker.Clear(); + throw new ElementExistsException("PhoneNumber", customerDataModel.PhoneNumber); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void UpdElement(CustomerDataModel customerDataModel) + { + try + { + var element = GetCustomerById(customerDataModel.Id) ?? throw new ElementNotFoundException(customerDataModel.Id); + _dbContext.Customers.Update(_mapper.Map(customerDataModel, element)); + _dbContext.SaveChanges(); + } + catch (ElementNotFoundException) + { + _dbContext.ChangeTracker.Clear(); + throw; + } + catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Buyers_PhoneNumber" }) + { + _dbContext.ChangeTracker.Clear(); + throw new ElementExistsException("PhoneNumber", customerDataModel.PhoneNumber); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void DelElement(string id) + { + try + { + var element = GetCustomerById(id) ?? throw new ElementNotFoundException(id); + _dbContext.Customers.Remove(element); + _dbContext.SaveChanges(); + } + catch (ElementNotFoundException) + { + _dbContext.ChangeTracker.Clear(); + throw; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + private Customer? GetCustomerById(string id) => _dbContext.Customers.FirstOrDefault(x => x.Id == id); +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/PostStorageContract.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/PostStorageContract.cs new file mode 100644 index 0000000..a56b81f --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/PostStorageContract.cs @@ -0,0 +1,190 @@ +using AutoMapper; +using Microsoft.EntityFrameworkCore; +using Npgsql; +using TwoFromTheCaseContracts.DataModels; +using TwoFromTheCaseContracts.Exceptions; +using TwoFromTheCaseContracts.StoragesContracts; +using TwoFromTheCaseDatabase.Models; + +namespace TwoFromTheCaseDatabase.Implementations; + +class PostStorageContract : IPostStorageContract +{ + private readonly TwoFromTheCaseDbContext _dbContext; + private readonly Mapper _mapper; + + public PostStorageContract(TwoFromTheCaseDbContext 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(); +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/PremisesStorageContract.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/PremisesStorageContract.cs new file mode 100644 index 0000000..724c1aa --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/PremisesStorageContract.cs @@ -0,0 +1,113 @@ +using AutoMapper; +using Microsoft.EntityFrameworkCore; +using Npgsql; +using TwoFromTheCaseContracts.DataModels; +using TwoFromTheCaseContracts.Exceptions; +using TwoFromTheCaseContracts.StoragesContracts; +using TwoFromTheCaseDatabase.Models; + +namespace TwoFromTheCaseDatabase.Implementations; + +class PremisesStorageContract : IPremisesStorageContract +{ + private readonly TwoFromTheCaseDbContext _dbContext; + private readonly Mapper _mapper; + + public PremisesStorageContract(TwoFromTheCaseDbContext twoFromTheCaseDbContext) + { + _dbContext = twoFromTheCaseDbContext; + var config = new MapperConfiguration(cfg => + { + cfg.CreateMap(); + cfg.CreateMap(); + }); + _mapper = new Mapper(config); + } + + public List GetList(bool onlyActive = true, string? customerId = null) + { + try + { + return [.. _dbContext.Premises.Select(x => _mapper.Map(x))]; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public PremisesDataModel? GetElementById(string id) + { + try + { + return _mapper.Map(GetPremisesById(id)); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void AddElement(PremisesDataModel premisesDataModel) + { + try + { + _dbContext.Premises.Add(_mapper.Map(premisesDataModel)); + _dbContext.SaveChanges(); + } + catch (InvalidOperationException ex) when (ex.TargetSite?.Name == "ThrowIdentityConflict") + { + _dbContext.ChangeTracker.Clear(); + throw new ElementExistsException("Id", premisesDataModel.Id); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void UpdElement(PremisesDataModel premisesDataModel) + { + try + { + var element = GetPremisesById(premisesDataModel.Id) ?? throw new ElementNotFoundException(premisesDataModel.Id); + _dbContext.Premises.Update(_mapper.Map(premisesDataModel, 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 = GetPremisesById(id) ?? throw new ElementNotFoundException(id); + _dbContext.Premises.Remove(element); + _dbContext.SaveChanges(); + } + catch (ElementNotFoundException) + { + _dbContext.ChangeTracker.Clear(); + throw; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + private Premises? GetPremisesById(string id) => _dbContext.Premises.FirstOrDefault(x => x.Id == id); +} \ No newline at end of file diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/SalaryStorageContract.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/SalaryStorageContract.cs new file mode 100644 index 0000000..40c7d2e --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/SalaryStorageContract.cs @@ -0,0 +1,57 @@ +using AutoMapper; +using TwoFromTheCaseContracts.DataModels; +using TwoFromTheCaseContracts.Exceptions; +using TwoFromTheCaseContracts.StoragesContracts; +using TwoFromTheCaseDatabase.Models; + +namespace TwoFromTheCaseDatabase.Implementations; + +class SalaryStorageContract : ISalaryStorageContract +{ + private readonly TwoFromTheCaseDbContext _dbContext; + private readonly Mapper _mapper; + + public SalaryStorageContract(TwoFromTheCaseDbContext dbContext) + { + _dbContext = dbContext; + var config = new MapperConfiguration(cfg => + { + cfg.CreateMap(); + cfg.CreateMap() + .ForMember(dest => dest.WorkerSalary, opt => opt.MapFrom(src => src.Salary)); + }); + _mapper = new Mapper(config); + } + + public List GetList(DateTime startDate, DateTime endDate, string? workerId = null) + { + try + { + var query = _dbContext.Salaries.Where(x => x.SalaryDate >= startDate && x.SalaryDate <= endDate); + if (workerId is not null) + { + query = query.Where(x => x.WorkerId == workerId); + } + return [.. query.Select(x => _mapper.Map(x))]; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void AddElement(SalaryDataModel salaryDataModel) + { + try + { + _dbContext.Salaries.Add(_mapper.Map(salaryDataModel)); + _dbContext.SaveChanges(); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/WorkStorageContract.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/WorkStorageContract.cs new file mode 100644 index 0000000..6c4504c --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/WorkStorageContract.cs @@ -0,0 +1,159 @@ +using AutoMapper; +using Microsoft.EntityFrameworkCore; +using Npgsql; +using TwoFromTheCaseContracts.DataModels; +using TwoFromTheCaseContracts.Exceptions; +using TwoFromTheCaseContracts.StoragesContracts; +using TwoFromTheCaseDatabase.Models; + +namespace TwoFromTheCaseDatabase.Implementations; + +class WorkStorageContract : IWorkStorageContract +{ + private readonly TwoFromTheCaseDbContext _dbContext; + private readonly Mapper _mapper; + + public WorkStorageContract(TwoFromTheCaseDbContext 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.WorkerWorks, x => x.MapFrom(src => src.Workers)); + cfg.CreateMap(); + }); + _mapper = new Mapper(config); + } + + public List GetList(DateTime? startDate = null, DateTime? endDate = null, string? premisesId = null, string? workerId = null, bool onlyActive = true) + { + try + { + var query = _dbContext.Works.Include(x => x.WorkerWorks).AsQueryable(); + if (startDate is not null && endDate is not null) + { + query = query.Where(x => x.StartDate >= startDate && x.FinishDate < endDate); + } + if (premisesId is not null) + { + query = query.Where(x => x.PremisesId == premisesId); + } + if (workerId is not null) + { + query = query.Where(x => x.WorkerWorks!.Any(y => y.WorkerId == workerId)); + } + return [.. query.Select(x => _mapper.Map(x))]; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public List GetHistoryByWorkId(string workId) + { + try + { + return [.. _dbContext.WorkHistories.Where(x => x.WorkId == workId).OrderByDescending(x => x.ChangeDate).Select(x => _mapper.Map(x))]; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public WorkDataModel? GetElementById(string id) + { + try + { + return _mapper.Map(GetWorkById(id)); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void AddElement(WorkDataModel workDataModel) + { + try + { + _dbContext.Works.Add(_mapper.Map(workDataModel)); + _dbContext.SaveChanges(); + } + catch (InvalidOperationException ex) when (ex.TargetSite?.Name == "ThrowIdentityConflict") + { + _dbContext.ChangeTracker.Clear(); + throw new ElementExistsException("Id", workDataModel.Id); + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + public void UpdElement(WorkDataModel workDataModel) + { + try + { + var transaction = _dbContext.Database.BeginTransaction(); + try + { + var element = GetWorkById(workDataModel.Id) ?? throw new ElementNotFoundException(workDataModel.Id); + if (element.Price != workDataModel.Price) + { + _dbContext.WorkHistories.Add(new WorkHistory() { WorkId = element.Id, OldPrice = element.Price }); + _dbContext.SaveChanges(); + } + _dbContext.Works.Update(_mapper.Map(workDataModel, element)); + _dbContext.SaveChanges(); + transaction.Commit(); + } + catch + { + transaction.Rollback(); + throw; + } + } + 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 = GetWorkById(id) ?? throw new ElementNotFoundException(id); + element.IsCancel = true; + _dbContext.SaveChanges(); + } + catch (ElementNotFoundException ex) + { + _dbContext.ChangeTracker.Clear(); + throw; + } + catch (Exception ex) + { + _dbContext.ChangeTracker.Clear(); + throw new StorageException(ex); + } + } + + private Work? GetWorkById(string id) => _dbContext.Works.FirstOrDefault(x => x.Id == id && !x.IsCancel); +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/WorkerStorageContract.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/WorkerStorageContract.cs new file mode 100644 index 0000000..01fd029 --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/WorkerStorageContract.cs @@ -0,0 +1,141 @@ +using AutoMapper; +using TwoFromTheCaseContracts.DataModels; +using TwoFromTheCaseContracts.Exceptions; +using TwoFromTheCaseContracts.StoragesContracts; +using TwoFromTheCaseDatabase.Models; + +namespace TwoFromTheCaseDatabase.Implementations; + +class WorkerStorageContract : IWorkerStorageContract +{ + private readonly TwoFromTheCaseDbContext _dbContext; + private readonly Mapper _mapper; + + public WorkerStorageContract(TwoFromTheCaseDbContext 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); +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDatabase.csproj b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDatabase.csproj index 4b1bd18..7f15655 100644 --- a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDatabase.csproj +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDatabase.csproj @@ -7,6 +7,7 @@ + -- 2.25.1 From ef48e78e607dba139d1d58cc30272fb8561dd732 Mon Sep 17 00:00:00 2001 From: Pyro <732603@gmail.com> Date: Thu, 24 Apr 2025 16:06:10 +0400 Subject: [PATCH 5/5] =?UTF-8?q?=D0=A2=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 | 4 +- .../DataModels/WorkDataModel.cs | 4 +- .../CustomerStrorageContract.cs | 5 +- .../PremisesStorageContract.cs | 36 +- .../Implementations/WorkerStorageContract.cs | 3 +- .../TwoFromTheCaseDatabase/Models/Customer.cs | 5 +- .../TwoFromTheCaseDatabase/Models/Post.cs | 2 +- .../TwoFromTheCaseDatabase/Models/Work.cs | 2 +- .../TwoFromTheCaseDatabase/Models/Worker.cs | 5 +- .../TwoFromTheCaseDatabase.csproj | 5 + .../TwoFromTheCaseDbContext.cs | 2 +- .../WorkBusinessLogicContractTests.cs | 4 +- .../ConfigurationDatabaseTest.cs | 8 + .../BaseStorageContractTest.cs | 25 ++ .../CustomerStorageContractTests.cs | 208 ++++++++++++ .../PostStorageContractTests.cs | 317 ++++++++++++++++++ .../PremisesStorageContractTests.cs | 261 ++++++++++++++ .../SalaryStorageContractTests.cs | 149 ++++++++ .../WorkStorageContractTests.cs | 300 +++++++++++++++++ .../WorkerStorageContractTests.cs | 226 +++++++++++++ .../TwoFromTheCaseTests.csproj | 1 + 21 files changed, 1548 insertions(+), 24 deletions(-) create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseTests/Infrastructure/ConfigurationDatabaseTest.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/BaseStorageContractTest.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/CustomerStorageContractTests.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/PostStorageContractTests.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/PremisesStorageContractTests.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/SalaryStorageContractTests.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/WorkStorageContractTests.cs create mode 100644 TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/WorkerStorageContractTests.cs diff --git a/TwoFromTheCaseProject/TwoFromTheCaseContracts/DataModels/PostDataModel.cs b/TwoFromTheCaseProject/TwoFromTheCaseContracts/DataModels/PostDataModel.cs index 190de73..850b9cb 100644 --- a/TwoFromTheCaseProject/TwoFromTheCaseContracts/DataModels/PostDataModel.cs +++ b/TwoFromTheCaseProject/TwoFromTheCaseContracts/DataModels/PostDataModel.cs @@ -5,9 +5,9 @@ using TwoFromTheCaseContracts.Infrastructure; namespace TwoFromTheCaseContracts.DataModels; -public class PostDataModel(string id, string postName, PostType postType, double salary, bool isActual, DateTime changeDate) : IValidation +public class PostDataModel(string postId, string postName, PostType postType, double salary, 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; diff --git a/TwoFromTheCaseProject/TwoFromTheCaseContracts/DataModels/WorkDataModel.cs b/TwoFromTheCaseProject/TwoFromTheCaseContracts/DataModels/WorkDataModel.cs index efdf4ce..ae7b72f 100644 --- a/TwoFromTheCaseProject/TwoFromTheCaseContracts/DataModels/WorkDataModel.cs +++ b/TwoFromTheCaseProject/TwoFromTheCaseContracts/DataModels/WorkDataModel.cs @@ -4,7 +4,7 @@ using TwoFromTheCaseContracts.Infrastructure; namespace TwoFromTheCaseContracts.DataModels; -public class WorkDataModel(string id, string premisesId, double price, bool isCancel, List workers) : IValidation +public class WorkDataModel(string id, string premisesId, double price, bool isCancel, List workerWorks) : IValidation { public string Id { get; private set; } = id; @@ -18,7 +18,7 @@ public class WorkDataModel(string id, string premisesId, double price, bool isCa public bool IsCancel { get; private set; } = isCancel; - public List Workers { get; private set; } = workers; + public List Workers { get; private set; } = workerWorks; public void Validate() { diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/CustomerStrorageContract.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/CustomerStrorageContract.cs index 7cacbe4..1ceee52 100644 --- a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/CustomerStrorageContract.cs +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/CustomerStrorageContract.cs @@ -18,8 +18,7 @@ class CustomerStrorageContract : ICustomerStrorageContract _dbContext = twoFromTheCaseDbContext; var config = new MapperConfiguration(cfg => { - cfg.CreateMap(); - cfg.CreateMap(); + cfg.AddMaps(typeof(Customer)); }); _mapper = new Mapper(config); } @@ -113,7 +112,7 @@ class CustomerStrorageContract : ICustomerStrorageContract _dbContext.ChangeTracker.Clear(); throw; } - catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Buyers_PhoneNumber" }) + catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Customers_PhoneNumber" }) { _dbContext.ChangeTracker.Clear(); throw new ElementExistsException("PhoneNumber", customerDataModel.PhoneNumber); diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/PremisesStorageContract.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/PremisesStorageContract.cs index 724c1aa..101967e 100644 --- a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/PremisesStorageContract.cs +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/PremisesStorageContract.cs @@ -19,7 +19,8 @@ class PremisesStorageContract : IPremisesStorageContract var config = new MapperConfiguration(cfg => { cfg.CreateMap(); - cfg.CreateMap(); + cfg.CreateMap() + .ForMember(x => x.IsDeleted, x => x.MapFrom(src => false)); }); _mapper = new Mapper(config); } @@ -28,7 +29,16 @@ class PremisesStorageContract : IPremisesStorageContract { try { - return [.. _dbContext.Premises.Select(x => _mapper.Map(x))]; + var query = _dbContext.Premises.AsQueryable(); + if (onlyActive) + { + query = query.Where(x => !x.IsDeleted); + } + if (customerId is not null) + { + query = query.Where(x => x.CustomerId == customerId); + } + return [.. query.Select(x => _mapper.Map(x))]; } catch (Exception ex) { @@ -73,11 +83,21 @@ class PremisesStorageContract : IPremisesStorageContract { try { - var element = GetPremisesById(premisesDataModel.Id) ?? throw new ElementNotFoundException(premisesDataModel.Id); - _dbContext.Premises.Update(_mapper.Map(premisesDataModel, element)); - _dbContext.SaveChanges(); + var transaction = _dbContext.Database.BeginTransaction(); + try + { + var element = GetPremisesById(premisesDataModel.Id) ?? throw new ElementNotFoundException(premisesDataModel.Id); + _dbContext.Premises.Update(_mapper.Map(premisesDataModel, element)); + _dbContext.SaveChanges(); + transaction.Commit(); + } + catch + { + transaction.Rollback(); + throw; + } } - catch (ElementNotFoundException) + catch (Exception ex) when (ex is ElementDeletedException || ex is ElementNotFoundException) { _dbContext.ChangeTracker.Clear(); throw; @@ -94,7 +114,7 @@ class PremisesStorageContract : IPremisesStorageContract try { var element = GetPremisesById(id) ?? throw new ElementNotFoundException(id); - _dbContext.Premises.Remove(element); + element.IsDeleted = true; _dbContext.SaveChanges(); } catch (ElementNotFoundException) @@ -109,5 +129,5 @@ class PremisesStorageContract : IPremisesStorageContract } } - private Premises? GetPremisesById(string id) => _dbContext.Premises.FirstOrDefault(x => x.Id == id); + private Premises? GetPremisesById(string id) => _dbContext.Premises.FirstOrDefault(x => x.Id == id && !x.IsDeleted); } \ No newline at end of file diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/WorkerStorageContract.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/WorkerStorageContract.cs index 01fd029..73a137d 100644 --- a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/WorkerStorageContract.cs +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Implementations/WorkerStorageContract.cs @@ -16,8 +16,7 @@ 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/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Customer.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Customer.cs index c899bb6..214f79a 100644 --- a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Customer.cs +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Customer.cs @@ -1,7 +1,10 @@ -using System.ComponentModel.DataAnnotations.Schema; +using AutoMapper; +using System.ComponentModel.DataAnnotations.Schema; +using TwoFromTheCaseContracts.DataModels; namespace TwoFromTheCaseDatabase.Models; +[AutoMap(typeof(CustomerDataModel), ReverseMap = true)] class Customer { public required string Id { get; set; } diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Post.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Post.cs index 098eadd..a5e4b43 100644 --- a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Post.cs +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Post.cs @@ -4,7 +4,7 @@ namespace TwoFromTheCaseDatabase.Models; class Post { - public required string Id { get; set; } + public required string Id { get; set; } = Guid.NewGuid().ToString(); public required string PostId { get; set; } diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Work.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Work.cs index 3aad7b4..486dec6 100644 --- a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Work.cs +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Work.cs @@ -4,7 +4,7 @@ namespace TwoFromTheCaseDatabase.Models; class Work { - public required string Id { get; set; } + public string Id { get; set; } = Guid.NewGuid().ToString(); public required string PremisesId { get; set; } diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Worker.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Worker.cs index bc3f80f..9d8a7da 100644 --- a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Worker.cs +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/Models/Worker.cs @@ -1,7 +1,10 @@ -using System.ComponentModel.DataAnnotations.Schema; +using AutoMapper; +using System.ComponentModel.DataAnnotations.Schema; +using TwoFromTheCaseContracts.DataModels; namespace TwoFromTheCaseDatabase.Models; +[AutoMap(typeof(WorkerDataModel), ReverseMap = true)] class Worker { public required string Id { get; set; } diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDatabase.csproj b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDatabase.csproj index 7f15655..06c079b 100644 --- a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDatabase.csproj +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDatabase.csproj @@ -16,4 +16,9 @@ + + + + + diff --git a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDbContext.cs b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDbContext.cs index e03eb2e..e243641 100644 --- a/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDbContext.cs +++ b/TwoFromTheCaseProject/TwoFromTheCaseDatabase/TwoFromTheCaseDbContext.cs @@ -32,7 +32,7 @@ class TwoFromTheCaseDbContext(IConfigurationDatabase configurationDatabase) : Db .HasFilter($"\"{nameof(Post.IsActual)}\" = TRUE"); modelBuilder.Entity() - .HasIndex(x => new { x.Premises, x.IsCancel }) + .HasIndex(x => new { x.PremisesId, x.IsCancel }) .IsUnique() .HasFilter($"\"{nameof(Work.IsCancel)}\" = FALSE"); diff --git a/TwoFromTheCaseProject/TwoFromTheCaseTests/BusinessLogicContractsTests/WorkBusinessLogicContractTests.cs b/TwoFromTheCaseProject/TwoFromTheCaseTests/BusinessLogicContractsTests/WorkBusinessLogicContractTests.cs index 7e52f66..44ae178 100644 --- a/TwoFromTheCaseProject/TwoFromTheCaseTests/BusinessLogicContractsTests/WorkBusinessLogicContractTests.cs +++ b/TwoFromTheCaseProject/TwoFromTheCaseTests/BusinessLogicContractsTests/WorkBusinessLogicContractTests.cs @@ -136,7 +136,7 @@ internal class WorkBusinessLogicContractTests } [Test] - public void GetAllWorksByPremisesByPeriod_PremisesIdIsNullOrEmpty_ThrowException_Test() + public void GetAllWorksByPremisesByPeriod_premisesIdIsNullOrEmpty_ThrowException_Test() { //Act&Assert Assert.That(() => _workBusinessLogicContract.GetAllWorksByPremisesByPeriod(null, DateTime.UtcNow, DateTime.UtcNow.AddDays(1)), Throws.TypeOf()); @@ -145,7 +145,7 @@ internal class WorkBusinessLogicContractTests } [Test] - public void GetAllWorksByPremisesByPeriod_PremisesIdIsNotGuid_ThrowException_Test() + public void GetAllWorksByPremisesByPeriod_premisesIdIsNotGuid_ThrowException_Test() { //Act&Assert Assert.That(() => _workBusinessLogicContract.GetAllWorksByPremisesByPeriod("productId", DateTime.UtcNow, DateTime.UtcNow.AddDays(1)), Throws.TypeOf()); diff --git a/TwoFromTheCaseProject/TwoFromTheCaseTests/Infrastructure/ConfigurationDatabaseTest.cs b/TwoFromTheCaseProject/TwoFromTheCaseTests/Infrastructure/ConfigurationDatabaseTest.cs new file mode 100644 index 0000000..787636a --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseTests/Infrastructure/ConfigurationDatabaseTest.cs @@ -0,0 +1,8 @@ +using TwoFromTheCaseContracts.Infrastructure; + +namespace TwoFromTheCaseTests.Infrastructure; + +class ConfigurationDatabaseTest : IConfigurationDatabase +{ + public string ConnectionString => "Host=127.0.0.1;Port=5432;Database=TwoFromTheCaseTest;Username=postgres;Password=postgres;"; +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/BaseStorageContractTest.cs b/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/BaseStorageContractTest.cs new file mode 100644 index 0000000..cdf3aa4 --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/BaseStorageContractTest.cs @@ -0,0 +1,25 @@ +using TwoFromTheCaseDatabase; +using TwoFromTheCaseTests.Infrastructure; + +namespace TwoFromTheCaseTests.StoragesContracts; + +abstract class BaseStorageContractTest +{ + protected TwoFromTheCaseDbContext TwoFromTheCaseDbContext { get; private set; } + + [OneTimeSetUp] + public void OneTimeSetUp() + { + TwoFromTheCaseDbContext = new TwoFromTheCaseDbContext(new ConfigurationDatabaseTest()); + + TwoFromTheCaseDbContext.Database.EnsureDeleted(); + TwoFromTheCaseDbContext.Database.EnsureCreated(); + } + + [OneTimeTearDown] + public void OneTimeTearDown() + { + TwoFromTheCaseDbContext.Database.EnsureDeleted(); + TwoFromTheCaseDbContext.Dispose(); + } +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/CustomerStorageContractTests.cs b/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/CustomerStorageContractTests.cs new file mode 100644 index 0000000..cc8231e --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/CustomerStorageContractTests.cs @@ -0,0 +1,208 @@ +using Microsoft.EntityFrameworkCore; +using TwoFromTheCaseContracts.DataModels; +using TwoFromTheCaseContracts.Enums; +using TwoFromTheCaseContracts.Exceptions; +using TwoFromTheCaseDatabase.Implementations; +using TwoFromTheCaseDatabase.Models; + +namespace TwoFromTheCaseTests.StoragesContracts; + +[TestFixture] +class CustomerStorageContractTests : BaseStorageContractTest +{ + private CustomerStrorageContract _customerStorageContract; + + [SetUp] + public void SetUp() + { + _customerStorageContract = new CustomerStrorageContract(TwoFromTheCaseDbContext); + } + + [TearDown] + public void TearDown() + { + TwoFromTheCaseDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Works\" CASCADE;"); + TwoFromTheCaseDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Premises\" CASCADE;"); + TwoFromTheCaseDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Customers\" CASCADE;"); + } + + [Test] + public void Try_GetList_WhenHaveRecords_Test() + { + var customer = InsertCustomerToDatabaseAndReturn(Guid.NewGuid().ToString(), phoneNumber: "+5-555-555-55-55"); + InsertCustomerToDatabaseAndReturn(Guid.NewGuid().ToString(), phoneNumber: "+6-666-666-66-66"); + InsertCustomerToDatabaseAndReturn(Guid.NewGuid().ToString(), phoneNumber: "+7-777-777-77-77"); + var list = _customerStorageContract.GetList(); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(3)); + AssertElement(list.First(x => x.Id == customer.Id), customer); + } + + [Test] + public void Try_GetList_WhenNoRecords_Test() + { + var list = _customerStorageContract.GetList(); + Assert.That(list, Is.Not.Null); + Assert.That(list, Is.Empty); + } + + [Test] + public void Try_GetElementById_WhenHaveRecord_Test() + { + var customer = InsertCustomerToDatabaseAndReturn(Guid.NewGuid().ToString()); + AssertElement(_customerStorageContract.GetElementById(customer.Id), customer); + } + + [Test] + public void Try_GetElementById_WhenNoRecord_Test() + { + InsertCustomerToDatabaseAndReturn(Guid.NewGuid().ToString()); + Assert.That(() => _customerStorageContract.GetElementById(Guid.NewGuid().ToString()), Is.Null); + } + + [Test] + public void Try_GetElementByName_WhenHaveRecord_Test() + { + var customer = InsertCustomerToDatabaseAndReturn(Guid.NewGuid().ToString()); + AssertElement(_customerStorageContract.GetElementByName(customer.Name), customer); + } + + [Test] + public void Try_GetElementByName_WhenNoRecord_Test() + { + InsertCustomerToDatabaseAndReturn(Guid.NewGuid().ToString()); + Assert.That(() => _customerStorageContract.GetElementByName("New Name"), Is.Null); + } + + [Test] + public void Try_GetElementByPhoneNumber_WhenHaveRecord_Test() + { + var customer = InsertCustomerToDatabaseAndReturn(Guid.NewGuid().ToString()); + AssertElement(_customerStorageContract.GetElementByPhoneNumber(customer.PhoneNumber), customer); + } + + [Test] + public void Try_GetElementByPhoneNumber_WhenNoRecord_Test() + { + InsertCustomerToDatabaseAndReturn(Guid.NewGuid().ToString()); + Assert.That(() => _customerStorageContract.GetElementByPhoneNumber("+8-888-888-88-88"), Is.Null); + } + + [Test] + public void Try_AddElement_Test() + { + var customer = CreateModel(Guid.NewGuid().ToString()); + _customerStorageContract.AddElement(customer); + AssertElement(GetCustomerFromDatabase(customer.Id), customer); + } + + [Test] + public void Try_AddElement_WhenHaveRecordWithSameId_Test() + { + var customer = CreateModel(Guid.NewGuid().ToString(), "New Name", "+5-555-555-55-55"); + InsertCustomerToDatabaseAndReturn(customer.Id); + Assert.That(() => _customerStorageContract.AddElement(customer), Throws.TypeOf()); + } + + [Test] + public void Try_AddElement_WhenHaveRecordWithSamePhoneNumber_Test() + { + var customer = CreateModel(Guid.NewGuid().ToString(), "New Name", "+5-555-555-55-55"); + InsertCustomerToDatabaseAndReturn(Guid.NewGuid().ToString(), phoneNumber: customer.PhoneNumber); + Assert.That(() => _customerStorageContract.AddElement(customer), Throws.TypeOf()); + } + + [Test] + public void Try_UpdElement_Test() + { + var customer = CreateModel(Guid.NewGuid().ToString(), "New Name", "+5-555-555-55-55"); + InsertCustomerToDatabaseAndReturn(customer.Id); + _customerStorageContract.UpdElement(customer); + AssertElement(GetCustomerFromDatabase(customer.Id), customer); + } + + [Test] + public void Try_UpdElement_WhenNoRecordWithThisId_Test() + { + Assert.That(() => _customerStorageContract.UpdElement(CreateModel(Guid.NewGuid().ToString())), Throws.TypeOf()); + } + + [Test] + public void Try_UpdElement_WhenHaveRecordWithSamePhoneNumber_Test() + { + var customer = CreateModel(Guid.NewGuid().ToString(), "New Name", "+5-555-555-55-55"); + InsertCustomerToDatabaseAndReturn(customer.Id, phoneNumber: "+7-777-777-77-77"); + InsertCustomerToDatabaseAndReturn(Guid.NewGuid().ToString(), phoneNumber: customer.PhoneNumber); + Assert.That(() => _customerStorageContract.UpdElement(customer), Throws.TypeOf()); + } + + [Test] + public void Try_DelElement_Test() + { + var customer = InsertCustomerToDatabaseAndReturn(Guid.NewGuid().ToString()); + _customerStorageContract.DelElement(customer.Id); + var element = GetCustomerFromDatabase(customer.Id); + Assert.That(element, Is.Null); + } + + [Test] + public void Try_DelElement_WhenHavePremisesByThisCustomer_Test() + { + var customer = InsertCustomerToDatabaseAndReturn(Guid.NewGuid().ToString()); + TwoFromTheCaseDbContext.Premises.Add(new Premises() { Id = Guid.NewGuid().ToString(), CustomerId = customer.Id, PremisesType = PremisesType.None, IsDeleted = false }); + TwoFromTheCaseDbContext.Premises.Add(new Premises() { Id = Guid.NewGuid().ToString(), CustomerId = customer.Id, PremisesType = PremisesType.None, IsDeleted = false }); + TwoFromTheCaseDbContext.SaveChanges(); + var PremisesBeforeDelete = TwoFromTheCaseDbContext.Premises.Where(x => x.CustomerId == customer.Id).ToArray(); + _customerStorageContract.DelElement(customer.Id); + var element = GetCustomerFromDatabase(customer.Id); + var PremisesAfterDelete = TwoFromTheCaseDbContext.Premises.Where(x => x.CustomerId == customer.Id).ToArray(); + Assert.Multiple(() => + { + Assert.That(element, Is.Null); + Assert.That(PremisesBeforeDelete, Has.Length.EqualTo(2)); + Assert.That(PremisesAfterDelete, Is.Empty); + Assert.That(TwoFromTheCaseDbContext.Premises.Count(), Is.EqualTo(0)); + }); + } + + [Test] + public void Try_DelElement_WhenNoRecordWithThisId_Test() + { + Assert.That(() => _customerStorageContract.DelElement(Guid.NewGuid().ToString()), Throws.TypeOf()); + } + + private Customer InsertCustomerToDatabaseAndReturn(string id, string name = "test", string phoneNumber = "+7-777-777-77-77") + { + var customer = new Customer() { Id = id, Name = name, PhoneNumber = phoneNumber }; + TwoFromTheCaseDbContext.Customers.Add(customer); + TwoFromTheCaseDbContext.SaveChanges(); + return customer; + } + + private static void AssertElement(CustomerDataModel? actual, Customer expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.Id, Is.EqualTo(expected.Id)); + Assert.That(actual.Name, Is.EqualTo(expected.Name)); + Assert.That(actual.PhoneNumber, Is.EqualTo(expected.PhoneNumber)); + }); + } + + private static CustomerDataModel CreateModel(string id, string name = "test", string phoneNumber = "+7-777-777-77-77") + => new(id, name, phoneNumber); + + private Customer? GetCustomerFromDatabase(string id) => TwoFromTheCaseDbContext.Customers.FirstOrDefault(x => x.Id == id); + + private static void AssertElement(Customer? actual, CustomerDataModel expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.Id, Is.EqualTo(expected.Id)); + Assert.That(actual.Name, Is.EqualTo(expected.Name)); + Assert.That(actual.PhoneNumber, Is.EqualTo(expected.PhoneNumber)); + }); + } +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/PostStorageContractTests.cs b/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/PostStorageContractTests.cs new file mode 100644 index 0000000..f850775 --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/PostStorageContractTests.cs @@ -0,0 +1,317 @@ +using Microsoft.EntityFrameworkCore; +using TwoFromTheCaseContracts.DataModels; +using TwoFromTheCaseContracts.Enums; +using TwoFromTheCaseContracts.Exceptions; +using TwoFromTheCaseDatabase.Implementations; +using TwoFromTheCaseDatabase.Models; + +namespace TwoFromTheCaseTests.StoragesContracts; + +[TestFixture] +internal class PostStorageContractTests : BaseStorageContractTest +{ + private PostStorageContract _postStorageContract; + + [SetUp] + public void SetUp() + { + _postStorageContract = new PostStorageContract(TwoFromTheCaseDbContext); + } + + [TearDown] + public void TearDown() + { + TwoFromTheCaseDbContext.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 = TwoFromTheCaseDbContext.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.Carpenter, double salary = 10, bool isActual = true, DateTime? changeDate = null) + { + var post = new Post() { Id = Guid.NewGuid().ToString(), PostId = id, PostName = postName, PostType = postType, Salary = salary, IsActual = isActual, ChangeDate = changeDate ?? DateTime.UtcNow }; + TwoFromTheCaseDbContext.Posts.Add(post); + TwoFromTheCaseDbContext.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.Salary, Is.EqualTo(expected.Salary)); + Assert.That(actual.IsActual, Is.EqualTo(expected.IsActual)); + }); + } + + private static PostDataModel CreateModel(string postId, string postName = "test", PostType postType = PostType.Carpenter, double salary = 10, bool isActual = false, DateTime? changeDate = null) + => new(postId, postName, postType, salary, isActual, changeDate ?? DateTime.UtcNow); + + private Post? GetPostFromDatabaseByPostId(string id) => TwoFromTheCaseDbContext.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.Salary, Is.EqualTo(expected.Salary)); + Assert.That(actual.IsActual, Is.EqualTo(expected.IsActual)); + }); + } +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/PremisesStorageContractTests.cs b/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/PremisesStorageContractTests.cs new file mode 100644 index 0000000..e65fa97 --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/PremisesStorageContractTests.cs @@ -0,0 +1,261 @@ +using Microsoft.EntityFrameworkCore; +using NUnit.Framework.Constraints; +using TwoFromTheCaseContracts.DataModels; +using TwoFromTheCaseContracts.Enums; +using TwoFromTheCaseContracts.Exceptions; +using TwoFromTheCaseDatabase.Implementations; +using TwoFromTheCaseDatabase.Models; + +namespace TwoFromTheCaseTests.StoragesContracts; + +[TestFixture] +internal class PremisesStorageContractTests : BaseStorageContractTest +{ + private PremisesStorageContract _premisesStorageContract; + private Customer _customer; + + [SetUp] + public void SetUp() + { + _premisesStorageContract = new PremisesStorageContract(TwoFromTheCaseDbContext); + _customer = InsertCustomerToDatabaseAndReturn(); + } + + [TearDown] + public void TearDown() + { + TwoFromTheCaseDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Premises\" CASCADE;"); + TwoFromTheCaseDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Customers\" CASCADE;"); + } + + [Test] + public void Try_GetList_WhenHaveRecords_Test() + { + var premises = InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), _customer.Id); + InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), _customer.Id); + InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), _customer.Id); + var list = _premisesStorageContract.GetList(); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(3)); + AssertElement(list.First(x => x.Id == premises.Id), premises); + } + + [Test] + public void Try_GetList_WhenNoRecords_Test() + { + var list = _premisesStorageContract.GetList(); + Assert.That(list, Is.Not.Null); + Assert.That(list, Is.Empty); + } + + [Test] + public void Try_GetList_OnlyActual_Test() + { + InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), _customer.Id, isDeleted: true); + InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), _customer.Id, isDeleted: false); + InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), _customer.Id, isDeleted: false); + var list = _premisesStorageContract.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() + { + InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), _customer.Id, isDeleted: true); + InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), _customer.Id, isDeleted: true); + InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), _customer.Id, isDeleted: false); + var list = _premisesStorageContract.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_GetList_ByCustomer_Test() + { + var customer = InsertCustomerToDatabaseAndReturn("name 2", phoneNumber: "+7-777-777-77-78"); + InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), _customer.Id, isDeleted: true); + InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), _customer.Id, isDeleted: false); + InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), customer.Id, isDeleted: false); + var list = _premisesStorageContract.GetList(customerId: _customer.Id, onlyActive: false); + Assert.That(list, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(list, Has.Count.EqualTo(2)); + Assert.That(list.All(x => x.CustomerId == _customer.Id)); + }); + } + + [Test] + public void Try_GetList_ByCustomerOnlyActual_Test() + { + var customer = InsertCustomerToDatabaseAndReturn("name 2", phoneNumber: "+7-777-777-77-78"); + InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), _customer.Id, isDeleted: true); + InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), _customer.Id, isDeleted: false); + InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), customer.Id, isDeleted: false); + var list = _premisesStorageContract.GetList(customerId: _customer.Id, onlyActive: true); + Assert.That(list, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(list, Has.Count.EqualTo(1)); + Assert.That(list.All(x => x.CustomerId == _customer.Id && !x.IsDeleted)); + }); + } + + [Test] + public void Try_GetElementById_WhenHaveRecord_Test() + { + var premises = InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), _customer.Id); + AssertElement(_premisesStorageContract.GetElementById(premises.Id), premises); + } + + [Test] + public void Try_GetElementById_WhenNoRecord_Test() + { + InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), _customer.Id); + Assert.That(() => _premisesStorageContract.GetElementById(Guid.NewGuid().ToString()), Is.Null); + } + + [Test] + public void Try_GetElementById_WhenRecordHasDeleted_Test() + { + var premises = InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), _customer.Id, isDeleted: true); + Assert.That(() => _premisesStorageContract.GetElementById(premises.Id), Is.Null); + } + + [Test] + public void Try_AddElement_Test() + { + var premises = CreateModel(Guid.NewGuid().ToString(), _customer.Id, isDeleted: false); + _premisesStorageContract.AddElement(premises); + AssertElement(GetPremisesFromDatabaseById(premises.Id), premises); + } + + [Test] + public void Try_AddElement_WhenIsDeletedIsTrue_Test() + { + var premises = CreateModel(Guid.NewGuid().ToString(), _customer.Id, isDeleted: true); + Assert.That(() => _premisesStorageContract.AddElement(premises), Throws.Nothing); + AssertElement(GetPremisesFromDatabaseById(premises.Id), CreateModel(premises.Id, _customer.Id, isDeleted: false)); + } + + [Test] + public void Try_AddElement_WhenHaveRecordWithSameId_Test() + { + var premises = CreateModel(Guid.NewGuid().ToString(), _customer.Id); + InsertPremisesToDatabaseAndReturn(premises.Id, _customer.Id); + Assert.That(() => _premisesStorageContract.AddElement(premises), Throws.TypeOf()); + } + + [Test] + public void Try_UpdElement_Test() + { + var premises = CreateModel(Guid.NewGuid().ToString(), _customer.Id, isDeleted: false); + InsertPremisesToDatabaseAndReturn(premises.Id, _customer.Id, isDeleted: false); + _premisesStorageContract.UpdElement(premises); + AssertElement(GetPremisesFromDatabaseById(premises.Id), premises); + } + + [Test] + public void Try_UpdElement_WhenIsDeletedIsTrue_Test() + { + var premises = CreateModel(Guid.NewGuid().ToString(), _customer.Id, isDeleted: true); + InsertPremisesToDatabaseAndReturn(premises.Id, _customer.Id, isDeleted: false); + _premisesStorageContract.UpdElement(premises); + AssertElement(GetPremisesFromDatabaseById(premises.Id), CreateModel(premises.Id, _customer.Id, isDeleted: false)); + } + + [Test] + public void Try_UpdElement_WhenNoRecordWithThisId_Test() + { + Assert.That(() => _premisesStorageContract.UpdElement(CreateModel(Guid.NewGuid().ToString(), _customer.Id)), Throws.TypeOf()); + } + + [Test] + public void Try_UpdElement_WhenRecordWasDeleted_Test() + { + var premises = CreateModel(Guid.NewGuid().ToString(), _customer.Id); + InsertPremisesToDatabaseAndReturn(premises.Id, _customer.Id, isDeleted: true); + Assert.That(() => _premisesStorageContract.UpdElement(premises), Throws.TypeOf()); + } + + [Test] + public void Try_DelElement_Test() + { + var premises = InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), _customer.Id, isDeleted: false); + _premisesStorageContract.DelElement(premises.Id); + var element = GetPremisesFromDatabaseById(premises.Id); + Assert.Multiple(() => + { + Assert.That(element, Is.Not.Null); + Assert.That(element!.IsDeleted); + }); + } + + [Test] + public void Try_DelElement_WhenNoRecordWithThisId_Test() + { + Assert.That(() => _premisesStorageContract.DelElement(Guid.NewGuid().ToString()), Throws.TypeOf()); + } + + [Test] + public void Try_DelElement_WhenRecordWasDeleted_Test() + { + var premises = InsertPremisesToDatabaseAndReturn(Guid.NewGuid().ToString(), _customer.Id, isDeleted: true); + Assert.That(() => _premisesStorageContract.DelElement(premises.Id), Throws.TypeOf()); + } + + private Customer InsertCustomerToDatabaseAndReturn(string customerName = "name", string phoneNumber = "+7-777-777-77-77") + { + var customer = new Customer() { Id = Guid.NewGuid().ToString(), Name = customerName, PhoneNumber = phoneNumber }; + TwoFromTheCaseDbContext.Customers.Add(customer); + TwoFromTheCaseDbContext.SaveChanges(); + return customer; + } + + private Premises InsertPremisesToDatabaseAndReturn(string id, string customerId, PremisesType premisesType = PremisesType.Commercial, bool isDeleted = false) + { + var premises = new Premises() { Id = id, CustomerId = customerId, PremisesType = premisesType, IsDeleted = isDeleted }; + TwoFromTheCaseDbContext.Premises.Add(premises); + TwoFromTheCaseDbContext.SaveChanges(); + return premises; + } + + private static void AssertElement(PremisesDataModel? actual, Premises expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.Id, Is.EqualTo(expected.Id)); + Assert.That(actual.CustomerId, Is.EqualTo(expected.CustomerId)); + Assert.That(actual.PremisesType, Is.EqualTo(expected.PremisesType)); + Assert.That(actual.IsDeleted, Is.EqualTo(expected.IsDeleted)); + }); + } + + private static PremisesDataModel CreateModel(string id, string customerId, PremisesType premisesType = PremisesType.Commercial, bool isDeleted = false) + => new(id, premisesType, customerId, isDeleted); + + private Premises? GetPremisesFromDatabaseById(string id) => TwoFromTheCaseDbContext.Premises.FirstOrDefault(x => x.Id == id); + + private static void AssertElement(Premises? actual, PremisesDataModel expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.Id, Is.EqualTo(expected.Id)); + Assert.That(actual.CustomerId, Is.EqualTo(expected.CustomerId)); + Assert.That(actual.PremisesType, Is.EqualTo(expected.PremisesType)); + Assert.That(actual.IsDeleted, Is.EqualTo(expected.IsDeleted)); + }); + } +} \ No newline at end of file diff --git a/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/SalaryStorageContractTests.cs b/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/SalaryStorageContractTests.cs new file mode 100644 index 0000000..fc9c016 --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/SalaryStorageContractTests.cs @@ -0,0 +1,149 @@ +using Microsoft.EntityFrameworkCore; +using TwoFromTheCaseContracts.DataModels; +using TwoFromTheCaseDatabase.Implementations; +using TwoFromTheCaseDatabase.Models; +using TwoFromTheCaseTests.StoragesContracts; + +namespace TwoFromTheCaseTests.StoragesContracts; + +[TestFixture] +internal class SalaryStorageContractTests : BaseStorageContractTest +{ + private SalaryStorageContract _salaryStorageContract; + private Worker _worker; + + [SetUp] + public void SetUp() + { + _salaryStorageContract = new SalaryStorageContract(TwoFromTheCaseDbContext); + _worker = InsertWorkerToDatabaseAndReturn(); + } + + [TearDown] + public void TearDown() + { + TwoFromTheCaseDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Salaries\" CASCADE;"); + TwoFromTheCaseDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Workers\" CASCADE;"); + } + + [Test] + public void Try_GetList_WhenHaveRecords_Test() + { + var salary = InsertSalaryToDatabaseAndReturn(_worker.Id, workerSalary: 100); + InsertSalaryToDatabaseAndReturn(_worker.Id); + InsertSalaryToDatabaseAndReturn(_worker.Id); + var list = _salaryStorageContract.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(), salary); + } + + [Test] + public void Try_GetList_WhenNoRecords_Test() + { + var list = _salaryStorageContract.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() + { + InsertSalaryToDatabaseAndReturn(_worker.Id, salaryDate: DateTime.UtcNow.AddDays(-2)); + InsertSalaryToDatabaseAndReturn(_worker.Id, salaryDate: DateTime.UtcNow.AddDays(-1).AddMinutes(-5)); + InsertSalaryToDatabaseAndReturn(_worker.Id, salaryDate: DateTime.UtcNow.AddDays(-1).AddMinutes(5)); + InsertSalaryToDatabaseAndReturn(_worker.Id, salaryDate: DateTime.UtcNow.AddDays(1).AddMinutes(-5)); + InsertSalaryToDatabaseAndReturn(_worker.Id, salaryDate: DateTime.UtcNow.AddDays(1).AddMinutes(5)); + InsertSalaryToDatabaseAndReturn(_worker.Id, salaryDate: DateTime.UtcNow.AddDays(-2)); + var list = _salaryStorageContract.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_ByWorker_Test() + { + var worker = InsertWorkerToDatabaseAndReturn("name 2"); + InsertSalaryToDatabaseAndReturn(_worker.Id); + InsertSalaryToDatabaseAndReturn(_worker.Id); + InsertSalaryToDatabaseAndReturn(worker.Id); + var list = _salaryStorageContract.GetList(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow.AddDays(1), _worker.Id); + Assert.That(list, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(list, Has.Count.EqualTo(2)); + Assert.That(list.All(x => x.WorkerId == _worker.Id)); + }); + } + + [Test] + public void Try_GetList_ByWorkerOnlyInDatePeriod_Test() + { + var worker = InsertWorkerToDatabaseAndReturn("name 2"); + InsertSalaryToDatabaseAndReturn(_worker.Id, salaryDate: DateTime.UtcNow.AddDays(-2)); + InsertSalaryToDatabaseAndReturn(_worker.Id, salaryDate: DateTime.UtcNow.AddDays(-1).AddMinutes(5)); + InsertSalaryToDatabaseAndReturn(worker.Id, salaryDate: DateTime.UtcNow.AddDays(-1).AddMinutes(5)); + InsertSalaryToDatabaseAndReturn(_worker.Id, salaryDate: DateTime.UtcNow.AddDays(1).AddMinutes(-5)); + InsertSalaryToDatabaseAndReturn(worker.Id, salaryDate: DateTime.UtcNow.AddDays(1).AddMinutes(-5)); + InsertSalaryToDatabaseAndReturn(_worker.Id, salaryDate: DateTime.UtcNow.AddDays(-2)); + var list = _salaryStorageContract.GetList(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow.AddDays(1), _worker.Id); + Assert.That(list, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(list, Has.Count.EqualTo(2)); + Assert.That(list.All(x => x.WorkerId == _worker.Id)); + }); + } + + [Test] + public void Try_AddElement_Test() + { + var salary = CreateModel(_worker.Id); + _salaryStorageContract.AddElement(salary); + AssertElement(GetSalaryFromDatabaseByWorkerId(_worker.Id), salary); + } + + private Worker InsertWorkerToDatabaseAndReturn(string workerFIO = "fio") + { + var worker = new Worker() { Id = Guid.NewGuid().ToString(), PostId = Guid.NewGuid().ToString(), FIO = workerFIO, IsDeleted = false }; + TwoFromTheCaseDbContext.Workers.Add(worker); + TwoFromTheCaseDbContext.SaveChanges(); + return worker; + } + + private Salary InsertSalaryToDatabaseAndReturn(string workerId, double workerSalary = 1, DateTime? salaryDate = null) + { + var salary = new Salary() { WorkerId = workerId, WorkerSalary = workerSalary, SalaryDate = salaryDate ?? DateTime.UtcNow }; + TwoFromTheCaseDbContext.Salaries.Add(salary); + TwoFromTheCaseDbContext.SaveChanges(); + return salary; + } + + private static void AssertElement(SalaryDataModel? actual, Salary expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.WorkerId, Is.EqualTo(expected.WorkerId)); + Assert.That(actual.Salary, Is.EqualTo(expected.WorkerSalary)); + }); + } + + private static SalaryDataModel CreateModel(string workerId, double workerSalary = 1, DateTime? salaryDate = null) + => new(workerId, salaryDate ?? DateTime.UtcNow, workerSalary); + + private Salary? GetSalaryFromDatabaseByWorkerId(string id) => TwoFromTheCaseDbContext.Salaries.FirstOrDefault(x => x.WorkerId == id); + + private static void AssertElement(Salary? actual, SalaryDataModel expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.WorkerId, Is.EqualTo(expected.WorkerId)); + Assert.That(actual.WorkerSalary, Is.EqualTo(expected.Salary)); + }); + } +} \ No newline at end of file diff --git a/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/WorkStorageContractTests.cs b/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/WorkStorageContractTests.cs new file mode 100644 index 0000000..a7ca9fd --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/WorkStorageContractTests.cs @@ -0,0 +1,300 @@ +using Microsoft.EntityFrameworkCore; +using TwoFromTheCaseContracts.DataModels; +using TwoFromTheCaseContracts.Exceptions; +using TwoFromTheCaseDatabase.Implementations; +using TwoFromTheCaseDatabase.Models; + +namespace TwoFromTheCaseTests.StoragesContracts; + +[TestFixture] +internal class WorkStorageContractTests : BaseStorageContractTest +{ + private WorkStorageContract _workStorageContract; + private Worker _worker; + private Customer _customer; + private Premises _premises; + + [SetUp] + public void SetUp() + { + _workStorageContract = new WorkStorageContract(TwoFromTheCaseDbContext); + _worker = InsertWorkerToDatabaseAndReturn(); + _customer = InsertCustomerToDatabaseAndReturn(); + _premises = InsertPremisesToDatabaseAndReturn(); + } + + [TearDown] + public void TearDown() + { + TwoFromTheCaseDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Works\" CASCADE;"); + TwoFromTheCaseDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Workers\" CASCADE;"); + TwoFromTheCaseDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Customers\" CASCADE;"); + TwoFromTheCaseDbContext.Database.ExecuteSqlRaw("TRUNCATE \"Premises\" CASCADE;"); + } + + [Test] + public void Try_GetList_WhenHaveRecords_Test() + { + var work = InsertWorkToDatabaseAndReturn(_premises.Id, workers: [(_worker.Id, 1)]); + _premises = InsertPremisesToDatabaseAndReturn(); + InsertWorkToDatabaseAndReturn(_premises.Id, workers: [(_worker.Id, 5)]); + var list = _workStorageContract.GetList(); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(2)); + AssertElement(list.First(x => x.Id == work.Id), work); + } + + [Test] + public void Try_GetList_WhenNoRecords_Test() + { + var list = _workStorageContract.GetList(); + Assert.That(list, Is.Not.Null); + Assert.That(list, Is.Empty); + } + + [Test] + public void Try_GetList_ByPeriod_Test() + { + InsertWorkToDatabaseAndReturn(_premises.Id, startDate: DateTime.UtcNow.AddDays(-1).AddMinutes(-3), workers: [(_worker.Id, 1)]); + _premises = InsertPremisesToDatabaseAndReturn(); + InsertWorkToDatabaseAndReturn(_premises.Id, startDate: DateTime.UtcNow.AddDays(-1).AddMinutes(3), workers: [(_worker.Id, 1)]); + _premises = InsertPremisesToDatabaseAndReturn(); + InsertWorkToDatabaseAndReturn(_premises.Id, startDate: DateTime.UtcNow.AddDays(1).AddMinutes(-3), workers: [(_worker.Id, 1)]); + _premises = InsertPremisesToDatabaseAndReturn(); + InsertWorkToDatabaseAndReturn(_premises.Id, startDate: DateTime.UtcNow.AddDays(1).AddMinutes(3), workers: [(_worker.Id, 1)]); + var list = _workStorageContract.GetList(startDate: DateTime.UtcNow.AddDays(-1), endDate: DateTime.UtcNow.AddDays(1)); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(3)); + } + + [Test] + public void Try_GetList_ByWorkerId_Test() + { + var worker = InsertWorkerToDatabaseAndReturn("Other worker"); + InsertWorkToDatabaseAndReturn(_premises.Id, workers: [(_worker.Id, 1)]); + _premises = InsertPremisesToDatabaseAndReturn(); + InsertWorkToDatabaseAndReturn(_premises.Id, workers: [(_worker.Id, 1)]); + var list = _workStorageContract.GetList(workerId: _worker.Id); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(2)); + Assert.That(list.All(x => x.Workers.Any(y => y.WorkerId == _worker.Id))); + } + + [Test] + public void Try_GetList_ByAllParameters_Test() + { + var worker = InsertWorkerToDatabaseAndReturn("Other worker"); + var premises = InsertPremisesToDatabaseAndReturn(); + InsertWorkToDatabaseAndReturn(_premises.Id, startDate: DateTime.UtcNow.AddDays(-1).AddMinutes(3), workers: [(_worker.Id, 1)]); + InsertWorkToDatabaseAndReturn(premises.Id, startDate: DateTime.UtcNow.AddDays(-1).AddMinutes(3), workers: [(worker.Id, 1)]); + premises = InsertPremisesToDatabaseAndReturn(); + InsertWorkToDatabaseAndReturn(premises.Id, startDate: DateTime.UtcNow.AddDays(1).AddMinutes(3), workers: [(worker.Id, 1)]); + premises = InsertPremisesToDatabaseAndReturn(); + InsertWorkToDatabaseAndReturn(premises.Id, startDate: DateTime.UtcNow.AddDays(-1).AddMinutes(-3), workers: [(_worker.Id, 1)]); + var list = _workStorageContract.GetList(startDate: DateTime.UtcNow.AddDays(-1), endDate: DateTime.UtcNow.AddDays(1), workerId: _worker.Id, premisesId: _premises.Id); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(1)); + } + + [Test] + public void Try_GetHistoryByWorkId_WhenHaveRecords_Test() + { + var work = InsertWorkToDatabaseAndReturn(_premises.Id); + InsertWorkHistoryToDatabaseAndReturn(work.Id, 20, DateTime.UtcNow.AddDays(-1)); + InsertWorkHistoryToDatabaseAndReturn(work.Id, 30, DateTime.UtcNow.AddMinutes(-10)); + InsertWorkHistoryToDatabaseAndReturn(work.Id, 40, DateTime.UtcNow.AddDays(1)); + var list = _workStorageContract.GetHistoryByWorkId(work.Id); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(3)); + } + + [Test] + public void Try_GetHistoryByWorkId_WhenNoRecords_Test() + { + var work = InsertWorkToDatabaseAndReturn(_premises.Id); + InsertWorkHistoryToDatabaseAndReturn(work.Id, 20, DateTime.UtcNow.AddDays(-1)); + InsertWorkHistoryToDatabaseAndReturn(work.Id, 30, DateTime.UtcNow.AddMinutes(-10)); + InsertWorkHistoryToDatabaseAndReturn(work.Id, 40, DateTime.UtcNow.AddDays(1)); + var list = _workStorageContract.GetHistoryByWorkId(Guid.NewGuid().ToString()); + Assert.That(list, Is.Not.Null); + Assert.That(list, Has.Count.EqualTo(0)); + } + + [Test] + public void Try_GetElementById_WhenHaveRecord_Test() + { + var work = InsertWorkToDatabaseAndReturn(_premises.Id); + AssertElement(_workStorageContract.GetElementById(work.Id), work); + } + + [Test] + public void Try_GetElementById_WhenNoRecord_Test() + { + InsertWorkToDatabaseAndReturn(_premises.Id); + Assert.That(() => _workStorageContract.GetElementById(Guid.NewGuid().ToString()), Is.Null); + } + + [Test] + public void Try_GetElementById_WhenRecordHasDeleted_Test() + { + var work = InsertWorkToDatabaseAndReturn(_premises.Id, isCancel: true); + Assert.That(() => _workStorageContract.GetElementById(work.Id), Is.Null); + } + + [Test] + public void Try_AddElement_Test() + { + var work = CreateModel(Guid.NewGuid().ToString(), [_worker.Id], _premises.Id, isCancel: false); + _workStorageContract.AddElement(work); + AssertElement(GetWorkFromDatabaseById(work.Id), work); + } + + [Test] + public void Try_AddElement_WhenIsCancelIsTrue_Test() + { + var work = CreateModel(Guid.NewGuid().ToString(), [_worker.Id], _premises.Id, isCancel: true); + Assert.That(() => _workStorageContract.AddElement(work), Throws.Nothing); + AssertElement(GetWorkFromDatabaseById(work.Id), CreateModel(work.Id, [_worker.Id], _premises.Id, isCancel: false)); + } + + [Test] + public void Try_DelElement_Test() + { + var work = InsertWorkToDatabaseAndReturn(_premises.Id, isCancel: false); + _workStorageContract.DelElement(work.Id); + var element = GetWorkFromDatabaseById(work.Id); + Assert.Multiple(() => + { + Assert.That(element, Is.Not.Null); + Assert.That(element!.IsCancel); + }); + } + + [Test] + public void Try_DelElement_WhenNoRecordWithThisId_Test() + { + Assert.That(() => _workStorageContract.DelElement(Guid.NewGuid().ToString()), Throws.TypeOf()); + } + + [Test] + public void Try_DelElement_WhenRecordWasDeleted_Test() + { + var work = InsertWorkToDatabaseAndReturn(_premises.Id, isCancel: true); + Assert.That(() => _workStorageContract.DelElement(work.Id), Throws.TypeOf()); + } + + private Worker InsertWorkerToDatabaseAndReturn(string fio = "test") + { + var worker = new Worker() { Id = Guid.NewGuid().ToString(), FIO = fio, PostId = Guid.NewGuid().ToString() }; + TwoFromTheCaseDbContext.Workers.Add(worker); + TwoFromTheCaseDbContext.SaveChanges(); + return worker; + } + + private Customer InsertCustomerToDatabaseAndReturn() + { + var customer = new Customer() { Id = Guid.NewGuid().ToString(), Name = "name", PhoneNumber = "+7-777-777-77-78" }; + TwoFromTheCaseDbContext.Customers.Add(customer); + TwoFromTheCaseDbContext.SaveChanges(); + return customer; + } + + private Premises InsertPremisesToDatabaseAndReturn() + { + var premises = new Premises() { Id = Guid.NewGuid().ToString(), CustomerId = _customer.Id }; + TwoFromTheCaseDbContext.Premises.Add(premises); + TwoFromTheCaseDbContext.SaveChanges(); + return premises; + } + + private Work InsertWorkToDatabaseAndReturn(string premisesId, double price = 1, DateTime? startDate = null, bool isCancel = false, List<(string, int)>? workers = null) + { + var work = new Work() { PremisesId = premisesId, Price = price, StartDate = startDate ?? DateTime.UtcNow, IsCancel = isCancel, WorkerWorks = [] }; + if (workers is not null) + { + foreach (var elem in workers) + { + work.WorkerWorks.Add(new WorkerWork { WorkerId = elem.Item1, WorkId = work.Id, Hours = elem.Item2 }); + } + } + TwoFromTheCaseDbContext.Works.Add(work); + TwoFromTheCaseDbContext.SaveChanges(); + return work; + } + + private WorkHistory InsertWorkHistoryToDatabaseAndReturn(string workId, double price, DateTime changeDate) + { + var workHistory = new WorkHistory() { Id = Guid.NewGuid().ToString(), WorkId = workId, OldPrice = price, ChangeDate = changeDate }; + TwoFromTheCaseDbContext.WorkHistories.Add(workHistory); + TwoFromTheCaseDbContext.SaveChanges(); + return workHistory; + } + + private static void AssertElement(WorkDataModel? actual, Work expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.Id, Is.EqualTo(expected.Id)); + Assert.That(actual.PremisesId, Is.EqualTo(expected.PremisesId)); + Assert.That(actual.Price, Is.EqualTo(expected.Price)); + Assert.That(actual.IsCancel, Is.EqualTo(expected.IsCancel)); + }); + + if (expected.WorkerWorks is not null) + { + Assert.That(actual.Workers, Is.Not.Null); + Assert.That(actual.Workers, Has.Count.EqualTo(expected.WorkerWorks.Count)); + for (int i = 0; i < actual.Workers.Count; ++i) + { + Assert.Multiple(() => + { + Assert.That(actual.Workers[i].WorkId, Is.EqualTo(expected.WorkerWorks[i].WorkId)); + Assert.That(actual.Workers[i].Hours, Is.EqualTo(expected.WorkerWorks[i].Hours)); + }); + } + } + else + { + Assert.That(actual.Workers, Is.Null); + } + } + + private static WorkDataModel CreateModel(string id, List workerIds, string PremisesId, double price = 1, bool isCancel = false) + { + var workers = workerIds.Select(x => new WorkerWorkDataModel(x, id, 1)).ToList(); + return new(id, PremisesId, price, isCancel, workers); + } + + private Work? GetWorkFromDatabaseById(string id) => TwoFromTheCaseDbContext.Works.FirstOrDefault(x => x.Id == id); + + private static void AssertElement(Work? actual, WorkDataModel expected) + { + Assert.That(actual, Is.Not.Null); + Assert.Multiple(() => + { + Assert.That(actual.Id, Is.EqualTo(expected.Id)); + Assert.That(actual.PremisesId, Is.EqualTo(expected.PremisesId)); + Assert.That(actual.Price, Is.EqualTo(expected.Price)); + Assert.That(actual.IsCancel, Is.EqualTo(expected.IsCancel)); + }); + + if (expected.Workers is not null) + { + Assert.That(actual.WorkerWorks, Is.Not.Null); + Assert.That(actual.WorkerWorks, Has.Count.EqualTo(expected.Workers.Count)); + for (int i = 0; i < actual.WorkerWorks.Count; ++i) + { + Assert.Multiple(() => + { + Assert.That(actual.WorkerWorks[i].WorkId, Is.EqualTo(expected.Workers[i].WorkId)); + Assert.That(actual.WorkerWorks[i].Hours, Is.EqualTo(expected.Workers[i].Hours)); + }); + } + } + else + { + Assert.That(actual.WorkerWorks, Is.Null); + } + } +} diff --git a/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/WorkerStorageContractTests.cs b/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/WorkerStorageContractTests.cs new file mode 100644 index 0000000..bfc5aa5 --- /dev/null +++ b/TwoFromTheCaseProject/TwoFromTheCaseTests/StoragesContracts/WorkerStorageContractTests.cs @@ -0,0 +1,226 @@ +using Microsoft.EntityFrameworkCore; +using TwoFromTheCaseContracts.DataModels; +using TwoFromTheCaseContracts.Exceptions; +using TwoFromTheCaseDatabase.Implementations; +using TwoFromTheCaseDatabase.Models; +using TwoFromTheCaseTests.StoragesContracts; + +namespace TwoFromTheCaseTests.StoragesContracts; + +[TestFixture] +internal class WorkerStorageContractTests : BaseStorageContractTest +{ + private WorkerStorageContract _workerStorageContract; + + [SetUp] + public void SetUp() + { + _workerStorageContract = new WorkerStorageContract(TwoFromTheCaseDbContext); + } + + [TearDown] + public void TearDown() + { + TwoFromTheCaseDbContext.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 }; + TwoFromTheCaseDbContext.Workers.Add(worker); + TwoFromTheCaseDbContext.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) => TwoFromTheCaseDbContext.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)); + }); + } +} \ No newline at end of file diff --git a/TwoFromTheCaseProject/TwoFromTheCaseTests/TwoFromTheCaseTests.csproj b/TwoFromTheCaseProject/TwoFromTheCaseTests/TwoFromTheCaseTests.csproj index ba71920..74c590d 100644 --- a/TwoFromTheCaseProject/TwoFromTheCaseTests/TwoFromTheCaseTests.csproj +++ b/TwoFromTheCaseProject/TwoFromTheCaseTests/TwoFromTheCaseTests.csproj @@ -20,6 +20,7 @@ + -- 2.25.1