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

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 System;
using AsbCloudApp.Data.DailyReport; using System.Linq;
using AsbCloudApp.Exceptions; using System.Net;
using AsbCloudApp.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading; using System.Threading;
using System.Threading.Tasks; 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.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> public DailyReportController(IWellOperationRepository wellOperationRepository,
/// Суточный рапорт IDailyReportService dailyReportService,
/// </summary> IDailyReportExportService dailyReportExportService,
[Route("api/well/{idWell}/[controller]")] IWellService wellService)
[ApiController] {
[Authorize] this.wellOperationRepository = wellOperationRepository;
public class DailyReportController : ControllerBase this.dailyReportService = dailyReportService;
{ this.dailyReportExportService = dailyReportExportService;
private readonly IDailyReportService dailyReportService; this.wellService = wellService;
private readonly IWellService wellService; }
public DailyReportController( private int IdUser
IDailyReportService dailyReportService, {
IWellService wellService) get
{ {
this.dailyReportService = dailyReportService; var idUser = User.GetUserId();
this.wellService = wellService;
}
/// <summary> if (!idUser.HasValue)
/// Список наборов данных для формирования рапорта throw new ForbidException("Неизвестный пользователь");
/// </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);
}
/// <summary> return idUser.Value;
/// Создание суточного рапорта }
/// </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();
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); var id = await dailyReportService.InsertAsync(idWell, dateStart.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc),
return Ok(result); cancellationToken);
}
/// <summary> return Ok(id);
/// Сохранение изменений набора данных для формирования рапорта (заголовок) }
/// </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);
/// <summary> /// <summary>
/// Сохранение изменений набора данных для формирования рапорта (блок КНБК) /// Обновить подпись
/// </summary> /// </summary>
/// <param name="idWell"></param> /// <param name="idWell">Id скважины</param>
/// <param name="date">Дата без учета времени</param> /// <param name="idDailyReport">Id суточного отчёта</param>
/// <param name="dto"></param> /// <param name="signBlock">Обновляемый блок</param>
/// <param name="token"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
[HttpPut("{date}/bha")] [HttpPut("sign")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] [Permission]
public Task<IActionResult> UpdateBhaAsync(int idWell, [Required] DateOnly date, [Required] BhaDto dto, CancellationToken token) [ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
=> UpdateReportBlockAsync(idWell, date, dto, token); [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public Task<IActionResult>
UpdateSignBlockAsync(int idWell, int idDailyReport, SignBlockDto signBlock, CancellationToken cancellationToken) =>
UpdateBlockAsync(idWell, idDailyReport, signBlock, cancellationToken);
/// <summary> /// <summary>
/// Сохранение изменений набора данных для формирования рапорта (безметражные работы) /// Обновить наработку подсистем
/// </summary> /// </summary>
/// <param name="idWell"></param> /// <param name="idWell">Id скважины</param>
/// <param name="date">Дата без учета времени</param> /// <param name="idDailyReport">Id суточного отчёта</param>
/// <param name="dto"></param> /// <param name="subsystemBlock">Обновляемый блок</param>
/// <param name="token"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
[HttpPut("{date}/noDrilling")] [HttpPut("subsystem")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] [Permission]
public Task<IActionResult> UpdateNoDrillingAsync(int idWell, [Required] DateOnly date, [Required] NoDrillingDto dto, CancellationToken token) [ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
=> UpdateReportBlockAsync(idWell, date, dto, token); [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public Task<IActionResult> UpdateSubsystemBlockAsync(int idWell, int idDailyReport, SubsystemBlockDto subsystemBlock,
CancellationToken cancellationToken)
{
var validSubsystemIds = new[] { 100000, 100001 };
/// <summary> if (subsystemBlock.Modules.Any(m => !validSubsystemIds.Contains(m.IdSubsystem)))
/// Сохранение изменений набора данных для формирования рапорта (САУБ) throw new ArgumentInvalidException($"Возможно добавить модули только с Id: {string.Join(", ", validSubsystemIds)}",
/// </summary> nameof(subsystemBlock.Modules));
/// <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);
/// <summary> return UpdateBlockAsync(idWell, idDailyReport, subsystemBlock, cancellationToken);
/// Сохранение изменений набора данных для формирования рапорта (подпись) }
/// </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);
/// <summary> /// <summary>
/// Обновление блока суточного рапорта /// Обновить баланс времени
/// </summary> /// </summary>
/// <param name="idWell">ключ скважины</param> /// <param name="idWell">Id скважины</param>
/// <param name="date">дата суточного рапорта</param> /// <param name="idDailyReport">Id суточного отчёта</param>
/// <param name="dto"></param> /// <param name="timeBalanceBlock">Обновляемый блок</param>
/// <param name="token"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
private async Task<IActionResult> UpdateReportBlockAsync(int idWell, DateOnly date, ItemInfoDto dto, CancellationToken token) [HttpPut("timeBalance")]
{ [Permission]
if (!await UserHasAccesToWellAsync(idWell, token)) [ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
return Forbid(); [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(); if (timeBalanceBlock.WellOperations.Any(o => !validWellOperationsIds.Contains(o.IdWellOperation)))
dto.LastUpdateDate = DateTimeOffset.Now; throw new ArgumentInvalidException($"Возможно добавить операции только с Id: {string.Join(",", validWellOperationsIds)}",
nameof(timeBalanceBlock.WellOperations));
var wellSections = wellOperationRepository.GetSectionTypes();
var result = await dailyReportService.UpdateBlockAsync(idWell, date, dto, token); if (wellSections.All(s => s.Id != timeBalanceBlock.IdSection))
return Ok(result); throw new ArgumentInvalidException($"Секция с Id: {timeBalanceBlock.IdSection} не найдена", nameof(timeBalanceBlock.IdSection));
}
/// <summary> return UpdateBlockAsync(idWell, idDailyReport, timeBalanceBlock, cancellationToken);
/// Сформировать и скачать рапорт в формате 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();
var well = await wellService.GetOrDefaultAsync(idWell, token); /// <summary>
if (well is null) /// Получить список суточных отчётов по скважине
return this.ValidationBadRequest(nameof(idWell), $"Скважина c id:{idWell} не найдена"); /// </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 stream = await dailyReportService.MakeReportAsync(idWell, date, token); var dailyReports = await dailyReportService.GetAsync(idWell, request, cancellationToken);
if (stream is null)
return NoContent();
var fileName = $"Суточный рапорт по скважине {well.Caption} куст {well.Cluster}.xlsx";
return File(stream, "application/octet-stream", fileName);
} return Ok(dailyReports);
}
/// <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);
protected async Task<bool> UserHasAccesToWellAsync(int idWell, CancellationToken token) var datesRanges = await dailyReportService.GetDatesRangeAsync(idWell, cancellationToken);
{
var idCompany = User.GetCompanyId();
if (idCompany is not null &&
await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token)
.ConfigureAwait(false))
return true;
return false;
}
}
} 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("Нет доступа к скважине");
}
}