Files
CMS/src/CMSMicroservice.Application/UserOrderCQ/Commands/SubmitShopBuyOrder/SubmitShopBuyOrderCommandHandler.cs

175 lines
6.9 KiB
C#
Raw Normal View History

2025-11-24 22:55:14 +03:30
using CMSMicroservice.Domain.Enums;
using CMSMicroservice.Domain.Events;
using CMSMicroservice.Domain.Entities.Order;
using Microsoft.Extensions.Logging;
2025-11-24 22:55:14 +03:30
namespace CMSMicroservice.Application.UserOrderCQ.Commands.SubmitShopBuyOrder;
2025-11-24 22:55:14 +03:30
public class
SubmitShopBuyOrderCommandHandler : IRequestHandler<SubmitShopBuyOrderCommand, SubmitShopBuyOrderResponseDto>
{
private readonly IApplicationDbContext _context;
private readonly ILogger<SubmitShopBuyOrderCommandHandler> _logger;
public SubmitShopBuyOrderCommandHandler(
IApplicationDbContext context,
ILogger<SubmitShopBuyOrderCommandHandler> logger)
{
_context = context;
_logger = logger;
}
2025-11-24 22:55:14 +03:30
public async Task<SubmitShopBuyOrderResponseDto> Handle(SubmitShopBuyOrderCommand request,
CancellationToken cancellationToken)
{
2025-11-24 22:55:14 +03:30
var user = await _context.Users
.Include(i => i.UserAddresses)
2025-11-25 00:39:31 +03:30
.Include(i => i.UserWallets)
.ThenInclude(i => i.UserWalletChangeLogs)
.Include(i => i.UserCarts)
2025-11-24 22:55:14 +03:30
.ThenInclude(i => i.Product)
.FirstOrDefaultAsync(w => w.Id == request.UserId, cancellationToken: cancellationToken);
if (user.UserCarts.Count == 0)
2025-11-24 22:55:14 +03:30
throw new NotFoundException("UserCart", request.UserId);
2025-11-25 00:39:31 +03:30
if (user.UserCarts.Sum(s => s.Count * s.Product.Price) != request.TotalAmount)
2025-11-24 22:55:14 +03:30
throw new Exception("مبلغ سفارش با مجموع سبد خرید مطابقت ندارد.");
2025-11-25 00:39:31 +03:30
var userWallet = user.UserWallets.FirstOrDefault();
if (userWallet == null)
throw new Exception("کیف پول کاربر یافت نشد.");
2025-11-25 01:58:45 +03:30
if (userWallet.Balance<=0 || userWallet.Balance<request.TotalAmount)
throw new Exception("موجودی کیف پول کاربر برای انجام این تراکنش کافی نیست.");
2025-11-25 00:39:31 +03:30
var newTransaction = new Transaction()
2025-11-25 00:39:31 +03:30
{
Amount = request.TotalAmount,
Description = "خرید از فروشگاه",
PaymentStatus = PaymentStatus.Success,
PaymentDate = DateTime.Now,
Type = TransactionType.Buy,
RefId = "localwallet-" + Guid.NewGuid().ToString()
};
await _context.Transactions.AddAsync(newTransaction, cancellationToken);
2025-11-25 00:39:31 +03:30
await _context.SaveChangesAsync(cancellationToken);
var newWalletLog = new UserWalletChangeLog()
{
CurrentBalance = userWallet.Balance,
2025-11-25 03:56:45 +03:30
CurrentNetworkBalance = userWallet.NetworkBalance,
WalletId = userWallet.Id,
2025-11-25 00:39:31 +03:30
ChangeValue = -1*request.TotalAmount,
IsIncrease = false,
2025-11-25 03:56:45 +03:30
RefrenceId = newTransaction.Id,
2025-11-25 00:39:31 +03:30
};
userWallet.Balance -= request.TotalAmount;
await _context.UserWalletChangeLogs.AddAsync(newWalletLog, cancellationToken);
await _context.SaveChangesAsync(cancellationToken);
var newOrder = new UserOrder()
2025-11-24 22:55:14 +03:30
{
2025-11-25 00:39:31 +03:30
Amount = request.TotalAmount,
2025-11-24 22:55:14 +03:30
PaymentStatus = PaymentStatus.Success,
PaymentMethod = PaymentMethod.Wallet,
2025-11-25 00:39:31 +03:30
PaymentDate = DateTime.Now,
2025-11-24 22:55:14 +03:30
UserId = request.UserId,
UserAddressId = user.UserAddresses.First(f => f.IsDefault).Id,
TransactionId = newTransaction.Id,
// سفارش فروشگاهی فیزیکی است، پس در ابتدا در انتظار ارسال است
DeliveryStatus = DeliveryStatus.Pending
2025-11-25 00:39:31 +03:30
};
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()
2025-11-24 22:55:14 +03:30
{
ProductId = s.ProductId,
Count = s.Count,
UnitPrice = s.Product.Price,
2025-11-25 00:39:31 +03:30
OrderId = newOrder.Id
2025-11-25 01:58:45 +03:30
});
await _context.FactorDetails.AddRangeAsync(factorDetailsList, cancellationToken);
user.UserCarts.Clear();
2025-11-25 04:59:50 +03:30
await _context.SaveChangesAsync(cancellationToken);
2025-11-25 01:58:45 +03:30
var finalResult = new SubmitShopBuyOrderResponseDto()
2025-11-25 00:39:31 +03:30
{
Id = newOrder.Id,
2025-11-25 04:59:50 +03:30
2025-11-25 00:39:31 +03:30
};
2025-11-25 01:58:45 +03:30
return finalResult;
}
private async Task<bool> 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.UtcNow
};
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;
}
}
}