using AsbCloudApp.Data.ProcessMapPlan; using AsbCloudApp.Repositories; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using System.Threading.Tasks; using System.Threading; using Microsoft.AspNetCore.Http; using AsbCloudApp.Exceptions; using AsbCloudApp.Requests; using System; using System.IO; using AsbCloudApp.Services; using System.Linq; using AsbCloudApp.Data; using AsbCloudApp.Requests.ParserOptions; using AsbCloudInfrastructure.Services.Parser; namespace AsbCloudWebApi.Controllers.ProcessMapPlan; /// /// РТК план /// [ApiController] [Route("api/well/{idWell}/[controller]")] [Authorize] public abstract class ProcessMapPlanBaseController : ControllerBase where TDto : ProcessMapPlanBaseDto { private readonly IChangeLogRepository repository; private readonly IWellService wellService; private readonly ParserExcelService parserService; protected ProcessMapPlanBaseController(IChangeLogRepository repository, IWellService wellService, ParserExcelService parserService) { this.repository = repository; this.wellService = wellService; this.parserService = parserService; } protected abstract string TemplateFileName { get; } /// /// Добавление /// /// /// /// /// [HttpPost] [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public async Task InsertRange([FromRoute] int idWell, IEnumerable dtos, CancellationToken token) { if (idWell == 0 || dtos.Any(d => d.IdWell != idWell)) return this.ValidationBadRequest(nameof(dtos), "all dtos should contain same idWell"); var idUser = await AssertUserHasAccessToWell(idWell, token); var result = await repository.InsertRange(idUser, dtos, token); return Ok(result); } /// /// Удалить все по скважине и добавить новые /// /// /// /// /// [HttpPost("replace")] [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public async Task ClearAndInsertRange([FromRoute] int idWell, IEnumerable dtos, CancellationToken token) { if (idWell == 0 || dtos.Any(d => d.IdWell != idWell)) return this.ValidationBadRequest(nameof(dtos), "all dtos should contain same idWell"); var idUser = await AssertUserHasAccessToWell(idWell, token); var request = new ProcessMapPlanBaseRequestWithWell(idWell); var result = await repository.ClearAndInsertRange(idUser, request, dtos, token); return Ok(result); } /// /// Удаление /// /// /// /// /// [HttpDelete] [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public async Task DeleteRange([FromRoute]int idWell, IEnumerable ids, CancellationToken token) { var idUser = await AssertUserHasAccessToWell(idWell, token); var result = await repository.DeleteRange(idUser, ids, token); return Ok(result); } /// /// Очистка /// /// /// /// [HttpDelete("clear")] [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public async Task Clear([FromRoute] int idWell, CancellationToken token) { var idUser = await AssertUserHasAccessToWell(idWell, token); var request = new ProcessMapPlanBaseRequestWithWell(idWell); var result = await repository.Clear(idUser, request, token); return Ok(result); } /// /// Получение /// /// /// /// /// [HttpGet] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public async Task>> Get([FromRoute] int idWell, [FromQuery]ProcessMapPlanBaseRequest request, CancellationToken token) { await AssertUserHasAccessToWell(idWell, token); var serviceRequest = new ProcessMapPlanBaseRequestWithWell(request, idWell); var result = await repository.Get(serviceRequest, token); return Ok(result); } /// /// Изменения за определенную дату /// /// /// /// /// [HttpGet("changeLog")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public async Task>> GetChangeLog([FromRoute] int idWell, [FromQuery] DateOnly? date, CancellationToken token) { await AssertUserHasAccessToWell(idWell, token); var serviceRequest = new ProcessMapPlanBaseRequestWithWell(idWell); var result = await repository.GetChangeLog(serviceRequest, date, token); return Ok(result); } /// /// Даты за которые есть изменения /// /// /// /// [HttpGet("dates")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public async Task>> GetDatesChange([FromRoute] int idWell, CancellationToken token) { await AssertUserHasAccessToWell(idWell, token); var serviceRequest = new ProcessMapPlanBaseRequestWithWell(idWell); var result = await repository.GetDatesChange(serviceRequest, token); return Ok(result); } /// /// Редактирование или добавление [для пакетного редактирования] /// /// /// /// /// [HttpPut()] [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public async Task UpdateOrInsertRange([FromRoute] int idWell, IEnumerable dtos, CancellationToken token) { var first = dtos.FirstOrDefault(); if (first is null) return NoContent(); if (idWell == 0 || dtos.Any(d => d.IdWell != idWell)) return this.ValidationBadRequest(nameof(dtos), "all dtos should contain same idWell"); var idUser = await AssertUserHasAccessToWell(idWell, token); var result = await repository.UpdateOrInsertRange(idUser, dtos, token); return Ok(result); } /// /// Импорт РТК из excel (xlsx) файла /// /// /// /// /// [HttpPost("parse")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public async Task>> Parse(int idWell, [FromForm] IFormFileCollection files, CancellationToken token) { await AssertUserHasAccessToWell(idWell, token); var stream = files.GetExcelFile(); try { var dto = parserService.Parse(stream, IParserOptionsRequest.Empty()); return Ok(dto); } catch (FileFormatException ex) { return this.ValidationBadRequest(nameof(files), ex.Message); } } /// /// Получение шаблона для заполнения РТК /// /// [HttpGet("template")] [AllowAnonymous] [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] [ProducesResponseType(StatusCodes.Status204NoContent)] public IActionResult GetTemplate() { var stream = parserService.GetTemplateFile(); return File(stream, "application/octet-stream", TemplateFileName); } /// /// returns user id, if he has access to well /// /// /// /// /// private async Task AssertUserHasAccessToWell(int idWell, CancellationToken token) { var idUser = GetUserId(); var idCompany = User.GetCompanyId(); if (!idCompany.HasValue) throw new ForbidException("Нет доступа к скважине"); if (!await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, idWell, token)) throw new ForbidException("Нет доступа к скважине"); return idUser; } /// /// returns user id or throw /// /// /// private int GetUserId() { var idUser = User.GetUserId() ?? throw new ForbidException("Неизвестный пользователь"); return idUser; } }