2023-09-22 15:30:57 +10:00
using Microsoft.EntityFrameworkCore ;
using Microsoft.Extensions.Logging ;
using PARR.BLL.Domain.Mq ;
2023-09-25 11:47:13 +10:00
using PARR.BLL.Helpers ;
2023-11-22 12:04:33 +10:00
using PARR.Constants ;
2023-09-22 15:30:57 +10:00
using PARR.DAL.Contracts ;
2024-03-20 15:26:14 +10:00
using PARR.DAL.Extensions ;
2023-09-25 11:47:13 +10:00
using PARR.DAL.Models ;
2023-09-22 15:30:57 +10:00
using PARR.DAL.Services.Interfaces ;
2024-07-03 12:01:46 +10:00
using PARR.TemplateDistributor ;
2023-09-25 11:47:13 +10:00
using System.Text.Json ;
2023-09-22 15:30:57 +10:00
namespace PARR.GeneratorTemplates.Services
{
internal class TemplateManager : ITemplateManager
{
private readonly ITemplateService templateService ;
2023-09-25 11:47:13 +10:00
private readonly IHostService hostService ;
2023-09-22 15:30:57 +10:00
private readonly ILogger < TemplateManager > logger ;
2023-09-25 11:47:13 +10:00
private readonly SettingsFromDb settingsFromDb ;
2023-10-05 16:56:02 +10:00
private readonly IRobotConfigurationService robotConfigurationService ;
2024-06-04 12:03:15 +10:00
private readonly IApplicationsInWorkService applicationsInWorkService ;
2024-07-03 12:01:46 +10:00
private readonly ITemplateDistributor templateDistributor ;
2023-09-22 15:30:57 +10:00
public TemplateManager (
ITemplateService templateService ,
2023-09-25 11:47:13 +10:00
IHostService hostService ,
ILogger < TemplateManager > logger ,
2023-10-05 16:56:02 +10:00
SettingsFromDb settingsFromDb ,
2024-06-04 12:03:15 +10:00
IRobotConfigurationService robotConfigurationService ,
2024-07-03 12:01:46 +10:00
IApplicationsInWorkService applicationsInWorkService ,
ITemplateDistributor templateDistributor
2023-09-22 15:30:57 +10:00
)
{
this . templateService = templateService ;
2023-09-25 11:47:13 +10:00
this . hostService = hostService ;
2023-09-22 15:30:57 +10:00
this . logger = logger ;
2023-09-25 11:47:13 +10:00
this . settingsFromDb = settingsFromDb ;
2023-10-05 16:56:02 +10:00
this . robotConfigurationService = robotConfigurationService ;
2024-06-04 12:03:15 +10:00
this . applicationsInWorkService = applicationsInWorkService ;
2024-07-03 12:01:46 +10:00
this . templateDistributor = templateDistributor ;
2023-09-22 15:30:57 +10:00
}
public async Task CreateTemplates ( GeneratorTemplateMq query )
{
2025-06-25 14:17:34 +10:00
//TODO Migratin to Job
////В таблице AppInWork находим Р Р , и смотрим е е рабочие группы. Затем по ним будем фильтровать хосты
//var appInWorkWg = await applicationsInWorkService.Get()
// .Include(t => t.WorkGroups)
// .FirstAsync(t => t.ApplicationId == query.ApplicationId && t.WorkId == query.WorkId);
2023-09-25 15:32:22 +10:00
2025-06-25 14:17:34 +10:00
//if (!appInWorkWg.WorkGroups.Any())
//{
// logger.LogWarning($"Н е генерирую шаблоны. Нет рабочих групп у ApplicationInWork с id: {appInWorkWg.Id}");
// return;
//}
2023-09-25 11:47:13 +10:00
2025-06-25 14:17:34 +10:00
//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;
//}
2023-09-25 11:47:13 +10:00
2025-06-25 14:17:34 +10:00
//// хосты группируем по РГ, чтоб потом распределить/рассчитать NextRun
//var groupingHostByWg = hosts.GroupBy(t => t.WorkGroupId);
2024-07-03 12:01:46 +10:00
2025-06-25 14:17:34 +10:00
//foreach (var group in groupingHostByWg)
//{
// var groupingHosts = group.ToList();
2024-07-03 12:01:46 +10:00
2025-06-25 14:17:34 +10:00
// var templates = CreateQueryTemplates(groupingHosts, query);
2024-07-03 12:01:46 +10:00
2025-06-25 14:17:34 +10:00
// //проверяем, что нет шаблонов с такими именами, исключаем их
// templates = await ExcludeExistTemplatesAsync(templates);
// if (!templates.Any())
// continue;
2024-09-16 09:30:28 +10:00
2025-06-25 14:17:34 +10:00
// //заполняем NextRun
// templates = await templateDistributor.DistributeTemplateAsync(templates, appInWorkWg.Id, (Guid)group.Key!);
2024-07-03 12:01:46 +10:00
2025-06-25 14:17:34 +10:00
// // сохраняем
// foreach (var template in templates)
// {
// if (!await templateService.CreateAsync(template) || !await templateService.CommitAsync(query.HistoryInitiator))
// {
// logger.LogError($"Ошибка при создании шаблона: Name: {template.Name}, ApplicationInWorkId: {template.ApplicationInWorkId}, HostId: {template.HostId}");
// }
// else
// {
// logger.LogInformation($"Создан шаблон: Name: {template.Name}, ApplicationInWorkId: {template.ApplicationInWorkId}, " +
// $"HostId: {template.HostId}");
// }
// }
//}
2024-07-03 12:01:46 +10:00
#region с о з д а в а л и ш а б л о н ы д о т о г о , к а к с т а л и г р у п п и р о в а т ь п о Р Г
////Создаем шаблоны
//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(),
// //Name = TemplateHelpers.GenerateTemplateName("З О " ,settingsFromDb.TemplatePrefixName, host.Ek, appInWork.Work!.Name),
// //Генерить имя с полным именем работы и подстановкой ЭК
2025-04-16 15:54:50 +10:00
// //Name = TemplateHelpers.GenerateTemplateNameWithResponseArea(host.ResponseArea!.Name, settingsFromDb.TemplatePrefixName, host.Ek, appInWork.Work!.Name.ApplyShortcode(Constants.Shortcode.ShortcodeEnum.EK, host.Ek)),
2024-07-03 12:01:46 +10:00
// //Вместо полного имени работы, подставляется сокращенный суффикс или полное имя с ЭК если суффикса нет
// Name = TemplateHelpers.GenerateTemplateNameWithResponseArea(
// host.ResponseArea!.Name,
// settingsFromDb.TemplatePrefixName,
// host.Ek,
2025-04-16 15:54:50 +10:00
// appInWork.Work!.TemplateSuffix ?? appInWork.Work!.Name.ApplyShortcode(Constants.Shortcode.ShortcodeEnum.EK, host.Ek)
2024-07-03 12:01:46 +10:00
// ),
// IsActiveTemplate = query.IsActiveTemplate ?? false,
// IsActiveSchedule = query.IsActiveSchedule ?? false,
// ApplicationInWorkId = appInWork.Id,
// HostId = host.Id,
// //TODO:
// //NextRun = ???,
// LastRun = null
// };
// 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}");
// }
//}
#endregion
}
2024-09-16 09:30:28 +10:00
/// <summary>
/// Исключаем существующие шаблоны из запроса на создание
/// </summary>
/// <param name="templates"></param>
/// <returns></returns>
private async Task < List < Template > > ExcludeExistTemplatesAsync ( List < Template > templates )
{
// то ли костыль, то ли нет. Иногда попадают отфильтрованные шаблоны для создания, но они уже есть в БД. Н а всякий проверяем есть они или нет, и если есть, исключаем их из запроса.
// ищмем по имени такие шаблоны в БД и исключаем их
var existTemplates = await templateService . Get ( ) . Where ( t = > templates . Select ( x = > x . Name ) . Any ( x = > x = = t . Name ) ) . ToListAsync ( ) ;
if ( existTemplates . Any ( ) )
{
existTemplates . ForEach ( item = > logger . LogWarning ( $"Исключаем из запроса на создание шаблон, так как он уже есть в БД: {item.Name}" ) ) ;
templates = templates . Where ( t = > ! existTemplates . Any ( x = > x . Name = = t . Name ) ) . ToList ( ) ;
}
return templates ;
}
2024-07-03 12:01:46 +10:00
private List < Template > CreateQueryTemplates ( List < Host > hosts , GeneratorTemplateMq query )
{
var templates = new List < Template > ( ) ;
2023-09-25 11:47:13 +10:00
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}" ) ;
2024-07-03 12:01:46 +10:00
//return;
return templates ;
2023-09-25 11:47:13 +10:00
}
var template = new Template
{
Id = Guid . NewGuid ( ) ,
2024-02-13 13:44:08 +10:00
//Name = TemplateHelpers.GenerateTemplateName("З О " ,settingsFromDb.TemplatePrefixName, host.Ek, appInWork.Work!.Name),
2024-06-14 14:27:37 +10:00
//Генерить имя с полным именем работы и подстановкой ЭК
2025-04-16 15:54:50 +10:00
//Name = TemplateHelpers.GenerateTemplateNameWithResponseArea(host.ResponseArea!.Name, settingsFromDb.TemplatePrefixName, host.Ek, appInWork.Work!.Name.ApplyShortcode(Constants.Shortcode.ShortcodeEnum.EK, host.Ek)),
2024-06-14 14:27:37 +10:00
//Вместо полного имени работы, подставляется сокращенный суффикс или полное имя с ЭК если суффикса нет
Name = TemplateHelpers . GenerateTemplateNameWithResponseArea (
2024-07-03 12:01:46 +10:00
host . ResponseArea ! . Name ,
settingsFromDb . TemplatePrefixName ,
host . Ek ,
2025-08-01 14:45:36 +10:00
appInWork . Work ! . TemplateSuffix ? ? appInWork . Work ! . Name
2024-06-14 14:27:37 +10:00
) ,
2024-06-13 09:01:02 +10:00
IsActiveTemplate = query . IsActiveTemplate ? ? false ,
IsActiveSchedule = query . IsActiveSchedule ? ? false ,
2025-06-25 14:17:34 +10:00
JobId = appInWork . Id , //TODO Migratin to Job
UnitId = host . Id , //TODO Migratin to Job
2024-07-03 12:01:46 +10:00
// NextRun не задаем значение, е г о рассчитаем позже
//NextRun = ???,
LastRun = null
2023-09-25 11:47:13 +10:00
} ;
2024-07-03 12:01:46 +10:00
templates . Add ( template ) ;
2023-09-25 11:47:13 +10:00
}
2024-07-03 12:01:46 +10:00
return templates ;
2023-09-22 15:30:57 +10:00
}
2024-07-03 12:01:46 +10:00
2023-09-22 15:30:57 +10:00
public async Task DeactivateTemplates ( GeneratorTemplateMq query )
{
2024-06-13 09:01:02 +10:00
//TODO: !!! тут не учитываются поля query.IsActiveTemplate, query.IsActiveSchedule, просто все деактивируется. !!!
2024-06-04 12:03:15 +10:00
//В таблице 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 ( ) ;
2023-09-22 15:30:57 +10:00
//Ищет все активные шаблоны согласно параметрам в таблице Templates, и деактивирует их. Меняем на статус Updating
2023-09-25 11:47:13 +10:00
// делаем sql формат для like из запроса.
string ekPattern = SqlHelpers . RegexToLike ( query . Ek ) ;
2023-09-22 15:30:57 +10:00
2023-09-25 15:32:22 +10:00
var queryTemplates = templateService . Get ( )
2025-06-25 14:17:34 +10:00
. Include ( t = > t . Unit ) //TODO Migratin to Job
. Include ( t = > t . Job ) //TODO Migratin to Job
2023-10-05 16:56:02 +10:00
. Include ( t = > t . RobotConfigurations )
2023-09-22 15:30:57 +10:00
. Where ( t = >
2023-10-05 16:56:02 +10:00
( t . IsActiveTemplate = = true | | t . IsActiveSchedule = = true )
2025-06-25 14:17:34 +10:00
//&& t.ApplicationsInWork!.ApplicationId == query.ApplicationId//TODO Migratin to Job
//&& t.ApplicationsInWork!.WorkId == query.WorkId//TODO Migratin to Job
& & EF . Functions . Like ( t . Unit ! . Name . ToLower ( ) , ekPattern )
2023-09-25 15:32:22 +10:00
) ;
// статус ЭК
if ( query . StatusEk > 0 )
2025-06-25 14:17:34 +10:00
queryTemplates = queryTemplates ; //.Where(t => t.Unit!.BaseFields.Status == query.StatusEk);//TODO Migratin to Job
2023-09-25 15:32:22 +10:00
var existTemplates = await queryTemplates
. AsSplitQuery ( )
. ToListAsync ( ) ;
2023-09-22 15:30:57 +10:00
2024-06-04 12:03:15 +10:00
// Исключаем хосты у которых нет нужных групп
2025-06-25 14:17:34 +10:00
existTemplates = existTemplates . Where ( t = > workGroups . Any ( x = > x . WorkGroup . Name = = t . Unit . BaseFields . WorkGroup ) ) . ToList ( ) ;
2024-06-04 12:03:15 +10:00
2023-09-22 15:30:57 +10:00
if ( ! existTemplates . Any ( ) )
{
logger . LogInformation ( "Нет шаблонов для деактивации" ) ;
return ;
}
existTemplates . ForEach ( item = >
{
item . DateModified = DateTimeOffset . UtcNow ;
2023-10-05 16:56:02 +10:00
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 ) ;
}
2023-09-22 15:30:57 +10:00
} ) ;
2024-10-08 10:29:34 +10:00
if ( await templateService . CommitAsync ( query . HistoryInitiator ) )
2023-09-22 15:30:57 +10:00
existTemplates . ForEach ( item = > logger . LogInformation ( $"Деактивирован шаблон: {item.Name}" ) ) ;
else
existTemplates . ForEach ( item = > logger . LogError ( $"Ошибка при дактивации шаблона: {item.Name}" ) ) ;
}
}
}