53 Commits

Author SHA1 Message Date
4bb1669cc6 Storekeeper email services 2025-10-02 19:41:13 +04:00
5953b0e38d Worker email service 2025-10-02 19:23:23 +04:00
ac62427ce7 transitition to pc 2025-10-02 17:03:36 +04:00
d7f59ea747 added mailkit service class 2025-09-28 23:16:57 +04:00
0b567ce757 Binding Components to Sets function 2025-09-28 22:53:29 +04:00
559a579867 transitive commit 2025-09-25 13:53:36 +04:00
95456cb956 reports division 2025-09-19 13:57:50 +04:00
cacd557cee Label + report fix 2025-09-18 21:59:24 +04:00
a272a6e3e6 Изменение надписи на кнопке 2025-09-18 18:13:50 +04:00
0f4d9a83d3 Pdf reports preview + cleanup 2025-09-18 17:33:00 +04:00
b96c2b1557 Report pages + implementation 2025-09-17 21:05:02 +04:00
7016193611 Merge branch 'Task_4_WebAPI' into Task_5_Reports 2025-09-17 11:58:56 +04:00
5c39a434c2 Недоделанные страницы отчётов 2025-09-16 19:07:12 +04:00
46965b2d98 Role-specific buttons enabled, front enhancements 2025-09-14 21:21:20 +04:00
86e7895122 Product fix 2025-09-14 18:56:31 +04:00
39927d8961 Validation on entity fields
Reports, email left
2025-09-14 02:29:41 +04:00
ee51e4d1f6 Purchase CRD done, all entities done
Field verifications, reports, email left
2025-09-14 01:07:07 +04:00
4d4fb598cc privacy policy update 2025-09-01 20:05:03 +04:00
b7a5975e03 Typos + can't edit/delete not your comment 2025-08-31 16:24:31 +04:00
611c1dfadc Comments displaying in ProductSets and deleting with them accordingly 2025-08-31 15:06:04 +04:00
16fb3d3870 Comments View done, shit code in progress 2025-08-29 21:30:40 +04:00
6cc1bf8116 ProductSet fixed 2025-08-29 17:47:00 +04:00
f72a5f0f30 ProductSet Components DO NOT WORK 2025-08-27 03:16:40 +04:00
99c34dd9a7 Authorization+Authentification, main page, minor page changes 2025-08-26 22:43:21 +04:00
a1cee42c10 Report logic 2025-08-26 20:39:48 +04:00
9df854e056 OfficePackage 2025-08-26 20:05:47 +04:00
d57d326eeb Components + Products Views done, Migrations, fixes 2025-08-26 19:29:42 +04:00
97cd727a93 missed errors 2025-08-25 23:49:45 +04:00
bce23f4a5e WebAPI -> WebApp, controllers + adapters 2025-08-25 23:22:16 +04:00
338070c5d8 ProductOrder without controller 2025-08-24 21:03:51 +04:00
7ea4bfad28 WebAPI user adapters & controllers, binding + view models 2025-08-24 19:27:25 +04:00
6781609da3 Storekeeper ViewModels 2025-08-24 17:49:49 +04:00
3178a4d40b Worker view models 2025-08-23 20:15:51 +04:00
769e042dc4 WebAPI project, binding models 2025-08-23 19:26:37 +04:00
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
319 changed files with 96393 additions and 143 deletions

View File

@@ -0,0 +1,138 @@
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> GetCommentsByProductSet(string productSetId)
{
_logger.LogInformation("GetCommentsByProductSet method called with productSetId: {productSetId}", productSetId);
if (productSetId.IsEmpty())
{
throw new ArgumentNullException(nameof(productSetId));
}
if (!productSetId.IsGuid())
{
throw new ValidationException("ProductSetId is not a unique identifier");
}
var comments = _commentStorageContract.GetList(productSetId: productSetId);
return comments ?? throw new NullListException();
}
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,95 @@
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.GetElementByDealerName(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);
}
}

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,240 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPBusinessLogic.OfficePackage;
using YAPContracts.BusinessLogicContracts;
using YAPContracts.StorageContracts;
using YAPDatabase.Implementations;
namespace YAPBusinessLogic.Implementations
{
internal class ReportBusinessLogicContract : IReportBusinessLogicContract
{
private readonly IProductStorageContract _productStorageContract;
private readonly IPurchaseStorageContract _purchaseStorageContract;
private readonly IProductSetStorageContract _productSetStorageContract;
private readonly IComponentStorageContract _componentStorageContract;
private readonly BasePdfBuilder _pdfBuilder;
public ReportBusinessLogicContract(IProductStorageContract productStorageContract, IPurchaseStorageContract purchaseStorageContract, IProductSetStorageContract productSetStorageContract, IComponentStorageContract componentStorageContract, BasePdfBuilder pdfBuilder)
{
_productStorageContract = productStorageContract;
_purchaseStorageContract = purchaseStorageContract;
_productSetStorageContract = productSetStorageContract;
_componentStorageContract = componentStorageContract;
_pdfBuilder = pdfBuilder;
}
/// <summary>
/// Список товаров по выбранным сборкам в формате текстового документа или электронной таблицы
/// </summary>
/// <param name="setsIds">Id соборок</param>
/// <param name="format">doc/xls</param>
public Stream MakeReportProductsByProductSets(List<string> setsIds, string format)
{
// Получаем продукты по сборкам
var products = _productStorageContract.GetListProductsByProductSet(setsIds);
if (string.Equals(format, "xls", StringComparison.OrdinalIgnoreCase))
{
var excel = new OpenXmlExcelBuilder();
excel.AddHeader("Products by Sets", 0, 4);
// таблица
var rows = new List<string[]>();
rows.Add(new[] { "Product", "Included in Sets" });
foreach (var prod in products)
{
var setNames = prod.Sets.Any()
? string.Join(", ", prod.Sets.Select(s => s.SetName))
: "No Sets.";
rows.Add(new[] { prod.Product?.Name ?? "-", setNames });
}
excel.AddTable([10, 10], rows);
return excel.Build();
}
else if (string.Equals(format, "doc", StringComparison.OrdinalIgnoreCase))
{
StringBuilder sb = new StringBuilder();
var word = new OpenXmlWordBuilder();
word.AddHeader("Products by Sets");
foreach (var prod in products)
{
word.AddParagraph($"Product: {prod.Product?.Name}");
sb.Append("Sets: ");
var setNames = prod.Sets.Any()
? string.Join(", ", prod.Sets.Select(s => s.SetName))
: "No Sets.";
sb.Append(setNames);
word.AddParagraph(sb.ToString());
sb.Clear();
}
return word.Build();
}
else
{
throw new ArgumentException("Only «doc» and «xls» formats are supported", nameof(format));
}
}
/// <summary>
/// Список сборок по выбранным товарам в формате текстового документа или электронной таблицы
/// </summary>
/// <param name="productIds">Id товаров</param>
/// <param name="format">doc/xls</param>
public Stream MakeReportProductSetsByProducts(List<string> productIds, string format)
{
// Получаем продукты по сборкам
var productSets = _productSetStorageContract.GetListProductSetsByProducts(productIds);
if (string.Equals(format, "xls", StringComparison.OrdinalIgnoreCase))
{
var excel = new OpenXmlExcelBuilder();
excel.AddHeader("Product Sets by Products", 0, 4);
var rows = new List<string[]>();
rows.Add(new[] { "Product Set", "Products" });
foreach (var set in productSets)
{
var productNames = set.Products.Any()
? string.Join(", ", set.Products.Select(p => p.Name))
: "Нет товаров";
rows.Add(new[] { set.Set?.SetName ?? "-", productNames });
}
excel.AddTable([10, 10], rows);
return excel.Build();
}
else if (string.Equals(format, "doc", StringComparison.OrdinalIgnoreCase))
{
StringBuilder sb = new StringBuilder();
var word = new OpenXmlWordBuilder();
word.AddHeader("Product Sets by Products");
foreach (var set in productSets)
{
word.AddParagraph($"Сборка: {set.Set?.SetName}");
sb.Append("Товары: ");
var productNames = set.Products.Any()
? string.Join(", ", set.Products.Select(p => p.Name))
: "Нет товаров";
sb.Append(productNames);
word.AddParagraph(sb.ToString());
sb.Clear();
}
return word.Build();
}
else
{
throw new ArgumentException("Only «doc» and «xls» formats are supported", nameof(format));
}
}
/// <summary>
/// Отчет по продажам за период с расшифровкой по комментариям и комплектющим
/// </summary>
/// <param name="dateStart">Начало периода</param>
/// <param name="dateEnd">Конец периода</param>
public Stream MakeReportByPurchases(DateTime dateStart, DateTime dateEnd)
{
_pdfBuilder.AddHeader("Purchases report");
var reportData = _purchaseStorageContract.GetDataForReport(dateStart, dateEnd);
_pdfBuilder.AddParagraph($"Period: {dateStart.ToLocalTime()} — {dateEnd.ToLocalTime()}");
foreach (var sale in reportData)
{
_pdfBuilder.AddParagraph($"----------------------------------");
_pdfBuilder.AddParagraph($"Purchase date: {sale.Purchase.PurchaseDate}");
_pdfBuilder.AddParagraph($"Total: {sale.Purchase.TotalPrice}");
_pdfBuilder.AddParagraph($"");
_pdfBuilder.AddParagraph($"Components");
if (sale.Components is { Count: > 0 })
{
_pdfBuilder.AddTable(
new[] { "Name", "Type" },
sale.Components.Select(p => new[] { p.Name, p.ComponentType.ToString() }).ToList()
);
}
else
{
_pdfBuilder.AddParagraph("No components found.");
}
_pdfBuilder.AddParagraph($"Comments");
if (sale.Comments is { Count: > 0 })
{
_pdfBuilder.AddTable(
new[] { "Text", "Date" },
sale.Comments.Select(p => new[] { p.Text, p.Date.ToString("dd.MM.yyyy") }).ToList()
);
}
else
{
_pdfBuilder.AddParagraph("No comments found.");
}
}
return _pdfBuilder.Build();
}
/// <summary>
/// Отчет по комплектующим за период с расшифровкой по покупкам и заказам
/// </summary>
/// <param name="dateStart">Начало периода</param>
/// <param name="dateEnd">Конец периода</param>
public Stream MakeReportByComponents(DateTime dateStart, DateTime dateEnd)
{
if (dateEnd < dateStart)
{
throw new ArgumentException("End date must be later than start date.");
}
_pdfBuilder.AddHeader("Components report");
var reportData = _componentStorageContract.GetDataForReport(dateStart, dateEnd);
_pdfBuilder.AddParagraph($"Period: {dateStart.ToLocalTime()} — {dateEnd.ToLocalTime()}");
foreach (var comp in reportData)
{
_pdfBuilder.AddParagraph($"----------------------------------");
_pdfBuilder.AddParagraph($"Name: {comp.Component.Name}");
_pdfBuilder.AddParagraph($"Type: {comp.Component.ComponentType}");
_pdfBuilder.AddParagraph($"");
_pdfBuilder.AddParagraph($"Purchases");
if (comp.Purchases is { Count: > 0 })
{
_pdfBuilder.AddTable(
new[] { "Date", "Sum" },
comp.Purchases.Select(p => new[] { p.PurchaseDate.ToString("MM/dd/yy"), p.TotalPrice.ToString() }).ToList()
);
}
else
{
_pdfBuilder.AddParagraph("No purchases found.");
}
_pdfBuilder.AddParagraph($"Orders");
if (comp.Orders is { Count: > 0 })
{
_pdfBuilder.AddTable(
new[] { "Date", "Dealer Name" },
comp.Orders.Select(p => new[] { p.OrderDate.ToString("dd.MM.yyyy"), p.DealerName }).ToList()
);
}
else
{
_pdfBuilder.AddParagraph("No orders found.");
}
}
return _pdfBuilder.Build();
}
}
}

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,12 @@
namespace YAPBusinessLogic.OfficePackage;
public abstract class BaseExcelBuilder
{
public abstract BaseExcelBuilder AddHeader(string header, int startIndex, int count);
public abstract BaseExcelBuilder AddParagraph(string text, int columnIndex);
public abstract BaseExcelBuilder AddTable(int[] columnsWidths, List<string[]> data);
public abstract Stream Build();
}

