namespace Netina.Core.EntityServices.DiscountHandlers; public class CalculateOrderDiscountCommandHandler : IRequestHandler { private readonly IRepositoryWrapper _repositoryWrapper; private readonly ICurrentUserService _currentUserService; public CalculateOrderDiscountCommandHandler(IRepositoryWrapper repositoryWrapper,ICurrentUserService currentUserService) { _repositoryWrapper = repositoryWrapper; _currentUserService = currentUserService; } public async Task Handle(CalculateOrderDiscountCommand 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("تخفیف وجود منقضی شده است یا وجود ندارد", ApiResultStatusCode.NotFound); if (_currentUserService.UserId != null && Guid.TryParse(_currentUserService.UserId, out Guid userId)) { var discountedUserOrder = await _repositoryWrapper.SetRepository() .TableNoTracking .FirstOrDefaultAsync(f => f.CustomerId == userId && f.DiscountCode == discount.Code, cancellationToken); if (discountedUserOrder != null) throw new AppException("شما یک بار از این کد تخفیف استفاده کرده اید", ApiResultStatusCode.BadRequest); } if (discount.IsForFirstPurchase) { if (_currentUserService.UserId != null && Guid.TryParse(_currentUserService.UserId, out Guid firstPurchaseUserId)) { var userOrderCount = await _repositoryWrapper.SetRepository() .TableNoTracking .CountAsync(f => f.CustomerId == firstPurchaseUserId && f.DiscountCode == discount.Code, cancellationToken); if (userOrderCount > 0) throw new AppException("شما قبلا خریدی داشته اید و نمیتوانید از تخفیف اولین خرید استفاده کنید", ApiResultStatusCode.BadRequest); } } double discountPrice = 0; double totalPrice = 0; if (discount.Type == DiscountType.All) { if (!discount.IsExpired()) { totalPrice = request.Order.OrderProducts.Sum(op => op.ProductCost); } } else if (discount.Type == DiscountType.Category) { var categoryDiscount = await _repositoryWrapper.SetRepository() .TableNoTracking .FirstOrDefaultAsync(d => d.Code == request.DiscountCode, cancellationToken); if ( categoryDiscount!=null && !categoryDiscount.IsExpired()) { totalPrice = request.Order.OrderProducts.Where(op => op.ProductCategoryId == categoryDiscount.CategoryId).Sum(op => op.ProductCost); } } else if (discount.Type == DiscountType.Product) { var productDiscount = await _repositoryWrapper.SetRepository() .TableNoTracking .FirstOrDefaultAsync(d => d.Code == request.DiscountCode, cancellationToken); if (productDiscount != null && !productDiscount.IsExpired()) { totalPrice = request.Order.OrderProducts.Where(op => op.ProductId == productDiscount!.ProductId).Sum(op => op.ProductCost); } } else if (discount.Type == DiscountType.Subscriber) { throw new NotImplementedException("Subscribe discount not implemented"); } discountPrice = discount.AmountType == DiscountAmountType.Amount ? discount.DiscountAmount : ((totalPrice / 100) * discount.DiscountPercent); return discountPrice; } }