diff --git a/AsbCloudApp/Data/Subsystems/SubsystemStatPlanFactDto.cs b/AsbCloudApp/Data/Subsystems/SubsystemStatPlanFactDto.cs new file mode 100644 index 00000000..f9290478 --- /dev/null +++ b/AsbCloudApp/Data/Subsystems/SubsystemStatPlanFactDto.cs @@ -0,0 +1,60 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace AsbCloudApp.Data.Subsystems; + +/// +/// Статистика плановых и фактических подсистем +/// +public class SubsystemPlanFactStatDto +{ + /// + /// Id скважины + /// + public int IdWell { get; set; } + + /// + /// Тип секции + /// + public int IdWellSectionType { get; set; } + + /// + /// Глубина по стволу от, м + /// + public double DepthStart { get; set; } + + /// + /// Глубина по стволу до, м + /// + public double DepthEnd { get; set; } + + /// + /// Использование ротора (план) + /// + public double AutoRotorPlan { get; set; } + + /// + /// Использование слайда (план) + /// + public double AutoSlidePlan { get; set; } + + /// + /// Использование слайда с осцилляцией (план) + /// + public double AutoOscillationPlan { get; set; } + + /// + /// Использование ротора (факт) + /// + public double? AutoRotorFact { get; set; } + + /// + /// Использование слайда (факт) + /// + public double? AutoSlideFact { get; set; } + + /// + /// Использование слайда (факт) + /// + public double? AutoOscillationFact { get; set; } +} diff --git a/AsbCloudApp/Requests/ProcessMapPlanBaseRequest.cs b/AsbCloudApp/Requests/ProcessMapPlanBaseRequest.cs index 9191d82d..e1940035 100644 --- a/AsbCloudApp/Requests/ProcessMapPlanBaseRequest.cs +++ b/AsbCloudApp/Requests/ProcessMapPlanBaseRequest.cs @@ -44,6 +44,19 @@ public class ProcessMapPlanBaseRequestWithWell : ProcessMapPlanBaseRequest IdWell = idWell; } + /// + /// + /// + /// + /// + /// + public ProcessMapPlanBaseRequestWithWell(int idWell, double? geDepth, double? leDepth) + { + IdWell = idWell; + GeDepth = geDepth; + LeDepth = leDepth; + } + /// /// Запрос для получения РТК план по скважине /// @@ -59,4 +72,14 @@ public class ProcessMapPlanBaseRequestWithWell : ProcessMapPlanBaseRequest /// Id скважины /// public int IdWell { get; set; } -} \ No newline at end of file + + /// + /// Меньше или равно глубины забоя + /// + public double? LeDepth { get; set; } + + /// + /// Больше или равно глубине забоя + /// + public double? GeDepth { get; set; } +} diff --git a/AsbCloudApp/Requests/SubsystemBaseRequest.cs b/AsbCloudApp/Requests/SubsystemBaseRequest.cs new file mode 100644 index 00000000..a083d434 --- /dev/null +++ b/AsbCloudApp/Requests/SubsystemBaseRequest.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace AsbCloudApp.Requests; + +/// +/// класс с фильтрами для запроса +/// +public class SubsystemBaseRequest: RequestBase, IValidatableObject +{ + private static readonly DateTimeOffset validationMinDate = new DateTimeOffset(2020,01,01,0,0,0, TimeSpan.Zero); + + /// + /// Больше или равно дате + /// + public DateTimeOffset? GeDate { get; set; } + + /// + /// Меньше или равно дате + /// + public DateTimeOffset? LeDate { get; set; } + + /// + /// Больше или равно глубины забоя + /// + public double? GeDepth { get; set; } + + /// + /// Меньше или равно глубины забоя + /// + public double? LeDepth { get; set; } + + /// + public IEnumerable Validate(ValidationContext validationContext) + { + if (GeDate.HasValue && GeDate < validationMinDate) + yield return new ValidationResult( + $"Должно быть больше {validationMinDate:O})", + new[] { nameof(GeDate) }); + + if (LeDate.HasValue && GeDate.HasValue) + { + if (LeDate < GeDate) + yield return new ValidationResult( + $"{nameof(LeDate)} должно быть больше {nameof(GeDate)}. ({LeDate:O} < {GeDate:O})", + new[] { nameof(LeDate), nameof(GeDate) }); + } + + if (LeDepth.HasValue && GeDepth.HasValue) + { + if (LeDepth < GeDepth) + yield return new ValidationResult( + $"{nameof(LeDepth)} должно быть больше {nameof(GeDepth)}. ({LeDepth} < {GeDepth})", + new[] { nameof(LeDepth), nameof(GeDepth) }); + } + + yield break; + } +} diff --git a/AsbCloudApp/Requests/SubsystemPlanFactRequest.cs b/AsbCloudApp/Requests/SubsystemPlanFactRequest.cs new file mode 100644 index 00000000..ba7d2566 --- /dev/null +++ b/AsbCloudApp/Requests/SubsystemPlanFactRequest.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; + +namespace AsbCloudApp.Requests; + +/// +/// класс с фильтрами для запроса +/// +public class SubsystemPlanFactRequest: SubsystemBaseRequest +{ + /// + /// идентификаторы скважин + /// + public IEnumerable IdsWell { get; set; } = Enumerable.Empty(); +} diff --git a/AsbCloudApp/Requests/SubsystemRequest.cs b/AsbCloudApp/Requests/SubsystemRequest.cs index 4c5705d6..5b5851cc 100644 --- a/AsbCloudApp/Requests/SubsystemRequest.cs +++ b/AsbCloudApp/Requests/SubsystemRequest.cs @@ -7,10 +7,8 @@ namespace AsbCloudApp.Requests; /// /// класс с фильтрами для запроса /// -public class SubsystemRequest: RequestBase, IValidatableObject +public class SubsystemRequest: SubsystemBaseRequest { - private static readonly DateTimeOffset validationMinDate = new DateTimeOffset(2020,01,01,0,0,0, TimeSpan.Zero); - /// /// идентификатор скважины /// @@ -20,52 +18,5 @@ public class SubsystemRequest: RequestBase, IValidatableObject /// /// Идентификатор бурильщика /// - public int? IdDriller { get; set; } - - /// - /// Больше или равно дате - /// - public DateTimeOffset? GeDate { get; set; } - - /// - /// Меньше или равно дате - /// - public DateTimeOffset? LeDate { get; set; } - - /// - /// Больше или равно глубины забоя - /// - public double? GeDepth { get; set; } - - /// - /// Меньше или равно глубины забоя - /// - public double? LeDepth { get; set; } - - /// - public IEnumerable Validate(ValidationContext validationContext) - { - if (GeDate.HasValue && GeDate < validationMinDate) - yield return new ValidationResult( - $"Должно быть больше {validationMinDate:O})", - new[] { nameof(GeDate) }); - - if (LeDate.HasValue && GeDate.HasValue) - { - if (LeDate < GeDate) - yield return new ValidationResult( - $"{nameof(LeDate)} должно быть больше {nameof(GeDate)}. ({LeDate:O} < {GeDate:O})", - new[] { nameof(LeDate), nameof(GeDate) }); - } - - if (LeDepth.HasValue && GeDepth.HasValue) - { - if (LeDepth < GeDepth) - yield return new ValidationResult( - $"{nameof(LeDepth)} должно быть больше {nameof(GeDepth)}. ({LeDepth} < {GeDepth})", - new[] { nameof(LeDepth), nameof(GeDepth) }); - } - - yield break; - } + public int? IdDriller { get; set; } } diff --git a/AsbCloudApp/Services/ISubsystemService.cs b/AsbCloudApp/Services/ISubsystemService.cs index 9a14b01e..684053ca 100644 --- a/AsbCloudApp/Services/ISubsystemService.cs +++ b/AsbCloudApp/Services/ISubsystemService.cs @@ -37,4 +37,12 @@ public interface ISubsystemService /// Task> GetByWellsAsync(GetStatRequest request, CancellationToken token); + + /// + /// Получение статистики по плановым и фактическим подсистемам на скважинах + /// + /// параметры запроса + /// + /// + Task> GetStatPlanFactByWellsAsync(SubsystemPlanFactRequest request, CancellationToken token); } \ No newline at end of file diff --git a/AsbCloudApp/Services/ITelemetryDataSaubService.cs b/AsbCloudApp/Services/ITelemetryDataSaubService.cs index 3823788a..4a23ee87 100644 --- a/AsbCloudApp/Services/ITelemetryDataSaubService.cs +++ b/AsbCloudApp/Services/ITelemetryDataSaubService.cs @@ -15,14 +15,14 @@ public interface ITelemetryDataSaubService : ITelemetryDataService /// Получение телеметрии для РТК статистики /// - /// + /// /// /// /// /// /// /// - Task> Get(int idTelemetry, bool isBitOnBottom, DateTimeOffset geDate, DateTimeOffset leDate, int take, CancellationToken token); + Task> Get(IEnumerable idsTelemetries, bool isBitOnBottom, DateTimeOffset geDate, DateTimeOffset leDate, int take, CancellationToken token); /// /// усредненная статистика по 1м за весь период diff --git a/AsbCloudApp/Services/ITelemetryService.cs b/AsbCloudApp/Services/ITelemetryService.cs index c1b4ba99..7b20c53b 100644 --- a/AsbCloudApp/Services/ITelemetryService.cs +++ b/AsbCloudApp/Services/ITelemetryService.cs @@ -33,6 +33,13 @@ public interface ITelemetryService /// TelemetryDto GetOrCreateTelemetryByUid(string uid); + /// + /// получить список телеметрии по ключам скважин + /// + /// ключи скважин + /// + IEnumerable GetOrDefaultTelemetriesByIdsWells(IEnumerable idsWells); + /// /// получить временную зону скважины по idTelemetry /// diff --git a/AsbCloudInfrastructure.Tests/Services/DataSaubStatServiceTest.cs b/AsbCloudInfrastructure.Tests/Services/DataSaubStatServiceTest.cs index 486ddc97..80783c73 100644 --- a/AsbCloudInfrastructure.Tests/Services/DataSaubStatServiceTest.cs +++ b/AsbCloudInfrastructure.Tests/Services/DataSaubStatServiceTest.cs @@ -220,7 +220,7 @@ public class DataSaubStatServiceTest } dataSaubServiceMock - .Get(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + .Get(Arg.Any>(), Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) .Returns(telemetryDataSaubDtos); dataSaubStatService = new DataSaubStatService( diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index ca66ebe8..ab0065a8 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -308,7 +308,6 @@ public static class DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); - services.AddTransient(); services.AddTransient(); services.AddTransient, CrudWellRelatedRepositoryBase>(); services.AddTransient(); @@ -487,6 +486,9 @@ public static class DependencyInjection services.AddTransient(); services.AddTransient, TelemetryDataSpinService>(); + // Subsystem service + services.AddTransient(); + // Wits services.AddTransient, WitsRecordRepository>(); services.AddTransient, WitsRecordRepository>(); diff --git a/AsbCloudInfrastructure/Repository/ProcessMapPlanBaseRepository.cs b/AsbCloudInfrastructure/Repository/ProcessMapPlanBaseRepository.cs index 922071e4..82649a3f 100644 --- a/AsbCloudInfrastructure/Repository/ProcessMapPlanBaseRepository.cs +++ b/AsbCloudInfrastructure/Repository/ProcessMapPlanBaseRepository.cs @@ -34,6 +34,16 @@ public class ProcessMapPlanBaseRepository : ChangeLogRepositoryAb query = query.Where(e => e.Creation >= from || e.Obsolete >= from); } + if (request.GeDepth.HasValue) + { + query = query.Where(e => e.DepthEnd > request.GeDepth); + } + + if (request.LeDepth.HasValue) + { + query = query.Where(e => e.DepthStart < request.LeDepth); + } + return query; } diff --git a/AsbCloudInfrastructure/Services/DataSaubStatService.cs b/AsbCloudInfrastructure/Services/DataSaubStatService.cs index bdeaf6eb..82ee0416 100644 --- a/AsbCloudInfrastructure/Services/DataSaubStatService.cs +++ b/AsbCloudInfrastructure/Services/DataSaubStatService.cs @@ -78,7 +78,7 @@ public class DataSaubStatService : IDataSaubStatService var geDate = detectedOperations.First().DateStart; var leDate = detectedOperations.OrderByDescending(d => d.DateEnd).First().DateEnd; - var dataSaub = await dataSaubService.Get(idTelemetry, true, geDate, leDate, 100_000, token); + var dataSaub = await dataSaubService.Get([idTelemetry], true, geDate, leDate, 100_000, token); if (!dataSaub.Any()) return 0; diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs index 2516bd65..0abd8fdf 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs @@ -37,14 +37,19 @@ public class TelemetryDataSaubService : TelemetryDataBaseService> Get(int idTelemetry, bool isBitOnBottom, DateTimeOffset geDate, DateTimeOffset leDate, int take, CancellationToken token) + public async Task> Get(IEnumerable idsTelemetries, bool isBitOnBottom, DateTimeOffset geDate, DateTimeOffset leDate, int take, CancellationToken token) { - var offset = telemetryService.GetTimezone(idTelemetry).Offset; + var offsetDict = new Dictionary(); + foreach (var idTelemetry in idsTelemetries) + { + offsetDict.Add(idTelemetry, telemetryService.GetTimezone(idTelemetry).Offset); + } + var geDateUtc = geDate.ToUniversalTime(); var leDateUtc = leDate.ToUniversalTime(); var query = db.Set() - .Where(t => t.IdTelemetry == idTelemetry) + .Where(t => idsTelemetries.Contains(t.IdTelemetry)) .Where(t => t.DateTime >= geDateUtc) .Where(t => t.DateTime <= leDateUtc); @@ -56,7 +61,7 @@ public class TelemetryDataSaubService : TelemetryDataBaseService Convert(e, offset.TotalHours)); + var dtos = entities.Select(e => Convert(e, offsetDict.GetValueOrDefault(e.IdTelemetry).TotalHours)); return dtos; } diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs index 6de56bdc..a13aa7ae 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs @@ -42,7 +42,7 @@ public class TelemetryService : ITelemetryService private IEnumerable GetTelemetryCache() => memoryCache.GetOrCreateBasic( db.Set() - .Include(t => t.Well)); + .Include(t => t.Well)); private void DropTelemetryCache() { @@ -167,6 +167,27 @@ public class TelemetryService : ITelemetryService return dto; } + public IEnumerable GetOrDefaultTelemetriesByIdsWells(IEnumerable idsWells) + { + var entities = GetTelemetryCache() + .Where(t => t.Well != null) + .Where(t => idsWells.Contains(t.Well!.Id)) + .Select(t => { + t.TimeZone = t.TimeZone.Hours != t.Well!.Timezone.Hours ? t.Well.Timezone : t.TimeZone; + + return t; + }); + + var dtos = entities.Select(t => { + var dto = t.Adapt(); + dto.IdWell = t.Well?.Id; + + return dto; + }); + + return dtos; + } + private Well? GetWellByTelemetryUid(string uid) { var telemetry = GetOrDefaultTelemetryByUid(uid); diff --git a/AsbCloudInfrastructure/Services/Subsystems/SubsystemService.cs b/AsbCloudInfrastructure/Services/Subsystems/SubsystemService.cs index 76bcefa2..05711fe0 100644 --- a/AsbCloudInfrastructure/Services/Subsystems/SubsystemService.cs +++ b/AsbCloudInfrastructure/Services/Subsystems/SubsystemService.cs @@ -1,20 +1,22 @@ +using AsbCloudApp.Data; +using AsbCloudApp.Data.DetectedOperation; +using AsbCloudApp.Data.ProcessMaps; +using AsbCloudApp.Data.Subsystems; +using AsbCloudApp.Exceptions; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests; +using AsbCloudApp.Services; +using AsbCloudDb.Model; +using AsbCloudInfrastructure.Services.DetectOperations; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using AsbCloudApp.Data; -using AsbCloudApp.Data.DetectedOperation; -using AsbCloudApp.Data.Subsystems; -using AsbCloudApp.Exceptions; -using AsbCloudApp.Requests; -using AsbCloudApp.Services; -using AsbCloudDb.Model; -using AsbCloudInfrastructure.Services.DetectOperations; namespace AsbCloudInfrastructure.Services.Subsystems; -internal class SubsystemService : ISubsystemService +public class SubsystemService : ISubsystemService { private const int IdSubsystemAPD = 1; private const int IdSubsystemAPDRotor = 11; @@ -26,18 +28,27 @@ internal class SubsystemService : ISubsystemService private readonly IWellService wellService; private readonly IDetectedOperationService detectedOperationService; private readonly IScheduleRepository scheduleRepository; + private readonly ITelemetryDataSaubService telemetryDataSaubService; + private readonly ITelemetryService telemetryService; + private readonly IChangeLogRepository processMapPlanRepository; private IDictionary subsystems = new Dictionary(); public SubsystemService(ICrudRepository subsystemRepository, IWellService wellService, IDetectedOperationService detectedOperationService, - IScheduleRepository scheduleRepository) + IScheduleRepository scheduleRepository, + ITelemetryService telemetryService, + ITelemetryDataSaubService telemetryDataSaubService, + IChangeLogRepository processMapPlanRepository) { this.wellService = wellService; this.subsystemRepository = subsystemRepository; this.detectedOperationService = detectedOperationService; this.scheduleRepository = scheduleRepository; + this.telemetryService = telemetryService; + this.telemetryDataSaubService = telemetryDataSaubService; + this.processMapPlanRepository = processMapPlanRepository; } // получить расписания бурильщиков по скважинам // ScheduleRepository добавить новый метод @@ -57,11 +68,11 @@ internal class SubsystemService : ISubsystemService var result = new List(); var schedulePage = await scheduleRepository.GetPageAsync(request, token); var wells = await wellService.GetAsync(new WellRequest { Ids = request.IdsWells }, token); - + foreach (var schedule in schedulePage) { var idWell = schedule.IdWell; - var well = wells.FirstOrDefault(w=> w.Id == idWell)!; + var well = wells.FirstOrDefault(w => w.Id == idWell)!; var byWellRequest = new DetectedOperationByWellRequest(idWell, new DetectedOperationRequest()); @@ -124,6 +135,70 @@ internal class SubsystemService : ISubsystemService return result; } + public async Task> GetStatPlanFactByWellsAsync(SubsystemPlanFactRequest request, CancellationToken token) + { + var telemetriesDict = telemetryService + .GetOrDefaultTelemetriesByIdsWells(request.IdsWell) + .ToDictionary(t => t.Id, t => t.IdWell); + + var dtNow = DateTimeOffset.UtcNow; + var geDate = request.GeDate ?? new DateTimeOffset(dtNow.Date); + var leDate = request.LeDate ?? geDate.AddDays(1).AddMinutes(-1); + var telemetryDataSaub = await telemetryDataSaubService.Get(telemetriesDict.Keys, false, geDate, leDate, 100_000, token); + + var groupedTelemetryDataSaub = telemetryDataSaub + .GroupBy(t => t.IdTelemetry) + .ToDictionary(t => t.Key, t => new + { + IdWell = telemetriesDict.GetValueOrDefault(t.Key)!, + MinDepth = t.MinBy(x => x.WellDepth)!.WellDepth, + MaxDepth = t.MaxBy(x => x.WellDepth)!.WellDepth + }); + + var result = new List(); + + foreach (var telemetryDataSaubItem in groupedTelemetryDataSaub) + { + var telemetryDataSaubInfo = telemetryDataSaubItem.Value; + var requestProcessMapPlan = new ProcessMapPlanBaseRequestWithWell(telemetryDataSaubInfo.IdWell!.Value, telemetryDataSaubInfo.MinDepth, telemetryDataSaubInfo.MaxDepth); + var processMapPlanSubsystems = await processMapPlanRepository.GetCurrent(requestProcessMapPlan, token); + + foreach (var processMapPlanSubsystem in processMapPlanSubsystems) + { + var stat = new SubsystemPlanFactStatDto(); + stat.IdWell = processMapPlanSubsystem.IdWell; + stat.IdWellSectionType = processMapPlanSubsystem.IdWellSectionType; + stat.DepthStart = processMapPlanSubsystem.DepthStart < telemetryDataSaubInfo.MinDepth + ? telemetryDataSaubInfo.MinDepth + : processMapPlanSubsystem.DepthStart; + stat.DepthEnd = processMapPlanSubsystem.DepthEnd > telemetryDataSaubInfo.MaxDepth + ? telemetryDataSaubInfo.MaxDepth + : processMapPlanSubsystem.DepthEnd; + stat.AutoRotorPlan = processMapPlanSubsystem.AutoRotor; + stat.AutoSlidePlan = processMapPlanSubsystem.AutoSlide; + stat.AutoOscillationPlan = processMapPlanSubsystem.AutoOscillation; + + var subsystemRequest = new SubsystemRequest() + { + IdWell = telemetriesDict.GetValueOrDefault(telemetryDataSaubItem.Key)!.Value, + GeDepth = stat.DepthStart, + LeDepth = stat.DepthEnd + }; + var subsystemStatFact = await GetStatAsync(subsystemRequest, token); + var subsystemStatFactDict = subsystemStatFact.ToDictionary(s => s.IdSubsystem); + + stat.AutoRotorFact = subsystemStatFactDict.GetValueOrDefault(IdSubsystemAPDRotor)?.KUsage; + stat.AutoSlideFact = subsystemStatFactDict.GetValueOrDefault(IdSubsystemAPDSlide)?.KUsage; + stat.AutoOscillationFact = subsystemStatFactDict.GetValueOrDefault(IdSubsystemOscillation)?.KUsage; + + result.Add(stat); + } + } + + return result; + } + + private async Task> CalcStatAsync( IEnumerable operations, CancellationToken token) { @@ -157,7 +232,7 @@ internal class SubsystemService : ISubsystemService SumDepthInterval = sumDepthInterval, OperationCount = operationCount, }; - if(oscillationStat.SumOperationDepthInterval != 0d) + if (oscillationStat.SumOperationDepthInterval != 0d) oscillationStat.KUsage = oscillationStat.SumDepthInterval / oscillationStat.SumOperationDepthInterval; return oscillationStat; diff --git a/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs b/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs index b4402ca6..4314cdf2 100644 --- a/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs +++ b/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs @@ -80,6 +80,24 @@ public class SubsystemController : ControllerBase return Ok(result); } + /// + /// получить статистику по плановым и фактическим подсистемам на скважинах + /// + [HttpGet("/api/serviceWork/subsystemWells")] + [Permission] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetStatPlanFactAsync([FromQuery] SubsystemPlanFactRequest request, CancellationToken token) + { + foreach (var idWell in request.IdsWell) + { + if (!await UserHasAccessToWellAsync(idWell, token)) + return Forbid(); + } + var subsystemStat = await subsystemService.GetStatPlanFactByWellsAsync(request, token); + + return Ok(subsystemStat); + } + private async Task UserHasAccessToWellAsync(int idWell, CancellationToken token) { var idCompany = User.GetCompanyId();