feat(bll,dal, templateDistributor): при получении рабочих дней по периоду, отсекаются дни выходящие за период

This commit is contained in:
Mikhail Trubnikov
2024-09-19 13:51:44 +10:00
parent 60c0ba9ec8
commit 9f193fe3ae
6 changed files with 80 additions and 51 deletions

View File

@@ -15,7 +15,7 @@ namespace PARR.BLL.Services.Implementations
}
private DateOnly GetEndPeriodDate(DateOnly startPeriod, DistributionPeriodTypeEnum periodType, string distributionPeriod)
public DateOnly GetEndPeriodDate(DateOnly startPeriod, DistributionPeriodTypeEnum periodType, string distributionPeriod)
{
switch (periodType)
{

View File

@@ -29,6 +29,7 @@ namespace PARR.BLL.Services.Interfaces
/// <param name="timeZoneOffsetHours"></param>
/// <returns></returns>
DateTimeOffset GetDateWithTimeZoneOffset(DateTimeOffset date, int timeZoneOffsetHours);
DateOnly GetEndPeriodDate(DateOnly startPeriod, DistributionPeriodTypeEnum periodType, string distributionPeriod);
/// <summary>
/// Получить только рабочие дни за период

View File

@@ -14,6 +14,7 @@ namespace PARR.DAL.TransformServices
private readonly IEsppSchTypeConfigService esppSchTypeConfigService;
private readonly IApplicationsInWorkService applicationsInWorkService;
private readonly IWeekendDayService weekendDayService;
private readonly INextRunModifierService nextRunModifierService;
private readonly ILogger<EsppScheduleTransformService> logger;
private readonly Dictionary<string, int> monthDict = new Dictionary<string, int>()
@@ -57,12 +58,14 @@ namespace PARR.DAL.TransformServices
ILogger<EsppScheduleTransformService> logger,
IEsppSchTypeConfigService esppSchTypeConfigService,
IApplicationsInWorkService applicationsInWorkService,
IWeekendDayService weekendDayService
IWeekendDayService weekendDayService,
INextRunModifierService nextRunModifierService
)
{
this.esppSchTypeConfigService = esppSchTypeConfigService;
this.applicationsInWorkService = applicationsInWorkService;
this.weekendDayService = weekendDayService;
this.nextRunModifierService = nextRunModifierService;
this.logger = logger;
}
@@ -104,7 +107,7 @@ namespace PARR.DAL.TransformServices
break;
}
nextRun = GetWorkDayAsync(nextRun).GetAwaiter().GetResult();
nextRun = nextRunModifierService.GetWorkDayAsync(nextRun).GetAwaiter().GetResult();
return nextRun;
}
@@ -158,7 +161,7 @@ namespace PARR.DAL.TransformServices
{
//если больше текущего вернуть lastRun. Это и есть следующая дата
if (lastRun > DateTimeOffset.UtcNow)
return await GetWorkDayAsync(lastRun);
return await nextRunModifierService.GetWorkDayAsync(lastRun);
var appInWork = await applicationsInWorkService.Get()
.Include(aiw => aiw.EsppSchValues)
@@ -402,7 +405,7 @@ namespace PARR.DAL.TransformServices
break;
}
return GetWorkDayAsync(nextRun).GetAwaiter().GetResult();
return nextRunModifierService.GetWorkDayAsync(nextRun).GetAwaiter().GetResult();
}
@@ -470,46 +473,5 @@ namespace PARR.DAL.TransformServices
return result;
}
/// <summary>
/// Получить рабочий день следующего срабатывания
/// </summary>
/// <param name="nextRun"></param>
/// <returns></returns>
private async Task<DateTimeOffset> GetWorkDayAsync(DateTimeOffset nextRun)
{
// получаем день относительно часового пояса МСК
var date = DateOnly.FromDateTime(DateResolver.IsCurrentDayRelativeMskTime(nextRun) ? nextRun.Date : nextRun.Date.AddDays(1));
if (await weekendDayService.IsWorkDayAsync(date, true))
{
//текущий nextRun рабочий день, возвращаем его
return nextRun;
}
// ищем следующий рабочий день, максимум 20 итераций, если за их кол-во не нашли рабочий, берём последний не рабочий
int count = 20;
while (count > 0)
{
date = date.AddDays(1);
var isWorkDay = await weekendDayService.IsWorkDayAsync(date, true);
if (isWorkDay)
break; // это рабочий день, выбираем его
count--;
if (!isWorkDay && count == 0)
logger.LogWarning($"Не нашли рабочий день за 20 итераций, взяли последний нерабочий {date}");
}
// смотрим, если смещали из-за пояса МСК на день вперед, вычитаем этот день назад
if (!DateResolver.IsCurrentDayRelativeMskTime(nextRun))
date = date.AddDays(-1);
// считаем новый NextRun
var dayCount = date.DayNumber - DateOnly.FromDateTime(nextRun.Date).DayNumber;
return nextRun.AddDays(dayCount);
}
}
}

View File

@@ -1,4 +1,5 @@

