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 AsbCloudApp.Data.ProcessMaps; using System.ComponentModel.DataAnnotations; using AsbCloudApp.Requests.ExportOptions; using AsbCloudApp.Services.Export; using AsbCloudApp.Services.Parsers; namespace AsbCloudWebApi.Controllers.ProcessMaps; /// /// РТК план базовый /// [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 IParserService parserService; private readonly IExportService processMapPlanExportService; protected ProcessMapPlanBaseController(IChangeLogRepository repository, IWellService wellService, IParserService parserService, IExportService processMapPlanExportService) { this.repository = repository; this.wellService = wellService; this.parserService = parserService; this.processMapPlanExportService = processMapPlanExportService; } protected abstract string TemplateFileName { get; } /// /// Добавление /// /// /// /// /// [HttpPost] [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public async Task InsertRange([FromRoute][Range(0,int.MaxValue)] int idWell, IEnumerable dtos, CancellationToken token) { var idUser = await AssertUserHasAccessToWell(idWell, token); foreach (var dto in dtos) dto.IdWell = idWell; 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) { var idUser = await AssertUserHasAccessToWell(idWell, token); foreach (var dto in dtos) dto.IdWell = idWell; 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) { if (!dtos.Any()) return NoContent(); var idUser = await AssertUserHasAccessToWell(idWell, token); foreach (var dto in dtos) dto.IdWell = idWell; 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, [Required] IFormFile file, CancellationToken token) { await AssertUserHasAccessToWell(idWell, token); var stream = file.GetExcelFile(); try { var options = new WellRelatedParserRequest(idWell); var dto = parserService.Parse(stream, options); return Ok(dto); } catch (FileFormatException ex) { return this.ValidationBadRequest(nameof(file), 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; } /// /// Формируем excel файл с текущими строками РТК /// /// id скважины /// /// Запрашиваемый файл [HttpGet("export")] [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task ExportAsync([FromRoute] int idWell, CancellationToken token) { var exportOptions = new WellRelatedExportRequest(idWell); var (fileName, file) = await processMapPlanExportService.ExportAsync(exportOptions, token); return File(file, "application/octet-stream", fileName); } /// /// returns user id or throw /// /// /// private int GetUserId() { var idUser = User.GetUserId() ?? throw new ForbidException("Неизвестный пользователь"); return idUser; } }