До начала тестов!
This commit is contained in:
@@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SquirrelTests", "SquirrelTe
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SquirrelBusinessLogic", "SquirrelBusinessLogic\SquirrelBusinessLogic.csproj", "{C03D0604-CD06-42DA-99CB-23B8306C3714}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SquirrelDatabase", "SquirrelDatabase\SquirrelDatabase.csproj", "{A8A7A434-A278-4362-8D34-C2E3CAA938C1}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -27,6 +29,10 @@ Global
|
||||
{C03D0604-CD06-42DA-99CB-23B8306C3714}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C03D0604-CD06-42DA-99CB-23B8306C3714}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C03D0604-CD06-42DA-99CB-23B8306C3714}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A8A7A434-A278-4362-8D34-C2E3CAA938C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A8A7A434-A278-4362-8D34-C2E3CAA938C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A8A7A434-A278-4362-8D34-C2E3CAA938C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A8A7A434-A278-4362-8D34-C2E3CAA938C1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace SquirrelContract.Exceptions;
|
||||
|
||||
public class ElementDeletedException : Exception
|
||||
{
|
||||
public ElementDeletedException(string id) : base($"Cannot modify a deleted item (id: {id})") { }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace SquirrelContract.Infastructure;
|
||||
|
||||
public interface IConfigurationDatabase
|
||||
{
|
||||
string ConnectionString { get; }
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
using AutoMapper;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Npgsql;
|
||||
using SquirrelContract.DataModels;
|
||||
using SquirrelContract.Exceptions;
|
||||
using SquirrelContract.StoragesContracts;
|
||||
using SquirrelDatabase.Models;
|
||||
using System;
|
||||
|
||||
namespace SquirrelDatabase.Implementations;
|
||||
|
||||
internal class ClientStorageContract : IClientStorageContract
|
||||
{
|
||||
private readonly SquirrelDbContext _dbContext;
|
||||
private readonly Mapper _mapper;
|
||||
|
||||
public ClientStorageContract(SquirrelDbContext squirrelDbContext)
|
||||
{
|
||||
_dbContext = squirrelDbContext;
|
||||
var config = new MapperConfiguration(cfg =>
|
||||
{
|
||||
cfg.CreateMap<Client, ClientDataModel>();
|
||||
cfg.CreateMap<ClientDataModel, Client>();
|
||||
});
|
||||
_mapper = new Mapper(config);
|
||||
}
|
||||
|
||||
public List<ClientDataModel> GetList()
|
||||
{
|
||||
try
|
||||
{
|
||||
return [.. _dbContext.Clients.Select(x => _mapper.Map<ClientDataModel>(x))];
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public ClientDataModel? GetElementById(string id)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _mapper.Map<ClientDataModel>(GetClientById(id));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public ClientDataModel? GetElementByFIO(string fio)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _mapper.Map<ClientDataModel>(_dbContext.Clients.FirstOrDefault(x => x.FIO == fio));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public ClientDataModel? GetElementByPhoneNumber(string phoneNumber)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _mapper.Map<ClientDataModel>(_dbContext.Clients.FirstOrDefault(x => x.PhoneNumber == phoneNumber));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddElement(ClientDataModel clientDataModel)
|
||||
{
|
||||
try
|
||||
{
|
||||
_dbContext.Clients.Add(_mapper.Map<Client>(clientDataModel));
|
||||
_dbContext.SaveChanges();
|
||||
}
|
||||
catch (InvalidOperationException ex) when (ex.TargetSite?.Name == "ThrowIdentityConflict")
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new ElementExistsException("Id", clientDataModel.Id);
|
||||
}
|
||||
catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Clients_PhoneNumber" })
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new ElementExistsException("PhoneNumber", clientDataModel.PhoneNumber);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdElement(ClientDataModel clientDataModel)
|
||||
{
|
||||
try
|
||||
{
|
||||
var element = GetClientById(clientDataModel.Id) ?? throw new ElementNotFoundException(clientDataModel.Id);
|
||||
_dbContext.Clients.Update(_mapper.Map(clientDataModel, element));
|
||||
_dbContext.SaveChanges();
|
||||
}
|
||||
catch (ElementNotFoundException)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw;
|
||||
}
|
||||
catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Clients_PhoneNumber" })
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new ElementExistsException("PhoneNumber", clientDataModel.PhoneNumber);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void DelElement(string id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var element = GetClientById(id) ?? throw new ElementNotFoundException(id);
|
||||
_dbContext.Clients.Remove(element);
|
||||
_dbContext.SaveChanges();
|
||||
}
|
||||
catch (ElementNotFoundException)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private Client? GetClientById(string id) => _dbContext.Clients.FirstOrDefault(x => x.Id == id);
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
using AutoMapper;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Npgsql;
|
||||
using SquirrelContract.DataModels;
|
||||
using SquirrelContract.Exceptions;
|
||||
using SquirrelContract.StoragesContracts;
|
||||
using SquirrelDatabase.Models;
|
||||
|
||||
namespace SquirrelDatabase.Implementations;
|
||||
|
||||
internal class CocktailStorageContract : ICocktailStorageContract
|
||||
{
|
||||
private readonly SquirrelDbContext _dbContext;
|
||||
private readonly Mapper _mapper;
|
||||
|
||||
public CocktailStorageContract(SquirrelDbContext dbContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
var config = new MapperConfiguration(cfg =>
|
||||
{
|
||||
cfg.CreateMap<Cocktail, CocktailDataModel>();
|
||||
cfg.CreateMap<CocktailDataModel, Cocktail>();
|
||||
cfg.CreateMap<CocktailHistory, CocktailHistoryDataModel>();
|
||||
});
|
||||
_mapper = new Mapper(config);
|
||||
}
|
||||
|
||||
public List<CocktailDataModel> GetList()
|
||||
{
|
||||
try
|
||||
{
|
||||
return [.. _dbContext.Cocktails.Select(x => _mapper.Map<CocktailDataModel>(x))];
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public List<CocktailHistoryDataModel> GetHistoryByCocktailId(string cocktailId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return [.. _dbContext.CocktailHistories.Where(x => x.CocktailId == cocktailId).OrderByDescending(x => x.ChangeDate).Select(x => _mapper.Map<CocktailHistoryDataModel>(x))];
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public CocktailDataModel? GetElementById(string id)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _mapper.Map<CocktailDataModel>(GetCocktailById(id));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public CocktailDataModel? GetElementByName(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _mapper.Map<CocktailDataModel>(_dbContext.Cocktails.FirstOrDefault(x => x.CocktailName == name));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddElement(CocktailDataModel cocktailDataModel)
|
||||
{
|
||||
try
|
||||
{
|
||||
_dbContext.Cocktails.Add(_mapper.Map<Cocktail>(cocktailDataModel));
|
||||
_dbContext.SaveChanges();
|
||||
}
|
||||
catch (InvalidOperationException ex) when (ex.TargetSite?.Name == "ThrowIdentityConflict")
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new ElementExistsException("Id", cocktailDataModel.Id);
|
||||
}
|
||||
catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Cocktails_CocktailName" })
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new ElementExistsException("CocktailName", cocktailDataModel.CocktailName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdElement(CocktailDataModel cocktailDataModel)
|
||||
{
|
||||
try
|
||||
{
|
||||
var element = GetCocktailById(cocktailDataModel.Id) ?? throw new ElementNotFoundException(cocktailDataModel.Id);
|
||||
_dbContext.Cocktails.Update(_mapper.Map(cocktailDataModel, element));
|
||||
_dbContext.SaveChanges();
|
||||
}
|
||||
catch (ElementNotFoundException)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw;
|
||||
}
|
||||
catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_Cocktails_CocktailName" })
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new ElementExistsException("CocktailName", cocktailDataModel.CocktailName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void DelElement(string id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var element = GetCocktailById(id) ?? throw new ElementNotFoundException(id);
|
||||
_dbContext.Cocktails.Remove(element);
|
||||
_dbContext.SaveChanges();
|
||||
}
|
||||
catch (ElementNotFoundException)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void ResElement(string id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var element = GetCocktailById(id) ?? throw new ElementNotFoundException(id);
|
||||
_dbContext.SaveChanges();
|
||||
}
|
||||
catch
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private Cocktail? GetCocktailById(string id) => _dbContext.Cocktails.FirstOrDefault(x => x.Id == id);
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
using AutoMapper;
|
||||
using SquirrelContract.DataModels;
|
||||
using SquirrelContract.Exceptions;
|
||||
using SquirrelContract.StoragesContracts;
|
||||
using SquirrelDatabase.Models;
|
||||
|
||||
namespace SquirrelDatabase.Implementations;
|
||||
|
||||
internal class EmployeeStorageContract : IEmployeeStorageContract
|
||||
{
|
||||
private readonly SquirrelDbContext _dbContext;
|
||||
private readonly Mapper _mapper;
|
||||
|
||||
public EmployeeStorageContract(SquirrelDbContext dbContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
var config = new MapperConfiguration(cfg =>
|
||||
{
|
||||
cfg.CreateMap<Employee, EmployeeDataModel>();
|
||||
cfg.CreateMap<EmployeeDataModel, Employee>();
|
||||
});
|
||||
_mapper = new Mapper(config);
|
||||
}
|
||||
|
||||
public List<EmployeeDataModel> GetList(bool onlyActive = true, string? postId = null, DateTime? fromBirthDate = null, DateTime? toBirthDate = null, DateTime? fromEmploymentDate = null, DateTime? toEmploymentDate = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var query = _dbContext.Employees.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<EmployeeDataModel>(x))];
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public EmployeeDataModel? GetElementById(string id)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _mapper.Map<EmployeeDataModel>(GetEmployeeById(id));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public EmployeeDataModel? GetElementByFIO(string fio)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _mapper.Map<EmployeeDataModel>(_dbContext.Employees.FirstOrDefault(x => x.FIO == fio));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public EmployeeDataModel? GetElementByEmail(string email)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _mapper.Map<EmployeeDataModel>(_dbContext.Employees.FirstOrDefault(x => x.Email == email));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddElement(EmployeeDataModel employeeDataModel)
|
||||
{
|
||||
try
|
||||
{
|
||||
_dbContext.Employees.Add(_mapper.Map<Employee>(employeeDataModel));
|
||||
_dbContext.SaveChanges();
|
||||
}
|
||||
catch (InvalidOperationException ex) when (ex.TargetSite?.Name == "ThrowIdentityConflict")
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new ElementExistsException("Id", employeeDataModel.Id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdElement(EmployeeDataModel employeeDataModel)
|
||||
{
|
||||
try
|
||||
{
|
||||
var element = GetEmployeeById(employeeDataModel.Id) ?? throw new ElementNotFoundException(employeeDataModel.Id);
|
||||
_dbContext.Employees.Update(_mapper.Map(employeeDataModel, 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 = GetEmployeeById(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 Employee? GetEmployeeById(string id) => _dbContext.Employees.FirstOrDefault(x => x.Id == id && !x.IsDeleted);
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
using AutoMapper;
|
||||
using CatHasPawsContratcs.Exceptions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Npgsql;
|
||||
using SquirrelContract.DataModels;
|
||||
using SquirrelContract.Exceptions;
|
||||
using SquirrelContract.StoragesContracts;
|
||||
using SquirrelDatabase.Models;
|
||||
|
||||
namespace SquirrelDatabase.Implementations;
|
||||
|
||||
internal class PostStorageContract : IPostStorageContract
|
||||
{
|
||||
private readonly SquirrelDbContext _dbContext;
|
||||
private readonly Mapper _mapper;
|
||||
|
||||
public PostStorageContract(SquirrelDbContext dbContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
var config = new MapperConfiguration(cfg =>
|
||||
{
|
||||
cfg.CreateMap<Post, PostDataModel>()
|
||||
.ForMember(x => x.Id, x => x.MapFrom(src => src.PostId));
|
||||
cfg.CreateMap<PostDataModel, Post>()
|
||||
.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<PostDataModel> GetList(bool onlyActual = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
var query = _dbContext.Posts.AsQueryable();
|
||||
if (onlyActual)
|
||||
{
|
||||
query = query.Where(x => x.IsActual);
|
||||
}
|
||||
return [.. query.Select(x => _mapper.Map<PostDataModel>(x))];
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public List<PostDataModel> GetPostWithHistory(string postId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return [.. _dbContext.Posts.Where(x => x.PostId == postId).Select(x => _mapper.Map<PostDataModel>(x))];
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public PostDataModel? GetElementById(string id)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _mapper.Map<PostDataModel>(_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<PostDataModel>(_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<Post>(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<Post>(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();
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using AutoMapper;
|
||||
using BarBelochkaContract.DataModels;
|
||||
using SquirrelContract.Exceptions;
|
||||
using SquirrelContract.StoragesContracts;
|
||||
using SquirrelDatabase.Models;
|
||||
|
||||
namespace SquirrelDatabase.Implementations;
|
||||
|
||||
internal class SalaryStorageContract : ISalaryStorageContract
|
||||
{
|
||||
private readonly SquirrelDbContext _dbContext;
|
||||
private readonly Mapper _mapper;
|
||||
|
||||
public SalaryStorageContract(SquirrelDbContext dbContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
var config = new MapperConfiguration(cfg =>
|
||||
{
|
||||
cfg.CreateMap<Salary, SalaryDataModel>();
|
||||
cfg.CreateMap<SalaryDataModel, Salary>()
|
||||
.ForMember(dest => dest.EmployeeSalary, opt => opt.MapFrom(src => src.Salary));
|
||||
});
|
||||
_mapper = new Mapper(config);
|
||||
}
|
||||
|
||||
public List<SalaryDataModel> GetList(DateTime startDate, DateTime endDate, string? employeeId = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var query = _dbContext.Salaries.Where(x => x.SalaryDate >= startDate && x.SalaryDate <= endDate);
|
||||
if (employeeId is not null)
|
||||
{
|
||||
query = query.Where(x => x.EmployeeId == employeeId);
|
||||
}
|
||||
return [.. query.Select(x => _mapper.Map<SalaryDataModel>(x))];
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddElement(SalaryDataModel salaryDataModel)
|
||||
{
|
||||
try
|
||||
{
|
||||
_dbContext.Salaries.Add(_mapper.Map<Salary>(salaryDataModel));
|
||||
_dbContext.SaveChanges();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
using AutoMapper;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SquirrelContract.DataModels;
|
||||
using SquirrelContract.Exceptions;
|
||||
using SquirrelDatabase.Models;
|
||||
|
||||
namespace SquirrelDatabase.Implementations;
|
||||
|
||||
internal class SaleStorageContract
|
||||
{
|
||||
private readonly SquirrelDbContext _dbContext;
|
||||
private readonly Mapper _mapper;
|
||||
|
||||
public SaleStorageContract(SquirrelDbContext dbContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
var config = new MapperConfiguration(cfg =>
|
||||
{
|
||||
cfg.CreateMap<SaleCocktail, SaleCocktailDataModel>();
|
||||
cfg.CreateMap<SaleCocktailDataModel, SaleCocktail>();
|
||||
cfg.CreateMap<Sale, SaleDataModel>();
|
||||
cfg.CreateMap<SaleDataModel, Sale>()
|
||||
.ForMember(x => x.IsCancel, x => x.MapFrom(src => false))
|
||||
.ForMember(x => x.SaleCocktails, x => x.MapFrom(src => src.Cocktails));
|
||||
});
|
||||
_mapper = new Mapper(config);
|
||||
}
|
||||
|
||||
public List<SaleDataModel> GetList(DateTime? startDate = null, DateTime? endDate = null, string? employeeId = null, string? clientId = null, string? cocktailId = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var query = _dbContext.Sales.Include(x => x.SaleCocktails).AsQueryable();
|
||||
if (startDate is not null && endDate is not null)
|
||||
{
|
||||
query = query.Where(x => x.SaleDate >= startDate && x.SaleDate < endDate);
|
||||
}
|
||||
if (employeeId is not null)
|
||||
{
|
||||
query = query.Where(x => x.EmployeeId == employeeId);
|
||||
}
|
||||
if (clientId is not null)
|
||||
{
|
||||
query = query.Where(x => x.ClientId == clientId);
|
||||
}
|
||||
if (cocktailId is not null)
|
||||
{
|
||||
query = query.Where(x => x.SaleCocktails!.Any(y => y.CocktailId == cocktailId));
|
||||
}
|
||||
return [.. query.Select(x => _mapper.Map<SaleDataModel>(x))];
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public SaleDataModel? GetElementById(string id)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _mapper.Map<SaleDataModel>(GetSaleById(id));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddElement(SaleDataModel saleDataModel)
|
||||
{
|
||||
try
|
||||
{
|
||||
_dbContext.Sales.Add(_mapper.Map<Sale>(saleDataModel));
|
||||
_dbContext.SaveChanges();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void DelElement(string id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var element = GetSaleById(id) ?? throw new ElementNotFoundException(id);
|
||||
if (element.IsCancel)
|
||||
{
|
||||
throw new ElementDeletedException(id);
|
||||
}
|
||||
element.IsCancel = true;
|
||||
_dbContext.SaveChanges();
|
||||
}
|
||||
catch (Exception ex) when (ex is ElementDeletedException || ex is ElementNotFoundException)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
throw new StorageException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private Sale? GetSaleById(string id) => _dbContext.Sales.FirstOrDefault(x => x.Id == id);
|
||||
}
|
||||
15
SquirrelContract/SquirrelDatabase/Models/Client.cs
Normal file
15
SquirrelContract/SquirrelDatabase/Models/Client.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace SquirrelDatabase.Models;
|
||||
|
||||
internal class Client
|
||||
{
|
||||
public required string Id { get; set; } = Guid.NewGuid().ToString();
|
||||
public required string FIO { get; set; }
|
||||
public required string PhoneNumber { get; set; }
|
||||
public double DiscountSize { get; set; }
|
||||
|
||||
[ForeignKey("ClientId")]
|
||||
public List<Sale>? Sales { get; set; }
|
||||
|
||||
}
|
||||
18
SquirrelContract/SquirrelDatabase/Models/Cocktail.cs
Normal file
18
SquirrelContract/SquirrelDatabase/Models/Cocktail.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using SquirrelContract.Enums;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace SquirrelDatabase.Models;
|
||||
|
||||
internal class Cocktail
|
||||
{
|
||||
public required string Id { get; set; }
|
||||
public required string CocktailName { get; set; }
|
||||
public double Price { get; set; }
|
||||
public required AlcoholType BaseAlcohol { get; set; }
|
||||
|
||||
[ForeignKey("CocktailId")]
|
||||
public List<CocktailHistory>? CocktailHistories { get; set; }
|
||||
|
||||
[ForeignKey("CocktailId")]
|
||||
public List<SaleCocktail>? SaleCocktails { get; set; }
|
||||
}
|
||||
14
SquirrelContract/SquirrelDatabase/Models/CocktailHistory.cs
Normal file
14
SquirrelContract/SquirrelDatabase/Models/CocktailHistory.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace SquirrelDatabase.Models;
|
||||
|
||||
internal class CocktailHistory
|
||||
{
|
||||
public string Id { get; set; } = Guid.NewGuid().ToString();
|
||||
|
||||
public required string CocktailId { get; set; }
|
||||
|
||||
public double OldPrice { get; set; }
|
||||
|
||||
public DateTime ChangeDate { get; set; }
|
||||
|
||||
public Cocktail? Cocktail { get; set; }
|
||||
}
|
||||
26
SquirrelContract/SquirrelDatabase/Models/Employee.cs
Normal file
26
SquirrelContract/SquirrelDatabase/Models/Employee.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace SquirrelDatabase.Models;
|
||||
|
||||
internal class Employee
|
||||
{
|
||||
public required string Id { get; set; }
|
||||
|
||||
public required string FIO { get; set; }
|
||||
|
||||
public string Email { get; set; }
|
||||
|
||||
public string PostId { get; set; }
|
||||
|
||||
public DateTime BirthDate { get; set; }
|
||||
|
||||
public DateTime EmploymentDate { get; set; }
|
||||
|
||||
public bool IsDeleted { get; set; }
|
||||
|
||||
[ForeignKey("EmployeeId")]
|
||||
public List<Salary>? Salaries { get; set; }
|
||||
|
||||
[ForeignKey("EmployeeId")]
|
||||
public List<Sale>? Sales { get; set; }
|
||||
}
|
||||
20
SquirrelContract/SquirrelDatabase/Models/Post.cs
Normal file
20
SquirrelContract/SquirrelDatabase/Models/Post.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using SquirrelContract.Enums;
|
||||
|
||||
namespace SquirrelDatabase.Models;
|
||||
|
||||
internal class Post
|
||||
{
|
||||
public required string Id { get; set; } = Guid.NewGuid().ToString();
|
||||
|
||||
public required string PostId { get; set; }
|
||||
|
||||
public required string PostName { get; set; }
|
||||
|
||||
public required PostType PostType { get; set; }
|
||||
|
||||
public double Salary { get; set; }
|
||||
|
||||
public bool IsActual { get; set; }
|
||||
|
||||
public DateTime ChangeDate { get; set; }
|
||||
}
|
||||
13
SquirrelContract/SquirrelDatabase/Models/Salary.cs
Normal file
13
SquirrelContract/SquirrelDatabase/Models/Salary.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace SquirrelDatabase.Models;
|
||||
|
||||
internal class Salary
|
||||
{
|
||||
public required string EmployeeId { get; set; }
|
||||
|
||||
public DateTime SalaryDate { get; set; }
|
||||
|
||||
public double EmployeeSalary { get; set; }
|
||||
|
||||
public Employee? Employee { get; set; }
|
||||
|
||||
}
|
||||
31
SquirrelContract/SquirrelDatabase/Models/Sale.cs
Normal file
31
SquirrelContract/SquirrelDatabase/Models/Sale.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using SquirrelContract.DataModels;
|
||||
using SquirrelContract.Enums;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace SquirrelDatabase.Models;
|
||||
|
||||
internal class Sale
|
||||
{
|
||||
public string Id { get; set; } = Guid.NewGuid().ToString();
|
||||
|
||||
public required string EmployeeId { get; set; }
|
||||
|
||||
public string? ClientId { get; set; }
|
||||
|
||||
public DateTime SaleDate { get; set; }
|
||||
|
||||
public double Sum { get; set; }
|
||||
|
||||
public DiscountType DiscountType { get; set; }
|
||||
|
||||
public double Discount { get; set; }
|
||||
|
||||
public bool IsCancel { get; set; }
|
||||
|
||||
public Employee? Employee { get; set; }
|
||||
|
||||
public Client? Client { get; set; }
|
||||
|
||||
[ForeignKey("SaleId")]
|
||||
public List<SaleCocktailDataModel>? SaleCocktails { get; set; }
|
||||
}
|
||||
10
SquirrelContract/SquirrelDatabase/Models/SaleCocktail.cs
Normal file
10
SquirrelContract/SquirrelDatabase/Models/SaleCocktail.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace SquirrelDatabase.Models;
|
||||
|
||||
internal class SaleCocktail
|
||||
{
|
||||
public required string SaleId { get; set; }
|
||||
|
||||
public required string CocktailId { get; set; }
|
||||
|
||||
public int Count { get; set; }
|
||||
}
|
||||
20
SquirrelContract/SquirrelDatabase/SquirrelDatabase.csproj
Normal file
20
SquirrelContract/SquirrelDatabase/SquirrelDatabase.csproj
Normal file
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper" Version="14.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.2" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SquirrelContract\SquirrelContract.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
53
SquirrelContract/SquirrelDatabase/SquirrelDbContext.cs
Normal file
53
SquirrelContract/SquirrelDatabase/SquirrelDbContext.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SquirrelContract.Infastructure;
|
||||
using SquirrelDatabase.Models;
|
||||
using System;
|
||||
namespace SquirrelDatabase;
|
||||
|
||||
internal class SquirrelDbContext(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<Client>().HasIndex(x => x.PhoneNumber).IsUnique();
|
||||
|
||||
modelBuilder.Entity<Cocktail>().HasIndex(x => x.CocktailName).IsUnique();
|
||||
|
||||
modelBuilder.Entity<Post>()
|
||||
.HasIndex(e => new { e.PostName, e.IsActual })
|
||||
.IsUnique()
|
||||
.HasFilter($"\"{nameof(Post.IsActual)}\" = TRUE");
|
||||
|
||||
modelBuilder.Entity<Post>()
|
||||
.HasIndex(e => new { e.PostId, e.IsActual })
|
||||
.IsUnique()
|
||||
.HasFilter($"\"{nameof(Post.IsActual)}\" = TRUE");
|
||||
|
||||
modelBuilder.Entity<SaleCocktail>().HasKey(x => new { x.SaleId, x.CocktailId });
|
||||
}
|
||||
|
||||
public DbSet<Client> Clients { get; set; }
|
||||
|
||||
public DbSet<Post> Posts { get; set; }
|
||||
|
||||
public DbSet<Cocktail> Cocktails { get; set; }
|
||||
|
||||
public DbSet<CocktailHistory> CocktailHistories { get; set; }
|
||||
|
||||
public DbSet<Salary> Salaries { get; set; }
|
||||
|
||||
public DbSet<Sale> Sales { get; set; }
|
||||
|
||||
public DbSet<SaleCocktail> SaleCocktails { get; set; }
|
||||
|
||||
public DbSet<Employee> Employees { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user