diff --git a/PARR.AIHITMainLoader/AihitMainLoader.cs b/PARR.AIHITMainLoader/AihitMainLoader.cs index 5f6d5118..2d007f5e 100644 --- a/PARR.AIHITMainLoader/AihitMainLoader.cs +++ b/PARR.AIHITMainLoader/AihitMainLoader.cs @@ -58,11 +58,14 @@ namespace PARR.AIHITMainLoader { loaderSettings.ResponseAreas.ForEach(responseArea => { + logger.LogDebug($"responseArea = {responseArea}"); var EKs = service.Invoke(responseArea); - EKs.ToList().ForEach(item => - { - listToMq.Add(item.ToMainData()); - }); + + if (EKs != null && EKs.Any()) + EKs.ToList().ForEach(item => + { + listToMq.Add(item.ToMainData()); + }); }); }); @@ -88,9 +91,9 @@ namespace PARR.AIHITMainLoader } - private List>> GetServices() + private List?>> GetServices() { - var serviceList = new List>>(); + var serviceList = new List?>>(); serviceList.Add(aihitService.GetCvkData); serviceList.Add(aihitService.GetPtkData); diff --git a/PARR.AIHITMainLoader/Services/AihitService.cs b/PARR.AIHITMainLoader/Services/AihitService.cs index dfd2e9fe..12218d60 100644 --- a/PARR.AIHITMainLoader/Services/AihitService.cs +++ b/PARR.AIHITMainLoader/Services/AihitService.cs @@ -21,7 +21,7 @@ namespace PARR.AIHITMainLoader.Services } - public IEnumerable GetPtkData(string respArea) + public IEnumerable? GetPtkData(string respArea) { var parameters = new List() { new SqlParameter("@зо", respArea) }; @@ -45,7 +45,7 @@ namespace PARR.AIHITMainLoader.Services } - public IEnumerable GetCvkData(string respArea) + public IEnumerable? GetCvkData(string respArea) { var parameters = new List() { new SqlParameter("@зо", respArea) }; diff --git a/PARR.AIHITMainLoader/Services/IAihitService.cs b/PARR.AIHITMainLoader/Services/IAihitService.cs index c6b420f4..6676ad4d 100644 --- a/PARR.AIHITMainLoader/Services/IAihitService.cs +++ b/PARR.AIHITMainLoader/Services/IAihitService.cs @@ -4,7 +4,7 @@ namespace PARR.AIHITMainLoader.Services { internal interface IAihitService { - IEnumerable GetPtkData(string respArea); - IEnumerable GetCvkData(string respArea); + IEnumerable? GetPtkData(string respArea); + IEnumerable? GetCvkData(string respArea); } } diff --git a/PARR.AIHITMainSyncer/Services/SyncerService.cs b/PARR.AIHITMainSyncer/Services/SyncerService.cs index 47a49a89..2b25fc07 100644 --- a/PARR.AIHITMainSyncer/Services/SyncerService.cs +++ b/PARR.AIHITMainSyncer/Services/SyncerService.cs @@ -13,18 +13,21 @@ namespace PARR.AIHITMainSyncer.Services 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 + IUnitFieldService unitFieldService, + IUnitFieldValueService unitFieldValueService ) { this.logger = logger; this.transformService = transformService; this.unitService = unitService; this.unitFieldService = unitFieldService; + this.unitFieldValueService = unitFieldValueService; } @@ -41,64 +44,88 @@ namespace PARR.AIHITMainSyncer.Services private async Task SyncUnitAsync(AihitMainDataMq objFromQuery) { - var fields = await GetFieldsInObjectAsync(objFromQuery); + var isChanged = false; - var unit = await unitService.GetUnitWithFieldsAsync(objFromQuery.Name); + var unit = await unitService.GetUnitByName(objFromQuery.Name); - if (unit == null) - unit = await CreateUnitAsync(objFromQuery); + 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 в БД: {unit.Name})"); - - await SyncFieldInUnitAsync(unit!, fields); - - + logger.LogInformation($"----- Набор данных в Unit изменён: {objFromQuery.Name} -----"); } - private async Task SyncFieldInUnitAsync(Unit unit, List fieldsId) + private bool SyncFields(Unit unit, UnitField field) { var isChanged = false; - //Смотрим какие поля нам прислали, есть новые? - var newFields = fieldsId.Except(unit.UnitFields.Select(uf => uf.FieldId)).ToList(); + var fieldInUnit = unit!.UnitFields.FirstOrDefault(u => u.FieldId == field.Id); - //добавляем если есть - if (newFields.Any()) + if (fieldInUnit == null) { - if (!isChanged) - isChanged = true; - newFields.ForEach(uf => - { - unit.UnitFields.Add( - new UnitInField { UnitId = unit.Id, FieldId = uf, DateCreated = DateTimeOffset.UtcNow } - ); - }); + if (!isChanged) isChanged = true; + unit.UnitFields.Add( + new UnitInField { UnitId = unit.Id, FieldId = field.Id, DateCreated = DateTimeOffset.UtcNow } + ); } - //TODO: Удаление неактуальных - - if (isChanged && !await unitFieldService.CommitAsync()) - logger.LogError($"Не удалось изменить набор Fields в Unit {unit.Name}"); - else - logger.LogInformation($"----- Набор Fields в Unit изменён: {unit.Name} -----"); + return isChanged; } - private async Task> GetFieldsInObjectAsync(AihitMainDataMq objFromQuery) + + private bool SyncValues(Unit unit, UnitField field, UnitFieldValue value) { - var fields = new List(); + var isChanged = false; - foreach (var item in objFromQuery.Properties) + var valueInUnit = unit!.UnitValues.FirstOrDefault(uv => uv.FieldId == field.Id); + + if (valueInUnit == null) { - var field = await CreateUnitFieldIfNotExistAsync(item.Key); - fields.Add(field!.Id); + 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 fields; + return isChanged; } - private async Task CreateUnitAsync(AihitMainDataMq objFromQuery) + private async Task CreateUnitAsync(AihitMainDataMq objFromQuery) { var unit = new Unit { Name = objFromQuery.Name.Trim() }; @@ -107,11 +134,11 @@ namespace PARR.AIHITMainSyncer.Services else logger.LogInformation($"----- Создан Unit: {unit.Name} -----"); - return await unitService.GetUnitWithFieldsAsync(unit.Name); + return (await unitService.GetUnitByName(unit.Name))!; } - private async Task CreateUnitFieldIfNotExistAsync(string name) + private async Task CreateUnitFieldIfNotExistAsync(string name) { var existUnitField = await unitFieldService.GetByAihitNameAsync(name); @@ -122,7 +149,7 @@ namespace PARR.AIHITMainSyncer.Services { Id = Guid.NewGuid(), AihitName = name.Trim(), - EsppName = null + EsppName = null, }; if (!await unitFieldService.CreateAsync(field) || !await unitFieldService.CommitAsync()) @@ -130,7 +157,61 @@ namespace PARR.AIHITMainSyncer.Services else logger.LogInformation($"Создана запись а таблице Fields: {name}, {field.ToJson()}"); - return await unitFieldService.GetAsync(field.Id); + 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.LogInformation($"Создана связь таблицы 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.LogInformation($"Создана запись а таблице Values: {newValue.Value}, {newValue.ToJson()}"); + + return (await unitFieldValueService.GetAsync(newValue.Id))!; } } } diff --git a/PARR.DAL/Migrations/20250514051030_units.Designer.cs b/PARR.DAL/Migrations/20250520021852_tblUnits.Designer.cs similarity index 99% rename from PARR.DAL/Migrations/20250514051030_units.Designer.cs rename to PARR.DAL/Migrations/20250520021852_tblUnits.Designer.cs index 7eed642c..678e7107 100644 --- a/PARR.DAL/Migrations/20250514051030_units.Designer.cs +++ b/PARR.DAL/Migrations/20250520021852_tblUnits.Designer.cs @@ -12,8 +12,8 @@ using PARR.DAL.Context; namespace PARR.DAL.Migrations { [DbContext(typeof(DataContext))] - [Migration("20250514051030_units")] - partial class units + [Migration("20250520021852_tblUnits")] + partial class tblUnits { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -2667,14 +2667,14 @@ namespace PARR.DAL.Migrations b.Property("DateModified") .HasColumnType("timestamp with time zone"); - b.Property("VlaueId") + b.Property("ValueId") .HasColumnType("uuid"); b.HasKey("UnitId", "FieldId"); b.HasIndex("FieldId"); - b.HasIndex("VlaueId"); + b.HasIndex("ValueId"); b.ToTable("UnitInValues", "unit", t => { @@ -3224,14 +3224,14 @@ namespace PARR.DAL.Migrations .IsRequired(); b.HasOne("PARR.DAL.Models.Unit.Unit", "Unit") - .WithMany("UnitInValues") + .WithMany("UnitValues") .HasForeignKey("UnitId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.HasOne("PARR.DAL.Models.Unit.UnitFieldValue", "Value") .WithMany("UnitInValues") - .HasForeignKey("VlaueId") + .HasForeignKey("ValueId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -3445,7 +3445,7 @@ namespace PARR.DAL.Migrations { b.Navigation("UnitFields"); - b.Navigation("UnitInValues"); + b.Navigation("UnitValues"); }); modelBuilder.Entity("PARR.DAL.Models.Unit.UnitField", b => diff --git a/PARR.DAL/Migrations/20250514051030_units.cs b/PARR.DAL/Migrations/20250520021852_tblUnits.cs similarity index 96% rename from PARR.DAL/Migrations/20250514051030_units.cs rename to PARR.DAL/Migrations/20250520021852_tblUnits.cs index c2911a68..44c3766c 100644 --- a/PARR.DAL/Migrations/20250514051030_units.cs +++ b/PARR.DAL/Migrations/20250520021852_tblUnits.cs @@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore.Migrations; namespace PARR.DAL.Migrations { /// - public partial class units : Migration + public partial class tblUnits : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) @@ -127,7 +127,7 @@ namespace PARR.DAL.Migrations { UnitId = table.Column(type: "uuid", nullable: false), FieldId = table.Column(type: "uuid", nullable: false), - VlaueId = table.Column(type: "uuid", nullable: false), + ValueId = table.Column(type: "uuid", nullable: false), DateCreated = table.Column(type: "timestamp with time zone", nullable: false), DateModified = table.Column(type: "timestamp with time zone", nullable: true) }, @@ -135,8 +135,8 @@ namespace PARR.DAL.Migrations { table.PrimaryKey("PK_UnitInValues", x => new { x.UnitId, x.FieldId }); table.ForeignKey( - name: "FK_UnitInValues_FieldValues_VlaueId", - column: x => x.VlaueId, + name: "FK_UnitInValues_FieldValues_ValueId", + column: x => x.ValueId, principalSchema: "unit", principalTable: "FieldValues", principalColumn: "Id", @@ -195,10 +195,10 @@ namespace PARR.DAL.Migrations column: "FieldId"); migrationBuilder.CreateIndex( - name: "IX_UnitInValues_VlaueId", + name: "IX_UnitInValues_ValueId", schema: "unit", table: "UnitInValues", - column: "VlaueId"); + column: "ValueId"); migrationBuilder.CreateIndex( name: "IX_Units_Name", diff --git a/PARR.DAL/Migrations/DataContextModelSnapshot.cs b/PARR.DAL/Migrations/DataContextModelSnapshot.cs index a51392a4..095ac4ae 100644 --- a/PARR.DAL/Migrations/DataContextModelSnapshot.cs +++ b/PARR.DAL/Migrations/DataContextModelSnapshot.cs @@ -2664,14 +2664,14 @@ namespace PARR.DAL.Migrations b.Property("DateModified") .HasColumnType("timestamp with time zone"); - b.Property("VlaueId") + b.Property("ValueId") .HasColumnType("uuid"); b.HasKey("UnitId", "FieldId"); b.HasIndex("FieldId"); - b.HasIndex("VlaueId"); + b.HasIndex("ValueId"); b.ToTable("UnitInValues", "unit", t => { @@ -3221,14 +3221,14 @@ namespace PARR.DAL.Migrations .IsRequired(); b.HasOne("PARR.DAL.Models.Unit.Unit", "Unit") - .WithMany("UnitInValues") + .WithMany("UnitValues") .HasForeignKey("UnitId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.HasOne("PARR.DAL.Models.Unit.UnitFieldValue", "Value") .WithMany("UnitInValues") - .HasForeignKey("VlaueId") + .HasForeignKey("ValueId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -3442,7 +3442,7 @@ namespace PARR.DAL.Migrations { b.Navigation("UnitFields"); - b.Navigation("UnitInValues"); + b.Navigation("UnitValues"); }); modelBuilder.Entity("PARR.DAL.Models.Unit.UnitField", b => diff --git a/PARR.DAL/Models/Unit/Unit.cs b/PARR.DAL/Models/Unit/Unit.cs index 824808be..86705e9c 100644 --- a/PARR.DAL/Models/Unit/Unit.cs +++ b/PARR.DAL/Models/Unit/Unit.cs @@ -30,6 +30,6 @@ namespace PARR.DAL.Models.Unit public ICollection UnitFields { get; set; } = new HashSet(); - public ICollection UnitInValues { get; set; } = new HashSet(); + public ICollection UnitValues { get; set; } = new HashSet(); } } diff --git a/PARR.DAL/Models/Unit/UnitInValue.cs b/PARR.DAL/Models/Unit/UnitInValue.cs index d0c7bd59..8d6486b0 100644 --- a/PARR.DAL/Models/Unit/UnitInValue.cs +++ b/PARR.DAL/Models/Unit/UnitInValue.cs @@ -15,7 +15,7 @@ namespace PARR.DAL.Models.Unit public Guid FieldId { get; set; } - public Guid VlaueId { get; set; } + public Guid ValueId { get; set; } public DateTimeOffset DateCreated { get; set; } @@ -28,7 +28,7 @@ namespace PARR.DAL.Models.Unit [ForeignKey(nameof(FieldId))] public UnitField? Field { get; set; } - [ForeignKey(nameof(VlaueId))] + [ForeignKey(nameof(ValueId))] public UnitFieldValue? Value { get; set; } } } diff --git a/PARR.DAL/Services/Implementations/Unit/UnitFieldValueService.cs b/PARR.DAL/Services/Implementations/Unit/UnitFieldValueService.cs index 0405c7ac..9082dc4c 100644 --- a/PARR.DAL/Services/Implementations/Unit/UnitFieldValueService.cs +++ b/PARR.DAL/Services/Implementations/Unit/UnitFieldValueService.cs @@ -19,5 +19,17 @@ namespace PARR.DAL.Services.Implementations.Unit { this.dataContext = dataContext; } + + + public async Task GetByValueNameAsync(string? value) + { + var query = EntitySet + .Include(v => v.FieldValues); + + if (string.IsNullOrWhiteSpace(value)) + return await query.FirstOrDefaultAsync(uf => uf.Value == null); + + return await query.FirstOrDefaultAsync(uf => uf.Value!.ToLower() == value.ToLower()); + } } } diff --git a/PARR.DAL/Services/Implementations/Unit/UnitService.cs b/PARR.DAL/Services/Implementations/Unit/UnitService.cs index 2b791a38..a7814aae 100644 --- a/PARR.DAL/Services/Implementations/Unit/UnitService.cs +++ b/PARR.DAL/Services/Implementations/Unit/UnitService.cs @@ -20,18 +20,20 @@ namespace PARR.DAL.Services.Implementations.Unit } - public async Task GetUnitWithFieldsAsync(string name) + public async Task GetUnitByName(string name) { - return await GetUnitWithIncludeFields() + return await GetUnitWithFieldsAndValues() .FirstOrDefaultAsync(u => u.Name.ToLower() == name.ToLower()); } - private IQueryable GetUnitWithIncludeFields() + private IQueryable GetUnitWithFieldsAndValues() { return EntitySet - .Include(t => t.UnitFields) - .ThenInclude(f => f.UnitField); + .Include(u => u.UnitFields) + .ThenInclude(f => f.UnitField) + .Include(u => u.UnitValues) + .ThenInclude(v => v.Value); } } } diff --git a/PARR.DAL/Services/Interfaces/Unit/IUnitFieldValueService.cs b/PARR.DAL/Services/Interfaces/Unit/IUnitFieldValueService.cs index dccc2e30..0dead022 100644 --- a/PARR.DAL/Services/Interfaces/Unit/IUnitFieldValueService.cs +++ b/PARR.DAL/Services/Interfaces/Unit/IUnitFieldValueService.cs @@ -3,7 +3,8 @@ using PARR.DAL.Services.Interfaces.Base; namespace PARR.DAL.Services.Interfaces.Unit { - internal interface IUnitFieldValueService: IBaseService + public interface IUnitFieldValueService: IBaseService { + Task GetByValueNameAsync(string? value); } } diff --git a/PARR.DAL/Services/Interfaces/Unit/IUnitService.cs b/PARR.DAL/Services/Interfaces/Unit/IUnitService.cs index db142657..3a5bebc1 100644 --- a/PARR.DAL/Services/Interfaces/Unit/IUnitService.cs +++ b/PARR.DAL/Services/Interfaces/Unit/IUnitService.cs @@ -4,6 +4,6 @@ namespace PARR.DAL.Services.Interfaces.Unit { public interface IUnitService : IBaseService { - Task GetUnitWithFieldsAsync(string name); + Task GetUnitByName(string name); } }