Files
CMS/src/CMSMicroservice.Application/CommissionCQ/Queries/GetAvailableWeeks/GetAvailableWeeksQueryHandler.cs

133 lines
5.0 KiB
C#

using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Domain.Enums;
using Microsoft.EntityFrameworkCore;
using System.Globalization;
namespace CMSMicroservice.Application.CommissionCQ.Queries.GetAvailableWeeks;
public class GetAvailableWeeksQueryHandler : IRequestHandler<GetAvailableWeeksQuery, GetAvailableWeeksResponseDto>
{
private readonly IApplicationDbContext _context;
public GetAvailableWeeksQueryHandler(IApplicationDbContext context)
{
_context = context;
}
public async Task<GetAvailableWeeksResponseDto> Handle(
GetAvailableWeeksQuery request,
CancellationToken cancellationToken)
{
var currentDate = DateTime.Now;
var currentWeekNumber = GetWeekNumber(currentDate);
// دریافت هفته‌های محاسبه شده از دیتابیس
var calculatedPools = await _context.WeeklyCommissionPools
.Where(p => p.IsCalculated)
.OrderByDescending(p => p.WeekNumber)
.Take(request.PastWeeksCount)
.ToListAsync(cancellationToken);
// دریافت لاگ‌های اجرا
var executionLogs = await _context.WorkerExecutionLogs
.Where(log => log.Status == WorkerExecutionStatus.Success ||
log.Status == WorkerExecutionStatus.Failed)
.GroupBy(log => log.WeekNumber)
.Select(g => new
{
WeekNumber = g.Key,
LastLog = g.OrderByDescending(l => l.StartedAt).First()
})
.ToDictionaryAsync(x => x.WeekNumber, x => x.LastLog, cancellationToken);
var allWeeks = new List<WeekInfoDto>();
// هفته جاری
var currentWeekInfo = CreateWeekInfo(currentDate, currentWeekNumber, calculatedPools, executionLogs);
// هفته‌های گذشته (12 هفته)
var pastWeeks = new List<WeekInfoDto>();
for (int i = 1; i <= request.PastWeeksCount; i++)
{
var pastDate = currentDate.AddDays(-7 * i);
var weekNumber = GetWeekNumber(pastDate);
pastWeeks.Add(CreateWeekInfo(pastDate, weekNumber, calculatedPools, executionLogs));
}
// هفته‌های آینده (4 هفته)
var futureWeeks = new List<WeekInfoDto>();
for (int i = 1; i <= request.FutureWeeksCount; i++)
{
var futureDate = currentDate.AddDays(7 * i);
var weekNumber = GetWeekNumber(futureDate);
futureWeeks.Add(CreateWeekInfo(futureDate, weekNumber, calculatedPools, executionLogs));
}
// تفکیک به calculated و pending
var calculatedWeeks = pastWeeks.Where(w => w.IsCalculated).ToList();
var pendingWeeks = pastWeeks.Where(w => !w.IsCalculated).ToList();
return new GetAvailableWeeksResponseDto
{
CurrentWeek = currentWeekInfo,
CalculatedWeeks = calculatedWeeks,
PendingWeeks = pendingWeeks,
FutureWeeks = futureWeeks
};
}
private WeekInfoDto CreateWeekInfo(
DateTime date,
string weekNumber,
List<Domain.Entities.Commission.WeeklyCommissionPool> calculatedPools,
Dictionary<string, Domain.Entities.Commission.WorkerExecutionLog> executionLogs)
{
var (startDate, endDate) = GetWeekRange(date);
var pool = calculatedPools.FirstOrDefault(p => p.WeekNumber == weekNumber);
var log = executionLogs.GetValueOrDefault(weekNumber);
var isCalculated = pool != null && pool.IsCalculated;
var displayText = $"{weekNumber} ({startDate:yyyy/MM/dd} - {endDate:yyyy/MM/dd})";
if (isCalculated)
{
displayText += " ✅ محاسبه شده";
}
return new WeekInfoDto
{
WeekNumber = weekNumber,
StartDate = startDate,
EndDate = endDate,
IsCalculated = isCalculated,
CalculatedAt = pool?.CalculatedAt,
LastExecutionStatus = log?.Status.ToString(),
TotalPoolAmount = pool?.TotalPoolAmount,
EligibleUsersCount = pool?.UserCommissionPayouts?.Count ?? 0,
DisplayText = displayText
};
}
private static string GetWeekNumber(DateTime date)
{
var calendar = CultureInfo.InvariantCulture.Calendar;
var weekOfYear = calendar.GetWeekOfYear(
date,
CalendarWeekRule.FirstFourDayWeek,
DayOfWeek.Monday);
return $"{date.Year}-W{weekOfYear:D2}";
}
private static (DateTime startDate, DateTime endDate) GetWeekRange(DateTime date)
{
var dayOfWeek = (int)date.DayOfWeek;
var daysToMonday = dayOfWeek == 0 ? 6 : dayOfWeek - 1; // اگر یکشنبه باشد، 6 روز عقب برو
var startDate = date.Date.AddDays(-daysToMonday);
var endDate = startDate.AddDays(6);
return (startDate, endDate);
}
}