96 lines
3.7 KiB
C#
96 lines
3.7 KiB
C#
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
|
|
};
|
|
}
|
|
}
|