Рефакторинг контроллеров

1. Добавлен метод расширения для парсинга Excel файлов
2. Рефакторинг контроллеров траекторий
This commit is contained in:
Степанов Дмитрий 2024-01-29 15:39:39 +05:00
parent 82650b1cfb
commit 4874a9288b
4 changed files with 170 additions and 141 deletions

View File

@ -2,14 +2,15 @@
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using AsbCloudInfrastructure.Services.Trajectory.Export;
using AsbCloudInfrastructure.Services.Trajectory.Import;
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;
using AsbCloudApp.Data;
using AsbCloudApp.Requests.Import;
using AsbCloudInfrastructure.Services;
namespace AsbCloudWebApi.Controllers.Trajectory
{
@ -21,26 +22,27 @@ namespace AsbCloudWebApi.Controllers.Trajectory
[Authorize]
public abstract class TrajectoryEditableController<TDto> : TrajectoryController<TDto>
where TDto : TrajectoryGeoDto
{
private readonly TrajectoryParserService<TDto> trajectoryImportService;
private readonly TrajectoryExportService<TDto> trajectoryExportService;
{
private readonly ParserServiceFactory parserServiceFactory;
private readonly TrajectoryExportService<TDto> trajectoryExportService;
private readonly ITrajectoryEditableRepository<TDto> trajectoryRepository;
public TrajectoryEditableController(IWellService wellService,
TrajectoryParserService<TDto> trajectoryImportService,
TrajectoryExportService<TDto> trajectoryExportService,
protected TrajectoryEditableController(IWellService wellService,
ParserServiceFactory parserServiceFactory,
TrajectoryExportService<TDto> trajectoryExportService,
ITrajectoryEditableRepository<TDto> trajectoryRepository)
: base(
wellService,
trajectoryExportService,
trajectoryRepository)
{
this.trajectoryImportService = trajectoryImportService;
this.trajectoryExportService = trajectoryExportService;
this.trajectoryExportService = trajectoryExportService;
this.trajectoryRepository = trajectoryRepository;
this.parserServiceFactory = parserServiceFactory;
}
}
protected abstract TrajectoryParserRequest ParserOptions { get; }
/// <summary>
/// Возвращает excel шаблон для заполнения строк траектории
/// </summary>
@ -55,56 +57,32 @@ namespace AsbCloudWebApi.Controllers.Trajectory
return File(stream, "application/octet-stream", fileName);
}
/// <summary>
/// Импортирует координаты из excel (xlsx) файла
/// </summary>
/// <param name="idWell">id скважины</param>
/// <param name="files">Коллекция из одного файла xlsx</param>
/// <param name="deleteBeforeImport">Удалить операции перед импортом, если фал валидный</param>
/// <param name="token"> Токен отмены задачи </param>
/// <returns>количество успешно записанных строк в БД</returns>
[HttpPost("import/{deleteBeforeImport}")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)]
public async Task<IActionResult> 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();
/// <summary>
/// Импортирует координаты из excel (xlsx) файла
/// </summary>
/// <param name="idWell">id скважины</param>
/// <param name="files">Коллекция из одного файла xlsx</param>
/// <param name="token"> Токен отмены задачи </param>
/// <returns>количество успешно записанных строк в БД</returns>
[HttpPost("parse")]
[ProducesResponseType((int)System.Net.HttpStatusCode.OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)]
public async Task<ActionResult<ParserResultDto<TDto>>> Parse(int idWell,
[FromForm] IFormFileCollection files,
CancellationToken token)
{
var idUser = User.GetUserId();
try
{
var trajectoryRows = trajectoryImportService.Import(stream);
foreach (var row in trajectoryRows)
{
row.IdWell = idWell;
row.IdUser = idUser.Value;
}
if (!idUser.HasValue)
return Forbid();
if (deleteBeforeImport)
await trajectoryRepository.DeleteByIdWellAsync(idWell, token);
if (!await CanUserAccessToWellAsync(idWell, token))
return Forbid();
var rowsCount = await trajectoryRepository.AddRangeAsync(trajectoryRows, token);
var parserService = parserServiceFactory.Create<TDto, TrajectoryParserRequest>(ParserOptions.IdParserService);
return Ok(rowsCount);
}
catch (FileFormatException ex)
{
return this.ValidationBadRequest(nameof(files), ex.Message);
}
}
return this.ParseExcelFile(files, ParserOptions, parserService);
}
/// <summary>
@ -130,31 +108,41 @@ namespace AsbCloudWebApi.Controllers.Trajectory
return Ok(result);
}
/// <summary>
/// Добавить массив строчек координат для плановой траектории
/// </summary>
/// <param name="idWell"></param>
/// <param name="rows"></param>
/// <param name="token"></param>
/// <returns>количество успешно записанных строк в БД</returns>
[HttpPost("range")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> AddRangeAsync(int idWell, [FromBody] IEnumerable<TDto> 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);
}
/// <summary>
/// Добавить массив строчек координат для плановой траектории
/// </summary>
/// <param name="idWell"></param>
/// <param name="dtos"></param>
/// <param name="deleteBeforeInsert"></param>
/// <param name="token"></param>
/// <returns>количество успешно записанных строк в БД</returns>
[HttpPost("range/{deleteBeforeInsert:bool}")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> AddRangeAsync(int idWell,
[FromBody] IEnumerable<TDto> dtos,
bool deleteBeforeInsert,
CancellationToken token)
{
if (!await CanUserAccessToWellAsync(idWell, token))
return Forbid();
var idUser = User.GetUserId();
if (!idUser.HasValue)
return Forbid();
foreach (var dto in dtos)
{
dto.IdUser = idUser.Value;
dto.IdWell = idWell;
}
if (deleteBeforeInsert)
await trajectoryRepository.DeleteByIdWellAsync(idWell, token);
var result = await trajectoryRepository.AddRangeAsync(dtos, token);
return Ok(result);
}
/// <summary>
/// Изменить выбранную строку с координатами
@ -201,4 +189,4 @@ namespace AsbCloudWebApi.Controllers.Trajectory
return Ok(result);
}
}
}
}

