feat: Add ClearCart command and response, implement CancelOrder command with validation, and enhance DeliveryStatus and User models

This commit is contained in:
masoodafar-web
2025-12-02 03:30:36 +03:30
parent 25fc73ae28
commit 78606cc5cc
100 changed files with 12925 additions and 8137 deletions

View File

@@ -0,0 +1,24 @@
using CMSMicroservice.Domain.Enums;
namespace CMSMicroservice.Application.UserOrderCQ.Commands.CancelOrder;
/// <summary>
/// Command برای لغو سفارش
/// </summary>
public record CancelOrderCommand : IRequest<CancelOrderResponseDto>
{
/// <summary>
/// شناسه سفارش
/// </summary>
public long OrderId { get; init; }
/// <summary>
/// دلیل لغو سفارش
/// </summary>
public string CancelReason { get; init; }
/// <summary>
/// آیا مبلغ باید بازگردانده شود؟
/// </summary>
public bool RefundPayment { get; init; }
}

View File

@@ -0,0 +1,74 @@
using CMSMicroservice.Domain.Events;
using CMSMicroservice.Domain.Enums;
namespace CMSMicroservice.Application.UserOrderCQ.Commands.CancelOrder;
public class CancelOrderCommandHandler : IRequestHandler<CancelOrderCommand, CancelOrderResponseDto>
{
private readonly IApplicationDbContext _context;
public CancelOrderCommandHandler(IApplicationDbContext context)
{
_context = context;
}
public async Task<CancelOrderResponseDto> Handle(CancelOrderCommand request, CancellationToken cancellationToken)
{
// پیدا کردن سفارش
var order = await _context.UserOrders
.Include(o => o.Transaction)
.FirstOrDefaultAsync(o => o.Id == request.OrderId, cancellationToken);
if (order == null)
{
throw new NotFoundException(nameof(UserOrder), request.OrderId);
}
// چک کردن که سفارش قابل لغو باشد
if (order.DeliveryStatus == DeliveryStatus.Delivered)
{
throw new InvalidOperationException("سفارش تحویل داده شده قابل لغو نیست");
}
if (order.DeliveryStatus == DeliveryStatus.Cancelled)
{
throw new InvalidOperationException("این سفارش قبلاً لغو شده است");
}
// تغییر وضعیت سفارش
order.DeliveryStatus = DeliveryStatus.Cancelled;
order.DeliveryDescription = $"لغو شده: {request.CancelReason}";
// اگر درخواست بازگشت پول داریم و پرداخت موفق بوده
if (request.RefundPayment &&
order.Transaction != null &&
order.Transaction.PaymentStatus == PaymentStatus.Success)
{
// ایجاد تراکنش استرداد
var refundTransaction = new Transactions
{
Amount = -order.Amount,
Description = $"بازگشت وجه سفارش {request.OrderId}: {request.CancelReason}",
PaymentStatus = PaymentStatus.Success,
PaymentDate = DateTime.UtcNow,
RefId = $"REFUND-ORDER-{order.Id}",
Type = TransactionType.Buy
};
await _context.Transactionss.AddAsync(refundTransaction, cancellationToken);
}
// ثبت Event
order.AddDomainEvent(new CancelOrderEvent(order, request.CancelReason));
await _context.SaveChangesAsync(cancellationToken);
return new CancelOrderResponseDto
{
OrderId = order.Id,
Status = order.DeliveryStatus,
Message = "سفارش با موفقیت لغو شد",
RefundProcessed = request.RefundPayment && order.Transaction != null
};
}
}

View File

@@ -0,0 +1,17 @@
namespace CMSMicroservice.Application.UserOrderCQ.Commands.CancelOrder;
public class CancelOrderCommandValidator : AbstractValidator<CancelOrderCommand>
{
public CancelOrderCommandValidator()
{
RuleFor(v => v.OrderId)
.GreaterThan(0)
.WithMessage("شناسه سفارش باید بزرگتر از صفر باشد");
RuleFor(v => v.CancelReason)
.NotEmpty()
.WithMessage("دلیل لغو سفارش الزامی است")
.MaximumLength(500)
.WithMessage("دلیل لغو نباید بیش از 500 کاراکتر باشد");
}
}

View File

@@ -0,0 +1,11 @@
using CMSMicroservice.Domain.Enums;
namespace CMSMicroservice.Application.UserOrderCQ.Commands.CancelOrder;
public class CancelOrderResponseDto
{
public long OrderId { get; set; }
public DeliveryStatus Status { get; set; }
public string Message { get; set; }
public bool RefundProcessed { get; set; }
}

View File

@@ -0,0 +1,26 @@
using Microsoft.Extensions.Logging;
using CMSMicroservice.Domain.Events;
namespace CMSMicroservice.Application.UserOrderCQ.EventHandlers.CancelOrderEventHandlers;
public class CancelOrderEventHandler : INotificationHandler<CancelOrderEvent>
{
private readonly ILogger<CancelOrderEventHandler> _logger;
public CancelOrderEventHandler(ILogger<CancelOrderEventHandler> logger)
{
_logger = logger;
}
public Task Handle(CancelOrderEvent notification, CancellationToken cancellationToken)
{
_logger.LogInformation("Order {OrderId} cancelled. Reason: {Reason}",
notification.Order.Id,
notification.CancelReason);
// اینجا می‌تونیم اعلان به کاربر بفرستیم
// یا موجودی محصولات رو بازگردانیم به انبار
return Task.CompletedTask;
}
}