2025-07-01 17:20:48 +10:00
|
|
|
|
using FluentValidation;
|
2025-12-19 10:48:41 +10:00
|
|
|
|
using Microsoft.EntityFrameworkCore;
|
2025-07-01 17:20:48 +10:00
|
|
|
|
using PARR.API.Contracts.V1.Requests;
|
2026-04-30 10:35:31 +10:00
|
|
|
|
using PARR.Core.Repositories.Interfaces;
|
|
|
|
|
|
using PARR.Core.Repositories.Interfaces.Job;
|
|
|
|
|
|
using PARR.Core.Repositories.Interfaces.Schedule;
|
|
|
|
|
|
using PARR.Core.Repositories.Interfaces.Unit;
|
2026-04-13 16:58:30 +10:00
|
|
|
|
using PARR.Domain.Enums;
|
2025-07-01 17:20:48 +10:00
|
|
|
|
|
|
|
|
|
|
namespace PARR.API.Validators
|
|
|
|
|
|
{
|
|
|
|
|
|
public class JobGroupValidator : AbstractValidator<JobGroupRequest>
|
|
|
|
|
|
{
|
2025-12-19 10:48:41 +10:00
|
|
|
|
public JobGroupValidator(
|
2026-04-30 10:35:31 +10:00
|
|
|
|
IJobGroupTypeRepository jobGroupTypeService,
|
|
|
|
|
|
IUnitFieldRepository unitFieldService,
|
|
|
|
|
|
IScheduleExcludeTypeRepository scheduleExcludeTypeService,
|
|
|
|
|
|
IScheduleExcludeTypeCalendarRepository scheduleExcludeTypeCalendarService,
|
|
|
|
|
|
IDistributionPeriodRepository distributionPeriodService
|
2025-12-19 10:48:41 +10:00
|
|
|
|
)
|
2025-07-01 17:20:48 +10:00
|
|
|
|
{
|
|
|
|
|
|
RuleFor(t => t.Name)
|
|
|
|
|
|
.NotNull().NotEmpty();
|
|
|
|
|
|
|
|
|
|
|
|
RuleFor(t => t.ShortDescription)
|
|
|
|
|
|
.NotNull().NotEmpty();
|
|
|
|
|
|
|
|
|
|
|
|
RuleFor(t => t.FullDescription)
|
|
|
|
|
|
.NotNull().NotEmpty();
|
|
|
|
|
|
|
|
|
|
|
|
RuleFor(t => t.Solution)
|
|
|
|
|
|
.NotNull().NotEmpty();
|
|
|
|
|
|
|
|
|
|
|
|
RuleFor(t => t.TemplateDuration)
|
|
|
|
|
|
.NotNull().NotEmpty();
|
2025-11-17 12:06:33 +10:00
|
|
|
|
|
|
|
|
|
|
RuleFor(t => t.GroupTypeId)
|
|
|
|
|
|
.MustAsync(async (entity, value, c) => await jobGroupTypeService.GetAsync(value) != null)
|
|
|
|
|
|
.WithMessage("Указан несуществующий Id типа");
|
2025-12-19 10:48:41 +10:00
|
|
|
|
|
|
|
|
|
|
//Проверяем существует ли такой GroupingUnitFieldId в unitField
|
|
|
|
|
|
RuleFor(t => t.GroupingUnitFieldId)
|
|
|
|
|
|
.MustAsync(async (entity, value, c) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!value.HasValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return await unitFieldService.GetAsync(value.Value) != null;
|
|
|
|
|
|
})
|
|
|
|
|
|
.WithMessage("Указано несуществующий Id поля");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RuleFor(t => t.GroupingUnitFieldId)
|
|
|
|
|
|
.MustAsync(async (entity, value, c) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
var groupingJobType = await jobGroupTypeService.Get().FirstAsync(t => t.Code == JobGroupTypesEnum.Group);
|
|
|
|
|
|
|
|
|
|
|
|
// Если это сгруппированный тип, то у него обязательно должно быть заполнено поле GroupingUnitFieldId
|
|
|
|
|
|
if (entity.GroupTypeId == groupingJobType.Id)
|
|
|
|
|
|
return value.HasValue;
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
})
|
|
|
|
|
|
.WithMessage("Не указано поле для группировки");
|
2025-12-26 11:21:45 +10:00
|
|
|
|
|
|
|
|
|
|
RuleFor(t => t.ScheduleExcludeTypeId)
|
|
|
|
|
|
.NotNull()
|
|
|
|
|
|
.NotEmpty()
|
|
|
|
|
|
.MustAsync(async (entity, value, c) => await scheduleExcludeTypeService.GetAsync(value) != null)
|
|
|
|
|
|
.WithMessage("Некорректное значение");
|
|
|
|
|
|
|
|
|
|
|
|
RuleFor(t => t.ScheduleExcludeTypeCalendarId)
|
|
|
|
|
|
.MustAsync(async (entity, value, c) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
// Если выбрано "Нет исключений", то это поле должно быть пустое, иначе, должно быть валидное значение
|
|
|
|
|
|
var type = await scheduleExcludeTypeService.GetAsync(entity.ScheduleExcludeTypeId);
|
|
|
|
|
|
if (type == null)
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
if (type.Code == ScheduleExcludeTypeEnum.None.ToString())
|
|
|
|
|
|
{
|
|
|
|
|
|
// ScheduleExcludeTypeCalendarId должно быть null
|
|
|
|
|
|
return value == null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Тип любой кроме "Нет исключений", значение обязательно
|
|
|
|
|
|
if (!value.HasValue)
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
return await scheduleExcludeTypeCalendarService.GetAsync(value.Value) != null;
|
|
|
|
|
|
})
|
|
|
|
|
|
.WithMessage("Некорректное значение");
|
|
|
|
|
|
|
2026-01-23 16:18:56 +10:00
|
|
|
|
RuleFor(t => t.DistributionConfig)
|
|
|
|
|
|
.Must((entity, value, c) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
// если включено автораспределение, должны быть настройки
|
|
|
|
|
|
if (entity.IsAutoDistributionEnabled && value != null)
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
// если выкл автораспределение, то валидно
|
|
|
|
|
|
if (!entity.IsAutoDistributionEnabled)
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}).WithMessage("Отсутствуют настройки автораспределения");
|
|
|
|
|
|
|
|
|
|
|
|
RuleFor(t => t.DistributionConfig)
|
|
|
|
|
|
.MustAsync(async (entity, value, c) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
// если есть настройка периода, проверить что она валидна
|
|
|
|
|
|
var periodId = value?.DistributionPeriodId;
|
|
|
|
|
|
|
|
|
|
|
|
if (periodId.HasValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
var exist = await distributionPeriodService.GetAsync(periodId.Value);
|
|
|
|
|
|
|
|
|
|
|
|
return exist != null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}).WithMessage("Некорректное значение периода распределения");
|
2025-12-26 11:21:45 +10:00
|
|
|
|
|
2026-02-09 15:48:30 +10:00
|
|
|
|
RuleFor(t => t.UserTimeZoneOffsetMinutes)
|
|
|
|
|
|
.Must((entity, value, c) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
// если IsResponseAreaTimezone == true, то поле UserTimeZoneOffsetMinutes обязательно.
|
|
|
|
|
|
// если IsResponseAreaTimezone == false, то UserTimeZoneOffsetMinutes должно быть null
|
|
|
|
|
|
return (entity.IsWorkGroupTimezone && value != null) || (!entity.IsWorkGroupTimezone && value == null);
|
|
|
|
|
|
}).WithMessage("Некорректное значение."); ;
|
|
|
|
|
|
|
2025-07-01 17:20:48 +10:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|