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:
masoodafar-web
2026-02-05 23:01:50 +03:30
parent b41342dcad
commit b2d676b555
96 changed files with 4822 additions and 589 deletions
@@ -0,0 +1,6 @@
namespace CMSMicroservice.Application.ProductsCQ.Queries.GetCustomerProducts;
public class GetCustomerProductsQuery : IRequest<GetCustomerProductsResponseDto>
{
public long Id { get; set; }
}
@@ -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;
}
}
@@ -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; }
}
@@ -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; }
}
@@ -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;
}
}
@@ -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; }
}