231 lines
13 KiB
C#
231 lines
13 KiB
C#
using FluentValidation;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Newtonsoft.Json.Linq;
|
||
using PARR.API.Contracts.V1.Requests;
|
||
using PARR.DAL.Services.Interfaces;
|
||
|
||
namespace PARR.API.Validators
|
||
{
|
||
public class ApplicationInWorkValidator : AbstractValidator<ApplicationInWorkRequest>
|
||
{
|
||
private readonly IApplicationsInWorkService applicationsInWorkService;
|
||
private readonly IEsppSchTypeConfigService esppSchTypeConfigService;
|
||
private readonly IWorkGroupService workGroupService;
|
||
private readonly IEsppSchTypeValueService esppSchTypeValueService;
|
||
|
||
public ApplicationInWorkValidator(
|
||
IApplicationsInWorkService applicationsInWorkService,
|
||
IEsppSchTypeConfigService esppSchTypeConfigService,
|
||
IWorkGroupService workGroupService,
|
||
IEsppSchTypeValueService esppSchTypeValueService
|
||
)
|
||
{
|
||
this.applicationsInWorkService = applicationsInWorkService;
|
||
this.esppSchTypeConfigService = esppSchTypeConfigService;
|
||
this.workGroupService = workGroupService;
|
||
this.esppSchTypeValueService = esppSchTypeValueService;
|
||
|
||
RuleFor(t => t.TemplateDuration)
|
||
.NotNull().NotEmpty()//.WithMessage("Длительность данного задания на выполнение работ не может быть пустым")
|
||
.Matches("^\\d{1,2}\\s\\d{1,2}[:]\\d{1,2}[:]\\d{1,2}$")
|
||
//.WithMessage("Длительность данного задания на выполнение работ должна соответствовать шаблону dd hh:mm:ss(7 00:00:00)");
|
||
.WithMessage("Значение не соответствует шаблону dd hh:mm:ss(7 00:00:00)");
|
||
|
||
RuleFor(t => t.ShortDescription)
|
||
.NotNull().NotEmpty();//.WithMessage("Краткое описание данного задания на выполнение работ не может быть пустым");
|
||
|
||
RuleFor(t => t.FullDescription)
|
||
.NotNull().NotEmpty();//.WithMessage("Подробное описание данного задания на выполнение работ не может быть пустым");
|
||
|
||
RuleFor(t => t.Solution)
|
||
.NotNull().NotEmpty();//.WithMessage("Решение данного задания на выполнение работ не может быть пустым");
|
||
|
||
RuleFor(t => t.WorkId)
|
||
.MustAsync(async (entity, value, c) => await IsWorkExist(entity))
|
||
.WithMessage("Указан несуществующий Id работы");
|
||
//.WithMessage("У данного задания на выполнение работ указан несуществующий Id работы");
|
||
|
||
RuleFor(t => t.ApplicationId)
|
||
.MustAsync(async (entity, value, c) => await IsApplicationExist(entity))
|
||
.WithMessage("Указан несуществующий Id программного обеспечения");
|
||
//.MustAsync(async (entity, value, c) => await AppInWorkIsUnique(entity))
|
||
// .WithMessage("Задание на выполнение работ с такими ПО и работой уже существует");
|
||
//.WithMessage("У данного задания на выполнение работ указан несуществующий Id программного обеспечения");
|
||
|
||
|
||
|
||
#region old schedule
|
||
//Проверяем настройки планировщика
|
||
//RuleFor(t => t.Schedule).NotNull().NotEmpty()
|
||
// .WithMessage("Настройки планировщика задания на выполнение работ не могут быть пустыми");
|
||
|
||
//RuleFor(t => t.Schedule.EsppSchValues)
|
||
// .NotNull().NotEmpty()
|
||
// .When(t => t.Schedule != null)
|
||
// .WithMessage("Настройки планировщика задания на выполнение работ не могут быть пустыми")
|
||
// .Must((entity, value, c) => IsEsppSchValuesExist(entity))
|
||
// .WithMessage("Не удалось найти подходящую конфигруцию планировщика задания на выполнение работ");
|
||
#endregion
|
||
|
||
//RuleFor(t => t.Schedule)
|
||
// .NotNull().NotEmpty()
|
||
// .When(t => t.Schedule.Count() > 0)
|
||
// .WithMessage("Настройки планировщика не могут быть пустыми")
|
||
// .Must((entity, value, c) => IsEsppSchValuesExist(entity.Schedule))
|
||
// .WithMessage("Не удалось найти подходящую конфигруцию планировщика задания");
|
||
|
||
#region comment
|
||
|
||
//RuleFor(t => t.Schedule.Values)
|
||
// .NotNull().NotEmpty().WithMessage($"Настройки значений планировщика задания на выполнение работ не могут быть пустыми")
|
||
// .Must((entity, value, c) => IsScheduleTypeValueIdExist(entity))
|
||
// .When(t => t.Schedule != null).WithMessage("Не удалось найти подходящую конфигруцию планировщика задания на выполнение работ");
|
||
|
||
//RuleFor(t => t.Schedule.TypeScheduleId)
|
||
// .NotNull().NotEmpty().WithMessage($"Тип планировщика задания на выполнение работ не может быть пустым")
|
||
// .Must((entity, value, c) => IsTypeScheduleIdExist(entity))
|
||
// .When(t => t.Schedule != null).WithMessage($"Не удалось найти указанный тип планировщика задания на выполнение работ");
|
||
|
||
//RuleFor(t => t.Schedule.Values)
|
||
// .NotNull().NotEmpty().WithMessage($"Настройки значений планировщика задания на выполнение работ не могут быть пустыми")
|
||
// .Must((entity, value, c) => IsScheduleTypeValueIdExist(entity))
|
||
// .When(t => t.Schedule != null).WithMessage("Не удалось найти подходящую конфигруцию планировщика задания на выполнение работ");
|
||
|
||
#endregion
|
||
|
||
|
||
RuleFor(t => t.WorkGroups)
|
||
.MustAsync(async (entity, value, c) => await IsWorkGroupsExistAsync(entity))
|
||
.WithMessage("Указаные несуществующие Id рабочих групп");
|
||
|
||
|
||
//Автораспределение может быть включено, только если у EsppSchTypeValues не пустое поле DistributionPeriodId
|
||
RuleFor(t => t.IsAutoDistributionEnabled)
|
||
.MustAsync(async (entity, value, c) => await IsAllowAutoDistributionEnabledAsync(entity, value))
|
||
.WithMessage("Нельзя включить автораспределение для этого типа расписания");
|
||
}
|
||
|
||
|
||
private async Task<bool> IsAllowAutoDistributionEnabledAsync(ApplicationInWorkRequest entity, bool value)//TODO JobGroupRequest
|
||
{
|
||
//Автораспределение может быть включено, только если у EsppSchTypeValues не пустое поле DistributionPeriodId
|
||
|
||
if (value == false)
|
||
return true;
|
||
|
||
//Распределение включено, смотрим, разрешено ли оно в расписании
|
||
//по идее, это расписание только с одним значением в EsppSchValues, но мы проверим у всех, но такого быть не может по хорошему
|
||
//foreach (var item in entity.Schedule)
|
||
//{
|
||
// var schVal = await esppSchTypeValueService.GetAsync(item.TypeValueId);
|
||
// if (schVal != null)
|
||
// if (schVal.DistributionPeriodId == null)
|
||
// return false;
|
||
//}
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
private async Task<bool> IsWorkGroupsExistAsync(ApplicationInWorkRequest entity)
|
||
{
|
||
var result = await workGroupService.Get().Where(t => entity.WorkGroups.Contains(t.Id)).ToListAsync();
|
||
|
||
return entity.WorkGroups.Count() == result.Count();
|
||
}
|
||
|
||
//private bool IsEsppSchValuesExist(ApplicationInWorkRequest request)
|
||
private bool IsEsppSchValuesExist(List<EsppSchValueRequest> listSchedule)
|
||
{
|
||
var configs = esppSchTypeConfigService.GetWithSchIncludes().ToList();
|
||
|
||
//Проверяем полученные Id конфигураций и Id конфигураций в базе
|
||
var typeConfigIdList = listSchedule.Select(t => t.TypeConfigId);
|
||
var foundTypeConfigIdList = configs.Where(t => typeConfigIdList.Contains(t.Id)).Distinct();
|
||
|
||
if (foundTypeConfigIdList.Count() == 0 //Не найдено совпадений с базой
|
||
|| foundTypeConfigIdList.Select(t => t.TypeScheduleId).Distinct().Count() > 1) //или имеют разный тип планировщика
|
||
return false;
|
||
|
||
var typeScheduleId = foundTypeConfigIdList.Select(t => t.TypeScheduleId).FirstOrDefault();
|
||
|
||
if (foundTypeConfigIdList.Count() != configs.Where(t => t.TypeScheduleId == typeScheduleId).Count()) //не все typeConfig найдены в базе
|
||
return false;
|
||
|
||
//Теперь проверяем значения
|
||
foreach (var item in listSchedule)
|
||
{
|
||
var curTypeConfig = configs.Where(t => t.Id == item.TypeConfigId).Single();
|
||
|
||
var isCurValueExist = curTypeConfig!.EsppSchType!.EsppSchTypeValues.Where(t => t.Id == item.TypeValueId).Any();
|
||
|
||
if (!isCurValueExist)
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
//private async Task<bool> AppInWorkIsUnique(ApplicationInWorkRequest request)
|
||
//{
|
||
// //уникальная запись по полям ApplicationId, WorkId
|
||
|
||
// var existSameAiW = await applicationsInWorkService.GetAsync(request.ApplicationId, request.WorkId);
|
||
|
||
// //TODO: тут спорно, нужна ли эта проверка? Мы же можем создать несколько РР на одно и тоже ПО но с разным расписанием?
|
||
// //к тому же, в методе update, такой проверки нет!
|
||
// //if (existSameAiW != null)
|
||
// // return BadRequest(new Response(false, new List<ErrorModel> {
|
||
// // new ErrorModel { Message = $"Уже существует задание на выполнение работ для программного обеспечения id({request.ApplicationId}) и работой id({request.WorkId})." } }
|
||
// // ));
|
||
|
||
// return existSameAiW == null;
|
||
//}
|
||
|
||
private async Task<bool> IsWorkExist(ApplicationInWorkRequest request)
|
||
{
|
||
//return await workService.GetAsync(request.WorkId) != null;
|
||
return true;
|
||
}
|
||
|
||
|
||
private async Task<bool> IsApplicationExist(ApplicationInWorkRequest request)
|
||
{
|
||
//return await workService.GetAsync(request.WorkId) != null;
|
||
return true;
|
||
}
|
||
|
||
|
||
//private bool IsTypeScheduleIdExist(ApplicationInWorkRequest request)
|
||
//{
|
||
// var configs = esppSchTypeConfigService.GetWithSchIncludes().ToList();
|
||
//var result = configs.Where(t => t.TypeId == request.Schedule.TypeScheduleId).FirstOrDefault() != null;
|
||
//return result;
|
||
// return false;
|
||
//}
|
||
|
||
|
||
//private bool IsScheduleTypeValueIdExist(ApplicationInWorkRequest request)
|
||
//{
|
||
// var configs = esppSchTypeConfigService.GetWithSchIncludes().ToList();
|
||
|
||
// var mustValues = configs.Where(t => t.TypeScheduleId == request.Schedule.TypeScheduleId).ToList();
|
||
// var values = request.Schedule.Values;
|
||
|
||
// foreach (var mustValue in mustValues)
|
||
// {
|
||
// var mlValues = mustValue?.EsppSchType?.EsppSchTypeValues.Select(t => t.Id);
|
||
|
||
// if (mlValues == null)
|
||
// return false;
|
||
|
||
// if (!mlValues.Intersect(values).Any())
|
||
// return false;
|
||
// }
|
||
|
||
// return true;
|
||
//}
|
||
|
||
}
|
||
}
|