diff --git a/PARR.TemplateGeneratorWorker/Services/ValidatorService.cs b/PARR.TemplateGeneratorWorker/Services/ValidatorService.cs index 6c670e80..c46bcbd8 100644 --- a/PARR.TemplateGeneratorWorker/Services/ValidatorService.cs +++ b/PARR.TemplateGeneratorWorker/Services/ValidatorService.cs @@ -1,9 +1,9 @@ -// ValidatorService.cs -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using PARR.Core.Repositories.Interfaces; using PARR.Core.Repositories.Interfaces.Job; using PARR.Core.Repositories.Interfaces.Unit; + namespace PARR.TemplateGeneratorWorker.Services { internal class ValidatorService : IValidatorService @@ -12,46 +12,48 @@ namespace PARR.TemplateGeneratorWorker.Services private readonly IJobRepository jobService; private readonly IUnitRepository unitService; private readonly ITemplateRepository templateService; + private readonly IUnitInValueRepository unitInValueRepo; public ValidatorService( ILogger logger, IJobRepository jobService, IUnitRepository unitService, - ITemplateRepository templateService + ITemplateRepository templateService, + IUnitInValueRepository unitInValueRepo ) { this.logger = logger; this.jobService = jobService; this.unitService = unitService; this.templateService = templateService; + this.unitInValueRepo = unitInValueRepo; } - - public async Task IsValidAsync(Guid jobId, Guid unitId, int? index, List? unitsInTemplate = null) + public async Task IsValidAsync(Guid jobId, Guid unitId, int? index, List<(Guid UnitId, Guid UnitFieldValueId)>? unitsInTemplate = null) { - // Проверяем JobId + // 1. Проверяем JobId var job = await jobService - .Get().AsNoTracking() - .FirstOrDefaultAsync(t => t.Id == jobId); + .Get().AsNoTracking() + .FirstOrDefaultAsync(t => t.Id == jobId); if (job == null) { - logger.LogError($"Не найдена регалментная работа {nameof(jobId)}: {jobId}"); + logger.LogError("Не найдена регламентная работа JobId: {JobId}", jobId); return false; } - // Проверяем UnitId (UnitId - это ID регионального юнита) + // 2. Проверяем UnitId (основной юнит шаблона) var unit = await unitService .Get().AsNoTracking() .FirstOrDefaultAsync(t => t.Id == unitId); if (unit == null) { - logger.LogError($"Не найден элемент конфигурации {nameof(unitId)}: {unitId}"); + logger.LogError("Не найден элемент конфигурации UnitId: {UnitId}", unitId); return false; } - // Проверяем уникальность (JobId, UnitId, Index) + // 3. Проверяем уникальность (JobId, UnitId, Index) var existingTemplate = await templateService .Get().AsNoTracking() .FirstOrDefaultAsync(t => t.JobId == jobId && t.UnitId == unitId && t.Index == index); @@ -62,19 +64,30 @@ namespace PARR.TemplateGeneratorWorker.Services return false; } - // Проверяем, что все UnitId в UnitsInTemplate существуют (если список не null и не пуст) if (unitsInTemplate != null && unitsInTemplate.Any()) { - var unitIdsToCheck = unitsInTemplate.ToHashSet(); - var existingUnitIdsCount = await unitService.Get() - .AsNoTracking() - .Where(u => unitIdsToCheck.Contains(u.Id)) - .Select(u => u.Id) - .CountAsync(); + var pairsToCheck = unitsInTemplate.Distinct().ToList(); + var unitIdsToCheck = pairsToCheck.Select(p => p.UnitId).Distinct().ToList(); + var valueIdsToCheck = pairsToCheck.Select(p => p.UnitFieldValueId).Distinct().ToList(); - if (existingUnitIdsCount != unitIdsToCheck.Count) + // Загружаем только те связи, которые относятся к проверяемым ID + var existingLinks = await unitInValueRepo.Get() + .AsNoTracking() + .Where(uiv => unitIdsToCheck.Contains(uiv.UnitId) && valueIdsToCheck.Contains(uiv.ValueId)) + .Select(uiv => new { uiv.UnitId, uiv.ValueId }) + .ToListAsync(); + + // Формируем HashSet существующих пар для быстрой проверки в памяти + var existingPairsSet = existingLinks + .Select(x => (x.UnitId, UnitFieldValueId: x.ValueId)) + .ToHashSet(); + + // Проверяем, что каждая запрошенная пара реально существует в БД + var allPairsValid = pairsToCheck.All(p => existingPairsSet.Contains((p.UnitId, p.UnitFieldValueId))); + + if (!allPairsValid) { - logger.LogError("Не все UnitId из UnitsInTemplate существуют в базе данных. Ожидается: {ExpectedCount}, Найдено: {FoundCount}", unitIdsToCheck.Count, existingUnitIdsCount); + logger.LogError("Не все пары (UnitId, UnitFieldValueId) из UnitsInTemplate являются валидными связями в UnitInValue."); return false; } } diff --git a/PARR.TemplateUpdater/Services/TemplateUpdaterService.cs b/PARR.TemplateUpdater/Services/TemplateUpdaterService.cs index 7f48ba52..12c0b282 100644 --- a/PARR.TemplateUpdater/Services/TemplateUpdaterService.cs +++ b/PARR.TemplateUpdater/Services/TemplateUpdaterService.cs @@ -19,6 +19,7 @@ namespace PARR.TemplateUpdater.Services private readonly IUnitRepository unitService; private readonly IRobotConfigurationRepository robotConfigurationService; private readonly INextRunService nextRunService; + private readonly IUnitInValueRepository unitInValueService; public TemplateUpdaterService( ILogger logger, @@ -26,7 +27,8 @@ namespace PARR.TemplateUpdater.Services IJobRepository jobService, IUnitRepository unitService, IRobotConfigurationRepository robotConfigurationService, - INextRunService nextRunService + INextRunService nextRunService, + IUnitInValueRepository unitInValueService ) { this.logger = logger; @@ -35,6 +37,7 @@ namespace PARR.TemplateUpdater.Services this.unitService = unitService; this.robotConfigurationService = robotConfigurationService; this.nextRunService = nextRunService; + this.unitInValueService = unitInValueService; } @@ -243,6 +246,34 @@ namespace PARR.TemplateUpdater.Services return false; } + if (query.UnitsInTemplate != null && query.UnitsInTemplate.Any()) + { + var pairsToCheck = query.UnitsInTemplate.Distinct().ToList(); + var unitIdsToCheck = pairsToCheck.Select(p => p.UnitId).Distinct().ToList(); + var valueIdsToCheck = pairsToCheck.Select(p => p.UnitFieldValueId).Distinct().ToList(); + + // Загружаем только те связи, которые относятся к проверяемым ID + var existingLinks = await unitInValueService.Get() + .AsNoTracking() + .Where(uiv => unitIdsToCheck.Contains(uiv.UnitId) && valueIdsToCheck.Contains(uiv.ValueId)) + .Select(uiv => new { uiv.UnitId, uiv.ValueId }) + .ToListAsync(); + + // Формируем HashSet существующих пар для быстрой проверки в памяти + var existingPairsSet = existingLinks + .Select(x => (x.UnitId, UnitFieldValueId: x.ValueId)) + .ToHashSet(); + + // Проверяем, что каждая запрошенная пара реально существует в БД + var allPairsValid = pairsToCheck.All(p => existingPairsSet.Contains((p.UnitId, p.UnitFieldValueId))); + + if (!allPairsValid) + { + logger.LogError("Сообщение не валидно. Не все пары (UnitId, UnitFieldValueId) из UnitsInTemplate существуют в UnitInValue."); + return false; + } + } + return true; } }