feat: Implement User Package Status and User Order Management features

- Added GetUserPackageStatus functionality with mapping and service implementation.
- Introduced UserOrder service methods for updating order status, applying discounts, and calculating order PV.
- Created Protobuf definitions for public messages and user orders, including necessary request and response messages.
- Implemented mapping profiles for package and user order related queries and commands.
- Developed query handlers and validators for new commands and queries in the application layer.
- Established PublicMessage service for handling public messages with appropriate gRPC endpoints.
This commit is contained in:
masoodafar-web
2025-12-04 03:43:28 +03:30
parent 256b41fcb5
commit 4b6f8187e5
34 changed files with 884 additions and 18 deletions

View File

@@ -1,10 +1,14 @@
using BackOffice.BFF.Application.PackageCQ.Queries.GetUserPackageStatus;
using BackOffice.BFF.Package.Protobuf.Protos.Package;
namespace BackOffice.BFF.WebApi.Common.Mappings;
public class PackageProfile : IRegister
{
void IRegister.Register(TypeAdapterConfig config)
{
//config.NewConfig<Source,Destination>()
// .Map(dest => dest.FullName, src => $"{src.Firstname} {src.Lastname}");
// GetUserPackageStatus
config.NewConfig<GetUserPackageStatusRequest, GetUserPackageStatusQuery>()
.Map(dest => dest.UserId, src => src.UserId);
}
}

View File

@@ -0,0 +1,66 @@
namespace BackOffice.BFF.WebApi.Common.Mappings;
using BackOffice.BFF.PublicMessage.Protobuf;
using BackOffice.BFF.Application.PublicMessageCQ.Queries.GetAllMessages;
using BackOffice.BFF.Application.PublicMessageCQ.Queries.GetActiveMessages;
using Google.Protobuf.WellKnownTypes;
public class PublicMessageProfile : IRegister
{
void IRegister.Register(TypeAdapterConfig config)
{
// GetAllMessages mappings
config.NewConfig<GetAllMessagesRequest, GetAllMessagesQuery>()
.Map(dest => dest.Status, src => src.Status != null ? (int?)src.Status.Value : null)
.Map(dest => dest.MessageType, src => src.MessageType != null ? (int?)src.MessageType.Value : null)
.Map(dest => dest.PageNumber, src => src.PageNumber)
.Map(dest => dest.PageSize, src => src.PageSize);
config.NewConfig<GetAllMessagesQuery, GetAllMessagesResponse>()
.Map(dest => dest.Messages, src => src.Messages)
.Map(dest => dest.TotalCount, src => src.TotalCount)
.Map(dest => dest.PageNumber, src => src.PageNumber)
.Map(dest => dest.PageSize, src => src.PageSize);
config.NewConfig<AdminPublicMessageDto, AdminPublicMessageDto>()
.Map(dest => dest.MessageId, src => src.MessageId)
.Map(dest => dest.Title, src => src.Title)
.Map(dest => dest.Content, src => src.Content)
.Map(dest => dest.MessageType, src => src.MessageType)
.Map(dest => dest.MessageTypeName, src => src.MessageTypeName)
.Map(dest => dest.Priority, src => src.Priority)
.Map(dest => dest.PriorityName, src => src.PriorityName)
.Map(dest => dest.Status, src => src.Status)
.Map(dest => dest.StatusName, src => src.StatusName)
.Map(dest => dest.StartsAt, src => src.StartsAt.HasValue ? Timestamp.FromDateTime(src.StartsAt.Value.ToUniversalTime()) : null)
.Map(dest => dest.ExpiresAt, src => src.ExpiresAt.HasValue ? Timestamp.FromDateTime(src.ExpiresAt.Value.ToUniversalTime()) : null)
.Map(dest => dest.PublishedAt, src => src.PublishedAt.HasValue ? Timestamp.FromDateTime(src.PublishedAt.Value.ToUniversalTime()) : null)
.Map(dest => dest.ArchivedAt, src => src.ArchivedAt.HasValue ? Timestamp.FromDateTime(src.ArchivedAt.Value.ToUniversalTime()) : null)
.Map(dest => dest.IsDismissible, src => src.IsDismissible)
.Map(dest => dest.TargetAudience, src => src.TargetAudience)
.Map(dest => dest.Tags, src => src.Tags)
.Map(dest => dest.Created, src => Timestamp.FromDateTime(src.Created.ToUniversalTime()))
.Map(dest => dest.LastModified, src => Timestamp.FromDateTime(src.LastModified.ToUniversalTime()));
// GetActiveMessages mappings
config.NewConfig<GetActiveMessagesRequest, GetActiveMessagesQuery>()
.Map(dest => dest.MessageType, src => src.MessageType != null ? (int?)src.MessageType.Value : null)
.Map(dest => dest.TargetAudience, src => src.TargetAudience);
config.NewConfig<GetActiveMessagesQuery, GetActiveMessagesResponse>()
.Map(dest => dest.Messages, src => src.Messages);
config.NewConfig<PublicMessageDto, PublicMessageDto>()
.Map(dest => dest.MessageId, src => src.MessageId)
.Map(dest => dest.Title, src => src.Title)
.Map(dest => dest.Content, src => src.Content)
.Map(dest => dest.MessageType, src => src.MessageType)
.Map(dest => dest.MessageTypeName, src => src.MessageTypeName)
.Map(dest => dest.Priority, src => src.Priority)
.Map(dest => dest.PriorityName, src => src.PriorityName)
.Map(dest => dest.StartsAt, src => Timestamp.FromDateTime(src.StartsAt.ToUniversalTime()))
.Map(dest => dest.ExpiresAt, src => Timestamp.FromDateTime(src.ExpiresAt.ToUniversalTime()))
.Map(dest => dest.IsDismissible, src => src.IsDismissible)
.Map(dest => dest.Tags, src => src.Tags);
}
}

