feat: Implement Approve and Reject Withdrawal commands with handlers

This commit is contained in:
masoodafar-web
2025-12-01 16:48:07 +03:30
parent 8d31a8c026
commit 4aaf2247ff
27 changed files with 989 additions and 1 deletions
@@ -0,0 +1,6 @@
namespace CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubStatistics;
public class GetClubStatisticsQuery : IRequest<GetClubStatisticsResponseDto>
{
// No parameters - returns overall statistics
}
@@ -0,0 +1,95 @@
namespace CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubStatistics;
public class GetClubStatisticsQueryHandler : IRequestHandler<GetClubStatisticsQuery, GetClubStatisticsResponseDto>
{
private readonly IApplicationDbContext _context;
public GetClubStatisticsQueryHandler(IApplicationDbContext context)
{
_context = context;
}
public async Task<GetClubStatisticsResponseDto> Handle(GetClubStatisticsQuery request, CancellationToken cancellationToken)
{
var now = DateTime.UtcNow;
// Basic statistics
var totalMembers = await _context.ClubMemberships.CountAsync(cancellationToken);
var activeMembers = await _context.ClubMemberships
.Where(x => x.IsActive)
.CountAsync(cancellationToken);
var inactiveMembers = totalMembers - activeMembers;
var expiredMembers = 0; // Since there's no expiration tracking in the model
double activePercentage = totalMembers > 0 ? (activeMembers / (double)totalMembers) * 100 : 0;
// Package distribution - ClubMembership doesn't have PackageId
// We'll return empty list for now or create mock data
var packageDistribution = new List<PackageLevelDistributionModel>();
// Monthly trend (last 6 months)
var sixMonthsAgo = now.AddMonths(-6);
var activations = await _context.ClubMemberships
.Where(x => x.ActivatedAt >= sixMonthsAgo && x.ActivatedAt != null)
.GroupBy(x => new { x.ActivatedAt!.Value.Year, x.ActivatedAt.Value.Month })
.Select(g => new { g.Key.Year, g.Key.Month, Count = g.Count() })
.ToListAsync(cancellationToken);
var monthlyTrend = new List<MonthlyMembershipTrendModel>();
for (int i = 5; i >= 0; i--)
{
var targetDate = now.AddMonths(-i);
var year = targetDate.Year;
var month = targetDate.Month;
var activationCount = activations.FirstOrDefault(x => x.Year == year && x.Month == month)?.Count ?? 0;
monthlyTrend.Add(new MonthlyMembershipTrendModel
{
Month = $"{year}-{month:D2}",
Activations = activationCount,
Expirations = 0, // No expiration tracking
NetChange = activationCount
});
}
// Total revenue - sum of initial contributions
var totalRevenue = await _context.ClubMemberships
.SumAsync(x => x.InitialContribution, cancellationToken);
// Average membership duration - calculate from ActivatedAt to now
var activeMemberships = await _context.ClubMemberships
.Where(x => x.IsActive && x.ActivatedAt != null)
.Select(x => x.ActivatedAt!.Value)
.ToListAsync(cancellationToken);
double averageDuration = 0;
if (activeMemberships.Any())
{
var durations = activeMemberships
.Select(activatedAt => (now - activatedAt).TotalDays)
.ToList();
averageDuration = durations.Average();
}
// Expiring soon count - not applicable since no expiration tracking
int expiringSoonCount = 0;
return new GetClubStatisticsResponseDto
{
TotalMembers = totalMembers,
ActiveMembers = activeMembers,
InactiveMembers = inactiveMembers,
ExpiredMembers = expiredMembers,
ActivePercentage = activePercentage,
PackageDistribution = packageDistribution,
MonthlyTrend = monthlyTrend,
TotalRevenue = totalRevenue,
AverageMembershipDurationDays = averageDuration,
ExpiringSoonCount = expiringSoonCount
};
}
}
@@ -0,0 +1,31 @@
namespace CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubStatistics;
public class GetClubStatisticsResponseDto
{
public int TotalMembers { get; set; }
public int ActiveMembers { get; set; }
public int InactiveMembers { get; set; }
public int ExpiredMembers { get; set; }
public double ActivePercentage { get; set; }
public List<PackageLevelDistributionModel> PackageDistribution { get; set; } = new();
public List<MonthlyMembershipTrendModel> MonthlyTrend { get; set; } = new();
public long TotalRevenue { get; set; }
public double AverageMembershipDurationDays { get; set; }
public int ExpiringSoonCount { get; set; }
}
public class PackageLevelDistributionModel
{
public long PackageId { get; set; }
public string PackageName { get; set; } = string.Empty;
public int MemberCount { get; set; }
public double Percentage { get; set; }
}
public class MonthlyMembershipTrendModel
{
public string Month { get; set; } = string.Empty;
public int Activations { get; set; }
public int Expirations { get; set; }
public int NetChange { get; set; }
}