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 WellDrillingProcessMapController : ProcessMapBaseController { private readonly IHubContext telemetryHubContext; private readonly IWellDrillingProcessMapReportService wellDrillingProcessMapReportService; private readonly IProcessMapReportExportService wellDrillingProcessMapReportExportService; private readonly IProcessMapImportService wellDrillingProcessMapImportService; private readonly ICrudRepository wellSectionRepository; public WellDrillingProcessMapController(IWellService wellService, IWellDrillingProcessMapRepository repository, IUserRepository userRepository, IHubContext telemetryHubContext, IProcessMapReportExportService wellDrillingProcessMapReportExportService, IProcessMapImportService wellDrillingProcessMapImportService, IWellDrillingProcessMapReportService wellDrillingProcessMapReportService, ICrudRepository wellSectionRepository) : base(wellService, repository, userRepository) { this.telemetryHubContext = telemetryHubContext; this.wellDrillingProcessMapReportExportService = wellDrillingProcessMapReportExportService; this.wellDrillingProcessMapImportService = wellDrillingProcessMapImportService; this.wellDrillingProcessMapReportService = wellDrillingProcessMapReportService; this.wellSectionRepository = wellSectionRepository; } /// /// Создание РТК /// /// Тело запроса /// Id скважины /// /// public override async Task InsertAsync(WellDrillingProcessMapDto processMap, int idWell, CancellationToken cancellationToken) { await CheckIsExistsWellSectionTypeAsync(processMap.IdWellSectionType, cancellationToken); var result = await base.InsertAsync(processMap, idWell, cancellationToken); await NotifyUsersBySignalR(idWell, cancellationToken); return result; } /// /// Обновление РТК /// /// Тело запроса /// Id скважины /// /// public override async Task UpdateAsync(WellDrillingProcessMapDto processMap, int idWell, CancellationToken cancellationToken) { await CheckIsExistsWellSectionTypeAsync(processMap.IdWellSectionType, cancellationToken); var result = await base.UpdateAsync(processMap, idWell, cancellationToken); await NotifyUsersBySignalR(idWell, cancellationToken); return result; } /// /// Удаление РТК /// /// Id скважины /// /// public override async Task DeleteAsync(int idWell, CancellationToken cancellationToken) { var result = await base.DeleteAsync(idWell, cancellationToken); await NotifyUsersBySignalR(idWell, cancellationToken); return result; } /// /// Получение отчета РТК бурение /// /// Id /// /// [HttpGet("report")] [ProducesResponseType(typeof(WellDrillingProcessMapDto), StatusCodes.Status200OK)] public async Task GetReportAsync(int idWell, CancellationToken cancellationToken) { var report = await wellDrillingProcessMapReportService.GetAsync(idWell, cancellationToken); return Ok(report); } /// /// Экспорт отчета РТК бурение /// /// Id скважины /// /// [HttpGet("report/export")] [ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK, "application/octet-stream")] [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task 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); } /// /// Импорт РТК бурение /// /// Id скважины /// /// /// /// [HttpPost("import/{options}")] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public async Task 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); } catch (FileFormatException ex) { return this.ValidationBadRequest(nameof(file), ex.Message); } return Ok(); } /// /// Экспорт РТК бурение /// /// Id скважины /// /// [HttpGet("export")] [ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK, "application/octet-stream")] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] public async Task ExportAsync(int idWell, CancellationToken cancellationToken) { var processMapsFile = await wellDrillingProcessMapImportService.ExportAsync(idWell, cancellationToken); return File(processMapsFile.File, "application/octet-stream", processMapsFile.Name); } /// /// Возвращает шаблон файла для импорта /// /// Запрашиваемый файл [HttpGet("template")] [ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK, "application/octet-stream")] public async Task GetTemplateAsync(CancellationToken cancellationToken) { var template = await wellDrillingProcessMapImportService.GetExcelTemplateStreamAsync(cancellationToken); return File(template.File, "application/octet-stream", template.Name); } private async Task CheckIsExistsWellSectionTypeAsync(int idWellSectionType, CancellationToken cancellationToken) { var wellSection = await wellSectionRepository.GetOrDefaultAsync(idWellSectionType, cancellationToken); if (wellSection is null) throw new ArgumentInvalidException(nameof(WellDrillingProcessMapDto.IdWellSectionType), $"Тип секции с Id: {idWellSectionType} не найден"); } 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); } }