feat(api): JobAutoControlController - управление автоматическим созданием/деактивацией/активацией РР
This commit is contained in:
@@ -263,7 +263,7 @@
|
||||
public static class StatWorkGroupWorkLoad
|
||||
{
|
||||
public const string Get = BaseStat + "/work-group-workloads/{responseAreaCode}";
|
||||
public const string GetByWorkGroups= BaseStat + "/work-group-workloads/";
|
||||
public const string GetByWorkGroups = BaseStat + "/work-group-workloads/";
|
||||
}
|
||||
|
||||
public static class StatWorkWorkLoad
|
||||
@@ -361,6 +361,17 @@
|
||||
}
|
||||
|
||||
|
||||
public static class JobAutoControl
|
||||
{
|
||||
public const string Get = "/jobs/" + appInWorkId + "/auto-control";
|
||||
public const string Create = "/jobs/" + appInWorkId + "/auto-control";
|
||||
public const string Update = "/jobs/" + appInWorkId + "/auto-control";
|
||||
public const string Delete = "/jobs/" + appInWorkId + "/auto-control";
|
||||
|
||||
public const string appInWorkId = "{applicationInWorkId}";
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Активатор/деактиватор шаблонов/расписаний
|
||||
/// </summary>
|
||||
|
||||
52
PARR.API/Contracts/V1/Requests/JobAutoControlRequest.cs
Normal file
52
PARR.API/Contracts/V1/Requests/JobAutoControlRequest.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using PARR.DAL.Contracts;
|
||||
|
||||
namespace PARR.API.Contracts.V1.Requests
|
||||
{
|
||||
public class JobAutoControlRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Создавать новые РР (из настроке РР)
|
||||
/// </summary>
|
||||
public bool CreateNew { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Деактивировать не актуальные согласно ЭК (обратные статусы ЭК)
|
||||
/// </summary>
|
||||
public bool Deactivate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Активировать РР после смены ЭК (согласно настройкам статусов ЭК)
|
||||
/// </summary>
|
||||
public bool Activate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Состояние для активированных РР, шаблоны
|
||||
/// </summary>
|
||||
public bool OnTemplateIsActive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Состояние для активированных РР, расписания
|
||||
/// </summary>
|
||||
public bool OnScheduleIsActive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Состояние для деактивированных РР, шаблоны
|
||||
/// </summary>
|
||||
public bool OffTemplateIsActive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Состояние для деактивированных РР, расписания
|
||||
/// </summary>
|
||||
public bool OffScheduleIsActive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Маски ЭК
|
||||
/// </summary>
|
||||
public required List<string> EkMasks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Статусы ЭК для которых включена генерация РР и активация
|
||||
/// </summary>
|
||||
public required List<EkStatusEnum> EnabledEkStatuses { get; set; }
|
||||
}
|
||||
}
|
||||
64
PARR.API/Contracts/V1/Responses/JobAutoControlResponse.cs
Normal file
64
PARR.API/Contracts/V1/Responses/JobAutoControlResponse.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
namespace PARR.API.Contracts.V1.Responses
|
||||
{
|
||||
public class JobAutoControlResponse
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public Guid ApplicationInWorkId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Создавать новые РР (из настроке РР)
|
||||
/// </summary>
|
||||
public bool CreateNew { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Деактивировать не актуальные согласно ЭК (обратные статусы ЭК)
|
||||
/// </summary>
|
||||
public bool Deactivate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Активировать РР после смены ЭК (согласно настройкам статусов ЭК)
|
||||
/// </summary>
|
||||
public bool Activate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Состояние для активированных РР, шаблоны
|
||||
/// </summary>
|
||||
public bool OnTemplateIsActive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Состояние для активированных РР, расписания
|
||||
/// </summary>
|
||||
public bool OnScheduleIsActive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Состояние для деактивированных РР, шаблоны
|
||||
/// </summary>
|
||||
public bool OffTemplateIsActive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Состояние для деактивированных РР, расписания
|
||||
/// </summary>
|
||||
public bool OffScheduleIsActive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Маски ЭК
|
||||
/// </summary>
|
||||
public List<JobEkMaskResponse>? EkMasks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Статусы ЭК для которых включена генерация РР и активация
|
||||
/// </summary>
|
||||
public List<EkStatusResponse>? EnabledEkStatuses{ get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Краткое описание
|
||||
/// </summary>
|
||||
public required string ShortDescription { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Рабочие группы
|
||||
/// </summary>
|
||||
public List<WorkGroupResponse>? WorkGroups { get; set; }
|
||||
}
|
||||
}
|
||||
9
PARR.API/Contracts/V1/Responses/JobEkMaskResponse.cs
Normal file
9
PARR.API/Contracts/V1/Responses/JobEkMaskResponse.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace PARR.API.Contracts.V1.Responses
|
||||
{
|
||||
public class JobEkMaskResponse
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public required string Name { get; set; }
|
||||
}
|
||||
}
|
||||
213
PARR.API/Controllers/V1/JobAutoControlController.cs
Normal file
213
PARR.API/Controllers/V1/JobAutoControlController.cs
Normal file
@@ -0,0 +1,213 @@
|
||||
using AutoMapper;
|
||||
using FluentValidation;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using PARR.API.Contracts.V1;
|
||||
using PARR.API.Contracts.V1.Requests;
|
||||
using PARR.API.Contracts.V1.Responses;
|
||||
using PARR.API.Contracts.V1.Responses.Base;
|
||||
using PARR.API.Controllers.V1.Base;
|
||||
using PARR.API.Services.Interfaces;
|
||||
using PARR.Constants;
|
||||
using PARR.DAL.Models;
|
||||
using PARR.DAL.Services.Interfaces;
|
||||
|
||||
namespace PARR.API.Controllers.V1
|
||||
{
|
||||
/// <summary>
|
||||
/// Управление автоматическим созданием/деактивацией/активацией РР
|
||||
/// </summary>
|
||||
[Authorize(Roles = ParrRoles.Administrator.Role)]
|
||||
public class JobAutoControlController : BaseApiController
|
||||
{
|
||||
private readonly IJobAutoControlService jobAutoControlService;
|
||||
private readonly IMapper mapper;
|
||||
private readonly IValidator<JobAutoControlRequest> validator;
|
||||
private readonly IUriService uriService;
|
||||
|
||||
public JobAutoControlController(
|
||||
IJobAutoControlService jobAutoControlService,
|
||||
IMapper mapper,
|
||||
IValidator<JobAutoControlRequest> validator,
|
||||
IUriService uriService
|
||||
)
|
||||
{
|
||||
this.jobAutoControlService = jobAutoControlService;
|
||||
this.mapper = mapper;
|
||||
this.validator = validator;
|
||||
this.uriService = uriService;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Получить настройки автоматического управления РР
|
||||
/// </summary>
|
||||
/// <param name="applicationInWorkId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet(ApiRoutes.JobAutoControl.Get)]
|
||||
public async Task<IActionResult> Get([FromRoute] Guid applicationInWorkId)
|
||||
{
|
||||
var obj = await jobAutoControlService.Get()
|
||||
.Include(t => t.ApplicationsInWork).ThenInclude(t => t.WorkGroups).ThenInclude(t => t.WorkGroup)
|
||||
.Include(t => t.JobEkMasks)
|
||||
.Include(t => t.JobAutoControlInEkStatuses).ThenInclude(t => t.EkStatus)
|
||||
.FirstOrDefaultAsync(t => t.ApplicationInWorkId == applicationInWorkId);
|
||||
|
||||
if (obj == null)
|
||||
return NotFound();
|
||||
|
||||
var response = mapper.Map<JobAutoControlResponse>(obj);
|
||||
|
||||
return Ok(new Response<JobAutoControlResponse>(response, true));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Создать настройки автоматического управления РР
|
||||
/// </summary>
|
||||
/// <param name="applicationInWorkId"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost(ApiRoutes.JobAutoControl.Create)]
|
||||
public async Task<IActionResult> Create([FromRoute] Guid applicationInWorkId, [FromBody] JobAutoControlRequest request)
|
||||
{
|
||||
var exist = await jobAutoControlService.Get().FirstOrDefaultAsync(t => t.ApplicationInWorkId == applicationInWorkId);
|
||||
if (exist != null)
|
||||
return BadRequest(new Response(false, new List<ErrorModel> {
|
||||
new ErrorModel { FieldName = nameof(applicationInWorkId), Message = $"Запись с {nameof(applicationInWorkId)}: {applicationInWorkId} уже существует." }
|
||||
}));
|
||||
|
||||
var resultValidate = await validator.ValidateAsync(request);
|
||||
if (!resultValidate.IsValid)
|
||||
return BadRequest(new Response(resultValidate.Errors));
|
||||
|
||||
var newObj = new DAL.Models.JobAutoControl
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
ApplicationInWorkId = applicationInWorkId,
|
||||
CreateNew = request.CreateNew,
|
||||
Deactivate = request.Deactivate,
|
||||
Activate = request.Activate,
|
||||
OnTemplateIsActive = request.OnTemplateIsActive,
|
||||
OnScheduleIsActive = request.OnScheduleIsActive,
|
||||
OffTemplateIsActive = request.OffTemplateIsActive,
|
||||
OffScheduleIsActive = request.OffScheduleIsActive
|
||||
};
|
||||
|
||||
// убираем пробелы и дубли
|
||||
request.EkMasks.Where(t => t.Trim() != string.Empty).Distinct().ToList().ForEach(mask => newObj.JobEkMasks.Add(new JobEkMask
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
DateCreated = DateTimeOffset.UtcNow,
|
||||
Name = mask.Trim(),
|
||||
JobAutoControlId = newObj.Id
|
||||
}));
|
||||
|
||||
request.EnabledEkStatuses.ForEach(status => newObj.JobAutoControlInEkStatuses.Add(new JobAutoControlInEkStatus
|
||||
{
|
||||
EkStatusCode = (int)status,
|
||||
JobAutoControlId = newObj.Id
|
||||
}));
|
||||
|
||||
if (!await jobAutoControlService.CreateAsync(newObj) || !await jobAutoControlService.CommitAsync())
|
||||
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = "Ошибка при создани записи." } }));
|
||||
|
||||
var locationUri = uriService.GetUri(ApiRoutes.JobAutoControl.Get, ApiRoutes.JobAutoControl.appInWorkId, applicationInWorkId);
|
||||
|
||||
var createdObj = await jobAutoControlService.Get()
|
||||
.Include(t => t.ApplicationsInWork).ThenInclude(t => t.WorkGroups).ThenInclude(t => t.WorkGroup)
|
||||
.Include(t => t.JobEkMasks)
|
||||
.Include(t => t.JobAutoControlInEkStatuses).ThenInclude(t => t.EkStatus)
|
||||
.FirstOrDefaultAsync(t => t.ApplicationInWorkId == applicationInWorkId);
|
||||
|
||||
return Created(locationUri, new Response<JobAutoControlResponse>(mapper.Map<JobAutoControlResponse>(createdObj), true));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Обновить настройки автоматического управления РР
|
||||
/// </summary>
|
||||
/// <param name="applicationInWorkId"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPut(ApiRoutes.JobAutoControl.Update)]
|
||||
public async Task<IActionResult> Update([FromRoute] Guid applicationInWorkId, [FromBody] JobAutoControlRequest request)
|
||||
{
|
||||
var resultValidate = await validator.ValidateAsync(request);
|
||||
if (!resultValidate.IsValid)
|
||||
return BadRequest(new Response(resultValidate.Errors));
|
||||
|
||||
var orig = await jobAutoControlService.Get()
|
||||
.Include(t => t.JobEkMasks)
|
||||
.Include(t => t.JobAutoControlInEkStatuses)
|
||||
.FirstOrDefaultAsync(t => t.ApplicationInWorkId == applicationInWorkId);
|
||||
|
||||
if (orig == null)
|
||||
return BadRequest(new Response(false, new List<ErrorModel> {
|
||||
new ErrorModel { FieldName = nameof(applicationInWorkId), Message = $"Запись с {nameof(applicationInWorkId)}: {applicationInWorkId} не существует." }
|
||||
}));
|
||||
|
||||
|
||||
orig.DateModified = DateTimeOffset.UtcNow;
|
||||
orig.CreateNew = request.CreateNew;
|
||||
orig.Deactivate = request.Deactivate;
|
||||
orig.Activate = request.Activate;
|
||||
orig.OnTemplateIsActive = request.OnTemplateIsActive;
|
||||
orig.OnScheduleIsActive = request.OnScheduleIsActive;
|
||||
orig.OffTemplateIsActive = request.OffTemplateIsActive;
|
||||
orig.OffScheduleIsActive = request.OffScheduleIsActive;
|
||||
|
||||
orig.JobEkMasks.Clear();
|
||||
// убираем пробелы и дубли
|
||||
request.EkMasks.Where(t => t.Trim() != string.Empty).Distinct().ToList().ForEach(mask => orig.JobEkMasks.Add(new JobEkMask
|
||||
{
|
||||
//Id = Guid.NewGuid(), // не пойму почему не нужно это поле. с ним ошибка.
|
||||
DateCreated = DateTimeOffset.UtcNow,
|
||||
Name = mask.Trim(),
|
||||
JobAutoControlId = orig.Id
|
||||
}));
|
||||
|
||||
orig.JobAutoControlInEkStatuses.Clear();
|
||||
request.EnabledEkStatuses.ForEach(status => orig.JobAutoControlInEkStatuses.Add(new JobAutoControlInEkStatus
|
||||
{
|
||||
EkStatusCode = (int)status,
|
||||
JobAutoControlId = orig.Id
|
||||
}));
|
||||
|
||||
if (!await jobAutoControlService.CommitAsync())
|
||||
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = "Ошибка при изменении записи." } }));
|
||||
|
||||
|
||||
var updatedObj = await jobAutoControlService.Get()
|
||||
.Include(t => t.ApplicationsInWork).ThenInclude(t => t.WorkGroups).ThenInclude(t => t.WorkGroup)
|
||||
.Include(t => t.JobEkMasks)
|
||||
.Include(t => t.JobAutoControlInEkStatuses).ThenInclude(t => t.EkStatus)
|
||||
.FirstOrDefaultAsync(t => t.ApplicationInWorkId == applicationInWorkId);
|
||||
|
||||
return Ok(new Response<JobAutoControlResponse>(mapper.Map<JobAutoControlResponse>(updatedObj), true));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Удалить настройки автоматического управления РР
|
||||
/// </summary>
|
||||
/// <param name="applicationInWorkId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete(ApiRoutes.JobAutoControl.Delete)]
|
||||
public async Task<IActionResult> Delete([FromRoute] Guid applicationInWorkId)
|
||||
{
|
||||
var obj = await jobAutoControlService.Get().FirstOrDefaultAsync(t => t.ApplicationInWorkId == applicationInWorkId);
|
||||
|
||||
if (obj == null)
|
||||
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = $"Ошибка при удалении настроект. Не найден настройки с {nameof(applicationInWorkId)}: {applicationInWorkId}" } }));
|
||||
|
||||
if (!jobAutoControlService.Delete(obj) || !await jobAutoControlService.CommitAsync())
|
||||
return BadRequest(new Response(false, new List<ErrorModel> { new ErrorModel { Message = $"Ошибка при удалении настроек." } }));
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,6 @@ using PARR.Constants;
|
||||
using PARR.DAL.DomainModels;
|
||||
using PARR.DAL.Models;
|
||||
using PARR.DAL.Services.Interfaces;
|
||||
using Serilog.Core;
|
||||
|
||||
namespace PARR.API.Controllers.V1
|
||||
{
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using PARR.API.Authentication.Models;
|
||||
using PARR.API.Contracts.V1.Responses;
|
||||
using PARR.API.MappingProfiles.Resolvers;
|
||||
using PARR.BLL.Helpers;
|
||||
using PARR.Constants.Shortcode;
|
||||
using PARR.DAL.DomainModels;
|
||||
using PARR.DAL.Extensions;
|
||||
@@ -276,10 +275,23 @@ namespace PARR.API.MappingProfiles
|
||||
|
||||
#endregion
|
||||
|
||||
#region JobAutoControl
|
||||
|
||||
CreateMap<JobAutoControl, JobAutoControlResponse>()
|
||||
.ForMember(d => d.EkMasks, o => o.MapFrom(s => s.JobEkMasks.OrderBy(t => t.Name)))
|
||||
.ForMember(d => d.EnabledEkStatuses, o => o.MapFrom(s => s.JobAutoControlInEkStatuses.Select(t => t.EkStatus).OrderBy(t => t.Name)))
|
||||
.ForMember(d => d.ShortDescription, o => o.MapFrom(s => s.ApplicationsInWork.ShortDescription))
|
||||
.ForMember(d => d.WorkGroups, o => o.MapFrom(s => s.ApplicationsInWork.WorkGroups.Select(t => t.WorkGroup).OrderBy(t => t.Name)));
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region ResponseArea
|
||||
CreateMap<ResponseArea, ResponseAreaResponse>();
|
||||
#endregion
|
||||
|
||||
CreateMap<JobEkMask, JobEkMaskResponse>();
|
||||
|
||||
|
||||
CreateMap<EkStatus, EkStatusResponse>();
|
||||
}
|
||||
|
||||
33
PARR.API/Validators/JobAutoControlRequestValidator.cs
Normal file
33
PARR.API/Validators/JobAutoControlRequestValidator.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using FluentValidation;
|
||||
using PARR.API.Contracts.V1.Requests;
|
||||
using PARR.DAL.Contracts;
|
||||
|
||||
namespace PARR.API.Validators
|
||||
{
|
||||
public class JobAutoControlRequestValidator : AbstractValidator<JobAutoControlRequest>
|
||||
{
|
||||
public JobAutoControlRequestValidator()
|
||||
{
|
||||
RuleFor(t => t.EkMasks).Must(items =>
|
||||
items.Count(t => t.Trim().Length > 0) > 0
|
||||
).WithMessage("Должна быть указана хотя бы одна маска ЭК");
|
||||
|
||||
RuleFor(t => t.EnabledEkStatuses).Must(
|
||||
items => items.Distinct().Count() == items.Count()
|
||||
).WithMessage("Статусы ЭК не должны повторяться");
|
||||
|
||||
RuleFor(t => t.EnabledEkStatuses).Must(items =>
|
||||
{
|
||||
return !items.Any(item => !Enum.IsDefined(typeof(EkStatusEnum), item)) && !items.Any(t => t == 0);
|
||||
})
|
||||
.WithMessage($"Допустимые значения: {(int)EkStatusEnum.New} ({EkStatusEnum.New}), " +
|
||||
$"{(int)EkStatusEnum.Preapre} ({EkStatusEnum.Preapre}), " +
|
||||
$"{(int)EkStatusEnum.Exploitation} ({EkStatusEnum.Exploitation}), " +
|
||||
$"{(int)EkStatusEnum.Repair} ({EkStatusEnum.Repair}), " +
|
||||
$"{(int)EkStatusEnum.Reserve} ({EkStatusEnum.Reserve}), " +
|
||||
$"{(int)EkStatusEnum.OutOfService} ({EkStatusEnum.OutOfService}), " +
|
||||
$"{(int)EkStatusEnum.Test} ({EkStatusEnum.Test}), " +
|
||||
$"{(int)EkStatusEnum.Development} ({EkStatusEnum.Development})");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,9 @@ namespace PARR.API.Validators
|
||||
{
|
||||
public RobotStateRequestValidator()
|
||||
{
|
||||
RuleFor(t => t.Robot).NotNull().IsInEnum().WithMessage($"Допустимые значения: {(int)RobotsAllEnum.TemplateOrder} ({RobotsAllEnum.TemplateOrder})," +
|
||||
$"{(int)RobotsAllEnum.ScheduleOrder} ({RobotsAllEnum.ScheduleOrder})," +
|
||||
$"{(int)RobotsAllEnum.TemplatesExport} ({RobotsAllEnum.TemplatesExport})," +
|
||||
RuleFor(t => t.Robot).NotNull().IsInEnum().WithMessage($"Допустимые значения: {(int)RobotsAllEnum.TemplateOrder} ({RobotsAllEnum.TemplateOrder}), " +
|
||||
$"{(int)RobotsAllEnum.ScheduleOrder} ({RobotsAllEnum.ScheduleOrder}), " +
|
||||
$"{(int)RobotsAllEnum.TemplatesExport} ({RobotsAllEnum.TemplatesExport}), " +
|
||||
$"{(int)RobotsAllEnum.ScheduleExport} ({RobotsAllEnum.ScheduleExport})");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user