2023-11-27 12:06:16 +10:00
using Microsoft.Extensions.DependencyInjection ;
using Microsoft.Extensions.Logging ;
using PARR.BLL.Helpers ;
2023-11-22 16:34:16 +10:00
using PARR.BLL.Services.Interfaces ;
using PARR.DAL.Contracts ;
using PARR.DAL.Models ;
2023-11-27 12:06:16 +10:00
using PARR.DAL.Services.Interfaces ;
2024-08-06 11:06:49 +10:00
using PARR.DAL.TransformServices ;
2023-11-22 16:34:16 +10:00
using PARR.EsppScheduleSync.Domain ;
using PARR.EsppScheduleSync.Settings ;
using PARR.EsppSync ;
namespace PARR.EsppScheduleSync
{
internal class ScheduleSyncher : IScheduleSyncher
{
private readonly ILogger < ScheduleSyncher > logger ;
private readonly GlobalSettings globalSettings ;
private readonly IMqService mqService ;
private readonly ISyncService < EsppObjectSchedule > syncService ;
private readonly SettingsFromDb settingsFromDb ;
2023-11-27 12:06:16 +10:00
private readonly IServiceProvider serviceProvider ;
2025-08-20 14:10:22 +10:00
//private readonly INextRunModifierService nextRunModifierService;
2023-11-22 16:34:16 +10:00
public ScheduleSyncher (
ILogger < ScheduleSyncher > logger ,
GlobalSettings globalSettings ,
IMqService mqService ,
ISyncService < EsppObjectSchedule > syncService ,
2023-11-27 12:06:16 +10:00
SettingsFromDb settingsFromDb ,
2025-08-20 14:10:22 +10:00
IServiceProvider serviceProvider
//INextRunModifierService nextRunModifierService
2023-11-22 16:34:16 +10:00
)
{
this . logger = logger ;
this . globalSettings = globalSettings ;
this . mqService = mqService ;
this . syncService = syncService ;
this . settingsFromDb = settingsFromDb ;
2023-11-27 12:06:16 +10:00
this . serviceProvider = serviceProvider ;
2025-08-20 14:10:22 +10:00
//this.nextRunModifierService = nextRunModifierService;
2023-11-22 16:34:16 +10:00
if ( globalSettings . MqSettings = = null )
{
logger . LogError ( "Нет секции настроек хранилища. MqSettings, EsppTemplates" ) ;
throw new Exception ( "Нет секции настроек хранилища. MqSettings, EsppTemplates" ) ;
}
}
2025-08-20 14:10:22 +10:00
public async Task StartAsync ( )
2023-11-22 16:34:16 +10:00
{
2025-08-20 14:10:22 +10:00
var isConnected = await mqService . InitConsumerAsync ( globalSettings ! . MqSettings ! , SyncScheduleAsync ) ;
2023-11-22 16:34:16 +10:00
if ( ! isConnected )
throw new Exception ( "Ошибка при подключении к RabbitMq" ) ;
logger . LogInformation ( $"Запущена проверка очереди {globalSettings.MqSettings!.QueueName}." ) ;
}
2025-08-20 14:10:22 +10:00
public async Task StopAsync ( )
2023-11-22 16:34:16 +10:00
{
2025-08-20 14:10:22 +10:00
await mqService . DisposeAsync ( ) ;
2023-11-22 16:34:16 +10:00
logger . LogInformation ( $"=== === === Соединение с очередью {globalSettings.MqSettings!.QueueName} закрыто === === ===" ) ;
}
private async Task SyncScheduleAsync ( string str )
{
await syncService . SyncEsppObjectAsync ( str , ParseStrToEsppObject , ConvertDbObjToEsppObj ) ;
}
/// <summary>
/// Преобразование модели БД в модель для сравнения
/// </summary>
/// <param name="template"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
2025-08-06 10:33:55 +10:00
private EsppObjectSchedule ConvertDbObjToEsppObj ( Template template )
2023-11-22 16:34:16 +10:00
{
2025-08-20 14:10:22 +10:00
//дефолтное значение, изменится в сервисе nextRunModifierService
var nextRunByAccountRobotTimeZone = DateTimeOffset . MinValue ;
using ( var scope = serviceProvider . CreateScope ( ) )
{
var nextRunModifierService = scope . ServiceProvider . GetService < INextRunModifierService > ( ) ;
if ( nextRunModifierService = = null )
throw new Exception ( $"Н е найден сервис: {nameof(INextRunModifierService)}" ) ;
nextRunByAccountRobotTimeZone = nextRunModifierService . GetNextRunByAccountRobotTimeZone ( template . NextRun ) ;
}
2023-11-27 12:06:16 +10:00
var esppObjectFromDb = new EsppObjectSchedule
{
TemplateName = template . Name ,
Code = template . ScheduleEsppId ? ? "" ,
ScheduleName = template . Name ,
IsActive = template . IsActiveSchedule ,
2025-06-25 14:17:34 +10:00
//ResponseArea = template.Host!.ResponseArea!.Name,//TODO Migration to job
2024-06-04 12:03:15 +10:00
//WorkGroup = template.Host!.WorkGroup!,
2025-06-25 14:17:34 +10:00
//WorkGroup = template.Host!.WorkGroup!.Name,//TODO Migration to job
2023-11-27 12:06:16 +10:00
//Мы решили, что для всех расписаний "Нет исключений", если что-то поменяется, тут нужно переделать
TypeV60calendar = settingsFromDb . ScheduleExclude = = "Нет исключений" ? "NONE" : "" ,
2024-08-06 11:06:49 +10:00
//Scheduled = EsppScheduleHelpers.GetNextRun(template.NextRun),
2025-08-20 14:10:22 +10:00
//Scheduled = EsppScheduleHelpers.GetNextRun(nextRunModifierService.GetNextRunByAccountRobotTimeZone(template.NextRun)),
//BasisTime = EsppScheduleHelpers.GetGenerationTime(nextRunModifierService.GetNextRunByAccountRobotTimeZone(template.NextRun)),
Scheduled = EsppScheduleHelpers . GetNextRun ( nextRunByAccountRobotTimeZone ) ,
BasisTime = EsppScheduleHelpers . GetGenerationTime ( nextRunByAccountRobotTimeZone ) ,
2023-11-27 12:06:16 +10:00
Timezone = settingsFromDb . ScheduleTimezone ,
//Мы решили, что для всех расписаний "Отсутствует дата завершения", если что-то поменяется, тут нужно переделать
TerminationType = settingsFromDb . ScheduleRepeatRange = = "Отсутствует дата завершения" ? "forever" : "" ,
CompleteAfter = "" ,
V60calendar = ""
} ;
FillScheduleFromDb ( template , ref esppObjectFromDb ) ;
return ClearOptionalFields ( esppObjectFromDb ) ;
}
/// <summary>
/// Заполнить расписание из БД
/// </summary>
/// <returns></returns>
private void FillScheduleFromDb ( Template template , ref EsppObjectSchedule esppObject )
{
using ( var scope = serviceProvider . CreateScope ( ) )
{
var esppSchTypeConfigService = scope . ServiceProvider . GetService < IEsppSchTypeConfigService > ( ) ;
if ( esppSchTypeConfigService = = null )
throw new Exception ( $"Н е найден сервис: {nameof(IEsppSchTypeConfigService)}" ) ;
2025-08-21 15:23:46 +10:00
var esppSchedule = esppSchTypeConfigService . GetEsppScheduleDto ( template . Job ! . GroupId ) ;
2023-11-27 12:06:16 +10:00
if ( esppSchedule = = null )
{
logger . LogError ( $"Н е смог получить расписание из БД для шаблона templateId: {template.Id}, {template.Name}" ) ;
return ;
}
var typeSchedule = GetTypeScheduleByString ( esppSchedule . TypeSchedule . Name ) ;
if ( ! typeSchedule . HasValue )
return ;
//тип повторения
esppObject . TypeSchedule = typeSchedule . Value ;
//в зависимости от типа, присваиваем значения
switch ( esppObject . TypeSchedule )
{
case EsppSchTypeScheduleEnum . Regularly :
esppObject . Interval = esppSchedule . Values . First ( t = > t . Order = = 0 ) . Value . EsppExportValue ;
break ;
case EsppSchTypeScheduleEnum . Weekly :
esppObject . Dayofweek = esppSchedule . Values . First ( t = > t . Order = = 0 ) . Value . EsppExportValue ;
break ;
case EsppSchTypeScheduleEnum . Monthly :
2024-08-02 15:25:43 +10:00
//если включено автораспределение, подставляем дату месяца из NextRun
2025-06-25 14:17:34 +10:00
//if (template.ApplicationsInWork?.IsAutoDistributionEnabled == true)//TODO Migration to job
//{
// var nextRunByRobotTimeZone = nextRunModifierService.GetNextRunByAccountRobotTimeZone(template.NextRun);
// esppObject.Dayofmonth = nextRunByRobotTimeZone.Day.ToString();
// // esppObject.Dayofmonth = template.NextRun.Day.ToString();
//}
//else
//{
2025-08-20 14:10:22 +10:00
esppObject . Dayofmonth = esppSchedule . Values . First ( t = > t . Order = = 0 ) . Value . EsppExportValue ;
2025-06-25 14:17:34 +10:00
//}
2023-11-27 12:06:16 +10:00
break ;
case EsppSchTypeScheduleEnum . Monthly2 :
esppObject . Md1 = esppSchedule . Values . First ( t = > t . Order = = 0 ) . Value . EsppExportValue ;
esppObject . Md2 = esppSchedule . Values . First ( t = > t . Order = = 1 ) . Value . EsppExportValue ;
break ;
case EsppSchTypeScheduleEnum . Annually :
esppObject . Annualm = esppSchedule . Values . First ( t = > t . Order = = 0 ) . Value . EsppExportValue ;
esppObject . Annualday = esppSchedule . Values . First ( t = > t . Order = = 1 ) . Value . EsppExportValue ;
break ;
case EsppSchTypeScheduleEnum . Annually2 :
esppObject . An1 = esppSchedule . Values . First ( t = > t . Order = = 0 ) . Value . EsppExportValue ;
esppObject . An2 = esppSchedule . Values . First ( t = > t . Order = = 1 ) . Value . EsppExportValue ;
esppObject . An3 = esppSchedule . Values . First ( t = > t . Order = = 2 ) . Value . EsppExportValue ;
break ;
}
2024-08-08 11:25:35 +10:00
2023-11-27 12:06:16 +10:00
}
2023-11-22 16:34:16 +10:00
}
/// <summary>
/// Парсинг из строки в модель для сравнения
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
private EsppObjectSchedule ? ParseStrToEsppObject ( string str )
{
2023-11-24 16:52:56 +10:00
var splittedContent = str . Split ( globalSettings . ParsingSeparator ) ;
2024-08-08 11:25:35 +10:00
if ( splittedContent . Length ! = 24 )
2023-11-24 16:52:56 +10:00
{
2024-08-08 11:25:35 +10:00
logger . LogError ( $"Входная строка после сплита не содержит 24 объекта (факт: {splittedContent.Length})." ) ;
2023-11-24 16:52:56 +10:00
return null ;
}
var templateName = splittedContent [ 6 ] ;
var scheduleName = splittedContent [ 2 ] ;
if ( ! IsValidName ( templateName ) | | ! IsValidName ( scheduleName ) )
return null ;
bool . TryParse ( splittedContent [ 1 ] . Trim ( ) , out var isActive ) ;
2023-11-27 09:27:20 +10:00
var typeSchedule = GetTypeScheduleByString ( splittedContent [ 7 ] ) ;
if ( ! typeSchedule . HasValue )
return null ;
2023-11-24 16:52:56 +10:00
var esppObject = new EsppObjectSchedule
{
TemplateName = templateName ,
Code = splittedContent [ 0 ] ,
ScheduleName = scheduleName ,
IsActive = isActive ,
ResponseArea = splittedContent [ 5 ] ,
WorkGroup = splittedContent [ 3 ] ,
2023-11-27 09:27:20 +10:00
TypeSchedule = typeSchedule . Value ,
2023-11-24 16:52:56 +10:00
Interval = splittedContent [ 8 ] ,
Dayofweek = splittedContent [ 15 ] ,
Dayofmonth = splittedContent [ 14 ] ,
Md1 = splittedContent [ 16 ] ,
Md2 = splittedContent [ 17 ] ,
Annualm = splittedContent [ 13 ] ,
Annualday = splittedContent [ 12 ] ,
An1 = splittedContent [ 9 ] ,
An2 = splittedContent [ 10 ] ,
An3 = splittedContent [ 11 ] ,
TypeV60calendar = splittedContent [ 21 ] ,
Scheduled = splittedContent [ 4 ] ,
Timezone = splittedContent [ 18 ] ,
TerminationType = splittedContent [ 19 ] ,
CompleteAfter = splittedContent [ 20 ] ,
2024-08-08 11:25:35 +10:00
V60calendar = splittedContent [ 22 ] ,
BasisTime = splittedContent [ 23 ]
2023-11-24 16:52:56 +10:00
} ;
return ClearOptionalFields ( esppObject ) ;
2023-11-22 16:34:16 +10:00
}
2023-11-24 16:52:56 +10:00
2023-11-27 09:27:20 +10:00
/// <summary>
/// Преобразовать из строки в Тип Повторения
/// </summary>
/// <param name="typeSchedule"></param>
/// <returns></returns>
private EsppSchTypeScheduleEnum ? GetTypeScheduleByString ( string typeSchedule )
{
typeSchedule = typeSchedule . ToLower ( ) ;
//Regularly, Регулярно (значение в ЕСПП и в БД не совпадают, в бд Regularly, в ЕСПП simple)
if ( typeSchedule = = "simple" | | typeSchedule = = EsppSchTypeScheduleEnum . Regularly . ToString ( ) . ToLower ( ) )
return EsppSchTypeScheduleEnum . Regularly ;
if ( typeSchedule = = EsppSchTypeScheduleEnum . Weekly . ToString ( ) . ToLower ( ) )
return EsppSchTypeScheduleEnum . Weekly ;
if ( typeSchedule = = EsppSchTypeScheduleEnum . Monthly . ToString ( ) . ToLower ( ) )
return EsppSchTypeScheduleEnum . Monthly ;
if ( typeSchedule = = EsppSchTypeScheduleEnum . Monthly2 . ToString ( ) . ToLower ( ) )
return EsppSchTypeScheduleEnum . Monthly2 ;
if ( typeSchedule = = EsppSchTypeScheduleEnum . Annually . ToString ( ) . ToLower ( ) )
return EsppSchTypeScheduleEnum . Annually ;
if ( typeSchedule = = EsppSchTypeScheduleEnum . Annually2 . ToString ( ) . ToLower ( ) )
return EsppSchTypeScheduleEnum . Annually2 ;
logger . LogError ( $"Н е смог преобразовать Тип повторения из ЕСПП в EsppSchTypeScheduleEnum. Получено значение {typeSchedule}" ) ;
return null ;
}
2023-11-24 16:52:56 +10:00
/// <summary>
/// Проверка имени шаблона и расписание на соответствие префиксу из настроек
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
private bool IsValidName ( string name )
{
var currentCulture = Thread . CurrentThread . CurrentCulture ;
2024-02-15 09:21:01 +10:00
//if (!string.IsNullOrEmpty(settingsFromDb.TemplatePrefixName) && name.StartsWith(settingsFromDb.TemplatePrefixName, true, currentCulture))
// return true;
2024-02-15 13:47:34 +10:00
if ( ! string . IsNullOrEmpty ( settingsFromDb . TemplatePrefixWithoutVariable ) & & name . Contains ( settingsFromDb . TemplatePrefixWithoutVariable ) ) // , StringComparison.CurrentCultureIgnoreCase
2023-11-24 16:52:56 +10:00
return true ;
2024-02-15 09:21:01 +10:00
logger . LogWarning ( $"Имя шаблона или расписания не соответствует обязательному префиксу({settingsFromDb.TemplatePrefixWithoutVariable}). {name} игнорирован" ) ;
2023-11-24 16:52:56 +10:00
return false ;
}
/// <summary>
/// Очистка полей которые не нуждаются в синхронизации
/// </summary>
/// <param name="esppObject"></param>
/// <returns></returns>
private EsppObjectSchedule ClearOptionalFields ( EsppObjectSchedule esppObject )
{
esppObject . Code = string . Empty ;
esppObject . ScheduleName = string . Empty ;
esppObject . ResponseArea = string . Empty ;
esppObject . WorkGroup = string . Empty ;
esppObject . CompleteAfter = string . Empty ;
2023-11-27 12:06:16 +10:00
esppObject . V60calendar = string . Empty ;
2023-11-24 16:52:56 +10:00
// В ЕСПП, при изменении "Повторять задачу", остаются предыдущие значения, их не нужно синхронизировать (касается только данных полученных из ЕСПП, в БД все ок)
// т.е . если стояло Ежедненвно:понедельник, а изменили например на Еженедельно..., то в ежедневно значения останутся, но будут отрабатывать значения из Еженедельно.
// Т е значения из Ежедненвно проверять не нужно, вот их и будем очищать
2023-11-27 09:27:20 +10:00
switch ( esppObject . TypeSchedule )
{
case EsppSchTypeScheduleEnum . Regularly :
//esppObject.Interval = string.Empty;
esppObject . Dayofweek = string . Empty ;
esppObject . Dayofmonth = string . Empty ;
esppObject . Md1 = string . Empty ;
esppObject . Md2 = string . Empty ;
esppObject . Annualm = string . Empty ;
esppObject . Annualday = string . Empty ;
esppObject . An1 = string . Empty ;
esppObject . An2 = string . Empty ;
esppObject . An3 = string . Empty ;
break ;
case EsppSchTypeScheduleEnum . Weekly :
esppObject . Interval = string . Empty ;
//esppObject.Dayofweek = string.Empty;
esppObject . Dayofmonth = string . Empty ;
esppObject . Md1 = string . Empty ;
esppObject . Md2 = string . Empty ;
esppObject . Annualm = string . Empty ;
esppObject . Annualday = string . Empty ;
esppObject . An1 = string . Empty ;
esppObject . An2 = string . Empty ;
esppObject . An3 = string . Empty ;
break ;
case EsppSchTypeScheduleEnum . Monthly :
esppObject . Interval = string . Empty ;
esppObject . Dayofweek = string . Empty ;
//esppObject.Dayofmonth = string.Empty;
esppObject . Md1 = string . Empty ;
esppObject . Md2 = string . Empty ;
esppObject . Annualm = string . Empty ;
esppObject . Annualday = string . Empty ;
esppObject . An1 = string . Empty ;
esppObject . An2 = string . Empty ;
esppObject . An3 = string . Empty ;
break ;
case EsppSchTypeScheduleEnum . Monthly2 :
esppObject . Interval = string . Empty ;
esppObject . Dayofweek = string . Empty ;
esppObject . Dayofmonth = string . Empty ;
//esppObject.Md1 = string.Empty;
//esppObject.Md2 = string.Empty;
esppObject . Annualm = string . Empty ;
esppObject . Annualday = string . Empty ;
esppObject . An1 = string . Empty ;
esppObject . An2 = string . Empty ;
esppObject . An3 = string . Empty ;
break ;
case EsppSchTypeScheduleEnum . Annually :
esppObject . Interval = string . Empty ;
esppObject . Dayofweek = string . Empty ;
esppObject . Dayofmonth = string . Empty ;
esppObject . Md1 = string . Empty ;
esppObject . Md2 = string . Empty ;
//esppObject.Annualm = string.Empty;
//esppObject.Annualday = string.Empty;
esppObject . An1 = string . Empty ;
esppObject . An2 = string . Empty ;
esppObject . An3 = string . Empty ;
break ;
case EsppSchTypeScheduleEnum . Annually2 :
esppObject . Interval = string . Empty ;
esppObject . Dayofweek = string . Empty ;
esppObject . Dayofmonth = string . Empty ;
esppObject . Md1 = string . Empty ;
esppObject . Md2 = string . Empty ;
esppObject . Annualm = string . Empty ;
esppObject . Annualday = string . Empty ;
//esppObject.An1 = string.Empty;
//esppObject.An2 = string.Empty;
//esppObject.An3 = string.Empty;
break ;
}
2023-11-24 16:52:56 +10:00
return esppObject ;
}
2023-11-22 16:34:16 +10:00
}
}