feat: Implement Discount Product and Shopping Cart functionalities

- Added UpdateDiscountProductCommandValidator for validating discount product updates.
- Created GetDiscountProductByIdQuery and its handler for retrieving discount product details by ID.
- Implemented GetDiscountProductsQuery and handler for fetching a list of discount products with filtering options.
- Developed AddToCartCommand and handler for adding products to the shopping cart.
- Implemented ClearCartCommand and handler for clearing the shopping cart.
- Created RemoveFromCartCommand and handler for removing items from the cart.
- Added UpdateCartItemCountCommand and handler for updating the quantity of items in the cart.
- Developed GetUserCartQuery and handler for retrieving the user's shopping cart details.
- Implemented Product Tag functionalities including assigning tags to products, creating, updating, and deleting tags.
- Added queries for fetching all tags and products by tag.
This commit is contained in:
masoodafar-web
2025-12-04 02:41:19 +03:30
parent c9dab944fa
commit 4f400eabc5
92 changed files with 2285 additions and 41 deletions
@@ -0,0 +1,13 @@
namespace BackOffice.BFF.Application.DiscountOrderCQ.Commands.CompleteOrderPayment;
public record CompleteOrderPaymentCommand : IRequest
{
/// <summary>شناسه سفارش</summary>
public long OrderId { get; init; }
/// <summary>کد تراکنش پرداخت</summary>
public string PaymentTransactionCode { get; init; }
/// <summary>مبلغ پرداخت شده</summary>
public long PaidAmount { get; init; }
}
@@ -0,0 +1,27 @@
using CMSMicroservice.Protobuf.Protos.DiscountOrder;
namespace BackOffice.BFF.Application.DiscountOrderCQ.Commands.CompleteOrderPayment;
public class CompleteOrderPaymentCommandHandler : IRequestHandler<CompleteOrderPaymentCommand>
{
private readonly IApplicationContractContext _context;
public CompleteOrderPaymentCommandHandler(IApplicationContractContext context)
{
_context = context;
}
public async Task<Unit> Handle(CompleteOrderPaymentCommand request, CancellationToken cancellationToken)
{
await _context.DiscountOrders.CompleteOrderPaymentAsync(
new CompleteOrderPaymentRequest
{
OrderId = request.OrderId,
PaymentTransactionCode = request.PaymentTransactionCode,
PaidAmount = request.PaidAmount
},
cancellationToken: cancellationToken);
return Unit.Value;
}
}
@@ -0,0 +1,16 @@
namespace BackOffice.BFF.Application.DiscountOrderCQ.Commands.CompleteOrderPayment;
public class CompleteOrderPaymentCommandValidator : AbstractValidator<CompleteOrderPaymentCommand>
{
public CompleteOrderPaymentCommandValidator()
{
RuleFor(x => x.OrderId)
.GreaterThan(0).WithMessage("شناسه سفارش نامعتبر است");
RuleFor(x => x.PaymentTransactionCode)
.NotEmpty().WithMessage("کد تراکنش پرداخت الزامی است");
RuleFor(x => x.PaidAmount)
.GreaterThan(0).WithMessage("مبلغ پرداخت شده باید بیشتر از صفر باشد");
}
}
@@ -0,0 +1,16 @@
namespace BackOffice.BFF.Application.DiscountOrderCQ.Commands.PlaceOrder;
public record PlaceOrderCommand : IRequest<PlaceOrderResponseDto>
{
/// <summary>شناسه کاربر</summary>
public long UserId { get; init; }
/// <summary>شناسه آدرس ارسال</summary>
public long AddressId { get; init; }
/// <summary>مبلغ پرداخت از موجودی تخفیف</summary>
public long DiscountBalanceAmount { get; init; }
/// <summary>مبلغ پرداخت از درگاه</summary>
public long GatewayAmount { get; init; }
}
@@ -0,0 +1,34 @@
using CMSMicroservice.Protobuf.Protos.DiscountOrder;
namespace BackOffice.BFF.Application.DiscountOrderCQ.Commands.PlaceOrder;
public class PlaceOrderCommandHandler : IRequestHandler<PlaceOrderCommand, PlaceOrderResponseDto>
{
private readonly IApplicationContractContext _context;
public PlaceOrderCommandHandler(IApplicationContractContext context)
{
_context = context;
}
public async Task<PlaceOrderResponseDto> Handle(PlaceOrderCommand request, CancellationToken cancellationToken)
{
var response = await _context.DiscountOrders.PlaceOrderAsync(
new PlaceOrderRequest
{
UserId = request.UserId,
AddressId = request.AddressId,
DiscountBalanceAmount = request.DiscountBalanceAmount,
GatewayAmount = request.GatewayAmount
},
cancellationToken: cancellationToken);
return new PlaceOrderResponseDto
{
OrderId = response.OrderId,
TrackingCode = response.TrackingCode,
RequiresGatewayPayment = response.RequiresGatewayPayment,
GatewayPayableAmount = response.GatewayPayableAmount
};
}
}
@@ -0,0 +1,23 @@
namespace BackOffice.BFF.Application.DiscountOrderCQ.Commands.PlaceOrder;
public class PlaceOrderCommandValidator : AbstractValidator<PlaceOrderCommand>
{
public PlaceOrderCommandValidator()
{
RuleFor(x => x.UserId)
.GreaterThan(0).WithMessage("شناسه کاربر نامعتبر است");
RuleFor(x => x.AddressId)
.GreaterThan(0).WithMessage("شناسه آدرس نامعتبر است");
RuleFor(x => x.DiscountBalanceAmount)
.GreaterThanOrEqualTo(0).WithMessage("مبلغ موجودی تخفیف نمی‌تواند منفی باشد");
RuleFor(x => x.GatewayAmount)
.GreaterThanOrEqualTo(0).WithMessage("مبلغ درگاه نمی‌تواند منفی باشد");
RuleFor(x => x)
.Must(x => x.DiscountBalanceAmount + x.GatewayAmount > 0)
.WithMessage("مجموع مبالغ پرداخت باید بیشتر از صفر باشد");
}
}
@@ -0,0 +1,16 @@
namespace BackOffice.BFF.Application.DiscountOrderCQ.Commands.PlaceOrder;
public class PlaceOrderResponseDto
{
/// <summary>شناسه سفارش</summary>
public long OrderId { get; set; }
/// <summary>کد پیگیری سفارش</summary>
public string TrackingCode { get; set; }
/// <summary>آیا نیاز به پرداخت از درگاه دارد</summary>
public bool RequiresGatewayPayment { get; set; }
/// <summary>مبلغ قابل پرداخت از درگاه</summary>
public long GatewayPayableAmount { get; set; }
}
@@ -0,0 +1,13 @@
namespace BackOffice.BFF.Application.DiscountOrderCQ.Commands.UpdateOrderStatus;
public record UpdateOrderStatusCommand : IRequest
{
/// <summary>شناسه سفارش</summary>
public long OrderId { get; init; }
/// <summary>وضعیت جدید</summary>
public int NewStatus { get; init; }
/// <summary>یادداشت مدیر (اختیاری)</summary>
public string AdminNote { get; init; }
}
@@ -0,0 +1,27 @@
using CMSMicroservice.Protobuf.Protos.DiscountOrder;
namespace BackOffice.BFF.Application.DiscountOrderCQ.Commands.UpdateOrderStatus;
public class UpdateOrderStatusCommandHandler : IRequestHandler<UpdateOrderStatusCommand>
{
private readonly IApplicationContractContext _context;
public UpdateOrderStatusCommandHandler(IApplicationContractContext context)
{
_context = context;
}
public async Task<Unit> Handle(UpdateOrderStatusCommand request, CancellationToken cancellationToken)
{
await _context.DiscountOrders.UpdateOrderStatusAsync(
new UpdateOrderStatusRequest
{
OrderId = request.OrderId,
NewStatus = request.NewStatus,
AdminNote = request.AdminNote ?? string.Empty
},
cancellationToken: cancellationToken);
return Unit.Value;
}
}
@@ -0,0 +1,13 @@
namespace BackOffice.BFF.Application.DiscountOrderCQ.Commands.UpdateOrderStatus;
public class UpdateOrderStatusCommandValidator : AbstractValidator<UpdateOrderStatusCommand>
{
public UpdateOrderStatusCommandValidator()
{
RuleFor(x => x.OrderId)
.GreaterThan(0).WithMessage("شناسه سفارش نامعتبر است");
RuleFor(x => x.NewStatus)
.InclusiveBetween(0, 6).WithMessage("وضعیت سفارش نامعتبر است");
}
}