From 312d653aec96e14799a4f9eb19b429274435cd18 Mon Sep 17 00:00:00 2001
From: ngfrolov <ng.frolov@autodrilling.ru>
Date: Fri, 7 Apr 2023 16:49:28 +0500
Subject: [PATCH] fix #9844930; Enable nullable for OperationsStatService.

---
 .../Services/IOperationsStatService.cs        |   6 +-
 .../Services/SAUB/TelemetryDataSaubService.cs |   2 +-
 .../OperationsStatService.cs                  | 178 +++++++++---------
 .../Services/WellOperationService/Race.cs     |   3 +-
 .../Controllers/OperationStatController.cs    |  10 +-
 .../Controllers/WellOperationController.cs    |   2 +-
 AsbCloudWebApi/Rest/OperationStat.http        |  46 +++++
 7 files changed, 147 insertions(+), 100 deletions(-)
 create mode 100644 AsbCloudWebApi/Rest/OperationStat.http

diff --git a/AsbCloudApp/Services/IOperationsStatService.cs b/AsbCloudApp/Services/IOperationsStatService.cs
index 6ceb76e1..a92d0553 100644
--- a/AsbCloudApp/Services/IOperationsStatService.cs
+++ b/AsbCloudApp/Services/IOperationsStatService.cs
@@ -16,7 +16,7 @@ namespace AsbCloudApp.Services
         /// <param name="idWell"></param>
         /// <param name="token"></param>
         /// <returns></returns>
-        Task<ClusterRopStatDto> GetRopStatAsync(int idWell, CancellationToken token);
+        Task<ClusterRopStatDto?> GetOrDefaultRopStatAsync(int idWell, CancellationToken token);
 
         /// <summary>
         /// Получить статистику по скважинам куста, которые доступны компании
@@ -25,7 +25,7 @@ namespace AsbCloudApp.Services
         /// <param name="idCompany"></param>
         /// <param name="token"></param>
         /// <returns></returns>
-        Task<StatClusterDto> GetStatClusterAsync(int idCluster, int idCompany, CancellationToken token = default);
+        Task<StatClusterDto?> GetOrDefaultStatClusterAsync(int idCluster, int idCompany, CancellationToken token);
 
         /// <summary>
         /// получить статистику по скважине
@@ -33,7 +33,7 @@ namespace AsbCloudApp.Services
         /// <param name="idWell"></param>
         /// <param name="token"></param>
         /// <returns></returns>
-        Task<StatWellDto> GetWellStatAsync(int idWell, CancellationToken token = default);
+        Task<StatWellDto?> GetOrDefaultWellStatAsync(int idWell, CancellationToken token);
 
         /// <summary>
         /// Получить данные для графика TVD
diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs
index ddebda4b..af16e2a1 100644
--- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs
+++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs
@@ -43,7 +43,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
                 .Where(t => t.BlockPosition > 0.0001)
                 .Where(t => t.WellDepth > 0.0001)
                 .Where(t => t.Mode != null)
