feat: refactor week number handling to use WeekDefinitionId across multiple entities and queries

This commit is contained in:
masoodafar-web
2025-12-19 10:41:22 +03:30
parent 3cb95dc349
commit 8b784101be
83 changed files with 17592 additions and 566 deletions
@@ -8,12 +8,12 @@ public record GetAllWeeklyPoolsQuery : IRequest<GetAllWeeklyPoolsResponseDto>
/// <summary>
/// از هفته (فیلتر اختیاری)
/// </summary>
public string? FromWeek { get; init; }
public int? FromWeekOrder { get; init; }
/// <summary>
/// تا هفته (فیلتر اختیاری)
/// </summary>
public string? ToWeek { get; init; }
public int? ToWeekOrder { get; init; }
/// <summary>
/// فقط Pool های محاسبه شده
@@ -3,25 +3,31 @@ namespace CMSMicroservice.Application.CommissionCQ.Queries.GetAllWeeklyPools;
public class GetAllWeeklyPoolsQueryHandler : IRequestHandler<GetAllWeeklyPoolsQuery, GetAllWeeklyPoolsResponseDto>
{
private readonly IApplicationDbContext _context;
private readonly IWeekDefinitionRepository _weekDefinitionRepository;
public GetAllWeeklyPoolsQueryHandler(IApplicationDbContext context)
public GetAllWeeklyPoolsQueryHandler(
IApplicationDbContext context,
IWeekDefinitionRepository weekDefinitionRepository)
{
_context = context;
_weekDefinitionRepository = weekDefinitionRepository;
}
public async Task<GetAllWeeklyPoolsResponseDto> Handle(GetAllWeeklyPoolsQuery request, CancellationToken cancellationToken)
{
var query = _context.WeeklyCommissionPools.AsNoTracking();
var query = _context.WeeklyCommissionPools
.Include(i=> i.WeekDefinition)
.AsNoTracking();
// Apply filters
if (!string.IsNullOrWhiteSpace(request.FromWeek))
if (request.FromWeekOrder!=null)
{
query = query.Where(x => string.Compare(x.WeekNumber, request.FromWeek) >= 0);
query = query.Where(x => x.WeekDefinition.WeekOrder>=request.FromWeekOrder );
}
if (!string.IsNullOrWhiteSpace(request.ToWeek))
if (request.ToWeekOrder!=null)
{
query = query.Where(x => string.Compare(x.WeekNumber, request.ToWeek) <= 0);
query = query.Where(x =>x.WeekDefinition.WeekOrder<= request.ToWeekOrder);
}
if (request.OnlyCalculated.HasValue && request.OnlyCalculated.Value)
@@ -30,7 +36,7 @@ public class GetAllWeeklyPoolsQueryHandler : IRequestHandler<GetAllWeeklyPoolsQu
}
// Order by week number descending (newest first)
query = query.OrderByDescending(x => x.WeekNumber);
query = query.OrderByDescending(x => x.WeekDefinitionId);
// Count total
var totalCount = await query.CountAsync(cancellationToken);
@@ -42,7 +48,8 @@ public class GetAllWeeklyPoolsQueryHandler : IRequestHandler<GetAllWeeklyPoolsQu
.Select(x => new WeeklyCommissionPoolDto
{
Id = x.Id,
WeekNumber = x.WeekNumber,
WeekDefinitionId = x.WeekDefinitionId,
WeekDisplayName = x.WeekDefinition.PersianWeekNumber,
TotalPoolAmount = x.TotalPoolAmount,
TotalBalances = x.TotalBalances,
ValuePerBalance = x.ValuePerBalance,
@@ -52,6 +59,19 @@ public class GetAllWeeklyPoolsQueryHandler : IRequestHandler<GetAllWeeklyPoolsQu
})
.ToListAsync(cancellationToken);
// Populate WeekDisplayName from cache
// foreach (var pool in pools)
// {
// // WeeklyCommissionPoolDto is a record, need to create new instance with display name
// // Since records are immutable, we can't modify them directly
// }
// // Create new list with WeekDisplayName populated
// var poolsWithDisplayName = pools.Select(p => p with
// {
// WeekDisplayName = _weekDefinitionRepository.GetDisplayNameByGregorianWeekNumber(p.WeekNumber)
// }).ToList();
return new GetAllWeeklyPoolsResponseDto
{
MetaData = new MetaDataDto
@@ -9,7 +9,8 @@ public record GetAllWeeklyPoolsResponseDto
public record WeeklyCommissionPoolDto
{
public long Id { get; init; }
public string WeekNumber { get; init; } = string.Empty;
public long WeekDefinitionId { get; init; }
public string WeekDisplayName { get; init; } = string.Empty;
public long TotalPoolAmount { get; init; }
public int TotalBalances { get; init; }
public long ValuePerBalance { get; init; }
@@ -2,29 +2,36 @@ using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Domain.Enums;
using Microsoft.EntityFrameworkCore;
using System.Globalization;
using DateTimeConverterCL;
namespace CMSMicroservice.Application.CommissionCQ.Queries.GetAvailableWeeks;
public class GetAvailableWeeksQueryHandler : IRequestHandler<GetAvailableWeeksQuery, GetAvailableWeeksResponseDto>
{
private readonly IApplicationDbContext _context;
private readonly IWeekDefinitionRepository _weekDefinitionRepository;
public GetAvailableWeeksQueryHandler(IApplicationDbContext context)
public GetAvailableWeeksQueryHandler(
IApplicationDbContext context,
IWeekDefinitionRepository weekDefinitionRepository)
{
_context = context;
_weekDefinitionRepository = weekDefinitionRepository;
}
public async Task<GetAvailableWeeksResponseDto> Handle(
GetAvailableWeeksQuery request,
CancellationToken cancellationToken)
{
var currentDate = DateTime.Now;
var currentWeekNumber = GetWeekNumber(currentDate);
var currentWeekDef = _weekDefinitionRepository.GetCurrentWeek();
// var currentWeekNumber = currentWeekDef != null
// ? $"{currentWeekDef.GregorianYear}-W{currentWeekDef.GregorianWeekNumber:D2}"
// : _weekDefinitionRepository.CalculateGregorianWeekNumber(DateTime.Now);
// دریافت هفته‌های محاسبه شده از دیتابیس
var calculatedPools = await _context.WeeklyCommissionPools
.Where(p => p.IsCalculated)
.OrderByDescending(p => p.WeekNumber)
.OrderByDescending(p => p.WeekDefinitionId)
.Take(request.PastWeeksCount)
.ToListAsync(cancellationToken);
@@ -32,7 +39,7 @@ public class GetAvailableWeeksQueryHandler : IRequestHandler<GetAvailableWeeksQu
var executionLogs = await _context.WorkerExecutionLogs
.Where(log => log.Status == WorkerExecutionStatus.Success ||
log.Status == WorkerExecutionStatus.Failed)
.GroupBy(log => log.WeekNumber)
.GroupBy(log => log.WeekDefinitionId)
.Select(g => new
{
WeekNumber = g.Key,
@@ -43,15 +50,16 @@ public class GetAvailableWeeksQueryHandler : IRequestHandler<GetAvailableWeeksQu
var allWeeks = new List<WeekInfoDto>();
// هفته جاری
var currentWeekInfo = CreateWeekInfo(currentDate, currentWeekNumber, calculatedPools, executionLogs);
var currentDate = DateTime.Now;
var currentWeekInfo = CreateWeekInfo(currentDate, currentWeekDef.Id, 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));
var weekNumber = GetWeekNumberUsingRepository(pastDate);
pastWeeks.Add(CreateWeekInfo(pastDate, currentWeekDef.Id, calculatedPools, executionLogs));
}
// هفته‌های آینده (4 هفته)
@@ -59,8 +67,8 @@ public class GetAvailableWeeksQueryHandler : IRequestHandler<GetAvailableWeeksQu
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));
var weekNumber = GetWeekNumberUsingRepository(futureDate);
futureWeeks.Add(CreateWeekInfo(futureDate, currentWeekDef.Id, calculatedPools, executionLogs));
}
// تفکیک به calculated و pending
@@ -76,26 +84,54 @@ public class GetAvailableWeeksQueryHandler : IRequestHandler<GetAvailableWeeksQu
};
}
private string GetWeekNumberUsingRepository(DateTime date)
{
var weekDef = _weekDefinitionRepository.GetWeekByDate(date);
if (weekDef != null)
{
return $"{weekDef.GregorianYear}-W{weekDef.GregorianWeekNumber:D2}";
}
// Fallback to manual calculation if not in cache
return _weekDefinitionRepository.CalculateGregorianWeekNumber(date);
}
private WeekInfoDto CreateWeekInfo(
DateTime date,
string weekNumber,
long weekDefinitionId,
List<Domain.Entities.Commission.WeeklyCommissionPool> calculatedPools,
Dictionary<string, Domain.Entities.Commission.WorkerExecutionLog> executionLogs)
Dictionary<long, Domain.Entities.Commission.WorkerExecutionLog> executionLogs)
{
// Get the actual WeekDefinition for this date
var weekDef = _weekDefinitionRepository.GetWeekByDate(date);
var actualWeekDefId = weekDef?.Id ?? weekDefinitionId;
var (startDate, endDate) = GetWeekRange(date);
var pool = calculatedPools.FirstOrDefault(p => p.WeekNumber == weekNumber);
var log = executionLogs.GetValueOrDefault(weekNumber);
var pool = calculatedPools.FirstOrDefault(p => p.WeekDefinitionId == actualWeekDefId);
var log = executionLogs.GetValueOrDefault(actualWeekDefId);
var isCalculated = pool != null && pool.IsCalculated;
//
// // تبدیل تاریخ به شمسی برای نمایش
// var persianCalendar = new PersianCalendar();
// var startDatePersian = $"{persianCalendar.GetYear(startDate):D4}/{persianCalendar.GetMonth(startDate):D2}/{persianCalendar.GetDayOfMonth(startDate):D2}";
// var endDatePersian = $"{persianCalendar.GetYear(endDate):D4}/{persianCalendar.GetMonth(endDate):D2}/{persianCalendar.GetDayOfMonth(endDate):D2}";
// تبدیل تاریخ به شمسی برای نمایش
var persianCalendar = new PersianCalendar();
var startDatePersian = $"{persianCalendar.GetYear(startDate):D4}/{persianCalendar.GetMonth(startDate):D2}/{persianCalendar.GetDayOfMonth(startDate):D2}";
var endDatePersian = $"{persianCalendar.GetYear(endDate):D4}/{persianCalendar.GetMonth(endDate):D2}/{persianCalendar.GetDayOfMonth(endDate):D2}";
// استفاده از DisplayName از WeekDefinition
var displayName = weekDef?.DisplayName ?? GetDisplayName(startDate);
string displayText;
// تبدیل weekNumber به شمسی فقط برای نمایش
var persianWeekNumber = ConvertWeekNumberToPersian(weekNumber, startDate);
var displayText = $"{persianWeekNumber} ({startDatePersian} - {endDatePersian})";
if (!string.IsNullOrEmpty(displayName))
{
// اگر DisplayName وجود داشت، از آن استفاده کن
displayText = $"{displayName} ({startDate.MiladiToJalali()} - {endDate.MiladiToJalali()})";
}
else
{
// تبدیل weekNumber به شمسی فقط برای نمایش (fallback)
var persianWeekNumber = _weekDefinitionRepository.GetWeekById(actualWeekDefId);
displayText = $"{persianWeekNumber?.PersianWeekNumber} ({startDate.MiladiToJalali()} - {endDate.MiladiToJalali()})";
}
if (isCalculated)
{
@@ -104,7 +140,8 @@ public class GetAvailableWeeksQueryHandler : IRequestHandler<GetAvailableWeeksQu
return new WeekInfoDto
{
WeekNumber = weekNumber, // میلادی (برای API)
WeekDefinitionId = actualWeekDefId,
DisplayName = weekDef?.DisplayName ?? _weekDefinitionRepository.GetWeekById(actualWeekDefId)?.DisplayName ?? "", // میلادی (برای API)
StartDate = startDate,
EndDate = endDate,
IsCalculated = isCalculated,
@@ -116,40 +153,16 @@ public class GetAvailableWeeksQueryHandler : IRequestHandler<GetAvailableWeeksQu
};
}
private static string GetWeekNumber(DateTime date)
private (DateTime startDate, DateTime endDate) GetWeekRange(DateTime date)
{
var year = date.Year;
// پیدا کردن اولین شنبه سال
var jan1 = new DateTime(year, 1, 1);
var jan1DayOfWeek = (int)jan1.DayOfWeek; // 0=Sunday, 1=Monday, ..., 6=Saturday
// محاسبه تعداد روزهایی که باید اضافه کنیم تا به اولین شنبه برسیم
var daysToFirstSaturday = jan1DayOfWeek == 6 ? 0 : (6 - jan1DayOfWeek + 7) % 7;
var firstSaturday = jan1.AddDays(daysToFirstSaturday);
// پیدا کردن شنبه شروع هفته جاری
var currentDayOfWeek = (int)date.DayOfWeek; // 0=Sun, 1=Mon, ..., 6=Sat
var daysToCurrentSaturday = currentDayOfWeek == 6 ? 0 : (currentDayOfWeek + 1) % 7;
var weekStartSaturday = date.Date.AddDays(-daysToCurrentSaturday);
// محاسبه شماره هفته
int weekNum;
if (weekStartSaturday < firstSaturday)
// First try to get from repository
var weekDef = _weekDefinitionRepository.GetWeekByDate(date);
if (weekDef != null)
{
weekNum = 1; // هفته اول سال
}
else
{
var daysSinceFirstSaturday = (weekStartSaturday - firstSaturday).Days;
weekNum = (daysSinceFirstSaturday / 7) + 1;
return (weekDef.StartDate, weekDef.EndDate);
}
return $"{year}-W{weekNum:D2}";
}
private static (DateTime startDate, DateTime endDate) GetWeekRange(DateTime date)
{
// Fallback: manual calculation
var dayOfWeek = (int)date.DayOfWeek;
// محاسبه تعداد روزهایی که باید عقب برویم تا به شنبه برسیم
// شنبه = 6, یکشنبه = 0, دوشنبه = 1, ..., جمعه = 5
@@ -161,32 +174,38 @@ public class GetAvailableWeeksQueryHandler : IRequestHandler<GetAvailableWeeksQu
return (startDate, endDate);
}
private static string ConvertWeekNumberToPersian(string gregorianWeekNumber, DateTime weekStartDate)
private string GetDisplayName(DateTime date)
{
// ورودی: "2025-W48"
var persianCalendar = new PersianCalendar();
var persianYear = persianCalendar.GetYear(weekStartDate);
// محاسبه شماره هفته شمسی
var jan1Persian = persianCalendar.ToDateTime(persianYear, 1, 1, 0, 0, 0, 0);
// پیدا کردن اولین شنبه سال شمسی
var jan1DayOfWeek = (int)jan1Persian.DayOfWeek;
var daysToFirstSaturday = jan1DayOfWeek == 6 ? 0 : (6 - jan1DayOfWeek + 7) % 7;
var firstSaturday = jan1Persian.AddDays(daysToFirstSaturday);
// محاسبه شماره هفته
int weekNum;
if (weekStartDate < firstSaturday)
{
weekNum = 1;
}
else
{
var daysSinceFirstSaturday = (weekStartDate - firstSaturday).Days;
weekNum = (daysSinceFirstSaturday / 7) + 1;
}
return $"{persianYear}-W{weekNum:D2}";
var weekDef = _weekDefinitionRepository.GetWeekByDate(date);
return weekDef?.DisplayName ?? "";
}
// private static string ConvertWeekNumberToPersian(string gregorianWeekNumber, DateTime weekStartDate)
// {
// // ورودی: "2025-W48"
// var persianCalendar = new PersianCalendar();
// var persianYear = persianCalendar.GetYear(weekStartDate);
//
// // محاسبه شماره هفته شمسی
// var jan1Persian = persianCalendar.ToDateTime(persianYear, 1, 1, 0, 0, 0, 0);
//
// // پیدا کردن اولین شنبه سال شمسی
// var jan1DayOfWeek = (int)jan1Persian.DayOfWeek;
// var daysToFirstSaturday = jan1DayOfWeek == 6 ? 0 : (6 - jan1DayOfWeek + 7) % 7;
// var firstSaturday = jan1Persian.AddDays(daysToFirstSaturday);
//
// // محاسبه شماره هفته
// int weekNum;
// if (weekStartDate < firstSaturday)
// {
// weekNum = 1;
// }
// else
// {
// var daysSinceFirstSaturday = (weekStartDate - firstSaturday).Days;
// weekNum = (daysSinceFirstSaturday / 7) + 1;
// }
//
// return $"{persianYear}-W{weekNum:D2}";
// }
}
@@ -17,8 +17,11 @@ public class GetAvailableWeeksResponseDto
public class WeekInfoDto
{
/// <summary>شناسه یکتای هفته</summary>
public required long WeekDefinitionId { get; init; }
/// <summary>شماره هفته (YYYY-Www)</summary>
public required string WeekNumber { get; init; }
public required string DisplayName { get; init; }
/// <summary>تاریخ شروع هفته</summary>
public required DateTime StartDate { get; init; }
@@ -18,7 +18,7 @@ public record GetCommissionPayoutHistoryQuery : IRequest<GetCommissionPayoutHist
/// <summary>
/// شماره هفته (اختیاری)
/// </summary>
public string? WeekNumber { get; init; }
public long? WeekDefinitionId { get; init; }
/// <summary>
/// مرتب‌سازی
@@ -3,15 +3,20 @@ namespace CMSMicroservice.Application.CommissionCQ.Queries.GetCommissionPayoutHi
public class GetCommissionPayoutHistoryQueryHandler : IRequestHandler<GetCommissionPayoutHistoryQuery, GetCommissionPayoutHistoryResponseDto>
{
private readonly IApplicationDbContext _context;
private readonly IWeekDefinitionRepository _weekDefinitionRepository;
public GetCommissionPayoutHistoryQueryHandler(IApplicationDbContext context)
public GetCommissionPayoutHistoryQueryHandler(
IApplicationDbContext context,
IWeekDefinitionRepository weekDefinitionRepository)
{
_context = context;
_weekDefinitionRepository = weekDefinitionRepository;
}
public async Task<GetCommissionPayoutHistoryResponseDto> Handle(GetCommissionPayoutHistoryQuery request, CancellationToken cancellationToken)
{
var query = _context.CommissionPayoutHistories
.Include(i=>i.WeekDefinition)
.AsNoTracking()
.AsQueryable();
@@ -26,9 +31,9 @@ public class GetCommissionPayoutHistoryQueryHandler : IRequestHandler<GetCommiss
query = query.Where(x => x.UserId == request.UserId.Value);
}
if (!string.IsNullOrEmpty(request.WeekNumber))
if (request.WeekDefinitionId!=null)
{
query = query.Where(x => x.WeekNumber == request.WeekNumber);
query = query.Where(x => x.WeekDefinitionId == request.WeekDefinitionId);
}
query = query.ApplyOrder(sortBy: request.SortBy ?? "Created");
@@ -42,7 +47,8 @@ public class GetCommissionPayoutHistoryQueryHandler : IRequestHandler<GetCommiss
Id = x.Id,
UserCommissionPayoutId = x.UserCommissionPayoutId,
UserId = x.UserId,
WeekNumber = x.WeekNumber,
WeekDefinitionId = x.WeekDefinitionId,
WeekDisplayName=x.WeekDefinition!.DisplayName,
AmountBefore = x.AmountBefore,
AmountAfter = x.AmountAfter,
OldStatus = x.OldStatus,
@@ -54,6 +60,12 @@ public class GetCommissionPayoutHistoryQueryHandler : IRequestHandler<GetCommiss
})
.ToListAsync(cancellationToken);
// // Populate WeekDisplayName from cache
// foreach (var model in models)
// {
// model.WeekDisplayName = _weekDefinitionRepository.GetDisplayNameByGregorianWeekNumber(model.WeekNumber);
// }
return new GetCommissionPayoutHistoryResponseDto
{
MetaData = meta,
@@ -13,11 +13,10 @@ public class GetCommissionPayoutHistoryQueryValidator : AbstractValidator<GetCom
.GreaterThan(0)
.WithMessage("شناسه کاربر معتبر نیست")
.When(x => x.UserId.HasValue);
RuleFor(x => x.WeekNumber)
.Matches(@"^\d{4}-W\d{2}$")
.WithMessage("فرمت شماره هفته باید YYYY-Www باشد")
.When(x => !string.IsNullOrEmpty(x.WeekNumber));
RuleFor(x => x.WeekDefinitionId)
.NotNull()
.GreaterThan(0)
.WithMessage("شماره هفته نمی‌تواند خالی باشد");
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
@@ -11,7 +11,8 @@ public class GetCommissionPayoutHistoryResponseModel
public long Id { get; set; }
public long UserCommissionPayoutId { get; set; }
public long UserId { get; set; }
public string WeekNumber { get; set; } = string.Empty;
public long WeekDefinitionId { get; set; }
public string WeekDisplayName { get; set; } = string.Empty;
public long AmountBefore { get; set; }
public long AmountAfter { get; set; }
public CommissionPayoutStatus? OldStatus { get; set; }
@@ -18,7 +18,7 @@ public record GetUserCommissionPayoutsQuery : IRequest<GetUserCommissionPayoutsR
/// <summary>
/// شماره هفته (اختیاری)
/// </summary>
public string? WeekNumber { get; init; }
public long? WeekDefinitionId { get; init; }
/// <summary>
/// مرتب‌سازی
@@ -3,15 +3,20 @@ namespace CMSMicroservice.Application.CommissionCQ.Queries.GetUserCommissionPayo
public class GetUserCommissionPayoutsQueryHandler : IRequestHandler<GetUserCommissionPayoutsQuery, GetUserCommissionPayoutsResponseDto>
{
private readonly IApplicationDbContext _context;
private readonly IWeekDefinitionRepository _weekDefinitionRepository;
public GetUserCommissionPayoutsQueryHandler(IApplicationDbContext context)
public GetUserCommissionPayoutsQueryHandler(
IApplicationDbContext context,
IWeekDefinitionRepository weekDefinitionRepository)
{
_context = context;
_weekDefinitionRepository = weekDefinitionRepository;
}
public async Task<GetUserCommissionPayoutsResponseDto> Handle(GetUserCommissionPayoutsQuery request, CancellationToken cancellationToken)
{
var query = _context.UserCommissionPayouts
.Include(x => x.WeekDefinition)
.Include(x => x.User)
.AsNoTracking()
.AsQueryable();
@@ -27,9 +32,9 @@ public class GetUserCommissionPayoutsQueryHandler : IRequestHandler<GetUserCommi
query = query.Where(x => x.Status == request.Status.Value);
}
if (!string.IsNullOrEmpty(request.WeekNumber))
if (request.WeekDefinitionId!=null)
{
query = query.Where(x => x.WeekNumber == request.WeekNumber);
query = query.Where(x => x.WeekDefinitionId == request.WeekDefinitionId);
}
query = query.ApplyOrder(sortBy: request.SortBy ?? "Created");
@@ -44,7 +49,8 @@ public class GetUserCommissionPayoutsQueryHandler : IRequestHandler<GetUserCommi
UserId = x.UserId,
FirstName = x.User.FirstName,
LastName = x.User.LastName,
WeekNumber = x.WeekNumber,
WeekDefinitionId = x.WeekDefinitionId,
WeekDisplayName = x.WeekDefinition != null ? x.WeekDefinition.DisplayName : "",
WeeklyPoolId = x.WeeklyPoolId,
BalancesEarned = x.BalancesEarned,
ValuePerBalance = x.ValuePerBalance,
@@ -58,6 +64,12 @@ public class GetUserCommissionPayoutsQueryHandler : IRequestHandler<GetUserCommi
})
.ToListAsync(cancellationToken);
// // Populate WeekDisplayName from cache
// foreach (var model in models)
// {
// model.WeekDisplayName = _weekDefinitionRepository.GetDisplayNameByGregorianWeekNumber(model.WeekNumber);
// }
return new GetUserCommissionPayoutsResponseDto
{
MetaData = meta,
@@ -14,10 +14,10 @@ public class GetUserCommissionPayoutsQueryValidator : AbstractValidator<GetUserC
.WithMessage("وضعیت معتبر نیست")
.When(x => x.Status.HasValue);
RuleFor(x => x.WeekNumber)
.Matches(@"^\d{4}-W\d{2}$")
.WithMessage("فرمت شماره هفته باید YYYY-Www باشد")
.When(x => !string.IsNullOrEmpty(x.WeekNumber));
RuleFor(x => x.WeekDefinitionId)
.GreaterThan(0)
.WithMessage("شماره هفته نمی‌تواند صفر باشد")
.When(x => x.WeekDefinitionId.HasValue);
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
@@ -12,7 +12,8 @@ public class GetUserCommissionPayoutsResponseModel
public long UserId { get; set; }
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
public string WeekNumber { get; set; } = string.Empty;
public long WeekDefinitionId { get; set; }
public string WeekDisplayName { get; set; } = string.Empty;
public long WeeklyPoolId { get; set; }
public long BalancesEarned { get; set; }
public decimal ValuePerBalance { get; set; }
@@ -11,9 +11,10 @@ public record GetUserWeeklyBalancesQuery : IRequest<GetUserWeeklyBalancesRespons
public long? UserId { get; init; }
/// <summary>
/// شماره هفته (اختیاری)
/// شناسه تعریف هفته (اختیاری) - روش ترجیحی
/// </summary>
public string? WeekNumber { get; init; }
public long? WeekDefinitionId { get; init; }
/// <summary>
/// فقط موارد Expired نشده؟
@@ -3,15 +3,20 @@ namespace CMSMicroservice.Application.CommissionCQ.Queries.GetUserWeeklyBalances
public class GetUserWeeklyBalancesQueryHandler : IRequestHandler<GetUserWeeklyBalancesQuery, GetUserWeeklyBalancesResponseDto>
{
private readonly IApplicationDbContext _context;
private readonly IWeekDefinitionRepository _weekDefinitionRepository;
public GetUserWeeklyBalancesQueryHandler(IApplicationDbContext context)
public GetUserWeeklyBalancesQueryHandler(
IApplicationDbContext context,
IWeekDefinitionRepository weekDefinitionRepository)
{
_context = context;
_weekDefinitionRepository = weekDefinitionRepository;
}
public async Task<GetUserWeeklyBalancesResponseDto> Handle(GetUserWeeklyBalancesQuery request, CancellationToken cancellationToken)
{
var query = _context.NetworkWeeklyBalances
.Include(x => x.WeekDefinition)
.AsNoTracking()
.AsQueryable();
@@ -21,19 +26,20 @@ public class GetUserWeeklyBalancesQueryHandler : IRequestHandler<GetUserWeeklyBa
query = query.Where(x => x.UserId == request.UserId.Value);
}
if (!string.IsNullOrEmpty(request.WeekNumber))
// فیلتر بر اساس WeekDefinitionId (روش ترجیحی)
if (request.WeekDefinitionId.HasValue)
{
query = query.Where(x => x.WeekNumber == request.WeekNumber);
query = query.Where(x => x.WeekDefinitionId == request.WeekDefinitionId.Value);
}
if (request.OnlyActive.HasValue && request.OnlyActive.Value)
{
query = query.Where(x => !x.IsExpired);
}
// نمی‌توانیم "-WeekNumber" استفاده کنیم چون WeekNumber یک string است
// از Created برای مرتب‌سازی استفاده می‌کنیم (جدیدترین هفته‌ها اول)
query = query.ApplyOrder(sortBy: request.SortBy ?? "Created");
// مرتب‌سازی بر اساس WeekDefinitionId (نزولی = جدیدترین اول)
query = query.ApplyOrder(sortBy: request.SortBy ?? "-WeekDefinitionId");
var meta = await query.GetMetaData(request.PaginationState, cancellationToken);
@@ -43,7 +49,8 @@ public class GetUserWeeklyBalancesQueryHandler : IRequestHandler<GetUserWeeklyBa
{
Id = x.Id,
UserId = x.UserId,
WeekNumber = x.WeekNumber,
WeekDefinitionId = x.WeekDefinitionId,
WeekDisplayName = x.WeekDefinition != null ? x.WeekDefinition.DisplayName : "",
LeftLegBalances = x.LeftLegBalances,
RightLegBalances = x.RightLegBalances,
TotalBalances = x.TotalBalances,
@@ -9,10 +9,10 @@ public class GetUserWeeklyBalancesQueryValidator : AbstractValidator<GetUserWeek
.WithMessage("شناسه کاربر معتبر نیست")
.When(x => x.UserId.HasValue);
RuleFor(x => x.WeekNumber)
.Matches(@"^\d{4}-W\d{2}$")
.WithMessage("فرمت شماره هفته باید YYYY-Www باشد")
.When(x => !string.IsNullOrEmpty(x.WeekNumber));
RuleFor(x => x.WeekDefinitionId)
.GreaterThan(0)
.WithMessage("شماره هفته نمی‌تواند صفر باشد")
.When(x => x.WeekDefinitionId.HasValue);
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
@@ -10,7 +10,9 @@ public class GetUserWeeklyBalancesResponseModel
{
public long Id { get; set; }
public long UserId { get; set; }
public string WeekNumber { get; set; } = string.Empty;
public long WeekDefinitionId { get; set; }
public string WeekDisplayName { get; set; } = string.Empty;
public int LeftLegBalances { get; set; }
public int RightLegBalances { get; set; }
public int TotalBalances { get; set; }
@@ -0,0 +1,45 @@
using CMSMicroservice.Application.Common.Models;
namespace CMSMicroservice.Application.CommissionCQ.Queries.GetWeekDefinitions;
/// <summary>
/// Query برای دریافت لیست هفته‌ها از کش (برای dropdown)
/// </summary>
public record GetWeekDefinitionsQuery : IRequest<GetWeekDefinitionsResponseDto>
{
//موقعیت صفحه بندی
public PaginationState? PaginationState { get; init; }
//مرتب سازی بر اساس
public string? SortBy { get; init; }
//فیلتر
public GetWeekDefinitionsFilter? Filter { get; init; }
}
/// <summary>
/// فیلترهای جستجوی هفته‌ها
/// </summary>
public class GetWeekDefinitionsFilter
{
//جستجوی متنی روی DisplayName (مثل "هفته یک")
public string? SearchText { get; set; }
//شماره ترتیب هفته
public int? WeekOrder { get; set; }
//شماره هفته میلادی (2025-W46)
public string? GregorianWeekNumber { get; set; }
//شماره هفته شمسی (1404-W35)
public string? PersianWeekNumber { get; set; }
//سال میلادی
public int? GregorianYear { get; set; }
//سال شمسی
public int? PersianYear { get; set; }
//فقط هفته‌های فعال
public bool? IsActive { get; set; }
}
@@ -0,0 +1,130 @@
using CMSMicroservice.Application.Common.Interfaces;
namespace CMSMicroservice.Application.CommissionCQ.Queries.GetWeekDefinitions;
/// <summary>
/// Handler برای دریافت لیست هفته‌ها از کش
/// </summary>
public class GetWeekDefinitionsQueryHandler : IRequestHandler<GetWeekDefinitionsQuery, GetWeekDefinitionsResponseDto>
{
private readonly IWeekDefinitionRepository _weekDefinitionRepository;
public GetWeekDefinitionsQueryHandler(IWeekDefinitionRepository weekDefinitionRepository)
{
_weekDefinitionRepository = weekDefinitionRepository;
}
public Task<GetWeekDefinitionsResponseDto> Handle(
GetWeekDefinitionsQuery request,
CancellationToken cancellationToken)
{
// گرفتن همه هفته‌ها از کش
var allWeeks = _weekDefinitionRepository.GetAllWeeks();
// اعمال فیلترها
var filteredWeeks = allWeeks.AsEnumerable();
if (request.Filter != null)
{
var filter = request.Filter;
// جستجوی متنی روی DisplayName
if (!string.IsNullOrWhiteSpace(filter.SearchText))
{
filteredWeeks = filteredWeeks.Where(w =>
w.DisplayName.Contains(filter.SearchText, StringComparison.OrdinalIgnoreCase));
}
// فیلتر بر اساس WeekOrder
if (filter.WeekOrder.HasValue)
{
filteredWeeks = filteredWeeks.Where(w => w.WeekOrder == filter.WeekOrder.Value);
}
// فیلتر بر اساس GregorianWeekNumber
if (!string.IsNullOrWhiteSpace(filter.GregorianWeekNumber))
{
filteredWeeks = filteredWeeks.Where(w =>
w.GregorianWeekNumber == filter.GregorianWeekNumber);
}
// فیلتر بر اساس PersianWeekNumber
if (!string.IsNullOrWhiteSpace(filter.PersianWeekNumber))
{
filteredWeeks = filteredWeeks.Where(w =>
w.PersianWeekNumber == filter.PersianWeekNumber);
}
// فیلتر بر اساس سال میلادی
if (filter.GregorianYear.HasValue)
{
filteredWeeks = filteredWeeks.Where(w => w.GregorianYear == filter.GregorianYear.Value);
}
// فیلتر بر اساس سال شمسی
if (filter.PersianYear.HasValue)
{
filteredWeeks = filteredWeeks.Where(w => w.PersianYear == filter.PersianYear.Value);
}
// فیلتر بر اساس فعال بودن
if (filter.IsActive.HasValue)
{
filteredWeeks = filteredWeeks.Where(w => w.IsActive == filter.IsActive.Value);
}
}
// مرتب‌سازی
filteredWeeks = request.SortBy?.ToLower() switch
{
"weekorder_desc" => filteredWeeks.OrderByDescending(w => w.WeekOrder),
"displayname" => filteredWeeks.OrderBy(w => w.DisplayName),
"displayname_desc" => filteredWeeks.OrderByDescending(w => w.DisplayName),
"startdate" => filteredWeeks.OrderBy(w => w.StartDate),
"startdate_desc" => filteredWeeks.OrderByDescending(w => w.StartDate),
_ => filteredWeeks.OrderBy(w => w.WeekOrder) // پیش‌فرض: weekorder
};
// تعداد کل قبل از صفحه‌بندی
var weeksList = filteredWeeks.ToList();
var totalCount = weeksList.Count;
// صفحه‌بندی
if (request.PaginationState != null)
{
var pageNumber = request.PaginationState.PageNumber > 0 ? request.PaginationState.PageNumber : 1;
var pageSize = request.PaginationState.PageSize > 0 ? request.PaginationState.PageSize : 20;
weeksList = weeksList
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.ToList();
}
// گرفتن هفته جاری برای مشخص کردن IsCurrentWeek
var currentWeek = _weekDefinitionRepository.GetCurrentWeek();
// تبدیل به DTO
var weekDtos = weeksList.Select(w => new WeekDefinitionItemDto
{
WeekOrder = w.WeekOrder,
DisplayName = w.DisplayName,
GregorianWeekNumber = w.GregorianWeekNumber,
PersianWeekNumber = w.PersianWeekNumber,
StartDate = w.StartDate,
EndDate = w.EndDate,
GregorianYear = w.GregorianYear,
PersianYear = w.PersianYear,
IsActive = w.IsActive,
IsCurrentWeek = currentWeek != null && w.WeekOrder == currentWeek.WeekOrder
}).ToList();
var response = new GetWeekDefinitionsResponseDto
{
Data = weekDtos,
TotalCount = totalCount
};
return Task.FromResult(response);
}
}
@@ -0,0 +1,49 @@
namespace CMSMicroservice.Application.CommissionCQ.Queries.GetWeekDefinitions;
/// <summary>
/// DTO برای پاسخ لیست هفته‌ها
/// </summary>
public class GetWeekDefinitionsResponseDto
{
//لیست هفته‌ها
public List<WeekDefinitionItemDto> Data { get; set; } = new();
//تعداد کل
public int TotalCount { get; set; }
}
/// <summary>
/// آیتم هفته برای dropdown
/// </summary>
public class WeekDefinitionItemDto
{
//شماره ترتیب هفته (1, 2, 3, ...)
public int WeekOrder { get; set; }
//نام نمایشی هفته (هفته یکم، هفته دوم، ...)
public string DisplayName { get; set; } = string.Empty;
//شماره هفته میلادی (2025-W46)
public string GregorianWeekNumber { get; set; } = string.Empty;
//شماره هفته شمسی (1404-W35)
public string PersianWeekNumber { get; set; } = string.Empty;
//تاریخ شروع هفته
public DateTime StartDate { get; set; }
//تاریخ پایان هفته
public DateTime EndDate { get; set; }
//سال میلادی
public int GregorianYear { get; set; }
//سال شمسی
public int PersianYear { get; set; }
//فعال بودن
public bool IsActive { get; set; }
//آیا هفته جاری است؟
public bool IsCurrentWeek { get; set; }
}
@@ -8,5 +8,5 @@ public record GetWeeklyCommissionPoolQuery : IRequest<WeeklyCommissionPoolDto?>
/// <summary>
/// شماره هفته
/// </summary>
public string WeekNumber { get; init; } = string.Empty;
public long WeekDefinitionId { get; init; }
}
@@ -3,21 +3,27 @@ namespace CMSMicroservice.Application.CommissionCQ.Queries.GetWeeklyCommissionPo
public class GetWeeklyCommissionPoolQueryHandler : IRequestHandler<GetWeeklyCommissionPoolQuery, WeeklyCommissionPoolDto?>
{
private readonly IApplicationDbContext _context;
private readonly IWeekDefinitionRepository _weekDefinitionRepository;
public GetWeeklyCommissionPoolQueryHandler(IApplicationDbContext context)
public GetWeeklyCommissionPoolQueryHandler(
IApplicationDbContext context,
IWeekDefinitionRepository weekDefinitionRepository)
{
_context = context;
_weekDefinitionRepository = weekDefinitionRepository;
}
public async Task<WeeklyCommissionPoolDto?> Handle(GetWeeklyCommissionPoolQuery request, CancellationToken cancellationToken)
{
var pool = await _context.WeeklyCommissionPools
var pool = await _context.WeeklyCommissionPools
.Include(x => x.WeekDefinition)
.AsNoTracking()
.Where(x => x.WeekNumber == request.WeekNumber)
.Where(x => x.WeekDefinitionId == request.WeekDefinitionId)
.Select(x => new WeeklyCommissionPoolDto
{
Id = x.Id,
WeekNumber = x.WeekNumber,
WeekDefinitionId = x.WeekDefinitionId,
WeekDisplayName=x.WeekDefinition.DisplayName,
TotalPoolAmount = x.TotalPoolAmount,
TotalBalances = x.TotalBalances,
ValuePerBalance = x.ValuePerBalance,
@@ -27,6 +33,11 @@ public class GetWeeklyCommissionPoolQueryHandler : IRequestHandler<GetWeeklyComm
})
.FirstOrDefaultAsync(cancellationToken);
return pool??new WeeklyCommissionPoolDto();
// if (pool != null)
// {
// pool.WeekDisplayName = _weekDefinitionRepository.GetDisplayNameByGregorianWeekNumber(pool.WeekNumber);
// }
return pool ?? new WeeklyCommissionPoolDto();
}
}
@@ -4,11 +4,9 @@ public class GetWeeklyCommissionPoolQueryValidator : AbstractValidator<GetWeekly
{
public GetWeeklyCommissionPoolQueryValidator()
{
RuleFor(x => x.WeekNumber)
.NotEmpty()
.WithMessage("شماره هفته نمی‌تواند خالی باشد")
.Matches(@"^\d{4}-W\d{2}$")
.WithMessage("فرمت شماره هفته باید YYYY-Www باشد");
RuleFor(x => x.WeekDefinitionId)
.GreaterThan(0)
.WithMessage("شماره هفته نمی‌تواند صفر باشد");
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
@@ -6,7 +6,8 @@ namespace CMSMicroservice.Application.CommissionCQ.Queries.GetWeeklyCommissionPo
public class WeeklyCommissionPoolDto
{
public long Id { get; set; }
public string WeekNumber { get; set; } = string.Empty;
public long WeekDefinitionId { get; set; }
public string WeekDisplayName { get; set; } = string.Empty;
public long TotalPoolAmount { get; set; }
public long TotalBalances { get; set; }
public decimal ValuePerBalance { get; set; }
@@ -4,7 +4,7 @@ public class GetWithdrawalRequestsQuery : IRequest<GetWithdrawalRequestsResponse
{
public int? Status { get; set; } // CommissionPayoutStatus enum
public long? UserId { get; set; }
public string? WeekNumber { get; set; }
public long? WeekDefinitionId { get; init; }
public string? IbanNumber { get; set; }
public PaginationState? PaginationState { get; set; }
public string? SortBy { get; set; }
@@ -3,10 +3,14 @@ namespace CMSMicroservice.Application.CommissionCQ.Queries.GetWithdrawalRequests
public class GetWithdrawalRequestsQueryHandler : IRequestHandler<GetWithdrawalRequestsQuery, GetWithdrawalRequestsResponseDto>
{
private readonly IApplicationDbContext _context;
private readonly IWeekDefinitionRepository _weekDefinitionRepository;
public GetWithdrawalRequestsQueryHandler(IApplicationDbContext context)
public GetWithdrawalRequestsQueryHandler(
IApplicationDbContext context,
IWeekDefinitionRepository weekDefinitionRepository)
{
_context = context;
_weekDefinitionRepository = weekDefinitionRepository;
}
public async Task<GetWithdrawalRequestsResponseDto> Handle(GetWithdrawalRequestsQuery request, CancellationToken cancellationToken)
@@ -14,6 +18,7 @@ public class GetWithdrawalRequestsQueryHandler : IRequestHandler<GetWithdrawalRe
var query = _context.UserCommissionPayouts
.AsNoTracking()
.Include(x => x.User)
.Include(x => x.WeekDefinition)
.Where(x => x.WithdrawalMethod != null) // Only requests with withdrawal method
.AsQueryable();
@@ -28,9 +33,9 @@ public class GetWithdrawalRequestsQueryHandler : IRequestHandler<GetWithdrawalRe
query = query.Where(x => x.UserId == request.UserId.Value);
}
if (!string.IsNullOrEmpty(request.WeekNumber))
if (request.WeekDefinitionId!= null && request.WeekDefinitionId >0)
{
query = query.Where(x => x.WeekNumber == request.WeekNumber);
query = query.Where(x => x.WeekDefinitionId == request.WeekDefinitionId);
}
if (!string.IsNullOrWhiteSpace(request.IbanNumber))
@@ -51,7 +56,8 @@ public class GetWithdrawalRequestsQueryHandler : IRequestHandler<GetWithdrawalRe
Id = x.Id,
UserId = x.UserId,
UserName = x.User != null ? (x.User.FirstName + " " + x.User.LastName).Trim() : x.User?.Mobile ?? "N/A",
WeekNumber = x.WeekNumber,
WeekDefinitionId = x.WeekDefinitionId,
WeekDisplayName =x.WeekDefinition.DisplayName,
Amount = x.TotalAmount,
Status = (int)x.Status,
WithdrawalMethod = x.WithdrawalMethod.HasValue ? (int)x.WithdrawalMethod.Value : 0,
@@ -11,7 +11,8 @@ public class WithdrawalRequestModel
public long Id { get; set; }
public long UserId { get; set; }
public string UserName { get; set; } = string.Empty;
public string WeekNumber { get; set; } = string.Empty;
public long WeekDefinitionId { get; set; }
public string WeekDisplayName { get; set; } = string.Empty;
public long Amount { get; set; }
public int Status { get; set; } // CommissionPayoutStatus enum
public int? WithdrawalMethod { get; set; }
@@ -4,7 +4,7 @@ namespace CMSMicroservice.Application.CommissionCQ.Queries.GetWorkerExecutionLog
public record GetWorkerExecutionLogsQuery : IRequest<GetWorkerExecutionLogsResponseDto>
{
public string? WeekNumber { get; init; }
public long? WeekDefinitionId { get; init; }
public string? ExecutionId { get; init; }
public bool? SuccessOnly { get; init; }
public bool? FailedOnly { get; init; }
@@ -6,10 +6,14 @@ namespace CMSMicroservice.Application.CommissionCQ.Queries.GetWorkerExecutionLog
public class GetWorkerExecutionLogsQueryHandler : IRequestHandler<GetWorkerExecutionLogsQuery, GetWorkerExecutionLogsResponseDto>
{
private readonly IApplicationDbContext _context;
private readonly IWeekDefinitionRepository _weekDefinitionRepository;
public GetWorkerExecutionLogsQueryHandler(IApplicationDbContext context)
public GetWorkerExecutionLogsQueryHandler(
IApplicationDbContext context,
IWeekDefinitionRepository weekDefinitionRepository)
{
_context = context;
_weekDefinitionRepository = weekDefinitionRepository;
}
public async Task<GetWorkerExecutionLogsResponseDto> Handle(
@@ -17,12 +21,14 @@ public class GetWorkerExecutionLogsQueryHandler : IRequestHandler<GetWorkerExecu
CancellationToken cancellationToken)
{
// Query from database
var query = _context.WorkerExecutionLogs.AsQueryable();
var query = _context.WorkerExecutionLogs
.Include(i=> i.WeekDefinition)
.AsQueryable();
// Apply filters
if (!string.IsNullOrEmpty(request.WeekNumber))
if (request.WeekDefinitionId!=null && request.WeekDefinitionId > 0)
{
query = query.Where(x => x.WeekNumber == request.WeekNumber);
query = query.Where(x => x.WeekDefinitionId == request.WeekDefinitionId);
}
if (request.SuccessOnly == true)
@@ -49,7 +55,8 @@ public class GetWorkerExecutionLogsQueryHandler : IRequestHandler<GetWorkerExecu
.Select(x => new WorkerExecutionLogModel
{
ExecutionId = x.ExecutionId.ToString(),
WeekNumber = x.WeekNumber,
WeekDefinitionId = x.WeekDefinitionId,
WeekDisplayName = x.WeekDefinition.DisplayName,
Step = "Full", // We only have full execution now
Success = x.Status == Domain.Entities.Commission.WorkerExecutionStatus.Success ||
x.Status == Domain.Entities.Commission.WorkerExecutionStatus.SuccessWithWarnings,
@@ -62,6 +69,12 @@ public class GetWorkerExecutionLogsQueryHandler : IRequestHandler<GetWorkerExecu
})
.ToListAsync(cancellationToken);
// // Populate WeekDisplayName from cache
// foreach (var log in logs)
// {
// log.WeekDisplayName = _weekDefinitionRepository.GetDisplayNameByGregorianWeekNumber(log.WeekNumber);
// }
return new GetWorkerExecutionLogsResponseDto
{
MetaData = new MetaData
@@ -11,7 +11,8 @@ public class GetWorkerExecutionLogsResponseDto
public class WorkerExecutionLogModel
{
public string ExecutionId { get; set; } = string.Empty;
public string WeekNumber { get; set; } = string.Empty;
public long WeekDefinitionId { get; set; }
public string WeekDisplayName { get; set; } = string.Empty;
public string Step { get; set; } = string.Empty; // "Balances" | "Pool" | "Payouts" | "Full"
public bool Success { get; set; }
public string? ErrorMessage { get; set; }
@@ -5,10 +5,14 @@ namespace CMSMicroservice.Application.CommissionCQ.Queries.GetWorkerStatus;
public class GetWorkerStatusQueryHandler : IRequestHandler<GetWorkerStatusQuery, GetWorkerStatusResponseDto>
{
private readonly IApplicationDbContext _context;
private readonly IWeekDefinitionRepository _weekDefinitionRepository;
public GetWorkerStatusQueryHandler(IApplicationDbContext context)
public GetWorkerStatusQueryHandler(
IApplicationDbContext context,
IWeekDefinitionRepository weekDefinitionRepository)
{
_context = context;
_weekDefinitionRepository = weekDefinitionRepository;
}
public async Task<GetWorkerStatusResponseDto> Handle(
@@ -19,13 +23,19 @@ public class GetWorkerStatusQueryHandler : IRequestHandler<GetWorkerStatusQuery,
// فعلاً mock data برمی‌گرداند
await Task.CompletedTask;
var currentWeek = _weekDefinitionRepository.GetCurrentWeek();
var currentWeekNumber = currentWeek != null
? $"{currentWeek.GregorianYear}-W{currentWeek.GregorianWeekNumber:D2}"
: null;
return new GetWorkerStatusResponseDto
{
IsRunning = false,
IsEnabled = true,
CurrentExecutionId = null,
CurrentWeekNumber = null,
CurrentWeekNumber = currentWeekNumber,
CurrentWeekDisplayName = currentWeek?.DisplayName,
CurrentStep = "Idle",
LastRunAt = DateTime.Now.AddHours(-24),
NextScheduledRun = DateTime.Now.AddDays(7),
@@ -6,6 +6,7 @@ public class GetWorkerStatusResponseDto
public bool IsEnabled { get; set; }
public string? CurrentExecutionId { get; set; }
public string? CurrentWeekNumber { get; set; }
public string? CurrentWeekDisplayName { get; set; }
public string? CurrentStep { get; set; } // "Balances" | "Pool" | "Payouts" | "Idle"
public DateTime? LastRunAt { get; set; }
public DateTime? NextScheduledRun { get; set; }