View File

@@ -1,10 +1,79 @@
namespace BackOffice.BFF.WebApi.Common.Mappings;
using BackOffice.BFF.UserOrder.Protobuf.Protos.UserOrder;
using BackOffice.BFF.Application.UserOrderCQ.Commands.UpdateOrderStatus;
using BackOffice.BFF.Application.UserOrderCQ.Commands.ApplyDiscountToOrder;
using BackOffice.BFF.Application.UserOrderCQ.Queries.GetOrdersByDateRange;
using BackOffice.BFF.Application.UserOrderCQ.Queries.CalculateOrderPV;
using Google.Protobuf.WellKnownTypes;
public class UserOrderProfile : IRegister
{
void IRegister.Register(TypeAdapterConfig config)
{
//config.NewConfig<Source,Destination>()
// .Map(dest => dest.FullName, src => $"{src.Firstname} {src.Lastname}");
// UpdateOrderStatus mappings
config.NewConfig<UpdateOrderStatusRequest, UpdateOrderStatusCommand>()
.Map(dest => dest.OrderId, src => src.OrderId)
.Map(dest => dest.NewStatus, src => src.NewStatus);
config.NewConfig<UpdateOrderStatusCommand, UpdateOrderStatusResponse>()
.Map(dest => dest.Success, src => src.Success)
.Map(dest => dest.Message, src => src.Message)
.Map(dest => dest.OldStatus, src => src.OldStatus)
.Map(dest => dest.NewStatus, src => src.NewStatus);
// GetOrdersByDateRange mappings
config.NewConfig<GetOrdersByDateRangeRequest, GetOrdersByDateRangeQuery>()
.Map(dest => dest.StartDate, src => src.StartDate.ToDateTime())
.Map(dest => dest.EndDate, src => src.EndDate.ToDateTime())
.Map(dest => dest.Status, src => src.Status != null ? (int?)src.Status.Value : null)
.Map(dest => dest.UserId, src => src.UserId != null ? (long?)src.UserId.Value : null)
.Map(dest => dest.PageNumber, src => src.PageNumber)
.Map(dest => dest.PageSize, src => src.PageSize);
config.NewConfig<GetOrdersByDateRangeQuery, GetOrdersByDateRangeResponse>()
.Map(dest => dest.MetaData, src => src.MetaData)
.Map(dest => dest.Orders, src => src.Orders);
config.NewConfig<OrderSummaryDto, OrderSummaryDto>()
.Map(dest => dest.OrderId, src => src.OrderId)
.Map(dest => dest.OrderNumber, src => src.OrderNumber)
.Map(dest => dest.UserId, src => src.UserId)
.Map(dest => dest.UserFullName, src => src.UserFullName)
.Map(dest => dest.TotalAmount, src => src.TotalAmount)
.Map(dest => dest.Status, src => src.Status)
.Map(dest => dest.StatusName, src => src.StatusName)
.Map(dest => dest.ItemsCount, src => src.ItemsCount)
.Map(dest => dest.CreatedAt, src => Timestamp.FromDateTime(src.CreatedAt.ToUniversalTime()));
// ApplyDiscountToOrder mappings
config.NewConfig<ApplyDiscountToOrderRequest, ApplyDiscountToOrderCommand>()
.Map(dest => dest.OrderId, src => src.OrderId)
.Map(dest => dest.DiscountAmount, src => src.DiscountAmount)
.Map(dest => dest.Reason, src => src.Reason);
config.NewConfig<ApplyDiscountToOrderCommand, ApplyDiscountToOrderResponse>()
.Map(dest => dest.Success, src => src.Success)
.Map(dest => dest.Message, src => src.Message)
.Map(dest => dest.OriginalAmount, src => src.OriginalAmount)
.Map(dest => dest.DiscountAmount, src => src.DiscountAmount)
.Map(dest => dest.FinalAmount, src => src.FinalAmount);
// CalculateOrderPV mappings
config.NewConfig<CalculateOrderPVRequest, CalculateOrderPVQuery>()
.Map(dest => dest.OrderId, src => src.OrderId);
config.NewConfig<CalculateOrderPVQuery, CalculateOrderPVResponse>()
.Map(dest => dest.OrderId, src => src.OrderId)
.Map(dest => dest.TotalPv, src => src.TotalPV)
.Map(dest => dest.Products, src => src.Products);
config.NewConfig<ProductPVDto, ProductPVDto>()
.Map(dest => dest.ProductId, src => src.ProductId)
.Map(dest => dest.ProductTitle, src => src.ProductTitle)
.Map(dest => dest.Quantity, src => src.Quantity)
.Map(dest => dest.UnitPv, src => src.UnitPV)
.Map(dest => dest.TotalPv, src => src.TotalPV);
}
}

