using Microsoft.Extensions.Logging; using PARR.BLL.Domain.Mq; using PARR.BLL.Services.Interfaces; using PARR.DAL.Extensions; using PARR.DAL.Models.Unit; using PARR.DAL.Services.Interfaces.Unit; namespace PARR.AIHITMainSyncer.Services { internal class SyncerService : ISyncerService { private readonly ILogger logger; private readonly ITransformService transformService; private readonly IUnitService unitService; private readonly IUnitFieldService unitFieldService; private readonly IUnitFieldValueService unitFieldValueService; public SyncerService( ILogger logger, ITransformService transformService, IUnitService unitService, IUnitFieldService unitFieldService, IUnitFieldValueService unitFieldValueService ) { this.logger = logger; this.transformService = transformService; this.unitService = unitService; this.unitFieldService = unitFieldService; this.unitFieldValueService = unitFieldValueService; } public async Task SyncAsync(string msg) { logger.LogInformation("Запуск синхронизации данных из очереди сообщений в ПАРР."); var objFromQuery = transformService.GetModelFromJson(msg); if (objFromQuery == null) return; await SyncUnitAsync(objFromQuery); } private async Task SyncUnitAsync(AihitMainDataMq objFromQuery) { var isChanged = false; var unit = await unitService.GetUnitByName(objFromQuery.Name); foreach (var item in objFromQuery.Properties) { //актуализируем справочники в соответствии с пришедшими данными var field = await CreateUnitFieldIfNotExistAsync(item.Key); var value = await CreateFieldValueIfNotExistAsync(field, item.Value); //Если ЭК не найден то создаём его if (unit == null) unit = await CreateUnitAsync(objFromQuery); //else // logger.LogDebug($"Найден Unit в БД: {unit.Name})"); //теперь проверяем наличие поля связанного с этим ЭК if (SyncFields(unit, field) && !isChanged) isChanged = true; //Синхронизируем значение if (SyncValues(unit, field, value) && !isChanged) isChanged = true; } if (isChanged && !await unitService.CommitAsync()) logger.LogError($"Не удалось изменить Unit {objFromQuery.Name}"); else logger.LogDebug($"----- Набор данных в Unit изменён: {objFromQuery.Name} -----"); } private bool SyncFields(Unit unit, UnitField field) { var isChanged = false; var fieldInUnit = unit!.UnitFields.FirstOrDefault(u => u.FieldId == field.Id); if (fieldInUnit == null) { if (!isChanged) isChanged = true; unit.UnitFields.Add( new UnitInField { UnitId = unit.Id, FieldId = field.Id, DateCreated = DateTimeOffset.UtcNow } ); } return isChanged; } private bool SyncValues(Unit unit, UnitField field, UnitFieldValue value) { var isChanged = false; var valueInUnit = unit!.UnitValues.FirstOrDefault(uv => uv.FieldId == field.Id); if (valueInUnit == null) { if (!isChanged) isChanged = true; unit.UnitValues.Add( new UnitInValue { UnitId = unit.Id, FieldId = field.Id, ValueId = value.Id, DateCreated = DateTime.UtcNow } ); } else if (valueInUnit.Value != value) { if (!isChanged) isChanged = true; { valueInUnit.ValueId = value.Id; valueInUnit.DateModified = DateTime.UtcNow; } } return isChanged; } private async Task CreateUnitAsync(AihitMainDataMq objFromQuery) { var unit = new Unit { Name = objFromQuery.Name.Trim() }; if (!await unitService.CreateAsync(unit) || !await unitService.CommitAsync()) logger.LogError($"Не удалось создать Unit {unit.Name}"); else logger.LogDebug($"----- Создан Unit: {unit.Name} -----"); return (await unitService.GetUnitByName(unit.Name))!; } private async Task CreateUnitFieldIfNotExistAsync(string name) { var existUnitField = await unitFieldService.GetByAihitNameAsync(name); if (existUnitField != null) return existUnitField; var field = new UnitField { Id = Guid.NewGuid(), AihitName = name.Trim(), EsppName = null, }; if (!await unitFieldService.CreateAsync(field) || !await unitFieldService.CommitAsync()) logger.LogError($"Не удалось создать запись в таблице Fields: {name}, {field.ToJson()}"); else logger.LogDebug($"Создана запись а таблице Fields: {name}, {field.ToJson()}"); return (await unitFieldService.GetAsync(field.Id))!; } private async Task CreateFieldValueIfNotExistAsync(UnitField field, string? value) { var existUnitFieldValue = await unitFieldValueService.GetByValueNameAsync(value); //если значение существует отдаем его if (existUnitFieldValue != null) { //проверяем связь с таблицей Fields if (existUnitFieldValue.FieldValues.FirstOrDefault(fv => fv.FieldId == field.Id) == null) { var unitFieldInUnitFieldValue = new UnitFieldInUnitFieldValue { FieldId = field.Id, FieldValueId = existUnitFieldValue.Id, DateCreated = DateTime.UtcNow, }; existUnitFieldValue.FieldValues.Add(unitFieldInUnitFieldValue); if (!await unitFieldValueService.CommitAsync()) logger.LogError($"Не удалось создать связь таблицы FieldValues и Fields: {unitFieldValueService.ToJson()}"); else logger.LogDebug($"Создана связь таблицы FieldValues и Fields: {unitFieldValueService.ToJson()}"); } return existUnitFieldValue; } //значение не найдено значит создаём его var newValue = new UnitFieldValue { Id = Guid.NewGuid(), Value = (value == null) ? null : value.Trim() }; //и привязываем значение к полю newValue.FieldValues.Add( new UnitFieldInUnitFieldValue { FieldId = field.Id, FieldValueId = newValue.Id, DateCreated = DateTime.UtcNow, } ); //пишем в базу данных if (!await unitFieldValueService.CreateAsync(newValue) || !await unitFieldValueService.CommitAsync()) logger.LogError($"Не удалось создать запись в таблице Values: {newValue.Value}, {newValue.ToJson()}"); else logger.LogDebug($"Создана запись а таблице Values: {newValue.Value}, {newValue.ToJson()}"); return (await unitFieldValueService.GetAsync(newValue.Id))!; } } }