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) switch (periodType)
{ {

View File

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

View File

@@ -14,6 +14,7 @@ namespace PARR.DAL.TransformServices
private readonly IEsppSchTypeConfigService esppSchTypeConfigService; private readonly IEsppSchTypeConfigService esppSchTypeConfigService;
private readonly IApplicationsInWorkService applicationsInWorkService; private readonly IApplicationsInWorkService applicationsInWorkService;
private readonly IWeekendDayService weekendDayService; private readonly IWeekendDayService weekendDayService;
private readonly INextRunModifierService nextRunModifierService;
private readonly ILogger<EsppScheduleTransformService> logger; private readonly ILogger<EsppScheduleTransformService> logger;
private readonly Dictionary<string, int> monthDict = new Dictionary<string, int>() private readonly Dictionary<string, int> monthDict = new Dictionary<string, int>()
@@ -57,12 +58,14 @@ namespace PARR.DAL.TransformServices
ILogger<EsppScheduleTransformService> logger, ILogger<EsppScheduleTransformService> logger,
IEsppSchTypeConfigService esppSchTypeConfigService, IEsppSchTypeConfigService esppSchTypeConfigService,
IApplicationsInWorkService applicationsInWorkService, IApplicationsInWorkService applicationsInWorkService,
IWeekendDayService weekendDayService IWeekendDayService weekendDayService,
INextRunModifierService nextRunModifierService
) )
{ {
this.esppSchTypeConfigService = esppSchTypeConfigService; this.esppSchTypeConfigService = esppSchTypeConfigService;
this.applicationsInWorkService = applicationsInWorkService; this.applicationsInWorkService = applicationsInWorkService;
this.weekendDayService = weekendDayService; this.weekendDayService = weekendDayService;
this.nextRunModifierService = nextRunModifierService;
this.logger = logger; this.logger = logger;
} }
@@ -104,7 +107,7 @@ namespace PARR.DAL.TransformServices
break; break;
} }
nextRun = GetWorkDayAsync(nextRun).GetAwaiter().GetResult(); nextRun = nextRunModifierService.GetWorkDayAsync(nextRun).GetAwaiter().GetResult();
return nextRun; return nextRun;
} }
@@ -158,7 +161,7 @@ namespace PARR.DAL.TransformServices
{ {
//если больше текущего вернуть lastRun. Это и есть следующая дата //если больше текущего вернуть lastRun. Это и есть следующая дата
if (lastRun > DateTimeOffset.UtcNow) if (lastRun > DateTimeOffset.UtcNow)
return await GetWorkDayAsync(lastRun); return await nextRunModifierService.GetWorkDayAsync(lastRun);
var appInWork = await applicationsInWorkService.Get() var appInWork = await applicationsInWorkService.Get()
.Include(aiw => aiw.EsppSchValues) .Include(aiw => aiw.EsppSchValues)
@@ -402,7 +405,7 @@ namespace PARR.DAL.TransformServices
break; break;
} }
return GetWorkDayAsync(nextRun).GetAwaiter().GetResult(); return nextRunModifierService.GetWorkDayAsync(nextRun).GetAwaiter().GetResult();
} }
@@ -470,46 +473,5 @@ namespace PARR.DAL.TransformServices
return result; 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 namespace PARR.DAL.TransformServices
{ {
/// <summary> /// <summary>
@@ -12,5 +13,12 @@ namespace PARR.DAL.TransformServices
/// <param name="nextRun"></param> /// <param name="nextRun"></param>
/// <returns></returns> /// <returns></returns>
DateTimeOffset GetNextRunByAccountRobotTimeZone(DateTimeOffset nextRun); 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 namespace PARR.DAL.TransformServices
{ {
internal class NextRunModifierService : INextRunModifierService internal class NextRunModifierService : INextRunModifierService
{ {
private readonly SettingsFromDb settingsFromDb; 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.settingsFromDb = settingsFromDb;
this.logger = logger;
this.weekendDayService = weekendDayService;
} }
@@ -16,5 +27,42 @@ namespace PARR.DAL.TransformServices
{ {
return nextRun.AddHours(settingsFromDb.EsppRobotAccountTimeZoneHour); 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 ICalendarService calendarService;
private readonly IEsppScheduleTransformService esppScheduleTransformService; private readonly IEsppScheduleTransformService esppScheduleTransformService;
private readonly IWeekendDayService weekendDayService; private readonly IWeekendDayService weekendDayService;
private readonly INextRunModifierService nextRunModifierService;
public TemplateDistributor( public TemplateDistributor(
ILogger<TemplateDistributor> logger, ILogger<TemplateDistributor> logger,
@@ -23,7 +24,8 @@ namespace PARR.TemplateDistributor
IApplicationsInWorkService applicationsInWorkService, IApplicationsInWorkService applicationsInWorkService,
ICalendarService calendarService, ICalendarService calendarService,
IEsppScheduleTransformService esppScheduleTransformService, IEsppScheduleTransformService esppScheduleTransformService,
IWeekendDayService weekendDayService IWeekendDayService weekendDayService,
INextRunModifierService nextRunModifierService
) )
{ {
this.logger = logger; this.logger = logger;
@@ -32,6 +34,7 @@ namespace PARR.TemplateDistributor
this.calendarService = calendarService; this.calendarService = calendarService;
this.esppScheduleTransformService = esppScheduleTransformService; this.esppScheduleTransformService = esppScheduleTransformService;
this.weekendDayService = weekendDayService; this.weekendDayService = weekendDayService;
this.nextRunModifierService = nextRunModifierService;
} }
@@ -228,7 +231,9 @@ namespace PARR.TemplateDistributor
#endregion #endregion
} }
else 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; return templates;
} }
@@ -281,7 +286,7 @@ namespace PARR.TemplateDistributor
/// </summary> /// </summary>
/// <param name="appInWork"></param> /// <param name="appInWork"></param>
/// <returns></returns> /// <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 period = appInWork.EsppSchValues.FirstOrDefault()?.EsppSchTypeValue?.DistributionPeriod;
var periodType = ParseDistributionPeriodType(period!.Type); 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; return result;
} }