View File

@@ -5,6 +5,7 @@ using BackOffice.BFF.Application.PackageCQ.Commands.UpdatePackage;
using BackOffice.BFF.Application.PackageCQ.Commands.DeletePackage;
using BackOffice.BFF.Application.PackageCQ.Queries.GetPackage;
using BackOffice.BFF.Application.PackageCQ.Queries.GetAllPackageByFilter;
using BackOffice.BFF.Application.PackageCQ.Queries.GetUserPackageStatus;
namespace BackOffice.BFF.WebApi.Services;
public class PackageService : PackageContract.PackageContractBase
{
@@ -34,4 +35,9 @@ public class PackageService : PackageContract.PackageContractBase
{
return await _dispatchRequestToCQRS.Handle<GetAllPackageByFilterRequest, GetAllPackageByFilterQuery, GetAllPackageByFilterResponse>(request, context);
}
public override async Task<GetUserPackageStatusResponse> GetUserPackageStatus(GetUserPackageStatusRequest request, ServerCallContext context)
{
return await _dispatchRequestToCQRS.Handle<GetUserPackageStatusRequest, GetUserPackageStatusQuery, GetUserPackageStatusResponse>(request, context);
}
}

View File

@@ -0,0 +1,26 @@
using BackOffice.BFF.PublicMessage.Protobuf;
using BackOffice.BFF.WebApi.Common.Services;
using BackOffice.BFF.Application.PublicMessageCQ.Queries.GetAllMessages;
using BackOffice.BFF.Application.PublicMessageCQ.Queries.GetActiveMessages;
namespace BackOffice.BFF.WebApi.Services;
public class PublicMessageService : PublicMessageContract.PublicMessageContractBase
{
private readonly IDispatchRequestToCQRS _dispatchRequestToCQRS;
public PublicMessageService(IDispatchRequestToCQRS dispatchRequestToCQRS)
{
_dispatchRequestToCQRS = dispatchRequestToCQRS;
}
public override async Task<GetAllMessagesResponse> GetAllMessages(GetAllMessagesRequest request, ServerCallContext context)
{
return await _dispatchRequestToCQRS.Handle<GetAllMessagesRequest, GetAllMessagesQuery, GetAllMessagesResponse>(request, context);
}
public override async Task<GetActiveMessagesResponse> GetActiveMessages(GetActiveMessagesRequest request, ServerCallContext context)
{
return await _dispatchRequestToCQRS.Handle<GetActiveMessagesRequest, GetActiveMessagesQuery, GetActiveMessagesResponse>(request, context);
}
}