-                .Where(t => modes.Contains(t.Mode.Value))
+                .Where(t => modes.Contains(t.Mode!.Value))
                 .Where(t => t.WellDepth - t.BitDepth < 0.01)
                 .GroupBy(t => new { 
                     t.DateTime.Hour,
diff --git a/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs b/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs
index 1e1dd035..68368e63 100644
--- a/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs
+++ b/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs
@@ -7,12 +7,12 @@ using Microsoft.Extensions.Caching.Memory;
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Numerics;
 using System.Threading;
 using System.Threading.Tasks;
 
 namespace AsbCloudInfrastructure.Services.WellOperationService
 {
+#nullable enable
     public class OperationsStatService : IOperationsStatService
     {
         private readonly IAsbCloudDbContext db;
@@ -26,8 +26,15 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
             this.wellService = wellService;
         }
 
-        public async Task<StatClusterDto> GetStatClusterAsync(int idCluster, int idCompany, CancellationToken token = default)
+        public async Task<StatClusterDto?> GetOrDefaultStatClusterAsync(int idCluster, int idCompany, CancellationToken token)
         {
+            var cluster = (await memoryCache
+                .GetOrCreateBasicAsync(db.Set<Cluster>(), token))
+                .FirstOrDefault(c => c.Id == idCluster);
+
+            if (cluster is null)
+                return null;
+
             var allWellsByCompany = await wellService.GetAsync(new() { IdCompany = idCompany }, token).ConfigureAwait(false);
 
             var idWellsByCompany = allWellsByCompany.Select(w => w.Id).Distinct();
@@ -41,9 +48,6 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
 
             var statsWells = await GetWellsStatAsync(wells, token).ConfigureAwait(false);
 
-            var cluster = (await memoryCache
-                .GetOrCreateBasicAsync(db.Set<Cluster>(), token))
-                .FirstOrDefault(c => c.Id == idCluster);
             var statClusterDto = new StatClusterDto
             {
                 Id = idCluster,
@@ -71,7 +75,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
             return statsWells;
         }
 
-        public async Task<StatWellDto> GetWellStatAsync(int idWell,
+        public async Task<StatWellDto?> GetOrDefaultWellStatAsync(int idWell,
             CancellationToken token = default)
         {
             var well = await db.Wells
@@ -79,11 +83,14 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
                 .FirstOrDefaultAsync(w => w.Id == idWell, token)
                 .ConfigureAwait(false);
 
+            if(well is null)
+                return null;
+
             var statWellDto = await CalcWellStatAsync(well, token);
             return statWellDto;
         }
 
-        public async Task<ClusterRopStatDto> GetRopStatAsync(int idWell, CancellationToken token)
+        public async Task<ClusterRopStatDto?> GetOrDefaultRopStatAsync(int idWell, CancellationToken token)
         {
             var clusterWellsIds = await wellService.GetClusterWellsIdsAsync(idWell, token)
                 .ConfigureAwait(false);
@@ -110,13 +117,15 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
                 .ToListAsync(token)
                 .ConfigureAwait(false);
 
-            var statsList = clusterWellsIds.Select(clusterWellId =>
+            var statsList = new List<StatOperationsDto>(clusterWellsIds.Count());
+            foreach (var clusterWellId in clusterWellsIds)
             {
                 var currentWellOps = operations.Where(o => o.IdWell == clusterWellId);
-                var timezoneOffsetH = wellService.GetTimezone(clusterWellId).Hours;
-                var stat = CalcStat(currentWellOps, timezoneOffsetH);
-                return stat;
-            }).Where(c => c is not null);
+                var timezoneOffsetHours = wellService.GetTimezone(clusterWellId).Hours;
+                var stat = CalcStat(currentWellOps, timezoneOffsetHours);
+                if(stat is not null)
+                    statsList.Add(stat);
+            };
 
             if (!statsList.Any())
                 return null;
@@ -130,7 +139,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
             return clusterRops;
         }
 
-        private async Task<StatWellDto> CalcWellStatAsync(Well well, CancellationToken token = default)
+        private async Task<StatWellDto> CalcWellStatAsync(Well well, CancellationToken token)
         {
             var wellType = (await memoryCache
                 .GetOrCreateBasicAsync(db.Set<WellType>(), token))
@@ -164,7 +173,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
             return statWellDto;
         }
 
-        private double CalcTvdLagDays(IOrderedEnumerable<WellOperation> wellOperations)
+        private static double CalcTvdLagDays(IOrderedEnumerable<WellOperation> wellOperations)
         {
             var operationsOrdered = wellOperations
                 .OrderBy(o => o.DateStart);
@@ -178,9 +187,13 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
             if (lastCorrespondingFactOperation is null)
                 return 0d;
             
-            var lastCorrespondingPlanOperation = wellOperations.FirstOrDefault(o => o.Id == lastCorrespondingFactOperation.IdPlan);
+            var lastCorrespondingPlanOperation = wellOperations
+                .FirstOrDefault(o => o.Id == lastCorrespondingFactOperation.IdPlan);
 
-            var lastFactOperation = factOperations.LastOrDefault();
+            if (lastCorrespondingPlanOperation is null) 
+                return 0d;
+
+            var lastFactOperation = factOperations.Last();
 
             var remainingPlanOperations = operationsOrdered
                 .Where(o => o.IdType == WellOperation.IdOperationTypePlan)
@@ -240,27 +253,27 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
             return section;
         }
 
-        private static StatOperationsDto CalcSectionStat(IEnumerable<WellOperation> operations, int idSectionType, double timezoneOffsetH)
+        private static StatOperationsDto? CalcSectionStat(IEnumerable<WellOperation> operations, int idSectionType, double timezoneOffsetHours)
         {
             var sectionOperations = operations
                 .Where(o => o.IdWellSectionType == idSectionType)
                 .OrderBy(o => o.DateStart)
                 .ThenBy(o => o.DepthStart);
 
-            return CalcStat(sectionOperations, timezoneOffsetH);
+            return CalcStat(sectionOperations, timezoneOffsetHours);
         }
 
-        private static StatOperationsDto CalcStat(IEnumerable<WellOperation> operations, double timezoneOffsetH)
+        private static StatOperationsDto? CalcStat(IEnumerable<WellOperation> operations, double timezoneOffsetHours)
         {
             if (!operations.Any())
                 return null;
 
-            var races = GetCompleteRaces(operations, timezoneOffsetH);
+            var races = GetCompleteRaces(operations, timezoneOffsetHours);
 
             var section = new StatOperationsDto
             {
-                Start = operations.FirstOrDefault()?.DateStart.ToRemoteDateTime(timezoneOffsetH),
-                End = operations.Max(o => o.DateStart.ToRemoteDateTime(timezoneOffsetH).AddHours(o.DurationHours)),
+                Start = operations.FirstOrDefault()?.DateStart.ToRemoteDateTime(timezoneOffsetHours),
+                End = operations.Max(o => o.DateStart.ToRemoteDateTime(timezoneOffsetHours).AddHours(o.DurationHours)),
                 WellDepthStart = operations.Min(o => o.DepthStart),
                 WellDepthEnd = operations.Max(o => o.DepthStart),
                 Rop = CalcROP(operations),
@@ -356,7 +369,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
         {
             var dDepth = 0d;
             var dHours = 0d;
-            foreach (var race in races)
+            foreach (Race race in races)
             {
                 dDepth += race.StartWellDepth;
                 for (var i = 0; i < race.Operations.Count; i++)
@@ -417,78 +430,71 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
 
             var tzOffsetHours = wellService.GetTimezone(idWell).Hours;
 
-            if (!wellOperationsPlan.Any())
-                return null;
-
-            var merged = MergeArraysBySections(sectionsIds, wellOperationsPlan, wellOperationsFact);
+            var merged = MergeArraysBySections(sectionsIds, wellOperationsPlan, wellOperationsFact).ToList();
             var tvd = new List<PlanFactPredictBase<WellOperationDto>>(merged.Count);
-            var firstPoint = merged.First();
-            var dateStart = firstPoint.Item1?.DateStart ?? firstPoint.Item2.DateStart;
-            int iLastMatch = 0;
+            var (Plan, Fact) = merged.First();
+            var dateStart = Plan?.DateStart ?? Fact!.DateStart;
+            int? iLastMatch = null;
             int iLastFact = 0;
             var nptHours = 0d;
             for (int i = 0; i < merged.Count; i++)
             {
                 var item = merged[i];
-                var plan = item.Item1;
-                var fact = item.Item2;
+                var plan = item.Plan;
+                var fact = item.Fact;
 
-                if (fact is not null && WellOperationCategory.NonProductiveTimeSubIds.Contains(fact.IdCategory))
+                var planFactPredict = new PlanFactPredictBase<WellOperationDto>();
+                if (plan is not null)
                 {
-                    nptHours += fact.DurationHours;
+                    planFactPredict.Plan = Convert(plan, tzOffsetHours);
+                    planFactPredict.Plan.Day = (planFactPredict.Plan.DateStart - dateStart).TotalDays;
+                    if (fact is not null)
+                        iLastMatch = i;
                 }
 
-                var planFactPredict = new PlanFactPredictBase<WellOperationDto>
+                if (fact is not null)
                 {
-                    Plan = Convert(plan, tzOffsetHours),
-                    Fact = Convert(fact, tzOffsetHours),
-                    Predict = null,
-                };
+                    if(WellOperationCategory.NonProductiveTimeSubIds.Contains(fact.IdCategory))
+                        nptHours += fact.DurationHours;
 
-                if (planFactPredict.Plan is not null)
-                    planFactPredict.Plan.Day = (planFactPredict.Plan.DateStart - dateStart).TotalDays;
-
-                if (planFactPredict.Fact is not null)
-                {
+                    planFactPredict.Fact = Convert(fact, tzOffsetHours);
                     planFactPredict.Fact.Day = (planFactPredict.Fact.DateStart - dateStart).TotalDays;
                     planFactPredict.Fact.NptHours = nptHours;
+                    iLastFact = i;
                 }
 
-                tvd.Add(planFactPredict);
-                if ((plan is not null) && (fact is not null))
-                    iLastMatch = i;
-                if (fact is not null)
-                    iLastFact = i;
+                tvd.Add(planFactPredict);                    
             }
 
-            if (iLastMatch == 0 || iLastMatch == merged.Count - 1)
+            if (iLastMatch is null || iLastMatch == merged.Count - 1)
                 return tvd;
 
-            var lastMatchPlan = merged[iLastMatch].Item1;
+            var lastMatchPlan = merged[iLastMatch.Value].Plan!;
             var lastMatchPlanOperationEnd = lastMatchPlan.DateStart.AddHours(lastMatchPlan.DurationHours);
-            var lastFact = merged[iLastFact].Item2;
+            var lastFact = merged[iLastFact].Fact!;
             var lastFactDateEnd = lastFact.DateStart.AddHours(lastFact.DurationHours);
             var startOffset = lastFactDateEnd - lastMatchPlanOperationEnd;
 
-            for (int i = iLastMatch + 1; i < merged.Count; i++)
+            for (int i = iLastMatch.Value + 1; i < merged.Count; i++)
             {
-                if (merged[i].Item1 is null)
+                if (merged[i].Plan is null)
                     continue;
-                tvd[i].Predict = Convert(merged[i].Item1, tzOffsetHours);
-                tvd[i].Predict.IdType = 2;
-                tvd[i].Predict.DateStart = tvd[i].Predict.DateStart + startOffset;
-                tvd[i].Predict.Day = (tvd[i].Predict.DateStart - dateStart).TotalDays;
+                var predict = Convert(merged[i].Plan!, tzOffsetHours);
+                predict.IdType = 2;
+                predict.DateStart = predict.DateStart + startOffset;
+                predict.Day = (predict.DateStart - dateStart).TotalDays;
+                tvd[i].Predict = predict;
             }
 
             return tvd;
         }
 
-        private static List<Tuple<WellOperation, WellOperation>> MergeArraysBySections(
+        private static IEnumerable<(WellOperation? Plan, WellOperation? Fact)> MergeArraysBySections(
             IEnumerable<int> sectionsIds,
             IOrderedEnumerable<WellOperation> wellOperationsPlan,
             IOrderedEnumerable<WellOperation> wellOperationsFact)
         {
-            var merged = new List<Tuple<WellOperation, WellOperation>>(wellOperationsPlan.Count());
+            var merged = new List<(WellOperation? Plan, WellOperation? Fact)>(wellOperationsPlan.Count());
             foreach (var sectionId in sectionsIds)
             {
                 var sectionOperationsPlan = wellOperationsPlan
@@ -501,46 +507,38 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
             return merged;
         }
 
-        private static List<Tuple<WellOperation, WellOperation>> MergeArrays(IEnumerable<WellOperation> operationsPlan, IEnumerable<WellOperation> operationsFact)
+        private static IEnumerable<(WellOperation? Plan, WellOperation? Fact)> MergeArrays(IEnumerable<WellOperation> operationsPlan, IEnumerable<WellOperation> operationsFact)
         {
-            var result = new List<Tuple<WellOperation, WellOperation>>();
+            var operationsFactWithNoPlan = operationsFact.Where(x => x.IdPlan == null).ToArray();
+            var operationsFactWithPlan = operationsFact.Where(x => x.IdPlan != null).ToArray();
 
-            var oparationsFactWithNoPlan = operationsFact
-                .Where(x => x.IdPlan == null)
-                .Select(x => new Tuple<WellOperation, WellOperation>(null, x));
+            var idsPlanWithFact = operationsFact.Where(x => x.IdPlan is not null).Select(x => x.IdPlan).Distinct();
+            var operationsPlanWithNoFact = operationsPlan.Where(x => !idsPlanWithFact.Contains(x.IdPlan)).ToArray();
 
-            var oparationsFactWithPlan = operationsFact
-                .Where(x => x.IdPlan != null)
-                .Select(x => new Tuple<WellOperation, WellOperation>(x.OperationPlan, x));
+            var result = new List<(WellOperation? Plan, WellOperation? Fact)>(operationsFactWithNoPlan.Length + operationsFactWithPlan.Length + operationsPlanWithNoFact.Length);
 
-            var idsPlanWithFact = operationsFact
-                .Where(x => x.IdPlan is not null)
-                .Select(x => x.IdPlan)
-                .Distinct();
-            var oparationsPlanWithNoFact = operationsPlan
-                .Where(x => !idsPlanWithFact.Contains(x.IdPlan))
-                .Select(x => new Tuple<WellOperation, WellOperation>(x, null));
+            foreach (var operation in operationsFactWithPlan)
+                result.Add((operation.OperationPlan, operation));
 
-            result.AddRange(oparationsFactWithNoPlan);
-            result.AddRange(oparationsFactWithPlan);
-            result.AddRange(oparationsPlanWithNoFact);
+            foreach (var operation in operationsFactWithNoPlan)
+                result.Add((null, operation));
 
-            result = result
-                .OrderBy(x => x.Item1?.DateStart)
-                .ThenBy(x => x.Item2?.DateStart)
-                .ToList();
-            return result;
+            foreach (var operation in operationsPlanWithNoFact)
+                result.Add((operation, null));
+
+            return result
+                .OrderBy(x => x.Plan?.DateStart)
+                .ThenBy(x => x.Fact?.DateStart);
         }
 
         private static WellOperationDto Convert(WellOperation source, double tzOffsetHours)
         {
-            if (source is null)
-                return null;
-            var dest = source.Adapt<WellOperationDto>();
-            dest.CategoryName = source.OperationCategory?.Name;
-            dest.WellSectionTypeName = source.WellSectionType?.Caption;
-            dest.DateStart = source.DateStart.ToRemoteDateTime(tzOffsetHours);
-            return dest;
+            var destination = source.Adapt<WellOperationDto>();
+            destination.CategoryName = source.OperationCategory?.Name;
+            destination.WellSectionTypeName = source.WellSectionType?.Caption;
+            destination.DateStart = source.DateStart.ToRemoteDateTime(tzOffsetHours);
+            return destination;
         }
     }
+#nullable disable
 }
diff --git a/AsbCloudInfrastructure/Services/WellOperationService/Race.cs b/AsbCloudInfrastructure/Services/WellOperationService/Race.cs
index e279111d..182ac88d 100644
--- a/AsbCloudInfrastructure/Services/WellOperationService/Race.cs
+++ b/AsbCloudInfrastructure/Services/WellOperationService/Race.cs
@@ -1,6 +1,7 @@
 using AsbCloudDb.Model;
 using System;
 using System.Collections.Generic;
+using System.Linq;
 
 namespace AsbCloudInfrastructure.Services.WellOperationService
 {
@@ -60,7 +61,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
         /// <summary>
         /// Список операций за рейс
         /// </summary>
-        public List<WellOperation>? Operations { get; internal set; }
+        public List<WellOperation> Operations { get; internal set; } = new List<WellOperation>();
     }
 #nullable disable
 }
diff --git a/AsbCloudWebApi/Controllers/OperationStatController.cs b/AsbCloudWebApi/Controllers/OperationStatController.cs
index cce509fb..d32ea4b7 100644
--- a/AsbCloudWebApi/Controllers/OperationStatController.cs
+++ b/AsbCloudWebApi/Controllers/OperationStatController.cs
@@ -9,6 +9,7 @@ using System.Threading.Tasks;
 
 namespace AsbCloudWebApi.Controllers
 {
+#nullable enable
     /// <summary>
     /// Статистика по операциям (заведенным вручную) на скважине
     /// </summary>
@@ -41,7 +42,7 @@ namespace AsbCloudWebApi.Controllers
             if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
                 return Forbid();
 
-            var result = await operationsStatService.GetRopStatAsync(
+            var result = await operationsStatService.GetOrDefaultRopStatAsync(
                 idWell, token).ConfigureAwait(false);
 
             return Ok(result);
@@ -64,7 +65,7 @@ namespace AsbCloudWebApi.Controllers
             if (idWell is null)
                 return NoContent();
 
-            var result = await operationsStatService.GetRopStatAsync(
+            var result = await operationsStatService.GetOrDefaultRopStatAsync(
                 (int)idWell, token).ConfigureAwait(false);
 
             return Ok(result);
@@ -87,7 +88,7 @@ namespace AsbCloudWebApi.Controllers
             if (idCompany is null)
                 return Forbid();
 
-            var result = await operationsStatService.GetStatClusterAsync(idCluster, idCompany.Value, token)
+            var result = await operationsStatService.GetOrDefaultStatClusterAsync(idCluster, idCompany.Value, token)
                 .ConfigureAwait(false);
             return Ok(result);
         }
@@ -132,7 +133,7 @@ namespace AsbCloudWebApi.Controllers
             if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
                 return Forbid();
 
-            var result = await operationsStatService.GetWellStatAsync(idWell, token)
+            var result = await operationsStatService.GetOrDefaultWellStatAsync(idWell, token)
                 .ConfigureAwait(false);
             return Ok(result);
         }
@@ -165,4 +166,5 @@ namespace AsbCloudWebApi.Controllers
                 idWell, token).ConfigureAwait(false);
         }
     }
+#nullable disable
 }
diff --git a/AsbCloudWebApi/Controllers/WellOperationController.cs b/AsbCloudWebApi/Controllers/WellOperationController.cs
index ae1943a6..c5174f2c 100644
--- a/AsbCloudWebApi/Controllers/WellOperationController.cs
+++ b/AsbCloudWebApi/Controllers/WellOperationController.cs
@@ -378,7 +378,7 @@ namespace AsbCloudWebApi.Controllers
         [Route("template")]
         [AllowAnonymous]
         [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)]
-        public IActionResult GetTamplate()
+        public IActionResult GetTemplate()
         {
             var stream = wellOperationImportService.GetExcelTemplateStream();
             var fileName = "ЕЦП_шаблон_файла_операций.xlsx";
diff --git a/AsbCloudWebApi/Rest/OperationStat.http b/AsbCloudWebApi/Rest/OperationStat.http
new file mode 100644
index 00000000..975f54b5
--- /dev/null
+++ b/AsbCloudWebApi/Rest/OperationStat.http
@@ -0,0 +1,46 @@
+@baseUrl = http://127.0.0.1:5000
+@contentType = application/json
+@auth = Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImN0eSI6IkpXVCJ9.eyJpZCI6IjEiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiZGV2IiwiaWRDb21wYW55IjoiMSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6InJvb3QiLCJuYmYiOjE2NjI1NDgxNjIsImV4cCI6MTY5NDEwNTc2MiwiaXNzIjoiYSIsImF1ZCI6ImEifQ.OEAlNzxi7Jat6pzDBTAjTbChskc-tdJthJexyWwwUKE
+
+@uid = 20210910_012752700
+@idCluster = 1
+@idWell = 1 
+#295
+
+# https://marketplace.visualstudio.com/items?itemName=humao.rest-client
+
+### 
+GET {{baseUrl}}/api/well/{{idWell}}/ropStat
+Content-Type: {{contentType}}
+accept: */*
+Authorization: {{auth}}
+
+### 
+GET {{baseUrl}}/api/telemetry/{{uid}}/ropStat
+Content-Type: {{contentType}}
+accept: */*
+Authorization: {{auth}}
+
+### 
+GET {{baseUrl}}/api/cluster/{{idCluster}}/stat
+Content-Type: {{contentType}}
+accept: */*
+Authorization: {{auth}}
+
+### 
+GET {{baseUrl}}/api/wellsStats?idWells=1&idWells={{idWell}}
+Content-Type: {{contentType}}
+accept: */*
+Authorization: {{auth}}
+
+### 
+GET {{baseUrl}}/api/well/{{idWell}}/stat
+Content-Type: {{contentType}}
+accept: */*
+Authorization: {{auth}}
+
+### 
+GET {{baseUrl}}/api/well/{{idWell}}/tvd
+Content-Type: {{contentType}}
+accept: */*
+Authorization: {{auth}}