using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using PARR.AIHITRelationshipsSyncer.Models; using PARR.AIHITRelationshipsSyncer.Services.Interfaces; using PARR.DAL.Models.Unit; using PARR.DAL.Services.Interfaces.Unit; using System.Reactive; using Unit = PARR.DAL.Models.Unit.Unit; namespace PARR.AIHITRelationshipsSyncer.Services.Implementations { internal class RelationshipsSyncSrevice : IRelationshipsSyncService { private readonly ILogger logger; private readonly IUnitService unitService; public RelationshipsSyncSrevice(ILogger logger, IUnitService unitService ) { this.logger = logger; this.unitService = unitService; } public async Task SyncAsync(List aihitdata) { var groupedData = aihitdata.Where(t => t.EKFindCode != null && t.ChildEk != null).GroupBy(ad => ad.EKFindCode); //Перебираем сгруппированные по родительскому ЭК данные foreach (var item in groupedData) { //Получаем имя родителя var parentName = item.First().EKFindCode; //if (parentName.ToLower() != "ас-рп-рцку-гор") // continue; //По имени получаем экземпляр Unit со всеми дочерними связями var unit = await GetUnitByNameAsync(parentName!); //Из данных АИХ ИТ получаем имена всех дочерних ЭК var childsName = item.Select(t => t.ChildEk); //Проходим циклом по полученному списку для актуализации связей в полученном нами экземпляре Unit foreach (var childName in childsName) { //if (childName.ToLower() != "рпа-робин-рцку-спиуи-прочее-26-гор") // continue; //Ищем детей по имени var child = unit.ChildUnits.FirstOrDefault(t => t.ChildUnit?.Name.ToLower() == childName!.ToLower().Trim()); //не нашли создаём и сразу пишем в базу, чтобы если попадуться дубликаты в списке они были созданы if (child == null) { var childUnit = await GetUnitByNameAsync(childName!); unit.ChildUnits.Add( new UnitInUnit { ParentUnitId = unit.Id, ChildUnitId = childUnit.Id, DateCreated = DateTimeOffset.UtcNow, DateSynced = DateTimeOffset.UtcNow } ); if (!await unitService.CommitAsync()) logger.LogError($"Не удалось создать связь Unit {unit.Name} с {childUnit.Name}"); else logger.LogInformation($"----- Создана новая связь Unit {unit.Name} с {childUnit.Name} -----"); } //Для всех обновляем дату синхронизации else child.DateSynced = DateTimeOffset.UtcNow; } //После проверки пришедших к нам из АИХ ИТ дочерних связей удаляем лишние/уже не существующие в базе var childsToDelete = unit.ChildUnits.Where(t => childsName.All(a => t.ChildUnit?.Name != a)); if (childsToDelete.Any()) DeleteChilds(unit, childsToDelete); //применяем изменения в базе данных if (!await unitService.CommitAsync()) logger.LogError($"Не удалось изменить связи Unit {unit.Name}"); else logger.LogDebug($"----- Изменены связи Unit: {unit.Name} -----"); } //Удаляем детей у тех кого детей в выборке АИХ ИТ не оказалось var parentNames = groupedData.Select(t => t.Key); var units = await unitService.Get().Include(t => t.ChildUnits).ToListAsync(); var parentsToDeleteChild = units.Where(t => parentNames.All(a => t.Name != a) && t.ChildUnits.Any()); if (parentsToDeleteChild.Any()) { foreach (var unit in parentsToDeleteChild) { unit.ChildUnits.Clear(); //применяем изменения в базе данных if (!await unitService.CommitAsync()) logger.LogError($"Не удалось удалить лишние связи Unit {unit.Name}"); else logger.LogInformation($"----- Удалены лишние связи Unit {unit.Name} -----"); } } } /// /// Удаление дочерних связей у ЭК /// /// /// private void DeleteChilds(Unit unit, IEnumerable unitToDeleteChilds) { foreach (var childUnit in unitToDeleteChilds) { logger.LogInformation($"----- Удаление связи Unit: {childUnit.ParentUnit!.Name} - {childUnit.ChildUnit!.Name} -----"); unit.ChildUnits.Remove(childUnit); } } /// /// Создать новый ЭК по имени /// /// /// private async Task CreateUnit(string ekName) { var unit = new Unit { Name = ekName.Trim() }; if (!await unitService.CreateAsync(unit) || !await unitService.CommitAsync()) logger.LogError($"Не удалось создать Unit {unit.Name}"); else logger.LogDebug($"----- Создан Unit: {unit.Name} -----"); return unit; } /// /// Получить ЭК с дочерними связями по имени, если такого ещё нет создать /// /// /// private async Task GetUnitByNameAsync(string ekName) { if (!unitService.Get().AsNoTracking().Any(u => u.Name.ToLower() == ekName.ToLower().Trim())) { return await CreateUnit(ekName); } return await unitService.Get() .Include(u => u.ChildUnits) .FirstAsync(u => u.Name.ToLower() == ekName.ToLower().Trim()); } } }