using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Data.ProcessMaps;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace AsbCloudWebApi.Controllers.ProcessMaps;
///
/// Конструкция скважины - план
///
[ApiController]
[Route("api/well/{idWell:int}/[controller]")]
[Authorize]
public class WellSectionPlanController : ControllerBase
{
private readonly IWellService wellService;
private readonly IWellSectionPlanRepository wellSectionPlanRepository;
private readonly ICrudRepository wellSectionRepository;
public WellSectionPlanController(IWellService wellService,
IWellSectionPlanRepository wellSectionPlanRepository,
ICrudRepository wellSectionRepository)
{
this.wellService = wellService;
this.wellSectionPlanRepository = wellSectionPlanRepository;
this.wellSectionRepository = wellSectionRepository;
}
//TODO: так же следует вынести в базовый контроллер
private int IdUser
{
get
{
var idUser = User.GetUserId();
if (!idUser.HasValue)
throw new ForbidException("Неизвестный пользователь");
return idUser.Value;
}
}
///
/// Добавить секцию
///
/// Идентификатор скважины
/// Секция скважины - план
///
///
[HttpPost]
[Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task InsertAsync(int idWell, WellSectionPlanDto wellSection, CancellationToken cancellationToken)
{
wellSection.IdWell = idWell;
wellSection.IdUser = IdUser;
await CheckIsExistsWellSectionTypeAsync(wellSection.IdSectionType, cancellationToken);
await AssertUserAccessToWell(idWell, cancellationToken);
var wellSectionId = await wellSectionPlanRepository.InsertAsync(wellSection, cancellationToken);
return Ok(wellSectionId);
}
///
/// Обновить секцию
///
/// Идентификатор скважины
/// Секция скважины - план
///
///
[HttpPut]
[Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task UpdateAsync(int idWell, WellSectionPlanDto wellSection, CancellationToken cancellationToken)
{
wellSection.IdWell = idWell;
wellSection.IdUser = IdUser;
wellSection.LastUpdateDate = DateTimeOffset.UtcNow;
await CheckIsExistsWellSectionTypeAsync(wellSection.IdSectionType, cancellationToken);
await AssertUserAccessToWell(idWell, cancellationToken);
var wellSectionId = await wellSectionPlanRepository.UpdateAsync(wellSection, cancellationToken);
if (wellSectionId == ICrudRepository.ErrorIdNotFound)
return this.ValidationBadRequest(nameof(wellSection.Id), $"Секции скважины с Id: {wellSection.Id} не существует");
return Ok(wellSectionId);
}
///
/// Получить типы секций
///
/// Идентификатор скважины
///
///
[HttpGet("wellSectionTypes")]
[ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task GetWellSectionTypesAsync(int idWell, CancellationToken cancellationToken)
{
await AssertUserAccessToWell(idWell, cancellationToken);
var wellSectionTypes = await wellSectionPlanRepository.GetWellSectionTypesAsync(idWell, cancellationToken);
if (!wellSectionTypes.Any())
return NoContent();
return Ok(wellSectionTypes);
}
///
/// Получить список секций
///
/// Идентификатор скважины
///
///
[HttpGet]
[ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task GetPlanWellSectionsAsync(int idWell, CancellationToken cancellationToken)
{
await AssertUserAccessToWell(idWell, cancellationToken);
var planWellSections = await wellSectionPlanRepository.GetByIdWellAsync(idWell, cancellationToken);
if (!planWellSections.Any())
return NoContent();
return Ok(planWellSections);
}
///
/// Удалить секцию
///
/// Идентификатор скважины
/// Идентификатор плановой секции
///
///
[HttpDelete]
[Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task DeleteAsync(int idWell, int id, CancellationToken cancellationToken)
{
await AssertUserAccessToWell(idWell, cancellationToken);
var deletedWellSectionPlanCount = await wellSectionPlanRepository.DeleteAsync(id, cancellationToken);
return Ok(deletedWellSectionPlanCount);
}
//TODO: нужно создать базовый контроллер связанный со скважиной и вынести этот метод туда. Данный метод много где дублируется
private async Task AssertUserAccessToWell(int idWell, CancellationToken cancellationToken)
{
var idCompany = User.GetCompanyId();
if (!idCompany.HasValue || !await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, idWell, cancellationToken))
throw new ForbidException("Нет доступа к скважине");
}
//TODO: тоже нужно вынести в базовый контроллер
private async Task CheckIsExistsWellSectionTypeAsync(int idWellSectionType, CancellationToken cancellationToken)
{
_ = await wellSectionRepository.GetOrDefaultAsync(idWellSectionType, cancellationToken)
?? throw new ArgumentInvalidException(nameof(ProcessMapPlanWellDrillingDto.IdWellSectionType),
$"Тип секции с Id: {idWellSectionType} не найден");
}
}