19 Commits

Author SHA1 Message Date
995cdbb057 user storage tests 2025-08-19 19:33:11 +04:00
d15cb6e2a7 StorekeeperStorageContract 2025-08-18 14:23:58 +04:00
3fc34acfa7 Storage final additions, forgotten user business logic, user storage implementation, missing storekeeper 2025-08-16 00:40:27 +04:00
5bfdbeb824 StoreKeeper StorageContracts 2025-08-12 19:47:51 +04:00
5061e98351 Merge branch 'Task_3_Storage' of https://git.is.ulstu.ru/strwbrry/PIBD-23_Coursach_YouAreProgrammerShop into Task_3_Storage 2025-08-12 19:44:21 +04:00
36d1ec8697 added missing DB connections, Storekeeper connections needed 2025-08-06 21:20:59 +04:00
6d8cfc4fa2 Merge branch 'Task_3_Storage' of https://git.is.ulstu.ru/strwbrry/PIBD-23_Coursach_YouAreProgrammerShop into Task_3_Storage 2025-08-06 15:08:16 +04:00
e6857ecab0 Начало работы с сторажами сторкипера 2025-08-06 15:08:09 +04:00
a83464f3b9 Worker Storage Contracts + dbContext user adjustments, missing UserStorageContext 2025-05-27 22:59:40 +04:00
87033022bb DbContext + models, StorageContract interfaces for Worker 2025-05-27 03:30:26 +04:00
d05e270321 merging branches 2025-05-27 01:00:23 +04:00
28b9ef2a11 StorageContracts storekeeper 2025-05-27 00:32:58 +04:00
bcb8db763d revert user changes 2025-05-27 00:09:01 +04:00
a77fcc6d38 beginning of storage contracts 2025-05-21 11:19:15 +04:00
0b559bc434 added "onlyActual" parameter for fake deletion entity ProductSet 2025-05-21 10:24:32 +04:00
e5ee5d19f3 updated user role system, removed typo 2025-05-17 14:19:56 +04:00
d0a173d8aa Бизнес-логика кладовщика (StorageContracts, BusinessLogicContracts, Implementations) и обновил сущности (isDeleted) 2025-05-16 01:36:43 +04:00
c350344c46 purchase adjustment, componentType 2 rename 2025-05-15 18:03:11 +04:00
8e80c00243 basic business logic, storage contract interfaces, no tests 2025-05-15 01:44:43 +04:00
76 changed files with 3089 additions and 99 deletions

View File

