feat: Implement bulk update for product prices and stock, and add low stock products query and toggle product status functionality

This commit is contained in:
masoodafar-web
2025-12-04 02:56:03 +03:30
parent f0f48118e7
commit 84f642e900
4 changed files with 234 additions and 3 deletions
@@ -1,10 +1,93 @@
using CMSMicroservice.Application.ProductsCQ.Commands.BulkUpdateProductPrices;
using CMSMicroservice.Application.ProductsCQ.Commands.BulkUpdateProductStock;
using CMSMicroservice.Application.ProductsCQ.Commands.ToggleProductStatus;
using CMSMicroservice.Application.ProductsCQ.Queries.GetLowStockProducts;
using CMSMicroservice.Protobuf.Protos.Products;
using ProtoProductPriceUpdate = CMSMicroservice.Protobuf.Protos.Products.ProductPriceUpdate;
using AppProductPriceUpdate = CMSMicroservice.Application.ProductsCQ.Commands.BulkUpdateProductPrices.ProductPriceUpdate;
using ProtoProductStockUpdate = CMSMicroservice.Protobuf.Protos.Products.ProductStockUpdate;
using AppProductStockUpdate = CMSMicroservice.Application.ProductsCQ.Commands.BulkUpdateProductStock.ProductStockUpdate;
using ProtoStockUpdateType = CMSMicroservice.Protobuf.Protos.Products.StockUpdateType;
using AppStockUpdateType = CMSMicroservice.Application.ProductsCQ.Commands.BulkUpdateProductStock.StockUpdateType;
using System.Linq;
namespace CMSMicroservice.WebApi.Common.Mappings;
public class ProductsProfile : IRegister
{
void IRegister.Register(TypeAdapterConfig config)
{
//config.NewConfig<Source,Destination>()
// .Map(dest => dest.FullName, src => $"{src.Firstname} {src.Lastname}");
// BulkUpdateProductPrices mappings
config.NewConfig<BulkUpdateProductPricesRequest, BulkUpdateProductPricesCommand>()
.Map(dest => dest.Products, src => src.Products);
config.NewConfig<ProtoProductPriceUpdate, AppProductPriceUpdate>()
.Map(dest => dest.ProductId, src => src.ProductId)
.Map(dest => dest.NewPrice, src => src.NewPrice)
.Map(dest => dest.NewDiscount, src => src.NewDiscount != null ? (int?)src.NewDiscount.Value : null)
.Map(dest => dest.NewClubDiscountPercent, src => src.NewClubDiscountPercent != null ? (int?)src.NewClubDiscountPercent.Value : null);
config.NewConfig<BulkUpdateProductPricesResponseDto, BulkUpdateProductPricesResponse>()
.Map(dest => dest.Total, src => src.UpdatedCount + src.FailedCount)
.Map(dest => dest.Succeeded, src => src.UpdatedCount)
.Map(dest => dest.Failed, src => src.FailedCount)
.Map(dest => dest.Errors, src => src.Errors.Select((msg, idx) => new BulkOperationError
{
ProductId = 0, // We don't have the ID in the error message
ErrorMessage = msg
}).ToList());
// BulkUpdateProductStock mappings
config.NewConfig<BulkUpdateProductStockRequest, BulkUpdateProductStockCommand>()
.Map(dest => dest.Products, src => src.Products)
.Map(dest => dest.UpdateType, src => (AppStockUpdateType)src.UpdateType);
config.NewConfig<ProtoProductStockUpdate, AppProductStockUpdate>()
.Map(dest => dest.ProductId, src => src.ProductId)
.Map(dest => dest.Quantity, src => src.Quantity);
config.NewConfig<BulkUpdateProductStockResponseDto, BulkUpdateProductStockResponse>()
.Map(dest => dest.Total, src => src.UpdatedCount + src.FailedCount)
.Map(dest => dest.Succeeded, src => src.UpdatedCount)
.Map(dest => dest.Failed, src => src.FailedCount)
.Map(dest => dest.Errors, src => src.Errors.Select(msg => new BulkOperationError
{
ProductId = 0,
ErrorMessage = msg
}).ToList());
// GetLowStockProducts mappings
config.NewConfig<GetLowStockProductsRequest, GetLowStockProductsQuery>()
.Map(dest => dest.Threshold, src => src.Threshold)
.Map(dest => dest.PageIndex, src => src.PageIndex)
.Map(dest => dest.PageSize, src => src.PageSize)
.Map(dest => dest.IsClubExclusive, src => src.IsClubExclusive != null ? (bool?)src.IsClubExclusive.Value : null);
config.NewConfig<GetLowStockProductsResponseDto, GetLowStockProductsResponse>()
.Map(dest => dest.MetaData, src => src.MetaData)
.Map(dest => dest.Products, src => src.Products);
config.NewConfig<LowStockProductDto, LowStockProduct>()
.Map(dest => dest.Id, src => src.Id)
.Map(dest => dest.Title, src => src.Title)
.Map(dest => dest.RemainingCount, src => src.RemainingCount)
.Map(dest => dest.Price, src => src.Price)
.Map(dest => dest.IsClubExclusive, src => src.IsClubExclusive);
// ToggleProductStatus mappings
config.NewConfig<ToggleProductStatusRequest, ToggleProductStatusCommand>()
.Map(dest => dest.ProductIds, src => src.ProductIds)
.Map(dest => dest.Enable, src => src.Enable)
.Map(dest => dest.DefaultStock, src => src.DefaultStock);
config.NewConfig<ToggleProductStatusResponseDto, ToggleProductStatusResponse>()
.Map(dest => dest.Total, src => src.UpdatedCount + src.FailedCount)
.Map(dest => dest.Succeeded, src => src.UpdatedCount)
.Map(dest => dest.Failed, src => src.FailedCount)
.Map(dest => dest.Errors, src => src.Errors.Select(msg => new BulkOperationError
{
ProductId = 0,
ErrorMessage = msg
}).ToList());
}
}
@@ -5,6 +5,10 @@ using CMSMicroservice.Application.ProductsCQ.Commands.UpdateProducts;
using CMSMicroservice.Application.ProductsCQ.Commands.DeleteProducts;
using CMSMicroservice.Application.ProductsCQ.Queries.GetProducts;
using CMSMicroservice.Application.ProductsCQ.Queries.GetAllProductsByFilter;
using CMSMicroservice.Application.ProductsCQ.Commands.BulkUpdateProductPrices;
using CMSMicroservice.Application.ProductsCQ.Commands.BulkUpdateProductStock;
using CMSMicroservice.Application.ProductsCQ.Queries.GetLowStockProducts;
using CMSMicroservice.Application.ProductsCQ.Commands.ToggleProductStatus;
namespace CMSMicroservice.WebApi.Services;
public class ProductsService : ProductsContract.ProductsContractBase
{
@@ -34,4 +38,24 @@ public class ProductsService : ProductsContract.ProductsContractBase
{
return await _dispatchRequestToCQRS.Handle<GetAllProductsByFilterRequest, GetAllProductsByFilterQuery, GetAllProductsByFilterResponse>(request, context);
}
public override async Task<BulkUpdateProductPricesResponse> BulkUpdateProductPrices(BulkUpdateProductPricesRequest request, ServerCallContext context)
{
return await _dispatchRequestToCQRS.Handle<BulkUpdateProductPricesRequest, BulkUpdateProductPricesCommand, BulkUpdateProductPricesResponse>(request, context);
}
public override async Task<BulkUpdateProductStockResponse> BulkUpdateProductStock(BulkUpdateProductStockRequest request, ServerCallContext context)
{
return await _dispatchRequestToCQRS.Handle<BulkUpdateProductStockRequest, BulkUpdateProductStockCommand, BulkUpdateProductStockResponse>(request, context);
}
public override async Task<GetLowStockProductsResponse> GetLowStockProducts(GetLowStockProductsRequest request, ServerCallContext context)
{
return await _dispatchRequestToCQRS.Handle<GetLowStockProductsRequest, GetLowStockProductsQuery, GetLowStockProductsResponse>(request, context);
}
public override async Task<ToggleProductStatusResponse> ToggleProductStatus(ToggleProductStatusRequest request, ServerCallContext context)
{
return await _dispatchRequestToCQRS.Handle<ToggleProductStatusRequest, ToggleProductStatusCommand, ToggleProductStatusResponse>(request, context);
}
}