using AsbCloudApp.Data; using AsbCloudApp.Services; using AsbCloudWebApi.SignalR; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace AsbCloudWebApi.Controllers { /// <summary> /// Контроллер отчетов по буровым скважинам /// </summary> [Route("api/well/{idWell}/report")] [ApiController] public class ReportController : ControllerBase { private readonly IReportService reportService; private readonly IFileService fileService; private readonly IWellService wellService; private readonly IHubContext<ReportsHub> reportsHubContext; public ReportController(IReportService reportService, IWellService wellService, IFileService fileService, IHubContext<ReportsHub> reportsHubContext) { this.reportService = reportService; this.fileService = fileService; this.wellService = wellService; this.reportsHubContext = reportsHubContext; } private void HandleReportProgressAsync(float progress, string operation, int id) => Task.Run(() => { reportsHubContext.Clients.Group($"Report_{id}").SendAsync( nameof(IReportHubClient.GetReportProgress), new { Progress = progress, Operation = operation, ReportName = "" } ).ConfigureAwait(false); }); private void HandleReportNameAsync(string reportName, int groupId) => Task.Run(() => { reportsHubContext.Clients.All.SendAsync( nameof(IReportHubClient.GetReportProgress), new { Progress = 100, Operation = "Отчет успешно создан", ReportName = reportName } ).ConfigureAwait(false); }); /// <summary> /// Создает отчет по скважине с указанными параметрами /// </summary> /// <param name="idWell">id скважины</param> /// <param name="idUser">id пользователя</param> /// <param name="stepSeconds">шаг интервала</param> /// <param name="format">формат отчета (0-PDF, 1-LAS)</param> /// <param name="begin">дата начала интервала</param> /// <param name="end">дата окончания интервала</param> /// <param name="token">Токен для отмены задачи</param> /// <returns>id фоновой задачи формирования отчета</returns> [HttpPost] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] public async Task<IActionResult> CreateReportAsync(int idWell, int idUser, int stepSeconds, int format, DateTime begin = default, DateTime end = default, CancellationToken token = default) { int? idCompany = User.GetCompanyId(); if (idCompany is null) return Forbid(); if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token).ConfigureAwait(false)) return Forbid(); var id = reportService.CreateReport(idWell, idUser, stepSeconds, format, begin, end, HandleReportProgressAsync, HandleReportNameAsync); return Ok(id); } /// <summary> /// Возвращает файл-отчет с диска на сервере /// </summary> /// <param name="idWell">id скважины</param> /// <param name="reportName">имя запрашиваемого файла (отчета)</param> /// <param name="token">Токен для отмены задачи</param> /// <returns>файл с отчетом</returns> [HttpGet] [Route("{reportName}")] [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] public async Task<IActionResult> GetReportAsync([FromRoute] int idWell, string reportName, CancellationToken token = default) { try { int? idCompany = User.GetCompanyId(); if (idCompany is null) return Forbid(); if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token).ConfigureAwait(false)) return Forbid(); // TODO: словарь content typoв var relativePath = Path.Combine(fileService.RootPath, $"{idWell}", $"{reportService.ReportCategoryId}", reportName); return PhysicalFile(Path.GetFullPath(relativePath), "application/pdf", reportName); } catch (FileNotFoundException ex) { return NotFound($"Файл не найден. Текст ошибки: {ex.Message}"); } } /// <summary> /// Возвращает имена отчетов, хранящихся на диске, /// которые подходят под указанные параметры /// </summary> /// <param name="idWell">id скважины</param> /// <param name="stepSeconds">шаг интервала</param> /// <param name="format">формат отчета (0-PDF, 1-LAS)</param> /// <param name="begin">дата начала интервала</param> /// <param name="end">дата окончания интервала</param> /// <param name="token">Токен для отмены задачи</param> /// <returns>Список имен существующих отчетов (отчетов)</returns> [HttpGet] [Route("suitableReports")] [ProducesResponseType(typeof(IEnumerable<string>), (int)System.Net.HttpStatusCode.OK)] public async Task<IActionResult> GetSuitableReportsNamesAsync(int idWell, int stepSeconds, int format, DateTime begin = default, DateTime end = default, CancellationToken token = default) { var suitableReportsNames = await reportService.GetSuitableReportsAsync(idWell, begin, end, stepSeconds, format, token).ConfigureAwait(false); if (suitableReportsNames is null || !suitableReportsNames.Any()) return NoContent(); return Ok(suitableReportsNames); } /// <summary> /// Возвращает прогнозируемое количество страниц будущего отчета /// </summary> /// <param name="idWell">id скважины</param> /// <param name="begin">дата начала интервала</param> /// <param name="end">дата окончания интервала</param> /// <param name="stepSeconds">шаг интервала</param> /// <param name="format">формат отчета (0-PDF, 1-LAS)</param> /// <param name="token">Токен для отмены задачи</param> /// <returns>прогнозируемое кол-во страниц отчета</returns> [HttpGet] [Route("reportSize")] [ProducesResponseType(typeof(string), (int)System.Net.HttpStatusCode.OK)] public async Task<IActionResult> GetReportSizeAsync(int idWell, int stepSeconds, int format, DateTime begin = default, DateTime end = default, CancellationToken token = default) { int? idCompany = User.GetCompanyId(); if (idCompany is null) return Forbid(); if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token).ConfigureAwait(false)) return Forbid(); int reportSize = reportService.GetReportPagesCount(idWell, begin, end, stepSeconds, format); return Ok(reportSize); } /// <summary> /// Возвращает даты самого старого и самого свежего отчетов в БД /// </summary> /// <param name="idWell">id скважины</param> /// <param name="token">Токен для отмены задачи</param> /// <returns>Даты самого старого и самого свежего отчетов в БД</returns> [HttpGet] [Route("datesRange")] [ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)] public async Task<IActionResult> GetReportsDateRangeAsync(int idWell, CancellationToken token = default) { int? idCompany = User.GetCompanyId(); if (idCompany is null) return Forbid(); if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token).ConfigureAwait(false)) return Forbid(); DatesRangeDto wellReportsDatesRange = await reportService.GetReportsDatesRangeAsync(idWell, token).ConfigureAwait(false); return Ok(wellReportsDatesRange); } } }