From 5ad26742e69ef73fd4f3b6e3adc48525dbe2cfe4 Mon Sep 17 00:00:00 2001 From: Mikhail Trubnikov Date: Wed, 21 Jan 2026 12:19:27 +1000 Subject: [PATCH 1/6] =?UTF-8?q?feat(dal):=20NextRunService,=20GetNextRunFo?= =?UTF-8?q?rJobGroupWithAutoDistributionAsync=20-=20=D1=80=D0=B5=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F,=20=D1=80=D0=B0?= =?UTF-8?q?=D1=81=D0=BF=D1=80=D0=B5=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D1=88=D0=B0=D0=B1=D0=BB=D0=BE=D0=BD=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PARR.DAL/NextRunServices/INextRunService.cs | 6 +- .../Models/TemplateWithWorkGroupDto.cs | 5 + PARR.DAL/NextRunServices/NextRunService.cs | 149 +++++++++++++++++- PARR.Test/NextRun/NextRunTest.cs | 12 +- 4 files changed, 162 insertions(+), 10 deletions(-) create mode 100644 PARR.DAL/NextRunServices/Models/TemplateWithWorkGroupDto.cs diff --git a/PARR.DAL/NextRunServices/INextRunService.cs b/PARR.DAL/NextRunServices/INextRunService.cs index 3800f9f9..d784a4a1 100644 --- a/PARR.DAL/NextRunServices/INextRunService.cs +++ b/PARR.DAL/NextRunServices/INextRunService.cs @@ -1,4 +1,6 @@ -namespace PARR.DAL.NextRunServices +using PARR.DAL.NextRunServices.Models; + +namespace PARR.DAL.NextRunServices { public interface INextRunService { @@ -7,7 +9,7 @@ /// /// /// - Task> GetNextRunForJobGroupWithAutoDistributionAsync(Guid jobGroupId); + Task?> GetNextRunForJobGroupWithAutoDistributionAsync(Guid jobGroupId); /// diff --git a/PARR.DAL/NextRunServices/Models/TemplateWithWorkGroupDto.cs b/PARR.DAL/NextRunServices/Models/TemplateWithWorkGroupDto.cs new file mode 100644 index 00000000..cdae20a5 --- /dev/null +++ b/PARR.DAL/NextRunServices/Models/TemplateWithWorkGroupDto.cs @@ -0,0 +1,5 @@ +namespace PARR.DAL.NextRunServices.Models +{ + internal record TemplateWithWorkGroupDto(Guid Id, DateTimeOffset? NextRun, string WorkGroup); + +} diff --git a/PARR.DAL/NextRunServices/NextRunService.cs b/PARR.DAL/NextRunServices/NextRunService.cs index ff5348b7..7860a2ab 100644 --- a/PARR.DAL/NextRunServices/NextRunService.cs +++ b/PARR.DAL/NextRunServices/NextRunService.cs @@ -1,6 +1,11 @@  using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; +using PARR.Constants; +using PARR.DAL.DomainServices.Shortcodes; +using PARR.DAL.Models; +using PARR.DAL.Models.Job; +using PARR.DAL.NextRunServices.Models; using PARR.DAL.NextRunServices.Subservices; using PARR.DAL.Services.Interfaces; using PARR.DAL.Services.Interfaces.Job; @@ -15,13 +20,15 @@ namespace PARR.DAL.NextRunServices private readonly IJobGroupService jobGroupService; private readonly IEsppScheduleTransformService esppScheduleTransformService; private readonly ITemplateDistributor templateDistributor; + private readonly IShortcodesService shortcodesService; public NextRunService( ILogger logger, ITemplateService templateService, IJobGroupService jobGroupService, IEsppScheduleTransformService esppScheduleTransformService, - ITemplateDistributor templateDistributor + ITemplateDistributor templateDistributor, + IShortcodesService shortcodesService ) { this.logger = logger; @@ -29,14 +36,94 @@ namespace PARR.DAL.NextRunServices this.jobGroupService = jobGroupService; this.esppScheduleTransformService = esppScheduleTransformService; this.templateDistributor = templateDistributor; + this.shortcodesService = shortcodesService; } - public async Task> GetNextRunForJobGroupWithAutoDistributionAsync(Guid jobGroupId) + public async Task?> GetNextRunForJobGroupWithAutoDistributionAsync(Guid jobGroupId) { - //TODO: - throw new NotImplementedException(); - //var ditributedTemplateList = await templateDistributor.DistributeTemplatesAsync(); + logger.LogInformation("Начинаю распределять шаблоны для группы работ {gobGroupId}", jobGroupId); + + var jobGroup = await jobGroupService.Get() + .Include(t => t.DistributionConfig) + .ThenInclude(t => t.DistributionPeriod) + .AsNoTracking() + .FirstOrDefaultAsync(t => t.Id == jobGroupId); + + if (jobGroup == null) + { + logger.LogError("Не найдена группа работа с id: {id}", jobGroupId); + return null; + } + + if (!jobGroup.IsAutoDistributionEnabled || jobGroup.DistributionConfig == null) + { + logger.LogError("Группа работ id: {id} не подходит для автораспределения, у нее или отсутствуют настройки или не включено автораспределение. IsAutoDistributionEnabled: {IsAutoDistributionEnabled}. Есть конфиг: {DistributionConfig}", jobGroupId, jobGroup.IsAutoDistributionEnabled, jobGroup.DistributionConfig != null); + return null; + } + + logger.LogInformation("Параметры распределения. groupId: {groupId}, name: {groupName}, referenceDate: {referenceDate}, " + + "distributionPeriodName: {distributionPeriodName}, distributionPeriodDuration: {distributionPeriodDuration}, " + + "distributionPeriodType: {distributionPeriodType}, IsExcludeWeekends: {IsExcludeWeekends}, IsGroupingByWorkGroup: {IsGroupingByWorkGroup}", + jobGroupId, jobGroup.GroupName, jobGroup.ReferenceDate, jobGroup.DistributionConfig.DistributionPeriod.Name, jobGroup.DistributionConfig.DistributionPeriod.Duration, jobGroup.DistributionConfig.DistributionPeriod.Type, + jobGroup.DistributionConfig.IsExcludeWeekends, jobGroup.DistributionConfig.IsGroupingByWorkGroup + ); + + var duration = GetDurationDays(jobGroup.DistributionConfig); + var dateStart = GetDateStart(jobGroup.ReferenceDate); + + var allTemplates = await templateService.Get() + .Include(t => t.Job) + .Where(t => t.Job!.GroupId == jobGroupId) + .AsNoTracking() + .ToListAsync(); + if (!allTemplates.Any()) + { + logger.LogInformation("В группе c ИД {jobGroupId} отсутствуют шаблоны", jobGroupId); + return null; + } + + logger.LogDebug("Всего шаблонов для распределения: {count} шт.", allTemplates.Count); + + var result = new List(); + + if (jobGroup.DistributionConfig.IsGroupingByWorkGroup) + { + // Нужно группировать по РГ + + // список шаблонов с полученной из шорткода РГ + var templatesWithWorkGroup = new List(); + foreach (var template in allTemplates) + { + var workGroupName = await shortcodesService.ApplyShortcodesAsync(template.Job!.WorkGroupMask, template); + templatesWithWorkGroup.Add(new TemplateWithWorkGroupDto(template.Id, template.NextRun, workGroupName)); + } + + var grouping = templatesWithWorkGroup.GroupBy(t => t.WorkGroup); + + //распределяем + foreach (var workGroupTemplates in grouping) + { + logger.LogInformation("Начинаю распределять шаблоны для рабочей группы: {workGroup}. Всего шаблонов: {countTemplates} шт.", workGroupTemplates.Key, workGroupTemplates.Count()); + var templatesForDistribute = workGroupTemplates.Select(t => new TemplateNextRunDto(t.Id, t.NextRun)).ToList(); + var distributedResult = await templateDistributor.DistributeTemplatesAsync(dateStart, duration, jobGroup.ReferenceDate, templatesForDistribute, jobGroup.DistributionConfig.IsExcludeWeekends); + + result.AddRange(distributedResult); + } + } + else + { + // Не нужна группировка по РГ + + // сразу распределяем все шаблоны + var templatesForDistribute = allTemplates.Select(t => new TemplateNextRunDto(t.Id, t.NextRun)).ToList(); + + result = await templateDistributor.DistributeTemplatesAsync(dateStart, duration, jobGroup.ReferenceDate, templatesForDistribute, jobGroup.DistributionConfig.IsExcludeWeekends); + } + + logger.LogInformation("Завершено распределение шаблонов для группы {jobGroupId}. Всего распределено шаблонов: {count} шт.", jobGroupId, result.Count); + + return result; } @@ -81,5 +168,57 @@ namespace PARR.DAL.NextRunServices return await esppScheduleTransformService.GetNextDateAsync(template.Job.Group.Id, template.Job.Group.ReferenceDate); } } + + + /// + /// Получить продолжительность в днях + /// + /// + /// + private int GetDurationDays(JobGroupDistributionConfig config) + { + var period = config.DistributionPeriod; + var periodType = period!.Type; + int.TryParse(period.Duration, out var duration); + + var periodDays = duration; + + if (periodType == DistributionPeriodTypeEnum.Day.ToString()) + periodDays = duration; + + + if (periodType == DistributionPeriodTypeEnum.Month.ToString()) + // в месяце 30 дней, duration*30 + periodDays = duration * 30; + + + if (periodType == DistributionPeriodTypeEnum.Year.ToString()) + // в году 365 дней, duration*365 + periodDays = duration * 365; + + + logger.LogDebug("Период распределения: {name}, duration: {duration}, type: {type}. Итого в днях: {days}", period.Name, period.Duration, period.Type, periodDays); + + if (periodDays == 0) + logger.LogWarning("Период распределения 0 дней. Неверный конфиг распределения в таблице {table}. {name}, duration: {duration}, type: {type}", nameof(DistributionPeriod), period.Name, period.Duration, period.Type); + + return periodDays; + } + + + /// + /// Получить дату начала распределения + /// + /// + /// + private DateOnly GetDateStart(DateTimeOffset referenceDate) + { + var today = DateTime.UtcNow; + + if (today < referenceDate) + return DateOnly.FromDateTime(referenceDate.Date); + else + return DateOnly.FromDateTime(today.Date); + } } } diff --git a/PARR.Test/NextRun/NextRunTest.cs b/PARR.Test/NextRun/NextRunTest.cs index c815937f..f6c905bf 100644 --- a/PARR.Test/NextRun/NextRunTest.cs +++ b/PARR.Test/NextRun/NextRunTest.cs @@ -1,4 +1,5 @@ -using PARR.DAL.NextRunServices.Models; +using PARR.DAL.NextRunServices; +using PARR.DAL.NextRunServices.Models; using PARR.DAL.NextRunServices.Subservices; namespace PARR.Test.NextRun @@ -6,10 +7,12 @@ namespace PARR.Test.NextRun internal class NextRunTest { private readonly ITemplateDistributor templateDistributor; + private readonly INextRunService nextRunService; - public NextRunTest(ITemplateDistributor templateDistributor) + public NextRunTest(ITemplateDistributor templateDistributor, INextRunService nextRunService) { this.templateDistributor = templateDistributor; + this.nextRunService = nextRunService; } int periodDays = 10; @@ -17,8 +20,11 @@ namespace PARR.Test.NextRun public async Task Test() { - await DistributeTemplatesAsync(); + //await DistributeTemplatesAsync(); //await GetValidNextRunForTemplateAsync(); + + var result = await nextRunService.GetNextRunForJobGroupWithAutoDistributionAsync(Guid.Parse("eadc5498-dba6-4f10-9b4b-a1653e3c3e61")); + } /// From b83438d6ca4c49591c3d4234003f5d841d22dcb0 Mon Sep 17 00:00:00 2001 From: Mikhail Trubnikov Date: Wed, 21 Jan 2026 15:36:54 +1000 Subject: [PATCH 2/6] =?UTF-8?q?feat(dal):=20NextRunService=20-=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B0=D0=BA?= =?UTF-8?q?=D1=82=D1=83=D0=B0=D0=BB=D1=8C=D0=BD=D0=BE=D0=B3=D0=BE=20nextRu?= =?UTF-8?q?n=20=D0=B4=D0=BB=D1=8F=20=D0=BD=D0=BE=D0=B2=D0=BE=D0=B3=D0=BE?= =?UTF-8?q?=20=D0=B8=D0=BB=D0=B8=20=D1=81=D1=83=D1=89=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D0=B2=D1=83=D1=8E=D1=89=D0=B5=D0=B3=D0=BE=20=D1=88=D0=B0=D0=B1?= =?UTF-8?q?=D0=BB=D0=BE=D0=BD=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PARR.DAL/NextRunServices/INextRunService.cs | 18 +++- PARR.DAL/NextRunServices/NextRunService.cs | 110 +++++++++++++++++--- PARR.Test/NextRun/NextRunTest.cs | 9 +- 3 files changed, 119 insertions(+), 18 deletions(-) diff --git a/PARR.DAL/NextRunServices/INextRunService.cs b/PARR.DAL/NextRunServices/INextRunService.cs index d784a4a1..a130620e 100644 --- a/PARR.DAL/NextRunServices/INextRunService.cs +++ b/PARR.DAL/NextRunServices/INextRunService.cs @@ -12,21 +12,29 @@ namespace PARR.DAL.NextRunServices Task?> GetNextRunForJobGroupWithAutoDistributionAsync(Guid jobGroupId); + ///// + ///// Получить NextRun по jobGroupId с расписанием ЕСПП + ///// + ///// + ///// + //Task GetNextRunForJobGroupWithEsppSchedulleAsync(Guid jobGroupId); + + /// - /// Получить NextRun по jobGroupId с расписанием ЕСПП + /// Получить nextRun для создаваемого шаблона, которого еще нет в БД /// /// /// - Task GetNextRunForJobGroupWithEsppSchedulleAsync(Guid jobGroupId); + Task GetNextRunForNewTemplateAsync(Guid jobGroupId); /// - /// Получить NextRun по id шаблона + /// Получить NextRun по id существующего шаблона /// /// - /// Новый шаблон или шаблон переведенный из unused + /// Шаблон переведенный из unused /// - Task GetNextRunForTemplate(Guid templateId, bool isNew); + Task GetNextRunForTemplateAsync(Guid templateId, bool isNew); } } diff --git a/PARR.DAL/NextRunServices/NextRunService.cs b/PARR.DAL/NextRunServices/NextRunService.cs index 7860a2ab..6b65980d 100644 --- a/PARR.DAL/NextRunServices/NextRunService.cs +++ b/PARR.DAL/NextRunServices/NextRunService.cs @@ -1,4 +1,5 @@  +using InfluxDB.Client.Api.Domain; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using PARR.Constants; @@ -127,9 +128,30 @@ namespace PARR.DAL.NextRunServices } - public async Task GetNextRunForJobGroupWithEsppSchedulleAsync(Guid jobGroupId) + //public async Task GetNextRunForJobGroupWithEsppSchedulleAsync(Guid jobGroupId) + //{ + // var jobGroup = await jobGroupService.Get().AsNoTracking().FirstOrDefaultAsync(t => t.Id == jobGroupId); + + // if (jobGroup == null) + // { + // logger.LogError("Не найдена группа работ с Id: {jobGroupId}.", jobGroupId); + // throw new ArgumentNullException(nameof(jobGroupId), $"Не найдена группа работ с Id: {jobGroupId}"); + // } + + // // Берем из обычного расписания ЕСПП + // return await esppScheduleTransformService.GetNextDateAsync(jobGroupId, jobGroup.ReferenceDate); + //} + + + public async Task GetNextRunForNewTemplateAsync(Guid jobGroupId) { - var jobGroup = await jobGroupService.Get().AsNoTracking().FirstOrDefaultAsync(t => t.Id == jobGroupId); + // определяю это автораспределение или нет, вызываю соответствующий рассчет + + var jobGroup = await jobGroupService.Get() + .Include(t => t.DistributionConfig) + .ThenInclude(t => t.DistributionPeriod) + .AsNoTracking() + .FirstOrDefaultAsync(t => t.Id == jobGroupId); if (jobGroup == null) { @@ -137,39 +159,103 @@ namespace PARR.DAL.NextRunServices throw new ArgumentNullException(nameof(jobGroupId), $"Не найдена группа работ с Id: {jobGroupId}"); } - // Берем из обычного расписания ЕСПП - return await esppScheduleTransformService.GetNextDateAsync(jobGroupId, jobGroup.ReferenceDate); + if (jobGroup.IsAutoDistributionEnabled) + { + // тут автораспределение + + if (jobGroup.DistributionConfig == null) + { + logger.LogError("Для группы работ {jobGroupId}, указано автораспределение, но отсутствует конфиг в таблице {GroupDistributionConfigs}", jobGroupId, nameof(JobGroupDistributionConfig)); + throw new ArgumentNullException(nameof(JobGroupDistributionConfig), $"Для jobGroupId: {jobGroupId} отсутствует конфигурация автораспределения в таблице {nameof(JobGroupDistributionConfig)}"); + } + + #region Вынести в одтельный метод, почти все повторяется + var dateStart = GetDateStart(jobGroup.ReferenceDate); + var duration = GetDurationDays(jobGroup.DistributionConfig); + + var result = await templateDistributor.GetValidNextRunForTemplateAsync(dateStart, + duration, + jobGroup.ReferenceDate, + new TemplateNextRunDto(Guid.Empty, null), + //TODO: тут пока не получаем список шаблонов, но позже, когда будем строить каждый раз план, нужно будет сюда передавать список связанных шаблонов + new List(), + jobGroup.DistributionConfig.IsExcludeWeekends, + isNew: true + ); + + #endregion + logger.LogDebug("Получил nextRun {nextRun} по jobGroupId {jobGroupId} для нового шаблона, тип расписания: автораспределение", result.NextRun, jobGroupId); + + return result.NextRun; + } + else + { + // тут расписание ЕСПП + var nextRun = await esppScheduleTransformService.GetNextDateAsync(jobGroup.Id, jobGroup.ReferenceDate); + logger.LogDebug("Получил nextRun {nextRun} по jobGroupId {jobGroupId}, тип расписания ЕСПП", nextRun, jobGroupId); + + return nextRun; + } } - public async Task GetNextRunForTemplate(Guid templateId, bool isNew) + public async Task GetNextRunForTemplateAsync(Guid templateId, bool isNew) { var template = await templateService.Get() - .Include(t => t.Job).ThenInclude(t => t.Group) + .Include(t => t.Job) + .ThenInclude(t => t.Group).ThenInclude(t => t.DistributionConfig).ThenInclude(t => t.DistributionPeriod) .AsNoTracking() .FirstOrDefaultAsync(t => t.Id == templateId); if (template == null) { - logger.LogError("Не найдена шаблон с Id: {templateId}.", templateId); - throw new ArgumentNullException(nameof(templateId), $"Не найдена шаблон с Id: {templateId}"); + logger.LogError("Не найден шаблон с Id: {templateId}.", templateId); + throw new ArgumentNullException(nameof(templateId), $"Не найден шаблон с Id: {templateId}"); } if (template.Job!.Group!.IsAutoDistributionEnabled == true) { // включено автораспределение - //TODO: !!!!!!!!!!!!!!!! добавить метод рассчета с учетом распределения - throw new NotImplementedException(); - //return await templateDistributor.GetValidNextRunForTemplateAsync(); + if (template.Job!.Group.DistributionConfig == null) + { + logger.LogError("Для шаблона {templateId}, jobGroupId {jobGroupId}, указано автораспределение, но отсутствует конфиг в таблице {GroupDistributionConfigs}", template.Id, template.Job.GroupId, nameof(JobGroupDistributionConfig)); + throw new ArgumentNullException(nameof(JobGroupDistributionConfig), $"Для jobGroupId: {template.Job.GroupId} отсутствует конфигурация автораспределения в таблице {nameof(JobGroupDistributionConfig)}"); + } + + #region Вынести в одтельный метод, почти все повторяется + var dateStart = GetDateStart(template.Job!.Group.ReferenceDate); + var duration = GetDurationDays(template.Job!.Group.DistributionConfig); + + var result = await templateDistributor.GetValidNextRunForTemplateAsync(dateStart, + duration, + template.Job.Group.ReferenceDate, + new TemplateNextRunDto(template.Id, template.NextRun), + //TODO: тут пока не получаем список шаблонов, но позже, когда будем строить каждый раз план, нужно будет сюда передавать список связанных шаблонов + new List(), + template.Job.Group.DistributionConfig.IsExcludeWeekends, + isNew + ); + #endregion + + logger.LogDebug("Получил nextRun {nextRun} по templateId {templateId}, isNew: {isNew}, тип расписания: автораспределение", result.NextRun, templateId, isNew); + + return result.NextRun; + } else { // считаем как ЕСПП - return await esppScheduleTransformService.GetNextDateAsync(template.Job.Group.Id, template.Job.Group.ReferenceDate); + var nextRun = await esppScheduleTransformService.GetNextDateAsync(template.Job.Group.Id, template.Job.Group.ReferenceDate); + logger.LogDebug("Получил nextRun {nextRun} по templateId {templateId}, isNew: {isNew}, тип расписания: ЕСПП", nextRun, templateId, isNew); + + return nextRun; } } + + + /// /// Получить продолжительность в днях /// diff --git a/PARR.Test/NextRun/NextRunTest.cs b/PARR.Test/NextRun/NextRunTest.cs index f6c905bf..48dbe1a9 100644 --- a/PARR.Test/NextRun/NextRunTest.cs +++ b/PARR.Test/NextRun/NextRunTest.cs @@ -23,7 +23,14 @@ namespace PARR.Test.NextRun //await DistributeTemplatesAsync(); //await GetValidNextRunForTemplateAsync(); - var result = await nextRunService.GetNextRunForJobGroupWithAutoDistributionAsync(Guid.Parse("eadc5498-dba6-4f10-9b4b-a1653e3c3e61")); + // распределить шаблоны (не сохраняя в БД) + //var result = await nextRunService.GetNextRunForJobGroupWithAutoDistributionAsync(Guid.Parse("eadc5498-dba6-4f10-9b4b-a1653e3c3e61")); + + // получить nextRun для еще не созданного шаблона + //var nextRunForNullTemplate = await nextRunService.GetNextRunForNewTemplateAsync(Guid.Parse("eadc5498-dba6-4f10-9b4b-a1653e3c3e61")); + + // получить nextRun для существующего шаблона + // var nextRunForExistTemplate = await nextRunService.GetNextRunForTemplateAsync(Guid.Parse("20fc3581-984e-4c9a-8b46-8a55c3401725"), false); } From e5bc42741c71aaebfac762e670074a2436e737f9 Mon Sep 17 00:00:00 2001 From: Mikhail Trubnikov Date: Wed, 21 Jan 2026 16:28:17 +1000 Subject: [PATCH 3/6] =?UTF-8?q?feat(templateDistributor):=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../V1/Requests/DistributeRequest.cs | 2 +- .../Controllers/V1/DistributorController.cs | 6 +- .../Validators/DistributeRequestValidator.cs | 25 +- PARR.BLL/Domain/Mq/TemplateDistributorMq.cs | 4 +- .../ITemplateDistributor.cs | 18 +- .../MqTemplateDistributor.cs | 10 +- .../Services/IValidatorService.cs | 2 +- .../Services/ValidatorService.cs | 38 +- .../TemplateDistributor.cs | 416 +----------------- PARR.TemplateDistributorWorker/Worker.cs | 12 +- docker-compose.template-distributor.yml | 2 +- 11 files changed, 65 insertions(+), 470 deletions(-) diff --git a/PARR.API/Contracts/V1/Requests/DistributeRequest.cs b/PARR.API/Contracts/V1/Requests/DistributeRequest.cs index 26b81422..1930a6b4 100644 --- a/PARR.API/Contracts/V1/Requests/DistributeRequest.cs +++ b/PARR.API/Contracts/V1/Requests/DistributeRequest.cs @@ -2,6 +2,6 @@ { public class DistributeRequest { - public Guid ApplicationInWorkId { get; set; } + public Guid JobGroupId { get; set; } } } diff --git a/PARR.API/Controllers/V1/DistributorController.cs b/PARR.API/Controllers/V1/DistributorController.cs index f102f938..31975fca 100644 --- a/PARR.API/Controllers/V1/DistributorController.cs +++ b/PARR.API/Controllers/V1/DistributorController.cs @@ -36,7 +36,7 @@ namespace PARR.API.Controllers.V1 /// - /// Перераспределить шаблоны для регламентной работы + /// Перераспределить шаблоны для группы работ /// /// [HttpPost(ApiRoutes.Distributor.Distribute)] @@ -48,7 +48,7 @@ namespace PARR.API.Controllers.V1 var requestToMq = new TemplateDistributorMq { - ApplicationInWorkId = request.ApplicationInWorkId + JobGroupId = request.JobGroupId }; var msg = JsonSerializer.Serialize(requestToMq); @@ -58,7 +58,7 @@ namespace PARR.API.Controllers.V1 if (sendResult.IsSuccess) return Created("", new Response(null, true, new List(), "Отправлен запрос на перераспределение регламентных работ.")); else - return BadRequest(new Response(false, new List { new ErrorModel { Message="Ошибка при отправке данных."} })); + return BadRequest(new Response(false, new List { new ErrorModel { Message = "Ошибка при отправке данных." } })); } } diff --git a/PARR.API/Validators/DistributeRequestValidator.cs b/PARR.API/Validators/DistributeRequestValidator.cs index 2f051a46..f7826eae 100644 --- a/PARR.API/Validators/DistributeRequestValidator.cs +++ b/PARR.API/Validators/DistributeRequestValidator.cs @@ -1,24 +1,27 @@ using FluentValidation; +using Microsoft.EntityFrameworkCore; using PARR.API.Contracts.V1.Requests; -using PARR.DAL.Services.Interfaces; +using PARR.DAL.Services.Interfaces.Job; namespace PARR.API.Validators { public class DistributeRequestValidator : AbstractValidator { - private readonly IApplicationsInWorkService applicationsInWorkService; - - public DistributeRequestValidator(IApplicationsInWorkService applicationsInWorkService) + public DistributeRequestValidator(IJobGroupService jobGroupService) { - this.applicationsInWorkService = applicationsInWorkService; - - - RuleFor(t => t.ApplicationInWorkId).NotEmpty().MustAsync(async (entity, value, c) => + RuleFor(t => t.JobGroupId).NotEmpty().MustAsync(async (entity, value, c) => { - var appInWork = await applicationsInWorkService.GetAsync(value); - - return appInWork != null; + return await jobGroupService.Get().FirstOrDefaultAsync(t => t.Id == value) != null; }).WithMessage("Недопустимое значение"); + + RuleFor(t => t.JobGroupId).NotEmpty().MustAsync(async (entity, value, c) => + { + var jobGroup = await jobGroupService.Get() + .Include(t => t.DistributionConfig) + .FirstOrDefaultAsync(t => t.Id == value); + + return jobGroup != null && jobGroup.IsAutoDistributionEnabled && jobGroup.DistributionConfig != null; + }).WithMessage("Отсутствуют настройки автораспределения"); } } } diff --git a/PARR.BLL/Domain/Mq/TemplateDistributorMq.cs b/PARR.BLL/Domain/Mq/TemplateDistributorMq.cs index 38bcfd5e..82bb7d4a 100644 --- a/PARR.BLL/Domain/Mq/TemplateDistributorMq.cs +++ b/PARR.BLL/Domain/Mq/TemplateDistributorMq.cs @@ -1,10 +1,10 @@ namespace PARR.BLL.Domain.Mq { /// - /// Модель в MQ, обновления расписаний шаблонов связанных с РР (для TemplateDistributor) + /// Модель в MQ, распределить шаблоны для JobGroupId (для TemplateDistributor) /// public class TemplateDistributorMq { - public Guid ApplicationInWorkId { get; set; } + public Guid JobGroupId { get; set; } } } diff --git a/PARR.TemplateDistributor/ITemplateDistributor.cs b/PARR.TemplateDistributor/ITemplateDistributor.cs index c28dd8ac..a819104d 100644 --- a/PARR.TemplateDistributor/ITemplateDistributor.cs +++ b/PARR.TemplateDistributor/ITemplateDistributor.cs @@ -1,22 +1,12 @@ -using PARR.DAL.Models; - -namespace PARR.TemplateDistributor +namespace PARR.TemplateDistributor { public interface ITemplateDistributor { /// - /// Формирует расписание запуска для шаблонов относительно одной РР (без сохранения в БД), (реализует оба режима распределения РР) + /// Обновляет NextRun (сохраняет в БД) /// - /// - /// + /// /// - Task> DistributeTemplateAsync(List