@@ -0,0 +1,122 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.Extensions.Logging;
using YAPContracts.BusinessLogicContracts;
using YAPContracts.DataModels;
using YAPContracts.Exceptions;
using YAPContracts.Extentions;
using YAPContracts.StorageContracts;
namespace YAPBusinessLogic.Implementations
{
internal class CommentBusinessLogicContract(ICommentStorageContract commentStorageContract, ILogger logger) : ICommentBusinessLogicContract
{
private readonly ILogger _logger = logger;
private readonly ICommentStorageContract _commentStorageContract = commentStorageContract;
public List<CommentDataModel> GetAllComments()
{
_logger.LogInformation("GetAllComments method called");
var comments = _commentStorageContract.GetList();
return comments ?? throw new NullListException();
}
public CommentDataModel? GetCommentByData(string data)
{
_logger.LogInformation("GetCommentByData method called with data: {data}", data);
if (data.IsEmpty())
{
throw new ArgumentNullException(nameof(data));
}
if (!data.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
}
var comment = _commentStorageContract.GetElementById(data);
return comment ?? throw new ElementNotFoundException(data);
}
public List<CommentDataModel> GetCommentsByProductSetByPeriod(string productSetId, DateTime fromDate, DateTime toDate)
{
_logger.LogInformation("GetCommentsByProductSetByPeriod method called with productSetId: {productSetId}, fromDate: {fromDate}, toDate: {toDate}", productSetId, fromDate, toDate);
if (productSetId.IsEmpty())
{
throw new ArgumentNullException(nameof(productSetId));
}
if (!productSetId.IsGuid())
{
throw new ValidationException("ProductSetId is not a unique identifier");
}
if (fromDate.IsNotLaterThan(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
}
var comments = _commentStorageContract.GetList(fromDate, toDate, productSetId: productSetId);
return comments ?? throw new NullListException();
}
public List<CommentDataModel> GetCommentsByUserByPeriod(string userId, DateTime fromDate, DateTime toDate)
{
_logger.LogInformation($"GetCommentsByUserSetByPeriod method called with userId: {userId}, fromDate: {fromDate}, toDate: {toDate}", userId, fromDate, toDate);
if (userId.IsEmpty())
{
throw new ArgumentNullException(nameof(userId));
}
if (!userId.IsGuid())
{
throw new ValidationException("UserId is not a unique identifier");
}
if (fromDate.IsNotLaterThan(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
}
var comments = _commentStorageContract.GetList(fromDate, toDate, userId: userId);
return comments ?? throw new NullListException();
}
public List<CommentDataModel> GetCommentsByPeriod(DateTime fromDate, DateTime toDate)
{
_logger.LogInformation($"GetCommentsByPeriod method called with fromDate: {fromDate}, toDate: {toDate}", fromDate, toDate);
if (fromDate.IsNotLaterThan(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
}
var comments = _commentStorageContract.GetList(fromDate, toDate);
return comments ?? throw new NullListException();
}
public void InsertComment(CommentDataModel comment)
{
_logger.LogInformation("Insert data: {json}", JsonSerializer.Serialize(comment));
ArgumentNullException.ThrowIfNull(comment);
comment.Validate();
_commentStorageContract.AddElement(comment);
}
public void UpdateComment(CommentDataModel comment)
{
_logger.LogInformation("Update data: {json}", JsonSerializer.Serialize(comment));
ArgumentNullException.ThrowIfNull(comment);
comment.Validate();
_commentStorageContract.UpdateElement(comment);
}
public void DeleteComment(string id)
{
_logger.LogInformation($"Delete data by id: {id}", id);
if (id.IsEmpty())
{
throw new ArgumentNullException(nameof(id));
}
if (!id.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
}
_commentStorageContract.DeleteElement(id);
}
}
}

View File

@@ -0,0 +1,71 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using YAPContracts.BusinessLogicContracts;
using YAPContracts.DataModels;
using YAPContracts.Exceptions;
using YAPContracts.Extentions;
using YAPContracts.StorageContracts;
namespace YAPBusinessLogic.Implementations;
internal class ComponentBusinessLogicContract(IComponentStorageContract componentStorageContract, ILogger logger) : IComponentBusinessLogicContract
{
private readonly ILogger _logger = logger;
private readonly IComponentStorageContract _componentStorageContract = componentStorageContract;
public List<ComponentDataModel> GetAllComponents(bool onlyActual)
{
_logger.LogInformation("GetAllComponents params: {onlyActual}", onlyActual);
return _componentStorageContract.GetList(onlyActual) ?? throw new NullListException();
}
public ComponentDataModel GetComponentByData(string data)
{
_logger.LogInformation("Get element by data: {data}", data);
if (data.IsEmpty())
{
throw new ArgumentNullException(nameof(data));
}
if (data.IsGuid())
{
return _componentStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data);
}
return _componentStorageContract.GetElementByName(data) ??
throw new ElementNotFoundException(data);
}
public void InsertComponent(ComponentDataModel componentDataModel)
{
_logger.LogInformation("New data: {json}", JsonSerializer.Serialize(componentDataModel));
ArgumentNullException.ThrowIfNull(componentDataModel);
componentDataModel.Validate();
_componentStorageContract.AddElement(componentDataModel);
}
public void UpdateComponent(ComponentDataModel componentDataModel)
{
_logger.LogInformation("Update data: {json}", JsonSerializer.Serialize(componentDataModel));
ArgumentNullException.ThrowIfNull(componentDataModel);
componentDataModel.Validate();
_componentStorageContract.UpdElement(componentDataModel);
}
public void DeleteComponent(string id)
{
_logger.LogInformation("Delete by id: {id}", id);
if (id.IsEmpty())
{
throw new ArgumentNullException(nameof(id));
}
if (!id.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
}
_componentStorageContract.DelElement(id);
}
}

View File

@@ -0,0 +1,70 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using YAPContracts.BusinessLogicContracts;
using YAPContracts.DataModels;
using YAPContracts.Exceptions;
using YAPContracts.Extentions;
using YAPContracts.StorageContracts;
namespace YAPBusinessLogic.Implementations;
internal class ProductBusinessLogicContract(IProductStorageContract productStorageContract, ILogger logger) : IProductBusinessLogicContract
{
private readonly ILogger _logger = logger;
private readonly IProductStorageContract _productStorageContract = productStorageContract;
public void DeleteProduct(string id)
{
_logger.LogInformation("Delete by id: {id}", id);
if (id.IsEmpty())
{
throw new ArgumentNullException(nameof(id));
}
if (!id.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
}
_productStorageContract.DelElement(id);
}
public List<ProductDataModel> GetAllProducts(bool onlyActual)
{
_logger.LogInformation("GetAllProducts params: {onlyActual}", onlyActual);
return _productStorageContract.GetList(onlyActual) ?? throw new NullListException();
}
public ProductDataModel GetProductByData(string data)
{
_logger.LogInformation("Get element by data: {data}", data);
if (data.IsEmpty())
{
throw new ArgumentNullException(nameof(data));
}
if (data.IsGuid())
{
return _productStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data);
}
return _productStorageContract.GetElementByName(data) ??
throw new ElementNotFoundException(data);
}
public void InsertProduct(ProductDataModel productDataModel)
{
_logger.LogInformation("New data: {json}", JsonSerializer.Serialize(productDataModel));
ArgumentNullException.ThrowIfNull(productDataModel);
productDataModel.Validate();
_productStorageContract.AddElement(productDataModel);
}
public void UpdateProduct(ProductDataModel productDataModel)
{
_logger.LogInformation("Update data: {json}", JsonSerializer.Serialize(productDataModel));
ArgumentNullException.ThrowIfNull(productDataModel);
productDataModel.Validate();
_productStorageContract.UpdElement(productDataModel);
}
}

View File

@@ -0,0 +1,103 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using YAPContracts.BusinessLogicContracts;
using YAPContracts.DataModels;
using YAPContracts.Exceptions;
using YAPContracts.Extentions;
using YAPContracts.StorageContracts;
namespace YAPBusinessLogic.Implementations;
internal class ProductOrderBusinessLogicContract(IProductOrderStorageContract productOrderStorageContract, ILogger logger) : IProductOrderBusinessLogicContract
{
private readonly ILogger _logger = logger;
private readonly IProductOrderStorageContract _productOrderStorageContract = productOrderStorageContract;
public List<ProductOrderDataModel> GetAllProductOrders(bool onlyActual = true)
{
_logger.LogInformation("GetAllProductOrders params: {onlyActual}", onlyActual);
return _productOrderStorageContract.GetList(onlyActual) ?? throw new NullListException();
}
public ProductOrderDataModel GetProductOrderByData(string data)
{
_logger.LogInformation("Get element by data: {data}", data);
if (data.IsEmpty())
{
throw new ArgumentNullException(nameof(data));
}
if (data.IsGuid())
{
return _productOrderStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data);
}
return _productOrderStorageContract.GetElementByName(data) ??
throw new ElementNotFoundException(data);
}
public List<ProductOrderDataModel> GetProductOrdersByDealerByPeriod(string dealerName, DateTime fromDate, DateTime toDate, bool onlyActual = true)
{
_logger.LogInformation("GetAllProductOrders params: {dealerName}, {fromDate}, {toDate}, {onlyActual}", dealerName, fromDate, toDate, onlyActual);
if (fromDate.IsNotLaterThan(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
}
if (dealerName.IsEmpty())
{
throw new ArgumentNullException(nameof(dealerName));
}
if (!dealerName.IsGuid())
{
throw new ValidationException("The value in the field dealerName is not a unique identifier.");
}
return _productOrderStorageContract.GetList(onlyActual, fromDate, toDate, dealerName: dealerName) ?? throw new NullListException();
}
public List<ProductOrderDataModel> GetProductOrdersByPeriod(DateTime fromDate, DateTime toDate, bool onlyActual = true)
{
_logger.LogInformation("GetAllProductOrders params: {fromDate}, {toDate}, {onlyActual}", fromDate, toDate, onlyActual);
if (fromDate.IsNotLaterThan(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
}
return _productOrderStorageContract.GetList(onlyActual, fromDate, toDate) ?? throw new NullListException();
}
public List<ProductOrderDataModel> GetProductOrdersByProductByPeriod(string productId, DateTime fromDate, DateTime toDate, bool onlyActual = true)
{
_logger.LogInformation("GetAllProductOrders params: {productId}, {fromDate}, {toDate}, {onlyActual}", productId, fromDate, toDate, onlyActual);
if (fromDate.IsNotLaterThan(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
}
if (productId.IsEmpty())
{
throw new ArgumentNullException(nameof(productId));
}
if (!productId.IsGuid())
{
throw new ValidationException("The value in the field productId is not a unique identifier.");
}
return _productOrderStorageContract.GetList(onlyActual, fromDate, toDate, productId: productId) ?? throw new NullListException();
}
public void InsertProductOrder(ProductOrderDataModel productOrderDataModel)
{
_logger.LogInformation("New data: {json}", JsonSerializer.Serialize(productOrderDataModel));
ArgumentNullException.ThrowIfNull(productOrderDataModel);
productOrderDataModel.Validate();
_productOrderStorageContract.AddElement(productOrderDataModel);
}
public void UpdateProductOrder(ProductOrderDataModel productOrderDataModel)
{
_logger.LogInformation("Update data: {json}", JsonSerializer.Serialize(productOrderDataModel));
ArgumentNullException.ThrowIfNull(productOrderDataModel);
productOrderDataModel.Validate();
_productOrderStorageContract.UpdElement(productOrderDataModel);
}
}

View File

@@ -0,0 +1,73 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Xml.Linq;
using YAPContracts.BusinessLogicContracts;
using YAPContracts.DataModels;
using YAPContracts.Exceptions;
using YAPContracts.Extentions;
using YAPContracts.StorageContracts;
namespace YAPBusinessLogic.Implementations
{
internal class ProductSetBusinessLogicContract(IProductSetStorageContract productSetStorageContract, ILogger logger) : IProductSetBusinessLogicContract
{
private readonly ILogger _logger = logger;
private readonly IProductSetStorageContract _productSetStorageContract = productSetStorageContract;
public List<ProductSetDataModel> GetAllProductSets(bool onlyActual = true)
{
_logger.LogInformation($"GetAllProductSets method called with parameter onlyActual: {onlyActual}", onlyActual);
var productSets = _productSetStorageContract.GetList(onlyActual);
return productSets ?? throw new NullListException();
}
public ProductSetDataModel? GetProductSetByData(string data)
{
_logger.LogInformation($"GetProductSetByData method called with data: {data}", data);
if (data.IsEmpty())
{
throw new ArgumentNullException(nameof(data));
}
if (!data.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
}
var productSet = _productSetStorageContract.GetElementById(data);
return productSet ?? throw new ElementNotFoundException(data);
}
public void InsertProductSet(ProductSetDataModel productSet)
{
_logger.LogInformation("Insert data: {json}", JsonSerializer.Serialize(productSet));
ArgumentNullException.ThrowIfNull(productSet);
productSet.Validate();
_productSetStorageContract.AddElement(productSet);
}
public void UpdateProductSet(ProductSetDataModel productSet)
{
_logger.LogInformation("Update data: {json}", JsonSerializer.Serialize(productSet));
ArgumentNullException.ThrowIfNull(productSet);
productSet.Validate();
_productSetStorageContract.UpdateElement(productSet);
}
public void DeleteProductSet(string id)
{
_logger.LogInformation($"Delete data by id: {id}", id);
if (id.IsEmpty())
{
throw new ArgumentNullException(nameof(id));
}
if (!id.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
}
_productSetStorageContract.DeleteElement(id);
}
}
}

View File

@@ -0,0 +1,103 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Xml.Linq;
using YAPContracts.BusinessLogicContracts;
using YAPContracts.DataModels;
using YAPContracts.Exceptions;
using YAPContracts.Extentions;
using YAPContracts.StorageContracts;
namespace YAPBusinessLogic.Implementations
{
internal class PurchaseBusinessLogicContract(IPurchaseStorageContract purchaseStorageContract, ILogger logger) : IPurchaseBusinessLogicContract
{
private readonly IPurchaseStorageContract _purchaseStorageContract = purchaseStorageContract;
private readonly ILogger _logger = logger;
public List<PurchaseDataModel> GetAllPurchases()
{
_logger.LogInformation("GetAllPurchases method called");
var purchases = _purchaseStorageContract.GetList();
return purchases ?? throw new NullListException();
}
public PurchaseDataModel? GetPurchaseByData(string data)
{
_logger.LogInformation("GetPurchaseByData method called with data: {data}", data);
if (data.IsEmpty())
{
throw new ArgumentNullException(nameof(data));
}
if (!data.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
}
var comment = _purchaseStorageContract.GetElementById(data);
return comment ?? throw new ElementNotFoundException(data);
}
public List<PurchaseDataModel> GetPurchasesByUserByPeriod(string userId, DateTime fromDate, DateTime toDate)
{
_logger.LogInformation($"GetPurchasesByUserByPeriod method called with userId: {userId}, fromDate: {fromDate}, toDate: {toDate}", userId, fromDate, toDate);
if (userId.IsEmpty())
{
throw new ArgumentNullException(nameof(userId));
}
if (!userId.IsGuid())
{
throw new ValidationException("ProductSetId is not a unique identifier");
}
if (fromDate.IsNotLaterThan(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
}
var comments = _purchaseStorageContract.GetList(fromDate, toDate, userId: userId);
return comments ?? throw new NullListException();
}
public List<PurchaseDataModel> GetPurchasesByPeriod(DateTime fromDate, DateTime toDate)
{
_logger.LogInformation($"GetPurchasesByPeriod method called with fromDate: {fromDate}, toDate: {toDate}", fromDate, toDate);
if (fromDate.IsNotLaterThan(toDate))
{
throw new IncorrectDatesException(fromDate, toDate);
}
var comments = _purchaseStorageContract.GetList(fromDate, toDate);
return comments ?? throw new NullListException();
}
public void InsertPurchase(PurchaseDataModel purchase)
{
_logger.LogInformation("Insert data: {json}", JsonSerializer.Serialize(purchase));
ArgumentNullException.ThrowIfNull(purchase);
purchase.Validate();
_purchaseStorageContract.AddElement(purchase);
}
public void UpdatePurchase(PurchaseDataModel purchase)
{
_logger.LogInformation("Update data: {json}", JsonSerializer.Serialize(purchase));
ArgumentNullException.ThrowIfNull(purchase);
purchase.Validate();
_purchaseStorageContract.UpdateElement(purchase);
}
public void DeletePurchase(string id)
{
_logger.LogInformation($"Delete data by id: {id}", id);
if (id.IsEmpty())
{
throw new ArgumentNullException(nameof(id));
}
if (!id.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
}
_purchaseStorageContract.DeleteElement(id);
}
}
}

View File

@@ -0,0 +1,66 @@
using Microsoft.Extensions.Logging;
using System.Text.Json;
using YAPContracts.BusinessLogicContracts;
using YAPContracts.DataModels.UserRoles;
using YAPContracts.Exceptions;
using YAPContracts.Extentions;
using YAPContracts.StorageContracts;
namespace YAPBusinessLogic.Implementations
{
internal class StorekeeperBusinessLogicContract(ILogger logger, IStorekeeperStorageContract storekeeperStorageContract) : IStorekeeperBusinessLogicContract
{
private readonly ILogger _logger = logger;
private readonly IStorekeeperStorageContract _storekeeperStorageContract = storekeeperStorageContract;
public List<StorekeeperDataModel> GetAllStorekeepers()
{
_logger.LogInformation("GetAllStorekeepers method called");
var storekeepers = _storekeeperStorageContract.GetList();
return storekeepers ?? throw new NullListException();
}
public StorekeeperDataModel? GetStorekeeperByData(string data)
{
_logger.LogInformation("GetStorekeeperByData method called with data: {data}", data);
if (data.IsEmpty())
{
throw new ArgumentNullException(nameof(data));
}
if (data.IsGuid())
{
return _storekeeperStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data);
}
var storekeeper = _storekeeperStorageContract.GetElementByLogin(data);
return storekeeper ?? throw new ElementNotFoundException(data);
}
public void InsertStorekeeper(StorekeeperDataModel storekeeper)
{
_logger.LogInformation("Insert data: {json}", JsonSerializer.Serialize(storekeeper));
ArgumentNullException.ThrowIfNull(storekeeper);
storekeeper.Validate();
_storekeeperStorageContract.AddElement(storekeeper);
}
public void UpdateStorekeeper(StorekeeperDataModel storekeeper)
{
_logger.LogInformation("Update data: {json}", JsonSerializer.Serialize(storekeeper));
ArgumentNullException.ThrowIfNull(storekeeper);
storekeeper.Validate();
_storekeeperStorageContract.UpdateElement(storekeeper);
}
public void DeleteStorekeeper(string id)
{
_logger.LogInformation($"Delete data by id: {id}", id);
if (id.IsEmpty())
{
throw new ArgumentNullException(nameof(id));
}
if (!id.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
}
_storekeeperStorageContract.DeleteElement(id);
}
}
}

View File

@@ -0,0 +1,66 @@
using Microsoft.Extensions.Logging;
using System.Text.Json;
using YAPContracts.BusinessLogicContracts;
using YAPContracts.DataModels.UserRoles;
using YAPContracts.Exceptions;
using YAPContracts.Extentions;
using YAPContracts.StorageContracts;
namespace YAPBusinessLogic.Implementations
{
internal class WorkerBusinessLogicContract(ILogger logger, IWorkerStorageContract workerStorageContract) : IWorkerBusinessLogicContract
{
private readonly ILogger _logger = logger;
private readonly IWorkerStorageContract _workerStorageContract = workerStorageContract;
public List<WorkerDataModel> GetAllWorkers()
{
_logger.LogInformation("GetAllWorkers method called");
var workers = _workerStorageContract.GetList();
return workers ?? throw new NullListException();
}
public WorkerDataModel? GetWorkerByData(string data)
{
_logger.LogInformation("GetWorkerByData method called with data: {data}", data);
if (data.IsEmpty())
{
throw new ArgumentNullException(nameof(data));
}
if (data.IsGuid())
{
return _workerStorageContract.GetElementById(data) ?? throw new ElementNotFoundException(data);
}
var worker = _workerStorageContract.GetElementByLogin(data);
return worker ?? throw new ElementNotFoundException(data);
}
public void InsertWorker(WorkerDataModel worker)
{
_logger.LogInformation("Insert data: {json}", JsonSerializer.Serialize(worker));
ArgumentNullException.ThrowIfNull(worker);
worker.Validate();
_workerStorageContract.AddElement(worker);
}
public void UpdateWorker(WorkerDataModel worker)
{
_logger.LogInformation("Update data: {json}", JsonSerializer.Serialize(worker));
ArgumentNullException.ThrowIfNull(worker);
worker.Validate();
_workerStorageContract.UpdateElement(worker);
}
public void DeleteWorker(string id)
{
_logger.LogInformation($"Delete data by id: {id}", id);
if (id.IsEmpty())
{
throw new ArgumentNullException(nameof(id));
}
if (!id.IsGuid())
{
throw new ValidationException("Id is not a unique identifier");
}
_workerStorageContract.DeleteElement(id);
}
}
}

View File

@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<InternalsVisibleTo Include="YAPTests" />
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.5" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\YAPContracts\YAPContracts.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,3 @@
{
"help":"https://go.microsoft.com/fwlink/?linkid=866610"
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
namespace YAPContracts.BusinessLogicContracts
{
public interface ICommentBusinessLogicContract
{
List<CommentDataModel> GetAllComments();
CommentDataModel? GetCommentByData(string data);
List<CommentDataModel> GetCommentsByProductSetByPeriod(string productSetId, DateTime fromDate, DateTime toDate);
List<CommentDataModel> GetCommentsByUserByPeriod(string userId, DateTime fromDate, DateTime toDate);
List<CommentDataModel> GetCommentsByPeriod(DateTime fromDate, DateTime toDate);
void InsertComment(CommentDataModel comment);
void UpdateComment(CommentDataModel comment);
void DeleteComment(string id);
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
namespace YAPContracts.BusinessLogicContracts;
public interface IComponentBusinessLogicContract
{
List<ComponentDataModel> GetAllComponents(bool onlyActual);
ComponentDataModel GetComponentByData(string data);
void InsertComponent(ComponentDataModel componentDataModel);
void UpdateComponent(ComponentDataModel componentDataModel);
void DeleteComponent(string id);
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
namespace YAPContracts.BusinessLogicContracts;
public interface IProductBusinessLogicContract
{
List<ProductDataModel> GetAllProducts(bool onlyActual);
ProductDataModel GetProductByData(string data);
void InsertProduct(ProductDataModel productDataModel);
void UpdateProduct(ProductDataModel productDataModel);
void DeleteProduct(string id);
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
namespace YAPContracts.BusinessLogicContracts;
public interface IProductOrderBusinessLogicContract
{
List<ProductOrderDataModel> GetAllProductOrders(bool onlyActual = true);
ProductOrderDataModel GetProductOrderByData(string data);
List<ProductOrderDataModel> GetProductOrdersByProductByPeriod(string productId, DateTime fromDate, DateTime toDate, bool onlyActual = true);
List<ProductOrderDataModel> GetProductOrdersByDealerByPeriod(string dealerId, DateTime fromDate, DateTime toDate, bool onlyActual = true);
List<ProductOrderDataModel> GetProductOrdersByPeriod(DateTime fromDate, DateTime toDate, bool onlyActual = true);
void InsertProductOrder(ProductOrderDataModel productDataModel);
void UpdateProductOrder(ProductOrderDataModel productDataModel);
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
namespace YAPContracts.BusinessLogicContracts
{
public interface IProductSetBusinessLogicContract
{
List<ProductSetDataModel> GetAllProductSets(bool onlyActual = true);
ProductSetDataModel? GetProductSetByData(string data);
void InsertProductSet(ProductSetDataModel productSet);
void UpdateProductSet(ProductSetDataModel productSet);
void DeleteProductSet(string id);
}
}

View File

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
namespace YAPContracts.BusinessLogicContracts
{
public interface IPurchaseBusinessLogicContract
{
List<PurchaseDataModel> GetAllPurchases();
PurchaseDataModel? GetPurchaseByData(string data);
List<PurchaseDataModel> GetPurchasesByUserByPeriod(string userId, DateTime fromDate, DateTime toDate);
List<PurchaseDataModel> GetPurchasesByPeriod(DateTime fromDate, DateTime toDate);
void InsertPurchase(PurchaseDataModel purchase);
void UpdatePurchase(PurchaseDataModel purchase);
void DeletePurchase(string id);
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels.UserRoles;
namespace YAPContracts.BusinessLogicContracts
{
public interface IStorekeeperBusinessLogicContract
{
List<StorekeeperDataModel> GetAllStorekeepers();
StorekeeperDataModel? GetStorekeeperByData(string data);
void InsertStorekeeper(StorekeeperDataModel comment);
void UpdateStorekeeper(StorekeeperDataModel comment);
void DeleteStorekeeper(string id);
}
}

View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
using YAPContracts.DataModels.UserRoles;
namespace YAPContracts.BusinessLogicContracts
{
public interface IWorkerBusinessLogicContract
{
List<WorkerDataModel> GetAllWorkers();
WorkerDataModel? GetWorkerByData(string data);
void InsertWorker(WorkerDataModel comment);
void UpdateWorker(WorkerDataModel comment);
void DeleteWorker(string id);
}
}

View File

@@ -10,11 +10,15 @@ using YAPContracts.Infrastructure;
namespace YAPContracts.DataModels;
public class ComponentDataModel(string id, string name, ComponentType componentType) : IValidation
public class ComponentDataModel(string id, string name, ComponentType componentType, bool IsDeleted, List<ComponentInProductDataModel> products, List<ComponentInProductSetDataModel> productSets) : IValidation
{
public string Id { get; private set; } = id;
public string Name { get; private set; } = name;
public ComponentType ComponentType { get; private set; } = componentType;
public bool IsDeleted { get; private set; } = IsDeleted;
public List<ComponentInProductDataModel> Products = products;
public List<ComponentInProductSetDataModel> ProductSets = productSets;
public void Validate()
{
if (!Id.IsGuid())

View File

@@ -10,12 +10,14 @@ using YAPContracts.Infrastructure;
namespace YAPContracts.DataModels;
public class ProductDataModel(string id, string name, double price, List<ComponentInProductDataModel> componentProducts) : IValidation
public class ProductDataModel(string id, string name, double price, bool isDeleted, List<ComponentInProductDataModel> componentProducts, List<ProductInPurchaseDataModel> purchases) : IValidation
{
public string Id { get; private set; } = id;
public string Name { get; private set; } = name;
public double Price { get; private set; } = price;
public List<ComponentInProductDataModel> ComponentProducts { get; private set; } = componentProducts;
public bool IsDeleted { get; private set; } = isDeleted;
public List<ComponentInProductDataModel> Components { get; private set; } = componentProducts;
public List<ProductInPurchaseDataModel> Purchases { get; private set; } = purchases;
public void Validate()
{
if (!Id.IsGuid())
@@ -34,9 +36,13 @@ public class ProductDataModel(string id, string name, double price, List<Compone
{
throw new ValidationException("Price is less than or equal to 0");
}
foreach (var component in ComponentProducts)
foreach (var component in Components)
{
component.Validate();
}
foreach (var purchase in Purchases)
{
purchase.Validate();
}
}
}

View File

@@ -9,12 +9,13 @@ using YAPContracts.Infrastructure;
namespace YAPContracts.DataModels;
public class ProductOrder(string id, DateTime orderDate, string dealerName, string productId) : IValidation
public class ProductOrderDataModel(string id, DateTime orderDate, string dealerName, string productId, string userId) : IValidation
{
public string Id { get; private set; } = id;
public DateTime OrderDate { get; private set;} = orderDate;
public string DealerName { get; private set; } = dealerName;
public string ProductId { get; private set;} = productId;
public string UserId { get; private set; } = userId;
public void Validate()
{
if (Id.IsEmpty())

View File

@@ -9,12 +9,13 @@ using YAPContracts.Infrastructure;
namespace YAPContracts.DataModels
{
public class ProductSetDataModel(string id, string setName, double totalPrice) : IValidation
public class ProductSetDataModel(string id, string setName, double totalPrice, bool isDeleted) : IValidation
{
public string Id { get; private set; } = id;
public string SetName { get; private set; } = setName;
public double TotalPrice { get; private set; } = totalPrice;
public bool IsDeleted { get; private set; } = isDeleted;
public void Validate()
{

View File

@@ -9,16 +9,20 @@ using YAPContracts.Infrastructure;
namespace YAPContracts.DataModels
{
public class PurchaseDataModel(string id, double totalPrice, DateTime purchaseDate, List<ProductSetInPurchaseDataModel> productSets) : IValidation
public class PurchaseDataModel(string id, string userId, double totalPrice, DateTime purchaseDate, List<ProductSetInPurchaseDataModel> productSets, List<ProductInPurchaseDataModel> products) : IValidation
{
public string Id { get; private set; } = id;
public string UserId { get; private set; } = userId;
public double TotalPrice { get; private set; } = totalPrice;
public DateTime PurchaseDate { get; private set; } = purchaseDate;
public List<ProductSetInPurchaseDataModel> ProductSets = productSets;
public List<ProductInPurchaseDataModel> Products = products;
public void Validate()
{
if (!Id.IsGuid())
@@ -29,6 +33,14 @@ namespace YAPContracts.DataModels
{
throw new ValidationException("Id is empty");
}
if (!UserId.IsGuid())
{
throw new ValidationException("UserId value is not valid");
}
if (UserId.IsEmpty())
{
throw new ValidationException("UserId is empty");
}
if (TotalPrice <= 0)
{
throw new ValidationException("TotalPrice is less than or equal to 0");
@@ -37,6 +49,10 @@ namespace YAPContracts.DataModels
{
productSet.Validate();
}
foreach (var product in Products)
{
product.Validate();
}
}
}
}

View File

@@ -1,33 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.Infrastructure;
namespace YAPContracts.DataModels.Roles
{
public class WorkerDataModel : UserDataModel
{
public List<PurchaseDataModel> Purchases { get; private set; }
public List<CommentDataModel> Comments { get; private set; }
public WorkerDataModel(string id, string login, string email, string passwordHash, List<PurchaseDataModel> purchases, List<CommentDataModel> comments) : base(id, login, email, passwordHash, "Worker")
{
Purchases = purchases;
Comments = comments;
}
public new void Validate()
{
base.Validate();
foreach (var purchase in Purchases)
{
purchase.Validate();
}
foreach (var comment in Comments)
{
comment.Validate();
}
}
}
}

View File

@@ -1,17 +1,18 @@
using System.Text.RegularExpressions;
using YAPContracts.Enums;
using YAPContracts.Extentions;
using YAPContracts.Infrastructure;
namespace YAPContracts.DataModels
{
public class UserDataModel(string id, string login, string email, string passwordHash, string role) : IValidation
public class UserDataModel(string id, string login, string email, string passwordHash, UserType role) : IValidation
{
public string Id { get; set; } = id;
public string Login { get; set; } = login;
public string Email { get; set; } = email;
public string PasswordHash { get; set; } = passwordHash;
public string Id { get; private set; } = id;
public string Login { get; private set; } = login;
public string Email { get; private set; } = email;
public string PasswordHash { get; private set; } = passwordHash;
public string Role { get; set; } = role; // "Worker", "Storekeeper"
public UserType Role { get; private set; } = role; // Worker, Storekeeper
public void Validate()
{
@@ -43,14 +44,6 @@ namespace YAPContracts.DataModels
{
throw new Exceptions.ValidationException("PasswordHash is empty");
}
if (Role.IsEmpty())
{
throw new Exceptions.ValidationException("Role is empty");
}
if (!Role.IsValidRole())
{
throw new Exceptions.ValidationException("Role value is not valid");
}
}
}
}

View File

@@ -3,18 +3,14 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.Enums;
namespace YAPContracts.DataModels.Roles
namespace YAPContracts.DataModels.UserRoles
{
public class StorekeeperDataModel : UserDataModel
{
// storekeeper specific properties here
public StorekeeperDataModel(string id, string login, string email, string passwordHash, string role) : base(id, login, email, passwordHash, "Storekeeper")
public StorekeeperDataModel(string id, string login, string email, string passwordHash, UserType role) : base(id, login, email, passwordHash, role)
{
}
public new void Validate()
{
base.Validate();
}
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.Enums;
namespace YAPContracts.DataModels.UserRoles
{
public class WorkerDataModel : UserDataModel
{
public WorkerDataModel(string id, string login, string email, string passwordHash, UserType role) : base(id, login, email, passwordHash, role)
{
}
}
}

View File

@@ -10,6 +10,6 @@ public enum ComponentType
{
None = 0,
Accessory = 1,
Trial = 2,
Consumable = 2,
SparePart = 3
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.Enums
{
public enum UserType
{
None = 0,
Worker = 1,
Storekeeper = 2
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.Exceptions
{
public class ElementDeletedException : Exception
{
public ElementDeletedException(string id) : base($"Cannot update a deleted item (id: {id})") { }
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.Exceptions
{
public class ElementExistsException : Exception
{
public string ParamName { get; private set; }
public string ParamValue { get; private set; }
public ElementExistsException(string paramName, string paramValue) : base($"There is already an element with value {paramValue} of parameter {paramName}")
{
ParamName = paramName;
ParamValue = paramValue;
}
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.Exceptions
{
public class ElementNotFoundException : Exception
{
public string Value { get; private set; }
public ElementNotFoundException(string value) : base($"Element \'{value}\' not found")
{
Value = value;
}
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.Exceptions
{
public class IncorrectDatesException : Exception
{
public IncorrectDatesException(DateTime start, DateTime end) : base($"The end date must be later than the start date. StartDate: {start:dd.MM.YYYY}; EndDate: {end:dd.MM.YYYY}") { }
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.Exceptions
{
public class NullListException : Exception
{
public NullListException() : base("The returned list is null") { }
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.Exceptions
{
public class StorageException : Exception
{
public StorageException(Exception ex) : base($"Error while working in storage: {ex.Message}", ex) { }
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.Extentions
{
public static class DateTimeExtention
{
public static bool IsNotLaterThan(this DateTime dateTime, DateTime olderDateTime)
{
return dateTime >= olderDateTime;
}
}
}

View File

@@ -17,10 +17,5 @@ namespace YAPContracts.Extentions
{
return Guid.TryParse(str, out _);
}
public static bool IsValidRole(this string str)
{
return str == "Worker" || str == "Storekeeper";
}
}
}

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.Infrastructure;
public interface IConfigurationDatabase
{
string ConnectionString { get; }
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
namespace YAPContracts.StorageContracts
{
public interface ICommentStorageContract
{
List<CommentDataModel> GetList(DateTime? fromDate = null, DateTime? toDate = null, string? userId = null, string? productSetId = null);
CommentDataModel? GetElementById(string id);
void AddElement(CommentDataModel comment);
void UpdateElement(CommentDataModel comment);
void DeleteElement(string id);
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
namespace YAPContracts.StorageContracts;
public interface IComponentStorageContract
{
List<ComponentDataModel> GetList(bool onlyActual = true);
ComponentDataModel? GetElementById(string id);
ComponentDataModel? GetElementByName(string name);
void AddElement(ComponentDataModel componentDataModel);
void UpdElement(ComponentDataModel componentDataModel);
void DelElement(string id);
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
namespace YAPContracts.StorageContracts;
public interface IProductOrderStorageContract
{
List<ProductOrderDataModel> GetList(bool onlyActual = true, DateTime? fromDate = null, DateTime? toDate = null, string? dealerName = null, string? productId = null, string? userId = null);
ProductOrderDataModel? GetElementById(string id);
ProductOrderDataModel? GetElementByDealerName(string name);
void AddElement(ProductOrderDataModel ProductOrderDataModel);
void UpdElement(ProductOrderDataModel ProductOrderDataModel);
void DelElement(string id);
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
namespace YAPContracts.StorageContracts
{
public interface IProductSetStorageContract
{
List<ProductSetDataModel> GetList(bool onlyActual = true);
ProductSetDataModel? GetElementById(string id);
ProductSetDataModel? GetElementByName(string name);
void AddElement(ProductSetDataModel productSet);
void UpdateElement(ProductSetDataModel productSet);
void DeleteElement(string id);
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
namespace YAPContracts.StorageContracts;
public interface IProductStorageContract
{
List<ProductDataModel> GetList(bool onlyActual = true);
ProductDataModel? GetElementById(string id);
ProductDataModel? GetElementByName(string name);
void AddElement(ProductDataModel ProductDataModel);
void UpdElement(ProductDataModel ProductDataModel);
void DelElement(string id);
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
namespace YAPContracts.StorageContracts
{
public interface IPurchaseStorageContract
{
List<PurchaseDataModel> GetList(DateTime? fromDate = null, DateTime? toDate = null, string? userId = null);
PurchaseDataModel? GetElementById(string id);
void AddElement(PurchaseDataModel purchase);
void UpdateElement(PurchaseDataModel purchase);
void DeleteElement(string id);
}
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels.UserRoles;
using YAPContracts.DataModels;
namespace YAPContracts.StorageContracts
{
public interface IStorekeeperStorageContract
{
List<StorekeeperDataModel> GetList();
StorekeeperDataModel? GetElementById(string id);
StorekeeperDataModel? GetElementByLogin(string login);
void AddElement(StorekeeperDataModel user);
void UpdateElement(StorekeeperDataModel user);
void DeleteElement(string id);
}
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
using YAPContracts.DataModels.UserRoles;
namespace YAPContracts.StorageContracts
{
public interface IWorkerStorageContract
{
List<WorkerDataModel> GetList();
WorkerDataModel? GetElementById(string id);
WorkerDataModel? GetElementByLogin(string login);
void AddElement(WorkerDataModel user);
void UpdateElement(WorkerDataModel user);
void DeleteElement(string id);
}
}

View File

@@ -0,0 +1,128 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Npgsql;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using YAPContracts.DataModels;
using YAPContracts.Exceptions;
using YAPContracts.StorageContracts;
using YAPDatabase.Models;
namespace YAPDatabase.Implementations
{
internal class CommentStorageContract : ICommentStorageContract
{
private readonly YAPDbContext _dbContext;
private readonly Mapper _mapper;
public CommentStorageContract(YAPDbContext dbContext)
{
_dbContext = dbContext;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Comment, CommentDataModel>();
cfg.CreateMap<CommentDataModel, Comment>();
});
_mapper = new Mapper(config);
}
public void AddElement(CommentDataModel comment)
{
try
{
_dbContext.Comments.Add(_mapper.Map<Comment>(comment));
_dbContext.SaveChanges();
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public void UpdateElement(CommentDataModel comment)
{
try
{
var newComment = GetCommentById(comment.Id) ?? throw new ElementNotFoundException(comment.Id);
_dbContext.Comments.Update(_mapper.Map(comment, newComment));
_dbContext.SaveChanges();
}
catch (ElementNotFoundException)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public void DeleteElement(string id)
{
try
{
var comment = GetCommentById(id) ?? throw new ElementNotFoundException(id);
_dbContext.Comments.Remove(comment);
_dbContext.SaveChanges();
}
catch (ElementNotFoundException ex)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public CommentDataModel? GetElementById(string id)
{
try
{
return _mapper.Map<CommentDataModel>(GetCommentById(id));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public List<CommentDataModel> GetList(DateTime? fromDate = null, DateTime? toDate = null, string? userId = null, string? productSetId = null)
{
try
{
var query = _dbContext.Comments.AsQueryable();
if (fromDate is not null && toDate is not null)
{
query = query.Where(x => x.CommentDate >= fromDate && x.CommentDate < toDate);
}
if (userId is not null)
{
query = query.Where(x => x.UserId == userId);
}
if (productSetId is not null)
{
query = query.Where(x => x.ProductSetId == productSetId);
}
return [.. query.Select(x => _mapper.Map<CommentDataModel>(x))];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
private Comment? GetCommentById(string id) => _dbContext.Comments.FirstOrDefault(x => x.Id == id);
}
}

View File

@@ -0,0 +1,133 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
using YAPContracts.Exceptions;
using YAPContracts.StorageContracts;
using YAPDatabase.Models;
namespace YAPDatabase.Implementations;
internal class ComponentStorageContract : IComponentStorageContract
{
private readonly YAPDbContext _dbContext;
private readonly Mapper _mapper;
public ComponentStorageContract(YAPDbContext dbContext)
{
_dbContext = dbContext;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<ComponentInProduct, ComponentInProductDataModel>();
cfg.CreateMap<ComponentInProductDataModel, ComponentInProduct>();
cfg.CreateMap<ComponentInProductSet, ComponentInProductSetDataModel>();
cfg.CreateMap<ComponentInProductSetDataModel, ComponentInProductSet>();
cfg.CreateMap<ComponentDataModel, Component>()
.ForMember(dest => dest.Products, opt => opt.MapFrom(src => src.Products))
.ForMember(dest => dest.ProductSets, opt => opt.MapFrom(src => src.ProductSets));
cfg.CreateMap<Component, ComponentDataModel>();
});
_mapper = new Mapper(config);
}
public void AddElement(ComponentDataModel component)
{
try
{
_dbContext.Components.Add(_mapper.Map<Component>(component));
_dbContext.SaveChanges();
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public void DelElement(string id)
{
try
{
var component = GetComponentById(id) ?? throw new ElementNotFoundException(id);
_dbContext.Components.Remove(component);
_dbContext.SaveChanges();
}
catch (ElementNotFoundException ex)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public ComponentDataModel? GetElementById(string id)
{
try
{
return _mapper.Map<ComponentDataModel>(GetComponentById(id));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public ComponentDataModel? GetElementByName(string name)
{
try
{
return _mapper.Map<ComponentDataModel>(_dbContext.Components.FirstOrDefault(x => x.Name == name));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public List<ComponentDataModel> GetList(bool onlyActual = true)
{
try
{
var query = _dbContext.Components.Include(x => x.Products).Include(x => x.ProductSets).AsQueryable();
return [.. query.Select(x => _mapper.Map<ComponentDataModel>(x))];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public void UpdElement(ComponentDataModel component)
{
try
{
var newComponent = GetComponentById(component.Id) ?? throw new ElementNotFoundException(component.Id);
_dbContext.Components.Update(_mapper.Map(component, newComponent));
_dbContext.SaveChanges();
}
catch (ElementNotFoundException ex)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
private Component? GetComponentById(string id) => _dbContext.Components.FirstOrDefault(x => x.Id == id);
}

View File

@@ -0,0 +1,136 @@
using AutoMapper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
using YAPContracts.Exceptions;
using YAPContracts.StorageContracts;
using YAPDatabase.Models;
namespace YAPDatabase.Implementations;
internal class ProductOrderStorageContract : IProductOrderStorageContract
{
private readonly YAPDbContext _dbContext;
private readonly Mapper _mapper;
public ProductOrderStorageContract(YAPDbContext dbContext)
{
_dbContext = dbContext;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<ProductOrder, ProductOrderDataModel>();
cfg.CreateMap<ProductOrderDataModel, ProductOrder>();
});
_mapper = new Mapper(config);
}
public void AddElement(ProductOrderDataModel productOrder)
{
try
{
_dbContext.ProductOrders.Add(_mapper.Map<ProductOrder>(productOrder));
_dbContext.SaveChanges();
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public void DelElement(string id)
{
try
{
var productOrder = GetProductOrderById(id) ?? throw new ElementNotFoundException(id);
_dbContext.ProductOrders.Remove(productOrder);
_dbContext.SaveChanges();
}
catch (ElementNotFoundException ex)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public ProductOrderDataModel? GetElementById(string id)
{
try
{
return _mapper.Map<ProductOrderDataModel>(GetProductOrderById(id));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public ProductOrderDataModel? GetElementByDealerName(string name)
{
try
{
return _mapper.Map<ProductOrderDataModel>(_dbContext.ProductOrders.FirstOrDefault(x => x.DealerName == name));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public List<ProductOrderDataModel> GetList(bool onlyActual = true, DateTime? fromDate = null, DateTime? toDate = null, string? dealerName = null, string? productId = null, string? userId = null)
{
try
{
var query = _dbContext.ProductOrders.AsQueryable();
if (fromDate is not null && toDate is not null)
{
query = query.Where(x => x.OrderDate >= fromDate && x.OrderDate < toDate);
}
if (userId is not null)
{
query = query.Where(x => x.UserId == userId);
}
if (productId is not null)
{
query = query.Where(x => x.ProductId == productId);
}
return [.. query.Select(x => _mapper.Map<ProductOrderDataModel>(x))];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public void UpdElement(ProductOrderDataModel productOrder)
{
try
{
var newProductOrder = GetProductOrderById(productOrder.Id) ?? throw new ElementNotFoundException(productOrder.Id);
_dbContext.ProductOrders.Update(_mapper.Map(productOrder, newProductOrder));
_dbContext.SaveChanges();
}
catch (ElementNotFoundException)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
private ProductOrder? GetProductOrderById(string id) => _dbContext.ProductOrders.FirstOrDefault(x => x.Id == id);
}

View File

@@ -0,0 +1,155 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Npgsql;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
using YAPContracts.Exceptions;
using YAPContracts.StorageContracts;
using YAPDatabase.Models;
namespace YAPDatabase.Implementations
{
internal class ProductSetStorageContract : IProductSetStorageContract
{
private readonly YAPDbContext _dbContext;
private readonly Mapper _mapper;
public ProductSetStorageContract(YAPDbContext dbContext)
{
_dbContext = dbContext;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<ComponentInProductSet, ComponentInProductSetDataModel>();
cfg.CreateMap<ComponentInProductSetDataModel, ComponentInProductSet>();
cfg.CreateMap<ProductSetDataModel, ProductSet>()
.ForMember(dest => dest.IsDeleted, opt => opt.MapFrom(src => false));
cfg.CreateMap<ProductSet, ProductSetDataModel>();
});
_mapper = new Mapper(config);
}
public void AddElement(ProductSetDataModel productSet)
{
try
{
_dbContext.ProductSets.Add(_mapper.Map<ProductSet>(productSet));
_dbContext.SaveChanges();
}
catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_ProductSets_SetName_IsDeleted" })
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("PostName", productSet.SetName);
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public void UpdateElement(ProductSetDataModel productSet)
{
try
{
var transaction = _dbContext.Database.BeginTransaction();
try
{
var element = GetProductSetById(productSet.Id) ?? throw new ElementNotFoundException(productSet.Id);
if (element.IsDeleted)
{
throw new ElementDeletedException(productSet.Id);
}
element.IsDeleted = true;
_dbContext.SaveChanges();
var newElement = _mapper.Map<ProductSet>(productSet);
_dbContext.ProductSets.Add(newElement);
_dbContext.SaveChanges();
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
catch (DbUpdateException ex) when (ex.InnerException is PostgresException { ConstraintName: "IX_ProductSets_SetName_IsDeleted" })
{
_dbContext.ChangeTracker.Clear();
throw new ElementExistsException("SetName", productSet.SetName);
}
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 DeleteElement(string id)
{
try
{
var element = GetProductSetById(id) ?? throw new ElementNotFoundException(id);
if (element.IsDeleted)
{
throw new ElementDeletedException(id);
}
element.IsDeleted = true;
_dbContext.SaveChanges();
}
catch
{
_dbContext.ChangeTracker.Clear();
throw;
}
}
public ProductSetDataModel? GetElementById(string id)
{
try
{
return _mapper.Map<ProductSetDataModel>(GetProductSetById(id));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public ProductSetDataModel? GetElementByName(string name)
{
try
{
return _mapper.Map<ProductSetDataModel>(_dbContext.ProductSets.FirstOrDefault(x => x.SetName == name));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public List<ProductSetDataModel> GetList(bool onlyActual = true)
{
var query = _dbContext.ProductSets.AsQueryable();
if (onlyActual)
{
query = query.Where(x => !x.IsDeleted);
}
return [.. query.Select(x => _mapper.Map<ProductSetDataModel>(x))];
}
private ProductSet? GetProductSetById(string id) => _dbContext.ProductSets.FirstOrDefault(x => x.Id == id && x.IsDeleted != true);
}
}

View File

@@ -0,0 +1,133 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
using YAPContracts.Exceptions;
using YAPContracts.StorageContracts;
using YAPDatabase.Models;
namespace YAPDatabase.Implementations;
internal class ProductStorageContract : IProductStorageContract
{
private readonly YAPDbContext _dbContext;
private readonly Mapper _mapper;
public ProductStorageContract(YAPDbContext dbContext)
{
_dbContext = dbContext;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<ProductInPurchase, ProductInPurchaseDataModel>();
cfg.CreateMap<ProductInPurchaseDataModel, ProductInPurchase>();
cfg.CreateMap<ComponentInProduct, ComponentInProductDataModel>();
cfg.CreateMap<ComponentInProductDataModel, ComponentInProduct>();
cfg.CreateMap<ProductDataModel, Product>()
.ForMember(dest => dest.ComponentsInProduct, opt => opt.MapFrom(src => src.Components))
.ForMember(dest => dest.ProductsInPurchace, opt => opt.MapFrom(src => src.Purchases));
;
cfg.CreateMap<Product, ProductDataModel>();
});
_mapper = new Mapper(config);
}
public void AddElement(ProductDataModel product)
{
try
{
_dbContext.Products.Add(_mapper.Map<Product>(product));
_dbContext.SaveChanges();
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public void DelElement(string id)
{
try
{
var product = GetProductById(id) ?? throw new ElementNotFoundException(id);
_dbContext.Products.Remove(product);
_dbContext.SaveChanges();
}
catch (ElementNotFoundException ex)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public ProductDataModel? GetElementById(string id)
{
try
{
return _mapper.Map<ProductDataModel>(GetProductById(id));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public ProductDataModel? GetElementByName(string name)
{
try
{
return _mapper.Map<ProductDataModel>(_dbContext.Products.FirstOrDefault(x => x.Name == name));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public List<ProductDataModel> GetList(bool onlyActual = true)
{
try
{
var query = _dbContext.Products.Include(x => x.ComponentsInProduct).Include(x => x.ProductsInPurchace).AsQueryable();
return [.. query.Select(x => _mapper.Map<ProductDataModel>(x))];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public void UpdElement(ProductDataModel product)
{
try
{
var newProduct = GetProductById(product.Id) ?? throw new ElementNotFoundException(product.Id);
_dbContext.Products.Update(_mapper.Map(product, newProduct));
_dbContext.SaveChanges();
}
catch (ElementNotFoundException ex)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
private Product? GetProductById(string id) => _dbContext.Products.FirstOrDefault(x => x.Id == id);
}

View File

@@ -0,0 +1,136 @@
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Npgsql;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using YAPContracts.DataModels;
using YAPContracts.Exceptions;
using YAPContracts.StorageContracts;
using YAPDatabase.Models;
namespace YAPDatabase.Implementations
{
internal class PurchaseStorageContract : IPurchaseStorageContract
{
private readonly YAPDbContext _dbContext;
private readonly Mapper _mapper;
public PurchaseStorageContract(YAPDbContext dbContext)
{
_dbContext = dbContext;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<ProductInPurchase, ProductInPurchaseDataModel>();
cfg.CreateMap<ProductInPurchaseDataModel, ProductInPurchase>();
cfg.CreateMap<ProductSetInPurchase, ProductSetInPurchaseDataModel>();
cfg.CreateMap<ProductSetInPurchaseDataModel, ProductSetInPurchase>();
cfg.CreateMap<PurchaseDataModel, Purchase>()
.ForMember(dest => dest.ProductsInPurchase, opt => opt.MapFrom(src => src.Products))
.ForMember(dest => dest.ProductSetsInPurchase, opt => opt.MapFrom(src => src.ProductSets));
cfg.CreateMap<Purchase, PurchaseDataModel>();
});
_mapper = new Mapper(config);
}
public void AddElement(PurchaseDataModel purchase)
{
try
{
_dbContext.Purchases.Add(_mapper.Map<Purchase>(purchase));
_dbContext.SaveChanges();
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public void UpdateElement(PurchaseDataModel purchase)
{
try
{
var newPurchase = GetPurchaseById(purchase.Id) ?? throw new ElementNotFoundException(purchase.Id);
_dbContext.Purchases.Update(_mapper.Map(purchase, newPurchase));
_dbContext.SaveChanges();
}
catch (ElementNotFoundException ex)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public void DeleteElement(string id)
{
try
{
var client = GetPurchaseById(id) ?? throw new ElementNotFoundException(id);
_dbContext.Purchases.Remove(client);
_dbContext.SaveChanges();
}
catch (ElementNotFoundException ex)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public PurchaseDataModel? GetElementById(string id)
{
try
{
return _mapper.Map<PurchaseDataModel>(GetPurchaseById(id));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public List<PurchaseDataModel> GetList(DateTime? fromDate = null, DateTime? toDate = null, string? userId = null)
{
try
{
var query = _dbContext.Purchases.Include(x => x.ProductsInPurchase).Include(x => x.ProductSetsInPurchase).AsQueryable();
if (fromDate is not null && toDate is not null)
{
query = query.Where(x => x.PurchaseDate >= fromDate && x.PurchaseDate < toDate);
}
if (userId is not null)
{
query = query.Where(x => x.UserId == userId);
}
return [.. query.Select(x => _mapper.Map<PurchaseDataModel>(x))];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
private Purchase? GetPurchaseById(string id)
{
return _dbContext.Purchases.FirstOrDefault(p => p.Id == id);
}
}
}

View File

@@ -0,0 +1,124 @@
using AutoMapper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels.UserRoles;
using YAPContracts.Exceptions;
using YAPContracts.StorageContracts;
using YAPDatabase.Models;
namespace YAPDatabase.Implementations;
internal class StorekeeperStorageContract : IStorekeeperStorageContract
{
private readonly YAPDbContext _dbContext;
private readonly Mapper _mapper;
public StorekeeperStorageContract(YAPDbContext dbContext)
{
_dbContext = dbContext;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Storekeeper, StorekeeperDataModel>();
cfg.CreateMap<StorekeeperDataModel, Storekeeper>();
});
_mapper = new Mapper(config);
}
public void AddElement(StorekeeperDataModel user)
{
try
{
_dbContext.Users.Add(_mapper.Map<Storekeeper>(user));
_dbContext.SaveChanges();
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public void DeleteElement(string id)
{
try
{
var user = GetStorekeeperById(id) ?? throw new ElementNotFoundException(id);
_dbContext.Users.Remove(user);
_dbContext.SaveChanges();
}
catch (ElementNotFoundException ex)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public StorekeeperDataModel? GetElementById(string id)
{
try
{
return _mapper.Map<StorekeeperDataModel>(GetStorekeeperById(id));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public StorekeeperDataModel? GetElementByLogin(string login)
{
try
{
return _mapper.Map<StorekeeperDataModel>(_dbContext.Users.OfType<Storekeeper>().FirstOrDefault(x => x.Login == login));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public List<StorekeeperDataModel> GetList()
{
try
{
return [.. _dbContext.Users.OfType<Storekeeper>().Select(x => _mapper.Map<StorekeeperDataModel>(x))];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public void UpdateElement(StorekeeperDataModel user)
{
try
{
var newStorekeeper = GetStorekeeperById(user.Id) ?? throw new ElementNotFoundException(user.Id);
_dbContext.Users.Update(_mapper.Map(user, newStorekeeper));
_dbContext.SaveChanges();
}
catch (ElementNotFoundException)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
private Storekeeper? GetStorekeeperById(string id) => _dbContext.Users.OfType<Storekeeper>().FirstOrDefault(x => x.Id == id);
}

View File

@@ -0,0 +1,128 @@
using AutoMapper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using YAPContracts.DataModels;
using YAPContracts.DataModels.UserRoles;
using YAPContracts.Exceptions;
using YAPContracts.StorageContracts;
using YAPDatabase.Models;
namespace YAPDatabase.Implementations
{
internal class WorkerStorageContract : IWorkerStorageContract
{
private readonly YAPDbContext _dbContext;
private readonly Mapper _mapper;
public WorkerStorageContract(YAPDbContext dbContext)
{
_dbContext = dbContext;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Worker, WorkerDataModel>();
cfg.CreateMap<WorkerDataModel, Worker>();
});
_mapper = new Mapper(config);
}
public void AddElement(WorkerDataModel user)
{
try
{
_dbContext.Users.Add(_mapper.Map<Worker>(user));
_dbContext.SaveChanges();
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public void UpdateElement(WorkerDataModel user)
{
try
{
var newWorker = GetWorkerById(user.Id) ?? throw new ElementNotFoundException(user.Id);
_dbContext.Users.Update(_mapper.Map(user, newWorker));
_dbContext.SaveChanges();
}
catch (ElementNotFoundException)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public void DeleteElement(string id)
{
try
{
var user = GetWorkerById(id) ?? throw new ElementNotFoundException(id);
_dbContext.Users.Remove(user);
_dbContext.SaveChanges();
}
catch (ElementNotFoundException ex)
{
_dbContext.ChangeTracker.Clear();
throw;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public WorkerDataModel? GetElementById(string id)
{
try
{
return _mapper.Map<WorkerDataModel>(GetWorkerById(id));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public WorkerDataModel? GetElementByLogin(string login)
{
try
{
return _mapper.Map<WorkerDataModel>(_dbContext.Users.OfType<Worker>().FirstOrDefault(x => x.Login == login));
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public List<WorkerDataModel> GetList()
{
try
{
return [.. _dbContext.Users.OfType<Worker>().Select(x => _mapper.Map<WorkerDataModel>(x))];
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
private Worker? GetWorkerById(string id) => _dbContext.Users.OfType<Worker>().FirstOrDefault(x => x.Id == id);
}
}

View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPDatabase.Models
{
internal class Comment
{
public required string Id { get; set; }
public required string ProductSetId { get; set; }
public required string UserId { get; set; }
public required string Text { get; set; }
public DateTime CommentDate { get; set; }
public Worker? User { get; set; }
public ProductSet? ProductSet { get; set; }
}
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
using YAPContracts.Enums;
namespace YAPDatabase.Models;
internal class Component
{
public required string Id { get; set; }
public required string Name { get; set; }
public ComponentType ComponentType { get; set; }
public bool IsDeleted { get; set; }
[ForeignKey("ComponentId")]
public List<ComponentInProduct>? Products { get; set; }
[ForeignKey("ComponentId")]
public List<ComponentInProductSet>? ProductSets { get; set; }
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPDatabase.Models;
internal class ComponentInProduct
{
public required string ComponentId { get; set; }
public required string ProductId { get; set; }
public Component? Component { get; set; }
public Product? Product { get; set; }
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPDatabase.Models;
internal class ComponentInProductSet
{
public required string ComponentId { get; set; }
public required string ProductSetId { get; set; }
public double Price { get; set; }
public Component? Component { get; set; }
public ProductSet? ProductSet { get; set; }
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPDatabase.Models;
internal class Product
{
public required string Id { get; set; }
public required string Name { get; set; }
public double Price { get; set; }
public bool IsDeleted { get; set; }
[ForeignKey("ProductId")]
public List<ProductOrder>? ProductOrders { get; set; }
[ForeignKey("ProductId")]
public List<ProductInPurchase>? ProductsInPurchace { get; set; }
[ForeignKey("ProductId")]
public List<ComponentInProduct>? ComponentsInProduct { get; set; }
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPDatabase.Models;
internal class ProductInPurchase
{
public required string PurchaseId { get; set; }
public required string ProductId { get; set; }
public int Amount { get; set; }
public Component? Component { get; set; }
public ProductSet? ProductSet { get; set; }
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPDatabase.Models;
internal class ProductOrder
{
public required string Id { get; set; }
public required string UserId { get; set; }
public DateTime OrderDate { get; set; }
public required string DealerName { get; set; }
public required string ProductId { get; set; }
public Product? Product { get; set; }
public Storekeeper? Storekeeper { get; set; }
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPDatabase.Models
{
internal class ProductSet // userId?
{
public required string Id { get; set; }
public required string SetName { get; set; }
public double TotalPrice { get; set; }
public bool IsDeleted { get; set; }
[ForeignKey("ProductSetId")]
public List<Comment>? Comments { get; set; }
[ForeignKey("ProductSetId")]
public List<ProductSetInPurchase>? ProductSetsInPurchase { get; set; }
[ForeignKey("ProductSetId")]
public List<ComponentInProductSet>? ComponentsInProductSet { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPDatabase.Models
{
internal class ProductSetInPurchase
{
public required string ProductSetId { get; set; }
public required string PurchaseId { get; set; }
public ProductSet? ProductSet { get; set; }
public Purchase? Purchase { get; set; }
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPDatabase.Models
{
internal class Purchase
{
public required string Id { get; set; }
public required string UserId { get; set; }
public double TotalPrice { get; set; }
public DateTime PurchaseDate { get; set; }
public Worker? User { get; set; }
[ForeignKey("PurchaseId")]
public List<ProductSetInPurchase>? ProductSetsInPurchase { get; set; }
[ForeignKey("PurchaseId")]
public List<ProductInPurchase>? ProductsInPurchase { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.Enums;
namespace YAPDatabase.Models
{
internal class Storekeeper : User
{
public Storekeeper() => Role = UserType.Storekeeper;
public List<ProductOrder>? ProductOrders { get; set; }
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.Enums;
namespace YAPDatabase.Models
{
internal abstract class User
{
public required string Id { get; set; } = default!;
public required string Login { get; set; } = default!;
public required string Email { get; set; } = default!;
public required string PasswordHash { get; set; } = default!;
public UserType Role { get; protected set; }
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.Enums;
namespace YAPDatabase.Models
{
internal class Worker : User
{
public Worker() => Role = UserType.Worker;
public List<Purchase>? Purchases { get; set; }
public List<Comment>? Comments { get; set; }
}
}

View File

@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<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.5" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../YAPContracts/YAPContracts.csproj" />
</ItemGroup>
<ItemGroup>
<InternalsVisibleTo Include="YAPTests" />
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,111 @@
using Microsoft.EntityFrameworkCore;
using YAPContracts.Enums;
using YAPContracts.Infrastructure;
using YAPDatabase.Models;
namespace YAPDatabase
{
internal class YAPDbContext(IConfigurationDatabase configuration) : DbContext
{
private readonly IConfigurationDatabase _configuration = configuration;
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseNpgsql(_configuration?.ConnectionString, o => o.SetPostgresVersion(12, 2));
base.OnConfiguring(optionsBuilder);
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// one Table-per-Hierarchy (TPH) for Users
modelBuilder.Entity<User>()
.HasDiscriminator<UserType>("Role")
.HasValue<Worker>(UserType.Worker)
.HasValue<Storekeeper>(UserType.Storekeeper);
modelBuilder.Entity<User>()
.HasKey(u => u.Id);
modelBuilder.Entity<User>()
.Property(u => u.Login).IsRequired();
modelBuilder.Entity<User>()
.Property(u => u.Email).IsRequired();
modelBuilder.Entity<User>()
.Property(u => u.PasswordHash).IsRequired();
// intermediate tables for many-to-many relationships
modelBuilder.Entity<ComponentInProduct>()
.HasKey(x => new { x.ComponentId, x.ProductId });
modelBuilder.Entity<ComponentInProductSet>()
.HasKey(x => new { x.ComponentId, x.ProductSetId });
modelBuilder.Entity<ProductInPurchase>()
.HasKey(x => new { x.ProductId, x.PurchaseId });
modelBuilder.Entity<ProductSetInPurchase>()
.HasKey(x => new { x.ProductSetId, x.PurchaseId });
// onlyActual & isDeleted properties for soft delete
modelBuilder.Entity<ProductSet>()
.Property(ps => ps.IsDeleted)
.HasDefaultValue(false);
modelBuilder.Entity<ProductSet>()
.HasIndex(e => new { e.SetName, e.IsDeleted })
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE"); // unique index for non-deleted sets
modelBuilder.Entity<Product>()
.Property(p => p.IsDeleted)
.HasDefaultValue(false);
modelBuilder.Entity<Product>()
.HasIndex(e => new { e.Name, e.IsDeleted })
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE"); // unique index for non-deleted products
modelBuilder.Entity<Component>()
.Property(c => c.IsDeleted)
.HasDefaultValue(false);
modelBuilder.Entity<Component>()
.HasIndex(e => new { e.Name, e.IsDeleted })
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE"); // unique index for non-deleted components
// User relationships
modelBuilder.Entity<Purchase>()
.HasOne<Worker>() // only Worker can create Purchase
.WithMany(w => w.Purchases)
.HasForeignKey(p => p.UserId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Comment>()
.HasOne<Worker>()
.WithMany(w => w.Comments)
.HasForeignKey(c => c.UserId)
.OnDelete(DeleteBehavior.Cascade);
// TODO: Storekeeper can manage Components and ProductOrders here
modelBuilder.Entity<ProductOrder>()
.HasOne<Storekeeper>() // only Storekeeper can create ProductOrder
.WithMany(w => w.ProductOrders)
.HasForeignKey(p => p.UserId)
.OnDelete(DeleteBehavior.Cascade);
}
public DbSet<User> Users { get; set; } // single table
public DbSet<Comment> Comments { get; set; }
public DbSet<Component> Components { get; set; }
public DbSet<ComponentInProduct> ComponentsInProduct { get; set; }
public DbSet<ComponentInProductSet> ComponentsInProductSet { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<ProductInPurchase> ProductsInPurchase { get; set; }
public DbSet<ProductOrder> ProductOrders { get; set; }
public DbSet<ProductSet> ProductSets { get; set; }
public DbSet<ProductSetInPurchase> ProductSetsInPurchase { get; set; }
public DbSet<Purchase> Purchases { get; set; }
}
}

View File

@@ -6,7 +6,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels;
using YAPContracts.DataModels.Roles;
using YAPContracts.Enums;
using YAPContracts.Exceptions;
namespace YAPTests.DataModelTests
@@ -17,77 +17,60 @@ namespace YAPTests.DataModelTests
[Test]
public void IdIsNullOrEmptyTest()
{
var user = CreateDataModel(null, "test", "mail@mail.ru", "hash", "Worker");
var user = CreateDataModel(null, "test", "mail@mail.ru", "hash", UserType.Worker);
Assert.That(() => user.Validate(), Throws.TypeOf<ValidationException>());
user = CreateDataModel(string.Empty, "test", "mail@mail.ru", "hash", "Worker");
user = CreateDataModel(string.Empty, "test", "mail@mail.ru", "hash", UserType.Worker);
Assert.That(() => user.Validate(), Throws.TypeOf<ValidationException>());
}
[Test]
public void IdIsNotGuidTest()
{
var user = CreateDataModel("id", "test", "mail@mail.ru", "hash", "Worker");
var user = CreateDataModel("id", "test", "mail@mail.ru", "hash", UserType.Worker);
Assert.That(() => user.Validate(), Throws.TypeOf<ValidationException>());
}
[Test]
public void LoginIsNullOrEmptyTest()
{
var user = CreateDataModel(Guid.NewGuid().ToString(), null, "mail@mail.ru", "hash", "Worker");
var user = CreateDataModel(Guid.NewGuid().ToString(), null, "mail@mail.ru", "hash", UserType.Worker);
Assert.That(() => user.Validate(), Throws.TypeOf<ValidationException>());
user = CreateDataModel(Guid.NewGuid().ToString(), string.Empty, "mail@mail.ru", "hash", "Worker");
user = CreateDataModel(Guid.NewGuid().ToString(), string.Empty, "mail@mail.ru", "hash", UserType.Worker);
Assert.That(() => user.Validate(), Throws.TypeOf<ValidationException>());
}
[Test]
public void LoginIsIncorrectTest()
{
var user = CreateDataModel(Guid.NewGuid().ToString(), "+", "mail@mail.ru", "hash", "Worker");
var user = CreateDataModel(Guid.NewGuid().ToString(), "+", "mail@mail.ru", "hash", UserType.Worker);
Assert.That(() => user.Validate(), Throws.TypeOf<ValidationException>());
}
[Test]
public void EmailIsNullOrEmptyTest()
{
var user = CreateDataModel(Guid.NewGuid().ToString(), "login", null, "hash", "Worker");
var user = CreateDataModel(Guid.NewGuid().ToString(), "login", null, "hash", UserType.Worker);
Assert.That(() => user.Validate(), Throws.TypeOf<ValidationException>());
user = CreateDataModel(Guid.NewGuid().ToString(), "login", string.Empty, "hash", "Worker");
user = CreateDataModel(Guid.NewGuid().ToString(), "login", string.Empty, "hash", UserType.Worker);
Assert.That(() => user.Validate(), Throws.TypeOf<ValidationException>());
}
[Test]
public void EmailIsIncorrectTest()
{
var user = CreateDataModel(Guid.NewGuid().ToString(), "login", "mail", "hash", "Worker");
var user = CreateDataModel(Guid.NewGuid().ToString(), "login", "mail", "hash", UserType.Worker);
Assert.That(() => user.Validate(), Throws.TypeOf<ValidationException>());
}
[Test]
public void PasswordHashIsNullOrEmptyTest()
{
var user = CreateDataModel(Guid.NewGuid().ToString(), "login", "mail@mail.ru", null, "Worker");
var user = CreateDataModel(Guid.NewGuid().ToString(), "login", "mail@mail.ru", null, UserType.Worker);
Assert.That(() => user.Validate(), Throws.TypeOf<ValidationException>());
user = CreateDataModel(Guid.NewGuid().ToString(), "login", "mail@mail.ru", string.Empty, "Worker");
user = CreateDataModel(Guid.NewGuid().ToString(), "login", "mail@mail.ru", string.Empty, UserType.Worker);
Assert.That(() => user.Validate(), Throws.TypeOf<ValidationException>());
}
[Test]
public void Worker_AllFieldsAreCorrectTest()
{
var userId = Guid.NewGuid().ToString();
List<CommentDataModel> comments = new List<CommentDataModel>() { new CommentDataModel(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), userId, "text", DateTime.UtcNow) };
List<PurchaseDataModel> purchases = new List<PurchaseDataModel>() { new PurchaseDataModel(Guid.NewGuid().ToString(), 100, DateTime.UtcNow, []) };
var worker = new WorkerDataModel(userId, "login", "mail@mail.ru", "hash", purchases, comments);
Assert.That(() => worker.Validate(), Throws.Nothing);
Assert.Multiple(() =>
{
Assert.That(worker.Role, Is.EqualTo("Worker"));
Assert.That(worker.Purchases, Is.EqualTo(purchases));
Assert.That(worker.Comments, Is.EqualTo(comments));
});
}
[Test]
public void AllFieldsAreCorrectTest()
{
@@ -95,7 +78,7 @@ namespace YAPTests.DataModelTests
var login = "name";
var email = "mail@mail.ru";
var passwordHash = "hash";
var role = "Worker";
var role = UserType.Worker;
var user = CreateDataModel(userId, login, email, passwordHash, role);
Assert.That(() => user.Validate(), Throws.Nothing);
Assert.Multiple(() =>
@@ -108,7 +91,7 @@ namespace YAPTests.DataModelTests
});
}
private static UserDataModel CreateDataModel(string? id, string? login, string? email, string? passwordHash, string? role) =>
private static UserDataModel CreateDataModel(string id, string login, string email, string passwordHash, UserType role) =>
new(id, login, email, passwordHash, role);
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.Infrastructure;
namespace YAPTests.Infrastructure
{
internal class DatabaseConfigurationTest : IConfigurationDatabase
{
public string ConnectionString => "Host=127.0.0.1;Port=5432;Database=MiniSoftTest;Username=postgres;Password=postgres;";
}
}

View File

@@ -0,0 +1,144 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.Enums;
using YAPDatabase;
using YAPDatabase.Models;
namespace YAPTests.Infrastructure
{
internal static class YAPDbContextExtentions
{
// TODO: допилить этот кал, добавление матрешкой Purchase -> ... -> Component
// ---------- USERS ----------
public static Worker InsertWorker(this YAPDbContext db, string? id = null, string login = "worker", string email = "worker@test.com")
{
var worker = new Worker
{
Id = id ?? Guid.NewGuid().ToString(),
Login = login,
Email = email,
PasswordHash = "hash"
};
db.Users.Add(worker);
db.SaveChanges();
return worker;
}
public static Storekeeper InsertStorekeeper(this YAPDbContext db, string? id = null, string login = "storekeeper", string email = "store@test.com")
{
var storekeeper = new Storekeeper
{
Id = id ?? Guid.NewGuid().ToString(),
Login = login,
Email = email,
PasswordHash = "hash"
};
db.Users.Add(storekeeper);
db.SaveChanges();
return storekeeper;
}
// ---------- PURCHASE ----------
public static Purchase InsertPurchase(this YAPDbContext db, string? id = null, string? workerId = null, DateTime? date = null, double totalPrice = 10)
{
var purchase = new Purchase
{
Id = id ?? Guid.NewGuid().ToString(),
UserId = workerId ?? Guid.NewGuid().ToString(),
PurchaseDate = date ?? DateTime.UtcNow,
TotalPrice = totalPrice
};
db.Purchases.Add(purchase);
db.SaveChanges();
return purchase;
}
// ---------- PRODUCTSET ----------
public static ProductSet InsertProductSet(this YAPDbContext db, string? id = null, string name = "TestSet", double totalPrice = 10)
{
var set = new ProductSet
{
Id = id ?? Guid.NewGuid().ToString(),
SetName = name,
TotalPrice = totalPrice
};
db.ProductSets.Add(set);
db.SaveChanges();
return set;
}
// ---------- COMPONENT ----------
public static Component InsertComponent(this YAPDbContext db, string? id = null, string name = "Component", ComponentType type = ComponentType.Consumable)
{
var comp = new Component
{
Id = Guid.NewGuid().ToString(),
Name = name,
ComponentType = type
};
db.Components.Add(comp);
db.SaveChanges();
return comp;
}
// ---------- COMMENT ----------
public static Comment InsertComment(this YAPDbContext db, string workerId, string productSetId, string? id = null, string text = "Test comment")
{
var comment = new Comment
{
Id = id ?? Guid.NewGuid().ToString(),
UserId = workerId,
ProductSetId = productSetId,
Text = text,
CommentDate = DateTime.UtcNow
};
db.Comments.Add(comment);
db.SaveChanges();
return comment;
}
// ---------- M:M RELATIONSHIPS ----------
public static void AddProductSetToPurchase(this YAPDbContext db, string setId, string purchaseId)
{
db.ProductSetsInPurchase.Add(new ProductSetInPurchase
{
ProductSetId = setId,
PurchaseId = purchaseId
});
db.SaveChanges();
}
public static void AddComponentToProductSet(this YAPDbContext db, string componentId, string setId, double price = 0)
{
db.ComponentsInProductSet.Add(new ComponentInProductSet
{
ComponentId = componentId,
ProductSetId = setId,
Price = price
});
db.SaveChanges();
}
// ---------- CLEANERS ----------
public static void ClearAll(this YAPDbContext db)
{
db.Comments.ExecuteDelete();
db.ComponentsInProductSet.ExecuteDelete();
db.ComponentsInProduct.ExecuteDelete();
db.ProductSetsInPurchase.ExecuteDelete();
db.Products.ExecuteDelete();
db.ProductSets.ExecuteDelete();
db.Components.ExecuteDelete();
db.Purchases.ExecuteDelete();
db.Users.ExecuteDelete();
}
}
}

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPDatabase;
using YAPTests.Infrastructure;
namespace YAPTests.StorageContractTests
{
internal abstract class BaseStorageContractTest
{
protected YAPDbContext YAPDbContext { get; private set; }
[OneTimeSetUp]
public void OneTimeSetUp()
{
YAPDbContext = new YAPDbContext(new DatabaseConfigurationTest());
YAPDbContext.Database.EnsureDeleted();
YAPDbContext.Database.EnsureCreated();
}
[OneTimeTearDown]
public void OneTimeTearDown()
{
YAPDbContext.Database.EnsureDeleted();
YAPDbContext.Dispose();
}
}
}

View File

@@ -0,0 +1,159 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.DataModels.UserRoles;
using YAPContracts.Enums;
using YAPDatabase.Implementations;
using YAPDatabase.Models;
using YAPTests.Infrastructure;
namespace YAPTests.StorageContractTests
{
[TestFixture]
internal class UserStorageContractTest : BaseStorageContractTest
{
private WorkerStorageContract _storage;
[SetUp]
public void SetUp()
{
_storage = new WorkerStorageContract(YAPDbContext);
}
[TearDown]
public void TearDown()
{
YAPDbContext.ClearAll();
}
[Test]
public void GetList_WhenNoRecords()
{
var list = _storage.GetList();
Assert.That(list, Is.Not.Null);
Assert.That(list, Is.Empty);
}
[Test]
public void AddElement_ShouldAddWorker()
{
var worker = new WorkerDataModel(Guid.NewGuid().ToString(), "login1", "test@test.com", "hash", UserType.Worker);
_storage.AddElement(worker);
var saved = YAPDbContext.Users.OfType<Worker>().FirstOrDefault(x => x.Id == worker.Id);
Assert.That(saved, Is.Not.Null);
Assert.That(saved!.Login, Is.EqualTo(worker.Login));
}
[Test]
public void GetElementById_ShouldReturnWorker()
{
var id = Guid.NewGuid().ToString();
var worker = new Worker { Id = id, Login = "login2", Email = "mail@test.com", PasswordHash = "hash"};
YAPDbContext.Users.Add(worker);
YAPDbContext.SaveChanges();
var result = _storage.GetElementById(id);
Assert.That(result, Is.Not.Null);
Assert.That(result!.Login, Is.EqualTo("login2"));
}
[Test]
public void UpdateElement_ShouldUpdateWorker()
{
var id = Guid.NewGuid().ToString();
YAPDbContext.Users.Add(new Worker { Id = id, Login = "old", Email = "old@test.com", PasswordHash = "hash" });
YAPDbContext.SaveChanges();
var updated = new WorkerDataModel(id, "newLogin", "new@test.com", "hash", UserType.Worker);
_storage.UpdateElement(updated);
var worker = YAPDbContext.Users.OfType<Worker>().FirstOrDefault(x => x.Id == id);
Assert.That(worker, Is.Not.Null);
Assert.That(worker!.Login, Is.EqualTo("newLogin"));
}
[Test]
public void DeleteElement_ShouldRemoveWorker()
{
var id = Guid.NewGuid().ToString();
YAPDbContext.Users.Add(new Worker { Id = id, Login = "deleteMe", Email = "mail@test.com", PasswordHash = "hash" });
YAPDbContext.SaveChanges();
_storage.DeleteElement(id);
var worker = YAPDbContext.Users.OfType<Worker>().FirstOrDefault(x => x.Id == id);
Assert.That(worker, Is.Null);
}
[Test]
public void GetElementByLogin_ShouldReturnCorrectWorker()
{
var id = Guid.NewGuid().ToString();
YAPDbContext.Users.Add(new Worker { Id = id, Login = "workerLogin", Email = "mail@test.com", PasswordHash = "hash" });
YAPDbContext.SaveChanges();
var result = _storage.GetElementByLogin("workerLogin");
Assert.That(result, Is.Not.Null);
Assert.That(result!.Login, Is.EqualTo("workerLogin"));
}
[Test]
public void GetList_ShouldReturnAllWorkers()
{
YAPDbContext.Users.AddRange(new[]
{
new Worker { Id = Guid.NewGuid().ToString(), Login = "w1", Email = "w1@test.com", PasswordHash = "hash" },
new Worker { Id = Guid.NewGuid().ToString(), Login = "w2", Email = "w2@test.com", PasswordHash = "hash" }
});
YAPDbContext.SaveChanges();
var result = _storage.GetList();
Assert.That(result.Count, Is.EqualTo(2));
Assert.That(result.Any(x => x.Login == "w1"));
Assert.That(result.Any(x => x.Login == "w2"));
}
[Test]
public void AddWorkerWithCommentsAndPurchases_ShouldSaveAndLoadCorrectly()
{
// Arrange
var workerUId = Guid.NewGuid().ToString();
var purchaseId = Guid.NewGuid().ToString();
var commentId = Guid.NewGuid().ToString();
var productSetId = Guid.NewGuid().ToString();
var worker = YAPDbContext.InsertWorker(id: workerUId);
var purchase = YAPDbContext.InsertPurchase(id: purchaseId, workerId: workerUId, date: DateTime.UtcNow, totalPrice: 1500);
YAPDbContext.InsertProductSet(productSetId, "TestSet", 1500);
var comment = YAPDbContext.InsertComment(workerUId, productSetId, commentId, "comm");
var savedWorker = YAPDbContext.Users
.OfType<Worker>()
.Include(w => w.Purchases)
.Include(w => w.Comments)
.FirstOrDefault(w => w.Id == workerUId);
// Assert
Assert.That(savedWorker, Is.Not.Null);
Assert.That(savedWorker!.Purchases, Has.Count.EqualTo(1));
Assert.That(savedWorker!.Comments, Has.Count.EqualTo(1));
var savedPurchase = savedWorker.Purchases!.First();
Assert.That(savedPurchase.Id, Is.EqualTo(purchaseId));
Assert.That(savedPurchase.TotalPrice, Is.EqualTo(1500));
var savedComment = savedWorker.Comments!.First();
Assert.That(savedComment.Id, Is.EqualTo(commentId));
Assert.That(savedComment.Text, Is.EqualTo("comm"));
}
}
}

View File

@@ -21,7 +21,8 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../YAPContracts/YAPContracts.csproj"/>
<ProjectReference Include="../YAPContracts/YAPContracts.csproj" />
<ProjectReference Include="..\YAPDatabase\YAPDatabase.csproj" />
</ItemGroup>
</Project>

View File

@@ -7,6 +7,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YAPContracts", "YAPContract
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YAPTests", "YAPTests\YAPTests.csproj", "{DE74A5B9-3323-4DC9-8772-309A913012CE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YAPBusinessLogic", "YAPBusinessLogic\YAPBusinessLogic.csproj", "{C6383D39-4E34-494E-9819-5EDFC7C25F00}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YAPDatabase", "YAPDatabase\YAPDatabase.csproj", "{67CBF689-959C-415F-B2A6-7F0830E5C4FF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -21,6 +25,14 @@ Global
{DE74A5B9-3323-4DC9-8772-309A913012CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DE74A5B9-3323-4DC9-8772-309A913012CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE74A5B9-3323-4DC9-8772-309A913012CE}.Release|Any CPU.Build.0 = Release|Any CPU
{C6383D39-4E34-494E-9819-5EDFC7C25F00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C6383D39-4E34-494E-9819-5EDFC7C25F00}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C6383D39-4E34-494E-9819-5EDFC7C25F00}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C6383D39-4E34-494E-9819-5EDFC7C25F00}.Release|Any CPU.Build.0 = Release|Any CPU
{67CBF689-959C-415F-B2A6-7F0830E5C4FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{67CBF689-959C-415F-B2A6-7F0830E5C4FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{67CBF689-959C-415F-B2A6-7F0830E5C4FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{67CBF689-959C-415F-B2A6-7F0830E5C4FF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE