Редактирование автоопределенных операций

This commit is contained in:
Степанов Дмитрий 2024-04-01 13:32:48 +03:00
parent 69ec6cc765
commit 14a07fd5d5
10 changed files with 10092 additions and 515 deletions

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
namespace AsbCloudApp.Data.DetectedOperation; namespace AsbCloudApp.Data.DetectedOperation;
@ -28,8 +29,7 @@ public class DetectedOperationDto: IId
/// <summary> /// <summary>
/// Id пользователя панели на момент начала операции /// Id пользователя панели на момент начала операции
/// </summary> /// </summary>
[Required] public int? IdUserAtStart { get; set; }
public int IdUserAtStart { get; set; }
/// <summary> /// <summary>
/// Пользователь панели оператора /// Пользователь панели оператора
@ -75,8 +75,8 @@ public class DetectedOperationDto: IId
/// <summary> /// <summary>
/// название/описание операции /// название/описание операции
/// </summary> /// </summary>
[Required] [JsonIgnore]
public WellOperationCategoryDto OperationCategory { get; set; } = null!; public WellOperationCategoryDto? OperationCategory { get; set; }
/// <summary> /// <summary>
/// Ключевой параметр операции /// Ключевой параметр операции

View File

@ -11,16 +11,16 @@ namespace AsbCloudApp.Repositories;
/// <summary> /// <summary>
/// Таблица автоматически определенных операций /// Таблица автоматически определенных операций
/// </summary> /// </summary>
public interface IDetectedOperationRepository : ICrudRepository<DetectedOperationDto> public interface IDetectedOperationRepository
{ {
/// <summary> /// <summary>
/// Добавление записей /// Добавление записей
/// </summary> /// </summary>
/// <param name="idUser"></param> /// <param name="idEditor"></param>
/// <param name="dtos"></param> /// <param name="dtos"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<int> Insert(int? idUser, IEnumerable<DetectedOperationDto> dtos, CancellationToken token); Task<int> InsertRange(int? idEditor, IEnumerable<DetectedOperationDto> dtos, CancellationToken token);
/// <summary> /// <summary>
/// Получить автоматически определенные операции по телеметрии /// Получить автоматически определенные операции по телеметрии
@ -33,38 +33,27 @@ public interface IDetectedOperationRepository : ICrudRepository<DetectedOperatio
/// <summary> /// <summary>
/// Редактирование записей /// Редактирование записей
/// </summary> /// </summary>
/// <param name="idUser"></param> /// <param name="idEditor"></param>
/// <param name="dtos"></param> /// <param name="dtos"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<int> Update(int idUser, IEnumerable<DetectedOperationDto> dtos, CancellationToken token); Task<int> UpdateRange(int idEditor, IEnumerable<DetectedOperationDto> dtos, CancellationToken token);
/// <summary>
/// Добавляет Dto у которых id == 0, изменяет dto у которых id != 0
/// </summary>
/// <param name="idUser"></param>
/// <param name="dtos"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> UpdateOrInsert(int idUser, IEnumerable<DetectedOperationDto> dtos, CancellationToken token);
/// <summary> /// <summary>
/// Удалить операции /// Удалить операции
/// </summary> /// </summary>
/// <param name="idUser"></param>
/// <param name="request"></param> /// <param name="request"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<int> Delete(int idUser, DetectedOperationByTelemetryRequest request, CancellationToken token); Task<int> Delete(DetectedOperationByTelemetryRequest request, CancellationToken token);
/// <summary> /// <summary>
/// Удаление записей /// Удаление записей
/// </summary> /// </summary>
/// <param name="idUser"></param>
/// <param name="ids"></param> /// <param name="ids"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<int> DeleteRange(int idUser, IEnumerable<int> ids, CancellationToken token); Task<int> DeleteRange(IEnumerable<int> ids, CancellationToken token);
/// <summary> /// <summary>
/// Получение дат последних определённых операций /// Получение дат последних определённых операций

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,64 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace AsbCloudDb.Migrations
{
/// <inheritdoc />
public partial class Update_DetectedOperation : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<int>(
name: "id_user",
table: "t_detected_operation",
type: "integer",
nullable: true,
comment: "Id пользователя по телеметрии на момент начала операции",
oldClrType: typeof(int),
oldType: "integer",
oldComment: "Id пользователя по телеметрии на момент начала операции");
migrationBuilder.AddColumn<DateTimeOffset>(
name: "creation",
table: "t_detected_operation",
type: "timestamp with time zone",
nullable: false,
defaultValue: new DateTimeOffset(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), new TimeSpan(0, 0, 0, 0, 0)),
comment: "дата создания");
migrationBuilder.AddColumn<int>(
name: "id_editor",
table: "t_detected_operation",
type: "integer",
nullable: true,
comment: "Редактор");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "creation",
table: "t_detected_operation");
migrationBuilder.DropColumn(
name: "id_editor",
table: "t_detected_operation");
migrationBuilder.AlterColumn<int>(
name: "id_user",
table: "t_detected_operation",
type: "integer",
nullable: false,
defaultValue: 0,
comment: "Id пользователя по телеметрии на момент начала операции",
oldClrType: typeof(int),
oldType: "integer",
oldNullable: true,
oldComment: "Id пользователя по телеметрии на момент начала операции");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,12 @@ namespace AsbCloudDb.Model
[Column("id_category"), Comment("Id категории операции")] [Column("id_category"), Comment("Id категории операции")]
public int IdCategory { get; set; } public int IdCategory { get; set; }
[Column("id_editor"), Comment("Редактор")]
public int? IdEditor { get; set; }
[Column("creation"), Comment("дата создания")]
public DateTimeOffset Creation { get; set; }
[Column("date_start", TypeName = "timestamp with time zone"), Comment("Дата начала операции")] [Column("date_start", TypeName = "timestamp with time zone"), Comment("Дата начала операции")]
public DateTimeOffset DateStart { get; set; } public DateTimeOffset DateStart { get; set; }
@ -27,7 +33,7 @@ namespace AsbCloudDb.Model
public DateTimeOffset DateEnd { get; set; } public DateTimeOffset DateEnd { get; set; }
[Column("id_user"), Comment("Id пользователя по телеметрии на момент начала операции")] [Column("id_user"), Comment("Id пользователя по телеметрии на момент начала операции")]
public int IdUsersAtStart { get; set; } public int? IdUsersAtStart { get; set; }
[NotMapped] [NotMapped]
public double DurationMinutes => (DateEnd - DateStart).TotalMinutes; public double DurationMinutes => (DateEnd - DateStart).TotalMinutes;

View File

@ -12,29 +12,30 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.ChangeTracking;
namespace AsbCloudInfrastructure.Repository; namespace AsbCloudInfrastructure.Repository;
public class DetectedOperationRepository : CrudRepositoryBase<DetectedOperationDto, DetectedOperation>, public class DetectedOperationRepository : IDetectedOperationRepository
IDetectedOperationRepository
{ {
private readonly IAsbCloudDbContext dbContext;
private readonly ITelemetryService telemetryService; private readonly ITelemetryService telemetryService;
public DetectedOperationRepository(IAsbCloudDbContext context, public DetectedOperationRepository(IAsbCloudDbContext dbContext,
ITelemetryService telemetryService) ITelemetryService telemetryService)
: base(context)
{ {
this.dbContext = dbContext;
this.telemetryService = telemetryService; this.telemetryService = telemetryService;
} }
public async Task<int> Delete(int idUser, DetectedOperationByTelemetryRequest request, CancellationToken token) public async Task<int> Delete(DetectedOperationByTelemetryRequest request, CancellationToken token)
{ {
var query = BuildQuery(request); var query = BuildQuery(request);
dbContext.Set<DetectedOperation>().RemoveRange(query); dbContext.Set<DetectedOperation>().RemoveRange(query);
return await dbContext.SaveChangesAsync(token); return await dbContext.SaveChangesAsync(token);
} }
public async Task<int> DeleteRange(int idUser, IEnumerable<int> ids, CancellationToken token) public async Task<int> DeleteRange(IEnumerable<int> ids, CancellationToken token)
{ {
var query = dbContext.Set<DetectedOperation>() var query = dbContext.Set<DetectedOperation>()
.Where(e => ids.Contains( e.Id)); .Where(e => ids.Contains( e.Id));
@ -66,7 +67,7 @@ public class DetectedOperationRepository : CrudRepositoryBase<DetectedOperationD
return dtos; return dtos;
} }
public async Task<int> Insert(int? idUser, IEnumerable<DetectedOperationDto> dtos, CancellationToken token) public async Task<int> InsertRange(int? idEditor, IEnumerable<DetectedOperationDto> dtos, CancellationToken token)
{ {
if(!dtos.Any()) if(!dtos.Any())
return 0; return 0;
@ -75,6 +76,10 @@ public class DetectedOperationRepository : CrudRepositoryBase<DetectedOperationD
var dbset = dbContext.Set<DetectedOperation>(); var dbset = dbContext.Set<DetectedOperation>();
foreach(var entity in entities) foreach(var entity in entities)
{ {
if (idEditor.HasValue)
entity.IdEditor = idEditor.Value;
entity.Creation = DateTimeOffset.UtcNow;
entity.Id = default; entity.Id = default;
dbset.Add(entity); dbset.Add(entity);
} }
@ -82,7 +87,7 @@ public class DetectedOperationRepository : CrudRepositoryBase<DetectedOperationD
return await dbContext.SaveChangesWithExceptionHandling(token); return await dbContext.SaveChangesWithExceptionHandling(token);
} }
public async Task<int> Update(int idUser, IEnumerable<DetectedOperationDto> dtos, CancellationToken token) public async Task<int> UpdateRange(int idEditor, IEnumerable<DetectedOperationDto> dtos, CancellationToken token)
{ {
if (!dtos.Any()) if (!dtos.Any())
return 0; return 0;
@ -108,32 +113,22 @@ public class DetectedOperationRepository : CrudRepositoryBase<DetectedOperationD
throw new ArgumentInvalidException(nameof(dtos), "Все записи должны существовать в БД"); throw new ArgumentInvalidException(nameof(dtos), "Все записи должны существовать в БД");
var entities = dtos var entities = dtos
.Select(Convert) .Select(dto =>
{
var entity = Convert(dto);
entity.IdEditor = idEditor;
return entity;
})
.ToArray(); .ToArray();
var entries = new Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry<DetectedOperation>[entities.Length]; var entries = new EntityEntry<DetectedOperation>[entities.Length];
for(var i = 0; i < entities.Length; i++) for(var i = 0; i < entities.Length; i++)
entries[i] = dbSet.Update(entities[i]); entries[i] = dbSet.Update(entities[i]);
var result = await dbContext.SaveChangesWithExceptionHandling(token); var result = await dbContext.SaveChangesWithExceptionHandling(token);
for (var i = 0; i < entries.Length; i++) foreach (var entry in entries)
entries[i].State = EntityState.Detached; entry.State = EntityState.Detached;
return result;
}
public async Task<int> UpdateOrInsert(int idUser, IEnumerable<DetectedOperationDto> dtos, CancellationToken token)
{
var result = 0;
var itemsToInsert = dtos.Where(e => e.Id == 0);
if (itemsToInsert.Any())
result += await Insert(idUser, itemsToInsert, token);
var itemsToUpdate = dtos.Where(e => e.Id != 0);
if (itemsToUpdate.Any())
result += await Update(idUser, itemsToUpdate, token);
return result; return result;
} }
@ -182,7 +177,7 @@ public class DetectedOperationRepository : CrudRepositoryBase<DetectedOperationD
return query; return query;
} }
protected virtual DetectedOperationDto Convert(DetectedOperation src, TimeSpan offset) private static DetectedOperationDto Convert(DetectedOperation src, TimeSpan offset)
{ {
var dto = src.Adapt<DetectedOperationDto>(); var dto = src.Adapt<DetectedOperationDto>();
dto.DateStart = src.DateStart.ToOffset(offset); dto.DateStart = src.DateStart.ToOffset(offset);
@ -190,11 +185,11 @@ public class DetectedOperationRepository : CrudRepositoryBase<DetectedOperationD
return dto; return dto;
} }
protected override DetectedOperation Convert(DetectedOperationDto src) private static DetectedOperation Convert(DetectedOperationDto src)
{ {
var entity = src.Adapt<DetectedOperation>(); var entity = src.Adapt<DetectedOperation>();
entity.DateStart = src.DateStart.ToUniversalTime(); entity.DateStart = src.DateStart.ToUniversalTime();
entity.DateEnd = src.DateEnd.ToUniversalTime(); entity.DateEnd = src.DateEnd.ToUniversalTime();
return entity; return entity;
} }
} }

