2025-09-11 16:03:51 +10:00
|
|
|
|
using FluentValidation;
|
2026-06-19 11:19:43 +10:00
|
|
|
|
using Microsoft.EntityFrameworkCore;
|
2025-09-11 16:03:51 +10:00
|
|
|
|
using PARR.API.Contracts.V1.Requests;
|
2026-04-30 10:35:31 +10:00
|
|
|
|
using PARR.Core.Repositories.Interfaces;
|
2026-07-03 11:17:48 +10:00
|
|
|
|
using PARR.Core.Repositories.Interfaces.JobGroupRepositories;
|
2026-04-30 10:35:31 +10:00
|
|
|
|
using PARR.Core.Repositories.Interfaces.Unit;
|
2025-09-11 16:03:51 +10:00
|
|
|
|
|
|
|
|
|
|
namespace PARR.API.Validators
|
|
|
|
|
|
{
|
|
|
|
|
|
public class JobRequestValidator : AbstractValidator<JobRequest>
|
|
|
|
|
|
{
|
2026-06-19 11:19:43 +10:00
|
|
|
|
private readonly ITnkRepository _tnkRepository;
|
|
|
|
|
|
private readonly IJobGroupRepository _jobGroupRepository;
|
|
|
|
|
|
private readonly IUnitFieldRepository _unitFieldRepository;
|
|
|
|
|
|
//private JobGroup? jobGroup;
|
2025-09-11 16:03:51 +10:00
|
|
|
|
|
|
|
|
|
|
public JobRequestValidator(
|
2026-06-19 11:19:43 +10:00
|
|
|
|
ITnkRepository tnkRepository,
|
|
|
|
|
|
IJobGroupRepository jobGroupRepository,
|
2026-09-24 16:03:57 +10:00
|
|
|
|
IUnitFieldRepository unitFieldRepository,
|
|
|
|
|
|
UnitFiltersBaseRequestValidator unitFilterValidator
|
2025-09-11 16:03:51 +10:00
|
|
|
|
)
|
|
|
|
|
|
{
|
2026-06-19 11:19:43 +10:00
|
|
|
|
_tnkRepository = tnkRepository;
|
|
|
|
|
|
_jobGroupRepository = jobGroupRepository;
|
|
|
|
|
|
_unitFieldRepository = unitFieldRepository;
|
2025-09-16 15:27:26 +10:00
|
|
|
|
|
2025-09-11 16:03:51 +10:00
|
|
|
|
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})");
|
|
|
|
|
|
|
2026-09-24 16:03:57 +10:00
|
|
|
|
//RuleForEach(t => t.UnitFilters)
|
|
|
|
|
|
// .NotNull().NotEmpty();
|
2025-09-11 16:03:51 +10:00
|
|
|
|
|
2026-09-24 16:03:57 +10:00
|
|
|
|
// Валидация фильтров (они могут быть пустые, мы так договорились)
|
|
|
|
|
|
Include(unitFilterValidator);
|
|
|
|
|
|
|
|
|
|
|
|
//RuleForEach(t => t.UnitFilters)
|
|
|
|
|
|
// .MustAsync(async (entity, value, c) => await IsUnitFiltersCorrect(entity))
|
|
|
|
|
|
// .WithMessage("Неверно заданы параметры фильтров.");
|
2025-09-11 16:03:51 +10:00
|
|
|
|
|
2026-06-19 11:19:43 +10:00
|
|
|
|
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);
|
|
|
|
|
|
});
|
2025-09-11 16:03:51 +10:00
|
|
|
|
|
2026-01-13 14:36:07 +10:00
|
|
|
|
|
|
|
|
|
|
RuleFor(t => t.ResponseAreaMask)
|
|
|
|
|
|
.NotNull().NotEmpty();
|
2026-06-19 11:19:43 +10:00
|
|
|
|
|
|
|
|
|
|
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("Некорректные параметры автоконтроля");
|
2025-09-11 16:03:51 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-24 16:03:57 +10:00
|
|
|
|
//private async Task<bool> IsUnitFiltersCorrect(JobRequest entity)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// // 1. Проверим маски, они не должны быть пустыми
|
|
|
|
|
|
// foreach (var unitFilter in entity.UnitFilters)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// if (string.IsNullOrEmpty(unitFilter.UnitFilterMask))
|
|
|
|
|
|
// return false;
|
|
|
|
|
|
// }
|
2025-09-11 16:03:51 +10:00
|
|
|
|
|
2026-09-24 16:03:57 +10:00
|
|
|
|
// // 2. Собираем все уникальные FieldId из всех фильтров в памяти
|
|
|
|
|
|
// var requestedFieldIds = entity.UnitFilters
|
|
|
|
|
|
// .SelectMany(uf =>
|
|
|
|
|
|
// (uf.FieldFilters ?? Enumerable.Empty<FieldFilterRequest>()).Select(ff => ff.FieldId)
|
|
|
|
|
|
// .Concat((uf.RelationshipFilters ?? Enumerable.Empty<RelationshipFilterRequest>()).Select(rf => rf.FieldId)))
|
|
|
|
|
|
// .Distinct()
|
|
|
|
|
|
// .ToList();
|
2025-09-11 16:03:51 +10:00
|
|
|
|
|
2026-09-24 16:03:57 +10:00
|
|
|
|
// // Если фильтров с ID нет, то и проверять в БД нечего
|
|
|
|
|
|
// if (!requestedFieldIds.Any())
|
|
|
|
|
|
// return true;
|
2025-09-11 16:03:51 +10:00
|
|
|
|
|
2026-09-24 16:03:57 +10:00
|
|
|
|
// // 3. Выполняем ОДИН запрос к БД.
|
|
|
|
|
|
// var existingFieldIds = await _unitFieldRepository.Get()
|
|
|
|
|
|
// .Where(field => requestedFieldIds.Contains(field.Id))
|
|
|
|
|
|
// .Select(field => field.Id)
|
|
|
|
|
|
// .Distinct()
|
|
|
|
|
|
// .ToListAsync();
|
2025-09-11 16:03:51 +10:00
|
|
|
|
|
2026-09-24 16:03:57 +10:00
|
|
|
|
// // 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
|
|
|
|
|
|
//}
|
2025-09-11 16:03:51 +10:00
|
|
|
|
|
|
|
|
|
|
private async Task<bool> IsGroupExist(JobRequest entity)
|
|
|
|
|
|
{
|
2026-06-19 11:19:43 +10:00
|
|
|
|
var jobGroup = await _jobGroupRepository.GetAsync(entity.GroupId);
|
2025-09-11 16:03:51 +10:00
|
|
|
|
|
|
|
|
|
|
return jobGroup != null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private async Task<bool> IsTnkExist(JobRequest entity)
|
|
|
|
|
|
{
|
2026-06-19 11:19:43 +10:00
|
|
|
|
return await _tnkRepository.GetAsync(entity.TnkId) != null;
|
2025-09-11 16:03:51 +10:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|