diff --git a/PARR.API/Contracts/V1/ApiRoutes.cs b/PARR.API/Contracts/V1/ApiRoutes.cs index d41ca1d5..0e45e8ba 100644 --- a/PARR.API/Contracts/V1/ApiRoutes.cs +++ b/PARR.API/Contracts/V1/ApiRoutes.cs @@ -53,6 +53,8 @@ public const string CreateCache = Base + "/tests/cache/"; + public const string IsWorkDay = Base + "/tests/is-work-day/"; + public const string paramDate = "{lastRunDate}"; public const string paramApplicationInWorkId = "{applicationInWorkId}"; } diff --git a/PARR.API/Controllers/V1/TestController.cs b/PARR.API/Controllers/V1/TestController.cs index 19fd0407..84b7c316 100644 --- a/PARR.API/Controllers/V1/TestController.cs +++ b/PARR.API/Controllers/V1/TestController.cs @@ -5,6 +5,7 @@ using PARR.API.Contracts.V1.Responses.Base; using PARR.API.Controllers.V1.Base; using PARR.API.Services.Interfaces; using PARR.DAL.CacheServices; +using PARR.DAL.Services.Interfaces; using PARR.DAL.TransformServices; namespace PARR.API.Controllers.V1 @@ -15,12 +16,19 @@ namespace PARR.API.Controllers.V1 private readonly IClientService clientService; private readonly IEsppScheduleTransformService esppScheduleTransformService; private readonly IRedisCacheService redisCacheService; + private readonly IWeekendDayService weekendDayService; - public TestController(IClientService clientService, IEsppScheduleTransformService esppScheduleTransformService, IRedisCacheService redisCacheService) + public TestController( + IClientService clientService, + IEsppScheduleTransformService esppScheduleTransformService, + IRedisCacheService redisCacheService, + IWeekendDayService weekendDayService + ) { this.clientService = clientService; this.esppScheduleTransformService = esppScheduleTransformService; this.redisCacheService = redisCacheService; + this.weekendDayService = weekendDayService; } @@ -83,6 +91,18 @@ namespace PARR.API.Controllers.V1 } + /// + /// Проверка, это рабочий день? + /// + /// + /// + [HttpGet(ApiRoutes.Test.IsWorkDay)] + public async Task IsWorkDay([FromQuery] DateOnly date) + { + return Ok(await weekendDayService.IsWorkDayAsync(date, true)); + } + + } public class CaheRequestTest diff --git a/PARR.API/Settings/UserCacheSettings.cs b/PARR.API/Settings/UserCacheSettings.cs index 4a5e6a04..f0de0de0 100644 --- a/PARR.API/Settings/UserCacheSettings.cs +++ b/PARR.API/Settings/UserCacheSettings.cs @@ -10,6 +10,7 @@ /// public TimeSpan UserCacheTtl { get; set; } + /// /// Сколько хранить в кэше заблокированных пользователей (как долго блокировать пользователя) /// diff --git a/PARR.DAL/ParrDalInstaller.cs b/PARR.DAL/ParrDalInstaller.cs index dc2cbfcd..60e83042 100644 --- a/PARR.DAL/ParrDalInstaller.cs +++ b/PARR.DAL/ParrDalInstaller.cs @@ -119,6 +119,10 @@ namespace PARR.DAL services.AddSingleton(settingsFromDb); PrefixSettings.PrefixWithoutVariable = settingsFromDb.TemplatePrefixWithoutVariable; + + var weekendCacheSettings = new WeekendCacheSettings(); + configuration.GetSection(nameof(WeekendCacheSettings)).Bind(weekendCacheSettings); + services.AddSingleton(weekendCacheSettings); } } diff --git a/PARR.DAL/Services/Implementations/WeekendDayService.cs b/PARR.DAL/Services/Implementations/WeekendDayService.cs index b514cbff..d70a3ee9 100644 --- a/PARR.DAL/Services/Implementations/WeekendDayService.cs +++ b/PARR.DAL/Services/Implementations/WeekendDayService.cs @@ -1,9 +1,11 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; +using PARR.DAL.CacheServices; using PARR.DAL.Context; using PARR.DAL.Models; using PARR.DAL.Services.Abstracts; using PARR.DAL.Services.Interfaces; +using PARR.DAL.Settings; namespace PARR.DAL.Services.Implementations { @@ -11,15 +13,24 @@ namespace PARR.DAL.Services.Implementations { private readonly DataContext dataContext; private readonly ILogger logger; + private readonly IRedisCacheService redisCacheService; + private readonly WeekendCacheSettings weekendCacheSettings; protected override DbSet EntitySet => dataContext.WeekendDays; protected override DataContext EntitiContext => dataContext; - public WeekendDayService(DataContext dataContext, ILogger logger) : base(logger) + public WeekendDayService( + DataContext dataContext, + ILogger logger, + IRedisCacheService redisCacheService, + WeekendCacheSettings weekendCacheSettings + ) : base(logger) { this.dataContext = dataContext; this.logger = logger; + this.redisCacheService = redisCacheService; + this.weekendCacheSettings = weekendCacheSettings; } @@ -28,5 +39,45 @@ namespace PARR.DAL.Services.Implementations return EntitySet.Where(t => t.Date >= start && t.Date <= end).Select(t => t.Date); } + + + public async Task IsWorkDayAsync(DateOnly date, bool useCache = false) + { + if (useCache) + { + // смотрим, есть ли в кэше рабочий день + var workdayInCache = await redisCacheService.GetCachedDataAsync(GetWorkDayKey(date)); + if (workdayInCache != null) + return true; + + // смотрим, есть ли в кэше выходной день + var weekendInCache = await redisCacheService.GetCachedDataAsync(GetWeekendKey(date)); + if (weekendInCache != null) + return false; + } + + var weekendInDb = await EntitySet.FirstOrDefaultAsync(t => t.Date == date); + + var isWorkday = weekendInDb == null; + + //сохраняем всегда в КЭШ значение выходного и рабочего дня + var cacheKey = isWorkday ? GetWorkDayKey(date) : GetWeekendKey(date); + //TODO:!!! Тут настройки вынести в DB settings + await redisCacheService.SetCachedDataAsync(cacheKey, date, weekendCacheSettings.WeekendTtl); + + return isWorkday; + } + + + private string GetWeekendKey(DateOnly day) + { + return $"weekend_{day.ToString("yyyy-MM-dd")}"; + } + + private string GetWorkDayKey(DateOnly day) + { + return $"workday_{day.ToString("yyyy-MM-dd")}"; + } + } } diff --git a/PARR.DAL/Services/Interfaces/IWeekendDayService.cs b/PARR.DAL/Services/Interfaces/IWeekendDayService.cs index d49e62e5..eacb242c 100644 --- a/PARR.DAL/Services/Interfaces/IWeekendDayService.cs +++ b/PARR.DAL/Services/Interfaces/IWeekendDayService.cs @@ -6,5 +6,6 @@ namespace PARR.DAL.Services.Interfaces public interface IWeekendDayService : IBaseService { IQueryable GetWeekends(DateOnly start, DateOnly end); + Task IsWorkDayAsync(DateOnly date, bool useCache = false); } } diff --git a/PARR.DAL/Settings/WeekendCacheSettings.cs b/PARR.DAL/Settings/WeekendCacheSettings.cs new file mode 100644 index 00000000..83977db6 --- /dev/null +++ b/PARR.DAL/Settings/WeekendCacheSettings.cs @@ -0,0 +1,10 @@ +namespace PARR.DAL.Settings +{ + public class WeekendCacheSettings + { + /// + /// Время хранения в кэше данных о выходных и рабочих днях + /// + public TimeSpan WeekendTtl { get; set; } = new TimeSpan(0, 5, 0); + } +} diff --git a/PARR.DAL/TransformServices/EsppScheduleTransformService.cs b/PARR.DAL/TransformServices/EsppScheduleTransformService.cs index 6436f482..dd9b1ead 100644 --- a/PARR.DAL/TransformServices/EsppScheduleTransformService.cs +++ b/PARR.DAL/TransformServices/EsppScheduleTransformService.cs @@ -208,7 +208,7 @@ namespace PARR.DAL.TransformServices //TODO: вот это повторяется от метода к методу - //Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию + //Если итоговая дата указывает на прошлое, то повторяем расчёт и уходим в рекурсию if (calcDay < DateTimeOffset.UtcNow) calcDay = GetNextDateRegularly(values, calcDay); @@ -216,6 +216,7 @@ namespace PARR.DAL.TransformServices return calcDay; } + private DateTimeOffset GetNextDateWeekly(List values, DateTimeOffset lastRun) { var dwNum = dwDict[values[0].Value.Value]; @@ -233,6 +234,7 @@ namespace PARR.DAL.TransformServices return calcDay; } + private DateTimeOffset GetNextDateMonthly(List values, DateTimeOffset lastRun) { int.TryParse(values[0].Value.Value, out int dayNum); @@ -247,6 +249,7 @@ namespace PARR.DAL.TransformServices return calcDay; } + private DateTimeOffset GetNextDateMonthly2(List values, DateTimeOffset lastRun) { var orderNum = orderDict[values[0].Value.Value]; @@ -268,6 +271,8 @@ namespace PARR.DAL.TransformServices return calcDay; } + + private DateTimeOffset GetNextDateAnnually(List values, DateTimeOffset lastRun) { var monthNum = monthDict[values[0].Value.Value]; @@ -283,6 +288,7 @@ namespace PARR.DAL.TransformServices return calcDay; } + private DateTimeOffset GetNextDateAnnually2(List values, DateTimeOffset lastRun) { var monthADict = new Dictionary @@ -322,6 +328,7 @@ namespace PARR.DAL.TransformServices return calcDay; } + private List FindAllDaysInMonth(int dwNum, ref DateTimeOffset calcDay) { if (((int)calcDay.DayOfWeek) != dwNum) @@ -338,6 +345,7 @@ namespace PARR.DAL.TransformServices return daysList; } + private void OffsetToDayOfWeek(int dwNum, ref DateTimeOffset calcDay) { var daysOffset = dwNum - ((int)calcDay.DayOfWeek); @@ -366,6 +374,7 @@ namespace PARR.DAL.TransformServices return lastRun; } + private DateTimeOffset GetPrevDateForDistributionRun(DateTimeOffset lastRun, DistributionPeriodTypeEnum periodType, string distributionPeriod) { switch (periodType) @@ -383,6 +392,7 @@ namespace PARR.DAL.TransformServices return lastRun; } + public async Task GetStartPeriodForDateAsync(Guid applicationInWorkId, DateTimeOffset date, DateTimeOffset referenceDate, DistributionPeriodTypeEnum periodType, string distributionPeriod) { @@ -422,6 +432,7 @@ namespace PARR.DAL.TransformServices } } + private DistributionPeriodTypeEnum ParseDistributionPeriodType(string value) { var result = (DistributionPeriodTypeEnum)Enum.Parse(typeof(DistributionPeriodTypeEnum), value);