diff --git a/AsbCloudApp/Data/TrajectoryGeoDto.cs b/AsbCloudApp/Data/TrajectoryGeoDto.cs index 1574666c..3f36aad6 100644 --- a/AsbCloudApp/Data/TrajectoryGeoDto.cs +++ b/AsbCloudApp/Data/TrajectoryGeoDto.cs @@ -11,6 +11,10 @@ namespace AsbCloudApp.Data /// public abstract class TrajectoryGeoDto { + /// + /// ИД строки с координатами + /// + public int Id { get; set; } /// /// Id скважины /// diff --git a/AsbCloudApp/Data/TrajectoryGeoFactDto.cs b/AsbCloudApp/Data/TrajectoryGeoFactDto.cs index 0245ec7c..a78811e4 100644 --- a/AsbCloudApp/Data/TrajectoryGeoFactDto.cs +++ b/AsbCloudApp/Data/TrajectoryGeoFactDto.cs @@ -7,11 +7,6 @@ namespace AsbCloudApp.Data; /// public class TrajectoryGeoFactDto : TrajectoryGeoDto { - /// - /// ИД строки с координатами - /// - public int Id { get; set; } - /// /// Радиус цели /// diff --git a/AsbCloudApp/Data/TrajectoryGeoPlanDto.cs b/AsbCloudApp/Data/TrajectoryGeoPlanDto.cs index 969b204a..ba9ffb86 100644 --- a/AsbCloudApp/Data/TrajectoryGeoPlanDto.cs +++ b/AsbCloudApp/Data/TrajectoryGeoPlanDto.cs @@ -6,11 +6,6 @@ namespace AsbCloudApp.Data /// public class TrajectoryGeoPlanDto: TrajectoryGeoDto { - /// - /// ИД строки с координатами - /// - public int Id { get; set; } - /// /// Радиус цели /// diff --git a/AsbCloudInfrastructure/Services/Trajectory/FactTrajectoryImportService.cs b/AsbCloudInfrastructure/Services/Trajectory/FactTrajectoryImportService.cs index 64699835..95b39bfc 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/FactTrajectoryImportService.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/FactTrajectoryImportService.cs @@ -10,7 +10,7 @@ namespace AsbCloudInfrastructure.Services.Trajectory { public override string templateFileName { get; set; } = "FactTrajectoryTemplate.xlsx"; public override string usingTemplateFile { get; set; } = "AsbCloudInfrastructure.Services.Trajectory"; - public override string sheetNamePlannedTrajectory { get; set; } = "Плановая траектория"; + public override string sheetNamePlannedTrajectory { get; set; } = "Фактическая траектория"; public override int headerRowsCount { get; set; } = 2; public override int ColumnWellboreDepth { get; set; } = 1; public override int ColumnZenithAngle { get; set; } = 2; diff --git a/AsbCloudWebApi/Controllers/Trajectory/FactTrajectoryController.cs b/AsbCloudWebApi/Controllers/Trajectory/FactTrajectoryController.cs index 73716012..6504da73 100644 --- a/AsbCloudWebApi/Controllers/Trajectory/FactTrajectoryController.cs +++ b/AsbCloudWebApi/Controllers/Trajectory/FactTrajectoryController.cs @@ -1,14 +1,7 @@ -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; @@ -16,194 +9,18 @@ namespace AsbCloudWebApi.Controllers.Trajectory; /// /// Фактическая траектория /// -[Authorize] [ApiController] [Route("api/well/{idWell}/[controller]")] -public class FactTrajectoryController : ControllerBase +public class FactTrajectoryController : TrajectoryController { - private readonly ITrajectoryEditableRepository factTrajectoryRepository; - private readonly IWellService wellService; - private readonly FactTrajectoryImportService factTrajectoryImportService; - - public FactTrajectoryController( - ITrajectoryEditableRepository trajectoryFactRepository, - IWellService wellService, - FactTrajectoryImportService factTrajectoryImportService) + public FactTrajectoryController(IWellService wellService, + FactTrajectoryImportService factTrajectoryImportService, + ITrajectoryEditableRepository trajectoryFactRepository) + : base( + wellService, + factTrajectoryImportService, + trajectoryFactRepository) { - this.factTrajectoryRepository = 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 factTrajectoryRepository.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 factTrajectoryRepository.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 factTrajectoryRepository.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 factTrajectoryRepository.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 factTrajectoryRepository.DeleteByIdWellAsync(idWell, token); - - var rowsCount = await factTrajectoryRepository.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); + fileName = "ЕЦП_шаблон_файла_фактическая_траектория.xlsx"; } } \ No newline at end of file diff --git a/AsbCloudWebApi/Controllers/Trajectory/PlannedTrajectoryController.cs b/AsbCloudWebApi/Controllers/Trajectory/PlannedTrajectoryController.cs index 40759b1c..01b87365 100644 --- a/AsbCloudWebApi/Controllers/Trajectory/PlannedTrajectoryController.cs +++ b/AsbCloudWebApi/Controllers/Trajectory/PlannedTrajectoryController.cs @@ -2,11 +2,8 @@ using AsbCloudApp.Repositories; using AsbCloudApp.Services; using AsbCloudInfrastructure.Services.Trajectory; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; -using System.IO; using System.Threading; using System.Threading.Tasks; @@ -18,216 +15,23 @@ namespace AsbCloudWebApi.Controllers.Trajectory /// [Route("api/well/{idWell}/plannedTrajectory")] [ApiController] - [Authorize] - public class PlannedTrajectoryController : ControllerBase + public class PlannedTrajectoryController : TrajectoryController { - private readonly IWellService wellService; - private readonly PlannedTrajectoryImportService plannedTrajectoryImportService; - private readonly ITrajectoryEditableRepository plannedTrajectoryRepository; private readonly TrajectoryService trajectoryVisualizationService; public PlannedTrajectoryController(IWellService wellService, PlannedTrajectoryImportService plannedTrajectoryImportService, ITrajectoryEditableRepository plannedTrajectoryRepository, TrajectoryService trajectoryVisualizationService) + : base( + wellService, + plannedTrajectoryImportService, + plannedTrajectoryRepository) { - this.plannedTrajectoryImportService = plannedTrajectoryImportService; - this.wellService = wellService; - this.plannedTrajectoryRepository = plannedTrajectoryRepository; + fileName = "ЕЦП_шаблон_файла_плановая_траектория.xlsx"; this.trajectoryVisualizationService = trajectoryVisualizationService; } - /// - /// Возвращает excel шаблон для заполнения строк плановой траектории - /// - /// Запрашиваемый файл - [HttpGet("template")] - [AllowAnonymous] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] - [ProducesResponseType(StatusCodes.Status204NoContent)] - public IActionResult GetTemplate() - { - var stream = plannedTrajectoryImportService.GetTemplateFile(); - var fileName = "ЕЦП_шаблон_файла_плановая_траектория.xlsx"; - return File(stream, "application/octet-stream", fileName); - } - - /// - /// Формируем 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 plannedTrajectoryImportService.ExportAsync(idWell, token); - var fileName = await plannedTrajectoryImportService.GetFileNameAsync(idWell, token); - 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 plannedTrajectoryImportService.ImportAsync(idWell, idUser.Value, stream, token); - - if (deleteBeforeImport) - await plannedTrajectoryRepository.DeleteByIdWellAsync(idWell, token); - - var rowsCount = await plannedTrajectoryRepository.AddRangeAsync(trajectoryRows, token); - - return Ok(rowsCount); - } - catch (FileFormatException ex) - { - return this.ValidationBadRequest(nameof(files), ex.Message); - } - } - - /// - /// Получаем список всех строк координат плановой траектории (для клиента) - /// - /// id скважины - /// Токен отмены задачи - /// Список добавленных координат плановой траектории - [HttpGet] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetAsync([FromRoute] int idWell, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, - token).ConfigureAwait(false)) - return Forbid(); - var result = await plannedTrajectoryRepository.GetAsync(idWell, token); - return Ok(result); - } - - /// - /// Добавить одну новую строчку координат для плановой траектории - /// - /// - /// - /// - /// количество успешно записанных строк в БД - [HttpPost] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task AddAsync(int idWell, [FromBody] TrajectoryGeoPlanDto 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 plannedTrajectoryRepository.AddAsync(row, token); - return Ok(result); - } - - /// - /// Добавить массив строчек координат для плановой траектории - /// - /// - /// - /// - /// количество успешно записанных строк в БД - [HttpPost("range")] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task AddRangeAsync(int idWell, [FromBody] IEnumerable rows, - CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - int? idUser = User.GetUserId(); - if (!idUser.HasValue) - return Forbid(); - foreach (var item in rows) - { - item.IdUser = idUser.Value; - item.IdWell = idWell; - } - var result = await plannedTrajectoryRepository.AddRangeAsync(rows, token); - return Ok(result); - } - - /// - /// Изменить выбранную строку с координатами - /// - /// - /// - /// - /// - /// количество успешно обновленных строк в БД - [HttpPut("{idRow}")] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task UpdateAsync(int idWell, int idRow, - [FromBody] TrajectoryGeoPlanDto 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 plannedTrajectoryRepository.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 plannedTrajectoryRepository.DeleteRangeAsync(new int[] { idRow }, token); - - return Ok(result); - } - /// /// Получение координат для визуализации траектории (плановой и фактической) /// @@ -238,20 +42,13 @@ namespace AsbCloudWebApi.Controllers.Trajectory [ProducesResponseType(typeof(PlanFactBase, IEnumerable, IEnumerable>), (int)System.Net.HttpStatusCode.OK)] public async Task GetTrajectoryCartesianPlanFactAsync(int idWell, CancellationToken token) { - if (!await CanUserAccessToWellAsync(idWell, + if (!await base.CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) return Forbid(); var result = await trajectoryVisualizationService.GetTrajectoryCartesianAsync(idWell, token); return Ok(result); } - - 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); - } } } diff --git a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryController.cs b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryController.cs new file mode 100644 index 00000000..8bd2cca6 --- /dev/null +++ b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryController.cs @@ -0,0 +1,237 @@ +using AsbCloudApp.Data; +using AsbCloudApp.Repositories; +using AsbCloudApp.Services; +using AsbCloudInfrastructure.Services.Trajectory; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudWebApi.Controllers.Trajectory +{ + + /// + /// Плановые и фактические траектории (загрузка и хранение) + /// + [ApiController] + [Authorize] + public abstract class TrajectoryController : ControllerBase + where Tdto : TrajectoryGeoDto + { + protected string fileName; + + private readonly IWellService wellService; + private readonly TrajectoryImportService trajectoryImportService; + private readonly ITrajectoryEditableRepository trajectoryRepository; + + public TrajectoryController(IWellService wellService, + TrajectoryImportService trajectoryImportService, + ITrajectoryEditableRepository trajectoryRepository) + { + this.trajectoryImportService = trajectoryImportService; + this.wellService = wellService; + this.trajectoryRepository = trajectoryRepository; + } + + /// + /// Возвращает excel шаблон для заполнения строк траектории + /// + /// Запрашиваемый файл + [HttpGet("template")] + [AllowAnonymous] + [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public IActionResult GetTemplate() + { + var stream = trajectoryImportService.GetTemplateFile(); + return File(stream, "application/octet-stream", fileName); + } + + /// + /// Формируем 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 trajectoryImportService.ExportAsync(idWell, token); + var fileName = await trajectoryImportService.GetFileNameAsync(idWell, token); + 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 trajectoryImportService.ImportAsync(idWell, idUser.Value, stream, token); + + if (deleteBeforeImport) + await trajectoryRepository.DeleteByIdWellAsync(idWell, token); + + var rowsCount = await trajectoryRepository.AddRangeAsync(trajectoryRows, token); + + return Ok(rowsCount); + } + catch (FileFormatException ex) + { + return this.ValidationBadRequest(nameof(files), ex.Message); + } + } + + /// + /// Получаем список всех строк координат траектории (для клиента) + /// + /// id скважины + /// Токен отмены задачи + /// Список добавленных координат траектории + [HttpGet] + //[ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public virtual async Task GetAsync([FromRoute] int idWell, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, + token).ConfigureAwait(false)) + return Forbid(); + var result = await trajectoryRepository.GetAsync(idWell, token); + return Ok(result); + } + + /// + /// Добавить одну новую строчку координат для плановой траектории + /// + /// + /// + /// + /// количество успешно записанных строк в БД + [HttpPost] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task AddAsync(int idWell, [FromBody] Tdto 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 trajectoryRepository.AddAsync(row, token); + return Ok(result); + } + + /// + /// Добавить массив строчек координат для плановой траектории + /// + /// + /// + /// + /// количество успешно записанных строк в БД + [HttpPost("range")] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task AddRangeAsync(int idWell, [FromBody] IEnumerable rows, + CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); + int? idUser = User.GetUserId(); + if (!idUser.HasValue) + return Forbid(); + foreach (var item in rows) + { + item.IdUser = idUser.Value; + item.IdWell = idWell; + } + var result = await trajectoryRepository.AddRangeAsync(rows, token); + return Ok(result); + } + + /// + /// Изменить выбранную строку с координатами + /// + /// + /// + /// + /// + /// количество успешно обновленных строк в БД + [HttpPut("{idRow}")] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task UpdateAsync(int idWell, int idRow, + [FromBody] Tdto 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 trajectoryRepository.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 trajectoryRepository.DeleteRangeAsync(new int[] { idRow }, token); + + return Ok(result); + } + + protected 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); + } + } + +}