View File

@@ -0,0 +1,14 @@
namespace YAPBusinessLogic.OfficePackage;
public abstract class BasePdfBuilder
{
public abstract BasePdfBuilder AddHeader(string header);
public abstract BasePdfBuilder AddParagraph(string text);
public abstract BasePdfBuilder AddPieChart(string title, List<(string Caption, double Value)> data);
public abstract BasePdfBuilder AddTable(string[] headers, List<string[]> rows, int[]? columnsWidths = null);
public abstract Stream Build();
}

View File

@@ -0,0 +1,12 @@
namespace YAPBusinessLogic.OfficePackage;
public abstract class BaseWordBuilder
{
public abstract BaseWordBuilder AddHeader(string header);
public abstract BaseWordBuilder AddParagraph(string text);
public abstract BaseWordBuilder AddTable(int[] widths, List<string[]> data);
public abstract Stream Build();
}

View File

@@ -0,0 +1,124 @@
using System.Text;
using MigraDocCore.DocumentObjectModel;
using MigraDocCore.DocumentObjectModel.Shapes.Charts;
using MigraDocCore.DocumentObjectModel.Tables;
using MigraDocCore.Rendering;
using Document = MigraDocCore.DocumentObjectModel.Document;
namespace YAPBusinessLogic.OfficePackage;
internal class MigraDocPdfBuilder : BasePdfBuilder
{
private readonly Document _document;
public MigraDocPdfBuilder()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
_document = new Document();
DefineStyles();
}
public override BasePdfBuilder AddHeader(string header)
{
_document.AddSection().AddParagraph(header, "NormalBold");
return this;
}
public override BasePdfBuilder AddParagraph(string text)
{
_document.LastSection.AddParagraph(text, "Normal");
return this;
}
public override BasePdfBuilder AddTable(string[] headers, List<string[]> rows, int[]? columnsWidths = null)
{
var section = _document.LastSection ?? _document.AddSection();
var table = section.AddTable();
table.Format.Font.Size = 10;
for (int i = 0; i < headers.Length; i++)
{
var column = table.AddColumn(Unit.FromCentimeter(columnsWidths != null && i < columnsWidths.Length ? columnsWidths[i] / 10.0 : 5.0));
column.Format.Alignment = ParagraphAlignment.Left;
}
var headerRow = table.AddRow();
headerRow.Shading.Color = Colors.LightGray;
headerRow.Format.Font.Bold = true;
for (int i = 0; i < headers.Length; i++)
{
headerRow.Cells[i].AddParagraph(headers[i]);
headerRow.Cells[i].Format.Alignment = ParagraphAlignment.Left;
headerRow.Cells[i].VerticalAlignment = VerticalAlignment.Center;
}
foreach (var row in rows)
{
var tableRow = table.AddRow();
for (int i = 0; i < headers.Length; i++)
{
string cellText = i < row.Length ? row[i] : string.Empty;
tableRow.Cells[i].AddParagraph(cellText);
tableRow.Cells[i].Format.Alignment = ParagraphAlignment.Left;
tableRow.Cells[i].VerticalAlignment = VerticalAlignment.Center;
}
}
return this;
}
public override BasePdfBuilder AddPieChart(string title, List<(string Caption, double Value)> data)
{
if (data == null || data.Count == 0)
{
return this;
}
var chart = new Chart(ChartType.Pie2D);
var series = chart.SeriesCollection.AddSeries();
series.Add(data.Select(x => x.Value).ToArray());
var xseries = chart.XValues.AddXSeries();
xseries.Add(data.Select(x => x.Caption).ToArray());
chart.DataLabel.Type = DataLabelType.Percent;
chart.DataLabel.Position = DataLabelPosition.OutsideEnd;
chart.Width = Unit.FromCentimeter(16);
chart.Height = Unit.FromCentimeter(12);
chart.TopArea.AddParagraph(title);
chart.XAxis.MajorTickMark = TickMarkType.Outside;
chart.YAxis.MajorTickMark = TickMarkType.Outside;
chart.YAxis.HasMajorGridlines = true;
chart.PlotArea.LineFormat.Width = 1;
chart.PlotArea.LineFormat.Visible = true;
chart.TopArea.AddLegend();
_document.LastSection.Add(chart);
return this;
}
public override Stream Build()
{
var stream = new MemoryStream();
var renderer = new PdfDocumentRenderer(true)
{
Document = _document
};
renderer.RenderDocument();
renderer.PdfDocument.Save(stream);
return stream;
}
private void DefineStyles()
{
var style = _document.Styles.AddStyle("NormalBold", "Normal");
style.Font.Bold = true;
}
}

View File

@@ -0,0 +1,303 @@
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
namespace YAPBusinessLogic.OfficePackage;
internal class OpenXmlExcelBuilder : BaseExcelBuilder
{
private readonly SheetData _sheetData;
private readonly MergeCells _mergeCells;
private readonly Columns _columns;
private uint _rowIndex = 0;
public OpenXmlExcelBuilder()
{
_sheetData = new SheetData();
_mergeCells = new MergeCells();
_columns = new Columns();
_rowIndex = 1;
}
public override BaseExcelBuilder AddHeader(string header, int startIndex, int count)
{
CreateCell(startIndex, _rowIndex, header, StyleIndex.BoldTextWithoutBorder);
for (int i = startIndex + 1; i < startIndex + count; ++i)
{
CreateCell(i, _rowIndex, "", StyleIndex.SimpleTextWithoutBorder);
}
_mergeCells.Append(new MergeCell()
{
Reference =
new StringValue($"{GetExcelColumnName(startIndex)}{_rowIndex}:{GetExcelColumnName(startIndex + count - 1)}{_rowIndex}")
});
_rowIndex++;
return this;
}
public override BaseExcelBuilder AddParagraph(string text, int columnIndex)
{
CreateCell(columnIndex, _rowIndex++, text, StyleIndex.SimpleTextWithoutBorder);
return this;
}
public override BaseExcelBuilder AddTable(int[] columnsWidths, List<string[]> data)
{
if (columnsWidths == null || columnsWidths.Length == 0)
{
throw new ArgumentNullException(nameof(columnsWidths));
}
if (data == null || data.Count == 0)
{
throw new ArgumentNullException(nameof(data));
}
if (data.Any(x => x.Length != columnsWidths.Length))
{
throw new InvalidOperationException("widths.Length != data.Length");
}
uint counter = 1;
int coef = 2;
_columns.Append(columnsWidths.Select(x => new Column
{
Min = counter,
Max = counter++,
Width = x * coef,
CustomWidth = true
}));
for (var j = 0; j < data.First().Length; ++j)
{
CreateCell(j, _rowIndex, data.First()[j], StyleIndex.BoldTextWithBorder);
}
_rowIndex++;
for (var i = 1; i < data.Count - 1; ++i)
{
for (var j = 0; j < data[i].Length; ++j)
{
CreateCell(j, _rowIndex, data[i][j], StyleIndex.SimpleTextWithBorder);
}
_rowIndex++;
}
for (var j = 0; j < data.Last().Length; ++j)
{
CreateCell(j, _rowIndex, data.Last()[j], StyleIndex.BoldTextWithBorder);
}
_rowIndex++;
return this;
}
public override Stream Build()
{
var stream = new MemoryStream();
using var spreadsheetDocument = SpreadsheetDocument.Create(stream, SpreadsheetDocumentType.Workbook);
var workbookpart = spreadsheetDocument.AddWorkbookPart();
GenerateStyle(workbookpart);
workbookpart.Workbook = new Workbook();
var worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet();
if (_columns.HasChildren)
{
worksheetPart.Worksheet.Append(_columns);
}
worksheetPart.Worksheet.Append(_sheetData);
var sheets = spreadsheetDocument.WorkbookPart!.Workbook.AppendChild(new Sheets());
var sheet = new Sheet()
{
Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart),
SheetId = 1,
Name = "Лист 1"
};
sheets.Append(sheet);
if (_mergeCells.HasChildren)
{
worksheetPart.Worksheet.InsertAfter(_mergeCells, worksheetPart.Worksheet.Elements<SheetData>().First());
}
return stream;
}
private static void GenerateStyle(WorkbookPart workbookPart)
{
var workbookStylesPart = workbookPart.AddNewPart<WorkbookStylesPart>();
workbookStylesPart.Stylesheet = new Stylesheet();
var fonts = new Fonts() { Count = 2, KnownFonts = BooleanValue.FromBoolean(true) };
fonts.Append(new DocumentFormat.OpenXml.Spreadsheet.Font
{
FontSize = new FontSize() { Val = 11 },
FontName = new FontName() { Val = "Calibri" },
FontFamilyNumbering = new FontFamilyNumbering() { Val = 2 },
FontScheme = new FontScheme() { Val = new EnumValue<FontSchemeValues>(FontSchemeValues.Minor) }
});
fonts.Append(new DocumentFormat.OpenXml.Spreadsheet.Font
{
FontSize = new FontSize() { Val = 11 },
FontName = new FontName() { Val = "Calibri" },
FontFamilyNumbering = new FontFamilyNumbering() { Val = 2 },
FontScheme = new FontScheme() { Val = new EnumValue<FontSchemeValues>(FontSchemeValues.Minor) },
Bold = new Bold()
});
workbookStylesPart.Stylesheet.Append(fonts);
// Default Fill
var fills = new Fills() { Count = 1 };
fills.Append(new Fill
{
PatternFill = new PatternFill() { PatternType = new EnumValue<PatternValues>(PatternValues.None) }
});
workbookStylesPart.Stylesheet.Append(fills);
// Default Border
var borders = new Borders() { Count = 2 };
borders.Append(new Border
{
LeftBorder = new LeftBorder(),
RightBorder = new RightBorder(),
TopBorder = new TopBorder(),
BottomBorder = new BottomBorder(),
DiagonalBorder = new DiagonalBorder()
});
borders.Append(new Border
{
LeftBorder = new LeftBorder() { Style = BorderStyleValues.Thin },
RightBorder = new RightBorder() { Style = BorderStyleValues.Thin },
TopBorder = new TopBorder() { Style = BorderStyleValues.Thin },
BottomBorder = new BottomBorder() { Style = BorderStyleValues.Thin }
});
workbookStylesPart.Stylesheet.Append(borders);
// Default cell format and a date cell format
var cellFormats = new CellFormats() { Count = 4 };
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 0,
BorderId = 0,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Left,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 0,
BorderId = 1,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Left,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 1,
BorderId = 0,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Center,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 1,
BorderId = 1,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Center,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
workbookStylesPart.Stylesheet.Append(cellFormats);
}
private enum StyleIndex
{
SimpleTextWithoutBorder = 0,
SimpleTextWithBorder = 1,
BoldTextWithoutBorder = 2,
BoldTextWithBorder = 3
}
private void CreateCell(int columnIndex, uint rowIndex, string text, StyleIndex styleIndex)
{
var columnName = GetExcelColumnName(columnIndex);
var cellReference = columnName + rowIndex;
var row = _sheetData.Elements<Row>().FirstOrDefault(r => r.RowIndex! == rowIndex);
if (row == null)
{
row = new Row() { RowIndex = rowIndex };
_sheetData.Append(row);
}
var newCell = row.Elements<Cell>()
.FirstOrDefault(c => c.CellReference != null && c.CellReference.Value == columnName + rowIndex);
if (newCell == null)
{
Cell? refCell = null;
foreach (Cell cell in row.Elements<Cell>())
{
if (cell.CellReference?.Value != null && cell.CellReference.Value.Length == cellReference.Length)
{
if (string.Compare(cell.CellReference.Value, cellReference, true) > 0)
{
refCell = cell;
break;
}
}
}
newCell = new Cell() { CellReference = cellReference };
row.InsertBefore(newCell, refCell);
}
newCell.CellValue = new CellValue(text);
newCell.DataType = CellValues.String;
newCell.StyleIndex = (uint)styleIndex;
}
private static string GetExcelColumnName(int columnNumber)
{
columnNumber += 1;
int dividend = columnNumber;
string columnName = string.Empty;
int modulo;
while (dividend > 0)
{
modulo = (dividend - 1) % 26;
columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
dividend = (dividend - modulo) / 26;
}
return columnName;
}
}

