2023-11-22 11:37:22 +10:00
using Microsoft.Extensions.DependencyInjection ;
using Microsoft.Extensions.Logging ;
2023-11-22 12:04:33 +10:00
using PARR.Constants ;
2023-11-22 11:37:22 +10:00
using PARR.DAL.Contracts ;
2025-08-12 11:50:29 +10:00
using PARR.DAL.DomainServices.Interfaces ;
2023-11-22 11:37:22 +10:00
using PARR.DAL.Models ;
using PARR.DAL.Services.Interfaces ;
2025-08-06 10:33:55 +10:00
using System.Reflection ;
2023-11-22 11:37:22 +10:00
namespace PARR.EsppSync
{
internal class SyncService < EsppObject > : ISyncService < EsppObject > where EsppObject : class , IEsppObject
{
private readonly ILogger < SyncService < EsppObject > > logger ;
2025-08-20 14:10:22 +10:00
private readonly IServiceProvider serviceProvider ;
//private readonly ITemplateService templateService;
//private readonly IRobotConfigurationService robotConfigurationService;
//private readonly IShortcodesService shortcodesService;
2023-11-22 11:37:22 +10:00
public SyncService (
ILogger < SyncService < EsppObject > > logger ,
2025-08-20 14:10:22 +10:00
IServiceProvider serviceProvider
//ITemplateService templateService,
//IRobotConfigurationService robotConfigurationService,
//IShortcodesService shortcodesService
2023-11-22 11:37:22 +10:00
)
{
this . logger = logger ;
2025-08-20 14:10:22 +10:00
this . serviceProvider = serviceProvider ;
//this.templateService = templateService;
//this.robotConfigurationService = robotConfigurationService;
//this.shortcodesService = shortcodesService;
2023-11-22 11:37:22 +10:00
}
public async Task SyncEsppObjectAsync (
string str ,
ParserHandlerDelegate < EsppObject > parser ,
2023-11-22 12:04:33 +10:00
ConvertDbObjToComparisonObjHandlerDelegate < EsppObject > converterToEsppObject
2023-11-22 11:37:22 +10:00
)
{
logger . LogDebug ( $"Получил строку. Начинаю работать. Строка: {str}" ) ;
if ( string . IsNullOrEmpty ( str ) )
{
logger . LogWarning ( "Получил пустую строку, ничего не делаю." ) ;
return ;
}
var esppObject = parser . Invoke ( str ) ;
if ( esppObject = = null )
{
logger . LogWarning ( "После парсинга строки, esppObject = null. Дальше ничего не буду делать." ) ;
return ;
}
2025-08-20 14:10:22 +10:00
using ( var scope = serviceProvider . CreateScope ( ) )
2023-11-22 11:37:22 +10:00
{
2025-08-20 14:10:22 +10:00
var templateService = GetServiceInScope < ITemplateService > ( scope ) ;
var robotConfigurationService = GetServiceInScope < IRobotConfigurationService > ( scope ) ;
var shortcodesService = GetServiceInScope < IShortcodesService > ( scope ) ;
2023-11-22 11:37:22 +10:00
2025-08-20 14:10:22 +10:00
try
2023-11-22 11:37:22 +10:00
{
2025-08-20 14:10:22 +10:00
var template = await templateService . GetTemplateByNameAsync ( esppObject . TemplateName ) ;
2025-08-06 10:33:55 +10:00
2025-08-20 14:10:22 +10:00
//todo: существует в ЕСПП но отсутствует в ПАРР. Может е г о деактивировать или еще что-то сделать. Пока просто пропустим
if ( template = = null )
2025-08-06 10:33:55 +10:00
{
2025-08-20 14:10:22 +10:00
logger . LogWarning ( $"Найден объект в ЕСПП с именем шаблона {esppObject.TemplateName} незарегистрированный в ПАРР." ) ;
2025-08-06 10:33:55 +10:00
2025-08-20 14:10:22 +10:00
return ;
2025-08-06 10:33:55 +10:00
}
2025-08-20 14:10:22 +10:00
else
{
var dbObjectInEsppObject = converterToEsppObject . Invoke ( template ) ;
2025-08-06 10:33:55 +10:00
2025-08-20 14:10:22 +10:00
//Проверяем наличие Shortcode в полях объекта из БД
var properties = dbObjectInEsppObject . GetType ( ) . GetProperties ( ) ;
2024-02-28 10:17:01 +10:00
2025-08-20 14:10:22 +10:00
foreach ( PropertyInfo property in properties )
{
var value = property . GetValue ( dbObjectInEsppObject ) ? . ToString ( ) ;
2024-02-28 10:17:01 +10:00
2025-08-20 14:10:22 +10:00
if ( value ! = null & & shortcodesService . isAnyShortcodes ( value ) )
property . SetValue ( dbObjectInEsppObject , await shortcodesService . ApplyShortcodesAsync ( value , template . UnitId , template . JobId ) ) ;
}
2023-11-22 11:37:22 +10:00
2025-08-20 14:10:22 +10:00
bool isChanged = false ;
//TODO: FIX ME Please, BRO
//bool isChanged;
2023-11-24 16:52:56 +10:00
2025-08-20 14:10:22 +10:00
// если в БД isActive == false, то синхронизировать только по полям из IEsppObject
2024-08-02 09:38:05 +10:00
2025-08-20 14:10:22 +10:00
if ( dbObjectInEsppObject . IsActive = = false )
2024-08-02 09:38:05 +10:00
{
2025-08-20 14:10:22 +10:00
logger . LogDebug ( $"Объект деактивирован в ПАРР. Сравниваем только обязательные поля. {esppObject.TemplateName}" ) ;
var lightDbObj = new EsppLightObject ( dbObjectInEsppObject ) ;
var lightEsppObject = new EsppLightObject ( esppObject ) ;
2024-08-02 09:38:05 +10:00
2025-08-20 14:10:22 +10:00
isChanged = IsChanged ( lightEsppObject , lightDbObj ) ;
2024-08-02 09:38:05 +10:00
}
2023-11-22 11:37:22 +10:00
else
2024-08-02 09:38:05 +10:00
{
2025-08-20 14:10:22 +10:00
logger . LogDebug ( $"Объект активирован в ПАРР. Сравниваем все поля. {esppObject.TemplateName}" ) ;
isChanged = IsChanged ( esppObject , dbObjectInEsppObject ) ;
2024-08-02 09:38:05 +10:00
}
2025-08-20 14:10:22 +10:00
if ( isChanged )
{
logger . LogInformation ( $"Есть изменения, требуется обновление. {esppObject.TemplateName}" ) ;
2024-08-02 09:38:05 +10:00
2025-08-20 14:10:22 +10:00
var config = robotConfigurationService . GetFromTemplateByRobotCode ( esppObject . Robot , ref template ) ;
2024-08-02 09:38:05 +10:00
2025-08-20 14:10:22 +10:00
// Если предыдущий статус был Create или Ок, то ставим ему Update
// пусть даже Create завершился с ошибками, но раз он уже есть в ЕСПП, то изменим на Update, сбросим все счетчики и пусть попробует обновить и исправить все
if ( config . TaskStatusCode ! = ( int ) TaskStatusEnum . Updating )
{
SetUpdateStatus ( ref template , robotConfigurationService , esppObject . Robot ) ;
2023-11-24 16:52:56 +10:00
2025-08-20 14:10:22 +10:00
if ( ! await templateService . CommitAsync ( ) )
logger . LogError ( $"Н е удалось изменить запись Template {template.Name}, Robot: {esppObject.Robot}" ) ;
else
logger . LogInformation ( $"Установлен принудительный статус {TaskStatusEnum.Updating}, Template {template.Name}, Robot: {esppObject.Robot}" ) ;
}
2023-11-22 11:37:22 +10:00
else
2025-08-20 14:10:22 +10:00
{
// Если пред статус был Update, то ничего не делаем, так е г о и оставляем, не сбрасывам кол-во попыток и ошибок
logger . LogInformation ( $"Есть изменения в Template {template.Name}, но предыдущий статус TaskStatusCode: {(TaskStatusEnum)config.TaskStatusCode}. Н е меняем статус, будем разбираться вручную." ) ;
}
#region Old logic
//SetUpdateStatus(ref template, robotConfigurationService, esppObject.Robot);
//if (!await templateService.CommitAsync())
// logger.LogError($"Н е удалось изменить запись Template {template.Name}, Robot: {esppObject.Robot}");
//else
// logger.LogInformation($"Установлен принудительный статус {TaskStatusEnum.Updating}, Template {template.Name}, Robot: {esppObject.Robot}");
#endregion
} //надо ли проверять если не изменился, но был статус Updating не понятно. Доверяем роботу пока, что после окончания работ он точно сообщит
else
{
logger . LogInformation ( $"Нет изменений, обновление не требуется. {esppObject.TemplateName}" ) ;
//если все поля совпали
//проверяем, какой был статус предыдущий статус в БД, если он был не Ок, то ставим ему О К
var robotConfig = robotConfigurationService . GetFromTemplateByRobotCode ( esppObject . Robot , ref template ) ;
if ( robotConfig . TaskStatusCode ! = ( int ) TaskStatusEnum . Ok )
{
robotConfigurationService . ChangeTaskStatus ( TaskStatusEnum . Ok , ref robotConfig ) ;
if ( ! await templateService . CommitAsync ( ) )
logger . LogError ( $"Н е удалось изменить запись Template {template.Name}, Robot: {esppObject.Robot}" ) ;
else
logger . LogInformation ( $"Установлен принудительный статус {TaskStatusEnum.Ok}, Template {template.Name}, Robot: {esppObject.Robot}" ) ;
}
2023-11-22 11:37:22 +10:00
}
}
}
2025-08-20 14:10:22 +10:00
catch ( Exception ex )
{
logger . LogError ( ex , $"Ошибка синхронизации объекта А С У ЕСПП {esppObject.TemplateName}" ) ;
}
2025-08-06 10:33:55 +10:00
}
2023-11-22 11:37:22 +10:00
}
private void SetUpdateStatus ( ref Template template , IRobotConfigurationService robotConfigurationService , RobotsEnum robot )
{
var robotConfig = robotConfigurationService . GetFromTemplateByRobotCode ( robot , ref template ) ;
robotConfigurationService . ChangeTaskStatus ( TaskStatusEnum . Updating , ref robotConfig ) ;
}
private Service GetServiceInScope < Service > ( IServiceScope scope )
{
var service = scope . ServiceProvider . GetService < Service > ( ) ;
if ( service = = null )
throw new Exception ( $"Н е найден сервис: {nameof(Service)}" ) ;
return service ;
}
2024-02-28 10:17:01 +10:00
//private bool IsChanged(EsppObject esppObj, EsppObject dbObj)
private bool IsChanged ( object esppObj , object dbObj )
2023-11-22 11:37:22 +10:00
{
foreach ( var prop in dbObj . GetType ( ) . GetProperties ( ) )
{
if ( prop = = null )
continue ;
var dbValue = dbObj . GetType ( ) . GetProperty ( prop . Name ) ? . GetValue ( dbObj , null ) ;
var esppValue = esppObj . GetType ( ) . GetProperty ( prop . Name ) ? . GetValue ( esppObj , null ) ;
if ( dbValue = = null | | esppValue = = null )
continue ;
//Replace("\r","").Replace("\n","") - в подробном описании могут быть переносы строк, в Rabbit прилетает без переносов. Убираем переносы для стравнения
2025-08-21 14:51:40 +10:00
var dbValueStr = Normalize ( dbValue ! . ToString ( ) ! ) ;
var esppValueStr = Normalize ( esppValue ! . ToString ( ) ! ) ;
2023-11-22 11:37:22 +10:00
if ( dbValueStr ! = esppValueStr )
{
2024-08-08 11:25:35 +10:00
logger . LogDebug ( $"Н е совпадают поля({prop.Name}). dbValueStr: {dbValueStr}, esppValueStr: {esppValueStr}" ) ;
2023-11-22 11:37:22 +10:00
return true ;
}
}
return false ;
}
2025-08-21 14:51:40 +10:00
/// <summary>
/// Удаляет ненужные символы из строки
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
private string Normalize ( string str )
{
str = str . Replace ( "\r" , string . Empty ) ;
str = str . Replace ( "\n" , string . Empty ) ;
str = str . Replace ( " " , string . Empty ) ;
2023-11-22 11:37:22 +10:00
2025-08-21 14:51:40 +10:00
return str . ToLower ( ) ;
}
2023-11-22 11:37:22 +10:00
}
2025-08-21 14:51:40 +10:00
2023-11-22 11:37:22 +10:00
}