Files
PIBD-23_Coursach_YouAreProg…/YouAreProgrammerShop/YAPDatabase/Implementations/PurchaseStorageContract.cs
strwbrry1 ee51e4d1f6 Purchase CRD done, all entities done
Field verifications, reports, email left
2025-09-14 01:07:07 +04:00

225 lines
8.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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);
}
}
}
}