View File

@ -1,8 +1,9 @@
using AsbCloudApp.Data.Trajectory;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests.Import;
using AsbCloudApp.Services;
using AsbCloudInfrastructure.Services;
using AsbCloudInfrastructure.Services.Trajectory.Export;
using AsbCloudInfrastructure.Services.Trajectory.Import;
using Microsoft.AspNetCore.Mvc;
namespace AsbCloudWebApi.Controllers.Trajectory;
@ -14,15 +15,20 @@ namespace AsbCloudWebApi.Controllers.Trajectory;
[Route("api/well/{idWell}/[controller]")]
public class TrajectoryFactManualController : TrajectoryEditableController<TrajectoryGeoFactDto>
{
protected override string fileName => "ЕЦП_шаблон_файлаактическая_траектория.xlsx";
public TrajectoryFactManualController(IWellService wellService,
TrajectoryFactManualParserService factTrajectoryImportService,
TrajectoryFactManualExportService factTrajectoryExportService,
ITrajectoryEditableRepository<TrajectoryGeoFactDto> trajectoryFactRepository)
: base(
wellService,
factTrajectoryImportService,
factTrajectoryExportService,
trajectoryFactRepository)
{ }
protected override string fileName => "ЕЦП_шаблон_файлаактическая_траектория.xlsx";
public TrajectoryFactManualController(IWellService wellService,
TrajectoryFactManualExportService trajectoryExportService,
ParserServiceFactory parserServiceFactory,
ITrajectoryEditableRepository<TrajectoryGeoFactDto> trajectoryRepository)
: base(wellService, parserServiceFactory, trajectoryExportService, trajectoryRepository)
{
}
protected override TrajectoryParserRequest ParserOptions => new()
{
IdParserService = ParserServiceFactory.IdTrajectoryFactManualParserService,
SheetName = "Фактическая траектория",
HeaderRowsCount = 2
};
}

View File

