До начала тестов!

This commit is contained in:
2025-03-10 12:22:57 +04:00
parent 397fd64eaf
commit de63a5844a
19 changed files with 1065 additions and 0 deletions

View File

@@ -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

View File

@@ -0,0 +1,6 @@
namespace SquirrelContract.Exceptions;
public class ElementDeletedException : Exception
{
public ElementDeletedException(string id) : base($"Cannot modify a deleted item (id: {id})") { }
}

View File

@@ -0,0 +1,6 @@
namespace SquirrelContract.Infastructure;
public interface IConfigurationDatabase
{
string ConnectionString { get; }
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}

View 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; }
}

View 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; }
}

View 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; }
}

View 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; }
}

View 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; }
}

View 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; }
}

View 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; }
}

View 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; }
}

View 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>

View 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; }
}