View File

@@ -5,6 +5,10 @@ using BackOffice.BFF.Application.UserOrderCQ.Commands.UpdateUserOrder;
using BackOffice.BFF.Application.UserOrderCQ.Commands.DeleteUserOrder;
using BackOffice.BFF.Application.UserOrderCQ.Queries.GetUserOrder;
using BackOffice.BFF.Application.UserOrderCQ.Queries.GetAllUserOrderByFilter;
using BackOffice.BFF.Application.UserOrderCQ.Commands.UpdateOrderStatus;
using BackOffice.BFF.Application.UserOrderCQ.Commands.ApplyDiscountToOrder;
using BackOffice.BFF.Application.UserOrderCQ.Queries.GetOrdersByDateRange;
using BackOffice.BFF.Application.UserOrderCQ.Queries.CalculateOrderPV;
namespace BackOffice.BFF.WebApi.Services;
public class UserOrderService : UserOrderContract.UserOrderContractBase
{
@@ -34,4 +38,24 @@ public class UserOrderService : UserOrderContract.UserOrderContractBase
{
return await _dispatchRequestToCQRS.Handle<GetAllUserOrderByFilterRequest, GetAllUserOrderByFilterQuery, GetAllUserOrderByFilterResponse>(request, context);
}
public override async Task<UpdateOrderStatusResponse> UpdateOrderStatus(UpdateOrderStatusRequest request, ServerCallContext context)
{
return await _dispatchRequestToCQRS.Handle<UpdateOrderStatusRequest, UpdateOrderStatusCommand, UpdateOrderStatusResponse>(request, context);
}
public override async Task<GetOrdersByDateRangeResponse> GetOrdersByDateRange(GetOrdersByDateRangeRequest request, ServerCallContext context)
{
return await _dispatchRequestToCQRS.Handle<GetOrdersByDateRangeRequest, GetOrdersByDateRangeQuery, GetOrdersByDateRangeResponse>(request, context);
}
public override async Task<ApplyDiscountToOrderResponse> ApplyDiscountToOrder(ApplyDiscountToOrderRequest request, ServerCallContext context)
{
return await _dispatchRequestToCQRS.Handle<ApplyDiscountToOrderRequest, ApplyDiscountToOrderCommand, ApplyDiscountToOrderResponse>(request, context);
}
public override async Task<CalculateOrderPVResponse> CalculateOrderPV(CalculateOrderPVRequest request, ServerCallContext context)
{
return await _dispatchRequestToCQRS.Handle<CalculateOrderPVRequest, CalculateOrderPVQuery, CalculateOrderPVResponse>(request, context);
}
}