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.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 AsbCloudDb.Model;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace AsbCloudWebApi.Controllers;
///
/// Суточный отчёт
///
[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;
}
}
///
/// Обновить подпись
///
/// Id скважины
/// Дата суточного отчёта
/// Обновляемый блок
///
///
[HttpPut("sign")]
[Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public Task UpdateSignBlockAsync(int idWell, DateOnly dateDailyReport, SignBlockDto signBlock,
CancellationToken cancellationToken) =>
UpdateOrInsertAsync(idWell, dateDailyReport, signBlock, cancellationToken);
///
/// Обновить наработку подсистем
///
/// Id скважины
/// Дата суточного отчёта
/// Обновляемый блок
///
///
[HttpPut("subsystem")]
[Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public Task UpdateSubsystemBlockAsync(int idWell, DateOnly dateDailyReport, SubsystemBlockDto subsystemBlock,
CancellationToken cancellationToken)
{
var validSubsystemNames = new[] { "АвтоСПО", "Автопроработка" };
if (subsystemBlock.Subsystems.Any(m => !validSubsystemNames.Contains(m.Name)))
throw new ArgumentInvalidException($"Возможно добавить подсистемы с именами {string.Join(", ", validSubsystemNames)}",
nameof(subsystemBlock.Subsystems));
return UpdateOrInsertAsync(idWell, dateDailyReport, subsystemBlock, cancellationToken);
}
///
/// Обновить баланс времени
///
/// Id скважины
/// Дата суточного отчёта
/// Обновляемый блок
///
///
[HttpPut("timeBalance")]
[Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public Task UpdateTimeBalanceBlockAsync(int idWell, DateOnly dateDailyReport, 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 UpdateOrInsertAsync(idWell, dateDailyReport, timeBalanceBlock, cancellationToken);
}
///
/// Получить список суточных отчётов по скважине
///
/// Идентификатор скважины
/// Параметры запроса
///
///
[HttpGet]
[ProducesResponseType(typeof(PaginationContainer), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task GetAsync(int idWell, [FromQuery] FileReportRequest request, CancellationToken cancellationToken)
{
await AssertUserAccessToWell(idWell, cancellationToken);
var dailyReports = await dailyReportService.GetAsync(idWell, request, cancellationToken);
return Ok(dailyReports);
}
///
/// Получить диапазон дат по которым возможно сформировать суточный отчёты
///
/// Id скважины
///
///
[HttpGet("datesRange")]
[ProducesResponseType(typeof(DatesRangeDto), (int)HttpStatusCode.OK)]
public async Task GetDatesRangeAsync(int idWell, CancellationToken cancellationToken)
{
await AssertUserAccessToWell(idWell, cancellationToken);
var datesRanges = await wellOperationRepository.GetDatesRangeAsync(idWell, WellOperation.IdOperationTypeFact, cancellationToken);
return Ok(datesRanges);
}
///
/// Экспорт суточного рапорта
///
/// Id скважины
/// Дата формирования суточного отчёта
///
///
[HttpGet("{dateDailyReport}")]
[ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task ExportAsync(int idWell, DateOnly dateDailyReport, CancellationToken cancellationToken)
{
await AssertUserAccessToWell(idWell, cancellationToken);
var dailyReport = await dailyReportExportService.ExportAsync(idWell, dateDailyReport, cancellationToken);
return File(dailyReport.File, "application/octet-stream", dailyReport.FileName);
}
private async Task UpdateOrInsertAsync(int idWell, DateOnly dateDailyReport, TBlock block,
CancellationToken cancellationToken)
where TBlock : ItemInfoDto
{
await AssertUserAccessToWell(idWell, cancellationToken);
var id = await dailyReportService.UpdateOrInsertAsync(idWell, dateDailyReport, 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("Нет доступа к скважине");
}
}