From ff58a21cc52db4d1173ba72a6a07137b0bd2fef2 Mon Sep 17 00:00:00 2001 From: Mikhail Trubnikov Date: Wed, 3 Jul 2024 10:16:54 +1000 Subject: [PATCH] =?UTF-8?q?feat(api):=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20AppInWorkController=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=B9=20=D1=80=D0=B5=D1=81=D0=BF?= =?UTF-8?q?=D0=BE=D0=BD=D1=81,=20=D0=B2=D0=B0=D0=BB=D0=B8=D0=B4=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D0=B4=D0=BB=D1=8F=20=D0=B3=D0=B0=D0=BB?= =?UTF-8?q?=D0=BA=D0=B8=20IsAutoDistributionEnabled?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../V1/Requests/ApplicationInWorkRequest.cs | 12 ++- .../V1/Responses/ApplicationInWorkResponse.cs | 10 ++- .../V1/ApplicationInWorkController.cs | 73 ++++++++++++++++++- PARR.API/Settings/MqSettings.cs | 9 +++ .../Validators/ApplicationInWorkValidator.cs | 34 ++++++++- PARR.API/appsettings.Development.json | 3 + PARR.API/appsettings.json | 6 ++ PARR.DAL/Models/ApplicationsInWork.cs | 1 - PARR.DAL/ParrDalInstaller.cs | 1 + .../EsppSchTypeValueService.cs | 23 ++++++ .../Interfaces/IEsppSchTypeValueService.cs | 9 +++ 11 files changed, 172 insertions(+), 9 deletions(-) create mode 100644 PARR.DAL/Services/Implementations/EsppSchTypeValueService.cs create mode 100644 PARR.DAL/Services/Interfaces/IEsppSchTypeValueService.cs diff --git a/PARR.API/Contracts/V1/Requests/ApplicationInWorkRequest.cs b/PARR.API/Contracts/V1/Requests/ApplicationInWorkRequest.cs index 90c4eb80..eb6df60b 100644 --- a/PARR.API/Contracts/V1/Requests/ApplicationInWorkRequest.cs +++ b/PARR.API/Contracts/V1/Requests/ApplicationInWorkRequest.cs @@ -15,7 +15,17 @@ public required string Solution { get; set; } - public DateTimeOffset NextRun { get; set; } + //public DateTimeOffset NextRun { get; set; } + + /// + /// Дата начала работ + /// + public DateTimeOffset ReferenceDate { get; set; } + + /// + /// Включить автораспределение + /// + public bool IsAutoDistributionEnabled { get; set; } public bool IsAgent { get; set; } diff --git a/PARR.API/Contracts/V1/Responses/ApplicationInWorkResponse.cs b/PARR.API/Contracts/V1/Responses/ApplicationInWorkResponse.cs index 5d25ff4c..94ee6f13 100644 --- a/PARR.API/Contracts/V1/Responses/ApplicationInWorkResponse.cs +++ b/PARR.API/Contracts/V1/Responses/ApplicationInWorkResponse.cs @@ -12,9 +12,13 @@ public required string Solution { get; set; } - public DateTimeOffset? LastRun { get; set; } + //public DateTimeOffset? LastRun { get; set; } - public DateTimeOffset NextRun { get; set; } + //public DateTimeOffset NextRun { get; set; } + + public DateTimeOffset ReferenceDate { get; set; } + + public bool IsAutoDistributionEnabled { get; set; } public bool IsAgent { get; set; } @@ -32,7 +36,7 @@ public ApplicationInWorkScheduleResponse? Schedule { get; set; } - public List? WorkGroups { get; set; } + public List? WorkGroups { get; set; } } diff --git a/PARR.API/Controllers/V1/ApplicationInWorkController.cs b/PARR.API/Controllers/V1/ApplicationInWorkController.cs index 3c4d1dca..96d19cac 100644 --- a/PARR.API/Controllers/V1/ApplicationInWorkController.cs +++ b/PARR.API/Controllers/V1/ApplicationInWorkController.cs @@ -11,10 +11,14 @@ using PARR.API.Contracts.V1.Responses.Base; using PARR.API.Controllers.V1.Base; using PARR.API.Extensions; using PARR.API.Services.Interfaces; +using PARR.API.Settings; +using PARR.BLL.Domain.Mq; +using PARR.BLL.Services.Interfaces; using PARR.Constants; using PARR.DAL.DomainModels; using PARR.DAL.Models; using PARR.DAL.Services.Interfaces; +using System.Text.Json; namespace PARR.API.Controllers.V1 { @@ -27,6 +31,8 @@ namespace PARR.API.Controllers.V1 private readonly IValidator validator; private readonly IUriService uriService; private readonly ITemplateService templateService; + private readonly IMqService mqService; + private readonly MqSettings mqSettings; public ApplicationInWorkController( ILogger logger, @@ -34,7 +40,9 @@ namespace PARR.API.Controllers.V1 IApplicationsInWorkService applicationsInWorkService, IValidator validator, IUriService uriService, - ITemplateService templateService + ITemplateService templateService, + IMqService mqService, + MqSettings mqSettings ) { this.logger = logger; @@ -43,6 +51,8 @@ namespace PARR.API.Controllers.V1 this.validator = validator; this.uriService = uriService; this.templateService = templateService; + this.mqService = mqService; + this.mqSettings = mqSettings; } @@ -147,7 +157,9 @@ namespace PARR.API.Controllers.V1 ShortDescription = request.ShortDescription.Trim(), FullDescription = request.FullDescription.Trim(), Solution = request.Solution.Trim(), - NextRun = request.NextRun, + //NextRun = request.NextRun, + IsAutoDistributionEnabled = request.IsAutoDistributionEnabled, + ReferenceDate = request.ReferenceDate, IsAgent = request.IsAgent, AgentName = request.AgentName?.Trim(), AgentTimeOutSec = request.AgentTimeOutSec, @@ -225,13 +237,18 @@ namespace PARR.API.Controllers.V1 if (orig == null) return BadRequest(new Response(false, new List { new ErrorModel { Message = $"Ошибка при изменении задания на выполнение работ. Не найдено задание с Id: {id}" } })); + //Расписание было изменено, ниже добавим задание в очередь на обновление расписаний у связанных шаблонов + var isScheduleChanged = IsScheduleChanged(orig, request); + orig.WorkId = request.WorkId; orig.ApplicationId = request.ApplicationId; orig.TemplateDuration = request.TemplateDuration; orig.ShortDescription = request.ShortDescription.Trim(); orig.FullDescription = request.FullDescription.Trim(); orig.Solution = request.Solution.Trim(); - orig.NextRun = request.NextRun; + //orig.NextRun = request.NextRun; + orig.ReferenceDate = request.ReferenceDate; + orig.IsAutoDistributionEnabled = request.IsAutoDistributionEnabled; orig.IsAgent = request.IsAgent; orig.AgentName = request.AgentName?.Trim(); orig.AgentTimeOutSec = request.AgentTimeOutSec; @@ -270,6 +287,26 @@ namespace PARR.API.Controllers.V1 $" {orig.FullDescription}, {orig.Solution}, {orig.NextRun}, {orig.IsAgent}, {orig.AgentName}, {orig.AgentTimeOutSec}, {orig.AgentScript}"); + if (isScheduleChanged) + { + //расписание было обновлено, отправим задание в очередь на перерасчет NextRun + var requestToMq = new TemplateDistributorMq + { + ApplicationInWorkId = id + }; + + var msg = JsonSerializer.Serialize(requestToMq); + + logger.LogDebug($"Расписание в РР applicationInWorkId: {id} было изменено. Отправляем задание в очередь на перерасчет NextRun"); + + var sendResult = mqService.Send(mqSettings.TemplateDistributor, new[] { msg }); + + if (sendResult.IsSuccess) + logger.LogInformation($"Задание на перерасчет NextRun успешно отправлено в очередь MQ {mqSettings.TemplateDistributor.QueueName}"); + else + logger.LogError($"Ошибка при отправке задания на перерасчет NextRun в очередь MQ {mqSettings.TemplateDistributor.QueueName}"); + } + var updatedApplicationInWork = await applicationsInWorkService.Get() .Include(t => t.Application).ThenInclude(t => t!.ApplicationType) .Include(t => t.Work) @@ -322,5 +359,35 @@ namespace PARR.API.Controllers.V1 return NoContent(); } + + + /// + /// Проверка, были ли изменения в расписании + /// + /// + /// + /// + private bool IsScheduleChanged(ApplicationsInWork orig, ApplicationInWorkRequest request) + { + var isScheduleChanged = false; + + if (orig.ReferenceDate != request.ReferenceDate) + isScheduleChanged = true; + + if (request.Schedule.Count() != orig.EsppSchValues.Count()) + isScheduleChanged = true; + + request.Schedule.ForEach(requestSchedule => + { + var schExist = orig.EsppSchValues.FirstOrDefault(t => t.ApplicationsInWorkId == orig.Id + && t.TypeValueId == requestSchedule.TypeValueId + && t.TypeConfigId == requestSchedule.TypeConfigId); + + if (schExist == null) + isScheduleChanged = true; + }); + + return isScheduleChanged; + } } } diff --git a/PARR.API/Settings/MqSettings.cs b/PARR.API/Settings/MqSettings.cs index 7cee6dae..7989cb5c 100644 --- a/PARR.API/Settings/MqSettings.cs +++ b/PARR.API/Settings/MqSettings.cs @@ -5,6 +5,7 @@ namespace PARR.API.Settings public class MqSettings { public MqGenerateTemplates GenerateTemplates { get; set; } = new MqGenerateTemplates(); + public MqTemplateDistributor TemplateDistributor { get; set; } = new MqTemplateDistributor(); public MqStatistics Statistics { get; set; } = new MqStatistics(); } @@ -16,6 +17,14 @@ namespace PARR.API.Settings public string Password { get; set; } = string.Empty; } + public class MqTemplateDistributor : IMqSettings + { + public string HostName { get; set; } = string.Empty; + public string QueueName { get; set; } = string.Empty; + public string User { get; set; } = string.Empty; + public string Password { get; set; } = string.Empty; + } + public class MqStatistics { public StatMqAuth StatMqAuth { get; set; } = new StatMqAuth(); diff --git a/PARR.API/Validators/ApplicationInWorkValidator.cs b/PARR.API/Validators/ApplicationInWorkValidator.cs index f973f46f..f953c81d 100644 --- a/PARR.API/Validators/ApplicationInWorkValidator.cs +++ b/PARR.API/Validators/ApplicationInWorkValidator.cs @@ -1,5 +1,6 @@ using FluentValidation; using Microsoft.EntityFrameworkCore; +using Newtonsoft.Json.Linq; using PARR.API.Contracts.V1.Requests; using PARR.DAL.Services.Interfaces; @@ -11,18 +12,21 @@ namespace PARR.API.Validators private readonly IWorkService workService; private readonly IEsppSchTypeConfigService esppSchTypeConfigService; private readonly IWorkGroupService workGroupService; + private readonly IEsppSchTypeValueService esppSchTypeValueService; public ApplicationInWorkValidator( IApplicationsInWorkService applicationsInWorkService, IWorkService workService, IEsppSchTypeConfigService esppSchTypeConfigService, - IWorkGroupService workGroupService + IWorkGroupService workGroupService, + IEsppSchTypeValueService esppSchTypeValueService ) { this.applicationsInWorkService = applicationsInWorkService; this.workService = workService; this.esppSchTypeConfigService = esppSchTypeConfigService; this.workGroupService = workGroupService; + this.esppSchTypeValueService = esppSchTypeValueService; RuleFor(t => t.TemplateDuration) .NotNull().NotEmpty()//.WithMessage("Длительность данного задания на выполнение работ не может быть пустым") @@ -96,8 +100,36 @@ namespace PARR.API.Validators RuleFor(t => t.WorkGroups) .MustAsync(async (entity, value, c) => await IsWorkGroupsExistAsync(entity)) .WithMessage("Указаные несуществующие Id рабочих групп"); + + + //Автораспределение может быть включено, только если у EsppSchTypeValues не пустое поле DistributionPeriodId + RuleFor(t => t.IsAutoDistributionEnabled) + .MustAsync(async (entity, value, c) => await IsAllowAutoDistributionEnabledAsync(entity, value)) + .WithMessage("Нельзя включить автораспределение для этого типа расписания"); } + + private async Task IsAllowAutoDistributionEnabledAsync(ApplicationInWorkRequest entity, bool value) + { + //Автораспределение может быть включено, только если у EsppSchTypeValues не пустое поле DistributionPeriodId + + if (value == false) + return true; + + //Распределение включено, смотрим, разрешено ли оно в расписании + //по идее, это расписание только с одним значением в EsppSchValues, но мы проверим у всех, но такого быть не может по хорошему + foreach (var item in entity.Schedule) + { + var schVal = await esppSchTypeValueService.GetAsync(item.TypeValueId); + if (schVal != null) + if (schVal.DistributionPeriodId == null) + return false; + } + + return true; + } + + private async Task IsWorkGroupsExistAsync(ApplicationInWorkRequest entity) { var result = await workGroupService.Get().Where(t => entity.WorkGroups.Contains(t.Id)).ToListAsync(); diff --git a/PARR.API/appsettings.Development.json b/PARR.API/appsettings.Development.json index 56f9d92b..b1f1d5d6 100644 --- a/PARR.API/appsettings.Development.json +++ b/PARR.API/appsettings.Development.json @@ -24,6 +24,9 @@ "GenerateTemplates": { "HostName": "10.99.253.216" }, + "TemplateDistributor": { + "HostName": "10.99.253.216" + }, "Statistics": { "StatMqAuth": { "HostName": "10.99.253.216" diff --git a/PARR.API/appsettings.json b/PARR.API/appsettings.json index 31ed1be8..22c4c29d 100644 --- a/PARR.API/appsettings.json +++ b/PARR.API/appsettings.json @@ -45,6 +45,12 @@ "User": "generate_templates_api", "Password": "DHhjgdsf*&%95" }, + "TemplateDistributor": { + "HostName": "parr-rabbitmq", + "QueueName": "parr-template-distributor", + "User": "espp_template_distributor_writer", + "Password": "KGgsdfu%%44qqwew" + }, "Statistics": { "StatMqAuth": { "HostName": "parr-rabbitmq", diff --git a/PARR.DAL/Models/ApplicationsInWork.cs b/PARR.DAL/Models/ApplicationsInWork.cs index 0e4bbde1..3e76cdeb 100644 --- a/PARR.DAL/Models/ApplicationsInWork.cs +++ b/PARR.DAL/Models/ApplicationsInWork.cs @@ -89,7 +89,6 @@ namespace PARR.DAL.Models /// public DateTimeOffset ReferenceDate { get; set; } - /// /// Выполняет агент /// diff --git a/PARR.DAL/ParrDalInstaller.cs b/PARR.DAL/ParrDalInstaller.cs index 86519ec0..79394dde 100644 --- a/PARR.DAL/ParrDalInstaller.cs +++ b/PARR.DAL/ParrDalInstaller.cs @@ -82,6 +82,7 @@ namespace PARR.DAL services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); // TransformServices services.AddTransient(); diff --git a/PARR.DAL/Services/Implementations/EsppSchTypeValueService.cs b/PARR.DAL/Services/Implementations/EsppSchTypeValueService.cs new file mode 100644 index 00000000..cd177f68 --- /dev/null +++ b/PARR.DAL/Services/Implementations/EsppSchTypeValueService.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using PARR.DAL.Context; +using PARR.DAL.Models; +using PARR.DAL.Services.Abstracts; +using PARR.DAL.Services.Interfaces; + +namespace PARR.DAL.Services.Implementations +{ + internal class EsppSchTypeValueService : BaseService, IEsppSchTypeValueService + { + private readonly DataContext dataContext; + + protected override DbSet EntitySet => dataContext.EsppSchTypeValues; + + protected override DataContext EntitiContext => dataContext; + + public EsppSchTypeValueService(DataContext dataContext, ILogger logger): base(logger) + { + this.dataContext = dataContext; + } + } +} diff --git a/PARR.DAL/Services/Interfaces/IEsppSchTypeValueService.cs b/PARR.DAL/Services/Interfaces/IEsppSchTypeValueService.cs new file mode 100644 index 00000000..12746ddd --- /dev/null +++ b/PARR.DAL/Services/Interfaces/IEsppSchTypeValueService.cs @@ -0,0 +1,9 @@ +using PARR.DAL.Models; +using PARR.DAL.Services.Interfaces.Base; + +namespace PARR.DAL.Services.Interfaces +{ + public interface IEsppSchTypeValueService : IBaseService + { + } +}