using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data; using AsbCloudApp.Repositories; using AsbCloudApp.Services; using AsbCloudInfrastructure.Services; using AsbCloudInfrastructure.Services.Trajectory; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace AsbCloudWebApi.Controllers.Trajectory; /// /// Фактическая траектория /// [Authorize] [ApiController] [Route("api/well/{idWell}/[controller]")] public class FactTrajectoryController : ControllerBase { private readonly ITrajectoryEditableRepository trajectoryFactRepository; private readonly IWellService wellService; private readonly FactTrajectoryImportService factTrajectoryImportService; public FactTrajectoryController( ITrajectoryEditableRepository trajectoryFactRepository, IWellService wellService, FactTrajectoryImportService factTrajectoryImportService) { this.trajectoryFactRepository = trajectoryFactRepository; this.wellService = wellService; this.factTrajectoryImportService = factTrajectoryImportService; } /// /// Метод получения всех строк фактических траекторий по id скважины /// /// Id скважины /// Токен отмены операции /// [HttpGet] [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] public async Task GetRowsAsync([FromRoute] int idWell, CancellationToken cancellationToken) { var importedFactTrajectories = await trajectoryFactRepository.GetAsync(idWell, cancellationToken); return Ok(importedFactTrajectories); } /// /// Добавить одну новую строчку координат для фактической траектории /// /// /// /// /// количество успешно записанных строк в БД [HttpPost] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] public async Task AddAsync(int idWell, [FromBody] TrajectoryGeoFactDto row, CancellationToken token) { if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) return Forbid(); var idUser = User.GetUserId(); if (!idUser.HasValue) return Forbid(); row.IdUser = idUser.Value; row.IdWell = idWell; var result = await trajectoryFactRepository.AddAsync(row, token); return Ok(result); } /// /// Изменить выбранную строку с координатами /// /// /// /// /// /// количество успешно обновленных строк в БД [HttpPut("{idRow}")] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] public async Task UpdateAsync(int idWell, int idRow, [FromBody] TrajectoryGeoFactDto row, CancellationToken token) { if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) return Forbid(); int? idUser = User.GetUserId(); if (!idUser.HasValue) return Forbid(); row.Id = idRow; row.IdUser = idUser.Value; row.IdWell = idWell; var result = await trajectoryFactRepository.UpdateAsync(row, token); return Ok(result); } /// /// Удалить выбранную строку с координатами /// /// /// /// /// количество успешно удаленных строк из БД [HttpDelete("{idRow}")] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] public async Task DeleteAsync(int idWell, int idRow, CancellationToken token) { if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) return Forbid(); var result = await trajectoryFactRepository.DeleteRangeAsync(new int[] { idRow }, token); return Ok(result); } /// /// Формируем 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) { if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) return Forbid(); var stream = await factTrajectoryImportService.ExportAsync(idWell, token); var fileName = await factTrajectoryImportService.GetFileNameAsync(idWell, token); return File(stream, "application/octet-stream", fileName); } /// /// Возвращает excel шаблон для заполнения строк фактической траектории /// /// Запрашиваемый файл [HttpGet("template")] [AllowAnonymous] [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] [ProducesResponseType(StatusCodes.Status204NoContent)] public IActionResult GetTemplate() { var stream = factTrajectoryImportService.GetTemplateFile(); var fileName = "ЕЦП_шаблон_файла_фактическая_импортируемая_траектория.xlsx"; return File(stream, "application/octet-stream", fileName); } /// /// Импортирует координаты из excel (xlsx) файла /// /// id скважины /// Коллекция из одного файла xlsx /// Удалить операции перед импортом, если фал валидный /// Токен отмены задачи /// количество успешно записанных строк в БД [HttpPost("import/{deleteBeforeImport}")] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] public async Task ImportAsync(int idWell, [FromForm] IFormFileCollection files, bool deleteBeforeImport, CancellationToken token) { int? idUser = User.GetUserId(); if (!idUser.HasValue) return Forbid(); if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) return Forbid(); if (files.Count < 1) return this.ValidationBadRequest(nameof(files), "нет файла"); var file = files[0]; if (Path.GetExtension(file.FileName).ToLower() != ".xlsx") return this.ValidationBadRequest(nameof(files), "Требуется xlsx файл."); using Stream stream = file.OpenReadStream(); try { var trajectoryRows = await factTrajectoryImportService.ImportAsync(idWell, idUser.Value, stream, token); if (deleteBeforeImport) await trajectoryFactRepository.DeleteByIdWellAsync(idWell, token); var rowsCount = await trajectoryFactRepository.AddRangeAsync(trajectoryRows, token); return Ok(rowsCount); } catch (FileFormatException ex) { return this.ValidationBadRequest(nameof(files), ex.Message); } } private async Task CanUserAccessToWellAsync(int idWell, CancellationToken token) { int? idCompany = User.GetCompanyId(); return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token).ConfigureAwait(false); } }