View File

@@ -0,0 +1,94 @@
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
namespace YAPBusinessLogic.OfficePackage;
internal class OpenXmlWordBuilder : BaseWordBuilder
{
private readonly Document _document;
private readonly Body _body;
public OpenXmlWordBuilder()
{
_document = new Document();
_body = _document.AppendChild(new Body());
}
public override BaseWordBuilder AddHeader(string header)
{
var paragraph = _body.AppendChild(new Paragraph());
var run = paragraph.AppendChild(new Run());
run.AppendChild(new RunProperties(new Bold()));
run.AppendChild(new Text(header));
return this;
}
public override BaseWordBuilder AddParagraph(string text)
{
var paragraph = _body.AppendChild(new Paragraph());
var run = paragraph.AppendChild(new Run());
run.AppendChild(new Text(text));
return this;
}
public override BaseWordBuilder AddTable(int[] widths, List<string[]> data)
{
if (widths == null || widths.Length == 0)
{
throw new ArgumentNullException(nameof(widths));
}
if (data == null || data.Count == 0)
{
throw new ArgumentNullException(nameof(data));
}
if (data.Any(x => x.Length != widths.Length))
{
throw new InvalidOperationException("widths.Length != data.Length");
}
var table = new Table();
table.AppendChild(new TableProperties(
new TableBorders(
new TopBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new BottomBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new LeftBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new RightBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new InsideHorizontalBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 },
new InsideVerticalBorder() { Val = new EnumValue<BorderValues>(BorderValues.Single), Size = 12 }
)
));
// Заголовок
var tr = new TableRow();
for (var j = 0; j < widths.Length; ++j)
{
tr.Append(new TableCell(
new TableCellProperties(new TableCellWidth() { Width = widths[j].ToString() }),
new Paragraph(new Run(new RunProperties(new Bold()), new Text(data.First()[j])))));
}
table.Append(tr);
// Данные
table.Append(data.Skip(1).Select(x =>
new TableRow(x.Select(y => new TableCell(new Paragraph(new Run(new Text(y))))))));
_body.Append(table);
return this;
}
public override Stream Build()
{
var stream = new MemoryStream();
using var wordDocument = WordprocessingDocument.Create(stream, WordprocessingDocumentType.Document);
var mainPart = wordDocument.AddMainDocumentPart();
mainPart.Document = _document;
return stream;
}
}

View File

@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<InternalsVisibleTo Include="YAPTests" />
<InternalsVisibleTo Include="YAPWebApplication" />
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="3.3.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.5" />
<PackageReference Include="MigraDocCore.DocumentObjectModel" Version="1.3.67" />
<PackageReference Include="MigraDocCore.Rendering" Version="1.3.67" />
<PackageReference Include="PdfSharpCore" Version="1.3.67" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\YAPContracts\YAPContracts.csproj" />
<ProjectReference Include="..\YAPDatabase\YAPDatabase.csproj" />
</ItemGroup>
</Project>

