Files
parr_api/PARR.AIHITMainSyncer/Services/SyncerService.cs

241 lines
9.5 KiB
C#
Raw Normal View History

2025-05-30 09:50:47 +10:00
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
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<SyncerService> logger;
private readonly ITransformService transformService;
private readonly IUnitService unitService;
private readonly IUnitFieldService unitFieldService;
private readonly IUnitFieldValueService unitFieldValueService;
public SyncerService(
ILogger<SyncerService> 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<AihitMainDataMq>(msg);
if (objFromQuery == null)
return;
await SyncUnitAsync(objFromQuery);
}
private async Task SyncUnitAsync(AihitMainDataMq objFromQuery)
{
2025-05-30 09:50:47 +10:00
await SyncFieldsAsync(objFromQuery.Properties);
2025-05-30 09:50:47 +10:00
await SyncValuesAsync(objFromQuery.Properties);
2025-05-30 09:50:47 +10:00
Unit unit = await GetUnit(objFromQuery.Name);
2025-05-30 09:50:47 +10:00
var changes = GetChangesInUnit(objFromQuery.Properties, unit);
2025-05-30 09:50:47 +10:00
if (changes.Any())
{
var fieldsNameWithId = await unitFieldService.Get().AsNoTracking().Where(t => changes.Select(c =>
Sanitize(c.Key.ToLower())).Any(c =>
c == t.AihitName.ToLower()
)).ToListAsync();
var valuesWithId = await unitFieldValueService.Get().AsNoTracking().Where(t => changes.Select(c =>
(c.Value == null) ? null : Sanitize(c.Value.ToLower())
).Any(c => c ==
((t.Value == null) ? null : t.Value!.ToLower())
)).ToListAsync();
foreach (var change in changes)
{
ApplyChange(unit, fieldsNameWithId, valuesWithId, change);
}
2025-05-30 09:50:47 +10:00
if (!await unitService.CommitAsync())
logger.LogError($"Не удалось применить изменения по актуализиции аттрибуто Unit {unit.Name} в базе данных");
}
}
2025-05-30 09:50:47 +10:00
private void ApplyChange(Unit unit, List<UnitField> fieldsNameWithId, List<UnitFieldValue> valuesWithId, KeyValuePair<string, string?> change)
{
2025-05-30 09:50:47 +10:00
var uValue = unit.UnitValues.FirstOrDefault(t => IsStringEqual(t.Field?.AihitName, change.Key));
2025-05-30 09:50:47 +10:00
if (uValue == null)
{
var f = new UnitInValue
{
UnitId = unit.Id,
FieldId = fieldsNameWithId.First(t => IsStringEqual(t.AihitName, change.Key)).Id,
ValueId = valuesWithId.First(t => IsStringEqual(t.Value, change.Value)).Id,
DateCreated = DateTimeOffset.UtcNow
};
2025-05-30 09:50:47 +10:00
unit.UnitValues.Add(f);
}
else
{
2025-05-30 09:50:47 +10:00
uValue.ValueId = valuesWithId.First(t => IsStringEqual(t.Value, change.Value)).Id;
uValue.DateModified = DateTimeOffset.UtcNow;
}
2025-05-30 09:50:47 +10:00
}
2025-05-30 09:50:47 +10:00
private List<KeyValuePair<string, string?>> GetChangesInUnit(Dictionary<string, string?> properties, Unit unit)
{
return properties.Where(t =>
!unit.UnitValues.Any(
uv => uv.Field!.AihitName.ToLower() == Sanitize(t.Key.ToLower()) && (
(t.Value == null) ?
uv.Value?.Value == null :
((uv.Value?.Value == null) ? null : uv.Value!.Value!.ToLower()) == Sanitize(t.Value.ToLower())
)
)
).ToList();
}
2025-05-30 09:50:47 +10:00
private async Task SyncValuesAsync(Dictionary<string, string?> properties)
{
2025-05-30 09:50:47 +10:00
// все поля из АИХИТ
var valuesFromAihit = properties.Select(t => t.Value?.Trim()).Distinct();
// список values для поиска в БД без null
var valuesFromAihitWithoutNull = valuesFromAihit.Where(x => x != null).Select(t => t!.ToLower()).ToList();
var valuesInDb = await unitFieldValueService.Get().Where(t =>
(t.Value != null &&
valuesFromAihitWithoutNull.Any(x => x == t.Value.ToLower())
)
|| (t.Value == null)
).Select(t => t.Value)
.ToListAsync();
if (!valuesFromAihit.Any(x => x == null))
valuesInDb.Remove(null);
2025-05-30 09:50:47 +10:00
var newValues = valuesFromAihit.Where(t => !valuesInDb.Any(x => IsStringEqual(x, t))).ToList();
2025-05-30 09:50:47 +10:00
if (newValues.Any())
{
2025-05-30 09:50:47 +10:00
foreach (var item in newValues)
{
var value = new UnitFieldValue
{
2025-05-30 09:50:47 +10:00
Id = Guid.NewGuid(),
DateCreated = DateTimeOffset.UtcNow,
Value = Sanitize(item)
};
if (!await unitFieldValueService.CreateAsync(value))
logger.LogError($"Не удалось создать запись в таблице FieldValues: {item}, {value.ToJson()}");
else
logger.LogInformation($"Создана запись а таблице FieldValues: {item}, {value.ToJson()}");
}
if (!await unitFieldValueService.CommitAsync())
logger.LogError($"Не удалось применить изменения по добавлению новых Fields в базе данных");
}
2025-05-30 09:50:47 +10:00
}
private async Task SyncFieldsAsync(Dictionary<string, string?> properties)
{
var fields = properties.Select(t => t.Key.Trim());
var newFields = fields.Where(t => !unitFieldService.Get().Any(f => f.AihitName.ToLower() == t.ToLower()));
if (newFields.Any())
{
2025-05-30 09:50:47 +10:00
foreach (var item in newFields)
{
2025-05-30 09:50:47 +10:00
var field = new UnitField
{
Id = Guid.NewGuid(),
AihitName = Sanitize(item)!,
EsppName = null,
};
if (!await unitFieldService.CreateAsync(field))
logger.LogError($"Не удалось создать запись в таблице Fields: {item}, {field.ToJson()}");
else
logger.LogInformation($"Создана запись а таблице Fields: {item}, {field.ToJson()}");
}
2025-05-30 09:50:47 +10:00
if (!await unitFieldService.CommitAsync())
logger.LogError($"Не удалось применить изменения по добавлению новых Fields в базе данных");
}
}
2025-05-30 09:50:47 +10:00
private string? Sanitize(string? value)
{
2025-05-30 09:50:47 +10:00
var _value = value?.Trim();
return _value;
}
2025-05-30 09:50:47 +10:00
private bool IsStringEqual(string? value1, string? value2)
{
2025-05-30 09:50:47 +10:00
var _value1 = value1?.ToLower().Trim();
var _value2 = value2?.ToLower().Trim();
return _value1 == _value2;
}
2025-05-30 09:50:47 +10:00
private async Task<Unit> GetUnit(string name)
{
var unit = await GetUnitByName(name.Trim());
2025-05-30 09:50:47 +10:00
if (unit == null)
unit = await CreateUnitAsync(name);
2025-05-30 09:50:47 +10:00
return unit;
}
2025-05-30 09:50:47 +10:00
private async Task<Unit> CreateUnitAsync(string name)
{
2025-05-30 09:50:47 +10:00
var unit = new Unit { Name = name.Trim() };
2025-05-30 09:50:47 +10:00
if (!await unitService.CreateAsync(unit) || !await unitService.CommitAsync())
logger.LogError($"Не удалось создать Unit {unit.Name}");
else
logger.LogInformation($"----- Создан Unit: {unit.Name} -----");
2025-05-30 09:50:47 +10:00
return unit;
}
2025-05-30 09:50:47 +10:00
public async Task<Unit?> GetUnitByName(string name)
{
return await GetUnitWithFieldsAndValues()
.FirstOrDefaultAsync(u => u.Name.ToLower() == name.ToLower());
}
2025-05-30 09:50:47 +10:00
private IQueryable<Unit> GetUnitWithFieldsAndValues()
{
return unitService.Get()
.Include(t => t.UnitValues)
.ThenInclude(uv => uv.Field)
.Include(t => t.UnitValues)
.ThenInclude(uf => uf.Value);
}
}
2025-05-30 09:50:47 +10:00
}