using System.ComponentModel.DataAnnotations; using System.IO; using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data; using AsbCloudApp.Data.ProcessMaps; using AsbCloudApp.Exceptions; using AsbCloudApp.Repositories; using AsbCloudApp.Services; using AsbCloudApp.Services.ProcessMaps; using AsbCloudApp.Services.ProcessMaps.WellDrillingProcessMap; using AsbCloudWebApi.SignalR; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; namespace AsbCloudWebApi.Controllers.ProcessMaps; public class ProcessMapWellDrillingController : ProcessMapBaseController<ProcessMapPlanWellDrillingDto> { private readonly IHubContext<TelemetryHub> telemetryHubContext; private readonly IProcessMapReportWellDrillingService wellDrillingProcessMapReportService; private readonly IProcessMapReportExportService wellDrillingProcessMapReportExportService; private readonly IProcessMapImportService wellDrillingProcessMapImportService; public ProcessMapWellDrillingController(IWellService wellService, IProcessMapPlanRepository<ProcessMapPlanWellDrillingDto> repository, IUserRepository userRepository, IHubContext<TelemetryHub> telemetryHubContext, IProcessMapReportExportService wellDrillingProcessMapReportExportService, IProcessMapImportService wellDrillingProcessMapImportService, IProcessMapReportWellDrillingService wellDrillingProcessMapReportService, ICrudRepository<WellSectionTypeDto> wellSectionRepository) : base(wellService, repository, userRepository, wellSectionRepository) { this.telemetryHubContext = telemetryHubContext; this.wellDrillingProcessMapReportExportService = wellDrillingProcessMapReportExportService; this.wellDrillingProcessMapImportService = wellDrillingProcessMapImportService; this.wellDrillingProcessMapReportService = wellDrillingProcessMapReportService; } /// <summary> /// Создание РТК /// </summary> /// <param name="processMap">Тело запроса</param> /// <param name="idWell">Id скважины</param> /// <param name="cancellationToken"></param> /// <returns></returns> public override async Task<IActionResult> InsertAsync(ProcessMapPlanWellDrillingDto processMap, int idWell, CancellationToken cancellationToken) { var result = await base.InsertAsync(processMap, idWell, cancellationToken); await NotifyUsersBySignalR(idWell, cancellationToken); return result; } /// <summary> /// Обновление РТК /// </summary> /// <param name="processMap">Тело запроса</param> /// <param name="idWell">Id скважины</param> /// <param name="cancellationToken"></param> /// <returns></returns> public override async Task<IActionResult> UpdateAsync(ProcessMapPlanWellDrillingDto processMap, int idWell, CancellationToken cancellationToken) { var result = await base.UpdateAsync(processMap, idWell, cancellationToken); await NotifyUsersBySignalR(idWell, cancellationToken); return result; } /// <summary> /// Удаление РТК /// </summary> /// <param name="id">Id удаляемой РТК</param> /// <param name="idWell">Id скважины</param> /// <param name="cancellationToken"></param> /// <returns></returns> public override async Task<IActionResult> DeleteAsync(int id, int idWell, CancellationToken cancellationToken) { var result = await base.DeleteAsync(id, idWell, cancellationToken); await NotifyUsersBySignalR(idWell, cancellationToken); return result; } /// <summary> /// Получение отчета РТК бурение /// </summary> /// <param name="idWell">Id</param> /// <param name="cancellationToken"></param> /// <returns></returns> [HttpGet("report")] [ProducesResponseType(typeof(ProcessMapPlanWellDrillingDto), StatusCodes.Status200OK)] public async Task<IActionResult> GetReportAsync(int idWell, CancellationToken cancellationToken) { var report = await wellDrillingProcessMapReportService.GetAsync(idWell, cancellationToken); return Ok(report); } /// <summary> /// Экспорт отчета РТК бурение /// </summary> /// <param name="idWell">Id скважины</param> /// <param name="cancellationToken"></param> /// <returns></returns> [HttpGet("report/export")] [ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK, "application/octet-stream")] [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task<IActionResult> ExportReportAsync(int idWell, CancellationToken cancellationToken) { var report = await wellDrillingProcessMapReportExportService.ExportAsync(idWell, cancellationToken); if (report is null) return NoContent(); return File(report.Value.File, "application/octet-stream", report.Value.Name); } /// <summary> /// Импорт РТК бурение /// </summary> /// <param name="idWell">Id скважины</param> /// <param name="options"></param> /// <param name="file"></param> /// <param name="cancellationToken"></param> /// <returns></returns> [HttpPost("import/{options}")] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public async Task<IActionResult> ImportAsync(int idWell, int options, [Required] IFormFile file, CancellationToken cancellationToken) { await AssertUserHasAccessToEditProcessMapAsync(idWell, cancellationToken); if (Path.GetExtension(file.FileName).ToLower() != ".xlsx") return this.ValidationBadRequest(nameof(file), "Требуется xlsx файл."); using Stream stream = file.OpenReadStream(); try { await wellDrillingProcessMapImportService.ImportAsync(idWell, IdUser, (options & 1) > 0, stream, cancellationToken); await NotifyUsersBySignalR(idWell, cancellationToken); } catch (FileFormatException ex) { return this.ValidationBadRequest(nameof(file), ex.Message); } return Ok(); } /// <summary> /// Экспорт РТК бурение /// </summary> /// <param name="idWell">Id скважины</param> /// <param name="cancellationToken"></param> /// <returns></returns> [HttpGet("export")] [ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK, "application/octet-stream")] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public async Task<IActionResult> ExportAsync(int idWell, CancellationToken cancellationToken) { var processMapsFile = await wellDrillingProcessMapImportService.ExportAsync(idWell, cancellationToken); return File(processMapsFile.File, "application/octet-stream", processMapsFile.Name); } /// <summary> /// Возвращает шаблон файла для импорта /// </summary> /// <returns>Запрашиваемый файл</returns> [HttpGet("template")] [ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK, "application/octet-stream")] public async Task<IActionResult> GetTemplateAsync(CancellationToken cancellationToken) { var template = await wellDrillingProcessMapImportService.GetExcelTemplateStreamAsync(cancellationToken); return File(template.File, "application/octet-stream", template.Name); } private async Task NotifyUsersBySignalR(int idWell, CancellationToken cancellationToken) { var wellDrillingProcessMaps = await repository.GetByIdWellAsync(idWell, cancellationToken); await telemetryHubContext.Clients .Group($"well_{idWell}") .SendAsync("UpdateProcessMap", wellDrillingProcessMaps, cancellationToken); } }