View File

@ -209,7 +209,7 @@ public class DetectedOperationService : IDetectedOperationService
return 0; return 0;
var requestByTelemetry = new DetectedOperationByTelemetryRequest(well.IdTelemetry.Value, request); var requestByTelemetry = new DetectedOperationByTelemetryRequest(well.IdTelemetry.Value, request);
var result = await operationRepository.Delete(-1, requestByTelemetry, token); var result = await operationRepository.Delete(requestByTelemetry, token);
return result; return result;
} }

View File

@ -48,7 +48,7 @@ public class WorkOperationDetection: Work
var detectedOperations = await detectedOperationService.DetectOperationsAsync(telemetryId, beginDate, token); var detectedOperations = await detectedOperationService.DetectOperationsAsync(telemetryId, beginDate, token);
if (detectedOperations.Any()) if (detectedOperations.Any())
await detectedOperationRepository.InsertRangeAsync(detectedOperations, token); await detectedOperationRepository.InsertRange(null, detectedOperations, token);
} }
} }
} }

View File

@ -7,137 +7,191 @@ using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudInfrastructure.Services.DetectOperations; using AsbCloudInfrastructure.Services.DetectOperations;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
namespace AsbCloudWebApi.Controllers.SAUB namespace AsbCloudWebApi.Controllers.SAUB
{ {
/// <summary> /// <summary>
/// Операции определенные по телеметрии САУБ /// Операции определенные по телеметрии САУБ
/// </summary> /// </summary>
[Route("api/[controller]")] [Route("api/well/{idWell}/[controller]")]
[ApiController] [ApiController]
[Authorize] [Authorize]
public class DetectedOperationController : ControllerBase public class DetectedOperationController : ControllerBase
{ {
private readonly IDetectedOperationService detectedOperationService; private readonly IDetectedOperationRepository detectedOperationRepository;
private readonly IWellService wellService; private readonly IDetectedOperationService detectedOperationService;
private readonly DetectedOperationExportService detectedOperationExportService; private readonly IWellService wellService;
private readonly DetectedOperationExportService detectedOperationExportService;
public DetectedOperationController(IDetectedOperationService detectedOperationService, IWellService wellService,
DetectedOperationExportService detectedOperationExportService)
{
this.detectedOperationService = detectedOperationService;
this.wellService = wellService;
this.detectedOperationExportService = detectedOperationExportService;
}
/// <summary> public DetectedOperationController(IDetectedOperationService detectedOperationService,
/// получить справочник операций. Отличается от операций заводимых вручную. IWellService wellService,
/// При задании id скважины вернет только те операции, которые определились в телеметрии этой скважины. DetectedOperationExportService detectedOperationExportService,
/// </summary> IDetectedOperationRepository detectedOperationRepository)
/// <param name="idWell">[опционально] id скважины</param> {
/// <param name="token"></param> this.detectedOperationService = detectedOperationService;
/// <returns></returns> this.wellService = wellService;
[HttpGet("categories")] this.detectedOperationExportService = detectedOperationExportService;
[ProducesResponseType(typeof(IEnumerable<WellOperationCategoryDto>), (int)System.Net.HttpStatusCode.OK)] this.detectedOperationRepository = detectedOperationRepository;
public async Task<IActionResult> GetCategoriesAsync([FromQuery] int? idWell, CancellationToken token) }
{
var result = await detectedOperationService.GetCategoriesAsync(idWell, token);
return Ok(result);
}
/// <summary> /// <summary>
/// Получить фильтрованный список операций по телеметрии САУБ /// Добавить операции
/// </summary> /// </summary>
/// <param name="request"></param> /// <param name="idWell"></param>
/// <param name="token"></param> /// <param name="dtos"></param>
/// <returns></returns> /// <param name="token"></param>
[HttpGet] /// <returns></returns>
[ProducesResponseType(typeof(DetectedOperationListDto), (int)System.Net.HttpStatusCode.OK)] [HttpPost]
public async Task<IActionResult> GetAsync( [ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[FromQuery] DetectedOperationByWellRequest request, public async Task<IActionResult> InsertRangeAsync(int idWell, IEnumerable<DetectedOperationDto> dtos, CancellationToken token)
CancellationToken token) {
{ var idUser = await AssertUserHasAccessToWellAsync(idWell, token);
if (!await UserHasAccessToWellAsync(request.IdWell, token))
return Forbid();
var result = await detectedOperationService.GetAsync(request, token); var result = await detectedOperationRepository.InsertRange(idUser, dtos, token);
return Ok(result);
}
/// <summary> return Ok(result);
/// Получить статистику по фильтрованному списку операций по телеметрии САУБ }
/// </summary>
/// <param name="request"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpGet("stat")]
[ProducesResponseType(typeof(IEnumerable<DetectedOperationStatDto>), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetStatAsync(
[FromQuery] DetectedOperationByWellRequest request,
CancellationToken token)
{
if (!await UserHasAccessToWellAsync(request.IdWell, token))
return Forbid();
var result = await detectedOperationService.GetOperationsStatAsync(request, token); /// <summary>
return Ok(result); /// Обновить операции
} /// </summary>
/// <param name="idWell"></param>
/// <param name="dtos"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpPut]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
public async Task<IActionResult> UpdateRangeAsync(int idWell, IEnumerable<DetectedOperationDto> dtos, CancellationToken token)
{
var idUser = await AssertUserHasAccessToWellAsync(idWell, token);
/// <summary> var result = await detectedOperationRepository.UpdateRange(idUser, dtos, token);
/// Удалить операции.
/// Удаленные операции будут определены повторно сервисом автоматизированного определения операций.
/// Может потребоваться при изменении алгоритмов определения
/// </summary>
/// <param name="request"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpDelete]
[Permission]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> DeleteAsync(
[FromQuery] DetectedOperationByWellRequest request,
CancellationToken token)
{
if (!await UserHasAccessToWellAsync(request.IdWell, token))
return Forbid();
var result = await detectedOperationService.DeleteAsync(request, token); return Ok(result);
return Ok(result); }
}
protected async Task<bool> UserHasAccessToWellAsync(int idWell, CancellationToken token) /// <summary>
{ /// Удалить операции
var idCompany = User.GetCompanyId(); /// </summary>
if (idCompany is not null && /// <param name="idWell"></param>
await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token) /// <param name="ids"></param>
.ConfigureAwait(false)) /// <param name="token"></param>
return true; /// <returns></returns>
return false; [HttpDelete]
} [ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
public async Task<IActionResult> DeleteRangeAsync(int idWell, IEnumerable<int> ids, CancellationToken token)
{
await AssertUserHasAccessToWellAsync(idWell, token);
/// <summary> var result = await detectedOperationRepository.DeleteRange(ids, token);
/// Создает excel файл с операциями по скважине
/// </summary>
/// <param name="idWell">id скважины</param>
/// <param name="token"></param>
[HttpGet("export")]
[Permission]
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)]
public async Task<IActionResult> ExportAsync(int idWell, CancellationToken token)
{
var idCompany = User.GetCompanyId();
if (idCompany is null) return Ok(result);
return Forbid(); }
var host = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}"; /// <summary>
var stream = await detectedOperationExportService.ExportAsync(idWell, host, token); /// получить справочник операций. Отличается от операций заводимых вручную.
/// При задании id скважины вернет только те операции, которые определились в телеметрии этой скважины.
return File(stream, "application/octet-stream", "operations.xlsx"); /// </summary>
} /// <param name="idWell">[опционально] id скважины</param>
} /// <param name="token"></param>
} /// <returns></returns>
[HttpGet]
[Route("/api/well/[controller]/categories")]
[ProducesResponseType(typeof(IEnumerable<WellOperationCategoryDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetCategoriesAsync([FromQuery] int? idWell, CancellationToken token)
{
var result = await detectedOperationService.GetCategoriesAsync(idWell, token);
return Ok(result);
}
/// <summary>
/// Получить фильтрованный список операций по телеметрии САУБ
/// </summary>
/// <param name="idWell"></param>
/// <param name="request"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpGet]
[ProducesResponseType(typeof(DetectedOperationDto), StatusCodes.Status200OK)]
public async Task<IActionResult> GetAsync(int idWell,
[FromQuery] DetectedOperationRequest request,
CancellationToken token)
{
await AssertUserHasAccessToWellAsync(idWell, token);
var well = await wellService.GetOrDefaultAsync(idWell, token);
if (well?.IdTelemetry is null)
return NoContent();
var requestToService = new DetectedOperationByTelemetryRequest(well.IdTelemetry.Value, request);
var result = await detectedOperationRepository.Get(requestToService, token);
return Ok(result);
}
/// <summary>
/// Получить статистику по фильтрованному списку операций по телеметрии САУБ
/// </summary>
/// <param name="idWell"></param>
/// <param name="request"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpGet("stat")]
[ProducesResponseType(typeof(IEnumerable<DetectedOperationStatDto>), StatusCodes.Status200OK)]
public async Task<IActionResult> GetStatAsync(int idWell, [FromQuery] DetectedOperationRequest request,
CancellationToken token)
{
await AssertUserHasAccessToWellAsync(idWell, token);
var requestToService = new DetectedOperationByWellRequest(idWell, request);
var result = await detectedOperationService.GetOperationsStatAsync(requestToService, token);
return Ok(result);
}
/// <summary>
/// Создает excel файл с операциями по скважине
/// </summary>
/// <param name="idWell">id скважины</param>
/// <param name="token"></param>
[HttpGet("export")]
[Permission]
[ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK, "application/octet-stream")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)]
public async Task<IActionResult> ExportAsync(int idWell, CancellationToken token)
{
var idCompany = User.GetCompanyId();
if (idCompany is null)
return Forbid();
var host = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}";
var stream = await detectedOperationExportService.ExportAsync(idWell, host, token);
return File(stream, "application/octet-stream", "operations.xlsx");
}
private async Task<int> AssertUserHasAccessToWellAsync(int idWell, CancellationToken token)
{
var idUser = User.GetUserId();
var idCompany = User.GetCompanyId();
if (!idUser.HasValue)
throw new ForbidException("Неизвестный пользователь");
if (!idCompany.HasValue)
throw new ForbidException("Нет доступа к скважине");
if (!await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, idWell, token))
throw new ForbidException("Нет доступа к скважине");
return idUser.Value;
}
}
}