2024-07-25 17:23:08 +10:00
using Microsoft.EntityFrameworkCore ;
using Microsoft.Extensions.Logging ;
2024-09-17 11:30:33 +10:00
using PARR.BLL.Helpers ;
2024-10-08 10:29:34 +10:00
using PARR.Common.Domain ;
2024-07-25 17:23:08 +10:00
using PARR.Constants ;
using PARR.DAL.Contracts ;
using PARR.DAL.Models ;
using PARR.DAL.Services.Interfaces ;
2024-09-17 11:30:33 +10:00
using System.Threading.Channels ;
using System.Threading.Tasks ;
2024-07-25 17:23:08 +10:00
namespace PARR.TemplateActivator ;
internal class TemplateActivator : ITemplateActivator
{
private readonly ILogger < TemplateActivator > logger ;
private readonly ITemplateService templateService ;
private readonly IRobotConfigurationService robotConfigurationService ;
2024-09-17 11:30:33 +10:00
private readonly IJobAutoControlService jobAutoControlService ;
private readonly IApplicationsInWorkService applicationsInWorkService ;
2024-07-25 17:23:08 +10:00
public TemplateActivator (
ILogger < TemplateActivator > logger ,
ITemplateService templateService ,
2024-09-17 11:30:33 +10:00
IRobotConfigurationService robotConfigurationService ,
IJobAutoControlService jobAutoControlService ,
IApplicationsInWorkService applicationsInWorkService
2024-07-25 17:23:08 +10:00
)
{
this . logger = logger ;
this . templateService = templateService ;
this . robotConfigurationService = robotConfigurationService ;
2024-09-17 11:30:33 +10:00
this . jobAutoControlService = jobAutoControlService ;
this . applicationsInWorkService = applicationsInWorkService ;
2024-07-25 17:23:08 +10:00
}
2024-07-26 11:41:40 +10:00
2024-10-08 10:29:34 +10:00
public async Task ChangeStateAsync ( Guid applicationInWorkId , TemplateActivatorActionsEnum action , IHistoryInitiator ? historyInitiator )
2024-07-25 17:23:08 +10:00
{
var query = templateService . Get ( )
. Include ( t = > t . RobotConfigurations ) . ThenInclude ( t = > t . Robot )
. Where ( t = > t . ApplicationInWorkId = = applicationInWorkId ) ;
var changes = 0 ;
switch ( action )
{
case TemplateActivatorActionsEnum . ActivateAllTemplates :
2024-07-26 11:41:40 +10:00
logger . LogInformation ( $"Получен запрос на активацию всех шаблонов" ) ;
2024-07-25 17:23:08 +10:00
query = query . Where ( t = > ! t . IsActiveTemplate ) ;
changes = await UpdateTemplateStateAsync ( query , true ) ;
break ;
case TemplateActivatorActionsEnum . ActivateTemplatesWithActiveSchedules :
2024-07-26 11:41:40 +10:00
logger . LogInformation ( $"Получен запрос на активацию всех шаблонов, у которых активировано расписание" ) ;
2024-07-25 17:23:08 +10:00
query = query . Where ( t = > ! t . IsActiveTemplate & & t . IsActiveSchedule ) ;
changes = await UpdateTemplateStateAsync ( query , true ) ;
break ;
case TemplateActivatorActionsEnum . DeactivateAllTemplates :
2024-07-26 11:41:40 +10:00
logger . LogInformation ( $"Получен запрос на деактивацию всех шаблонов" ) ;
2024-07-25 17:23:08 +10:00
query = query . Where ( t = > t . IsActiveTemplate ) ;
changes = await UpdateTemplateStateAsync ( query , false ) ;
break ;
case TemplateActivatorActionsEnum . DeactivateTemplatesWithDeactivationSchedules :
2024-07-26 11:41:40 +10:00
logger . LogInformation ( $"Получен запрос на деактивацию всех шаблонов, у которых неактивированы расписания" ) ;
query = query . Where ( t = > t . IsActiveTemplate & & ! t . IsActiveSchedule ) ;
2024-07-25 17:23:08 +10:00
changes = await UpdateTemplateStateAsync ( query , false ) ;
break ;
case TemplateActivatorActionsEnum . ActivateAllSchedules :
2024-07-26 11:41:40 +10:00
logger . LogInformation ( $"Получен запрос на активацию всех расписаний" ) ;
2024-07-25 17:23:08 +10:00
query = query . Where ( t = > ! t . IsActiveSchedule ) ;
changes = await UpdateScheduleStateAsync ( query , true ) ;
break ;
case TemplateActivatorActionsEnum . DeactivateAllSchedules :
2024-07-26 11:41:40 +10:00
logger . LogInformation ( $"Получен запрос на деактивацию всех расписаний" ) ;
2024-07-25 17:23:08 +10:00
query = query . Where ( t = > t . IsActiveSchedule ) ;
changes = await UpdateScheduleStateAsync ( query , false ) ;
break ;
case TemplateActivatorActionsEnum . ActivateSchedulesWithActiveTemplates :
2024-07-26 11:41:40 +10:00
logger . LogInformation ( $"Получен запрос на активацию всех расписаний, у которых активированы шаблоны" ) ;
2024-07-25 17:23:08 +10:00
query = query . Where ( t = > t . IsActiveTemplate & & ! t . IsActiveSchedule ) ;
changes = await UpdateScheduleStateAsync ( query , true ) ;
break ;
case TemplateActivatorActionsEnum . DeactivateSchedulesWithDeactivationTemplates :
2024-07-26 11:41:40 +10:00
logger . LogInformation ( $"Получен запрос на деактивацию всех расписаний, у которых неактивированы шаблоны" ) ;
query = query . Where ( t = > ! t . IsActiveTemplate & & t . IsActiveSchedule ) ;
2024-07-25 17:23:08 +10:00
changes = await UpdateScheduleStateAsync ( query , false ) ;
break ;
2024-08-09 12:14:04 +10:00
case TemplateActivatorActionsEnum . DeactivateSchedulesWithTemplateSyncErrors :
logger . LogInformation ( $"Получен запрос на деактивацию всех расписаний, у которых шаблоны синхронизированы с ошибкой" ) ;
2024-08-12 16:21:30 +10:00
query = query . Where ( t = > t . IsActiveTemplate & &
2024-08-09 16:36:37 +10:00
t . RobotConfigurations . Any ( t = >
t . RobotCode = = ( int ) RobotsEnum . TemplateOrder & &
2024-08-09 12:14:04 +10:00
t . RobotStatusCode = = ( int ) RobotStatusEnum . Error )
) ;
changes = await UpdateScheduleStateAsync ( query , false ) ;
break ;
2024-09-17 11:30:33 +10:00
case TemplateActivatorActionsEnum . DeactivateAllForAutoControl :
logger . LogInformation ( $"Получен запрос на деактивацию шаблонов и расписаний, для ЭК неудовлетворяющим условиям автоконтроля" ) ;
2024-09-24 12:16:55 +10:00
changes = await CoordinateJobsWithAutoControlAsync ( applicationInWorkId , query , false ) ;
break ;
case TemplateActivatorActionsEnum . ActivateAllForAutoControl :
logger . LogInformation ( $"Получен запрос на активацию шаблонов и расписаний, для ЭК удовлетворяющим условиям автоконтроля" ) ;
changes = await CoordinateJobsWithAutoControlAsync ( applicationInWorkId , query , true ) ;
2024-09-17 11:30:33 +10:00
break ;
2024-07-25 17:23:08 +10:00
default :
break ;
}
2024-10-08 10:29:34 +10:00
if ( historyInitiator ! = null )
2024-10-11 09:16:10 +10:00
{
historyInitiator . InitiatorComment + = $" Action: {action.ToString()}" ;
historyInitiator . InitiatorComment = historyInitiator . InitiatorComment . Trim ( ) ;
}
2024-10-08 10:29:34 +10:00
if ( changes > 0 & & ! await templateService . CommitAsync ( historyInitiator ) )
2024-09-17 11:30:33 +10:00
logger . LogError ( $"{GetType().Name} не удалось записать измения в БД о новых состояниях шаблонов и расписаний регламентной работы Id {applicationInWorkId}" ) ;
logger . LogDebug ( $"{GetType().Name} изменил состояние шаблонов/расписаний({changes}) регламентной работы Id {applicationInWorkId}" ) ;
}
2024-09-24 12:16:55 +10:00
private async Task < int > CoordinateJobsWithAutoControlAsync ( Guid applicationInWorkId , IQueryable < Template > query , bool isActivate )
2024-09-17 11:30:33 +10:00
{
var changes = 0 ;
2024-09-24 12:16:55 +10:00
//Добавляем информацию о рабочих группах для возможности их фильтрации
query = query . Include ( t = > t . Host ) . ThenInclude ( h = > h ! . WorkGroup ) ;
2024-09-17 11:30:33 +10:00
//Получаем настройки авто-контроля
2024-09-24 12:16:55 +10:00
var jobAutoControlSettings = await GetJobAutoControlSettingsAsync ( applicationInWorkId ) ;
2024-09-17 11:30:33 +10:00
if ( jobAutoControlSettings = = null )
return 0 ;
var trueEkStatuses = jobAutoControlSettings . JobAutoControlInEkStatuses ;
var trueMasks = jobAutoControlSettings . JobEkMasks ;
if ( ! trueEkStatuses . Any ( ) | | ! trueMasks . Any ( ) )
{
logger . LogWarning ( $"В ApplicationInWork({applicationInWorkId}) не заданы настройки фильтрации статусов ЭК хоста или маски е г о имени" ) ;
return 0 ;
}
//Фильтруем обратное состояние - активированные для деактивации
query = FilterTemplatesQueryByWrongState ( query , jobAutoControlSettings , isActivate ) ;
//Фильтруем по маскам ЭК
var templates = FilterTemplatesByNameNotMatchToMasks ( query , trueMasks ) ;
if ( ! templates . Any ( ) )
return 0 ;
//Фильтруем по рабочим группам
var appInWorkWorkGroups = GetApplicationInWorkWorkGroups ( applicationInWorkId ) ;
if ( appInWorkWorkGroups . Any ( ) )
templates = templates . Where ( t = > appInWorkWorkGroups . Any ( awg = > t . Host ! . WorkGroupId = = awg . WorkGroupId ) ) . ToList ( ) ;
//Фильтруем соответствие статусов ЭК условиям автоконтроля
var checkEkStatus = FilterTemplatesByWrongEkStatus ( templates , trueEkStatuses , isActivate ) ;
//Меняем состояние отфильтрованных шаблонов если какие-то остались
if ( checkEkStatus . Any ( ) )
changes = UpdateState ( checkEkStatus ,
isActivate ? jobAutoControlSettings . OnTemplateIsActive : jobAutoControlSettings . OffTemplateIsActive ,
isActivate ? jobAutoControlSettings . OnScheduleIsActive : jobAutoControlSettings . OffScheduleIsActive ) ;
2024-07-25 17:23:08 +10:00
2024-09-17 11:30:33 +10:00
return changes ;
2024-07-25 17:23:08 +10:00
}
2024-09-17 11:30:33 +10:00
private List < AppInWorkInWorkGroup > GetApplicationInWorkWorkGroups ( Guid applicationInWorkId )
{
var appInWorkInWorkGroups = applicationsInWorkService . Get ( )
. Include ( aiw = > aiw . WorkGroups )
2024-09-24 12:16:55 +10:00
. FirstOrDefault ( t = > t . Id = = applicationInWorkId ) ? . WorkGroups ;
2024-09-17 11:30:33 +10:00
if ( appInWorkInWorkGroups ! = null )
return appInWorkInWorkGroups . ToList ( ) ;
return new List < AppInWorkInWorkGroup > ( ) ;
}
private List < Template > FilterTemplatesByWrongEkStatus ( List < Template > templates , ICollection < JobAutoControlInEkStatus > trueEkStatuses , bool isActivate )
{
if ( isActivate )
return templates . Where ( t = > trueEkStatuses . Any ( tes = > tes . EkStatusCode = = t . Host ! . EkStatusCode ) ) . ToList ( ) ;
return templates . Where ( t = > ! trueEkStatuses . Any ( tes = > tes . EkStatusCode = = t . Host ! . EkStatusCode ) ) . ToList ( ) ;
}
private List < Template > FilterTemplatesByNameNotMatchToMasks ( IQueryable < Template > query , ICollection < JobEkMask > trueMasks )
{
var result = new List < Template > ( ) ;
foreach ( var mask in trueMasks )
{
var templates = query . Where ( t = > EF . Functions . Like ( t . Host ! . Ek . ToLower ( ) , SqlHelpers . RegexToLike ( mask . Name ) ) ) . ToList ( ) ;
result . AddRange ( templates ) ;
}
return result ;
}
private IQueryable < Template > FilterTemplatesQueryByWrongState ( IQueryable < Template > query , JobAutoControl jobAutoControlSettings , bool isActivate )
{
if ( isActivate )
2024-09-24 12:16:55 +10:00
return query . Where ( t = > t . IsActiveTemplate ! = jobAutoControlSettings . OnTemplateIsActive | | t . IsActiveSchedule ! = jobAutoControlSettings . OnScheduleIsActive ) ;
2024-09-17 11:30:33 +10:00
2024-09-24 12:16:55 +10:00
return query . Where ( t = > t . IsActiveTemplate ! = jobAutoControlSettings . OffTemplateIsActive | | t . IsActiveSchedule ! = jobAutoControlSettings . OffScheduleIsActive ) ;
2024-09-17 11:30:33 +10:00
}
2024-09-24 12:16:55 +10:00
private async Task < JobAutoControl > GetJobAutoControlSettingsAsync ( Guid applicationInWorkId )
2024-09-17 11:30:33 +10:00
{
return await jobAutoControlService . Get ( )
. Include ( jac = > jac . JobAutoControlInEkStatuses )
. Include ( jac = > jac . JobEkMasks )
. Where ( jac = > jac . ApplicationInWorkId = = applicationInWorkId ) . FirstAsync ( ) ;
}
2024-07-26 11:41:40 +10:00
/// <summary>
/// Обновить состояние расписаний по запросу query на newState, без записи в БД. Возвращает количество шаблонов требующих фиксации в БД
/// </summary>
/// <param name="query"></param>
/// <param name="newState"></param>
/// <returns></returns>
2024-07-25 17:23:08 +10:00
private async Task < int > UpdateScheduleStateAsync ( IQueryable < Template > query , bool newState )
{
var templates = await query . Select ( t = > t ) . ToListAsync ( ) ;
if ( templates . Any ( ) )
templates . ForEach ( t = >
{
t . IsActiveSchedule = newState ;
UpdateRobotConfiguration ( RobotsEnum . ScheduleOrder , t ) ;
} ) ;
templates . ForEach ( t = > t . IsActiveSchedule = newState ) ;
return templates . Count ;
}
2024-07-26 11:41:40 +10:00
/// <summary>
2024-07-29 16:51:18 +10:00
/// Обновить состояние шаблонов по запросу query на newState, без записи в БД. Возвращает количество расписаний требующих фиксацию в БД
2024-07-26 11:41:40 +10:00
/// </summary>
/// <param name="query"></param>
/// <param name="newState"></param>
/// <returns></returns>
2024-07-25 17:23:08 +10:00
private async Task < int > UpdateTemplateStateAsync ( IQueryable < Template > query , bool newState )
{
var templates = await query . Select ( t = > t ) . ToListAsync ( ) ;
if ( templates . Any ( ) )
templates . ForEach ( t = >
{
t . IsActiveTemplate = newState ;
UpdateRobotConfiguration ( RobotsEnum . TemplateOrder , t ) ;
} ) ;
return templates . Count ;
}
2024-09-17 11:30:33 +10:00
/// <summary>
/// Обновить состояние шаблонов по запросу query на newState, без записи в БД. Возвращает количество расписаний требующих фиксацию в БД
/// </summary>
/// <param name="query"></param>
/// <param name="newState"></param>
/// <returns></returns>
private async Task < int > UpdateStateAsync ( IQueryable < Template > query , bool newTemplateState , bool newSchedulerState )
{
var templates = await query . Select ( t = > t ) . ToListAsync ( ) ;
return UpdateState ( templates , newTemplateState , newSchedulerState ) ;
}
private int UpdateState ( List < Template > templates , bool newTemplateState , bool newSchedulerState )
{
if ( templates . Any ( ) )
templates . ForEach ( t = >
{
t . IsActiveTemplate = newTemplateState ;
t . IsActiveSchedule = newSchedulerState ;
UpdateRobotConfiguration ( RobotsEnum . TemplateOrder , t ) ;
} ) ;
return templates . Count ;
}
2024-07-26 11:41:40 +10:00
/// <summary>
/// принудительно обновить состояние задачи, связанной с шаблоном/расписанием, на обновление
/// </summary>
/// <param name="robotsEnum"></param>
/// <param name="t"></param>
2024-07-25 17:23:08 +10:00
private void UpdateRobotConfiguration ( RobotsEnum robotsEnum , Template t )
{
var config = robotConfigurationService . GetFromTemplateByRobotCode ( robotsEnum , ref t ) ;
robotConfigurationService . ChangeTaskStatus ( TaskStatusEnum . Updating , ref config ) ;
}
}