170 lines
6.7 KiB
C#
170 lines
6.7 KiB
C#
using CMSMicroservice.Application.Common.Exceptions;
|
|
using CMSMicroservice.Application.Common.Interfaces;
|
|
using CMSMicroservice.Domain.Entities;
|
|
using CMSMicroservice.Domain.Enums;
|
|
using CMSMicroservice.Domain.Common;
|
|
using MediatR;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Logging;
|
|
using ValidationException = FluentValidation.ValidationException;
|
|
|
|
namespace CMSMicroservice.Application.PackageCQ.Commands.InitiateBasePackagePayment;
|
|
|
|
/// <summary>
|
|
/// Handler برای ثبت اولیه تراکنش و سفارش پکیج پایه
|
|
/// این Handler فقط Transaction و Order را با وضعیت Pending ایجاد میکند
|
|
/// BFF سپس کاربر را به درگاه PYMS هدایت میکند
|
|
/// </summary>
|
|
public class InitiateBasePackagePaymentCommandHandler : IRequestHandler<InitiateBasePackagePaymentCommand, InitiateBasePackagePaymentResponseDto>
|
|
{
|
|
private readonly IApplicationDbContext _context;
|
|
private readonly ILogger<InitiateBasePackagePaymentCommandHandler> _logger;
|
|
|
|
/// <summary>
|
|
/// شناسه پکیج پایه در دیتابیس
|
|
/// </summary>
|
|
private const long BasePackageId = 4;
|
|
|
|
public InitiateBasePackagePaymentCommandHandler(
|
|
IApplicationDbContext context,
|
|
ILogger<InitiateBasePackagePaymentCommandHandler> logger)
|
|
{
|
|
_context = context;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<InitiateBasePackagePaymentResponseDto> Handle(
|
|
InitiateBasePackagePaymentCommand request,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
_logger.LogInformation(
|
|
"Initiating base package payment for UserId: {UserId}",
|
|
request.UserId);
|
|
|
|
// 1. پیدا کردن کاربر
|
|
var user = await _context.Users
|
|
.FirstOrDefaultAsync(u => u.Id == request.UserId, cancellationToken);
|
|
|
|
if (user == null)
|
|
{
|
|
_logger.LogWarning("User not found. UserId: {UserId}", request.UserId);
|
|
throw new NotFoundException(nameof(User), request.UserId);
|
|
}
|
|
|
|
// 2. بررسی عدم خرید قبلی پکیج پایه
|
|
if (user.PackagePurchaseMethod != PackagePurchaseMethod.None)
|
|
{
|
|
_logger.LogWarning(
|
|
"User {UserId} has already purchased base package via {Method}",
|
|
request.UserId,
|
|
user.PackagePurchaseMethod);
|
|
|
|
return new InitiateBasePackagePaymentResponseDto
|
|
{
|
|
Success = false,
|
|
Message = "شما قبلاً پکیج پایه را خریداری کردهاید."
|
|
};
|
|
}
|
|
|
|
// 3. بررسی عدم وجود سفارش Pending
|
|
var pendingOrder = await _context.UserOrders
|
|
.FirstOrDefaultAsync(o =>
|
|
o.UserId == request.UserId &&
|
|
o.PaymentStatus == PaymentStatus.Pending &&
|
|
o.PackageId == BasePackageId,
|
|
cancellationToken);
|
|
|
|
if (pendingOrder != null)
|
|
{
|
|
_logger.LogWarning(
|
|
"User {UserId} has pending order {OrderId}",
|
|
request.UserId,
|
|
pendingOrder.Id);
|
|
|
|
// برگرداندن سفارش موجود برای ادامه پرداخت
|
|
var existingTransaction = await _context.Transactions
|
|
.FirstOrDefaultAsync(t => t.Id == pendingOrder.TransactionId, cancellationToken);
|
|
|
|
return new InitiateBasePackagePaymentResponseDto
|
|
{
|
|
Success = true,
|
|
Message = "سفارش قبلی در انتظار پرداخت یافت شد.",
|
|
OrderId = pendingOrder.Id,
|
|
TransactionId = existingTransaction?.Id ?? 0,
|
|
Amount = SystemConstants.BasePackageAmount
|
|
};
|
|
}
|
|
|
|
// 4. پیدا کردن آدرس پیشفرض کاربر
|
|
var defaultAddress = await _context.UserAddresses
|
|
.Where(a => a.UserId == request.UserId)
|
|
.OrderByDescending(a => a.Created)
|
|
.FirstOrDefaultAsync(cancellationToken);
|
|
|
|
if (defaultAddress == null)
|
|
{
|
|
_logger.LogWarning("No address found for user {UserId}", request.UserId);
|
|
throw new ValidationException("لطفاً ابتدا یک آدرس برای خود ثبت کنید.");
|
|
}
|
|
|
|
// 5. ایجاد Transaction با وضعیت Pending
|
|
var transaction = new Transaction
|
|
{
|
|
Amount = SystemConstants.BasePackageAmount,
|
|
Description = $"خرید پکیج پایه ۵۶ میلیونی - کاربر #{user.Id}",
|
|
PaymentStatus = PaymentStatus.Pending,
|
|
Type = TransactionType.DepositIpg
|
|
};
|
|
|
|
_context.Transactions.Add(transaction);
|
|
await _context.SaveChangesAsync(cancellationToken);
|
|
|
|
_logger.LogInformation(
|
|
"Created Transaction {TransactionId} with Pending status for UserId {UserId}",
|
|
transaction.Id,
|
|
request.UserId);
|
|
|
|
// 6. ایجاد UserOrder با وضعیت Pending
|
|
var order = new UserOrder
|
|
{
|
|
UserId = user.Id,
|
|
PackageId = BasePackageId,
|
|
Amount = SystemConstants.BasePackageAmount,
|
|
PaymentStatus = PaymentStatus.Pending,
|
|
DeliveryStatus = DeliveryStatus.None,
|
|
UserAddressId = defaultAddress.Id,
|
|
PaymentMethod = PaymentMethod.IPG,
|
|
TransactionId = transaction.Id
|
|
};
|
|
|
|
_context.UserOrders.Add(order);
|
|
await _context.SaveChangesAsync(cancellationToken);
|
|
|
|
_logger.LogInformation(
|
|
"Created UserOrder {OrderId} for UserId {UserId}, TransactionId: {TransactionId}",
|
|
order.Id,
|
|
request.UserId,
|
|
transaction.Id);
|
|
|
|
return new InitiateBasePackagePaymentResponseDto
|
|
{
|
|
Success = true,
|
|
Message = "تراکنش و سفارش با موفقیت ثبت شد.",
|
|
OrderId = order.Id,
|
|
TransactionId = transaction.Id,
|
|
Amount = SystemConstants.BasePackageAmount
|
|
};
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(
|
|
ex,
|
|
"Error in InitiateBasePackagePaymentCommand for UserId: {UserId}",
|
|
request.UserId);
|
|
throw;
|
|
}
|
|
}
|
|
}
|