2024-02-06 16:54:40 +10:00
using Microsoft.EntityFrameworkCore ;
using Microsoft.Extensions.Logging ;
using PARR.BLL.Domain.Mq ;
using PARR.BLL.Services.Interfaces ;
using PARR.DAL.Contracts ;
using PARR.DAL.Extensions ;
using PARR.DAL.Models ;
using PARR.DAL.Services.Interfaces ;
using System.Text.RegularExpressions ;
namespace PARR.AIHITSyncer.Services
{
internal class SyncerService : ISyncerService
{
private readonly ILogger < SyncerService > logger ;
private readonly IHostService hostService ;
private readonly IApplicationService appService ;
private readonly IApplicationInHostService appInHostService ;
private readonly IApplicationTypeService appTypeService ;
private readonly ITransformService transformService ;
2024-06-04 11:00:14 +10:00
private readonly IWorkGroupService workGroupService ;
2024-02-06 16:54:40 +10:00
public List < ApplicationType > AppTypes { get ; private set ; } = new List < ApplicationType > ( ) ;
public SyncerService (
ILogger < SyncerService > logger ,
IHostService hostService ,
IApplicationService appService ,
IApplicationInHostService appInHostService ,
IApplicationTypeService appTypeService ,
2024-06-04 11:00:14 +10:00
ITransformService transformService ,
IWorkGroupService workGroupService
2024-02-06 16:54:40 +10:00
)
{
this . logger = logger ;
this . hostService = hostService ;
this . appService = appService ;
this . appInHostService = appInHostService ;
this . appTypeService = appTypeService ;
this . transformService = transformService ;
2024-06-04 11:00:14 +10:00
this . workGroupService = workGroupService ;
2024-02-06 16:54:40 +10:00
}
public async Task SyncAsync ( string msg )
{
await GetAppTypesAsync ( ) ;
var objFromQuery = transformService . GetModelFromJson < AihitDataMq > ( msg ) ;
if ( objFromQuery = = null )
return ;
await SyncHostAsync ( objFromQuery ) ;
}
private async Task SyncHostAsync ( AihitDataMq objFromQuery )
{
//ищем существующий хост в БД
2024-04-18 10:18:14 +10:00
//var host = await hostService.GetHostWithAppsByIpAsync(objFromQuery.IP);
var host = await hostService . GetHostWithAppsByEkAsync ( objFromQuery . EK ) ;
2024-02-06 16:54:40 +10:00
var isNew = false ;
//если не нашли - создаём
if ( host = = null )
{
isNew = true ;
host = await CreateHostAsync ( objFromQuery ) ;
}
else
{
logger . LogDebug ( $"Найден хост в БД: {host!.Ek}({host.IP})" ) ;
//проверям и обновляем поля
await SyncHostFieldsAsync ( host , objFromQuery ) ;
}
//получаем лист ПО из объекта
var appsInObj = await GetAppsInObjectAsync ( host , objFromQuery ) ;
await SyncApplicationInHostAsync ( host , appsInObj , ! isNew ) ;
}
private async Task < Host ? > CreateHostAsync ( AihitDataMq objFromQuery )
{
var id = Guid . NewGuid ( ) ;
2024-06-04 11:00:14 +10:00
2024-06-18 14:28:38 +10:00
int responseAreaCode = GetResponseAreaCodeFromStr ( objFromQuery . ResponseArea ) ? ? 0 ;
if ( responseAreaCode = = 0 )
return null ;
2024-06-04 11:00:14 +10:00
2024-02-06 16:54:40 +10:00
var host = new Host
{
Id = id ,
Ek = objFromQuery . EK ,
IP = objFromQuery . IP ,
EkStatusCode = ResolveCode ( objFromQuery . Status ) ,
2024-06-04 11:00:14 +10:00
//WorkGroup = objFromQuery.WorkGroup,
2024-06-18 14:28:38 +10:00
WorkGroup = await CreateWorkGroupIfNotExistAsync ( objFromQuery . WorkGroup , objFromQuery . WorkGroupResponseArea ) ,
// ResponseAreaCode = ((ResolveCode(objFromQuery.ResponseArea) == 0) ? 99 : ResolveCode(objFromQuery.ResponseArea))
ResponseAreaCode = responseAreaCode
2024-02-06 16:54:40 +10:00
} ;
if ( ! await hostService . CreateAsync ( host ) | | ! await hostService . CommitAsync ( ) )
logger . LogError ( $"Н е удалось создать узел {host.Ek}({host.IP})" ) ;
else
logger . LogInformation ( $"----- Создан узел: {host.Id} -----" ) ;
2024-04-18 10:18:14 +10:00
//return await hostService.GetHostWithAppsByIpAsync(host.IP);
return await hostService . GetHostWithAppsByEkAsync ( host . Ek ) ;
2024-02-06 16:54:40 +10:00
}
2024-06-18 14:28:38 +10:00
private async Task < WorkGroup ? > CreateWorkGroupIfNotExistAsync ( string? workGroupName , string wgResponseArea )
2024-06-04 11:00:14 +10:00
{
2024-06-18 14:28:38 +10:00
if ( string . IsNullOrEmpty ( workGroupName ) | | string . IsNullOrWhiteSpace ( workGroupName ) )
return null ;
if ( string . IsNullOrEmpty ( wgResponseArea ) | | string . IsNullOrWhiteSpace ( wgResponseArea ) )
return null ;
int wgCode = GetResponseAreaCodeFromStr ( wgResponseArea ) ? ? 0 ;
if ( wgCode = = 0 )
return null ;
2024-06-04 11:00:14 +10:00
var existWorkGroup = await workGroupService . GetByNameAsync ( workGroupName ) ;
if ( existWorkGroup ! = null )
2024-06-18 14:28:38 +10:00
{
//проверяем, соответствует ли рабочая группа
if ( existWorkGroup . ResponseAreaCode ! = wgCode )
{
logger . LogDebug ( $"У рабочей группы {existWorkGroup.Name} не совпадают З О , обновляем, текущее значение: {existWorkGroup.ResponseAreaCode}, новое: {wgCode}" ) ;
existWorkGroup . ResponseAreaCode = wgCode ;
if ( ! await workGroupService . CommitAsync ( ) )
{
logger . LogError ( $"Ошибка при обновлении З О рабочей группы {existWorkGroup.Name}" ) ;
}
}
2024-06-04 11:00:14 +10:00
return existWorkGroup ;
2024-06-18 14:28:38 +10:00
}
2024-06-04 11:00:14 +10:00
var workGroup = new WorkGroup
{
Id = Guid . NewGuid ( ) ,
Name = workGroupName . Trim ( ) ,
2024-06-18 14:28:38 +10:00
ResponseAreaCode = wgCode
2024-06-04 11:00:14 +10:00
} ;
if ( ! await workGroupService . CreateAsync ( workGroup ) | | ! await workGroupService . CommitAsync ( ) )
logger . LogError ( $"Н е удалось создать запись в таблице WorkGroups: {workGroupName}, {workGroup.ToJson()}" ) ;
else
logger . LogInformation ( $"Создана запись а таблице WorkGroups: {workGroupName}, {workGroup.ToJson()}" ) ;
2025-05-19 16:09:55 +10:00
return await workGroupService . GetAsync ( workGroup . Id ) ;
2024-06-04 11:00:14 +10:00
}
2024-02-06 16:54:40 +10:00
private async Task SyncHostFieldsAsync ( Host host , AihitDataMq objFromQuery )
{
var isChanged = false ;
if ( host . IP ! = objFromQuery . IP )
{
host . IP = objFromQuery . IP ;
isChanged = true ;
}
if ( host . EkStatusCode ! = ResolveCode ( objFromQuery . Status ) )
{
host . EkStatusCode = ResolveCode ( objFromQuery . Status ) ;
isChanged = true ;
}
2024-06-04 11:00:14 +10:00
//TODO Удалить после перехода на самостоятельный объект WorkGroup
//if (objFromQuery.WorkGroup != null && (host.WorkGroup == null || !host.WorkGroup!.Equals(objFromQuery.WorkGroup)))
//{
// host.WorkGroup = objFromQuery.WorkGroup;
// isChanged = true;
//}
2024-06-04 12:30:44 +10:00
if ( objFromQuery . WorkGroup ! = null & & ( host . WorkGroup = = null | | ! host . WorkGroup ! . Name . Equals ( objFromQuery . WorkGroup ) ) )
2024-02-06 16:54:40 +10:00
{
2024-06-18 14:28:38 +10:00
host . WorkGroup = await CreateWorkGroupIfNotExistAsync ( objFromQuery . WorkGroup , objFromQuery . WorkGroupResponseArea ) ;
2024-02-06 16:54:40 +10:00
isChanged = true ;
}
2024-06-04 11:00:14 +10:00
2024-06-18 14:28:38 +10:00
int responseAreaCode = GetResponseAreaCodeFromStr ( objFromQuery . ResponseArea ) ? ? 0 ;
2024-08-30 10:17:06 +10:00
if ( responseAreaCode = = 0 )
{
2024-06-18 14:28:38 +10:00
logger . LogWarning ( $"Ошибка при получении З О хоста: {objFromQuery.EK}, З О : {objFromQuery.ResponseArea}" ) ;
return ;
}
2024-06-04 11:00:14 +10:00
2024-06-18 14:28:38 +10:00
//if (host.ResponseAreaCode != ((ResolveCode(objFromQuery.ResponseArea) == 0) ? 99 : ResolveCode(objFromQuery.ResponseArea)))
if ( host . ResponseAreaCode ! = responseAreaCode )
2024-02-06 16:54:40 +10:00
{ //TODO Возможно проще выгружать с помощью INCLUDE зону ответственности и сравнивать string
2024-06-18 14:28:38 +10:00
//host.ResponseAreaCode = ((ResolveCode(objFromQuery.ResponseArea) == 0) ? 99 : ResolveCode(objFromQuery.ResponseArea));
host . ResponseAreaCode = responseAreaCode ;
2024-02-06 16:54:40 +10:00
isChanged = true ;
}
if ( isChanged )
{
host . DateModified = DateTimeOffset . UtcNow ;
if ( ! await hostService . CommitAsync ( ) )
logger . LogError ( $"Н е удалось обновить узел {host.Ek}({host.IP})" ) ;
else
logger . LogInformation ( $"Обновлён Host: {host.Ek}({host.Id})" ) ;
}
}
private async Task < List < Application > > GetAppsInObjectAsync ( Host ? host , AihitDataMq objFromQuery )
{
var applications = new List < Application > ( ) ;
2024-04-18 10:18:14 +10:00
if ( objFromQuery . APP ! = null )
2024-02-06 16:54:40 +10:00
{
2024-04-19 15:31:19 +10:00
var appList = ParseAppsList ( objFromQuery . APP ) ;
2024-02-06 16:54:40 +10:00
foreach ( var app in appList )
{
var created = await CreateAppIfNotExistAsync ( app , ApplicationTypesEnum . APP ) ;
if ( created ! = null )
applications . Add ( created ) ;
}
}
2024-04-18 10:18:14 +10:00
if ( objFromQuery . DB ! = null )
2024-02-06 16:54:40 +10:00
{
2024-04-19 15:31:19 +10:00
var appList = ParseAppsList ( objFromQuery . DB ) ;
2024-02-06 16:54:40 +10:00
foreach ( var app in appList )
{
var created = await CreateAppIfNotExistAsync ( app , ApplicationTypesEnum . DB ) ;
if ( created ! = null )
applications . Add ( created ) ;
}
}
2024-04-18 10:18:14 +10:00
if ( objFromQuery . CKBS ! = null )
2024-02-06 16:54:40 +10:00
{
2024-04-19 15:31:19 +10:00
var appList = ParseAppsList ( objFromQuery . CKBS ) ;
2024-04-18 10:18:14 +10:00
foreach ( var app in appList )
{
var created = await CreateAppIfNotExistAsync ( app , ApplicationTypesEnum . CKBS ) ;
if ( created ! = null )
applications . Add ( created ) ;
}
}
if ( objFromQuery . IB ! = null )
{
2024-04-19 15:31:19 +10:00
var appList = ParseAppsList ( objFromQuery . IB ) ;
2024-04-18 10:18:14 +10:00
foreach ( var app in appList )
{
var created = await CreateAppIfNotExistAsync ( app , ApplicationTypesEnum . IB ) ;
if ( created ! = null )
applications . Add ( created ) ;
}
}
if ( objFromQuery . SI ! = null )
{
2024-04-19 15:31:19 +10:00
var appList = ParseAppsList ( objFromQuery . SI ) ;
2024-04-18 10:18:14 +10:00
foreach ( var app in appList )
{
var created = await CreateAppIfNotExistAsync ( app , ApplicationTypesEnum . SI ) ;
if ( created ! = null )
applications . Add ( created ) ;
}
}
if ( objFromQuery . SM ! = null )
{
2024-04-19 15:31:19 +10:00
var appList = ParseAppsList ( objFromQuery . SM ) ;
2024-04-18 10:18:14 +10:00
foreach ( var app in appList )
{
var created = await CreateAppIfNotExistAsync ( app , ApplicationTypesEnum . SM ) ;
if ( created ! = null )
applications . Add ( created ) ;
}
}
if ( objFromQuery . OS ! = null )
{
2024-04-19 15:31:19 +10:00
var appList = ParseAppsList ( objFromQuery . OS ) ;
2024-02-06 16:54:40 +10:00
foreach ( var app in appList )
{
var created = await CreateAppIfNotExistAsync ( app , ApplicationTypesEnum . OS ) ;
if ( created ! = null )
applications . Add ( created ) ;
}
}
return applications ;
}
2024-04-19 15:31:19 +10:00
private List < string > ParseAppsList ( string appStr )
{
2024-08-30 10:17:06 +10:00
// в АИХИТ стали появляться разделители \r \n находим их и заменяем на ,
if ( appStr . Contains ( "\r" ) | | appStr . Contains ( "\n" ) )
{
string orig = appStr ;
appStr = appStr . Replace ( "\r" , "," ) . Replace ( "\n" , "," ) ;
logger . LogDebug ( $"В строке найдены переносы, заменены на разделители. Исходная строка: {orig}. Результат: {appStr}" ) ;
}
2024-04-19 15:31:19 +10:00
var regex = new Regex ( "\\([^)]*\\)" ) ;
2024-06-04 11:00:14 +10:00
if ( regex . IsMatch ( appStr ) )
2024-04-19 15:31:19 +10:00
foreach ( var parenthesis in regex . Matches ( appStr ) )
{
if ( ! string . IsNullOrEmpty ( parenthesis . ToString ( ) ) )
{
var newParenthesis = parenthesis . ToString ( ) ! . Replace ( "," , "<|>" ) . Replace ( ";" , "<|>" ) ;
appStr = appStr . Replace ( parenthesis ! . ToString ( ) ! , newParenthesis ) ;
}
}
2024-06-04 11:00:14 +10:00
2024-04-19 15:31:19 +10:00
return appStr . Split ( new char [ ] { ',' , ';' } ) . Select ( a = > a . Replace ( "<|>" , "," ) ) . Distinct ( ) . ToList ( ) ;
}
2024-02-06 16:54:40 +10:00
private async Task < Application ? > CreateAppIfNotExistAsync ( string appName , ApplicationTypesEnum type )
{
if ( string . IsNullOrEmpty ( appName ) | | string . IsNullOrWhiteSpace ( appName ) ) return null ;
var appType = GetAppTypeByName ( type ) ;
if ( appType = = null )
{
logger . LogError ( $"Н е удалось создать запись в таблице Applications: {appName}, так как не получил AppType: {type.ToString()}" ) ;
return null ;
}
2024-04-17 11:51:24 +10:00
var existApp = await appService . GetByNameAsync ( appName , appType . Id ) ;
if ( existApp ! = null )
return existApp ;
//Создаем
2024-02-06 16:54:40 +10:00
var app = new Application
{
Id = Guid . NewGuid ( ) ,
Name = appName . Trim ( ) ,
ApplicationTypeId = appType . Id
} ;
if ( ! await appService . CreateAsync ( app ) | | ! await appService . CommitAsync ( ) )
logger . LogError ( $"Н е удалось создать запись в таблице Application: {appName}, {app.ToJson()}" ) ;
else
logger . LogInformation ( $"Создана запись а таблице Application: {appName}, {app.ToJson()}" ) ;
return await appService . GetAsync ( app . Id ) ;
}
/// <summary>
/// Метод синхронизации
/// </summary>
/// <param name="host">Хост</param>
/// <param name="hostApplications">Список программного обеспечения</param>
/// <param name="isUpdateDateModified">Признак обновления поля DateModified</param>
/// <returns></returns>
private async Task SyncApplicationInHostAsync ( Host ? host , List < Application > appsInObject , bool isUpdateDateModified = false )
{
var isUpdated = false ;
if ( host = = null )
return ;
logger . LogDebug ( $"Host: {host.Ek}({host.IP}), начало синхронизации приложений ({appsInObject.Count()}) " ) ;
foreach ( var appInObject in appsInObject )
{
var exist = host . ApplicationsInHosts . FirstOrDefault ( a = > a . ApplicationId = = appInObject . Id ) ;
if ( exist = = null )
{
//add
logger . LogInformation ( $"Host: {host.Ek}({host.IP}), добавление нового приложения Application {appInObject.Name}" ) ;
var newAppHost = new ApplicationInHost { Id = Guid . NewGuid ( ) , ApplicationId = appInObject . Id , HostId = host . Id } ;
if ( ! await appInHostService . CreateAsync ( newAppHost ) )
logger . LogError ( $"Н е удалось создать ApplicationInHost {appInObject.Name}, host: {host.Ek}({host.IP})" ) ;
isUpdated = true ;
}
}
foreach ( var appInHost in host . ApplicationsInHosts )
{
var appToRemove = appsInObject . FirstOrDefault ( a = > a . Id = = appInHost . ApplicationId ) ;
if ( appToRemove = = null )
{
//todo remove appToRemove
var obj = await appInHostService . Get ( ) . FirstOrDefaultAsync ( t = > t . ApplicationId = = appInHost . ApplicationId & & t . HostId = = host . Id ) ;
if ( obj ! = null )
{
logger . LogInformation ( $"Host: {host.Ek}({host.IP}), удаление неактуального приложения Application {appInHost.Application?.Name}" ) ;
appInHostService . Delete ( obj ) ;
if ( ! await appInHostService . CommitAsync ( ) )
logger . LogError ( $"Н е удалось удалить Application {appInHost.Application?.Name} узла {host.Ek}({host.IP})" ) ;
isUpdated = true ;
}
}
}
if ( isUpdated & & isUpdateDateModified )
host . DateModified = DateTimeOffset . UtcNow ;
if ( ! await appInHostService . CommitAsync ( ) )
logger . LogError ( $"Н е удалось обновить ApplicationInHost для Host: {host.Ek}({host.IP})" ) ;
2024-07-22 16:59:15 +10:00
logger . LogDebug ( $"Host: {host.Ek}({host.IP}) конец синхронизации приложений" ) ;
2024-02-06 16:54:40 +10:00
}
private ApplicationType ? GetAppTypeByName ( ApplicationTypesEnum type )
{
var existType = AppTypes . FirstOrDefault ( t = > t . Name = = type . ToString ( ) ) ;
if ( existType = = null )
logger . LogError ( $"Н е найден AppType: {type}" ) ;
return existType ;
}
/// <summary>
/// Возвращает первую цифру из строки, котроая является кодом статуса или зоны ответственности для ЭК
/// </summary>
/// <param name="field"></param>
/// <returns></returns>
private int ResolveCode ( string field )
{
var pattern = "\\d+" ;
var regex = new Regex ( pattern ) ;
int . TryParse ( regex . Match ( field ) . Value , out int result ) ;
return result ;
}
2024-06-18 14:28:38 +10:00
private int? GetResponseAreaCodeFromStr ( string responseAreaStr )
{
if ( string . IsNullOrEmpty ( responseAreaStr ) | | string . IsNullOrWhiteSpace ( responseAreaStr ) )
return null ;
if ( responseAreaStr . ToUpper ( ) . Trim ( ) = = "ОБЩЕЕ" )
return ( int ) ResponseAreaEnum . general ;
if ( responseAreaStr . ToUpper ( ) . Trim ( ) = = "00-ГВЦ" )
return ( int ) ResponseAreaEnum . gvc ;
return ResolveCode ( responseAreaStr ) ;
}
2024-02-06 16:54:40 +10:00
private async Task GetAppTypesAsync ( )
{
if ( AppTypes = = null | | AppTypes . Count = = 0 )
AppTypes = await appTypeService . Get ( ) . ToListAsync ( ) ;
}
}
}