diff --git a/PARR.API/Contracts/V1/Responses/JobGroupResponse.cs b/PARR.API/Contracts/V1/Responses/JobGroupResponse.cs
index 4e26b101..b57f19ec 100644
--- a/PARR.API/Contracts/V1/Responses/JobGroupResponse.cs
+++ b/PARR.API/Contracts/V1/Responses/JobGroupResponse.cs
@@ -50,6 +50,11 @@
// public int? AgentTimeOutSec { get; set; }
// public string? AgentScript { get; set; }
+
+ ///
+ /// Юнит фильтры
+ ///
+ public List? UnitFilters { get; set; }
}
public class JobGroupResponse : JobGroupWithDistributionConfigResponse
@@ -71,10 +76,10 @@
///
public ScheduleExcludeTypeCalendarResponse? ScheduleExcludeTypeCalendar { get; set; }
- ///
- /// Юнит фильтры
- ///
- public List? UnitFilters { get; set; }
+ /////
+ ///// Юнит фильтры
+ /////
+ //public List? UnitFilters { get; set; }
}
public class JobGroupAutoControlResponse
diff --git a/PARR.API/Contracts/V1/Responses/JobResponse.cs b/PARR.API/Contracts/V1/Responses/JobResponse.cs
index 33590680..39a73dd4 100644
--- a/PARR.API/Contracts/V1/Responses/JobResponse.cs
+++ b/PARR.API/Contracts/V1/Responses/JobResponse.cs
@@ -30,6 +30,9 @@
public int? TemplatesCount { get; set; }
+ ///
+ /// Юнит фильтры Работы
+ ///
public List? UnitFilters { get; set; }
public JobAutoControlResponse? AutoControl { get; set; }
diff --git a/PARR.API/Controllers/V1/JobController.cs b/PARR.API/Controllers/V1/JobController.cs
index f38b0aa4..57413d9e 100644
--- a/PARR.API/Controllers/V1/JobController.cs
+++ b/PARR.API/Controllers/V1/JobController.cs
@@ -82,6 +82,7 @@ namespace PARR.API.Controllers.V1
var paginationFilter = _mapper.Map(paginationQuery);
IQueryable query = _jobRepository.Get()
+ .AsNoTracking()
.Include(t => t.AutoControl);
@@ -152,9 +153,22 @@ namespace PARR.API.Controllers.V1
{
var job = await _jobRepository.Get()
.Include(t => t.Tnk)
- .Include(t => t.Group).ThenInclude(t => t.GroupType)
- .Include(t => t.Group).ThenInclude(t => t.AutoControl)
- .Include(t => t.Group).ThenInclude(t => t.GroupingUnitField)
+ .Include(t => t.Group)
+ .ThenInclude(t => t.GroupType)
+ .Include(t => t.Group)
+ .ThenInclude(t => t.AutoControl)
+ .Include(t => t.Group)
+ .ThenInclude(t => t.GroupingUnitField)
+ //--- Фильтры в группе
+ .Include(t => t.Group)
+ .ThenInclude(t => t.UnitFilters)
+ .ThenInclude(t => t.FieldFilters)
+ .ThenInclude(t => t.UnitField)
+ .Include(t => t.Group)
+ .ThenInclude(t => t.UnitFilters)
+ .ThenInclude(t => t.RelationshipFilters)
+ .ThenInclude(t=>t.UnitField)
+ //---
.Include(t => t.UnitFilters)
.ThenInclude(t => t.FieldFilters)
.ThenInclude(t => t.UnitField)
@@ -162,6 +176,7 @@ namespace PARR.API.Controllers.V1
.ThenInclude(t => t.RelationshipFilters)
.ThenInclude(t => t.UnitField)
.Include(t => t.AutoControl)
+ .AsNoTracking()
.FirstOrDefaultAsync(t => t.Id == id);
if (job == null)
@@ -169,12 +184,9 @@ namespace PARR.API.Controllers.V1
var response = _mapper.Map(job);
- response.TemplatesCount = await GetCountTemplatesAsync(id); //await templateService.Get().CountAsync(t => t.JobId == id);
+ response.TemplatesCount = await GetCountTemplatesAsync(id);
response.MatchingStatus = await GetMatchingStatusAsync(id);
- //var statistics = await GetStatisticsAsync(response.Id);
- //BindStatistics(response, statistics);
-
return Ok(new Response(response, true));
}
@@ -244,6 +256,16 @@ namespace PARR.API.Controllers.V1
.Include(t => t.UnitFilters)
.ThenInclude(t => t.RelationshipFilters)
.Include(t => t.AutoControl)
+ //--- Фильтры в группе
+ .Include(t => t.Group)
+ .ThenInclude(t => t.UnitFilters)
+ .ThenInclude(t => t.FieldFilters)
+ .ThenInclude(t => t.UnitField)
+ .Include(t => t.Group)
+ .ThenInclude(t => t.UnitFilters)
+ .ThenInclude(t => t.RelationshipFilters)
+ .ThenInclude(t => t.UnitField)
+ //---
.FirstOrDefaultAsync(t => t.Id == job.Id);
var locationUri = _uriService.GetUri(ApiRoutes.Job.Get, ApiRoutes.Job.getParam, createdJob!.Id);
@@ -365,6 +387,16 @@ namespace PARR.API.Controllers.V1
.Include(t => t.UnitFilters)
.ThenInclude(t => t.RelationshipFilters)
.Include(t => t.AutoControl)
+ //--- Фильтры в группе
+ .Include(t => t.Group)
+ .ThenInclude(t => t.UnitFilters)
+ .ThenInclude(t => t.FieldFilters)
+ .ThenInclude(t => t.UnitField)
+ .Include(t => t.Group)
+ .ThenInclude(t => t.UnitFilters)
+ .ThenInclude(t => t.RelationshipFilters)
+ .ThenInclude(t => t.UnitField)
+ //---
.FirstAsync(t => t.Id == orig.Id);
var response = _mapper.Map(updatedJob);
diff --git a/PARR.API/MappingProfiles/DomainToResponseProfile.cs b/PARR.API/MappingProfiles/DomainToResponseProfile.cs
index 4d7c5b2f..fba83343 100644
--- a/PARR.API/MappingProfiles/DomainToResponseProfile.cs
+++ b/PARR.API/MappingProfiles/DomainToResponseProfile.cs
@@ -388,7 +388,8 @@ namespace PARR.API.MappingProfiles
.ForMember(d => d.GroupType, o => o.MapFrom(s => s.GroupType))
.ForMember(d => d.GroupingUnitField, o => o.MapFrom(s => s.GroupingUnitField))
.ForMember(d => d.IsWorkGroupTimezone, o => o.MapFrom(s => s.IsResponseAreaTimezone))
- .ForMember(d => d.AutoControl, o => o.MapFrom(s => s.AutoControl));
+ .ForMember(d => d.AutoControl, o => o.MapFrom(s => s.AutoControl))
+ .ForMember(d => d.UnitFilters, o => o.MapFrom(s => s.UnitFilters));
CreateMap()
.ForMember(d => d.Name, o => o.MapFrom(s => s.GroupName))
@@ -399,8 +400,7 @@ namespace PARR.API.MappingProfiles
CreateMap()
.ForMember(d => d.ScheduleExcludeType, o => o.MapFrom(s => s.ScheduleExcludeType))
- .ForMember(d => d.ScheduleExcludeTypeCalendar, o => o.MapFrom(s => s.ScheduleExcludeTypeCalendar))
- .ForMember(d => d.UnitFilters, o => o.MapFrom(s => s.UnitFilters));
+ .ForMember(d => d.ScheduleExcludeTypeCalendar, o => o.MapFrom(s => s.ScheduleExcludeTypeCalendar));
//.ForMember(d => d.DistributionConfig, o => o.MapFrom(s => s.DistributionConfig));
//------- unit filters
diff --git a/PARR.API/Validators/JobRequestValidator.cs b/PARR.API/Validators/JobRequestValidator.cs
index c54f5c84..3427d2ae 100644
--- a/PARR.API/Validators/JobRequestValidator.cs
+++ b/PARR.API/Validators/JobRequestValidator.cs
@@ -12,7 +12,6 @@ namespace PARR.API.Validators
private readonly ITnkRepository _tnkRepository;
private readonly IJobGroupRepository _jobGroupRepository;
private readonly IUnitFieldRepository _unitFieldRepository;
- //private JobGroup? jobGroup;
public JobRequestValidator(
ITnkRepository tnkRepository,
@@ -39,15 +38,28 @@ namespace PARR.API.Validators
.MustAsync(async (entity, value, c) => await IsGroupExist(entity))
.WithMessage("Указан несуществующий Id группы работ({PropertyValue})");
- //RuleForEach(t => t.UnitFilters)
- // .NotNull().NotEmpty();
+ #region UnitFiters
+
+ When(t => t.UnitFilters != null && t.UnitFilters.Any(), () =>
+ {
+ RuleFor(t => t.UnitFilters)
+ .MustAsync(async (entity, value, c) =>
+ {
+ // Проверяем флаг в БД: разрешены ли фильтры для этой группы
+ return await jobGroupRepository.Get()
+ .AnyAsync(t => t.Id == entity.GroupId && t.GroupType!.IsAllowJobUnitFilter == true, c);
+ })
+ .WithMessage("Дополнительные фильтры запрещены")
+ // Stop делает так, что если флаг равен false, FluentValidation остановится
+ // и НЕ пойдет выполнять Include базового валидатора (сэкономим запрос к БД)
+ .DependentRules(() =>
+ {
+ // Этот валидатор сработает ПОСЛЕ успешной проверки флага IsAllowJobUnitFilter
+ Include(unitFilterValidator);
+ });
+ });
- // Валидация фильтров (они могут быть пустые, мы так договорились)
- Include(unitFilterValidator);
-
- //RuleForEach(t => t.UnitFilters)
- // .MustAsync(async (entity, value, c) => await IsUnitFiltersCorrect(entity))
- // .WithMessage("Неверно заданы параметры фильтров.");
+ #endregion
RuleFor(t => t.Relationships)
.MustAsync(async (entity, value, c) =>
@@ -99,64 +111,6 @@ namespace PARR.API.Validators
.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)
{