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.PackageCQ.Queries.GetCustomerPackageDetails;
public class GetCustomerPackageDetailsQuery : IRequest<GetCustomerPackageDetailsResponseDto>
{
public long PackageId { get; set; }
}
@@ -0,0 +1,68 @@
using CMSMicroservice.Application.Common.Exceptions;
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Domain.Entities;
using Mapster;
namespace CMSMicroservice.Application.PackageCQ.Queries.GetCustomerPackageDetails;
public class GetCustomerPackageDetailsQueryHandler : IRequestHandler<GetCustomerPackageDetailsQuery, GetCustomerPackageDetailsResponseDto>
{
private readonly IApplicationDbContext _context;
public GetCustomerPackageDetailsQueryHandler(IApplicationDbContext context)
{
_context = context;
}
public async Task<GetCustomerPackageDetailsResponseDto> Handle(GetCustomerPackageDetailsQuery request, CancellationToken cancellationToken)
{
var package = await _context.Packages
.AsNoTracking()
.Where(x => x.Id == request.PackageId)
.ProjectToType<GetCustomerPackageDetailsResponseDto>()
.FirstOrDefaultAsync(cancellationToken);
if (package == null)
throw new NotFoundException(nameof(Package), request.PackageId);
// Add features based on package (this could be stored in DB in future)
package.Features = new List<PackageFeatureDto>
{
new PackageFeatureDto
{
Title = "درآمد کمیسیون",
Description = "دریافت کمیسیون از فروش محصولات",
Icon = "commission",
IsHighlighted = true
},
new PackageFeatureDto
{
Title = "پشتیبانی 24/7",
Description = "دسترسی به پشتیبانی در تمام ساعات شبانه روز",
Icon = "support",
IsHighlighted = false
},
new PackageFeatureDto
{
Title = "آموزش‌های تخصصی",
Description = "دسترسی به دوره‌های آموزشی و وبینارها",
Icon = "education",
IsHighlighted = true
}
};
// Set purchase requirements
package.Requirements = new PurchaseRequirementsDto
{
RequiresMembership = false,
MinimumWalletBalance = package.Price / 10, // 10% minimum
Restrictions = new List<string>
{
"باید حداقل 18 سال سن داشته باشید",
"تایید هویت الزامی است"
}
};
return package;
}
}
@@ -0,0 +1,27 @@
namespace CMSMicroservice.Application.PackageCQ.Queries.GetCustomerPackageDetails;
public class GetCustomerPackageDetailsResponseDto
{
public long Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public long Price { get; set; }
public string ImagePath { get; set; }
public List<PackageFeatureDto> Features { get; set; } = new();
public PurchaseRequirementsDto Requirements { get; set; }
}
public class PackageFeatureDto
{
public string Title { get; set; }
public string Description { get; set; }
public string Icon { get; set; }
public bool IsHighlighted { get; set; }
}
public class PurchaseRequirementsDto
{
public bool RequiresMembership { get; set; }
public long MinimumWalletBalance { get; set; }
public List<string> Restrictions { get; set; } = new();
}
@@ -0,0 +1,7 @@
namespace CMSMicroservice.Application.PackageCQ.Queries.GetCustomerPackages;
public class GetCustomerPackagesQuery : IRequest<List<GetCustomerPackagesResponseDto>>
{
public bool IncludeInactive { get; set; }
public int? PackageTypeFilter { get; set; }
}
@@ -0,0 +1,51 @@
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Domain.Entities;
using Mapster;
namespace CMSMicroservice.Application.PackageCQ.Queries.GetCustomerPackages;
public class GetCustomerPackagesQueryHandler : IRequestHandler<GetCustomerPackagesQuery, List<GetCustomerPackagesResponseDto>>
{
private readonly IApplicationDbContext _context;
public GetCustomerPackagesQueryHandler(IApplicationDbContext context)
{
_context = context;
}
public async Task<List<GetCustomerPackagesResponseDto>> Handle(GetCustomerPackagesQuery request, CancellationToken cancellationToken)
{
var query = _context.Packages
.AsNoTracking()
.AsQueryable();
// Filter by PackageType if specified
if (request.PackageTypeFilter.HasValue)
{
// Note: Package entity doesn't have PackageType enum, so we filter by convention
// Assuming Title or Description contains the package type indicator
// If Package entity needs PackageType field, it should be added to migration
}
// Get all packages (assuming all are available unless marked otherwise)
var packages = await query
.ProjectToType<GetCustomerPackagesResponseDto>()
.ToListAsync(cancellationToken);
// Map additional fields
foreach (var package in packages)
{
package.Name = package.Title;
package.ImageUrl = package.ImagePath;
package.Currency = "IRR";
package.IsAvailable = true;
package.ValidityDays = 365; // Default validity
package.IsPopular = false;
package.ShortDescription = package.Description?.Length > 100
? package.Description.Substring(0, 100) + "..."
: package.Description;
}
return packages;
}
}
@@ -0,0 +1,18 @@
namespace CMSMicroservice.Application.PackageCQ.Queries.GetCustomerPackages;
public class GetCustomerPackagesResponseDto
{
public long Id { get; set; }
public string Name { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public long Price { get; set; }
public string Currency { get; set; } = "IRR";
public int PackageType { get; set; }
public bool IsAvailable { get; set; } = true;
public string ImageUrl { get; set; }
public string ImagePath { get; set; }
public int ValidityDays { get; set; }
public bool IsPopular { get; set; }
public string ShortDescription { get; set; }
}
@@ -0,0 +1,12 @@
using CMSMicroservice.Application.Common.Models;
namespace CMSMicroservice.Application.PackageCQ.Queries.GetCustomerPurchaseHistory;
public class GetCustomerPurchaseHistoryQuery : IRequest<GetCustomerPurchaseHistoryResponseDto>
{
public long UserId { get; set; }
public PaginationState PaginationState { get; set; }
public int? PackageTypeFilter { get; set; }
public DateTime? FromDate { get; set; }
public DateTime? ToDate { get; set; }
}
@@ -0,0 +1,90 @@
using CMSMicroservice.Application.Common.Extensions;
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Application.Common.Models;
using CMSMicroservice.Domain.Enums;
using Mapster;
namespace CMSMicroservice.Application.PackageCQ.Queries.GetCustomerPurchaseHistory;
public class GetCustomerPurchaseHistoryQueryHandler : IRequestHandler<GetCustomerPurchaseHistoryQuery, GetCustomerPurchaseHistoryResponseDto>
{
private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
public GetCustomerPurchaseHistoryQueryHandler(
IApplicationDbContext context,
ICurrentUserService currentUser)
{
_context = context;
_currentUser = currentUser;
}
public async Task<GetCustomerPurchaseHistoryResponseDto> Handle(GetCustomerPurchaseHistoryQuery request, CancellationToken cancellationToken)
{
// Resolve UserId from JWT if not specified
var userId = request.UserId == 0
? (long.TryParse(_currentUser.UserId, out var currentUserId) ? currentUserId : 0)
: request.UserId;
if (userId == 0)
throw new UnauthorizedAccessException("User ID not found");
var query = _context.UserOrders
.AsNoTracking()
.Where(x => x.UserId == userId && x.PackageId != null)
.Include(x => x.Package)
.AsQueryable();
// Apply date filters if specified
if (request.FromDate.HasValue)
query = query.Where(x => x.Created >= request.FromDate.Value);
if (request.ToDate.HasValue)
query = query.Where(x => x.Created <= request.ToDate.Value);
// Apply PackageType filter if needed (Package entity doesn't have Type enum currently)
// This would require Package entity to have a PackageType field
// Order by most recent first
query = query.OrderByDescending(x => x.Created);
// Get metadata
var metaData = await query.GetMetaData(request.PaginationState, cancellationToken);
// Get paginated results
var orders = await query
.PaginatedListAsync(request.PaginationState)
.ToListAsync(cancellationToken);
var purchases = orders.Select(order => new PackagePurchaseHistoryDto
{
Id = order.Id,
PackageId = order.PackageId ?? 0,
PackageName = order.Package?.Title ?? "نامشخص",
Amount = order.Amount,
PackageType = 0, // Default, needs Package.PackageType field
PurchaseDate = order.Created,
ExpiryDate = order.PaymentDate?.AddDays(365), // Assuming 1 year validity
Status = order.PaymentStatus,
StatusMessage = GetStatusMessage(order.PaymentStatus),
ReferenceCode = order.Transaction?.RefId ?? order.Id.ToString()
}).ToList();
return new GetCustomerPurchaseHistoryResponseDto
{
MetaData = metaData,
Purchases = purchases
};
}
private string GetStatusMessage(PaymentStatus status)
{
return status switch
{
PaymentStatus.Pending => "در انتظار پرداخت",
PaymentStatus.Success => "فعال",
PaymentStatus.Reject => "رد شده",
_ => "نامشخص"
};
}
}
@@ -0,0 +1,24 @@
using CMSMicroservice.Application.Common.Models;
using CMSMicroservice.Domain.Enums;
namespace CMSMicroservice.Application.PackageCQ.Queries.GetCustomerPurchaseHistory;
public class GetCustomerPurchaseHistoryResponseDto
{
public MetaData MetaData { get; set; }
public List<PackagePurchaseHistoryDto> Purchases { get; set; } = new();
}
public class PackagePurchaseHistoryDto
{
public long Id { get; set; }
public long PackageId { get; set; }
public string PackageName { get; set; }
public long Amount { get; set; }
public int PackageType { get; set; }
public DateTime PurchaseDate { get; set; }
public DateTime? ExpiryDate { get; set; }
public PaymentStatus Status { get; set; }
public string StatusMessage { get; set; }
public string ReferenceCode { get; set; }
}