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; using PARR.DAL.Services.Interfaces; namespace PARR.API.Controllers.V1 { /// /// Управление работами /// [Authorize(Roles = ParrRoles.Administrator.Role)] public class WorkController : BaseApiController { private readonly ILogger logger; private readonly IMapper mapper; private readonly IWorkService workService; private readonly IValidator validator; private readonly IUriService uriService; public WorkController( ILogger logger, IMapper mapper, IWorkService workService, IValidator validator, IUriService uriService ) { this.logger = logger; this.mapper = mapper; this.workService = workService; this.validator = validator; this.uriService = uriService; } /// /// Список видов работ постранично /// /// /// [HttpGet(ApiRoutes.Work.GetAll)] public async Task GetAll([FromQuery] PaginationQuery paginationQuery, [FromQuery] WorkGetAllQuery filter) { var paginationFilter = mapper.Map(paginationQuery); IQueryable query = workService.Get() .OrderBy(t => t.Name); if (filter.AllParents) query = query.Include(t => t.Tnk).ThenInclude(s => s.Subprocess).ThenInclude(p => p.Process); if (!string.IsNullOrWhiteSpace(filter.Name)) query = query.Where(t => t.Name.ToLower().Contains(filter.Name.ToLower())); if (filter.Id.HasValue) query = query.Where(t => t.Id == filter.Id); if (filter.TnkId.HasValue) query = query.Where(t => t.TnkId == filter.TnkId.Value); var works = await workService.GetPage(query, paginationFilter).ToListAsync(); if (!works.Any()) return NoContent(); if (filter.AllParents) { //todo: тут бесконечность в маппинге // респонс с иерархией вверх до процесса var allResponse = mapper.Map>(works); var paginationAllResponse = new PagedResponse(allResponse, true).GetPaginatedProps(paginationFilter, query); return Ok(paginationAllResponse); } var workResponse = mapper.Map>(works); var paginationResponse = new PagedResponse(workResponse, true).GetPaginatedProps(paginationFilter, query); return Ok(paginationResponse); } /// /// Получить работу по id /// /// /// [HttpGet(ApiRoutes.Work.Get)] public async Task GetById([FromRoute] Guid id) { var work = await workService.Get() .FirstOrDefaultAsync(t => t.Id == id); if (work == null) return NotFound(); var response = mapper.Map(work); return Ok(new Response(response, true)); } /// /// Создать вид работы /// /// /// [HttpPost(ApiRoutes.Work.Create)] public async Task Create([FromBody] WorkRequest request) { var resultValidate = await validator.ValidateAsync(request); if (!resultValidate.IsValid) return BadRequest(new Response(resultValidate.Errors)); var existName = await workService.Get().FirstOrDefaultAsync(t => t.Name.ToLower() == request.Name.Trim().ToLower()); if (existName != null) return BadRequest(new Response(false, new List { new ErrorModel { FieldName = nameof(request.Name), Message = $"Вид работы с именем \"{request.Name}\" уже существует." } })); var existEsppId = await workService.Get().FirstOrDefaultAsync(t => t.EsppId == request.EsppId); if (existEsppId != null) return BadRequest(new Response(false, new List { new ErrorModel { FieldName = nameof(request.EsppId), Message = $"Вид работы с EsppId: {request.EsppId} уже существует." } })); var work = new Work { Id = Guid.NewGuid(), Name = request.Name.Trim(), EsppId = request.EsppId, TnkId = request.TnkId, TemplateSuffix = request.TemplateSuffix }; if (!await workService.CreateAsync(work) || !await workService.CommitAsync()) return BadRequest(new Response(false, new List { new ErrorModel { Message = "Ошибка при создании вида работ." } })); logger.LogInformation($"Пользователь {User.Identity?.Name} добавил вид работ: {work.Name}, {work.EsppId}, {work.TnkId}"); var locationUri = uriService.GetUri(ApiRoutes.Work.Get, ApiRoutes.Work.getParam, work.Id); return Created(locationUri, new Response(mapper.Map(work), true)); } /// /// Обновить вид работ /// /// /// /// [HttpPut(ApiRoutes.Work.Update)] public async Task Update([FromRoute] Guid id, [FromBody] WorkRequest request) { var resultValidate = await validator.ValidateAsync(request); if (!resultValidate.IsValid) return BadRequest(new Response(resultValidate.Errors)); //проверка на уникальность esppId var existEsppId = await workService.Get().FirstOrDefaultAsync(t => t.Id != id && t.EsppId == request.EsppId); if (existEsppId != null) return BadRequest(new Response(false, new List { new ErrorModel { FieldName = nameof(request.EsppId), Message = $"Уже есть вид работ с EsppId: {request.EsppId}" } })); var orig = await workService.Get() .FirstOrDefaultAsync(t => t.Id == id); if (orig == null) return BadRequest(new Response(false, new List { new ErrorModel { Message = $"Ошибка при изменении вида работ. Не найдена работа Id: {id}" } })); orig.Name = request.Name.Trim(); orig.EsppId = request.EsppId; orig.TnkId = request.TnkId; orig.DateModified = DateTimeOffset.UtcNow; orig.TemplateSuffix = request.TemplateSuffix; if (!await workService.CommitAsync()) return BadRequest(new Response(false, new List { new ErrorModel { Message = "Ошибка записи в базу данных изменений вида работ." } })); logger.LogInformation($"Пользователь {User.Identity?.Name} обновил работу: {orig.Id}, {orig.Name}, {orig.EsppId}, {orig.TnkId}"); return Ok(new Response(mapper.Map(orig), true)); } /// /// Удалить вид работ (если у него нет заданий (AppInWork)) /// /// /// [HttpDelete(ApiRoutes.Work.Delete)] public async Task Delete([FromRoute] Guid id) { var work = await workService.Get().Include(t => t.ApplicationsInWorks).FirstOrDefaultAsync(t => t.Id == id); if (work == null) return BadRequest(new Response(false, new List { new ErrorModel { Message = $"Ошибка при удалении вида работ." } })); if (work.ApplicationsInWorks.Any()) return BadRequest(new Response(false, new List { new ErrorModel { Message = $"Ошибка при удалении вида работ. У данной работы есть задания ({work.ApplicationsInWorks.Count()} шт.)" } })); if (!workService.Delete(work) || !await workService.CommitAsync()) return BadRequest(new Response(false, new List { new ErrorModel { Message = $"Ошибка при удалении вида работ." } })); logger.LogInformation($"Пользователь {User.Identity?.Name} удалил вид работ: {work.Id}, {work.Name}, {work.EsppId}, {work.TnkId}"); return NoContent(); } } }