using CMSMicroservice.Application.Common.Interfaces; using CMSMicroservice.Application.Common.Services; using CMSMicroservice.Domain.Entities.DiscountShop; using CMSMicroservice.Domain.Entities.Payment; using CMSMicroservice.Domain.Enums; using MediatR; using Microsoft.EntityFrameworkCore; namespace CMSMicroservice.Application.DiscountShopCQ.Commands.PlaceOrder; public class PlaceOrderCommandHandler : IRequestHandler { private readonly IApplicationDbContext _context; private readonly IInventoryService _inventoryService; public PlaceOrderCommandHandler( IApplicationDbContext context, IInventoryService inventoryService) { _context = context; _inventoryService = inventoryService; } public async Task Handle(PlaceOrderCommand request, CancellationToken cancellationToken) { // Get user wallet var userWallet = await _context.UserWallets .FirstOrDefaultAsync(w => w.UserId == request.UserId, cancellationToken); if (userWallet == null) { return new PlaceOrderResponseDto { Success = false, Message = "کیف پول کاربر یافت نشد" }; } // Get cart items with products var cartItems = await _context.DiscountShoppingCarts .Where(c => c.UserId == request.UserId) .Include(c => c.Product) .ToListAsync(cancellationToken); if (!cartItems.Any()) { return new PlaceOrderResponseDto { Success = false, Message = "سبد خرید خالی است" }; } // Validate stock and calculate totals long totalAmount = 0; long totalDiscountAmount = 0; var orderDetails = new List(); foreach (var cartItem in cartItems) { var product = cartItem.Product; // Check stock if (product.RemainingCount < cartItem.Count) { return new PlaceOrderResponseDto { Success = false, Message = $"موجودی محصول '{product.Title}' کافی نیست" }; } // Check if product is active if (!product.IsActive) { return new PlaceOrderResponseDto { Success = false, Message = $"محصول '{product.Title}' غیرفعال است" }; } // Calculate discount for this product var itemTotal = product.Price * cartItem.Count; var maxDiscountForItem = (itemTotal * product.MaxDiscountPercent) / 100; totalAmount += itemTotal; totalDiscountAmount += maxDiscountForItem; orderDetails.Add(new DiscountOrderDetail { ProductId = product.Id, Count = cartItem.Count, UnitPrice = product.Price, DiscountPercentUsed = product.MaxDiscountPercent, DiscountAmount = maxDiscountForItem, FinalPrice = itemTotal - maxDiscountForItem }); } // Validate discount balance usage var maxDiscountBalanceUsable = totalDiscountAmount; var actualDiscountBalanceUsed = Math.Min(request.DiscountBalanceToUse, maxDiscountBalanceUsable); actualDiscountBalanceUsed = Math.Min(actualDiscountBalanceUsed, userWallet.DiscountBalance); if (actualDiscountBalanceUsed < request.DiscountBalanceToUse) { return new PlaceOrderResponseDto { Success = false, Message = $"موجودی تخفیف کافی نیست. حداکثر قابل استفاده: {maxDiscountBalanceUsable:N0} تومان، موجودی شما: {userWallet.DiscountBalance:N0} تومان" }; } var gatewayAmountRequired = totalAmount - actualDiscountBalanceUsed; // Calculate VAT using centralized calculator var vatBreakdown = VatCalculator.CalculateBreakdown(gatewayAmountRequired); var vatAmount = vatBreakdown.VatAmount; var finalGatewayAmount = vatBreakdown.GrossAmount; // Create transaction for gateway payment var transaction = new Transaction { Amount = finalGatewayAmount, Description = $"خرید از فروشگاه تخفیف - مبلغ کل: {totalAmount:N0}، اعتبار تخفیف: {actualDiscountBalanceUsed:N0}", PaymentStatus = PaymentStatus.Pending, Type = TransactionType.DiscountShopPurchase }; _context.Transactions.Add(transaction); await _context.SaveChangesAsync(cancellationToken); // Create order var order = new DiscountOrder { UserId = request.UserId, TotalAmount = totalAmount, DiscountBalanceUsed = actualDiscountBalanceUsed, GatewayAmountPaid = finalGatewayAmount, VatAmount = vatAmount, PaymentStatus = PaymentStatus.Pending, TransactionId = transaction.Id, UserAddressId = request.UserAddressId, DeliveryStatus = DeliveryStatus.Pending }; _context.DiscountOrders.Add(order); await _context.SaveChangesAsync(cancellationToken); // Add order details foreach (var detail in orderDetails) { detail.DiscountOrderId = order.Id; } _context.DiscountOrderDetails.AddRange(orderDetails); // رزرو موجودی برای سفارش pending foreach (var cartItem in cartItems) { await _inventoryService.ReserveStockAsync( cartItem.ProductId, ProductType.DiscountProduct, cartItem.Count, order.Id, cancellationToken); } // Clear cart _context.DiscountShoppingCarts.RemoveRange(cartItems); await _context.SaveChangesAsync(cancellationToken); return new PlaceOrderResponseDto { Success = true, Message = "سفارش ایجاد شد. لطفا پرداخت را تکمیل کنید", OrderId = order.Id, TransactionId = transaction.Id, TotalAmount = totalAmount, DiscountBalanceUsed = actualDiscountBalanceUsed, GatewayAmountRequired = finalGatewayAmount }; } }