feat: Implement customer profile and referral queries
- Add GetCustomerProfileResponseDto for retrieving customer profile information. - Create GetCustomerReferralsQuery and GetCustomerReferralsQueryHandler to fetch customer referrals with pagination and filtering options. - Introduce GetCustomerReferralsResponseDto to structure the response for customer referrals. - Implement GetCustomerSettingsQuery and GetCustomerSettingsQueryHandler to retrieve user settings. - Add GetCustomerOrder and GetCustomerOrderQueryHandler for fetching specific customer orders. - Create GetCustomerOrderHistoryQuery and GetCustomerOrderHistoryQueryHandler to retrieve order history with filtering options. - Implement GetCustomerOrdersQuery and GetCustomerOrdersQueryHandler for fetching multiple customer orders with filters. - Add GetCustomerWalletChangeLogQuery and GetCustomerWalletChangeLogQueryHandler for retrieving wallet change logs. - Implement GetCustomerWithdrawalSettingsQuery and GetCustomerWithdrawalSettingsQueryHandler for fetching withdrawal settings. - Create GetCustomerWithdrawalsQuery and GetCustomerWithdrawalsQueryHandler to retrieve customer withdrawal requests.
This commit is contained in:
+6
@@ -0,0 +1,6 @@
|
||||
namespace CMSMicroservice.Application.ProductsCQ.Queries.GetCustomerProducts;
|
||||
|
||||
public class GetCustomerProductsQuery : IRequest<GetCustomerProductsResponseDto>
|
||||
{
|
||||
public long Id { get; set; }
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
using CMSMicroservice.Application.Common.Interfaces;
|
||||
using CMSMicroservice.Domain.Entities;
|
||||
|
||||
namespace CMSMicroservice.Application.ProductsCQ.Queries.GetCustomerProducts;
|
||||
|
||||
public class GetCustomerProductsQueryHandler : IRequestHandler<GetCustomerProductsQuery, GetCustomerProductsResponseDto>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public GetCustomerProductsQueryHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetCustomerProductsResponseDto> Handle(GetCustomerProductsQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var product = await _context.Products
|
||||
.AsNoTracking()
|
||||
.Where(x => x.Id == request.Id)
|
||||
.Include(x => x.ProductGalleries)
|
||||
.ThenInclude(pg => pg.ProductImage)
|
||||
.Include(x => x.ProductCategories)
|
||||
.ThenInclude(pc => pc.Category)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
|
||||
if (product == null)
|
||||
throw new NotFoundException(nameof(Products), request.Id);
|
||||
|
||||
var response = new GetCustomerProductsResponseDto
|
||||
{
|
||||
Id = product.Id,
|
||||
Title = product.Title,
|
||||
Description = product.Description,
|
||||
ShortInfomation = product.ShortInfomation,
|
||||
FullInformation = product.FullInformation,
|
||||
Price = product.Price,
|
||||
Discount = product.Discount,
|
||||
Rate = product.Rate,
|
||||
ImagePath = product.ImagePath,
|
||||
ThumbnailPath = product.ThumbnailPath,
|
||||
SaleCount = product.SaleCount,
|
||||
ViewCount = product.ViewCount,
|
||||
RemainingCount = product.RemainingCount,
|
||||
Gallery = product.ProductGalleries?.Select(pg => new ProductGalleryModel
|
||||
{
|
||||
ProductGalleryId = pg.Id,
|
||||
ProductImageId = pg.ProductImageId,
|
||||
Title = pg.ProductImage?.Title ?? string.Empty,
|
||||
ImagePath = pg.ProductImage?.ImagePath ?? string.Empty,
|
||||
ImageThumbnailPath = pg.ProductImage?.ImageThumbnailPath ?? string.Empty
|
||||
}).ToList() ?? new List<ProductGalleryModel>(),
|
||||
Categories = product.ProductCategories?.Select(pc => new ProductCategoryModel
|
||||
{
|
||||
CategoryId = pc.CategoryId,
|
||||
Title = pc.Category?.Title ?? string.Empty,
|
||||
Path = BuildCategoryPath(pc.Category)
|
||||
}).ToList() ?? new List<ProductCategoryModel>()
|
||||
};
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private List<CategoryNodeModel> BuildCategoryPath(Category? category)
|
||||
{
|
||||
var path = new List<CategoryNodeModel>();
|
||||
|
||||
while (category != null)
|
||||
{
|
||||
path.Insert(0, new CategoryNodeModel
|
||||
{
|
||||
Id = category.Id,
|
||||
Title = category.Title,
|
||||
ParentId = category.ParentId
|
||||
});
|
||||
|
||||
// Move to parent
|
||||
if (category.ParentId.HasValue)
|
||||
{
|
||||
category = _context.Categories
|
||||
.AsNoTracking()
|
||||
.FirstOrDefault(c => c.Id == category.ParentId.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
category = null;
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
namespace CMSMicroservice.Application.ProductsCQ.Queries.GetCustomerProducts;
|
||||
|
||||
public class GetCustomerProductsResponseDto
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string ShortInfomation { get; set; }
|
||||
public string FullInformation { get; set; }
|
||||
public long Price { get; set; }
|
||||
public int Discount { get; set; }
|
||||
public int Rate { get; set; }
|
||||
public string ImagePath { get; set; }
|
||||
public string ThumbnailPath { get; set; }
|
||||
public int SaleCount { get; set; }
|
||||
public int ViewCount { get; set; }
|
||||
public int RemainingCount { get; set; }
|
||||
public List<ProductGalleryModel> Gallery { get; set; }
|
||||
public List<ProductCategoryModel> Categories { get; set; }
|
||||
}
|
||||
|
||||
public class ProductGalleryModel
|
||||
{
|
||||
public long ProductGalleryId { get; set; }
|
||||
public long ProductImageId { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string ImagePath { get; set; }
|
||||
public string ImageThumbnailPath { get; set; }
|
||||
}
|
||||
|
||||
public class ProductCategoryModel
|
||||
{
|
||||
public long CategoryId { get; set; }
|
||||
public string Title { get; set; }
|
||||
public List<CategoryNodeModel> Path { get; set; }
|
||||
}
|
||||
|
||||
public class CategoryNodeModel
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
public long? ParentId { get; set; }
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
using CMSMicroservice.Application.Common.Models;
|
||||
|
||||
namespace CMSMicroservice.Application.ProductsCQ.Queries.GetCustomerProductsByFilter;
|
||||
|
||||
public class GetCustomerProductsByFilterQuery : IRequest<GetCustomerProductsByFilterResponseDto>
|
||||
{
|
||||
public PaginationState? PaginationState { get; set; }
|
||||
public string? SortBy { get; set; }
|
||||
|
||||
// Filters
|
||||
public long? Id { get; set; }
|
||||
public string? Title { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? ShortInfomation { get; set; }
|
||||
public string? FullInformation { get; set; }
|
||||
public long? Price { get; set; }
|
||||
public int? Discount { get; set; }
|
||||
public int? Rate { get; set; }
|
||||
public string? ImagePath { get; set; }
|
||||
public string? ThumbnailPath { get; set; }
|
||||
public int? SaleCount { get; set; }
|
||||
public int? ViewCount { get; set; }
|
||||
public int? RemainingCount { get; set; }
|
||||
public List<long>? CategoryIds { get; set; }
|
||||
}
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
using CMSMicroservice.Application.Common.Extensions;
|
||||
using CMSMicroservice.Application.Common.Interfaces;
|
||||
using CMSMicroservice.Application.Common.Models;
|
||||
using CMSMicroservice.Domain.Entities;
|
||||
|
||||
namespace CMSMicroservice.Application.ProductsCQ.Queries.GetCustomerProductsByFilter;
|
||||
|
||||
public class GetCustomerProductsByFilterQueryHandler : IRequestHandler<GetCustomerProductsByFilterQuery, GetCustomerProductsByFilterResponseDto>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public GetCustomerProductsByFilterQueryHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetCustomerProductsByFilterResponseDto> Handle(GetCustomerProductsByFilterQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context.Products
|
||||
.AsNoTracking()
|
||||
.Include(x => x.ProductCategories)
|
||||
.ThenInclude(pc => pc.Category)
|
||||
.AsQueryable();
|
||||
|
||||
// Apply filters
|
||||
if (request.Id.HasValue)
|
||||
query = query.Where(x => x.Id == request.Id.Value);
|
||||
|
||||
if (!string.IsNullOrEmpty(request.Title))
|
||||
query = query.Where(x => x.Title.Contains(request.Title));
|
||||
|
||||
if (!string.IsNullOrEmpty(request.Description))
|
||||
query = query.Where(x => x.Description.Contains(request.Description));
|
||||
|
||||
if (!string.IsNullOrEmpty(request.ShortInfomation))
|
||||
query = query.Where(x => x.ShortInfomation.Contains(request.ShortInfomation));
|
||||
|
||||
if (!string.IsNullOrEmpty(request.FullInformation))
|
||||
query = query.Where(x => x.FullInformation.Contains(request.FullInformation));
|
||||
|
||||
if (request.Price.HasValue)
|
||||
query = query.Where(x => x.Price == request.Price.Value);
|
||||
|
||||
if (request.Discount.HasValue)
|
||||
query = query.Where(x => x.Discount == request.Discount.Value);
|
||||
|
||||
if (request.Rate.HasValue)
|
||||
query = query.Where(x => x.Rate == request.Rate.Value);
|
||||
|
||||
if (request.SaleCount.HasValue)
|
||||
query = query.Where(x => x.SaleCount == request.SaleCount.Value);
|
||||
|
||||
if (request.ViewCount.HasValue)
|
||||
query = query.Where(x => x.ViewCount == request.ViewCount.Value);
|
||||
|
||||
if (request.RemainingCount.HasValue)
|
||||
query = query.Where(x => x.RemainingCount == request.RemainingCount.Value);
|
||||
|
||||
if (request.CategoryIds != null && request.CategoryIds.Any())
|
||||
query = query.Where(x => x.ProductCategories.Any(pc => request.CategoryIds.Contains(pc.CategoryId)));
|
||||
|
||||
// Apply sorting
|
||||
if (!string.IsNullOrEmpty(request.SortBy))
|
||||
query = query.ApplyOrder(request.SortBy);
|
||||
else
|
||||
query = query.OrderByDescending(x => x.Created);
|
||||
|
||||
// Pagination
|
||||
var totalCount = await query.CountAsync(cancellationToken);
|
||||
|
||||
var paginationState = request.PaginationState ?? new PaginationState { PageNumber = 1, PageSize = 10 };
|
||||
var products = await query
|
||||
.Skip((paginationState.PageNumber - 1) * paginationState.PageSize)
|
||||
.Take(paginationState.PageSize)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
var metaData = new MetaData
|
||||
{
|
||||
TotalCount = totalCount,
|
||||
CurrentPage = paginationState.PageNumber,
|
||||
PageSize = paginationState.PageSize,
|
||||
TotalPage = (int)Math.Ceiling((double)totalCount / paginationState.PageSize),
|
||||
HasPrevious = paginationState.PageNumber > 1,
|
||||
HasNext = paginationState.PageNumber < (int)Math.Ceiling((double)totalCount / paginationState.PageSize)
|
||||
};
|
||||
|
||||
var models = products.Select(p => new CustomerProductModel
|
||||
{
|
||||
Id = p.Id,
|
||||
Title = p.Title,
|
||||
Description = p.Description,
|
||||
ShortInfomation = p.ShortInfomation,
|
||||
FullInformation = p.FullInformation,
|
||||
Price = p.Price,
|
||||
Discount = p.Discount,
|
||||
Rate = p.Rate,
|
||||
ImagePath = p.ImagePath,
|
||||
ThumbnailPath = p.ThumbnailPath,
|
||||
SaleCount = p.SaleCount,
|
||||
ViewCount = p.ViewCount,
|
||||
RemainingCount = p.RemainingCount,
|
||||
Categories = p.ProductCategories?.Select(pc => new ProductCategoryPathModel
|
||||
{
|
||||
CategoryId = pc.CategoryId,
|
||||
Title = pc.Category?.Title ?? string.Empty,
|
||||
Path = BuildCategoryPath(pc.Category)
|
||||
}).ToList() ?? new List<ProductCategoryPathModel>()
|
||||
}).ToList();
|
||||
|
||||
return new GetCustomerProductsByFilterResponseDto
|
||||
{
|
||||
MetaData = metaData,
|
||||
Models = models
|
||||
};
|
||||
}
|
||||
|
||||
private List<CategoryNodeItemModel> BuildCategoryPath(Category? category)
|
||||
{
|
||||
var path = new List<CategoryNodeItemModel>();
|
||||
|
||||
while (category != null)
|
||||
{
|
||||
path.Insert(0, new CategoryNodeItemModel
|
||||
{
|
||||
Id = category.Id,
|
||||
Title = category.Title,
|
||||
ParentId = category.ParentId
|
||||
});
|
||||
|
||||
// Move to parent
|
||||
if (category.ParentId.HasValue)
|
||||
{
|
||||
category = _context.Categories
|
||||
.AsNoTracking()
|
||||
.FirstOrDefault(c => c.Id == category.ParentId.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
category = null;
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
using CMSMicroservice.Application.Common.Models;
|
||||
|
||||
namespace CMSMicroservice.Application.ProductsCQ.Queries.GetCustomerProductsByFilter;
|
||||
|
||||
public class GetCustomerProductsByFilterResponseDto
|
||||
{
|
||||
public MetaData MetaData { get; set; }
|
||||
public List<CustomerProductModel> Models { get; set; }
|
||||
}
|
||||
|
||||
public class CustomerProductModel
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string ShortInfomation { get; set; }
|
||||
public string FullInformation { get; set; }
|
||||
public long Price { get; set; }
|
||||
public int Discount { get; set; }
|
||||
public int Rate { get; set; }
|
||||
public string ImagePath { get; set; }
|
||||
public string ThumbnailPath { get; set; }
|
||||
public int SaleCount { get; set; }
|
||||
public int ViewCount { get; set; }
|
||||
public int RemainingCount { get; set; }
|
||||
public List<ProductCategoryPathModel> Categories { get; set; }
|
||||
}
|
||||
|
||||
public class ProductCategoryPathModel
|
||||
{
|
||||
public long CategoryId { get; set; }
|
||||
public string Title { get; set; }
|
||||
public List<CategoryNodeItemModel> Path { get; set; }
|
||||
}
|
||||
|
||||
public class CategoryNodeItemModel
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
public long? ParentId { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user