Контроллер суточного отчёта

This commit is contained in:
Степанов Дмитрий 2023-11-03 19:37:14 +05:00
parent 0d468103ae
commit af5d713fc7

View File

@ -1,196 +1,224 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.DailyReport;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Data.DailyReport;
using AsbCloudApp.Data.DailyReport.Blocks;
using AsbCloudApp.Data.DailyReport.Blocks.Sign;
using AsbCloudApp.Data.DailyReport.Blocks.Subsystems;
using AsbCloudApp.Data.DailyReport.Blocks.TimeBalance;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudApp.Services.DailyReport;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace AsbCloudWebApi.Controllers
namespace AsbCloudWebApi.Controllers;
/// <summary>
/// Суточный отчёт
/// </summary>
[ApiController]
[Route("api/well/{idWell:int}/[controller]")]
[Authorize]
public class DailyReportController : ControllerBase
{
private readonly IWellOperationRepository wellOperationRepository;
private readonly IDailyReportService dailyReportService;
private readonly IDailyReportExportService dailyReportExportService;
private readonly IWellService wellService;
/// <summary>
/// Суточный рапорт
/// </summary>
[Route("api/well/{idWell}/[controller]")]
[ApiController]
[Authorize]
public class DailyReportController : ControllerBase
{
private readonly IDailyReportService dailyReportService;
private readonly IWellService wellService;
public DailyReportController(IWellOperationRepository wellOperationRepository,
IDailyReportService dailyReportService,
IDailyReportExportService dailyReportExportService,
IWellService wellService)
{
this.wellOperationRepository = wellOperationRepository;
this.dailyReportService = dailyReportService;
this.dailyReportExportService = dailyReportExportService;
this.wellService = wellService;
}
public DailyReportController(
IDailyReportService dailyReportService,
IWellService wellService)
{
this.dailyReportService = dailyReportService;
this.wellService = wellService;
}
private int IdUser
{
get
{
var idUser = User.GetUserId();
/// <summary>
/// Список наборов данных для формирования рапорта
/// </summary>
/// <param name="idWell"></param>
/// <param name="begin"></param>
/// <param name="end"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpGet]
[ProducesResponseType(typeof(IEnumerable<DailyReportDto>), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetListAsync(int idWell, DateOnly? begin, DateOnly? end, CancellationToken token)
{
var result = await dailyReportService.GetListAsync(idWell, begin, end, token);
return Ok(result);
}
if (!idUser.HasValue)
throw new ForbidException("Неизвестный пользователь");
/// <summary>
/// Создание суточного рапорта
/// </summary>
/// <param name="idWell"></param>
/// <param name="startDate"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpPost]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> AddAsync(int idWell, [Required] DateOnly startDate, CancellationToken token)
{
if (!await UserHasAccesToWellAsync(idWell, token))
return Forbid();
return idUser.Value;
}
}
var idUser = User.GetUserId()!.Value;
/// <summary>
/// Создать суточный отчёт
/// </summary>
/// <param name="idWell">Id скважины</param>
/// <param name="dateStart">Дата формирования суточного отчёта</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost]
[Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> InsertAsync(int idWell, DateOnly dateStart, CancellationToken cancellationToken)
{
await AssertUserAccessToWell(idWell, cancellationToken);
var result = await dailyReportService.AddAsync(idWell, startDate, idUser, token);
return Ok(result);
}
var id = await dailyReportService.InsertAsync(idWell, dateStart.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc),
cancellationToken);
/// <summary>
/// Сохранение изменений набора данных для формирования рапорта (заголовок)
/// </summary>
/// <param name="idWell"></param>
/// <param name="date">Дата без учета времени</param>
/// <param name="dto"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpPut("{date}/head")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public Task<IActionResult> UpdateHeadAsync(int idWell, [Required] DateOnly date, [Required] HeadDto dto, CancellationToken token)
=> UpdateReportBlockAsync(idWell, date, dto, token);
return Ok(id);
}
/// <summary>
/// Сохранение изменений набора данных для формирования рапорта (блок КНБК)
/// </summary>
/// <param name="idWell"></param>
/// <param name="date">Дата без учета времени</param>
/// <param name="dto"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpPut("{date}/bha")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public Task<IActionResult> UpdateBhaAsync(int idWell, [Required] DateOnly date, [Required] BhaDto dto, CancellationToken token)
=> UpdateReportBlockAsync(idWell, date, dto, token);
/// <summary>
/// Обновить подпись
/// </summary>
/// <param name="idWell">Id скважины</param>
/// <param name="idDailyReport">Id суточного отчёта</param>
/// <param name="signBlock">Обновляемый блок</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPut("sign")]
[Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public Task<IActionResult>
UpdateSignBlockAsync(int idWell, int idDailyReport, SignBlockDto signBlock, CancellationToken cancellationToken) =>
UpdateBlockAsync(idWell, idDailyReport, signBlock, cancellationToken);
/// <summary>
/// Сохранение изменений набора данных для формирования рапорта (безметражные работы)
/// </summary>
/// <param name="idWell"></param>
/// <param name="date">Дата без учета времени</param>
/// <param name="dto"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpPut("{date}/noDrilling")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public Task<IActionResult> UpdateNoDrillingAsync(int idWell, [Required] DateOnly date, [Required] NoDrillingDto dto, CancellationToken token)
=> UpdateReportBlockAsync(idWell, date, dto, token);
/// <summary>
/// Обновить наработку подсистем
/// </summary>
/// <param name="idWell">Id скважины</param>
/// <param name="idDailyReport">Id суточного отчёта</param>
/// <param name="subsystemBlock">Обновляемый блок</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPut("subsystem")]
[Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public Task<IActionResult> UpdateSubsystemBlockAsync(int idWell, int idDailyReport, SubsystemBlockDto subsystemBlock,
CancellationToken cancellationToken)
{
var validSubsystemIds = new[] { 100000, 100001 };
/// <summary>
/// Сохранение изменений набора данных для формирования рапорта (САУБ)
/// </summary>
/// <param name="idWell"></param>
/// <param name="date">Дата без учета времени</param>
/// <param name="dto"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpPut("{date}/saub")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public Task<IActionResult> UpdateSaubAsync(int idWell, [Required] DateOnly date, [Required] SaubDto dto, CancellationToken token)
=> UpdateReportBlockAsync(idWell, date, dto, token);
if (subsystemBlock.Modules.Any(m => !validSubsystemIds.Contains(m.IdSubsystem)))
throw new ArgumentInvalidException($"Возможно добавить модули только с Id: {string.Join(", ", validSubsystemIds)}",
nameof(subsystemBlock.Modules));
/// <summary>
/// Сохранение изменений набора данных для формирования рапорта (подпись)
/// </summary>
/// <param name="idWell"></param>
/// <param name="date">Дата без учета времени</param>
/// <param name="dto"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpPut("{date}/sign")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public Task<IActionResult> UpdateSignAsync(int idWell, [Required] DateOnly date, [Required] SignDto dto, CancellationToken token)
=> UpdateReportBlockAsync(idWell, date, dto, token);
return UpdateBlockAsync(idWell, idDailyReport, subsystemBlock, cancellationToken);
}
/// <summary>
/// Обновление блока суточного рапорта
/// </summary>
/// <param name="idWell">ключ скважины</param>
/// <param name="date">дата суточного рапорта</param>
/// <param name="dto"></param>
/// <param name="token"></param>
/// <returns></returns>
private async Task<IActionResult> UpdateReportBlockAsync(int idWell, DateOnly date, ItemInfoDto dto, CancellationToken token)
{
if (!await UserHasAccesToWellAsync(idWell, token))
return Forbid();
/// <summary>
/// Обновить баланс времени
/// </summary>
/// <param name="idWell">Id скважины</param>
/// <param name="idDailyReport">Id суточного отчёта</param>
/// <param name="timeBalanceBlock">Обновляемый блок</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPut("timeBalance")]
[Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public Task<IActionResult> UpdateTimeBalanceBlockAsync(int idWell, int idDailyReport, TimeBalanceBlockDto timeBalanceBlock,
CancellationToken cancellationToken)
{
var validWellOperationsIds = new[] { 4001, 4002, 4004, 4012 };
dto.IdUser = User.GetUserId();
dto.LastUpdateDate = DateTimeOffset.Now;
if (timeBalanceBlock.WellOperations.Any(o => !validWellOperationsIds.Contains(o.IdWellOperation)))
throw new ArgumentInvalidException($"Возможно добавить операции только с Id: {string.Join(",", validWellOperationsIds)}",
nameof(timeBalanceBlock.WellOperations));
var result = await dailyReportService.UpdateBlockAsync(idWell, date, dto, token);
return Ok(result);
}
var wellSections = wellOperationRepository.GetSectionTypes();
/// <summary>
/// Сформировать и скачать рапорт в формате excel
/// </summary>
/// <param name="idWell"></param>
/// <param name="date"></param>
/// <param name="token"></param>
/// <returns></returns>
[HttpGet("{date}/excel")]
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<IActionResult> DownloadAsync(int idWell, DateOnly date, CancellationToken token)
{
if (!await UserHasAccesToWellAsync(idWell, token))
return Forbid();
if (wellSections.All(s => s.Id != timeBalanceBlock.IdSection))
throw new ArgumentInvalidException($"Секция с Id: {timeBalanceBlock.IdSection} не найдена", nameof(timeBalanceBlock.IdSection));
var well = await wellService.GetOrDefaultAsync(idWell, token);
if (well is null)
return this.ValidationBadRequest(nameof(idWell), $"Скважина c id:{idWell} не найдена");
return UpdateBlockAsync(idWell, idDailyReport, timeBalanceBlock, cancellationToken);
}
var stream = await dailyReportService.MakeReportAsync(idWell, date, token);
if (stream is null)
return NoContent();
/// <summary>
/// Получить список суточных отчётов по скважине
/// </summary>
/// <param name="idWell">Идентификатор скважины</param>
/// <param name="request">Параметры запроса</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet]
[ProducesResponseType(typeof(PaginationContainer<DailyReportDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> GetAsync(int idWell, [FromQuery] FileReportRequest request, CancellationToken cancellationToken)
{
await AssertUserAccessToWell(idWell, cancellationToken);
var fileName = $"Суточный рапорт по скважине {well.Caption} куст {well.Cluster}.xlsx";
return File(stream, "application/octet-stream", fileName);
var dailyReports = await dailyReportService.GetAsync(idWell, request, cancellationToken);
}
return Ok(dailyReports);
}
protected async Task<bool> UserHasAccesToWellAsync(int idWell, CancellationToken token)
{
var idCompany = User.GetCompanyId();
if (idCompany is not null &&
await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token)
.ConfigureAwait(false))
return true;
return false;
}
}
/// <summary>
/// Получить диапазон дат по которым возможно сформировать суточный отчёты
/// </summary>
/// <param name="idWell">Id скважины</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet("datesRange")]
[ProducesResponseType(typeof(DatesRangeDto), (int)HttpStatusCode.OK)]
public async Task<IActionResult> GetDatesRangeAsync(int idWell, CancellationToken cancellationToken)
{
await AssertUserAccessToWell(idWell, cancellationToken);
var datesRanges = await dailyReportService.GetDatesRangeAsync(idWell, cancellationToken);
return Ok(datesRanges);
}
/// <summary>
/// Экспорт суточного рапорта
/// </summary>
/// <param name="idWell">Id скважины</param>
/// <param name="dailyReportDateStart">Дата формирования суточного отчёта</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet("{dailyReportDateStart}")]
[ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> ExportAsync(int idWell, DateOnly dailyReportDateStart, CancellationToken cancellationToken)
{
await AssertUserAccessToWell(idWell, cancellationToken);
var dailyReport = await dailyReportExportService.ExportAsync(idWell,
dailyReportDateStart.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc), cancellationToken);
return File(dailyReport.File, "application/octet-stream", dailyReport.FileName);
}
private async Task<IActionResult> UpdateBlockAsync<TBlock>(int idWell, int idDailyReport, TBlock block,
CancellationToken cancellationToken)
where TBlock : EditableBlock
{
await AssertUserAccessToWell(idWell, cancellationToken);
var id = await dailyReportService.UpdateBlockAsync(idDailyReport, IdUser, block, cancellationToken);
return Ok(id);
}
private async Task AssertUserAccessToWell(int idWell, CancellationToken cancellationToken)
{
var idCompany = User.GetCompanyId();
if (!idCompany.HasValue || !await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, idWell, cancellationToken))
throw new ForbidException("Нет доступа к скважине");
}
}