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:
+13
@@ -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; }
|
||||
}
|
||||
+27
@@ -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;
|
||||
}
|
||||
}
|
||||
+16
@@ -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("مبلغ پرداخت شده باید بیشتر از صفر باشد");
|
||||
}
|
||||
}
|
||||
+16
@@ -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; }
|
||||
}
|
||||
+34
@@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
+23
@@ -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("مجموع مبالغ پرداخت باید بیشتر از صفر باشد");
|
||||
}
|
||||
}
|
||||
+16
@@ -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; }
|
||||
}
|
||||
+13
@@ -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; }
|
||||
}
|
||||
+27
@@ -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;
|
||||
}
|
||||
}
|
||||
+13
@@ -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("وضعیت سفارش نامعتبر است");
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
namespace BackOffice.BFF.Application.DiscountOrderCQ.Queries.GetOrderById;
|
||||
|
||||
public record GetOrderByIdQuery : IRequest<GetOrderByIdResponseDto>
|
||||
{
|
||||
/// <summary>شناسه سفارش</summary>
|
||||
public long OrderId { get; init; }
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
using CMSMicroservice.Protobuf.Protos.DiscountOrder;
|
||||
|
||||
namespace BackOffice.BFF.Application.DiscountOrderCQ.Queries.GetOrderById;
|
||||
|
||||
public class GetOrderByIdQueryHandler : IRequestHandler<GetOrderByIdQuery, GetOrderByIdResponseDto>
|
||||
{
|
||||
private readonly IApplicationContractContext _context;
|
||||
|
||||
public GetOrderByIdQueryHandler(IApplicationContractContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetOrderByIdResponseDto> Handle(GetOrderByIdQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var response = await _context.DiscountOrders.GetOrderByIdAsync(
|
||||
new GetOrderByIdRequest { OrderId = request.OrderId },
|
||||
cancellationToken: cancellationToken);
|
||||
|
||||
return new GetOrderByIdResponseDto
|
||||
{
|
||||
Id = response.Id,
|
||||
UserId = response.UserId,
|
||||
TrackingCode = response.TrackingCode,
|
||||
Status = response.Status,
|
||||
StatusTitle = response.StatusTitle,
|
||||
TotalPrice = response.TotalPrice,
|
||||
DiscountBalanceUsed = response.DiscountBalanceUsed,
|
||||
GatewayPayment = response.GatewayPayment,
|
||||
FinalPrice = response.FinalPrice,
|
||||
PaymentTransactionCode = response.PaymentTransactionCode,
|
||||
AdminNote = response.AdminNote,
|
||||
CreatedAt = response.CreatedAt.ToDateTime(),
|
||||
PaidAt = response.HasPaidAt ? response.PaidAt.ToDateTime() : null,
|
||||
ShippingAddress = new AddressInfoDto
|
||||
{
|
||||
Id = response.ShippingAddress.Id,
|
||||
RecipientName = response.ShippingAddress.RecipientName,
|
||||
RecipientPhone = response.ShippingAddress.RecipientPhone,
|
||||
Province = response.ShippingAddress.Province,
|
||||
City = response.ShippingAddress.City,
|
||||
PostalCode = response.ShippingAddress.PostalCode,
|
||||
FullAddress = response.ShippingAddress.FullAddress
|
||||
},
|
||||
Items = response.Items.Select(item => new OrderItemDto
|
||||
{
|
||||
Id = item.Id,
|
||||
ProductId = item.ProductId,
|
||||
ProductTitle = item.ProductTitle,
|
||||
UnitPrice = item.UnitPrice,
|
||||
DiscountPercent = item.DiscountPercent,
|
||||
Quantity = item.Quantity,
|
||||
TotalPrice = item.TotalPrice,
|
||||
DiscountedPrice = item.DiscountedPrice
|
||||
}).ToList()
|
||||
};
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
namespace BackOffice.BFF.Application.DiscountOrderCQ.Queries.GetOrderById;
|
||||
|
||||
public class GetOrderByIdQueryValidator : AbstractValidator<GetOrderByIdQuery>
|
||||
{
|
||||
public GetOrderByIdQueryValidator()
|
||||
{
|
||||
RuleFor(x => x.OrderId)
|
||||
.GreaterThan(0).WithMessage("شناسه سفارش نامعتبر است");
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
namespace BackOffice.BFF.Application.DiscountOrderCQ.Queries.GetOrderById;
|
||||
|
||||
public class GetOrderByIdResponseDto
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public long UserId { get; set; }
|
||||
public string TrackingCode { get; set; }
|
||||
public int Status { get; set; }
|
||||
public string StatusTitle { get; set; }
|
||||
public long TotalPrice { get; set; }
|
||||
public long DiscountBalanceUsed { get; set; }
|
||||
public long GatewayPayment { get; set; }
|
||||
public long FinalPrice { get; set; }
|
||||
public string PaymentTransactionCode { get; set; }
|
||||
public string AdminNote { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime? PaidAt { get; set; }
|
||||
|
||||
public AddressInfoDto ShippingAddress { get; set; }
|
||||
public List<OrderItemDto> Items { get; set; } = new();
|
||||
}
|
||||
|
||||
public class AddressInfoDto
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string RecipientName { get; set; }
|
||||
public string RecipientPhone { get; set; }
|
||||
public string Province { get; set; }
|
||||
public string City { get; set; }
|
||||
public string PostalCode { get; set; }
|
||||
public string FullAddress { get; set; }
|
||||
}
|
||||
|
||||
public class OrderItemDto
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public long ProductId { get; set; }
|
||||
public string ProductTitle { get; set; }
|
||||
public long UnitPrice { get; set; }
|
||||
public int DiscountPercent { get; set; }
|
||||
public int Quantity { get; set; }
|
||||
public long TotalPrice { get; set; }
|
||||
public long DiscountedPrice { get; set; }
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
namespace BackOffice.BFF.Application.DiscountOrderCQ.Queries.GetUserOrders;
|
||||
|
||||
public record GetUserOrdersQuery : IRequest<GetUserOrdersResponseDto>
|
||||
{
|
||||
/// <summary>شناسه کاربر</summary>
|
||||
public long UserId { get; init; }
|
||||
|
||||
/// <summary>فیلتر براساس وضعیت سفارش</summary>
|
||||
public int? Status { get; init; }
|
||||
|
||||
/// <summary>شماره صفحه</summary>
|
||||
public int PageNumber { get; init; } = 1;
|
||||
|
||||
/// <summary>تعداد در هر صفحه</summary>
|
||||
public int PageSize { get; init; } = 20;
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
using BackOffice.BFF.Application.Common.Models;
|
||||
using CMSMicroservice.Protobuf.Protos.DiscountOrder;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
namespace BackOffice.BFF.Application.DiscountOrderCQ.Queries.GetUserOrders;
|
||||
|
||||
public class GetUserOrdersQueryHandler : IRequestHandler<GetUserOrdersQuery, GetUserOrdersResponseDto>
|
||||
{
|
||||
private readonly IApplicationContractContext _context;
|
||||
|
||||
public GetUserOrdersQueryHandler(IApplicationContractContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetUserOrdersResponseDto> Handle(GetUserOrdersQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var grpcRequest = new GetUserOrdersRequest
|
||||
{
|
||||
UserId = request.UserId,
|
||||
PageNumber = request.PageNumber,
|
||||
PageSize = request.PageSize
|
||||
};
|
||||
|
||||
if (request.Status.HasValue)
|
||||
grpcRequest.Status = new Int32Value { Value = request.Status.Value };
|
||||
|
||||
var response = await _context.DiscountOrders.GetUserOrdersAsync(grpcRequest, cancellationToken: cancellationToken);
|
||||
|
||||
return new GetUserOrdersResponseDto
|
||||
{
|
||||
MetaData = new MetaData
|
||||
{
|
||||
CurrentPage = response.MetaData.CurrentPage,
|
||||
TotalPage = response.MetaData.TotalPages,
|
||||
PageSize = response.MetaData.PageSize,
|
||||
TotalCount = response.MetaData.TotalCount,
|
||||
HasPrevious = response.MetaData.HasPrevious,
|
||||
HasNext = response.MetaData.HasNext
|
||||
},
|
||||
Orders = response.Orders.Select(order => new UserOrderDto
|
||||
{
|
||||
Id = order.Id,
|
||||
TrackingCode = order.TrackingCode,
|
||||
Status = order.Status,
|
||||
StatusTitle = order.StatusTitle,
|
||||
TotalPrice = order.TotalPrice,
|
||||
FinalPrice = order.FinalPrice,
|
||||
ItemCount = order.ItemCount,
|
||||
CreatedAt = order.CreatedAt.ToDateTime()
|
||||
}).ToList()
|
||||
};
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
namespace BackOffice.BFF.Application.DiscountOrderCQ.Queries.GetUserOrders;
|
||||
|
||||
public class GetUserOrdersQueryValidator : AbstractValidator<GetUserOrdersQuery>
|
||||
{
|
||||
public GetUserOrdersQueryValidator()
|
||||
{
|
||||
RuleFor(x => x.UserId)
|
||||
.GreaterThan(0).WithMessage("شناسه کاربر نامعتبر است");
|
||||
|
||||
RuleFor(x => x.PageNumber)
|
||||
.GreaterThan(0).WithMessage("شماره صفحه باید بیشتر از صفر باشد");
|
||||
|
||||
RuleFor(x => x.PageSize)
|
||||
.GreaterThan(0).WithMessage("تعداد در صفحه باید بیشتر از صفر باشد")
|
||||
.LessThanOrEqualTo(100).WithMessage("حداکثر تعداد در صفحه 100 است");
|
||||
|
||||
RuleFor(x => x.Status)
|
||||
.InclusiveBetween(0, 6).When(x => x.Status.HasValue)
|
||||
.WithMessage("وضعیت سفارش نامعتبر است");
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
using BackOffice.BFF.Application.Common.Models;
|
||||
|
||||
namespace BackOffice.BFF.Application.DiscountOrderCQ.Queries.GetUserOrders;
|
||||
|
||||
public class GetUserOrdersResponseDto
|
||||
{
|
||||
public MetaData MetaData { get; set; }
|
||||
public List<UserOrderDto> Orders { get; set; } = new();
|
||||
}
|
||||
|
||||
public class UserOrderDto
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string TrackingCode { get; set; }
|
||||
public int Status { get; set; }
|
||||
public string StatusTitle { get; set; }
|
||||
public long TotalPrice { get; set; }
|
||||
public long FinalPrice { get; set; }
|
||||
public int ItemCount { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user