View File

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

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.BindingModels;
using YAPContracts.DataModels;
using YAPContracts.ViewModels;
namespace YAPContracts.AdapterContracts
{
public interface ICommentAdapter
{
List<CommentViewModel>? GetList();
CommentViewModel? GetCommentById(string id);
List<CommentViewModel>? GetCommentsByProductSetAndPeriod(string productSetId, DateTime fromDate, DateTime toDate);
List<CommentViewModel>? GetCommentsByUserAndPeriod(string userId, DateTime fromDate, DateTime toDate);
List<CommentViewModel>? GetCommentsByPeriod(DateTime fromDate, DateTime toDate);
void Create(CommentBindingModel comment);
void Update(CommentBindingModel comment);
void Delete(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.BindingModels;
using YAPContracts.ViewModels;
namespace YAPContracts.AdapterContracts
{
public interface IComponentAdapter
{
List<ComponentViewModel>? GetList(bool onlyActual);
ComponentViewModel? GetComponentByData(string data);
void Insert(ComponentBindingModel component);
void Update(ComponentBindingModel component);
void Delete(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.BindingModels;
using YAPContracts.DataModels;
using YAPContracts.ViewModels;
namespace YAPContracts.AdapterContracts
{
public interface IProductAdapter
{
List<ProductViewModel>? GetList(bool onlyActual = true);
ProductViewModel? GetProductByData(string data);
void Insert(ProductBindingModel product);
void Update(ProductBindingModel product);
void Delete(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.BindingModels;
using YAPContracts.ViewModels;
namespace YAPContracts.AdapterContracts;
public interface IProductOrderAdapter
{
List<ProductOrderViewModel>? GetList();
List<ProductOrderViewModel>? GetListByPeriod(DateTime fromDate, DateTime toDate);
List<ProductOrderViewModel>? GetListByProductAndPeriod(string productId, DateTime fromDate, DateTime toDate);
ProductOrderViewModel? GetElement(string data);
void RegisterProductOrder(ProductOrderBindingModel productOrderModel);
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.BindingModels;
using YAPContracts.DataModels;
using YAPContracts.ViewModels;
namespace YAPContracts.AdapterContracts
{
public interface IProductSetAdapter
{
List<ProductSetViewModel>? GetList();
ProductSetViewModel? GetProductSetByData(string data);
void Insert(ProductSetBindingModel productSet);
void Update(ProductSetBindingModel productSet);
void Delete(string id);
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.BindingModels;
using YAPContracts.DataModels;
using YAPContracts.ViewModels;
namespace YAPContracts.AdapterContracts
{
public interface IPurchaseAdapter
{
List<PurchaseViewModel>? GetList();
PurchaseViewModel? GetElement(string id);
List<PurchaseViewModel>? GetByUserAndPeriod(string userId, DateTime fromDate, DateTime toDate);
List<PurchaseViewModel>? GetByPeriod(DateTime fromDate, DateTime toDate);
void Register(PurchaseBindingModel purchase);
void Update(PurchaseBindingModel purchase);
void Delete(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.BindingModels;
using YAPContracts.ViewModels;
namespace YAPContracts.AdapterContracts
{
public interface IStorekeeperAdapter
{
List<StorekeeperViewModel>? GetList();
StorekeeperViewModel? GetElement(string id);
void Register(StorekeeperBindingModel storekeeper);
void Update(StorekeeperBindingModel storekeeper);
void Delete(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.BindingModels;
using YAPContracts.ViewModels;
namespace YAPContracts.AdapterContracts
{
public interface IWorkerAdapter
{
List<WorkerViewModel>? GetList();
WorkerViewModel? GetElement(string id);
void Register(WorkerBindingModel worker);
void Update(WorkerBindingModel worker);
void Delete(string id);
}
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Net.Mime.MediaTypeNames;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace YAPContracts.BindingModels
{
public class CommentBindingModel
{
public string? Id { get; set; }
[Required(ErrorMessage = "This field is required")]
public string? ProductSetId { get; set; }
public string? UserId { get; set; }
public DateTime Date { get; set; }
[Required(ErrorMessage = "This field is required")]
[StringLength(400, MinimumLength = 4, ErrorMessage = "Atleast 4 symbols")]
public string? Text { get; set; }
}
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using YAPContracts.Enums;
namespace YAPContracts.BindingModels
{
public class ComponentBindingModel
{
public string? Id { get; set; }
[Required(ErrorMessage = "This field is required")]
[Display(Name = "Component Name")]
public string? Name { get; set; }
[Required(ErrorMessage = "This field is required")]
[Display(Name = "Component Type")]
public string? ComponentType { get; set; }
public List<string>? ProductSetIds { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.BindingModels
{
public class ComponentInProductSetBindingModel
{
public string? ComponentId { get; private set; }
public string? ProductSetId { get; private set; }
public int Amount { get; private set; }
}
}

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace YAPContracts.BindingModels
{
public class ProductBindingModel
{
public string? Id { get; set; }
[Required(ErrorMessage = "This field is required")]
[Display(Name = "Product Name")]
public string? Name { get; set; }
[Required(ErrorMessage = "This field is required")]
[Range(1, double.MaxValue, ErrorMessage = "Price must be greater than 0")]
[Display(Name = "Price")]
public double Price { get; set; }
[Required(ErrorMessage = "This field is required")]
[Display(Name = "Components")]
public List<string> ComponentIds { get; set; } = new List<string>();
public List<ProductOrderBindingModel> ProductOrders { get; set; } = new List<ProductOrderBindingModel>();
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.BindingModels
{
public class ProductInPurchaseBindingModel
{
public string? PurchaseId { get; set; }
public string? ProductId { get; set; }
public int Amount { get; set; }
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.Infrastructure;
namespace YAPContracts.BindingModels
{
public class ProductOrderBindingModel
{
public string? Id { get; set; }
public string? UserId { get; set; }
[FutureDate]
public DateTime OrderDate { get; set; }
[Required(ErrorMessage = "This field is required")]
[StringLength(30, MinimumLength = 2, ErrorMessage = "Atleast 2 symbols")]
public string? DealerName { get; set; }
[Required(ErrorMessage = "This field is required")]
public string? ProductId { get; set; }
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.BindingModels
{
public class ProductSetBindingModel
{
public string? Id { get; set; }
[Required(ErrorMessage = "This field is required")]
[Display(Name = "Set Name")]
public string? SetName { get; set; }
[Required(ErrorMessage = "This field is required")]
[Range(1, double.MaxValue, ErrorMessage = "Total Price must be greater than 0")]
[Display(Name = "Total Price")]
public double? TotalPrice { get; set; }
[Required(ErrorMessage = "This field is required")]
[MinLength(1, ErrorMessage = "Atleast 1 Component is required")]
[Display(Name = "Components")]
public List<string>? ComponentIds { 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 YAPContracts.BindingModels
{
public class PurchaseBindingModel
{
public string? Id { get; set; }
public string? UserId { get; set; }
public double TotalPrice { get; set; }
public DateTime PurchaseDate { get; set; }
public List<ProductInPurchaseBindingModel>? Products { get; set; }
public List<string>? ProductSetIds { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.BindingModels
{
public class StorekeeperBindingModel
{
public string? Id { get; set; }
public string? Login { get; set; }
public string? Email { get; set; }
public string? Password { get; set; }
public List<string>? ProductOrderIds { 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 YAPContracts.BindingModels
{
public class WorkerBindingModel
{
public string? Id { get; set; }
public string? Login { get; set; }
public string? Email { get; set; }
public string? Password { get; set; }
public List<string>? PurchaseIds { get; set; }
public List<string>? CommentIds { get; set; }
}
}

View File

@@ -0,0 +1,30 @@
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> GetCommentsByProductSet(string productSetId);
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 = true);
ProductDataModel GetProductByData(string data);
void InsertProduct(ProductDataModel productDataModel);
void UpdateProduct(ProductDataModel productDataModel);
void DeleteProduct(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 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 dealerName, DateTime fromDate, DateTime toDate, bool onlyActual = true);
List<ProductOrderDataModel> GetProductOrdersByPeriod(DateTime fromDate, DateTime toDate, bool onlyActual = true);
void InsertProductOrder(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,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.BusinessLogicContracts
{
public interface IReportBusinessLogicContract
{
Stream MakeReportProductsByProductSets(List<string> setsIds, string format);
Stream MakeReportProductSetsByProducts(List<string> productIds, string format);
public Stream MakeReportByPurchases(DateTime dateStart, DateTime dateEnd);
public Stream MakeReportByComponents(DateTime dateStart, DateTime dateEnd);
}
}

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

@@ -9,13 +9,31 @@ using YAPContracts.Infrastructure;
namespace YAPContracts.DataModels
{
public class CommentDataModel(string id, string productSetId, string userId, string text, DateTime date) : IValidation
public class CommentDataModel : IValidation
{
public string Id { get; private set; } = id;
public string ProductSetId { get; private set; } = productSetId;
public string UserId { get; private set; } = userId;
public string Text { get; private set; } = text;
public DateTime Date { get; private set; } = date;
public string Id { get; private set; }
public string ProductSetId { get; private set; }
public string UserId { get; private set; }
public string Text { get; private set; }
public DateTime Date { get; private set; }
public CommentDataModel(string id, string productSetId, string userId, string text, DateTime date)
{
Id = id;
ProductSetId = productSetId;
UserId = userId;
Text = text;
Date = date;
}
public CommentDataModel()
{
Id = Guid.NewGuid().ToString();
ProductSetId = string.Empty;
UserId = string.Empty;
Text = string.Empty;
Date = DateTime.UtcNow;
}
public void Validate()
{

View File

@@ -10,11 +10,34 @@ using YAPContracts.Infrastructure;
namespace YAPContracts.DataModels;
public class ComponentDataModel(string id, string name, ComponentType componentType) : IValidation
public class ComponentDataModel : IValidation
{
public string Id { get; private set; } = id;
public string Name { get; private set; } = name;
public ComponentType ComponentType { get; private set; } = componentType;
public string Id { get; private set; }
public string Name { get; private set; }
public ComponentType ComponentType { get; private set; }
public bool IsDeleted { get; private set; }
// public List<ComponentInProductDataModel> Products = products;
public List<ComponentInProductSetDataModel> ProductSets { get; private set; }
public ComponentDataModel(string id, string name, ComponentType componentType, bool isDeleted, List<ComponentInProductSetDataModel> productSets)
{
Id = id;
Name = name;
ComponentType = componentType;
IsDeleted = isDeleted;
ProductSets = productSets;
}
public ComponentDataModel()
{
Id = Guid.NewGuid().ToString();
Name = string.Empty;
ComponentType = ComponentType.None;
IsDeleted = false;
ProductSets = new List<ComponentInProductSetDataModel>();
}
public void Validate()
{
if (!Id.IsGuid())
@@ -29,7 +52,7 @@ public class ComponentDataModel(string id, string name, ComponentType componentT
{
throw new ValidationException("Name is empty");
}
if (componentType == ComponentType.None)
if (ComponentType == ComponentType.None)
{
throw new ValidationException("Product type is empty");
}

View File

@@ -9,11 +9,25 @@ using YAPContracts.Infrastructure;
namespace YAPContracts.DataModels
{
public class ComponentInProductSetDataModel(string componentId, string productSetId, int amount) : IValidation
public class ComponentInProductSetDataModel : IValidation
{
public string ComponentId { get; private set; } = componentId;
public string ProductSetId { get; private set; } = productSetId;
public int Amount { get; private set; } = amount;
public string ComponentId { get; private set; }
public string ProductSetId { get; private set; }
public int Price { get; private set; }
public ComponentInProductSetDataModel(string componentId, string productSetId, int price)
{
ComponentId = componentId;
ProductSetId = productSetId;
Price = price;
}
public ComponentInProductSetDataModel()
{
ComponentId = string.Empty;
ProductSetId = string.Empty;
Price = 0;
}
public void Validate()
{
@@ -33,7 +47,7 @@ namespace YAPContracts.DataModels
{
throw new ValidationException("ProductSetId value is not valid");
}
if (Amount <= 0)
if (Price <= 0)
{
throw new ValidationException("Amount is less than or equal to 0");
}

View File

@@ -10,12 +10,36 @@ using YAPContracts.Infrastructure;
namespace YAPContracts.DataModels;
public class ProductDataModel(string id, string name, double price, List<ComponentInProductDataModel> componentProducts) : IValidation
public class ProductDataModel : 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 string Id { get; private set; }
public string Name { get; private set; }
public double Price { get; private set; }
public bool IsDeleted { get; private set; }
public List<ComponentInProductDataModel> Components { get; private set; }
public List<ProductInPurchaseDataModel> Purchases { get; private set; }
public ProductDataModel(string id, string name, double price, bool isDeleted,
List<ComponentInProductDataModel> componentProducts, List<ProductInPurchaseDataModel> purchases)
{
Id = id;
Name = name;
Price = price;
IsDeleted = isDeleted;
Components = componentProducts;
Purchases = purchases;
}
public ProductDataModel()
{
Id = string.Empty;
Name = string.Empty;
Price = 0;
IsDeleted = false;
Components = new List<ComponentInProductDataModel>();
Purchases = new List<ProductInPurchaseDataModel>();
}
public void Validate()
{
if (!Id.IsGuid())
@@ -34,9 +58,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,35 @@ using YAPContracts.Infrastructure;
namespace YAPContracts.DataModels;
public class ProductOrder(string id, DateTime orderDate, string dealerName, string productId) : IValidation
public class ProductOrderDataModel : 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 ProductDataModel? _product;
public string Id { get; private set; }
public DateTime OrderDate { get; private set;}
public string DealerName { get; private set; }
public string ProductId { get; private set;}
public string UserId { get; private set; }
public string ProductName => _product?.Name ?? string.Empty;
public ProductOrderDataModel(string id, DateTime orderDate, string dealerName, string productId, string userId)
{
Id = id;
OrderDate = orderDate;
DealerName = dealerName;
ProductId = productId;
UserId = userId;
}
public ProductOrderDataModel()
{
Id = Guid.NewGuid().ToString();
OrderDate = DateTime.Now;
DealerName = string.Empty;
ProductId = string.Empty;
UserId = string.Empty;
}
public void Validate()
{
if (Id.IsEmpty())

View File

@@ -9,12 +9,37 @@ using YAPContracts.Infrastructure;
namespace YAPContracts.DataModels
{
public class ProductSetDataModel(string id, string setName, double totalPrice) : IValidation
public class ProductSetDataModel : IValidation
{
public string Id { get; private set; } = id;
public string SetName { get; private set; } = setName;
public string Id { get; private set; }
public string SetName { get; private set; }
public double TotalPrice { get; private set; } = totalPrice;
public double TotalPrice { get; private set; }
public bool IsDeleted { get; private set; }
public List<ComponentInProductSetDataModel> Components { get; private set; }
public List<CommentDataModel>? Comments { get; set; }
public ProductSetDataModel(string id, string setName, double totalPrice, bool isDeleted, List<ComponentInProductSetDataModel> components, List<CommentDataModel>? comments)
{
Id = id;
SetName = setName;
TotalPrice = totalPrice;
IsDeleted = isDeleted;
Components = components;
Comments = comments;
}
public ProductSetDataModel()
{
Id = Guid.NewGuid().ToString();
SetName = string.Empty;
TotalPrice = 0;
IsDeleted = false;
Components = new List<ComponentInProductSetDataModel>();
Comments = new List<CommentDataModel>();
}
public void Validate()
{

View File

@@ -9,16 +9,12 @@ using YAPContracts.Exceptions;
namespace YAPContracts.DataModels
{
public class ProductSetInPurchaseDataModel(string purchaseId, string productSetId, int amount, double? discount) : IValidation
public class ProductSetInPurchaseDataModel(string purchaseId, string productSetId) : IValidation
{
public string PurchaseId { get; private set; } = purchaseId;
public string ProductSetId { get; private set; } = productSetId;
public int Amount { get; private set; } = amount;
public double? Discount { get; private set; } = discount;
public void Validate()
{
if (PurchaseId.IsEmpty())
@@ -37,14 +33,6 @@ namespace YAPContracts.DataModels
{
throw new ValidationException("ProductSetId value is not valid");
}
if (Amount <= 0)
{
throw new ValidationException("Amount is less than or equal to 0");
}
if (Discount.HasValue && Discount < 0)
{
throw new ValidationException("Discount is less than 0");
}
}
}
}

View File

@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.DataModels
{
/// <summary>
/// Сущность для отчета по продуктам по сборкам
/// </summary>
public class ProductWithSetsDataModel
{
public ProductDataModel? Product { get; set; } = null!;
public List<ProductSetDataModel> Sets { get; set; } = new();
}
/// <summary>
/// Сущность для отчета по сборкам по продуктам
/// </summary>
public class SetWithProductsDataModel
{
public List<ProductDataModel> Products { get; set; } = new();
public ProductSetDataModel? Set { get; set; } = null!;
}
/// <summary>
/// Сущность для отчета по продажам с расшифровкой по комплектующим и комментариям
/// </summary>
public class PurchasesReportModel
{
public PurchaseDataModel? Purchase { get; set; } = null;
public List<ComponentDataModel>? Components { get; set; } = new();
public List<CommentDataModel>? Comments { get; set; } = new();
}
/// <summary>
/// Сущность для отчета по комплектующим с расшифровкой по покупкам и заказам на товары за период.
/// </summary>
public class ComponentReportModel
{
public ComponentDataModel? Component { get; set; } = null;
public List<PurchaseDataModel>? Purchases { get; set; } = new();
public List<ProductOrderDataModel>? Orders { get; set; } = new();
}
}

View File

@@ -9,15 +9,39 @@ using YAPContracts.Infrastructure;
namespace YAPContracts.DataModels
{
public class PurchaseDataModel(string id, double totalPrice, DateTime purchaseDate, List<ProductSetInPurchaseDataModel> productSets) : IValidation
public class PurchaseDataModel : IValidation
{
public string Id { get; private set; } = id;
public string Id { get; private set; }
public double TotalPrice { get; private set; } = totalPrice;
public string UserId { get; private set; }
public DateTime PurchaseDate { get; private set; } = purchaseDate;
public double TotalPrice { get; private set; }
public List<ProductSetInPurchaseDataModel> ProductSets = productSets;
public DateTime PurchaseDate { get; private set; }
public List<ProductSetInPurchaseDataModel> ProductSets { get; private set; }
public List<ProductInPurchaseDataModel> Products { get; private set; }
public PurchaseDataModel(string id, string userId, double totalPrice, DateTime purchaseDate, List<ProductSetInPurchaseDataModel> productSets, List<ProductInPurchaseDataModel> products)
{
Id = id;
UserId = userId;
TotalPrice = totalPrice;
PurchaseDate = purchaseDate;
ProductSets = productSets;
Products = products;
}
public PurchaseDataModel()
{
Id = string.Empty;
UserId = string.Empty;
TotalPrice = 0;
PurchaseDate = DateTime.UtcNow;
ProductSets = new List<ProductSetInPurchaseDataModel>();
Products = new List<ProductInPurchaseDataModel>();
}
public void Validate()
{
@@ -29,14 +53,22 @@ namespace YAPContracts.DataModels
{
throw new ValidationException("Id is empty");
}
if (TotalPrice <= 0)
if (!UserId.IsGuid())
{
throw new ValidationException("TotalPrice is less than or equal to 0");
throw new ValidationException("UserId value is not valid");
}
if (UserId.IsEmpty())
{
throw new ValidationException("UserId is empty");
}
foreach (var productSet in ProductSets)
{
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,26 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.Infrastructure
{
public class FutureDateAttribute : ValidationAttribute
{
public FutureDateAttribute()
{
ErrorMessage = "Date must be later than today";
}
public override bool IsValid(object? value)
{
if (value is DateTime date)
{
return date.Date >= DateTime.Today;
}
return false;
}
}
}

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,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 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);
List<ComponentReportModel>? GetDataForReport(DateTime start, DateTime finish);
}

View File

@@ -0,0 +1,16 @@
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);
}

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 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);
List<SetWithProductsDataModel> GetListProductSetsByProducts(List<string> prodIds);
}
}

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 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);
List<ProductWithSetsDataModel> GetListProductsByProductSet(List<string> setsIds);
}

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 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);
List<PurchasesReportModel>? GetDataForReport(DateTime start, DateTime finish);
}
}

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,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.ViewModels
{
public class CommentViewModel
{
public string Id { get; set; } = default!;
public string Text { get; set; } = default!;
public DateTime CommentDate { get; set; }
public string? AuthorId { get; set; }
public string? ProductSetId { get; set; }
public string? UserLogin { get; set; }
public string? ProductSetName { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.ViewModels
{
public class ComponentInProductSetViewModel
{
public string ComponentId { get; set; } = default!;
public string ComponentName { get; set; } = default!;
public double Price { 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 YAPContracts.ViewModels
{
public class ComponentInProductViewModel
{
public string ComponentId { get; set; } = default!;
public string ComponentName { get; set; } = default!;
}
}

View File

@@ -0,0 +1,12 @@
using YAPContracts.Enums;
namespace YAPContracts.ViewModels;
public class ComponentViewModel
{
public string Id { get; set; } = default!;
public string Name { get; set; } = default!;
public ComponentType ComponentType { get; set; }
public List<string>? ProductSetIds { get; set; }
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.ViewModels
{
public class ProductInPurchaseViewModel
{
public string ProductId { get; set; } = default!;
public string PurchaseId { get; set; } = default!;
public int Amount { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.ViewModels
{
public class ProductOrderViewModel
{
public string Id { get; set; } = default!;
public DateTime OrderDate { get; set; }
public string DealerName { get; set; } = default!;
public string ProductName { get; set; } = default!;
public StorekeeperViewModel? Author { get; set; } // вырезать по мере необходимости
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.ViewModels
{
public class ProductSetViewModel
{
public string Id { get; set; } = default!;
public string SetName { get; set; } = default!;
public double TotalPrice { get; set; }
public List<string>? ComponentIds { get; set; }
public List<CommentViewModel>? Comments { 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 YAPContracts.ViewModels
{
public class ProductViewModel
{
public string Id { get; set; } = default!;
public string Name { get; set; } = default!;
public double Price { get; set; }
public List<string>? ComponentIds { get; set; }
public List<ProductOrderViewModel>? ProductOrders { get; set; }
}
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YAPContracts.ViewModels
{
public class PurchaseViewModel
{
public string Id { get; set; } = default!;
public string UserId { get; set; } = default!;
public double TotalPrice { get; set; }
public DateTime PurchaseDate { get; set; }
public WorkerViewModel? User { get; set; }
public List<ProductInPurchaseViewModel>? Products { get; set; }
public List<string>? ProductSetIds { get; set; }
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.Enums;
namespace YAPContracts.ViewModels
{
public class StorekeeperViewModel
{
public string Id { get; set; } = default!;
public string Login { get; set; } = default!;
public string Email { get; set; } = default!;
public UserType Role { get; } = UserType.Worker;
public List<ProductOrderViewModel>? ProductOrders { get; set; }
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YAPContracts.Enums;
namespace YAPContracts.ViewModels
{
public class WorkerViewModel
{
public string Id { get; set; } = default!;
public string Login { get; set; } = default!;
public string Email { get; set; } = default!;
public UserType Role { get; } = UserType.Worker;
public List<PurchaseViewModel>? Purchases { get; set; }
public List<CommentViewModel>? Comments { get; set; }
}
}

View File

@@ -6,4 +6,10 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.3.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,130 @@
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>()
.ForMember(dest => dest.Date, opt => opt.MapFrom(src => src.CommentDate));
cfg.CreateMap<CommentDataModel, Comment>()
.ForMember(dest => dest.CommentDate, opt => opt.MapFrom(src => src.Date));
});
_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,164 @@
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>();
cfg.CreateMap<Component, ComponentDataModel>();
cfg.CreateMap<Purchase, PurchaseDataModel>() //Для отчета
.ForMember(dest => dest.Products, opt => opt.MapFrom(src => src.ProductsInPurchase))
.ForMember(dest => dest.ProductSets, opt => opt.MapFrom(src => src.ProductSetsInPurchase));;
cfg.CreateMap<ProductOrder, ProductOrderDataModel>(); //Для отчета
});
_mapper = new Mapper(config);
}
public void AddElement(ComponentDataModel component)
{
try
{
var entity = _mapper.Map<Component>(component);
_dbContext.Components.Add(entity);
_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.Include(x => x.ProductSets).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.Include(x => x.ProductSets).FirstOrDefault(x => x.Id == id);
public List<ComponentReportModel>? GetDataForReport(DateTime start, DateTime finish)
{
try
{
var data = _dbContext.Components
.Select(c => new ComponentReportModel
{
Component = _mapper.Map<ComponentDataModel>(c),
Purchases = c.Products
.SelectMany(cp => cp.Product.ProductsInPurchace).Where(pip => pip.Purchase.PurchaseDate >= start && pip.Purchase.PurchaseDate <= finish)
.Select(pip => _mapper.Map<PurchaseDataModel>(pip.Purchase))
.ToList(),
Orders = c.Products
.SelectMany(p => p.Product.ProductOrders).Where(po => po.OrderDate >= start && po.OrderDate <= finish)
.Select(ord => _mapper.Map<ProductOrderDataModel>(ord))
.ToList()
})
.ToList();
return data;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
}

View File

@@ -0,0 +1,113 @@
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>();
cfg.CreateMap<Product, ProductDataModel>();
});
_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 ProductOrderDataModel? GetElementById(string id)
{
try
{
var order = _mapper.Map<ProductOrderDataModel>(GetProductOrderById(id));
if (!String.IsNullOrEmpty(order.ProductId))
{
order._product = _mapper.Map<ProductDataModel>(_dbContext.Products.FirstOrDefault(x => x.Id == order.ProductId));
}
return order;
}
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
{
List<ProductOrderDataModel> result = new List<ProductOrderDataModel>();
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);
}
result = [.. query.Select(x => _mapper.Map<ProductOrderDataModel>(x))];
foreach (var order in result)
{
if (!String.IsNullOrEmpty(order.ProductId))
{
order._product = _mapper.Map<ProductDataModel>(_dbContext.Products.FirstOrDefault(x => x.Id == order.ProductId));
}
}
return result;
}
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,195 @@
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<ComponentInProductSetDataModel, ComponentInProductSet>();
cfg.CreateMap<ComponentInProductSet, ComponentInProductSetDataModel>();
cfg.CreateMap<Comment, CommentDataModel>().ForMember(dest => dest.Date, opt => opt.MapFrom(src => src.CommentDate));
cfg.CreateMap<CommentDataModel, Comment>().ForMember(dest => dest.CommentDate, opt => opt.MapFrom(src => src.Date));
cfg.CreateMap<ProductSetDataModel, ProductSet>()
.ForMember(dest => dest.ComponentsInProductSet, opt => opt.MapFrom(src => src.Components))
.ForMember(dest => dest.IsDeleted, opt => opt.MapFrom(src => false));
cfg.CreateMap<ProductSet, ProductSetDataModel>()
.ForMember(dest => dest.Components, opt => opt.MapFrom(src => src.ComponentsInProductSet));
cfg.CreateMap<Product, ProductDataModel>();
});
_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);
}
_dbContext.ProductSets.Update(_mapper.Map(productSet, element));
_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);
}
if (element.Comments != null)
{
foreach (var comment in element.Comments)
{
_dbContext.Comments.Remove(comment);
}
}
element.IsDeleted = true;
_dbContext.SaveChanges();
}
catch
{
_dbContext.ChangeTracker.Clear();
throw;
}
}
public ProductSetDataModel? GetElementById(string id)
{
try
{
var model = GetProductSetById(id);
return _mapper.Map<ProductSetDataModel>(model);
}
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))];
}
public List<SetWithProductsDataModel> GetListProductSetsByProducts(List<string> prodIds)
{
try
{
return _dbContext.ProductSets.Where(x => x.IsDeleted != true)
.Where(p => p.ComponentsInProductSet
.Any(cp => cp.Component.Products
.Any(cps => prodIds.Contains(cps.ProductId))))
.Select(p => new SetWithProductsDataModel()
{
Set = _mapper.Map<ProductSetDataModel>(p),
Products = p.ComponentsInProductSet
.Select(cp => cp.Component)
.SelectMany(c => c.Products)
.Where(cps => prodIds.Contains(cps.ProductId))
.Select(cps => cps.Product)
.Distinct()
.Select(x => _mapper.Map<ProductDataModel>(x)).ToList()
}).ToList();
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
private ProductSet? GetProductSetById(string id) => _dbContext.ProductSets.Include(x => x.ComponentsInProductSet).Include(x => x.Comments).FirstOrDefault(x => x.Id == id && x.IsDeleted != true);
}
}

View File

@@ -0,0 +1,166 @@
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>()
.ForMember(dest => dest.Components, opt => opt.MapFrom(src => src.ComponentsInProduct))
.ForMember(dest => dest.Purchases, opt => opt.MapFrom(src => src.ProductsInPurchace)); ;
cfg.CreateMap<ProductSet, ProductSetDataModel>();
});
_mapper = new Mapper(config);
}
public void AddElement(ProductDataModel product)
{
try
{
var prod = _mapper.Map<Product>(product);
_dbContext.Products.Add(prod);
_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
{
var prod = GetProductById(id);
return _mapper.Map<ProductDataModel>(prod);
}
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.Include(x => x.ComponentsInProduct).FirstOrDefault(x => x.Id == id);
public List<ProductWithSetsDataModel> GetListProductsByProductSet(List<string> setsIds)
{
try
{
return _dbContext.Products
.Where(p => p.ComponentsInProduct
.Any(cp => cp.Component.ProductSets
.Any(cps => setsIds.Contains(cps.ProductSetId))))
.Select(p => new ProductWithSetsDataModel()
{
Product = _mapper.Map<ProductDataModel>(p),
Sets = p.ComponentsInProduct
.Select(cp => cp.Component)
.SelectMany(c => c.ProductSets)
.Where(cps => setsIds.Contains(cps.ProductSetId))
.Select(cps => cps.ProductSet)
.Distinct()
.Select(x => _mapper.Map<ProductSetDataModel>(x)).ToList()
}).ToList();
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
}

View File

@@ -0,0 +1,224 @@
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>()
.ForMember(dest => dest.Products, opt => opt.MapFrom(src => src.ProductsInPurchase))
.ForMember(dest => dest.ProductSets, opt => opt.MapFrom(src => src.ProductSetsInPurchase));;
cfg.CreateMap<Component, ComponentDataModel>();
});
_mapper = new Mapper(config);
}
public void AddElement(PurchaseDataModel purchase)
{
try
{
var entity = _mapper.Map<Purchase>(purchase);
entity.TotalPrice = CalculateTotalPrice(entity);
if (entity.TotalPrice <= 0) throw new ValidationException("Total price must be greater than zero.");
_dbContext.Purchases.Add(entity);
_dbContext.SaveChanges();
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
public void UpdateElement(PurchaseDataModel purchase)
{
try
{
var oldPurchase = GetPurchaseById(purchase.Id) ?? throw new ElementNotFoundException(purchase.Id);
var newEntity = _mapper.Map(purchase, oldPurchase);
newEntity.TotalPrice = CalculateTotalPrice(newEntity);
if (newEntity.TotalPrice <= 0) throw new ValidationException("Total price must be greater than zero.");
_dbContext.Purchases.Update(newEntity);
_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.Include(x => x.ProductsInPurchase).Include(x => x.ProductSetsInPurchase).FirstOrDefault(p => p.Id == id);
}
private double CalculateTotalPrice(Purchase entity)
{
double total = 0;
// Products
if (entity.ProductsInPurchase != null && entity.ProductsInPurchase.Any())
{
var productIds = entity.ProductsInPurchase.Select(p => p.ProductId).ToList();
var productsFromDb = _dbContext.Products
.Where(p => productIds.Contains(p.Id))
.ToDictionary(p => p.Id, p => p.Price);
foreach (var product in entity.ProductsInPurchase)
{
if (productsFromDb.TryGetValue(product.ProductId, out var price))
{
total += price * product.Amount;
}
}
}
// ProductSets
if (entity.ProductSetsInPurchase != null && entity.ProductSetsInPurchase.Any())
{
var setIds = entity.ProductSetsInPurchase.Select(ps => ps.ProductSetId).ToList();
var setsFromDb = _dbContext.ProductSets
.Where(s => setIds.Contains(s.Id))
.ToDictionary(s => s.Id, s => s.TotalPrice);
foreach (var set in entity.ProductSetsInPurchase)
{
if (setsFromDb.TryGetValue(set.ProductSetId, out var price))
{
total += price;
}
}
}
return total;
}
/// <summary>
/// Метод для получения отчета по продажам с расшифровкой
/// по комплектующим и комментариям за период.
/// </summary>
/// <param name="start"></param>
/// <param name="finish"></param>
/// <returns></returns>
public List<PurchasesReportModel>? GetDataForReport(DateTime start, DateTime finish)
{
try
{
var report = _dbContext.Purchases
.Where(p => p.PurchaseDate >= start && p.PurchaseDate <= finish)
.Select(p => new PurchasesReportModel
{
Purchase = _mapper.Map<PurchaseDataModel>(p),
Components = p.ProductSetsInPurchase
.SelectMany(pps => pps.ProductSet.ComponentsInProductSet)
.Select(cps => cps.Component)
.Select(comp => _mapper.Map<ComponentDataModel>(comp))
.ToList(),
Comments = p.ProductSetsInPurchase
.SelectMany(pps => pps.ProductSet.Comments)
.Select(c => new CommentDataModel(c.Id, c.ProductSetId, c.UserId, c.Text, c.CommentDate))
.ToList()
})
.ToList();
return report;
}
catch (Exception ex)
{
_dbContext.ChangeTracker.Clear();
throw new StorageException(ex);
}
}
}
}

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,466 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using YAPDatabase;
#nullable disable
namespace YAPDatabase.Migrations
{
[DbContext(typeof(YAPDbContext))]
[Migration("20250826085148_InitMigration")]
partial class InitMigration
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.5")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("YAPDatabase.Models.Comment", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("CommentDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("ProductSetId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ProductSetId");
b.HasIndex("UserId");
b.ToTable("Comments");
});
modelBuilder.Entity("YAPDatabase.Models.Component", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("ComponentType")
.HasColumnType("integer");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false);
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Name", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("Components");
});
modelBuilder.Entity("YAPDatabase.Models.ComponentInProduct", b =>
{
b.Property<string>("ComponentId")
.HasColumnType("text");
b.Property<string>("ProductId")
.HasColumnType("text");
b.HasKey("ComponentId", "ProductId");
b.HasIndex("ProductId");
b.ToTable("ComponentsInProduct");
});
modelBuilder.Entity("YAPDatabase.Models.ComponentInProductSet", b =>
{
b.Property<string>("ComponentId")
.HasColumnType("text");
b.Property<string>("ProductSetId")
.HasColumnType("text");
b.Property<double>("Price")
.HasColumnType("double precision");
b.HasKey("ComponentId", "ProductSetId");
b.HasIndex("ProductSetId");
b.ToTable("ComponentsInProductSet");
});
modelBuilder.Entity("YAPDatabase.Models.Product", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false);
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<double>("Price")
.HasColumnType("double precision");
b.HasKey("Id");
b.HasIndex("Name", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("Products");
});
modelBuilder.Entity("YAPDatabase.Models.ProductInPurchase", b =>
{
b.Property<string>("ProductId")
.HasColumnType("text");
b.Property<string>("PurchaseId")
.HasColumnType("text");
b.Property<int>("Amount")
.HasColumnType("integer");
b.HasKey("ProductId", "PurchaseId");
b.HasIndex("PurchaseId");
b.ToTable("ProductsInPurchase");
});
modelBuilder.Entity("YAPDatabase.Models.ProductOrder", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("DealerName")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("OrderDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("ProductId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ProductId");
b.HasIndex("UserId");
b.ToTable("ProductOrders");
});
modelBuilder.Entity("YAPDatabase.Models.ProductSet", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false);
b.Property<string>("SetName")
.IsRequired()
.HasColumnType("text");
b.Property<double>("TotalPrice")
.HasColumnType("double precision");
b.HasKey("Id");
b.HasIndex("SetName", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("ProductSets");
});
modelBuilder.Entity("YAPDatabase.Models.ProductSetInPurchase", b =>
{
b.Property<string>("ProductSetId")
.HasColumnType("text");
b.Property<string>("PurchaseId")
.HasColumnType("text");
b.HasKey("ProductSetId", "PurchaseId");
b.HasIndex("PurchaseId");
b.ToTable("ProductSetsInPurchase");
});
modelBuilder.Entity("YAPDatabase.Models.Purchase", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("PurchaseDate")
.HasColumnType("timestamp with time zone");
b.Property<double>("TotalPrice")
.HasColumnType("double precision");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("Purchases");
});
modelBuilder.Entity("YAPDatabase.Models.User", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Login")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PasswordHash")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Role")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("Users");
b.HasDiscriminator<int>("Role");
b.UseTphMappingStrategy();
});
modelBuilder.Entity("YAPDatabase.Models.Storekeeper", b =>
{
b.HasBaseType("YAPDatabase.Models.User");
b.HasDiscriminator().HasValue(2);
});
modelBuilder.Entity("YAPDatabase.Models.Worker", b =>
{
b.HasBaseType("YAPDatabase.Models.User");
b.HasDiscriminator().HasValue(1);
});
modelBuilder.Entity("YAPDatabase.Models.Comment", b =>
{
b.HasOne("YAPDatabase.Models.ProductSet", "ProductSet")
.WithMany("Comments")
.HasForeignKey("ProductSetId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("YAPDatabase.Models.Worker", "User")
.WithMany("Comments")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ProductSet");
b.Navigation("User");
});
modelBuilder.Entity("YAPDatabase.Models.ComponentInProduct", b =>
{
b.HasOne("YAPDatabase.Models.Component", "Component")
.WithMany("Products")
.HasForeignKey("ComponentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("YAPDatabase.Models.Product", "Product")
.WithMany("ComponentsInProduct")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Component");
b.Navigation("Product");
});
modelBuilder.Entity("YAPDatabase.Models.ComponentInProductSet", b =>
{
b.HasOne("YAPDatabase.Models.Component", "Component")
.WithMany("ProductSets")
.HasForeignKey("ComponentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("YAPDatabase.Models.ProductSet", "ProductSet")
.WithMany("ComponentsInProductSet")
.HasForeignKey("ProductSetId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Component");
b.Navigation("ProductSet");
});
modelBuilder.Entity("YAPDatabase.Models.ProductInPurchase", b =>
{
b.HasOne("YAPDatabase.Models.Product", "Product")
.WithMany("ProductsInPurchace")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("YAPDatabase.Models.Purchase", "Purchase")
.WithMany("ProductsInPurchase")
.HasForeignKey("PurchaseId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
b.Navigation("Purchase");
});
modelBuilder.Entity("YAPDatabase.Models.ProductOrder", b =>
{
b.HasOne("YAPDatabase.Models.Product", "Product")
.WithMany("ProductOrders")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("YAPDatabase.Models.Storekeeper", "Storekeeper")
.WithMany("ProductOrders")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
b.Navigation("Storekeeper");
});
modelBuilder.Entity("YAPDatabase.Models.ProductSetInPurchase", b =>
{
b.HasOne("YAPDatabase.Models.ProductSet", "ProductSet")
.WithMany("ProductSetsInPurchase")
.HasForeignKey("ProductSetId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("YAPDatabase.Models.Purchase", "Purchase")
.WithMany("ProductSetsInPurchase")
.HasForeignKey("PurchaseId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ProductSet");
b.Navigation("Purchase");
});
modelBuilder.Entity("YAPDatabase.Models.Purchase", b =>
{
b.HasOne("YAPDatabase.Models.Worker", "User")
.WithMany("Purchases")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("YAPDatabase.Models.Component", b =>
{
b.Navigation("ProductSets");
b.Navigation("Products");
});
modelBuilder.Entity("YAPDatabase.Models.Product", b =>
{
b.Navigation("ComponentsInProduct");
b.Navigation("ProductOrders");
b.Navigation("ProductsInPurchace");
});
modelBuilder.Entity("YAPDatabase.Models.ProductSet", b =>
{
b.Navigation("Comments");
b.Navigation("ComponentsInProductSet");
b.Navigation("ProductSetsInPurchase");
});
modelBuilder.Entity("YAPDatabase.Models.Purchase", b =>
{
b.Navigation("ProductSetsInPurchase");
b.Navigation("ProductsInPurchase");
});
modelBuilder.Entity("YAPDatabase.Models.Storekeeper", b =>
{
b.Navigation("ProductOrders");
});
modelBuilder.Entity("YAPDatabase.Models.Worker", b =>
{
b.Navigation("Comments");
b.Navigation("Purchases");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,347 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace YAPDatabase.Migrations
{
/// <inheritdoc />
public partial class InitMigration : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Components",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
Name = table.Column<string>(type: "text", nullable: false),
ComponentType = table.Column<int>(type: "integer", nullable: false),
IsDeleted = table.Column<bool>(type: "boolean", nullable: false, defaultValue: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Components", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Products",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
Name = table.Column<string>(type: "text", nullable: false),
Price = table.Column<double>(type: "double precision", nullable: false),
IsDeleted = table.Column<bool>(type: "boolean", nullable: false, defaultValue: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Products", x => x.Id);
});
migrationBuilder.CreateTable(
name: "ProductSets",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
SetName = table.Column<string>(type: "text", nullable: false),
TotalPrice = table.Column<double>(type: "double precision", nullable: false),
IsDeleted = table.Column<bool>(type: "boolean", nullable: false, defaultValue: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ProductSets", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Users",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
Login = table.Column<string>(type: "text", nullable: false),
Email = table.Column<string>(type: "text", nullable: false),
PasswordHash = table.Column<string>(type: "text", nullable: false),
Role = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Users", x => x.Id);
});
migrationBuilder.CreateTable(
name: "ComponentsInProduct",
columns: table => new
{
ComponentId = table.Column<string>(type: "text", nullable: false),
ProductId = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ComponentsInProduct", x => new { x.ComponentId, x.ProductId });
table.ForeignKey(
name: "FK_ComponentsInProduct_Components_ComponentId",
column: x => x.ComponentId,
principalTable: "Components",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_ComponentsInProduct_Products_ProductId",
column: x => x.ProductId,
principalTable: "Products",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ComponentsInProductSet",
columns: table => new
{
ComponentId = table.Column<string>(type: "text", nullable: false),
ProductSetId = table.Column<string>(type: "text", nullable: false),
Price = table.Column<double>(type: "double precision", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ComponentsInProductSet", x => new { x.ComponentId, x.ProductSetId });
table.ForeignKey(
name: "FK_ComponentsInProductSet_Components_ComponentId",
column: x => x.ComponentId,
principalTable: "Components",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_ComponentsInProductSet_ProductSets_ProductSetId",
column: x => x.ProductSetId,
principalTable: "ProductSets",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Comments",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
ProductSetId = table.Column<string>(type: "text", nullable: false),
UserId = table.Column<string>(type: "text", nullable: false),
Text = table.Column<string>(type: "text", nullable: false),
CommentDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Comments", x => x.Id);
table.ForeignKey(
name: "FK_Comments_ProductSets_ProductSetId",
column: x => x.ProductSetId,
principalTable: "ProductSets",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Comments_Users_UserId",
column: x => x.UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ProductOrders",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
UserId = table.Column<string>(type: "text", nullable: false),
OrderDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
DealerName = table.Column<string>(type: "text", nullable: false),
ProductId = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ProductOrders", x => x.Id);
table.ForeignKey(
name: "FK_ProductOrders_Products_ProductId",
column: x => x.ProductId,
principalTable: "Products",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_ProductOrders_Users_UserId",
column: x => x.UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Purchases",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
UserId = table.Column<string>(type: "text", nullable: false),
TotalPrice = table.Column<double>(type: "double precision", nullable: false),
PurchaseDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Purchases", x => x.Id);
table.ForeignKey(
name: "FK_Purchases_Users_UserId",
column: x => x.UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ProductSetsInPurchase",
columns: table => new
{
ProductSetId = table.Column<string>(type: "text", nullable: false),
PurchaseId = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ProductSetsInPurchase", x => new { x.ProductSetId, x.PurchaseId });
table.ForeignKey(
name: "FK_ProductSetsInPurchase_ProductSets_ProductSetId",
column: x => x.ProductSetId,
principalTable: "ProductSets",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_ProductSetsInPurchase_Purchases_PurchaseId",
column: x => x.PurchaseId,
principalTable: "Purchases",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ProductsInPurchase",
columns: table => new
{
PurchaseId = table.Column<string>(type: "text", nullable: false),
ProductId = table.Column<string>(type: "text", nullable: false),
Amount = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ProductsInPurchase", x => new { x.ProductId, x.PurchaseId });
table.ForeignKey(
name: "FK_ProductsInPurchase_Products_ProductId",
column: x => x.ProductId,
principalTable: "Products",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_ProductsInPurchase_Purchases_PurchaseId",
column: x => x.PurchaseId,
principalTable: "Purchases",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Comments_ProductSetId",
table: "Comments",
column: "ProductSetId");
migrationBuilder.CreateIndex(
name: "IX_Comments_UserId",
table: "Comments",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_Components_Name_IsDeleted",
table: "Components",
columns: new[] { "Name", "IsDeleted" },
unique: true,
filter: "\"IsDeleted\" = FALSE");
migrationBuilder.CreateIndex(
name: "IX_ComponentsInProduct_ProductId",
table: "ComponentsInProduct",
column: "ProductId");
migrationBuilder.CreateIndex(
name: "IX_ComponentsInProductSet_ProductSetId",
table: "ComponentsInProductSet",
column: "ProductSetId");
migrationBuilder.CreateIndex(
name: "IX_ProductOrders_ProductId",
table: "ProductOrders",
column: "ProductId");
migrationBuilder.CreateIndex(
name: "IX_ProductOrders_UserId",
table: "ProductOrders",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_Products_Name_IsDeleted",
table: "Products",
columns: new[] { "Name", "IsDeleted" },
unique: true,
filter: "\"IsDeleted\" = FALSE");
migrationBuilder.CreateIndex(
name: "IX_ProductSets_SetName_IsDeleted",
table: "ProductSets",
columns: new[] { "SetName", "IsDeleted" },
unique: true,
filter: "\"IsDeleted\" = FALSE");
migrationBuilder.CreateIndex(
name: "IX_ProductSetsInPurchase_PurchaseId",
table: "ProductSetsInPurchase",
column: "PurchaseId");
migrationBuilder.CreateIndex(
name: "IX_ProductsInPurchase_PurchaseId",
table: "ProductsInPurchase",
column: "PurchaseId");
migrationBuilder.CreateIndex(
name: "IX_Purchases_UserId",
table: "Purchases",
column: "UserId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Comments");
migrationBuilder.DropTable(
name: "ComponentsInProduct");
migrationBuilder.DropTable(
name: "ComponentsInProductSet");
migrationBuilder.DropTable(
name: "ProductOrders");
migrationBuilder.DropTable(
name: "ProductSetsInPurchase");
migrationBuilder.DropTable(
name: "ProductsInPurchase");
migrationBuilder.DropTable(
name: "Components");
migrationBuilder.DropTable(
name: "ProductSets");
migrationBuilder.DropTable(
name: "Products");
migrationBuilder.DropTable(
name: "Purchases");
migrationBuilder.DropTable(
name: "Users");
}
}
}

View File

@@ -0,0 +1,463 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using YAPDatabase;
#nullable disable
namespace YAPDatabase.Migrations
{
[DbContext(typeof(YAPDbContext))]
partial class YAPDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.5")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("YAPDatabase.Models.Comment", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("CommentDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("ProductSetId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ProductSetId");
b.HasIndex("UserId");
b.ToTable("Comments", (string)null);
});
modelBuilder.Entity("YAPDatabase.Models.Component", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("ComponentType")
.HasColumnType("integer");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false);
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Name", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("Components", (string)null);
});
modelBuilder.Entity("YAPDatabase.Models.ComponentInProduct", b =>
{
b.Property<string>("ComponentId")
.HasColumnType("text");
b.Property<string>("ProductId")
.HasColumnType("text");
b.HasKey("ComponentId", "ProductId");
b.HasIndex("ProductId");
b.ToTable("ComponentsInProduct", (string)null);
});
modelBuilder.Entity("YAPDatabase.Models.ComponentInProductSet", b =>
{
b.Property<string>("ComponentId")
.HasColumnType("text");
b.Property<string>("ProductSetId")
.HasColumnType("text");
b.Property<double>("Price")
.HasColumnType("double precision");
b.HasKey("ComponentId", "ProductSetId");
b.HasIndex("ProductSetId");
b.ToTable("ComponentsInProductSet", (string)null);
});
modelBuilder.Entity("YAPDatabase.Models.Product", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false);
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<double>("Price")
.HasColumnType("double precision");
b.HasKey("Id");
b.HasIndex("Name", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("Products", (string)null);
});
modelBuilder.Entity("YAPDatabase.Models.ProductInPurchase", b =>
{
b.Property<string>("ProductId")
.HasColumnType("text");
b.Property<string>("PurchaseId")
.HasColumnType("text");
b.Property<int>("Amount")
.HasColumnType("integer");
b.HasKey("ProductId", "PurchaseId");
b.HasIndex("PurchaseId");
b.ToTable("ProductsInPurchase", (string)null);
});
modelBuilder.Entity("YAPDatabase.Models.ProductOrder", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("DealerName")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("OrderDate")
.HasColumnType("timestamp with time zone");
b.Property<string>("ProductId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ProductId");
b.HasIndex("UserId");
b.ToTable("ProductOrders", (string)null);
});
modelBuilder.Entity("YAPDatabase.Models.ProductSet", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false);
b.Property<string>("SetName")
.IsRequired()
.HasColumnType("text");
b.Property<double>("TotalPrice")
.HasColumnType("double precision");
b.HasKey("Id");
b.HasIndex("SetName", "IsDeleted")
.IsUnique()
.HasFilter("\"IsDeleted\" = FALSE");
b.ToTable("ProductSets", (string)null);
});
modelBuilder.Entity("YAPDatabase.Models.ProductSetInPurchase", b =>
{
b.Property<string>("ProductSetId")
.HasColumnType("text");
b.Property<string>("PurchaseId")
.HasColumnType("text");
b.HasKey("ProductSetId", "PurchaseId");
b.HasIndex("PurchaseId");
b.ToTable("ProductSetsInPurchase", (string)null);
});
modelBuilder.Entity("YAPDatabase.Models.Purchase", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("PurchaseDate")
.HasColumnType("timestamp with time zone");
b.Property<double>("TotalPrice")
.HasColumnType("double precision");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("Purchases", (string)null);
});
modelBuilder.Entity("YAPDatabase.Models.User", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Login")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PasswordHash")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Role")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("Users", (string)null);
b.HasDiscriminator<int>("Role");
b.UseTphMappingStrategy();
});
modelBuilder.Entity("YAPDatabase.Models.Storekeeper", b =>
{
b.HasBaseType("YAPDatabase.Models.User");
b.HasDiscriminator().HasValue(2);
});
modelBuilder.Entity("YAPDatabase.Models.Worker", b =>
{
b.HasBaseType("YAPDatabase.Models.User");
b.HasDiscriminator().HasValue(1);
});
modelBuilder.Entity("YAPDatabase.Models.Comment", b =>
{
b.HasOne("YAPDatabase.Models.ProductSet", "ProductSet")
.WithMany("Comments")
.HasForeignKey("ProductSetId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("YAPDatabase.Models.Worker", "User")
.WithMany("Comments")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ProductSet");
b.Navigation("User");
});
modelBuilder.Entity("YAPDatabase.Models.ComponentInProduct", b =>
{
b.HasOne("YAPDatabase.Models.Component", "Component")
.WithMany("Products")
.HasForeignKey("ComponentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("YAPDatabase.Models.Product", "Product")
.WithMany("ComponentsInProduct")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Component");
b.Navigation("Product");
});
modelBuilder.Entity("YAPDatabase.Models.ComponentInProductSet", b =>
{
b.HasOne("YAPDatabase.Models.Component", "Component")
.WithMany("ProductSets")
.HasForeignKey("ComponentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("YAPDatabase.Models.ProductSet", "ProductSet")
.WithMany("ComponentsInProductSet")
.HasForeignKey("ProductSetId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Component");
b.Navigation("ProductSet");
});
modelBuilder.Entity("YAPDatabase.Models.ProductInPurchase", b =>
{
b.HasOne("YAPDatabase.Models.Product", "Product")
.WithMany("ProductsInPurchace")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("YAPDatabase.Models.Purchase", "Purchase")
.WithMany("ProductsInPurchase")
.HasForeignKey("PurchaseId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
b.Navigation("Purchase");
});
modelBuilder.Entity("YAPDatabase.Models.ProductOrder", b =>
{
b.HasOne("YAPDatabase.Models.Product", "Product")
.WithMany("ProductOrders")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("YAPDatabase.Models.Storekeeper", "Storekeeper")
.WithMany("ProductOrders")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
b.Navigation("Storekeeper");
});
modelBuilder.Entity("YAPDatabase.Models.ProductSetInPurchase", b =>
{
b.HasOne("YAPDatabase.Models.ProductSet", "ProductSet")
.WithMany("ProductSetsInPurchase")
.HasForeignKey("ProductSetId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("YAPDatabase.Models.Purchase", "Purchase")
.WithMany("ProductSetsInPurchase")
.HasForeignKey("PurchaseId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ProductSet");
b.Navigation("Purchase");
});
modelBuilder.Entity("YAPDatabase.Models.Purchase", b =>
{
b.HasOne("YAPDatabase.Models.Worker", "User")
.WithMany("Purchases")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("YAPDatabase.Models.Component", b =>
{
b.Navigation("ProductSets");
b.Navigation("Products");
});
modelBuilder.Entity("YAPDatabase.Models.Product", b =>
{
b.Navigation("ComponentsInProduct");
b.Navigation("ProductOrders");
b.Navigation("ProductsInPurchace");
});
modelBuilder.Entity("YAPDatabase.Models.ProductSet", b =>
{
b.Navigation("Comments");
b.Navigation("ComponentsInProductSet");
b.Navigation("ProductSetsInPurchase");
});
modelBuilder.Entity("YAPDatabase.Models.Purchase", b =>
{
b.Navigation("ProductSetsInPurchase");
b.Navigation("ProductsInPurchase");
});
modelBuilder.Entity("YAPDatabase.Models.Storekeeper", b =>
{
b.Navigation("ProductOrders");
});
modelBuilder.Entity("YAPDatabase.Models.Worker", b =>
{
b.Navigation("Comments");
b.Navigation("Purchases");
});
#pragma warning restore 612, 618
}
}
}

Some files were not shown because too many files have changed in this diff Show More