@ -2,58 +2,62 @@
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using AsbCloudInfrastructure.Services.Trajectory;
using AsbCloudInfrastructure.Services.Trajectory.Import;
using AsbCloudInfrastructure.Services.Trajectory.Export;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Requests.Import;
using AsbCloudInfrastructure.Services;
namespace AsbCloudWebApi.Controllers.Trajectory
{
/// <summary>
/// Плановая траектория (загрузка и хранение)
/// </summary>
[Route("api/well/{idWell}/[controller]")]
[ApiController]
public class TrajectoryPlanController : TrajectoryEditableController<TrajectoryGeoPlanDto>
{
private readonly TrajectoryService trajectoryVisualizationService;
/// <summary>
/// Плановая траектория (загрузка и хранение)
/// </summary>
[Route("api/well/{idWell}/[controller]")]
[ApiController]
public class TrajectoryPlanController : TrajectoryEditableController<TrajectoryGeoPlanDto>
{
private readonly TrajectoryService trajectoryVisualizationService;
protected override string fileName => "ЕЦП_шаблон_файла_плановая_траектория.xlsx";
protected override string fileName => "ЕЦП_шаблон_файла_плановая_траектория.xlsx";
public TrajectoryPlanController(IWellService wellService,
TrajectoryPlanExportService trajectoryExportService,
ParserServiceFactory parserServiceFactory,
ITrajectoryEditableRepository<TrajectoryGeoPlanDto> trajectoryRepository,
TrajectoryService trajectoryVisualizationService)
: base(wellService, parserServiceFactory, trajectoryExportService, trajectoryRepository)
{
this.trajectoryVisualizationService = trajectoryVisualizationService;
}
protected override TrajectoryParserRequest ParserOptions => new()
{
IdParserService = ParserServiceFactory.IdTrajectoryPlanParserService,
SheetName = "Плановая траектория",
HeaderRowsCount = 2
};
public TrajectoryPlanController(IWellService wellService,
TrajectoryPlanParserService trajectoryPlanImportService,
TrajectoryPlanExportService trajectoryPlanExportService,
ITrajectoryEditableRepository<TrajectoryGeoPlanDto> trajectoryPlanRepository,
TrajectoryService trajectoryVisualizationService)
: base(
wellService,
trajectoryPlanImportService,
trajectoryPlanExportService,
trajectoryPlanRepository)
{
this.trajectoryVisualizationService = trajectoryVisualizationService;
}
/// <summary>
/// Получение координат для визуализации траектории (плановой и фактической)
/// </summary>
/// <param name="idWell"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpGet("trajectoryCartesianPlanFact")]
[ProducesResponseType(
typeof(TrajectoryPlanFactDto<IEnumerable<TrajectoryCartesianPlanDto>, IEnumerable<TrajectoryCartesianFactDto>>),
(int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetTrajectoryCartesianPlanFactAsync(int idWell, CancellationToken token)
{
if (!await CanUserAccessToWellAsync(idWell,
token).ConfigureAwait(false))
return Forbid();
/// <summary>
/// Получение координат для визуализации траектории (плановой и фактической)
/// </summary>
/// <param name="idWell"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpGet("trajectoryCartesianPlanFact")]
[ProducesResponseType(typeof(TrajectoryPlanFactDto<IEnumerable<TrajectoryCartesianPlanDto>, IEnumerable<TrajectoryCartesianFactDto>>), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetTrajectoryCartesianPlanFactAsync(int idWell, CancellationToken token)
{
if (!await CanUserAccessToWellAsync(idWell,
token).ConfigureAwait(false))
return Forbid();
var result = await trajectoryVisualizationService.GetTrajectoryCartesianAsync(idWell, token);
return Ok(result);
}
}
}
var result = await trajectoryVisualizationService.GetTrajectoryCartesianAsync(idWell, token);
return Ok(result);
}
}
}

View File

@ -3,7 +3,12 @@ using AsbCloudWebApi.Converters;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Security.Claims;
using AsbCloudApp.Data;
using AsbCloudApp.Requests.Import;
using AsbCloudApp.Services;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Mvc
{
@ -59,6 +64,32 @@ namespace Microsoft.AspNetCore.Mvc
return options;
}
}
}
public static ActionResult<ParserResultDto<TDto>> ParseExcelFile<TDto, TOptions>(this ControllerBase controller,
IFormFileCollection files,
TOptions options,
IParserService<TDto, TOptions> parserService)
where TDto : class, IId
where TOptions : ParserOptionsRequestBase
{
if (files.Count < 1)
return controller.ValidationBadRequest(nameof(files), "Нет файла");
var file = files[0];
if (Path.GetExtension(file.FileName).ToLower() != ".xlsx")
return controller.ValidationBadRequest(nameof(files), "Требуется .xlsx файл.");
using var stream = file.OpenReadStream();
try
{
var items = parserService.Parse(stream, options);
return controller.Ok(items);
}
catch (FileFormatException ex)
{
return controller.ValidationBadRequest(nameof(files), ex.Message);
}
}
}
}