DD.WellWorkover.Cloud/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanBaseController.cs

363 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using AsbCloudApp.Data;
using AsbCloudApp.Data.ProcessMaps;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Requests.ExportOptions;
using AsbCloudApp.Requests.ParserOptions;
using AsbCloudApp.Services;
using AsbCloudApp.Services.Export;
using AsbCloudApp.Services.Parsers;
using AsbCloudDb.Model.ProcessMapPlan;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudWebApi.Controllers.ProcessMaps;
/// <summary>
/// РТК план базовый
/// </summary>
[ApiController]
[Route("api/well/{idWell}/[controller]")]
[Authorize]
public abstract class ProcessMapPlanBaseController<TEntity, TDto> : ControllerBase
where TEntity : ProcessMapPlanBase
where TDto : ProcessMapPlanBaseDto
{
private readonly IChangeLogRepository<TDto, ProcessMapPlanBaseRequestWithWell> repository;
private readonly IWellService wellService;
private readonly IParserService<TDto, WellRelatedParserRequest> parserService;
private readonly ITelemetryService telemetryService;
private readonly IExportService<WellRelatedExportRequest> processMapPlanExportService;
protected ProcessMapPlanBaseController(IChangeLogRepository<TDto, ProcessMapPlanBaseRequestWithWell> repository,
IWellService wellService,
IParserService<TDto, WellRelatedParserRequest> parserService,
IExportService<WellRelatedExportRequest> processMapPlanExportService,
ITelemetryService telemetryService)
{
this.repository = repository;
this.wellService = wellService;
this.parserService = parserService;
this.telemetryService = telemetryService;
this.processMapPlanExportService = processMapPlanExportService;
}
protected abstract string TemplateFileName { get; }
/// <summary>
/// Добавление
/// </summary>
/// <param name="idWell"></param>
/// <param name="dtos"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpPost]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> InsertRange([FromRoute][Range(0, int.MaxValue)] int idWell, IEnumerable<TDto> 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);
}
/// <summary>
/// Удалить все по скважине и добавить новые
/// </summary>
/// <param name="idWell"></param>
/// <param name="dtos"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpPost("replace")]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> ClearAndInsertRange([FromRoute] int idWell, IEnumerable<TDto> 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);
}
/// <summary>
/// Пометить записи как удаленные
/// </summary>
/// <param name="idWell"></param>
/// <param name="ids"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpDelete]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> MarkAsDeleted([FromRoute] int idWell, IEnumerable<int> ids, CancellationToken token)
{
var idUser = await AssertUserHasAccessToWell(idWell, token);
var result = await repository.MarkAsDeleted(idUser, ids, token);
return Ok(result);
}
/// <summary>
/// Очистка
/// </summary>
/// <param name="idWell"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpDelete("clear")]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> 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);
}
/// <summary>
/// Получение текущих записей по параметрам
/// </summary>
/// <param name="idWell"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<IEnumerable<TDto>>> GetCurrent([FromRoute] int idWell, CancellationToken token)
{
await AssertUserHasAccessToWell(idWell, token);
var serviceRequest = new ProcessMapPlanBaseRequestWithWell(idWell);
var result = await repository.GetCurrent(serviceRequest, token);
return Ok(result);
}
/// <summary>
/// Получение измененных записей за определенную дату по ключу скважины
/// </summary>
/// <param name="idWell"></param>
/// <param name="moment"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpGet("changelogByMoment")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<IEnumerable<ChangeLogDto<TDto>>>> GetChangeLogByMoment([FromRoute] int idWell, DateTimeOffset? moment, CancellationToken token)
{
await AssertUserHasAccessToWell(idWell, token);
var dataRequest = new ProcessMapPlanBaseRequestWithWell(idWell);
var changeLogRequest = new ChangeLogRequest()
{
Moment = moment
};
var builder = repository
.GetQueryBuilder(changeLogRequest)
.ApplyRequest(dataRequest);
var dtos = await builder.GetChangeLogData(token);
return Ok(dtos);
}
/// <summary>
/// Получение записей за определенную дату по uid
/// </summary>
/// <param name="uid"></param>
/// <param name="updateFrom"></param>
/// <param name="token"></param>
/// <returns></returns>
[AllowAnonymous]
[HttpGet("/api/telemetry/{uid}/[controller]")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<IEnumerable<ChangeLogDto<TDto>>>> GetByUid(string uid, DateTimeOffset? updateFrom, CancellationToken token)
{
var idWell = telemetryService.GetIdWellByTelemetryUid(uid) ?? -1;
if (idWell < 0)
return this.ValidationBadRequest(nameof(uid), "Скважина по uid не найдена");
var serviceRequest = new ProcessMapPlanBaseRequestWithWell(idWell)
{
UpdateFrom = updateFrom,
};
var result = await repository.GetChangeLogForDate(serviceRequest, null, token);
return Ok(result);
}
/// <summary>
/// Изменения за определенную дату
/// </summary>
/// <param name="idWell"></param>
/// <param name="date"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpGet("changeLogForDate")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<IEnumerable<ChangeLogDto<TDto>>>> GetChangeLogForDate([FromRoute] int idWell, [FromQuery] DateOnly? date, CancellationToken token)
{
await AssertUserHasAccessToWell(idWell, token);
var serviceRequest = new ProcessMapPlanBaseRequestWithWell(idWell);
var result = await repository.GetChangeLogForDate(serviceRequest, date, token);
return Ok(result);
}
/// <summary>
/// Даты за которые есть изменения
/// </summary>
/// <param name="idWell"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpGet("dates")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<IEnumerable<DateOnly>>> 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);
}
/// <summary>
/// Редактирование или добавление [для пакетного редактирования]
/// </summary>
/// <param name="idWell"></param>
/// <param name="dtos"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpPut()]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> UpdateOrInsertRange([FromRoute] int idWell, IEnumerable<TDto> 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);
}
/// <summary>
/// Импорт РТК из excel (xlsx) файла
/// </summary>
/// <param name="idWell"></param>
/// <param name="file"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpPost("parse")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<ActionResult<ParserResultDto<TDto>>> 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);
}
}
/// <summary>
/// Получение шаблона для заполнения РТК
/// </summary>
/// <returns></returns>
[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);
}
/// <summary>
/// returns user id, if he has access to well
/// </summary>
/// <param name="idWell"></param>
/// <param name="token"></param>
/// <returns></returns>
/// <exception cref="ForbidException"></exception>
private async Task<int> 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;
}
/// <summary>
/// Формируем excel файл с текущими строками РТК
/// </summary>
/// <param name="idWell">id скважины</param>
/// <param name="token"></param>
/// <returns>Запрашиваемый файл</returns>
[HttpGet("export")]
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<IActionResult> 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);
}
/// <summary>
/// returns user id or throw
/// </summary>
/// <returns></returns>
/// <exception cref="ForbidException"></exception>
private int GetUserId()
{
var idUser = User.GetUserId() ?? throw new ForbidException("Неизвестный пользователь");
return idUser;
}
}