using FluentValidation; using Microsoft.EntityFrameworkCore; using PARR.API.Contracts.V1.Requests; using PARR.Core.Repositories.Interfaces; using PARR.Core.Repositories.Interfaces.JobGroupRepositories; using PARR.Core.Repositories.Interfaces.Unit; namespace PARR.API.Validators { public class JobRequestValidator : AbstractValidator { private readonly ITnkRepository _tnkRepository; private readonly IJobGroupRepository _jobGroupRepository; private readonly IUnitFieldRepository _unitFieldRepository; //private JobGroup? jobGroup; public JobRequestValidator( ITnkRepository tnkRepository, IJobGroupRepository jobGroupRepository, IUnitFieldRepository unitFieldRepository, UnitFiltersBaseRequestValidator unitFilterValidator ) { _tnkRepository = tnkRepository; _jobGroupRepository = jobGroupRepository; _unitFieldRepository = unitFieldRepository; RuleFor(t => t.Name) .NotNull().NotEmpty(); RuleFor(t => t.WorkName) .NotNull().NotEmpty(); RuleFor(t => t.TnkId) .MustAsync(async (entity, value, c) => await IsTnkExist(entity)) .WithMessage("Указан несуществующий Id ТНК({PropertyValue})"); RuleFor(t => t.GroupId) .MustAsync(async (entity, value, c) => await IsGroupExist(entity)) .WithMessage("Указан несуществующий Id группы работ({PropertyValue})"); //RuleForEach(t => t.UnitFilters) // .NotNull().NotEmpty(); // Валидация фильтров (они могут быть пустые, мы так договорились) Include(unitFilterValidator); //RuleForEach(t => t.UnitFilters) // .MustAsync(async (entity, value, c) => await IsUnitFiltersCorrect(entity)) // .WithMessage("Неверно заданы параметры фильтров."); RuleFor(t => t.Relationships) .MustAsync(async (entity, value, c) => { // Relationships должны быть обязательно заполнены если в типе работ IsRelationshipsAllowed==true var relationshipsIsRequired = await jobGroupRepository.Get() .AnyAsync(t => t.Id == entity.GroupId && t.GroupType!.IsRelationshipsAllowed, c); if (relationshipsIsRequired && value != null) return true; if (!relationshipsIsRequired && value == null) return true; return false; }) .WithMessage("Некорректные настройки кол-ва связей"); When(t => t.Relationships != null, () => { RuleFor(t => t.Relationships!.MinValueRelationships) .GreaterThanOrEqualTo(0); RuleFor(t => t.Relationships!.MaxValueRelationships) .GreaterThanOrEqualTo(t => t.Relationships!.MinValueRelationships); }); RuleFor(t => t.ResponseAreaMask) .NotNull().NotEmpty(); RuleFor(t => t.AutoControl) .MustAsync(async (entity, value, c) => { // Автоконтроль разрешен только типам работ, у которых выключен IsJobGroupAutoControl var isAllowedJobAutocontrol = await jobGroupRepository.Get() .AnyAsync(t => t.Id == entity.GroupId && t.GroupType!.IsJobGroupAutoControl == false, c); // Разрешен автоконтроль и есть значение if (isAllowedJobAutocontrol && value != null) return true; // Запрещен автоконтроль и нет значения if (!isAllowedJobAutocontrol && value == null) return true; return false; }) .WithMessage("Некорректные параметры автоконтроля"); } //private async Task IsUnitFiltersCorrect(JobRequest entity) //{ // // 1. Проверим маски, они не должны быть пустыми // foreach (var unitFilter in entity.UnitFilters) // { // if (string.IsNullOrEmpty(unitFilter.UnitFilterMask)) // return false; // } // // 2. Собираем все уникальные FieldId из всех фильтров в памяти // var requestedFieldIds = entity.UnitFilters // .SelectMany(uf => // (uf.FieldFilters ?? Enumerable.Empty()).Select(ff => ff.FieldId) // .Concat((uf.RelationshipFilters ?? Enumerable.Empty()).Select(rf => rf.FieldId))) // .Distinct() // .ToList(); // // Если фильтров с ID нет, то и проверять в БД нечего // if (!requestedFieldIds.Any()) // return true; // // 3. Выполняем ОДИН запрос к БД. // var existingFieldIds = await _unitFieldRepository.Get() // .Where(field => requestedFieldIds.Contains(field.Id)) // .Select(field => field.Id) // .Distinct() // .ToListAsync(); // // 4. Если количество найденных ID в БД меньше, чем мы запрашивали, // // значит какого-то fieldId не существует // return requestedFieldIds.Count == existingFieldIds.Count; // #region Old // //foreach (var unitFilter in entity.UnitFilters) // //{ // // if (string.IsNullOrEmpty(unitFilter.UnitFilterMask)) // // return false; // // if (unitFilter.FieldFilters != null && unitFilter.FieldFilters.Any()) // // foreach (var fieldFilter in unitFilter.FieldFilters) // // { // // var fieldId = fieldFilter.FieldId; // // if (await _unitFieldRepository.GetAsync(fieldId) == null) // // return false; // // } // // if (unitFilter.RelationshipFilters != null && unitFilter.RelationshipFilters.Any()) // // foreach (var relationshipFilter in unitFilter.RelationshipFilters!) // // { // // var fieldId = relationshipFilter.FieldId; // // if (await _unitFieldRepository.GetAsync(fieldId) == null) // // return false; // // } // //} // //return true; // #endregion //} private async Task IsGroupExist(JobRequest entity) { var jobGroup = await _jobGroupRepository.GetAsync(entity.GroupId); return jobGroup != null; } private async Task IsTnkExist(JobRequest entity) { return await _tnkRepository.GetAsync(entity.TnkId) != null; } } }