using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using PARR.BLL.Domain.Mq; using PARR.BLL.Helpers; using PARR.Constants; using PARR.DAL.Contracts; using PARR.DAL.Extensions; using PARR.DAL.Models; using PARR.DAL.Services.Interfaces; using System.Text.Json; namespace PARR.GeneratorTemplates.Services { internal class TemplateManager : ITemplateManager { private readonly ITemplateService templateService; private readonly IHostService hostService; private readonly ILogger logger; private readonly SettingsFromDb settingsFromDb; private readonly IRobotConfigurationService robotConfigurationService; private readonly IApplicationsInWorkService applicationsInWorkService; public TemplateManager( ITemplateService templateService, IHostService hostService, ILogger logger, SettingsFromDb settingsFromDb, IRobotConfigurationService robotConfigurationService, IApplicationsInWorkService applicationsInWorkService ) { this.templateService = templateService; this.hostService = hostService; this.logger = logger; this.settingsFromDb = settingsFromDb; this.robotConfigurationService = robotConfigurationService; this.applicationsInWorkService = applicationsInWorkService; } public async Task CreateTemplates(GeneratorTemplateMq query) { //В таблице AppInWork находим РР, и смотрим ее рабочие группы. Затем по ним будем фильтровать хосты var appInWorkWg = await applicationsInWorkService.Get() .Include(t => t.WorkGroups) .FirstAsync(t => t.ApplicationId == query.ApplicationId && t.WorkId == query.WorkId); if (!appInWorkWg.WorkGroups.Any()) { logger.LogWarning($"Не генерирую шаблоны. Нет рабочих групп у ApplicationInWork с id: {appInWorkWg.Id}"); return; } var workGroups = appInWorkWg.WorkGroups.ToList(); //Согласно параметрам, находит все ЭК в таблице Hosts. //Далее проверяет есть ли такие шаблоны в таблице Templates, если нет, то создает, активирует и ставит статус Creating. //Если такие шаблоны уже есть, ничего с ними не делает. string ekPattern = SqlHelpers.RegexToLike(query.Ek); // список хостов для создания шаблонов var queryHosts = hostService.Get() //.Include(t => t.WorkGroupItem) .Include(t => t.ApplicationsInHosts) .ThenInclude(t => t.Application).ThenInclude(t => t!.ApplicationsInWorks).ThenInclude(w => w.Work) .Include(t => t.Templates) .ThenInclude(w => w.ApplicationsInWork) .Include(t => t.ResponseArea) .Where(t => t.ApplicationsInHosts.Any(h => h.ApplicationId == query.ApplicationId && h.Application!.ApplicationsInWorks.Any(w => w.WorkId == query.WorkId) ) && EF.Functions.Like(t.Ek.ToLower(), ekPattern) // смотрим что нет такого шаблона && t.Templates.Any(templ => templ.ApplicationsInWork!.WorkId == query.WorkId && templ.ApplicationsInWork.ApplicationId == query.ApplicationId) == false // смотрим что у этих хостов есть нужные группы //&& workGroups.Any(x => x.WorkGroupId == t.WorkGroupId) ); // статус ЭК if (query.StatusEk > 0) queryHosts = queryHosts.Where(t => t.EkStatusCode == query.StatusEk); var hosts = await queryHosts .AsSplitQuery() .ToListAsync(); // Исключаем хосты у которых нет нужных групп hosts = hosts.Where(t => workGroups.Any(x => x.WorkGroupId == t.WorkGroupId)).ToList(); if (!hosts.Any()) { logger.LogInformation($"Не найдено ЭК попадающих под условие: ${JsonSerializer.Serialize(query)}"); return; } //Создаем шаблоны foreach (var host in hosts) { var appInWork = host.ApplicationsInHosts.FirstOrDefault(t => t.ApplicationId == query.ApplicationId)?.Application?.ApplicationsInWorks.FirstOrDefault(a => a.WorkId == query.WorkId); if (appInWork == null) { // такого не может быть, так как выполнился запрос при получении списка хостов, но мало ли logger.LogError($"Ошибка при создании шаблона. В таблице ApplicationsInWorks не найден Id согласно запроса WorkId: {query.WorkId}, ApplicationId: {query.ApplicationId}"); return; } var template = new Template { Id = Guid.NewGuid(), //TODO:!!! //Name = TemplateHelpers.GenerateTemplateName("ЗО" ,settingsFromDb.TemplatePrefixName, host.Ek, appInWork.Work!.Name), //Генерить имя с полным именем работы и подстановкой ЭК //Name = TemplateHelpers.GenerateTemplateNameWithResponseArea(host.ResponseArea!.Name, settingsFromDb.TemplatePrefixName, host.Ek, appInWork.Work!.Name.ApplyShortcode(Constants.Shortcode.Shortcodes.EK, host.Ek)), //Вместо полного имени работы, подставляется сокращенный суффикс или полное имя с ЭК если суффикса нет Name = TemplateHelpers.GenerateTemplateNameWithResponseArea( host.ResponseArea!.Name, settingsFromDb.TemplatePrefixName, host.Ek, appInWork.Work!.TemplateSuffix ?? appInWork.Work!.Name.ApplyShortcode(Constants.Shortcode.Shortcodes.EK, host.Ek) ), //IsActiveTemplate = true, //IsActiveSchedule = true, IsActiveTemplate = query.IsActiveTemplate ?? false, IsActiveSchedule = query.IsActiveSchedule ?? false, ApplicationInWorkId = appInWork.Id, HostId = host.Id }; if (!await templateService.CreateAsync(template) || !await templateService.CommitAsync()) { logger.LogError($"Ошибка при создании шаблона: Name: {template.Name}, ApplicationInWorkId: {template.ApplicationInWorkId}, HostId: {template.HostId}"); } else { logger.LogInformation($"Создан шаблон: Name: {template.Name}, ApplicationInWorkId: {template.ApplicationInWorkId}, " + $"HostId: {template.HostId}"); } } } public async Task DeactivateTemplates(GeneratorTemplateMq query) { //TODO: !!! тут не учитываются поля query.IsActiveTemplate, query.IsActiveSchedule, просто все деактивируется. !!! //В таблице AppInWork находим РР, и смотрим ее рабочие группы. Затем по ним будем фильтровать хосты var appInWorkWg = await applicationsInWorkService.Get() .Include(t => t.WorkGroups) .FirstAsync(t => t.ApplicationId == query.ApplicationId && t.WorkId == query.WorkId); if (!appInWorkWg.WorkGroups.Any()) { logger.LogWarning($"Не деактивируем шаблоны. Нет рабочих групп у ApplicationInWork с id: {appInWorkWg.Id}"); return; } var workGroups = appInWorkWg.WorkGroups.ToList(); //Ищет все активные шаблоны согласно параметрам в таблице Templates, и деактивирует их. Меняем на статус Updating // делаем sql формат для like из запроса. string ekPattern = SqlHelpers.RegexToLike(query.Ek); var queryTemplates = templateService.Get() .Include(t => t.Host) .Include(t => t.ApplicationsInWork) .Include(t => t.RobotConfigurations) .Where(t => (t.IsActiveTemplate == true || t.IsActiveSchedule == true) && t.ApplicationsInWork!.ApplicationId == query.ApplicationId && t.ApplicationsInWork!.WorkId == query.WorkId && EF.Functions.Like(t.Host!.Ek.ToLower(), ekPattern) ); // статус ЭК if (query.StatusEk > 0) queryTemplates = queryTemplates.Where(t => t.Host!.EkStatusCode == query.StatusEk); var existTemplates = await queryTemplates .AsSplitQuery() .ToListAsync(); // Исключаем хосты у которых нет нужных групп existTemplates = existTemplates.Where(t => workGroups.Any(x => x.WorkGroupId == t.Host.WorkGroupId)).ToList(); if (!existTemplates.Any()) { logger.LogInformation("Нет шаблонов для деактивации"); return; } existTemplates.ForEach(item => { item.DateModified = DateTimeOffset.UtcNow; if (item.IsActiveTemplate) { item.IsActiveTemplate = false; //необходимо обновить шаблон var config = robotConfigurationService.GetFromTemplateByRobotCode(RobotsEnum.TemplateOrder, ref item); robotConfigurationService.ChangeTaskStatus(TaskStatusEnum.Updating, ref config); } if (item.IsActiveSchedule) { item.IsActiveSchedule = false; //необходимо обновить расписание var config = robotConfigurationService.GetFromTemplateByRobotCode(RobotsEnum.ScheduleOrder, ref item); robotConfigurationService.ChangeTaskStatus(TaskStatusEnum.Updating, ref config); } }); if (await templateService.CommitAsync()) existTemplates.ForEach(item => logger.LogInformation($"Деактивирован шаблон: {item.Name}")); else existTemplates.ForEach(item => logger.LogError($"Ошибка при дактивации шаблона: {item.Name}")); } } }