namespace PARR.DAL.TransformServices
{
/// <summary>
@@ -12,5 +13,12 @@ namespace PARR.DAL.TransformServices
/// <param name="nextRun"></param>
/// <returns></returns>
DateTimeOffset GetNextRunByAccountRobotTimeZone(DateTimeOffset nextRun);
/// <summary>
/// Получить РАБОЧИЙ день следующего срабатывания
/// </summary>
/// <param name="nextRun"></param>
/// <returns></returns>
Task<DateTimeOffset> GetWorkDayAsync(DateTimeOffset nextRun);
}
}

View File

@@ -1,14 +1,25 @@
using PARR.DAL.Contracts;
using Microsoft.Extensions.Logging;
using PARR.Common;
using PARR.DAL.Contracts;
using PARR.DAL.Services.Interfaces;
namespace PARR.DAL.TransformServices
{
internal class NextRunModifierService : INextRunModifierService
{
private readonly SettingsFromDb settingsFromDb;
private readonly ILogger<NextRunModifierService> logger;
private readonly IWeekendDayService weekendDayService;
public NextRunModifierService(SettingsFromDb settingsFromDb)
public NextRunModifierService(
SettingsFromDb settingsFromDb,
ILogger<NextRunModifierService> logger,
IWeekendDayService weekendDayService
)
{
this.settingsFromDb = settingsFromDb;
this.logger = logger;
this.weekendDayService = weekendDayService;
}
@@ -16,5 +27,42 @@ namespace PARR.DAL.TransformServices
{
return nextRun.AddHours(settingsFromDb.EsppRobotAccountTimeZoneHour);
}
public async Task<DateTimeOffset> GetWorkDayAsync(DateTimeOffset nextRun)
{
// получаем день относительно часового пояса МСК
var date = DateOnly.FromDateTime(DateResolver.IsCurrentDayRelativeMskTime(nextRun) ? nextRun.Date : nextRun.Date.AddDays(1));
if (await weekendDayService.IsWorkDayAsync(date, true))
{
//текущий nextRun рабочий день, возвращаем его
return nextRun;
}
// ищем следующий рабочий день, максимум 20 итераций, если за их кол-во не нашли рабочий, берём последний не рабочий
int count = 20;
while (count > 0)
{
date = date.AddDays(1);
var isWorkDay = await weekendDayService.IsWorkDayAsync(date, true);
if (isWorkDay)
break; // это рабочий день, выбираем его
count--;
if (!isWorkDay && count == 0)
logger.LogWarning($"Не нашли рабочий день за 20 итераций, взяли последний нерабочий {date}");
}
// смотрим, если смещали из-за пояса МСК на день вперед, вычитаем этот день назад
if (!DateResolver.IsCurrentDayRelativeMskTime(nextRun))
date = date.AddDays(-1);
// считаем новый NextRun
var dayCount = date.DayNumber - DateOnly.FromDateTime(nextRun.Date).DayNumber;
return nextRun.AddDays(dayCount);
}
}
}

View File

@@ -16,6 +16,7 @@ namespace PARR.TemplateDistributor
private readonly ICalendarService calendarService;
private readonly IEsppScheduleTransformService esppScheduleTransformService;
private readonly IWeekendDayService weekendDayService;
private readonly INextRunModifierService nextRunModifierService;
public TemplateDistributor(
ILogger<TemplateDistributor> logger,
@@ -23,7 +24,8 @@ namespace PARR.TemplateDistributor
IApplicationsInWorkService applicationsInWorkService,
ICalendarService calendarService,
IEsppScheduleTransformService esppScheduleTransformService,
IWeekendDayService weekendDayService
IWeekendDayService weekendDayService,
INextRunModifierService nextRunModifierService
)
{
this.logger = logger;
@@ -32,6 +34,7 @@ namespace PARR.TemplateDistributor
this.calendarService = calendarService;
this.esppScheduleTransformService = esppScheduleTransformService;
this.weekendDayService = weekendDayService;
this.nextRunModifierService = nextRunModifierService;
}
@@ -228,7 +231,9 @@ namespace PARR.TemplateDistributor
#endregion
}
else
templates.ForEach(t => t.NextRun = appInWork!.ReferenceDate);
// templates.ForEach(t => t.NextRun = appInWork!.ReferenceDate);
// это не автораспределение, по ReferenceDate получаем ближайший рабочий день
templates.ForEach(async t => t.NextRun = await nextRunModifierService.GetWorkDayAsync(appInWork!.ReferenceDate));
return templates;
}
@@ -281,7 +286,7 @@ namespace PARR.TemplateDistributor
/// </summary>
/// <param name="appInWork"></param>
/// <returns></returns>
public async Task<List<DateOnly>> GetWorkDaysAsync(ApplicationsInWork appInWork)
private async Task<List<DateOnly>> GetWorkDaysAsync(ApplicationsInWork appInWork)
{
var period = appInWork.EsppSchValues.FirstOrDefault()?.EsppSchTypeValue?.DistributionPeriod;
var periodType = ParseDistributionPeriodType(period!.Type);
@@ -303,6 +308,11 @@ namespace PARR.TemplateDistributor
}
});
//----- убираем даты, которые могли выйти за конец периода (из-за сдвига NextRun по рабочим дням)
var endPeriod = calendarService.GetEndPeriodDate(startPeriod, periodType, period.Duration);
result = result.Where(t => t <= endPeriod).ToList();
//-----
return result;
}