DD.WellWorkover.Cloud/AsbCloudWebApi/Controllers/DailyReportController.cs
Степанов Дмитрий dcaec8b4a2 Доработки
1. Добавлен шаблон суточного отчёта
2. Рефакторинг DTO для суточного отчёта
3. Обновлена валидация входных данных в методах контроллера
4. Небольшой рефакторинг сервисов
2023-11-07 15:57:15 +05:00

237 lines
9.6 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 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;
/// <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;
public DailyReportController(IWellOperationRepository wellOperationRepository,
IDailyReportService dailyReportService,
IDailyReportExportService dailyReportExportService,
IWellService wellService)
{
this.wellOperationRepository = wellOperationRepository;
this.dailyReportService = dailyReportService;
this.dailyReportExportService = dailyReportExportService;
this.wellService = wellService;
}
private int IdUser
{
get
{
var idUser = User.GetUserId();
if (!idUser.HasValue)
throw new ForbidException("Неизвестный пользователь");
return idUser.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)
{
var dateStartToDateTime = dateStart.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc);
var datesRange = await dailyReportService.GetDatesRangeAsync(idWell, cancellationToken);
if (dateStartToDateTime < datesRange?.From || dateStartToDateTime > datesRange?.To)
throw new ArgumentInvalidException("Невозможно сформировать суточный отчёт", nameof(dateStart));
await AssertUserAccessToWell(idWell, cancellationToken);
var id = await dailyReportService.InsertAsync(idWell, dateStart.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc),
cancellationToken);
return Ok(id);
}
/// <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">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 validSubsystemNames = new[] { "АвтоСПО", "Автопроработка" };
if (subsystemBlock.Modules.Any(m => !validSubsystemNames.Contains(m.SubsystemName)))
throw new ArgumentInvalidException($"Возможно добавить модули только с именами {string.Join(", ", validSubsystemNames)}",
nameof(subsystemBlock.Modules));
return UpdateBlockAsync(idWell, idDailyReport, subsystemBlock, cancellationToken);
}
/// <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[] { 1, 2, 3, 4 };
if (timeBalanceBlock.WellOperations.Any(o => !validWellOperationsIds.Contains(o.IdWellOperation)))
throw new ArgumentInvalidException($"Возможно добавить операции только с Id: {string.Join(", ", validWellOperationsIds)}",
nameof(timeBalanceBlock.WellOperations));
var wellSections = wellOperationRepository.GetSectionTypes();
if (wellSections.All(s => s.Id != timeBalanceBlock.IdSection))
throw new ArgumentInvalidException($"Секция с Id: {timeBalanceBlock.IdSection} не найдена", nameof(timeBalanceBlock.IdSection));
return UpdateBlockAsync(idWell, idDailyReport, timeBalanceBlock, cancellationToken);
}
/// <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 dailyReports = await dailyReportService.GetAsync(idWell, request, cancellationToken);
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);
var datesRanges = await dailyReportService.GetDatesRangeAsync(idWell, cancellationToken);
return Ok(datesRanges);
}
/// <summary>
/// Экспорт суточного рапорта
/// </summary>
/// <param name="idWell">Id скважины</param>
/// <param name="dateStart">Дата формирования суточного отчёта</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet("{dateStart}")]
[ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> ExportAsync(int idWell, DateOnly dateStart, CancellationToken cancellationToken)
{
var dateStartToDateTime = dateStart.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc);
var datesRange = await dailyReportService.GetDatesRangeAsync(idWell, cancellationToken);
if (dateStartToDateTime < datesRange?.From || dateStartToDateTime > datesRange?.To)
throw new ArgumentInvalidException("Невозможно получить суточный отчёт", nameof(dateStart));
await AssertUserAccessToWell(idWell, cancellationToken);
var dailyReport = await dailyReportExportService.ExportAsync(idWell,
dateStart.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("Нет доступа к скважине");
}
}