using CMSMicroservice.Domain.Enums; using CMSMicroservice.Domain.Events; using CMSMicroservice.Domain.Entities.Order; using Microsoft.Extensions.Logging; namespace CMSMicroservice.Application.UserOrderCQ.Commands.SubmitShopBuyOrder; public class SubmitShopBuyOrderCommandHandler : IRequestHandler { private readonly IApplicationDbContext _context; private readonly ILogger _logger; public SubmitShopBuyOrderCommandHandler( IApplicationDbContext context, ILogger logger) { _context = context; _logger = logger; } public async Task Handle(SubmitShopBuyOrderCommand request, CancellationToken cancellationToken) { var user = await _context.Users .Include(i => i.UserAddresses) .Include(i => i.UserWallets) .ThenInclude(i => i.UserWalletChangeLogs) .Include(i => i.UserCarts) .ThenInclude(i => i.Product) .FirstOrDefaultAsync(w => w.Id == request.UserId, cancellationToken: cancellationToken); if (user.UserCarts.Count == 0) throw new NotFoundException("UserCart", request.UserId); if (user.UserCarts.Sum(s => s.Count * s.Product.Price) != request.TotalAmount) throw new Exception("مبلغ سفارش با مجموع سبد خرید مطابقت ندارد."); var userWallet = user.UserWallets.FirstOrDefault(); if (userWallet == null) throw new Exception("کیف پول کاربر یافت نشد."); if (userWallet.Balance<=0 || userWallet.Balance f.IsDefault).Id, TransactionId = newTransaction.Id, // سفارش فروشگاهی فیزیکی است، پس در ابتدا در انتظار ارسال است DeliveryStatus = DeliveryStatus.Pending }; await _context.UserOrders.AddAsync(newOrder, cancellationToken); await _context.SaveChangesAsync(cancellationToken); // محاسبه و ثبت VAT (اگر فعال باشد) var vatCreated = await CalculateAndSaveVAT(newOrder.Id, request.TotalAmount, cancellationToken); if (vatCreated) { newOrder.HasVAT = true; await _context.SaveChangesAsync(cancellationToken); } var factorDetailsList = user.UserCarts.Select(s => new FactorDetails() { ProductId = s.ProductId, Count = s.Count, UnitPrice = s.Product.Price, OrderId = newOrder.Id }); await _context.FactorDetails.AddRangeAsync(factorDetailsList, cancellationToken); user.UserCarts.Clear(); await _context.SaveChangesAsync(cancellationToken); var finalResult = new SubmitShopBuyOrderResponseDto() { Id = newOrder.Id, }; return finalResult; } private async Task CalculateAndSaveVAT(long orderId, long orderAmount, CancellationToken cancellationToken) { try { // بررسی فعال بودن VAT var vatEnabledConfig = await _context.SystemConfigurations .FirstOrDefaultAsync(x => x.Scope == ConfigurationScope.VAT && x.Key == "IsEnabled", cancellationToken); if (vatEnabledConfig == null || !bool.TryParse(vatEnabledConfig.Value, out var isEnabled) || !isEnabled) { _logger.LogInformation("VAT is disabled. Skipping VAT calculation for order {OrderId}", orderId); return false; } // دریافت نرخ VAT var vatRateConfig = await _context.SystemConfigurations .FirstOrDefaultAsync(x => x.Scope == ConfigurationScope.VAT && x.Key == "Rate", cancellationToken); if (vatRateConfig == null || !decimal.TryParse(vatRateConfig.Value, out var vatRate)) { _logger.LogWarning("VAT Rate configuration not found or invalid. Using default 0.09"); vatRate = 0.09m; } // محاسبه مالیات var vatAmount = (long)(orderAmount * vatRate); var totalAmount = orderAmount + vatAmount; // ثبت VAT var orderVAT = new OrderVAT { OrderId = orderId, VATRate = vatRate, BaseAmount = orderAmount, VATAmount = vatAmount, TotalAmount = totalAmount, IsPaid = true, PaidAt = DateTime.Now }; await _context.OrderVATs.AddAsync(orderVAT, cancellationToken); await _context.SaveChangesAsync(cancellationToken); _logger.LogInformation( "VAT calculated and saved for order {OrderId}. Rate: {Rate}%, Base: {Base}, VAT: {VAT}, Total: {Total}", orderId, vatRate * 100, orderAmount, vatAmount, totalAmount ); return true; } catch (Exception ex) { _logger.LogError(ex, "Error calculating VAT for order {OrderId}", orderId); // عدم محاسبه VAT نباید مانع ثبت سفارش شود return false; } } }