namespace NetinaShop.Core.EntityServices.DiscountHandlers; public class CalculateDiscountCommandHandler : IRequestHandler { private readonly IRepositoryWrapper _repositoryWrapper; public CalculateDiscountCommandHandler(IRepositoryWrapper repositoryWrapper) { _repositoryWrapper = repositoryWrapper; } public async Task Handle(CalculateDiscountCommand request, CancellationToken cancellationToken) { if (request.Order == null) throw new AppException("Order is null", ApiResultStatusCode.BadRequest); var discount = await _repositoryWrapper.SetRepository() .TableNoTracking .FirstOrDefaultAsync(d => d.Code == request.DiscountCode, cancellationToken); if (discount == null) throw new AppException("Discount not found", ApiResultStatusCode.NotFound); double discountPrice = 0; foreach (var orderProductGrouped in request.Order.OrderProducts.GroupBy(o=>o.ProductCategoryId)) { var categoryDiscount = await _repositoryWrapper.SetRepository() .TableNoTracking .FirstOrDefaultAsync(d => d.CategoryId == orderProductGrouped.Key && d.HasCode == false && d.ExpireDate.Date > DateTime.Today.Date , cancellationToken); if (categoryDiscount != null && !categoryDiscount.IsExpired()) { var totalPrice = request.Order.OrderProducts.Where(op => op.ProductCategoryId == categoryDiscount.CategoryId) .Sum(op => op.ProductCost); discountPrice = categoryDiscount.AmountType == DiscountAmountType.Amount ? totalPrice - categoryDiscount.DiscountAmount : totalPrice - ((totalPrice / 100) * categoryDiscount.DiscountAmount); } foreach (var orderProduct in orderProductGrouped) { var productDiscount = await _repositoryWrapper.SetRepository() .TableNoTracking .FirstOrDefaultAsync(d => d.HasCode == false && d.ProductId == orderProduct.ProductId && d.ExpireDate.Date > DateTime.Today.Date, cancellationToken); if (productDiscount != null && !productDiscount.IsExpired()) { var totalPrice = request.Order.OrderProducts.Where(op => op.ProductId == productDiscount.ProductId).Sum(op => op.ProductCost); discountPrice = productDiscount.AmountType == DiscountAmountType.Amount ? totalPrice - productDiscount.DiscountAmount : totalPrice - ((totalPrice / 100) * productDiscount.DiscountAmount); } } } if (discount.Type == DiscountType.All) { if (!discount.IsExpired()) { var totalPrice = request.Order.OrderProducts.Sum(op => op.ProductCost); discountPrice = discount.AmountType == DiscountAmountType.Amount ? totalPrice - discount.DiscountAmount : totalPrice - ((totalPrice / 100) * discount.DiscountAmount); } } else if (discount.Type == DiscountType.Category) { var categoryDiscount = await _repositoryWrapper.SetRepository() .TableNoTracking .FirstOrDefaultAsync(d => d.Code == request.DiscountCode, cancellationToken); if ( categoryDiscount!=null && !categoryDiscount.IsExpired()) { var totalPrice = request.Order.OrderProducts.Where(op => op.ProductCategoryId == categoryDiscount.CategoryId).Sum(op => op.ProductCost); discountPrice = discount.AmountType == DiscountAmountType.Amount ? totalPrice - discount.DiscountAmount : totalPrice - ((totalPrice / 100) * discount.DiscountAmount); } } else if (discount.Type == DiscountType.Product) { var productDiscount = await _repositoryWrapper.SetRepository() .TableNoTracking .FirstOrDefaultAsync(d => d.Code == request.DiscountCode, cancellationToken); if (productDiscount != null && !productDiscount.IsExpired()) { var totalPrice = request.Order.OrderProducts.Where(op => op.ProductId == productDiscount!.ProductId).Sum(op => op.ProductCost); discountPrice = discount.AmountType == DiscountAmountType.Amount ? totalPrice - discount.DiscountAmount : totalPrice - ((totalPrice / 100) * discount.DiscountAmount); } } else if (discount.Type == DiscountType.Subscriber) { throw new NotImplementedException("Subscribe discount not implemented"); } return discountPrice; } }