using Netina.Domain.Entities.ProductCategories; namespace Netina.Core.EntityServices.DiscountHandlers; public class CalculateOrderDiscountCommandHandler( IRepositoryWrapper repositoryWrapper, ICurrentUserService currentUserService) : IRequestHandler { 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 (discount.IsForFirstPurchase) { if (currentUserService.UserId != null && Guid.TryParse(currentUserService.UserId, out Guid firstPurchaseUserId)) { var customer = await repositoryWrapper.SetRepository() .TableNoTracking .FirstOrDefaultAsync(c => c.UserId == firstPurchaseUserId, cancellationToken); if (customer == null) throw new BaseApiException(ApiResultStatusCode.NotFound, "Customer not found"); var userOrderCount = await repositoryWrapper.SetRepository() .TableNoTracking .CountAsync(f => f.CustomerId == customer.Id && 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()) { var subCats = await repositoryWrapper.SetRepository().TableNoTracking .Where(c => c.ParentId == categoryDiscount.CategoryId) .Select(c => c.Id) .ToListAsync(cancellationToken); subCats.Add(categoryDiscount.CategoryId); totalPrice = request.Order.OrderProducts.Where(op => subCats.Contains(op.ProductCategoryId)).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; } }