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

175 lines
6.9 KiB
C#

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<SubmitShopBuyOrderCommand, SubmitShopBuyOrderResponseDto>
{
private readonly IApplicationDbContext _context;
private readonly ILogger<SubmitShopBuyOrderCommandHandler> _logger;
public SubmitShopBuyOrderCommandHandler(
IApplicationDbContext context,
ILogger<SubmitShopBuyOrderCommandHandler> logger)
{
_context = context;
_logger = logger;
}
public async Task<SubmitShopBuyOrderResponseDto> 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<request.TotalAmount)
throw new Exception("موجودی کیف پول کاربر برای انجام این تراکنش کافی نیست.");
var newTransaction = new Transaction()
{
Amount = request.TotalAmount,
Description = "خرید از فروشگاه",
PaymentStatus = PaymentStatus.Success,
PaymentDate = DateTime.Now,
Type = TransactionType.Buy,
RefId = "localwallet-" + Guid.NewGuid().ToString()
};
await _context.Transactions.AddAsync(newTransaction, cancellationToken);
await _context.SaveChangesAsync(cancellationToken);
var newWalletLog = new UserWalletChangeLog()
{
CurrentBalance = userWallet.Balance,
CurrentNetworkBalance = userWallet.NetworkBalance,
WalletId = userWallet.Id,
ChangeValue = -1*request.TotalAmount,
IsIncrease = false,
RefrenceId = newTransaction.Id,
};
userWallet.Balance -= request.TotalAmount;
await _context.UserWalletChangeLogs.AddAsync(newWalletLog, cancellationToken);
await _context.SaveChangesAsync(cancellationToken);
var newOrder = new UserOrder()
{
Amount = request.TotalAmount,
PaymentStatus = PaymentStatus.Success,
PaymentMethod = PaymentMethod.Wallet,
PaymentDate = DateTime.Now,
UserId = request.UserId,
UserAddressId = user.UserAddresses.First(f => 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<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.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;
}
}
}