From 30c190f62f337b56b4378030abd62530ebce5f29 Mon Sep 17 00:00:00 2001 From: Mikhail Kuznetsov Date: Wed, 27 Mar 2024 11:13:52 +1000 Subject: [PATCH] =?UTF-8?q?feat(api):=20appInWorkContoller=20=D0=B4=D0=BE?= =?UTF-8?q?=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=BC=D0=B5=D1=82=D0=BE?= =?UTF-8?q?=D0=B4=20Create?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PARR.API/Contracts/V1/ApiRoutes.cs | 13 ++-- .../V1/Requests/ApplicationInWorkRequest.cs | 27 ++++++++ .../V1/ApplicationInWorkController.cs | 61 ++++++++++++++++++- .../Validators/ApplicationInWorkValidator.cs | 54 ++++++++++++++++ 4 files changed, 149 insertions(+), 6 deletions(-) create mode 100644 PARR.API/Contracts/V1/Requests/ApplicationInWorkRequest.cs create mode 100644 PARR.API/Validators/ApplicationInWorkValidator.cs diff --git a/PARR.API/Contracts/V1/ApiRoutes.cs b/PARR.API/Contracts/V1/ApiRoutes.cs index be60ca06..c29d0210 100644 --- a/PARR.API/Contracts/V1/ApiRoutes.cs +++ b/PARR.API/Contracts/V1/ApiRoutes.cs @@ -1,6 +1,4 @@ -using System.Runtime.InteropServices; - -namespace PARR.API.Contracts.V1 +namespace PARR.API.Contracts.V1 { // https://tproger.ru/translations/luchshie-praktiki-razrabotki-rest-api-20-sovetov/ @@ -281,7 +279,6 @@ namespace PARR.API.Contracts.V1 } - #endregion #region Job @@ -291,7 +288,13 @@ namespace PARR.API.Contracts.V1 public static class Job { public const string GetAll = Base + "/jobs/"; - //public const string Get = Base + "/jobs/" + getParam; + public const string Get = Base + "/jobs/" + getParam; + + public const string GetScheduler = Base + "/jobs/" + getParam + "/scheduller"; + + public const string Delete = Base + "/jobs/" + getParam; + public const string Create = Base + "/jobs/"; + public const string Update = Base + "/jobs/" + getParam; public const string getParam = "{id}"; } diff --git a/PARR.API/Contracts/V1/Requests/ApplicationInWorkRequest.cs b/PARR.API/Contracts/V1/Requests/ApplicationInWorkRequest.cs new file mode 100644 index 00000000..422c535a --- /dev/null +++ b/PARR.API/Contracts/V1/Requests/ApplicationInWorkRequest.cs @@ -0,0 +1,27 @@ +namespace PARR.API.Contracts.V1.Requests +{ + public class ApplicationInWorkRequest + { + + public required Guid WorkId { get; set; } + + public required Guid ApplicationId { get; set; } + + public required string TemplateDuration { get; set; } + + public required string ShortDescription { get; set; } + + public required string FullDescription { get; set; } + + public required string Solution { get; set; } + public DateTimeOffset NextRun { get; set; } + + public bool IsAgent { get; set; } + + public string? AgentName { get; set; } + + public int? AgentTimeOutSec { get; set; } + + public string? AgentScript { get; set; } + } +} diff --git a/PARR.API/Controllers/V1/ApplicationInWorkController.cs b/PARR.API/Controllers/V1/ApplicationInWorkController.cs index 20a839c6..9018627e 100644 --- a/PARR.API/Controllers/V1/ApplicationInWorkController.cs +++ b/PARR.API/Controllers/V1/ApplicationInWorkController.cs @@ -1,13 +1,16 @@ 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.Requests.Queries; using PARR.API.Contracts.V1.Responses; using PARR.API.Contracts.V1.Responses.Base; using PARR.API.Controllers.V1.Base; using PARR.API.Extensions; +using PARR.API.Services.Interfaces; using PARR.Constants; using PARR.DAL.DomainModels; using PARR.DAL.Models; @@ -21,16 +24,72 @@ namespace PARR.API.Controllers.V1 [Authorize(Roles = ParrRoles.Administrator.Role)] public class ApplicationInWorkController : BaseApiController { + private readonly ILogger logger; private readonly IMapper mapper; private readonly IApplicationsInWorkService applicationsInWorkService; + private readonly IValidator validator; + private readonly IUriService uriService; public ApplicationInWorkController( + ILogger logger, IMapper mapper, - IApplicationsInWorkService applicationsInWorkService + IApplicationsInWorkService applicationsInWorkService, + IValidator validator, + IUriService uriService ) { + this.logger = logger; this.mapper = mapper; this.applicationsInWorkService = applicationsInWorkService; + this.validator = validator; + this.uriService = uriService; + } + + + /// + /// Создать задание на выполнение работ(ApplicationInWork) + /// + /// + /// + [HttpPost(ApiRoutes.Job.Create)] + public async Task Create([FromBody] ApplicationInWorkRequest request) + { + var resultValidate = await validator.ValidateAsync(request); + + if (!resultValidate.IsValid) + return BadRequest(new Response(resultValidate.Errors)); + + var existSameAiW = await applicationsInWorkService.Get(request.ApplicationId, request.WorkId); + + if (existSameAiW != null) + return BadRequest(new Response(false, new List { + new ErrorModel { Message = $"Уже существует задание на выполнение работ для программного обеспечения id(\"{request.ApplicationId}\") и работой id({request.WorkId})." } } + )); + + var applicationInWork = new ApplicationsInWork + { + Id = Guid.NewGuid(), + WorkId = request.WorkId, + ApplicationId = request.ApplicationId, + TemplateDuration = request.TemplateDuration, + ShortDescription = request.ShortDescription, + FullDescription = request.FullDescription, + Solution = request.Solution, + NextRun = request.NextRun, + IsAgent = request.IsAgent, + AgentName = request.AgentName, + AgentTimeOutSec = request.AgentTimeOutSec, + AgentScript = request.AgentScript + }; + + if (!await applicationsInWorkService.CreateAsync(applicationInWork) || !await applicationsInWorkService.CommitAsync()) + return BadRequest(new Response(false, new List { new ErrorModel { Message = "Ошибка при записи нового задания на выполнение работ в базу данных" } })); + + logger.LogInformation($"Пользователь {User.Identity?.Name} добавил задание на выполнение работ: {applicationInWork.ShortDescription}, {applicationInWork.Solution}, {applicationInWork.NextRun}"); + + var locationUri = uriService.GetUri(ApiRoutes.Job.Get, ApiRoutes.Job.getParam, applicationInWork.Id); + + return Created(locationUri, new Response(mapper.Map(applicationInWork), true)); } diff --git a/PARR.API/Validators/ApplicationInWorkValidator.cs b/PARR.API/Validators/ApplicationInWorkValidator.cs new file mode 100644 index 00000000..ec0af5b4 --- /dev/null +++ b/PARR.API/Validators/ApplicationInWorkValidator.cs @@ -0,0 +1,54 @@ +using FluentValidation; +using PARR.API.Contracts.V1.Requests; +using PARR.DAL.Services.Interfaces; + +namespace PARR.API.Validators +{ + public class ApplicationInWorkValidator : AbstractValidator + { + private readonly IApplicationsInWorkService applicationsInWorkService; + private readonly IWorkService workService; + + public ApplicationInWorkValidator( + IApplicationsInWorkService applicationsInWorkService, + IWorkService workService + ) + { + this.applicationsInWorkService = applicationsInWorkService; + this.workService = workService; + + RuleFor(t => t.TemplateDuration) + .NotNull().NotEmpty().WithMessage("Длительность данного задания на выполнение работ не может быть пустым") + .Matches("^\\d{1,2}\\s\\d{2}[:]\\d{2}[:]\\d{2}$") + .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 работы"); + + RuleFor(t => t.ApplicationId) + .MustAsync(async (entity, value, c) => await IsApplicationExist(entity)) + .WithMessage("У данного задания на выполнение работ указан несуществующий Id программного обеспечения"); + } + + + private async Task IsWorkExist(ApplicationInWorkRequest request) + { + return await workService.GetAsync(request.WorkId) != null; + } + + private async Task IsApplicationExist(ApplicationInWorkRequest request) + { + return await workService.GetAsync(request.WorkId) != null; + } + } +}