diff --git a/PARR.BLL/Services/Implementations/CalendarService.cs b/PARR.BLL/Services/Implementations/CalendarService.cs index 6991d391..9c4b4613 100644 --- a/PARR.BLL/Services/Implementations/CalendarService.cs +++ b/PARR.BLL/Services/Implementations/CalendarService.cs @@ -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) { diff --git a/PARR.BLL/Services/Interfaces/ICalendarService.cs b/PARR.BLL/Services/Interfaces/ICalendarService.cs index 85075d44..e2c3b468 100644 --- a/PARR.BLL/Services/Interfaces/ICalendarService.cs +++ b/PARR.BLL/Services/Interfaces/ICalendarService.cs @@ -29,6 +29,7 @@ namespace PARR.BLL.Services.Interfaces /// /// DateTimeOffset GetDateWithTimeZoneOffset(DateTimeOffset date, int timeZoneOffsetHours); + DateOnly GetEndPeriodDate(DateOnly startPeriod, DistributionPeriodTypeEnum periodType, string distributionPeriod); /// /// Получить только рабочие дни за период diff --git a/PARR.DAL/TransformServices/EsppScheduleTransformService.cs b/PARR.DAL/TransformServices/EsppScheduleTransformService.cs index 28603aca..09f6cb5f 100644 --- a/PARR.DAL/TransformServices/EsppScheduleTransformService.cs +++ b/PARR.DAL/TransformServices/EsppScheduleTransformService.cs @@ -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 logger; private readonly Dictionary monthDict = new Dictionary() @@ -57,12 +58,14 @@ namespace PARR.DAL.TransformServices ILogger 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; } - - /// - /// Получить рабочий день следующего срабатывания - /// - /// - /// - private async Task 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); - } } } diff --git a/PARR.DAL/TransformServices/INextRunModifierService.cs b/PARR.DAL/TransformServices/INextRunModifierService.cs index 4567244e..2e36fb9c 100644 --- a/PARR.DAL/TransformServices/INextRunModifierService.cs +++ b/PARR.DAL/TransformServices/INextRunModifierService.cs @@ -1,4 +1,5 @@  + namespace PARR.DAL.TransformServices { /// @@ -12,5 +13,12 @@ namespace PARR.DAL.TransformServices /// /// DateTimeOffset GetNextRunByAccountRobotTimeZone(DateTimeOffset nextRun); + + /// + /// Получить РАБОЧИЙ день следующего срабатывания + /// + /// + /// + Task GetWorkDayAsync(DateTimeOffset nextRun); } } diff --git a/PARR.DAL/TransformServices/NextRunModifierService.cs b/PARR.DAL/TransformServices/NextRunModifierService.cs index c6adbc99..2b5e41aa 100644 --- a/PARR.DAL/TransformServices/NextRunModifierService.cs +++ b/PARR.DAL/TransformServices/NextRunModifierService.cs @@ -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 logger; + private readonly IWeekendDayService weekendDayService; - public NextRunModifierService(SettingsFromDb settingsFromDb) + public NextRunModifierService( + SettingsFromDb settingsFromDb, + ILogger 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 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); + } } } diff --git a/PARR.TemplateDistributor/TemplateDistributor.cs b/PARR.TemplateDistributor/TemplateDistributor.cs index 86f25f74..19b7ce48 100644 --- a/PARR.TemplateDistributor/TemplateDistributor.cs +++ b/PARR.TemplateDistributor/TemplateDistributor.cs @@ -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 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 /// /// /// - public async Task> GetWorkDaysAsync(ApplicationsInWork appInWork) + private async Task> 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; }