From 8bbaca0d0cce26c4c2acb9228508ab403fd8a1b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Wed, 22 Nov 2023 14:47:17 +0500 Subject: [PATCH 01/10] =?UTF-8?q?=D0=9D=D0=BE=D0=B2=D1=8B=D0=B5=20=D1=80?= =?UTF-8?q?=D0=B0=D1=81=D1=87=D1=91=D1=82=D1=8B=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D0=B0=D0=B2=D1=82=D0=BE=D0=BC=D0=B0=D1=82=D0=B8=D1=87=D0=B5?= =?UTF-8?q?=D1=81=D0=BA=D0=BE=D0=B3=D0=BE=20=D0=BE=D0=BF=D1=80=D0=B5=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BE=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Поправел excel шаблон 2. Доработаны алгоритмы определения операций бурения 3. Небольшой рефакторинг DetectorAbstract, добавил метод для валидации 4. Закомментированы неиспользуемые детекторы. 5. Обновлена спецификация определения операций бурения 6. Добавлены тесты для определения операций бурения --- .../DetectOperations/DetectOperations.xlsx | Bin 15436 -> 15404 bytes .../DetectedOperationExportService.cs | 22 +- .../Detectors/DetectorAbstract.cs | 79 ++--- .../Detectors/DetectorDevelopment.cs | 134 ++++---- .../Detectors/DetectorDrilling.cs | 39 ++- .../Detectors/DetectorSlipsTime.cs | 78 ++--- .../DetectOperations/Detectors/readme.md | 1 - .../Specifications/Бурение ротор и слайд.md | 46 ++- .../WorkOperationDetection.cs | 29 +- .../Detectors/DetectorDrillingTests.cs | 290 ++++++++++++++++++ 10 files changed, 506 insertions(+), 212 deletions(-) delete mode 100644 AsbCloudInfrastructure/Services/DetectOperations/Detectors/readme.md create mode 100644 AsbCloudWebApi.Tests/Services/DetectedOperations/Detectors/DetectorDrillingTests.cs diff --git a/AsbCloudInfrastructure/Services/DetectOperations/DetectOperations.xlsx b/AsbCloudInfrastructure/Services/DetectOperations/DetectOperations.xlsx index 9073c58dcc6ba789363fbf4d6d438636f41260c1..1c366050097ce39261c518d89f23a5d14b0db8f0 100644 GIT binary patch delta 5427 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 delta 5421 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 diff --git a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs index 3c1550c1..cfb115f0 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs @@ -14,7 +14,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations; public class DetectedOperationExportService { - private readonly DetectorAbstract[] detectors = { new DetectorDrilling(), new DetectorSlipsTime() }; + private readonly DetectorAbstract[] detectors = { new DetectorDrilling() }; private readonly IDictionary domains = new Dictionary { @@ -122,10 +122,17 @@ public class DetectedOperationExportService row.Cell(columnDepthStart).Value = detectedOperations[i].DepthStart; row.Cell(columnDepthEnd).Value = detectedOperations[i].DepthEnd; row.Cell(columnDepth).Value = detectedOperations[i].DepthEnd - detectedOperations[i].DepthStart; - row.Cell(columnIdReasonOfEnd).Value = detectedOperations[i].IdReasonOfEnd; + row.Cell(columnIdReasonOfEnd).Value = detectedOperations[i].IdReasonOfEnd switch + { + 0 => "Не определена", + 1 => "Не определено начало операции", + 101 => "Разница глубин забоя и положением долота", + 300 => "Низкое давление", + _ => detectedOperations[i].IdReasonOfEnd + }; var link = - $"{domains[idDomain]}/well/{well.Id}/telemetry/monitoring?end={Uri.EscapeDataString(dateStart.AddSeconds(3544).ToString("yyyy-MM-ddTHH:mm:ss.fff"))}&range=3600"; + $"{domains[idDomain]}/well/{well.Id}/telemetry/monitoring?end={Uri.EscapeDataString(dateStart.AddSeconds(1800 * 0.9).ToString("yyyy-MM-ddTHH:mm:ss.fff"))}&range=1800"; row.Cell(columnDateStart).Value = dateStart; row.Cell(columnDateStart).SetHyperlink(new XLHyperlink(link)); @@ -191,10 +198,8 @@ public class DetectedOperationExportService var isDetected = false; var positionBegin = 0; var positionEnd = data.Length - gap; - var step = 10; while (positionEnd > positionBegin) { - step++; foreach (var detector in detectors) { if (!detector.TryDetect(idTelemetry, data, positionBegin, positionEnd, lastDetectedOperation, out var result)) @@ -203,14 +208,11 @@ public class DetectedOperationExportService detectedOperations.Add(result!.Operation); lastDetectedOperation = result.Operation; isDetected = true; - step = 1; positionBegin = result.TelemetryEnd; break; } - - if (step > 20) - step = 10; - positionBegin += step; + + positionBegin += 1; } if (isDetected) diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs index 38a3aeac..07d2b16e 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs @@ -4,8 +4,7 @@ using System.Linq; namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors { - - internal abstract class DetectorAbstract + public abstract class DetectorAbstract { private readonly int stepLength = 3; @@ -34,14 +33,15 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors protected const int IdReasonOfEnd_Drilling = 600; protected const int IdReasonOfEnd_Custom1 = 10_000; - - public abstract Func GetIdOperation { get; } - public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, DetectedOperation? previousOperation, out OperationDetectorResult? result) + protected abstract Func GetIdOperation { get; } + + public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, DetectedOperation? previousOperation, + out OperationDetectorResult? result) { // Проверка соответствия критерию начала операции if (DetectBegin(telemetry, begin, previousOperation)) - { + { // Поиск окончания соответствия критерию int idReasonOfEnd = 0; var positionEnd = begin; @@ -52,30 +52,31 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors break; idReasonOfEnd = DetectEnd(telemetry, positionEnd, previousOperation); - - if(idReasonOfEnd is IdReasonOfEnd_DeltaDepthIsHi or IdReasonOfEnd_PressureIsLo && - !IsValidByWellDepthDoesNotChange(telemetry, begin, positionEnd)) - break; - - if (idReasonOfEnd != IdReasonOfEnd_NotDetected) + + if (idReasonOfEnd != IdReasonOfEnd_NotDetected) break; } - result = null; result = MakeOperation(idTelemetry, telemetry, begin, positionEnd, idReasonOfEnd); - return true; + return result is not null; } + result = null; return false; } - protected abstract bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation); - protected virtual int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation) - => DetectBegin(telemetry, position, previousOperation) - ? IdReasonOfEnd_NotDetected - : IdReasonOfEnd_NotDetectBegin; + protected virtual bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult) => + operationDetectorResult.Operation.IdReasonOfEnd != IdReasonOfEnd_NotDetected; - private OperationDetectorResult MakeOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, int idReasonOfEnd) + protected abstract bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation); + + protected virtual int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation) + => DetectBegin(telemetry, position, previousOperation) + ? IdReasonOfEnd_NotDetected + : IdReasonOfEnd_NotDetectBegin; + + private OperationDetectorResult? MakeOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, + int idReasonOfEnd) { var pBegin = telemetry[begin]; var pEnd = telemetry[end]; @@ -96,10 +97,9 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors IdReasonOfEnd = idReasonOfEnd, }, }; - return result; - } - protected abstract bool IsValid(DetectableTelemetry[] telemetry, int begin, int end); + return !IsValidOperationDetectorResult(result) ? null : result; + } protected abstract double CalcValue(DetectableTelemetry[] telemetry, int begin, int end); @@ -118,16 +118,16 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors int fragmentLength) { var end = begin + fragmentLength; - end = end < telemetry.Length - ? end + end = end < telemetry.Length + ? end : telemetry.Length; var subData = telemetry[begin..end].Select(yGetter); if (end - begin > 10) { var ratio = (end - begin) / 5; - subData = subData.Where((_,i) => i % ratio > 0); - } - + subData = subData.Where((_, i) => i % ratio > 0); + } + var avg = subData.Average(); return avg; } @@ -189,9 +189,9 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors /// /// protected static (double min, double max, double sum, int count) CalcStat( - DetectableTelemetry[] telemetry, - Func getter, - int begin, + DetectableTelemetry[] telemetry, + Func getter, + int begin, int count) { var sum = 0d; @@ -210,6 +210,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors max = itemValue; sum += itemValue; } + return (min, max, sum, end - begin); } @@ -256,7 +257,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors var end = begin + count; end = end < telemetry.Length ? end : telemetry.Length; - for (var i = begin; i < end; i ++) + for (var i = begin; i < end; i++) { var item = telemetry[i]; var itemValue = getter(item); @@ -264,9 +265,10 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors min = itemValue; if (max < itemValue) max = itemValue; - if(max - min > deviation) + if (max - min > deviation) return true; } + return false; } @@ -290,8 +292,8 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors var max = double.MinValue; var end = begin + count; end = end < telemetry.Length ? end : telemetry.Length; - var step = count > 15 ? count / 5 : count > 3 ? 3: 1; - for (var i = begin; i < end; i+= step) + var step = count > 15 ? count / 5 : count > 3 ? 3 : 1; + for (var i = begin; i < end; i += step) { var item = telemetry[i]; var itemValue = getter(item); @@ -302,6 +304,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors if (max - min > deviation) return true; } + return false; } @@ -323,6 +326,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors if (Math.Abs(beginPointValue - itemValue) > deviation) return true; } + return false; } @@ -341,13 +345,12 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors { var item = telemetry[i]; var itemValue = getter(item); - if ( itemValue - beginPointValue > deviation) + if (itemValue - beginPointValue > deviation) return true; } + return false; } } - - } diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDevelopment.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDevelopment.cs index 64c01f6c..13f665e4 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDevelopment.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDevelopment.cs @@ -1,68 +1,66 @@ -using System; -using AsbCloudDb.Model; - -namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors -{ - - /// - /// Проработка перед наращиванием - /// - internal class DetectorDevelopment : DetectorAbstract - { - protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end) - => CalcDeltaMinutes(telemetry, begin, end); - - public override Func GetIdOperation => (_, _, _) - => WellOperationCategory.IdDevelopment; - - protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation) - { - if (previousOperation?.IdCategory == WellOperationCategory.IdSlipsTime) - return false; - - var point0 = telemetry[position]; - var delta = point0.WellDepth - point0.BitDepth; - if (delta < 0.03d || delta > 30) - return false; - - if (point0.Pressure < 15) - return false; - - if (point0.BlockPosition > 2.5) - return false; - - if (point0.RotorSpeed < 10) - return false; - - if (!ContainsDeviationApprox(telemetry, d => d.BlockPosition, position, 60, 0.03)) - return false; - - return true; - } - - protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation) - { - var point0 = telemetry[position]; - var delta = point0.WellDepth - point0.BitDepth; - if (delta < 0.03d || delta > 30) - return IdReasonOfEnd_DeltaDepthOutOfRange; - - if (point0.Pressure < 15) - return IdReasonOfEnd_PressureIsLo; - - if (point0.BlockPosition > 31) - return IdReasonOfEnd_BlockPositionIsHi; - - if (point0.RotorSpeed < 10) - return IdReasonOfEnd_RotorSpeedIsLo; - - return IdReasonOfEnd_NotDetected; - } - - protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end) - => IsValidByWellDepthDoesNotChange(telemetry, begin, end); - } - - -} - +// using System; +// using AsbCloudDb.Model; +// +// namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors +// { +// +// /// +// /// Проработка перед наращиванием +// /// +// internal class DetectorDevelopment : DetectorAbstract +// { +// protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end) +// => CalcDeltaMinutes(telemetry, begin, end); +// +// public override Func GetIdOperation => (_, _, _) +// => WellOperationCategory.IdDevelopment; +// +// protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation) +// { +// if (previousOperation?.IdCategory == WellOperationCategory.IdSlipsTime) +// return false; +// +// var point0 = telemetry[position]; +// var delta = point0.WellDepth - point0.BitDepth; +// if (delta < 0.03d || delta > 30) +// return false; +// +// if (point0.Pressure < 15) +// return false; +// +// if (point0.BlockPosition > 2.5) +// return false; +// +// if (point0.RotorSpeed < 10) +// return false; +// +// if (!ContainsDeviationApprox(telemetry, d => d.BlockPosition, position, 60, 0.03)) +// return false; +// +// return true; +// } +// +// protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation) +// { +// var point0 = telemetry[position]; +// var delta = point0.WellDepth - point0.BitDepth; +// if (delta < 0.03d || delta > 30) +// return IdReasonOfEnd_DeltaDepthOutOfRange; +// +// if (point0.Pressure < 15) +// return IdReasonOfEnd_PressureIsLo; +// +// if (point0.BlockPosition > 31) +// return IdReasonOfEnd_BlockPositionIsHi; +// +// if (point0.RotorSpeed < 10) +// return IdReasonOfEnd_RotorSpeedIsLo; +// +// return IdReasonOfEnd_NotDetected; +// } +// +// protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end) +// => IsValidByWellDepthDoesNotChange(telemetry, begin, end); +// } +// } +// diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs index 3e7af4af..ef0484de 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs @@ -4,9 +4,9 @@ using AsbCloudDb.Model; namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors; -internal class DetectorDrilling : DetectorAbstract +public class DetectorDrilling : DetectorAbstract { - public override Func GetIdOperation => DefineDrillingOperation; + protected override Func GetIdOperation => DefineDrillingOperation; protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation) { @@ -18,9 +18,6 @@ internal class DetectorDrilling : DetectorAbstract if (point0.Pressure < 25) return false; - if (point0.RotorSpeed < 5) - return false; - return true; } @@ -37,26 +34,38 @@ internal class DetectorDrilling : DetectorAbstract return IdReasonOfEnd_NotDetected; } - - protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end) - => IsValidByWellDepthIncreasing(telemetry, begin, end); - + protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end) => CalcRop(telemetry, begin, end); + protected override bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult) => + operationDetectorResult.Operation.IdReasonOfEnd is IdReasonOfEnd_DeltaDepthIsHi or IdReasonOfEnd_PressureIsLo && + Math.Abs(operationDetectorResult.Operation.DepthStart - operationDetectorResult.Operation.DepthEnd) > 0.01; + private static int DefineDrillingOperation(DetectableTelemetry[] telemetry, int begin, int end) { const int idSlideWithOscillation = 12000; - var telemetryRange = telemetry[begin.. end]; - + var telemetryRange = telemetry[begin.. end] + .OrderBy(x => x.DateTime).ToList(); + + for (var i = telemetryRange.Count - 1; i >= 0 && telemetryRange.Count > 1; i--) + { + if (Math.Abs(telemetryRange[i].WellDepth - telemetryRange[i - 1].WellDepth) < 0.001d) + { + telemetryRange.RemoveAt(i); + continue; + } + + break; + } + var avgRotorSpeed = telemetryRange.Average(t => t.RotorSpeed); - + if (avgRotorSpeed < 10) return WellOperationCategory.IdSlide; - - var despersion = telemetryRange - .Average(t => Math.Pow((t.RotorSpeed - avgRotorSpeed) / avgRotorSpeed, 2)); + + var despersion = telemetryRange.Average(t => Math.Pow(t.RotorSpeed/avgRotorSpeed - 1, 2)); return despersion < 0.2d ? WellOperationCategory.IdRotor : idSlideWithOscillation; } diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs index 8be8b197..187aee33 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs @@ -1,39 +1,39 @@ -using System; -using AsbCloudDb.Model; - -namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors -{ - - internal class DetectorSlipsTime : DetectorAbstract - { - protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end) - => CalcDeltaMinutes(telemetry, begin, end); - - public override Func GetIdOperation => (_, _, _) => WellOperationCategory.IdSlipsTime; - - protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation) - { - var point0 = telemetry[position]; - var delta = point0.WellDepth - point0.BitDepth; - if (delta > 2.5d) - return false; - - if (point0.Pressure > 15) - return false; - - if (point0.BlockPosition > 8) - return false; - - if (point0.HookWeight > 20) - return false; - - return true; - } - - protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end) - => IsValidByWellDepthDoesNotChange(telemetry, begin, end); - } - - -} - +// using System; +// using AsbCloudDb.Model; +// +// namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors +// { +// +// internal class DetectorSlipsTime : DetectorAbstract +// { +// protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end) +// => CalcDeltaMinutes(telemetry, begin, end); +// +// public override Func GetIdOperation => (_, _, _) => WellOperationCategory.IdSlipsTime; +// +// protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation) +// { +// var point0 = telemetry[position]; +// var delta = point0.WellDepth - point0.BitDepth; +// if (delta > 2.5d) +// return false; +// +// if (point0.Pressure > 15) +// return false; +// +// if (point0.BlockPosition > 8) +// return false; +// +// if (point0.HookWeight > 20) +// return false; +// +// return true; +// } +// +// protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end) +// => IsValidByWellDepthDoesNotChange(telemetry, begin, end); +// } +// +// +// } +// diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/readme.md b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/readme.md deleted file mode 100644 index 5f282702..00000000 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/readme.md +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Specifications/Бурение ротор и слайд.md b/AsbCloudInfrastructure/Services/DetectOperations/Specifications/Бурение ротор и слайд.md index 965f271e..8d69d2b4 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Specifications/Бурение ротор и слайд.md +++ b/AsbCloudInfrastructure/Services/DetectOperations/Specifications/Бурение ротор и слайд.md @@ -1,29 +1,27 @@ -Метод определения бурения +# Алгоритм определения бурения в роторе, слайде, слайде с осцилляцией -Признак начала операции = +## Метод определения операции бурения -расстояние от долота до забоя < 0.03м  И + Признак начала операции = + (расстояние от долота до забоя < 0.03м) И + (давление > 25атм) + + Признак окончания операции = + (расстояние от долота до забоя > 0.03м) ИЛИ + (давление < 25атм) -давление > 25атм +## Валидация + Для точного определения операции бурения, необходимо убрать диапазон в которых сработал признак окончания операции и не менялась глубина: + Определили точку окончания операции исходя из Признак окончания операции. + Определяем временной интервал, когда не менялась глубина (т.е. время шло, а глубина была неизменна) + Определив начальную точку и точку окончания операции + Исключаем этот интервал из операции. -Признак окончания операции = +## Метод определения бурения в слайде + Необходимо рассчитать средние обороты ротора за всю операцию бурения. + Если среднее арифметическое больше константы (10 об/мин), то это бурение в роторе, если меньше, то это бурение в слайде. -расстояние от долота до забоя > 0.03м  ИЛИ - -давление < 25атм - -Находим границы - -После того когда мы нашли границы, мы должны определить операцию, тогда мы смотрим на забой точки окончания операций сравниваем с забоем точками начала операций: - -Если они равны друг другу, то мы эту операцию дальше не обрабатываем, а выбрасываем. - -Если они не равны, то у нас произошло увеличение забоя, значит эта операция бурения. - -Дальше мы определяем как мы бурили в роторе или слайде, для этого нам необходимо рассчитать среднюю скорость(среднее арифметическое) за всю операцию бурения . Если среднее арифметическое больше константы (10 об/мин), то это бурение в роторе, если меньше, то это бурение в слайде. - -Если бурение в роторе, то мы считаем только дисперсию нормированных оборотов ротора(по среднему значению). (Так как это может быть бурение в слайде с осцилляцией и выглядеть как бурение в роторе): - -Если полученное значение меньше константы(0,2), то мы подтвердили что бурение в роторе. - -Если полученное значение больше константы, то это бурение в слайде с осцилляцией. \ No newline at end of file +## Метод определения бурения в роторе, слайде с осцилляцией + Необходимо рассчитать десперсию нормированных оборотов ротора по(по среднему значению) + 1. Если полученное значение больше константы(0,2), то мы подтвердили что бурение в роторе. + 2. Если полученное значение меньше константы, то это бурение в слайде с осцилляцией. \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs b/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs index 4673d032..fd762b09 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs @@ -16,11 +16,11 @@ public class WorkOperationDetection: Work { private static readonly DetectorAbstract[] detectors = new DetectorAbstract[] { + new DetectorDrilling() // new DetectorRotor(), // new DetectorSlide(), //new DetectorDevelopment(), //new DetectorTemplating(), - new DetectorSlipsTime(), //new DetectorStaticSurveying(), //new DetectorFlashingBeforeConnection(), //new DetectorFlashing(), @@ -116,7 +116,6 @@ public class WorkOperationDetection: Work { var data = await query .Where(d => d.DateTime > startDate) - .Take(take) .ToArrayAsync(token); if (data.Length < gap) @@ -125,25 +124,21 @@ public class WorkOperationDetection: Work var isDetected = false; var positionBegin = 0; var positionEnd = data.Length - gap; - var step = 10; while (positionEnd > positionBegin) { - step ++; - for (int i = 0; i < detectors.Length; i++) + foreach (var detector in detectors) { - if (detectors[i].TryDetect(idTelemetry, data, positionBegin, positionEnd, lastDetectedOperation, out OperationDetectorResult? result)) - { - detectedOperations.Add(result!.Operation); - lastDetectedOperation = result.Operation; - isDetected = true; - step = 1; - positionBegin = result.TelemetryEnd; - break; - } + if (!detector.TryDetect(idTelemetry, data, positionBegin, positionEnd, lastDetectedOperation, out var result)) + continue; + + detectedOperations.Add(result!.Operation); + lastDetectedOperation = result.Operation; + isDetected = true; + positionBegin = result.TelemetryEnd; + break; } - if (step > 20) - step = 10; - positionBegin += step; + + positionBegin += 1; } if (isDetected) diff --git a/AsbCloudWebApi.Tests/Services/DetectedOperations/Detectors/DetectorDrillingTests.cs b/AsbCloudWebApi.Tests/Services/DetectedOperations/Detectors/DetectorDrillingTests.cs new file mode 100644 index 00000000..4dc797fb --- /dev/null +++ b/AsbCloudWebApi.Tests/Services/DetectedOperations/Detectors/DetectorDrillingTests.cs @@ -0,0 +1,290 @@ +using System.Collections.Generic; +using AsbCloudDb.Model; +using AsbCloudInfrastructure.Services.DetectOperations; +using AsbCloudInfrastructure.Services.DetectOperations.Detectors; +using Xunit; + +namespace AsbCloudWebApi.Tests.Services.DetectedOperations.Detectors; + +public class DetectorDrillingTests : DetectorDrilling +{ + private const int idSlide = 5002; + private const int idRotor = 5003; + private const int idSlideWithOscillation = 12000; + + [Theory] + [MemberData(nameof(TelemetryRangeDrillingRotor))] + public void DefineDrillingOperation_ShouldReturn_DrillingRotor(DetectableTelemetry[] telemetryRange) + { + //act + var result = GetIdOperation.Invoke(telemetryRange, 0, telemetryRange.Length); + + //assert + Assert.Equal(idRotor, result); + } + + [Theory] + [MemberData(nameof(TelemetryRangeDrillingSlide))] + public void DefineDrillingOperation_ShouldReturn_DrillingSlide(DetectableTelemetry[] telemetryRange) + { + //act + var result = GetIdOperation.Invoke(telemetryRange, 0, telemetryRange.Length); + + //assert + Assert.Equal(idSlide, result); + } + + [Theory] + [MemberData(nameof(TelemetryRangeDrillingSlideWithOscillation))] + public void DefineDrillingOperation_ShouldReturn_DrillingSlideWithOscillation(DetectableTelemetry[] telemetryRange) + { + //act + var result = GetIdOperation.Invoke(telemetryRange, 0, telemetryRange.Length); + + //assert + Assert.Equal(idSlideWithOscillation, result); + } + + [Fact] + public void IsValidOperationDetectorResult_ShouldReturn_True() + { + //arrange + var operationDetectorResult = new OperationDetectorResult + { + Operation = new DetectedOperation + { + IdReasonOfEnd = IdReasonOfEnd_PressureIsLo, + DepthStart = 5000, + DepthEnd = 6000 + } + }; + + //act + var result = IsValidOperationDetectorResult(operationDetectorResult); + + //assert + Assert.True(result); + } + + [Fact] + public void IsValidOperationDetectorResult_ShouldReturn_False() + { + //arrange + var operationDetectorResult = new OperationDetectorResult + { + Operation = new DetectedOperation + { + IdReasonOfEnd = IdReasonOfEnd_PressureIsLo, + DepthStart = 5000, + DepthEnd = 5000 + } + }; + + //act + var result = IsValidOperationDetectorResult(operationDetectorResult); + + //assert + Assert.False(result); + } + + public static IEnumerable TelemetryRangeDrillingRotor() + { + yield return new object[] + { + new[] + { + new DetectableTelemetry + { + WellDepth = 4.187f, + Pressure = 27.815952f, + HookWeight = 34.221367f, + BlockPosition = 24.388f, + BitDepth = 4.187f, + RotorSpeed = 40.3f + }, + new DetectableTelemetry + { + WellDepth = 4.232f, + Pressure = 28.080372f, + HookWeight = 34.162174f, + BlockPosition = 24.343f, + BitDepth = 4.232f, + RotorSpeed = 40.3f + }, + new DetectableTelemetry + { + WellDepth = 4.277f, + Pressure = 29.047901f, + HookWeight = 33.688717f, + BlockPosition = 24.298f, + BitDepth = 24.298f, + RotorSpeed = 40.3f + }, + new DetectableTelemetry + { + WellDepth = 4.309f, + Pressure = 29.574032f, + HookWeight = 33.692104f, + BlockPosition = 24.266f, + BitDepth = 4.309f, + RotorSpeed = 40.4f + }, + new DetectableTelemetry + { + WellDepth = 4.324f, + Pressure = 24.007977f, + HookWeight = 34.838448f, + BlockPosition = 24.251f, + BitDepth = 4.324f, + RotorSpeed = 40.5f + }, + new DetectableTelemetry + { + WellDepth = 4.324f, + Pressure = 24.04114f, + HookWeight = 34.423424f, + BlockPosition = 24.252f, + BitDepth = 4.323f, + RotorSpeed = 40.3f + } + } + }; + } + + public static IEnumerable TelemetryRangeDrillingSlide() + { + yield return new object[] + { + new[] + { + new DetectableTelemetry + { + WellDepth = 447.276001f, + Pressure = 26.619421f, + HookWeight = 40.9143829f, + BlockPosition = 4.559f, + BitDepth = 477.265991f, + RotorSpeed = 0 + }, + new DetectableTelemetry + { + WellDepth = 477.289f, + Pressure = 28.716f, + HookWeight = 38.27f, + BlockPosition = 4.5f, + BitDepth = 477.289f, + RotorSpeed = 0.1f + }, + new DetectableTelemetry + { + WellDepth = 477.30899f, + Pressure = 33.953495f, + HookWeight = 38.27f, + BlockPosition = 4.5359997f, + BitDepth = 477.289001f, + RotorSpeed = 0.1f + }, + } + }; + } + + public static IEnumerable TelemetryRangeDrillingSlideWithOscillation() + { + yield return new object[] + { + new[] + { + new DetectableTelemetry + { + IdUser = 1, + WellDepth = 415.306f, + Pressure = 53.731934f, + HookWeight = 41.049942f, + BlockPosition = 28.666f, + BitDepth = 415.293f, + RotorSpeed = 0.3f + }, + new DetectableTelemetry + { + IdUser = 1, + WellDepth = 415.311f, + Pressure = 57.660595f, + HookWeight = 40.898712f, + BlockPosition = 28.648f, + BitDepth = 415.311f, + RotorSpeed = 0.2f + }, + new DetectableTelemetry + { + IdUser = 1, + WellDepth = 415.326f, + Pressure = 59.211086f, + HookWeight = 40.882797f, + BlockPosition = 28.633f, + BitDepth = 415.326f, + RotorSpeed = 0.1f + }, + new DetectableTelemetry + { + IdUser = 1, + WellDepth = 415.344f, + Pressure = 59.484406f, + HookWeight = 40.91972f, + BlockPosition = 28.615f, + BitDepth = 415.344f, + RotorSpeed = 0.2f + }, + new DetectableTelemetry + { + IdUser = 1, + WellDepth = 415.364f, + Pressure = 60.739918f, + HookWeight = 40.795666f, + BlockPosition = 28.595f, + BitDepth = 415.364f, + RotorSpeed = 4.5f + }, + new DetectableTelemetry + { + IdUser = 1, + WellDepth = 415.378f, + Pressure = 62.528984f, + HookWeight = 40.52114f, + BlockPosition = 28.581f, + BitDepth = 415.378f, + RotorSpeed = 22.6f + }, + new DetectableTelemetry + { + IdUser = 1, + WellDepth = 415.392f, + Pressure = 67.0039f, + HookWeight = 38.878895f, + BlockPosition = 28.569f, + BitDepth = 415.39f, + RotorSpeed = 50f + }, + new DetectableTelemetry + { + IdUser = 1, + WellDepth = 415.392f, + Pressure = 65.72418f, + HookWeight = 42.53173f, + BlockPosition = 28.622f, + BitDepth = 415.337f, + RotorSpeed = 93f + }, + new DetectableTelemetry + { + IdUser = 1, + WellDepth = 415.392f, + Pressure = 56.82195f, + HookWeight = 43.15844f, + BlockPosition = 28.704f, + BitDepth = 415.255f, + RotorSpeed = 71.5f + } + } + }; + } +} \ No newline at end of file From 1a237f70506d4727b6378ccc0c33927ab50cd551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Thu, 23 Nov 2023 09:47:10 +0500 Subject: [PATCH 02/10] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BA=D0=BE=D0=BD=D1=81=D1=82=D0=B0=D0=BD?= =?UTF-8?q?=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Изменена пороговая константа средних оборотов ротора 2. Изменена пороговая константа давления 3. Поправлена спецификация --- .../Services/DetectOperations/Detectors/DetectorDrilling.cs | 6 +++--- .../Specifications/Бурение ротор и слайд.md | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs index ef0484de..ac1954f9 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs @@ -15,7 +15,7 @@ public class DetectorDrilling : DetectorAbstract if (delta > 0.03d) return false; - if (point0.Pressure < 25) + if (point0.Pressure < 18) return false; return true; @@ -29,7 +29,7 @@ public class DetectorDrilling : DetectorAbstract if (delta > 0.03d) return IdReasonOfEnd_DeltaDepthIsHi; - if (point0.Pressure < 25) + if (point0.Pressure < 18) return IdReasonOfEnd_PressureIsLo; return IdReasonOfEnd_NotDetected; @@ -62,7 +62,7 @@ public class DetectorDrilling : DetectorAbstract var avgRotorSpeed = telemetryRange.Average(t => t.RotorSpeed); - if (avgRotorSpeed < 10) + if (avgRotorSpeed < 5) return WellOperationCategory.IdSlide; var despersion = telemetryRange.Average(t => Math.Pow(t.RotorSpeed/avgRotorSpeed - 1, 2)); diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Specifications/Бурение ротор и слайд.md b/AsbCloudInfrastructure/Services/DetectOperations/Specifications/Бурение ротор и слайд.md index 8d69d2b4..fb6ea702 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Specifications/Бурение ротор и слайд.md +++ b/AsbCloudInfrastructure/Services/DetectOperations/Specifications/Бурение ротор и слайд.md @@ -4,11 +4,11 @@ Признак начала операции = (расстояние от долота до забоя < 0.03м) И - (давление > 25атм) + (давление > 18атм) Признак окончания операции = (расстояние от долота до забоя > 0.03м) ИЛИ - (давление < 25атм) + (давление < 18атм) ## Валидация Для точного определения операции бурения, необходимо убрать диапазон в которых сработал признак окончания операции и не менялась глубина: @@ -19,7 +19,7 @@ ## Метод определения бурения в слайде Необходимо рассчитать средние обороты ротора за всю операцию бурения. - Если среднее арифметическое больше константы (10 об/мин), то это бурение в роторе, если меньше, то это бурение в слайде. + Если среднее арифметическое больше константы (5 об/мин), то это бурение в роторе, если меньше, то это бурение в слайде. ## Метод определения бурения в роторе, слайде с осцилляцией Необходимо рассчитать десперсию нормированных оборотов ротора по(по среднему значению) From a435dce3081cc856c6e7f2ddd4f0568e7027730e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Tue, 28 Nov 2023 11:23:30 +0500 Subject: [PATCH 03/10] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Дополнения шаблона для отладки 1.2 Добавлен комментарии 2. Вернул определение операции удержание в клиньях --- .../DetectOperations/DetectOperations.xlsx | Bin 15404 -> 82771 bytes .../DetectedOperationExportService.cs | 71 ++++++++++++----- .../Detectors/DetectorDrilling.cs | 14 +++- .../Detectors/DetectorSlipsTime.cs | 74 +++++++++--------- .../WorkOperationDetection.cs | 3 +- 5 files changed, 99 insertions(+), 63 deletions(-) diff --git a/AsbCloudInfrastructure/Services/DetectOperations/DetectOperations.xlsx b/AsbCloudInfrastructure/Services/DetectOperations/DetectOperations.xlsx index 1c366050097ce39261c518d89f23a5d14b0db8f0..bfde3933dfe90138edac356828aaee2b15b6e39e 100644 GIT binary patch literal 82771 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়w+V2sJCm^Jv>x= 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 domains = new Dictionary { @@ -38,6 +43,7 @@ public class DetectedOperationExportService private const int columnDeltaDepth = 7; private const int columnDepth = 8; private const int columnIdReasonOfEnd = 9; + private const int columnComment = 10; private readonly IAsbCloudDbContext dbContext; @@ -65,14 +71,14 @@ public class DetectedOperationExportService return await GenerateExcelFileStreamAsync(well, idDomain, operations, cancellationToken); } - private async Task GenerateExcelFileStreamAsync(Well well, int idDomain, IEnumerable detectedOperations, + private async Task GenerateExcelFileStreamAsync(Well well, int idDomain, IEnumerable operationDetectorResults, CancellationToken cancellationToken) { using var excelTemplateStream = await GetExcelTemplateStreamAsync(cancellationToken); using var workbook = new XLWorkbook(excelTemplateStream, XLEventTracking.Disabled); - await AddToWorkbookAsync(workbook, well, idDomain, detectedOperations, cancellationToken); + await AddToWorkbookAsync(workbook, well, idDomain, operationDetectorResults, cancellationToken); MemoryStream memoryStream = new MemoryStream(); workbook.SaveAs(memoryStream, new SaveOptions { }); @@ -80,22 +86,23 @@ public class DetectedOperationExportService return memoryStream; } - private async Task AddToWorkbookAsync(XLWorkbook workbook, Well well, int idDomain, IEnumerable detectedOperations, + private async Task AddToWorkbookAsync(XLWorkbook workbook, Well well, int idDomain, IEnumerable operationDetectorResults, CancellationToken cancellationToken) { const string sheetName = "Операции"; - if (!detectedOperations.Any()) + if (!operationDetectorResults.Any()) return; var sheet = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetName) ?? throw new FileFormatException($"Книга excel не содержит листа {sheetName}."); - await AddToSheetAsync(sheet, well, idDomain, detectedOperations.OrderBy(x => x.DateStart).ThenBy(x => x.DepthStart).ToArray(), + await AddToSheetAsync(sheet, well, idDomain, operationDetectorResults + .OrderBy(x => x.Operation.DateStart).ThenBy(x => x.Operation.DepthStart).ToArray(), cancellationToken); } - private async Task AddToSheetAsync(IXLWorksheet sheet, Well well, int idDomain, IList detectedOperations, + private async Task AddToSheetAsync(IXLWorksheet sheet, Well well, int idDomain, IList operationDetectorResults, CancellationToken cancellationToken) { var wellOperationCategories = await dbContext.WellOperationCategories.ToListAsync(cancellationToken); @@ -103,14 +110,14 @@ public class DetectedOperationExportService sheet.Cell(cellDepositName).Value = well.Cluster.Deposit.Caption; sheet.Cell(cellClusterName).Value = well.Cluster.Caption; sheet.Cell(cellWellName).Value = well.Caption; - sheet.Cell(cellDeltaDate).Value = detectedOperations.Max(o => o.DateEnd) - detectedOperations.Min(o => o.DateStart); + sheet.Cell(cellDeltaDate).Value = operationDetectorResults.Max(o => o.Operation.DateEnd) - operationDetectorResults.Min(o => o.Operation.DateStart); - var timeZoneWell = TimeSpan.FromHours(well.Timezone.Hours); - - for (int i = 0; i < detectedOperations.Count; i++) + for (int i = 0; i < operationDetectorResults.Count; i++) { - var dateStart = detectedOperations[i].DateStart.ToOffset(timeZoneWell); - var dateEnd = detectedOperations[i].DateEnd.ToOffset(timeZoneWell); + var detectedOperations = operationDetectorResults.Select(o => o.Operation).ToArray(); + + var dateStart = detectedOperations[i].DateStart.ToRemoteDateTime(well.Timezone.Hours); + var dateEnd = detectedOperations[i].DateEnd.ToRemoteDateTime(well.Timezone.Hours); var row = sheet.Row(5 + i + headerRowsCount); @@ -137,9 +144,11 @@ public class DetectedOperationExportService row.Cell(columnDateStart).Value = dateStart; row.Cell(columnDateStart).SetHyperlink(new XLHyperlink(link)); - row.Cell(columnDeltaDepth).Value = i > 0 && i + 1 < detectedOperations.Count + row.Cell(columnDeltaDepth).Value = i > 0 && i + 1 < detectedOperations.Length ? detectedOperations[i].DepthStart - detectedOperations[i - 1].DepthEnd : 0; + + row.Cell(columnComment).Value = CreateComment(operationDetectorResults[i]); } } @@ -158,8 +167,32 @@ public class DetectedOperationExportService return memoryStream; } + + private string? CreateComment(OperationDetectorResult operationDetectorResult) + { + switch (operationDetectorResult.Operation.IdCategory) + { + case 12000: + case 5002: + case 5003: + { + var detectorDrilling = detectors.FirstOrDefault(d => d is DetectorDrilling) as DetectorDrilling; + var avgRotorSpeed = Math.Round(detectorDrilling.AvgRotorSpeedDict[(operationDetectorResult.TelemetryBegin, operationDetectorResult.TelemetryEnd)], 2); + var despersion = Math.Round(detectorDrilling.DespersionDict[(operationDetectorResult.TelemetryBegin, operationDetectorResult.TelemetryEnd)], 2); - private async Task> DetectOperationsAsync(int idTelemetry, DateTimeOffset begin, + var stringBuilder = new StringBuilder(); + + stringBuilder.AppendLine($"Средняя скорость оборотов ротора: {avgRotorSpeed}"); + stringBuilder.AppendLine($"Нормированные обороты ротора: {despersion}"); + + return stringBuilder.ToString(); + } + default: + return null; + } + } + + private async Task> DetectOperationsAsync(int idTelemetry, DateTimeOffset begin, CancellationToken token) { var query = dbContext.TelemetryDataSaub @@ -180,7 +213,7 @@ public class DetectedOperationExportService .OrderBy(d => d.DateTime); var startDate = begin; - var detectedOperations = new List(8); + var detectedOperationResults = new List(8); DetectedOperation? lastDetectedOperation = null; const int minOperationLength = 5; const int maxDetectorsInterpolationFrameLength = 30; @@ -205,8 +238,8 @@ public class DetectedOperationExportService if (!detector.TryDetect(idTelemetry, data, positionBegin, positionEnd, lastDetectedOperation, out var result)) continue; - detectedOperations.Add(result!.Operation); - lastDetectedOperation = result.Operation; + detectedOperationResults.Add(result!); + lastDetectedOperation = result!.Operation; isDetected = true; positionBegin = result.TelemetryEnd; break; @@ -221,6 +254,6 @@ public class DetectedOperationExportService startDate = data[positionEnd].DateTime; } - return detectedOperations; + return detectedOperationResults; } } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs index ac1954f9..cc8b7353 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using AsbCloudDb.Model; @@ -8,6 +9,9 @@ public class DetectorDrilling : DetectorAbstract { protected override Func GetIdOperation => DefineDrillingOperation; + public IDictionary<(int, int), float> AvgRotorSpeedDict { get; } = new Dictionary<(int, int), float>(); + public IDictionary<(int, int), double> DespersionDict { get; } = new Dictionary<(int, int), double>(); + protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation) { var point0 = telemetry[position]; @@ -42,7 +46,7 @@ public class DetectorDrilling : DetectorAbstract operationDetectorResult.Operation.IdReasonOfEnd is IdReasonOfEnd_DeltaDepthIsHi or IdReasonOfEnd_PressureIsLo && Math.Abs(operationDetectorResult.Operation.DepthStart - operationDetectorResult.Operation.DepthEnd) > 0.01; - private static int DefineDrillingOperation(DetectableTelemetry[] telemetry, int begin, int end) + private int DefineDrillingOperation(DetectableTelemetry[] telemetry, int begin, int end) { const int idSlideWithOscillation = 12000; @@ -61,12 +65,14 @@ public class DetectorDrilling : DetectorAbstract } var avgRotorSpeed = telemetryRange.Average(t => t.RotorSpeed); - + var despersion = telemetryRange.Average(t => Math.Pow(t.RotorSpeed/avgRotorSpeed - 1, 2)); + + AvgRotorSpeedDict.Add((begin, end), avgRotorSpeed); + DespersionDict.Add((begin, end), despersion); + if (avgRotorSpeed < 5) return WellOperationCategory.IdSlide; - var despersion = telemetryRange.Average(t => Math.Pow(t.RotorSpeed/avgRotorSpeed - 1, 2)); - return despersion < 0.2d ? WellOperationCategory.IdRotor : idSlideWithOscillation; } } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs index 187aee33..7ca25fe5 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs @@ -1,39 +1,35 @@ -// using System; -// using AsbCloudDb.Model; -// -// namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors -// { -// -// internal class DetectorSlipsTime : DetectorAbstract -// { -// protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end) -// => CalcDeltaMinutes(telemetry, begin, end); -// -// public override Func GetIdOperation => (_, _, _) => WellOperationCategory.IdSlipsTime; -// -// protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation) -// { -// var point0 = telemetry[position]; -// var delta = point0.WellDepth - point0.BitDepth; -// if (delta > 2.5d) -// return false; -// -// if (point0.Pressure > 15) -// return false; -// -// if (point0.BlockPosition > 8) -// return false; -// -// if (point0.HookWeight > 20) -// return false; -// -// return true; -// } -// -// protected override bool IsValid(DetectableTelemetry[] telemetry, int begin, int end) -// => IsValidByWellDepthDoesNotChange(telemetry, begin, end); -// } -// -// -// } -// +using System; +using AsbCloudDb.Model; + +namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors; + +public class DetectorSlipsTime : DetectorAbstract +{ + protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end) + => CalcDeltaMinutes(telemetry, begin, end); + + protected override Func GetIdOperation => (_, _, _) => WellOperationCategory.IdSlipsTime; + + protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation) + { + var point0 = telemetry[position]; + var delta = point0.WellDepth - point0.BitDepth; + if (delta > 2.5d) + return false; + + if (point0.Pressure > 15) + return false; + + if (point0.BlockPosition > 8) + return false; + + if (point0.HookWeight > 20) + return false; + + return true; + } + + protected override bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult) => + Math.Abs(operationDetectorResult.Operation.DepthStart - operationDetectorResult.Operation.DepthEnd) > 0.01; +} + diff --git a/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs b/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs index fd762b09..43815670 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs @@ -16,7 +16,8 @@ public class WorkOperationDetection: Work { private static readonly DetectorAbstract[] detectors = new DetectorAbstract[] { - new DetectorDrilling() + new DetectorDrilling(), + new DetectorSlipsTime() // new DetectorRotor(), // new DetectorSlide(), //new DetectorDevelopment(), From fd8b0de5a005982ed4cf9e32c4ad6f53ca184e3e Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Mon, 4 Dec 2023 11:11:25 +0500 Subject: [PATCH 04/10] Replace GetIdOperation delegate by method. Add Mode to DetectableTelemetry --- .../DetectOperations/DetectableTelemetry.cs | 26 +++++++++---------- .../Detectors/DetectorAbstract.cs | 6 ++--- .../Detectors/DetectorDrilling.cs | 4 +-- .../Detectors/DetectorSlipsTime.cs | 7 ++--- .../WorkOperationDetection.cs | 1 + 5 files changed, 21 insertions(+), 23 deletions(-) diff --git a/AsbCloudInfrastructure/Services/DetectOperations/DetectableTelemetry.cs b/AsbCloudInfrastructure/Services/DetectOperations/DetectableTelemetry.cs index 626b58d6..55a605f2 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/DetectableTelemetry.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/DetectableTelemetry.cs @@ -1,18 +1,16 @@ using System; -namespace AsbCloudInfrastructure.Services.DetectOperations +namespace AsbCloudInfrastructure.Services.DetectOperations; + +public class DetectableTelemetry { - - public class DetectableTelemetry - { - public DateTimeOffset DateTime { get; set; } - public int? IdUser { get; set; } - public float WellDepth { get; set; } - public float Pressure { get; set; } - public float HookWeight { get; set; } - public float BlockPosition { get; set; } - public float BitDepth { get; set; } - public float RotorSpeed { get; set; } - } - + public DateTimeOffset DateTime { get; set; } + public int? IdUser { get; set; } + public int Mode { get; set; } + public float WellDepth { get; set; } + public float Pressure { get; set; } + public float HookWeight { get; set; } + public float BlockPosition { get; set; } + public float BitDepth { get; set; } + public float RotorSpeed { get; set; } } diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs index 07d2b16e..bacebad9 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs @@ -34,8 +34,6 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors protected const int IdReasonOfEnd_Custom1 = 10_000; - protected abstract Func GetIdOperation { get; } - public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, DetectedOperation? previousOperation, out OperationDetectorResult? result) { @@ -87,7 +85,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors Operation = new DetectedOperation { IdTelemetry = idTelemetry, - IdCategory = GetIdOperation.Invoke(telemetry, begin, end), + IdCategory = GetIdOperation(telemetry, begin, end), IdUsersAtStart = pBegin.IdUser ?? -1, DateStart = pBegin.DateTime, DateEnd = pEnd.DateTime, @@ -101,6 +99,8 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors return !IsValidOperationDetectorResult(result) ? null : result; } + protected abstract int GetIdOperation(DetectableTelemetry[] telemetry, int begin, int end); + protected abstract double CalcValue(DetectableTelemetry[] telemetry, int begin, int end); ///

diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs index cc8b7353..80889677 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs @@ -7,8 +7,6 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors; public class DetectorDrilling : DetectorAbstract { - protected override Func GetIdOperation => DefineDrillingOperation; - public IDictionary<(int, int), float> AvgRotorSpeedDict { get; } = new Dictionary<(int, int), float>(); public IDictionary<(int, int), double> DespersionDict { get; } = new Dictionary<(int, int), double>(); @@ -46,7 +44,7 @@ public class DetectorDrilling : DetectorAbstract operationDetectorResult.Operation.IdReasonOfEnd is IdReasonOfEnd_DeltaDepthIsHi or IdReasonOfEnd_PressureIsLo && Math.Abs(operationDetectorResult.Operation.DepthStart - operationDetectorResult.Operation.DepthEnd) > 0.01; - private int DefineDrillingOperation(DetectableTelemetry[] telemetry, int begin, int end) + protected override int GetIdOperation(DetectableTelemetry[] telemetry, int begin, int end) { const int idSlideWithOscillation = 12000; diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs index 7ca25fe5..7109376d 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs @@ -8,8 +8,6 @@ public class DetectorSlipsTime : DetectorAbstract protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end) => CalcDeltaMinutes(telemetry, begin, end); - protected override Func GetIdOperation => (_, _, _) => WellOperationCategory.IdSlipsTime; - protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation) { var point0 = telemetry[position]; @@ -29,7 +27,10 @@ public class DetectorSlipsTime : DetectorAbstract return true; } - protected override bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult) => + protected override int GetIdOperation(DetectableTelemetry[] telemetry, int begin, int end) + => WellOperationCategory.IdSlipsTime; + + protected override bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult) => Math.Abs(operationDetectorResult.Operation.DepthStart - operationDetectorResult.Operation.DepthEnd) > 0.01; } diff --git a/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs b/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs index 43815670..36b5cbf8 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs @@ -96,6 +96,7 @@ public class WorkOperationDetection: Work { DateTime = d.DateTime, IdUser = d.IdUser, + Mode = d.Mode, WellDepth = d.WellDepth, Pressure = d.Pressure, HookWeight = d.HookWeight, From 948002955deefdbf7ed088f0b04402cf4eea9e51 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Mon, 4 Dec 2023 17:36:00 +0500 Subject: [PATCH 05/10] DetectorDrilling. Extract RefineEdges method from GetIdOperation. Move detectedOperation helper data to ExtraData property --- AsbCloudDb/Model/DetectedOperation.cs | 5 +- .../DetectedOperationExportService.cs | 98 ++++++++++++------- .../Detectors/DetectorAbstract.cs | 75 +++++++++----- .../Detectors/DetectorDrilling.cs | 77 +++++++++------ .../Detectors/DetectorSlipsTime.cs | 10 +- 5 files changed, 171 insertions(+), 94 deletions(-) diff --git a/AsbCloudDb/Model/DetectedOperation.cs b/AsbCloudDb/Model/DetectedOperation.cs index 8d862de4..27f4f928 100644 --- a/AsbCloudDb/Model/DetectedOperation.cs +++ b/AsbCloudDb/Model/DetectedOperation.cs @@ -1,5 +1,6 @@ using Microsoft.EntityFrameworkCore; using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Text.Json.Serialization; @@ -40,8 +41,8 @@ namespace AsbCloudDb.Model [Column("value"), Comment("Ключевой показатель операции")] public double Value { get; set; } - [Column("id_reason_of_end"), Comment("Код признака окончания операции")] - public int IdReasonOfEnd { get; set; } + [Column("extra_data", TypeName = "jsonb"), Comment("доп. инфо по операции")] + public IDictionary ExtraData { get; set; } = null!; [JsonIgnore] [ForeignKey(nameof(IdTelemetry))] diff --git a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs index dab037d5..0d882c58 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs @@ -10,6 +10,8 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using AsbCloudInfrastructure.Services.DetectOperations.Detectors; +using AsbCloudApp.Repositories; +using AsbCloudInfrastructure.Repository; namespace AsbCloudInfrastructure.Services.DetectOperations; @@ -46,11 +48,13 @@ public class DetectedOperationExportService private const int columnComment = 10; private readonly IAsbCloudDbContext dbContext; + private readonly IWellOperationRepository wellOperationRepository; - public DetectedOperationExportService(IAsbCloudDbContext dbContext) + public DetectedOperationExportService(IAsbCloudDbContext dbContext, IWellOperationRepository wellOperationRepository) { this.dbContext = dbContext; - } + this.wellOperationRepository = wellOperationRepository; + } public async Task ExportAsync(int idWell, int idDomain, CancellationToken cancellationToken) { @@ -112,31 +116,26 @@ public class DetectedOperationExportService sheet.Cell(cellWellName).Value = well.Caption; sheet.Cell(cellDeltaDate).Value = operationDetectorResults.Max(o => o.Operation.DateEnd) - operationDetectorResults.Min(o => o.Operation.DateStart); + var detectedOperations = operationDetectorResults.Select(o => o.Operation).ToArray(); + for (int i = 0; i < operationDetectorResults.Count; i++) { - var detectedOperations = operationDetectorResults.Select(o => o.Operation).ToArray(); - - var dateStart = detectedOperations[i].DateStart.ToRemoteDateTime(well.Timezone.Hours); - var dateEnd = detectedOperations[i].DateEnd.ToRemoteDateTime(well.Timezone.Hours); + var current = detectedOperations[i]; + var dateStart = current.DateStart.ToRemoteDateTime(well.Timezone.Hours); + var dateEnd = current.DateEnd.ToRemoteDateTime(well.Timezone.Hours); var row = sheet.Row(5 + i + headerRowsCount); - row.Cell(columnOperationName).Value = detectedOperations[i].IdCategory == 12000 - ? "Бурение в слайде с осцилляцией" - : wellOperationCategories.Single(o => o.Id == detectedOperations[i].IdCategory).Name; + row.Cell(columnOperationName).Value = GetCategoryName(wellOperationCategories, current); row.Cell(columnDateEnd).Value = dateEnd; row.Cell(columnDuration).Value = (dateEnd - dateStart).TotalMinutes; - row.Cell(columnDepthStart).Value = detectedOperations[i].DepthStart; - row.Cell(columnDepthEnd).Value = detectedOperations[i].DepthEnd; - row.Cell(columnDepth).Value = detectedOperations[i].DepthEnd - detectedOperations[i].DepthStart; - row.Cell(columnIdReasonOfEnd).Value = detectedOperations[i].IdReasonOfEnd switch - { - 0 => "Не определена", - 1 => "Не определено начало операции", - 101 => "Разница глубин забоя и положением долота", - 300 => "Низкое давление", - _ => detectedOperations[i].IdReasonOfEnd - }; + row.Cell(columnDepthStart).Value = current.DepthStart; + row.Cell(columnDepthEnd).Value = current.DepthEnd; + row.Cell(columnDepth).Value = current.DepthEnd - current.DepthStart; + + if (current.ExtraData.TryGetValue("IdReasonOfEnd", out object? idReasonOfEndObject) + && idReasonOfEndObject is int idReasonOfEnd) + row.Cell(columnIdReasonOfEnd).Value = GetIdReasonOfEnd(idReasonOfEnd); var link = $"{domains[idDomain]}/well/{well.Id}/telemetry/monitoring?end={Uri.EscapeDataString(dateStart.AddSeconds(1800 * 0.9).ToString("yyyy-MM-ddTHH:mm:ss.fff"))}&range=1800"; @@ -145,14 +144,40 @@ public class DetectedOperationExportService row.Cell(columnDateStart).SetHyperlink(new XLHyperlink(link)); row.Cell(columnDeltaDepth).Value = i > 0 && i + 1 < detectedOperations.Length - ? detectedOperations[i].DepthStart - detectedOperations[i - 1].DepthEnd + ? current.DepthStart - detectedOperations[i - 1].DepthEnd : 0; row.Cell(columnComment).Value = CreateComment(operationDetectorResults[i]); } } - - private async Task GetExcelTemplateStreamAsync(CancellationToken cancellationToken) + + private static string GetCategoryName(IEnumerable wellOperationCategories, DetectedOperation current) + { + var idCategory = current.IdCategory; + if (idCategory == WellOperationCategory.IdSlide + && current.ExtraData[DetectorDrilling.ExtraDataKeyHasOscillation] is bool hasOscillation + && hasOscillation) + return "Бурение в слайде с осцилляцией"; + + var category = wellOperationCategories.FirstOrDefault(o => o.Id == current.IdCategory); + + if(category is not null) + return category.Name; + + return $"Операция №{idCategory}"; + } + + private static string GetIdReasonOfEnd(int idReasonOfEnd) + => idReasonOfEnd switch { + 0 => "Не определена", + 1 => "Не определено начало операции", + 101 => "Разница глубин забоя и положением долота", + 300 => "Низкое давление", + _ => idReasonOfEnd.ToString($"Причина № {idReasonOfEnd}"), + + }; + + private async Task GetExcelTemplateStreamAsync(CancellationToken cancellationToken) { string resourceName = Assembly.GetExecutingAssembly() .GetManifestResourceNames() @@ -170,22 +195,23 @@ public class DetectedOperationExportService private string? CreateComment(OperationDetectorResult operationDetectorResult) { - switch (operationDetectorResult.Operation.IdCategory) + var operation = operationDetectorResult.Operation; + switch (operation.IdCategory) { - case 12000: - case 5002: - case 5003: + case WellOperationCategory.IdRotor: + case WellOperationCategory.IdSlide: { - var detectorDrilling = detectors.FirstOrDefault(d => d is DetectorDrilling) as DetectorDrilling; - var avgRotorSpeed = Math.Round(detectorDrilling.AvgRotorSpeedDict[(operationDetectorResult.TelemetryBegin, operationDetectorResult.TelemetryEnd)], 2); - var despersion = Math.Round(detectorDrilling.DespersionDict[(operationDetectorResult.TelemetryBegin, operationDetectorResult.TelemetryEnd)], 2); + var avgRotorSpeed = operation.ExtraData[DetectorDrilling.ExtraDataKeyAvgRotorSpeed]; + var dispersionOfNormalizedRotorSpeed = operation.ExtraData[DetectorDrilling.ExtraDataKeyDispersionOfNormalizedRotorSpeed]; + var isAfbEnabledObject = operation.ExtraData[DetectorDrilling.ExtraDataKeyIsAfbEnabled]; + var AfbState = ""; + if (isAfbEnabledObject is bool isAfbEnabled && isAfbEnabled) + AfbState = "АКБ - вкл"; - var stringBuilder = new StringBuilder(); - - stringBuilder.AppendLine($"Средняя скорость оборотов ротора: {avgRotorSpeed}"); - stringBuilder.AppendLine($"Нормированные обороты ротора: {despersion}"); - - return stringBuilder.ToString(); + var comment = $"Средняя скорость оборотов ротора: {avgRotorSpeed}\r\n" + + $"Дисперсия нормированных оборотов ротора: {dispersionOfNormalizedRotorSpeed} \r\n" + + $"{AfbState}"; + return comment; } default: return null; diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs index bacebad9..8a85b86f 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs @@ -1,5 +1,6 @@ using AsbCloudDb.Model; using System; +using System.Collections.Generic; using System.Linq; namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors @@ -55,16 +56,31 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors break; } - result = MakeOperation(idTelemetry, telemetry, begin, positionEnd, idReasonOfEnd); - return result is not null; + var (Begin, End) = RefineEdges(telemetry, begin, positionEnd); + + if (!IsValidTelemetryRange(telemetry, Begin, End)) + { + result = null; + return false; + } + + result = MakeOperationDetectorResult(idTelemetry, telemetry, Begin, End, idReasonOfEnd); + + return IsValidOperationDetectorResult(result); } result = null; return false; } - protected virtual bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult) => - operationDetectorResult.Operation.IdReasonOfEnd != IdReasonOfEnd_NotDetected; + protected virtual bool IsValidTelemetryRange(DetectableTelemetry[] telemetry, int begin, int end) + => end - begin > 1; + + protected virtual (int Begin, int End) RefineEdges(DetectableTelemetry[] telemetry, int begin, int end) + => (begin, end); + + protected virtual bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult) + => operationDetectorResult.Operation.DateEnd - operationDetectorResult.Operation.DateStart > TimeSpan.FromSeconds(3); protected abstract bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation); @@ -73,36 +89,51 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors ? IdReasonOfEnd_NotDetected : IdReasonOfEnd_NotDetectBegin; - private OperationDetectorResult? MakeOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, + private OperationDetectorResult MakeOperationDetectorResult( + int idTelemetry, + DetectableTelemetry[] telemetry, + int begin, + int end, int idReasonOfEnd) { - var pBegin = telemetry[begin]; - var pEnd = telemetry[end]; + var operation = MakeOperation(idTelemetry, telemetry, begin, end); + + operation.ExtraData["IdReasonOfEnd"] = idReasonOfEnd; + var result = new OperationDetectorResult { TelemetryBegin = begin, TelemetryEnd = end, - Operation = new DetectedOperation - { - IdTelemetry = idTelemetry, - IdCategory = GetIdOperation(telemetry, begin, end), - IdUsersAtStart = pBegin.IdUser ?? -1, - DateStart = pBegin.DateTime, - DateEnd = pEnd.DateTime, - DepthStart = (double)pBegin.WellDepth, - DepthEnd = (double)pEnd.WellDepth, - Value = CalcValue(telemetry, begin, end), - IdReasonOfEnd = idReasonOfEnd, - }, + Operation = operation, }; - return !IsValidOperationDetectorResult(result) ? null : result; + return result; } - protected abstract int GetIdOperation(DetectableTelemetry[] telemetry, int begin, int end); + protected abstract DetectedOperation MakeOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end); protected abstract double CalcValue(DetectableTelemetry[] telemetry, int begin, int end); + protected DetectedOperation MakeDetectedOperationBlank(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end) + { + var pBegin = telemetry[begin]; + var pEnd = telemetry[end]; + + var operation = new DetectedOperation + { + IdTelemetry = idTelemetry, + IdUsersAtStart = pBegin.IdUser ?? -1, + DateStart = pBegin.DateTime, + DateEnd = pEnd.DateTime, + DepthStart = (double)pBegin.WellDepth, + DepthEnd = (double)pEnd.WellDepth, + ExtraData = new Dictionary(), + Value = CalcValue(telemetry, begin, end), + }; + + return operation; + } + /// /// Среднее арифметическое /// @@ -111,7 +142,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors /// /// /// - public static double CalcAvgAppr( + protected static double CalcAvgAppr( Func yGetter, DetectableTelemetry[] telemetry, int begin, diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs index 80889677..2120b271 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using AsbCloudDb.Model; @@ -7,10 +6,13 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors; public class DetectorDrilling : DetectorAbstract { - public IDictionary<(int, int), float> AvgRotorSpeedDict { get; } = new Dictionary<(int, int), float>(); - public IDictionary<(int, int), double> DespersionDict { get; } = new Dictionary<(int, int), double>(); + private const double dispersionOfNormalizedRotorSpeedThreshold = 0.2d; + public const string ExtraDataKeyHasOscillation = "hasOscillation"; + public const string ExtraDataKeyDispersionOfNormalizedRotorSpeed = "dispersionOfNormalizedRotorSpeed"; + public const string ExtraDataKeyAvgRotorSpeed = "avgRotorSpeed"; + public const string ExtraDataKeyIsAfbEnabled = "isAfbEnabled"; - protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation) + protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation) { var point0 = telemetry[position]; var delta = point0.WellDepth - point0.BitDepth; @@ -41,36 +43,49 @@ public class DetectorDrilling : DetectorAbstract => CalcRop(telemetry, begin, end); protected override bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult) => - operationDetectorResult.Operation.IdReasonOfEnd is IdReasonOfEnd_DeltaDepthIsHi or IdReasonOfEnd_PressureIsLo && Math.Abs(operationDetectorResult.Operation.DepthStart - operationDetectorResult.Operation.DepthEnd) > 0.01; - protected override int GetIdOperation(DetectableTelemetry[] telemetry, int begin, int end) + protected override (int Begin, int End) RefineEdges(DetectableTelemetry[] telemetry, int begin, int end) + { + var i = end; + for (; i > begin + 1; i--) + if (telemetry[i].WellDepth - telemetry[i - 1].WellDepth > 0.001d) + break; + + return (begin, i); + } + + protected override DetectedOperation MakeOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end) + { + var (avgRotorSpeed, dispersionOfNormalizedRotorSpeed, isAfbEnabled) = CalcCriteries(telemetry, begin, end); + var operation = MakeDetectedOperationBlank(idTelemetry, telemetry, begin, end); + operation.IdCategory = GetIdOperation(avgRotorSpeed, dispersionOfNormalizedRotorSpeed); + operation.ExtraData[ExtraDataKeyAvgRotorSpeed] = avgRotorSpeed; + operation.ExtraData[ExtraDataKeyDispersionOfNormalizedRotorSpeed] = dispersionOfNormalizedRotorSpeed; + operation.ExtraData[ExtraDataKeyHasOscillation] = dispersionOfNormalizedRotorSpeed > dispersionOfNormalizedRotorSpeedThreshold; + operation.ExtraData[ExtraDataKeyIsAfbEnabled] = isAfbEnabled; + return operation; + } + + private static (double avgRotorSpeed, double dispersionOfNormalizedRotorSpeed, bool isAfbEnabled) CalcCriteries(DetectableTelemetry[] telemetry, int begin, int end) + { + var telemetryRange = telemetry[begin..end]; + var avgRotorSpeed = telemetryRange.Average(t => t.RotorSpeed); + var dispersion = telemetryRange.Average(t => Math.Pow(t.RotorSpeed / avgRotorSpeed - 1, 2)); + var isAfbEnabled = telemetryRange.Any(t => t.Mode > 0); + return (avgRotorSpeed, dispersion, isAfbEnabled); + } + + private static int GetIdOperation(double avgRotorSpeed, double dispersionOfNormalizedRotorSpeed) { - const int idSlideWithOscillation = 12000; - - var telemetryRange = telemetry[begin.. end] - .OrderBy(x => x.DateTime).ToList(); + const int idSlideWithOscillation = WellOperationCategory.IdSlide; - for (var i = telemetryRange.Count - 1; i >= 0 && telemetryRange.Count > 1; i--) - { - if (Math.Abs(telemetryRange[i].WellDepth - telemetryRange[i - 1].WellDepth) < 0.001d) - { - telemetryRange.RemoveAt(i); - continue; - } - - break; - } + if (avgRotorSpeed < 5) + return WellOperationCategory.IdSlide; - var avgRotorSpeed = telemetryRange.Average(t => t.RotorSpeed); - var despersion = telemetryRange.Average(t => Math.Pow(t.RotorSpeed/avgRotorSpeed - 1, 2)); - - AvgRotorSpeedDict.Add((begin, end), avgRotorSpeed); - DespersionDict.Add((begin, end), despersion); - - if (avgRotorSpeed < 5) - return WellOperationCategory.IdSlide; - - return despersion < 0.2d ? WellOperationCategory.IdRotor : idSlideWithOscillation; - } + if (dispersionOfNormalizedRotorSpeed < dispersionOfNormalizedRotorSpeedThreshold) + return WellOperationCategory.IdRotor; + else + return idSlideWithOscillation; + } } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs index 7109376d..509970c4 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs @@ -27,10 +27,14 @@ public class DetectorSlipsTime : DetectorAbstract return true; } - protected override int GetIdOperation(DetectableTelemetry[] telemetry, int begin, int end) - => WellOperationCategory.IdSlipsTime; - protected override bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult) => Math.Abs(operationDetectorResult.Operation.DepthStart - operationDetectorResult.Operation.DepthEnd) > 0.01; + + protected override DetectedOperation MakeOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end) + { + var operation = MakeDetectedOperationBlank(idTelemetry, telemetry, begin, end); + operation.IdCategory = WellOperationCategory.IdSlipsTime; + return operation; + } } From fdc615d343095132ea8d988ff471466eb66bbc20 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 5 Dec 2023 10:56:49 +0500 Subject: [PATCH 06/10] =?UTF-8?q?DetectorAbstract=20=D0=B4=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=BE=20=D0=BE=D0=BF=D1=80=D0=B5?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B2=D0=BA=D0=BB?= =?UTF-8?q?=D1=8E=D1=87=D0=B5=D0=BD=D0=BD=D1=8B=D1=85=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D1=81=D0=B8=D1=81=D1=82=D0=B5=D0=BC=20=D0=B2=D0=BE=20=D0=B2?= =?UTF-8?q?=D1=80=D0=B5=D0=BC=D1=8F=20=D0=B2=D1=8B=D0=BF=D0=BE=D0=BB=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudDb/Model/DetectedOperation.cs | 55 +++++++++++++ .../DetectedOperationExportService.cs | 4 +- .../DetectedOperationService.cs | 17 ++-- .../Detectors/DetectorAbstract.cs | 78 ++++++++++++------- .../Detectors/DetectorDrilling.cs | 25 +++--- .../Detectors/DetectorSlipsTime.cs | 13 ++-- .../SAUB/DetectedOperationController.cs | 8 +- AsbCloudWebApi/Program.cs | 1 + 8 files changed, 144 insertions(+), 57 deletions(-) diff --git a/AsbCloudDb/Model/DetectedOperation.cs b/AsbCloudDb/Model/DetectedOperation.cs index 27f4f928..7300eb59 100644 --- a/AsbCloudDb/Model/DetectedOperation.cs +++ b/AsbCloudDb/Model/DetectedOperation.cs @@ -41,6 +41,9 @@ namespace AsbCloudDb.Model [Column("value"), Comment("Ключевой показатель операции")] public double Value { get; set; } + [Column("enabled_subsystems"), Comment("флаги аключенных подсистем")] + public int EnabledSubsystems { get; set; } + [Column("extra_data", TypeName = "jsonb"), Comment("доп. инфо по операции")] public IDictionary ExtraData { get; set; } = null!; @@ -54,5 +57,57 @@ namespace AsbCloudDb.Model public override string ToString() => $"{IdCategory}\t{DateStart:G}\t{DateEnd:G}\t{DurationMinutes:#0.#}\t{DepthStart:#0.#}\t{DepthEnd:#0.#}"; + + /// + /// Флаги аключенных подсистем + /// + [Flags] + public enum EnabledSubsystemsFlags + { + /// + /// Автоподача долота + /// + AutoRotor = 1 << 0, + /// + /// БУРЕНИЕ В СЛАЙДЕ + /// + AutoSlide = 1 << 1, + /// + /// ПРОРАБОТКА + /// + AutoConditionig = 1 << 2, + /// + /// СПУСК СПО + /// + AutoSinking = 1 << 3, + /// + /// ПОДЪЕМ СПО + /// + AutoLifting = 1 << 4, + /// + /// ПОДЪЕМ С ПРОРАБОТКОЙ + /// + AutoLiftingWithConditionig = 1 << 5, + /// + /// блокировка + /// + AutoBlocknig = 1 << 6, + } + + /// + /// Есть ли флаг подсистемы у операции + /// + /// + /// + public bool HasSubsystemFlag(EnabledSubsystemsFlags flag) + => HasSubsystemFlag((int)flag); + + /// + /// Есть ли флаг/флаги подсистемы у операции + /// + /// + /// + public bool HasSubsystemFlag(int flags) + => (EnabledSubsystems & flags) > 0; } } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs index 0d882c58..bb5f2663 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs @@ -193,7 +193,7 @@ public class DetectedOperationExportService return memoryStream; } - private string? CreateComment(OperationDetectorResult operationDetectorResult) + private static string CreateComment(OperationDetectorResult operationDetectorResult) { var operation = operationDetectorResult.Operation; switch (operation.IdCategory) @@ -214,7 +214,7 @@ public class DetectedOperationExportService return comment; } default: - return null; + return string.Empty; } } diff --git a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs index a3cf05c4..a164cb4e 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs @@ -201,7 +201,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations if (well?.IdTelemetry is null || well.Timezone is null) return 0; - var query = BuildQuery(well, request); + var query = BuildQueryBase(well, request); if (query is null) return 0; @@ -232,13 +232,10 @@ namespace AsbCloudInfrastructure.Services.DetectOperations }; } - private IQueryable? BuildQuery(WellDto well, DetectedOperationRequest request) - { - if (well?.IdTelemetry is null || well.Timezone is null) - return null; + private IQueryable BuildQueryBase(WellDto well, DetectedOperationRequest request) + { var query = db.Set() - .Include(o => o.OperationCategory) .Where(o => o.IdTelemetry == well.IdTelemetry); if (request is not null) @@ -262,6 +259,14 @@ namespace AsbCloudInfrastructure.Services.DetectOperations query = query.Where(o => o.IdUsersAtStart == request.EqIdTelemetryUser); } + return query; + } + + private IQueryable BuildQuery(WellDto well, DetectedOperationRequest request) + { + IQueryable query = BuildQueryBase(well, request) + .Include(o => o.OperationCategory); + if (request?.SortFields?.Any() == true) { query = query.SortBy(request.SortFields); diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs index 8a85b86f..6da769bf 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs @@ -96,7 +96,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors int end, int idReasonOfEnd) { - var operation = MakeOperation(idTelemetry, telemetry, begin, end); + var operation = MakeDetectedOperation(idTelemetry, telemetry, begin, end); operation.ExtraData["IdReasonOfEnd"] = idReasonOfEnd; @@ -110,57 +110,83 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors return result; } - protected abstract DetectedOperation MakeOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end); - - protected abstract double CalcValue(DetectableTelemetry[] telemetry, int begin, int end); - - protected DetectedOperation MakeDetectedOperationBlank(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end) + private DetectedOperation MakeDetectedOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end) { var pBegin = telemetry[begin]; var pEnd = telemetry[end]; - + var (IdCategory, ExtraData) = GetSpecificInformation(telemetry, begin, end); var operation = new DetectedOperation { + IdCategory = IdCategory, IdTelemetry = idTelemetry, IdUsersAtStart = pBegin.IdUser ?? -1, DateStart = pBegin.DateTime, DateEnd = pEnd.DateTime, DepthStart = (double)pBegin.WellDepth, DepthEnd = (double)pEnd.WellDepth, - ExtraData = new Dictionary(), + ExtraData = ExtraData, Value = CalcValue(telemetry, begin, end), + EnabledSubsystems = DetectEnabledSubsystems(telemetry, begin, end) }; return operation; } /// - /// Среднее арифметическое + /// Получение информации специфичной для конкретного детектора + /// IdCategory - одна из констант WellOperationCategory + /// ExtraData - дополнительная информация для отладки алгоритмов авто определения + /// + /// + protected abstract (int IdCategory, IDictionary ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry, int begin, int end); + + /// + /// Расчет ключевого параметра операции /// - /// /// /// - /// + /// /// - protected static double CalcAvgAppr( - Func yGetter, - DetectableTelemetry[] telemetry, - int begin, - int fragmentLength) + protected abstract double CalcValue(DetectableTelemetry[] telemetry, int begin, int end); + + /// + /// Определение включенных подсистем во время выполнения операции + /// + /// + /// + /// + /// + private static int DetectEnabledSubsystems(DetectableTelemetry[] telemetry, int begin, int end) { - var end = begin + fragmentLength; - end = end < telemetry.Length - ? end - : telemetry.Length; - var subData = telemetry[begin..end].Select(yGetter); - if (end - begin > 10) + var enabledSubsystems = 0; + + for (var i = begin; i < end; i += 2) { - var ratio = (end - begin) / 5; - subData = subData.Where((_, i) => i % ratio > 0); + var mode = telemetry[i].Mode; + + if(mode == 1) + enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoRotor; + + if (mode == 3) + enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoSlide; + + if (mode == 2) + enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoConditionig; + + if (mode == 4) + enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoSinking; + + if (mode == 5) + enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoLifting; + + if (mode == 6) + enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoLiftingWithConditionig; + + if (mode == 10) + enabledSubsystems |= (int)DetectedOperation.EnabledSubsystemsFlags.AutoBlocknig; } - var avg = subData.Average(); - return avg; + return enabledSubsystems; } /// diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs index 2120b271..3806e380 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Drawing; using System.Linq; using AsbCloudDb.Model; @@ -55,25 +57,23 @@ public class DetectorDrilling : DetectorAbstract return (begin, i); } - protected override DetectedOperation MakeOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end) + protected override (int IdCategory, IDictionary ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry, int begin, int end) { - var (avgRotorSpeed, dispersionOfNormalizedRotorSpeed, isAfbEnabled) = CalcCriteries(telemetry, begin, end); - var operation = MakeDetectedOperationBlank(idTelemetry, telemetry, begin, end); - operation.IdCategory = GetIdOperation(avgRotorSpeed, dispersionOfNormalizedRotorSpeed); - operation.ExtraData[ExtraDataKeyAvgRotorSpeed] = avgRotorSpeed; - operation.ExtraData[ExtraDataKeyDispersionOfNormalizedRotorSpeed] = dispersionOfNormalizedRotorSpeed; - operation.ExtraData[ExtraDataKeyHasOscillation] = dispersionOfNormalizedRotorSpeed > dispersionOfNormalizedRotorSpeedThreshold; - operation.ExtraData[ExtraDataKeyIsAfbEnabled] = isAfbEnabled; - return operation; + var (avgRotorSpeed, dispersionOfNormalizedRotorSpeed) = CalcCriteries(telemetry, begin, end); + var idCategory = GetIdOperation(avgRotorSpeed, dispersionOfNormalizedRotorSpeed); + var extraData = new Dictionary(); + extraData[ExtraDataKeyAvgRotorSpeed] = avgRotorSpeed; + extraData[ExtraDataKeyDispersionOfNormalizedRotorSpeed] = dispersionOfNormalizedRotorSpeed; + extraData[ExtraDataKeyHasOscillation] = dispersionOfNormalizedRotorSpeed > dispersionOfNormalizedRotorSpeedThreshold; + return (idCategory, extraData); } - private static (double avgRotorSpeed, double dispersionOfNormalizedRotorSpeed, bool isAfbEnabled) CalcCriteries(DetectableTelemetry[] telemetry, int begin, int end) + private static (double avgRotorSpeed, double dispersionOfNormalizedRotorSpeed) CalcCriteries(DetectableTelemetry[] telemetry, int begin, int end) { var telemetryRange = telemetry[begin..end]; var avgRotorSpeed = telemetryRange.Average(t => t.RotorSpeed); var dispersion = telemetryRange.Average(t => Math.Pow(t.RotorSpeed / avgRotorSpeed - 1, 2)); - var isAfbEnabled = telemetryRange.Any(t => t.Mode > 0); - return (avgRotorSpeed, dispersion, isAfbEnabled); + return (avgRotorSpeed, dispersion); } private static int GetIdOperation(double avgRotorSpeed, double dispersionOfNormalizedRotorSpeed) @@ -88,4 +88,5 @@ public class DetectorDrilling : DetectorAbstract else return idSlideWithOscillation; } + } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs index 509970c4..58bdba27 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using AsbCloudDb.Model; namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors; @@ -27,14 +28,12 @@ public class DetectorSlipsTime : DetectorAbstract return true; } + protected override (int IdCategory, IDictionary ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry, int begin, int end) + { + return (WellOperationCategory.IdSlipsTime, new Dictionary()); + } + protected override bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult) => Math.Abs(operationDetectorResult.Operation.DepthStart - operationDetectorResult.Operation.DepthEnd) > 0.01; - - protected override DetectedOperation MakeOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end) - { - var operation = MakeDetectedOperationBlank(idTelemetry, telemetry, begin, end); - operation.IdCategory = WellOperationCategory.IdSlipsTime; - return operation; - } } diff --git a/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs b/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs index 33255f21..3c6d5b64 100644 --- a/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs @@ -60,7 +60,7 @@ namespace AsbCloudWebApi.Controllers.SAUB [FromQuery] DetectedOperationRequest request, CancellationToken token) { - if (!await UserHasAccesToWellAsync(request.IdWell, token)) + if (!await UserHasAccessToWellAsync(request.IdWell, token)) return Forbid(); var result = await detectedOperationService.GetAsync(request, token); @@ -79,7 +79,7 @@ namespace AsbCloudWebApi.Controllers.SAUB [FromQuery] DetectedOperationRequest request, CancellationToken token) { - if (!await UserHasAccesToWellAsync(request.IdWell, token)) + if (!await UserHasAccessToWellAsync(request.IdWell, token)) return Forbid(); var result = await detectedOperationService.GetOperationsStatAsync(request, token); @@ -101,14 +101,14 @@ namespace AsbCloudWebApi.Controllers.SAUB [FromQuery] DetectedOperationRequest request, CancellationToken token) { - if (!await UserHasAccesToWellAsync(request.IdWell, token)) + if (!await UserHasAccessToWellAsync(request.IdWell, token)) return Forbid(); var result = await detectedOperationService.DeleteAsync(request, token); return Ok(result); } - protected async Task UserHasAccesToWellAsync(int idWell, CancellationToken token) + protected async Task UserHasAccessToWellAsync(int idWell, CancellationToken token) { var idCompany = User.GetCompanyId(); if (idCompany is not null && diff --git a/AsbCloudWebApi/Program.cs b/AsbCloudWebApi/Program.cs index 18825902..864b9600 100644 --- a/AsbCloudWebApi/Program.cs +++ b/AsbCloudWebApi/Program.cs @@ -7,6 +7,7 @@ namespace AsbCloudWebApi { // Uncomment next line to find wired exceptions by tracing. //static TraceListenerView trace4debug = new TraceListenerView(); + enum A { a = 1 << 2 } public static void Main(string[] args) { From 29c5de89a596bdd5f157f3dce0fe2a54b85fbb20 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 5 Dec 2023 11:12:20 +0500 Subject: [PATCH 07/10] DetectedOperation add migration --- ...n_add_subsystems_and_extraData.Designer.cs | 9090 +++++++++++++++++ ...dOperation_add_subsystems_and_extraData.cs | 51 + .../AsbCloudDbContextModelSnapshot.cs | 17 +- 3 files changed, 9153 insertions(+), 5 deletions(-) create mode 100644 AsbCloudDb/Migrations/20231205061148_DetectedOperation_add_subsystems_and_extraData.Designer.cs create mode 100644 AsbCloudDb/Migrations/20231205061148_DetectedOperation_add_subsystems_and_extraData.cs diff --git a/AsbCloudDb/Migrations/20231205061148_DetectedOperation_add_subsystems_and_extraData.Designer.cs b/AsbCloudDb/Migrations/20231205061148_DetectedOperation_add_subsystems_and_extraData.Designer.cs new file mode 100644 index 00000000..e3461b2f --- /dev/null +++ b/AsbCloudDb/Migrations/20231205061148_DetectedOperation_add_subsystems_and_extraData.Designer.cs @@ -0,0 +1,9090 @@ +// +using System; +using System.Collections.Generic; +using System.Text.Json; +using AsbCloudDb.Model; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace AsbCloudDb.Migrations +{ + [DbContext(typeof(AsbCloudDbContext))] + [Migration("20231205061148_DetectedOperation_add_subsystems_and_extraData")] + partial class DetectedOperation_add_subsystems_and_extraData + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .UseCollation("Russian_Russia.1251") + .HasAnnotation("ProductVersion", "6.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack"); + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("AsbCloudDb.Model.Cluster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Caption") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption") + .HasComment("Название"); + + b.Property("IdDeposit") + .HasColumnType("integer") + .HasColumnName("id_deposit"); + + b.Property("Latitude") + .HasColumnType("double precision") + .HasColumnName("latitude"); + + b.Property("Longitude") + .HasColumnType("double precision") + .HasColumnName("longitude"); + + b.Property("Timezone") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("timezone") + .HasComment("Смещение часового пояса от UTC"); + + b.HasKey("Id"); + + b.HasIndex("IdDeposit"); + + b.ToTable("t_cluster"); + + b.HasComment("Кусты"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Company", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Caption") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption"); + + b.Property("IdCompanyType") + .HasMaxLength(255) + .HasColumnType("integer") + .HasColumnName("id_company_type") + .HasComment("вид деятельности"); + + b.HasKey("Id"); + + b.HasIndex("IdCompanyType"); + + b.ToTable("t_company"); + + b.HasData( + new + { + Id = 1, + Caption = "ООО \"АСБ\"", + IdCompanyType = 3 + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.CompanyType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Caption") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption"); + + b.Property("IsContact") + .HasColumnType("boolean") + .HasColumnName("is_contact"); + + b.Property("Order") + .HasColumnType("integer") + .HasColumnName("order"); + + b.HasKey("Id"); + + b.ToTable("t_company_type"); + + b.HasData( + new + { + Id = 1, + Caption = "Недропользователь", + IsContact = true, + Order = 3 + }, + new + { + Id = 2, + Caption = "Буровой подрядчик", + IsContact = true, + Order = 2 + }, + new + { + Id = 3, + Caption = "Сервис автоматизации бурения", + IsContact = true, + Order = 0 + }, + new + { + Id = 4, + Caption = "Сервис по ГТИ", + IsContact = true, + Order = 6 + }, + new + { + Id = 5, + Caption = "Растворный сервис", + IsContact = true, + Order = 4 + }, + new + { + Id = 6, + Caption = "Сервис по ННБ", + IsContact = true, + Order = 5 + }, + new + { + Id = 7, + Caption = "Служба супервайзинга", + IsContact = false, + Order = 1 + }, + new + { + Id = 9, + Caption = "Сервис по цементированию", + IsContact = true, + Order = 7 + }, + new + { + Id = 11, + Caption = "Дизельный сервис", + IsContact = false, + Order = 9 + }, + new + { + Id = 12, + Caption = "Сервис по обслуживанию верхних силовых приводов", + IsContact = true, + Order = 8 + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Contact", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Company") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("company") + .HasComment("компания"); + + b.Property("Email") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("email") + .HasComment("email"); + + b.Property("FullName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("full_name") + .HasComment("ФИО"); + + b.Property("IdCompanyType") + .HasMaxLength(255) + .HasColumnType("integer") + .HasColumnName("id_company_type") + .HasComment("вид деятельности"); + + b.Property("IdWell") + .HasMaxLength(255) + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("ключ скважины"); + + b.Property("Phone") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("phone") + .HasComment("номер телефона"); + + b.Property("Position") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("position") + .HasComment("должность"); + + b.HasKey("Id"); + + b.HasIndex("IdCompanyType"); + + b.HasIndex("IdWell"); + + b.ToTable("t_contact"); + + b.HasComment("Контакты"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DailyReports.DailyReport", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Date") + .HasColumnType("timestamp with time zone") + .HasColumnName("date") + .HasComment("Дата формирования отчёта"); + + b.Property("DateLastUpdate") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_update") + .HasComment("Дата последнего обновления"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("ID скважины"); + + b.Property("SignBlock") + .HasColumnType("jsonb") + .HasColumnName("sign_block") + .HasComment("Подпись"); + + b.Property("SubsystemBlock") + .HasColumnType("jsonb") + .HasColumnName("subsystem_block") + .HasComment("Наработкой подсистем"); + + b.Property("TimeBalanceBlock") + .HasColumnType("jsonb") + .HasColumnName("time_balance_block") + .HasComment("Баланс времени"); + + b.HasKey("Id"); + + b.HasIndex("IdWell", "Date") + .IsUnique(); + + b.ToTable("t_daily_report"); + + b.HasComment("Ежедневные отчёты"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Deposit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Caption") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption"); + + b.Property("Latitude") + .HasColumnType("double precision") + .HasColumnName("latitude"); + + b.Property("Longitude") + .HasColumnType("double precision") + .HasColumnName("longitude"); + + b.Property("Timezone") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("timezone") + .HasComment("Смещение часового пояса от UTC"); + + b.HasKey("Id"); + + b.ToTable("t_deposit"); + + b.HasComment("Месторождение"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DetectedOperation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateEnd") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_end") + .HasComment("Дата начала операции"); + + b.Property("DateStart") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_start") + .HasComment("Дата начала операции"); + + b.Property("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("depth_end") + .HasComment("Глубина после завершения операции, м"); + + b.Property("DepthStart") + .HasColumnType("double precision") + .HasColumnName("depth_start") + .HasComment("Глубина на начало операции, м"); + + b.Property("EnabledSubsystems") + .HasColumnType("integer") + .HasColumnName("enabled_subsystems") + .HasComment("флаги аключенных подсистем"); + + b.Property>("ExtraData") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("extra_data") + .HasComment("доп. инфо по операции"); + + b.Property("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category") + .HasComment("Id категории операции"); + + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property("IdUsersAtStart") + .HasColumnType("integer") + .HasColumnName("id_user") + .HasComment("Id пользователя по телеметрии на момент начала операции"); + + b.Property("Value") + .HasColumnType("double precision") + .HasColumnName("value") + .HasComment("Ключевой показатель операции"); + + b.HasKey("Id"); + + b.HasIndex("IdCategory"); + + b.HasIndex("IdTelemetry"); + + b.ToTable("t_detected_operation"); + + b.HasComment("автоматически определенные операции по телеметрии"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Driller", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id") + .HasComment("Идентификатор"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name") + .HasComment("Имя"); + + b.Property("Patronymic") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("patronymic") + .HasComment("Отчество"); + + b.Property("Surname") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("surname") + .HasComment("Фамилия"); + + b.HasKey("Id"); + + b.ToTable("t_driller"); + + b.HasComment("Бурильщик"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DrillingProgramPart", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("IdFileCategory") + .HasColumnType("integer") + .HasColumnName("id_file_category"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well"); + + b.HasKey("Id"); + + b.HasIndex("IdFileCategory"); + + b.HasIndex("IdWell", "IdFileCategory") + .IsUnique(); + + b.ToTable("t_drilling_program_part"); + + b.HasComment("части программ бурения"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DrillTest", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id") + .HasComment("Идентификатор"); + + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry") + .HasComment("Идентификатор телеметрии"); + + b.Property("DepthStart") + .HasColumnType("real") + .HasColumnName("depthStart") + .HasComment("Глубина начала"); + + b.Property("Params") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("t_drill_test_params") + .HasComment("Параметры записи drill test"); + + b.Property("TimeStampStart") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp_start") + .HasComment("Время начала"); + + b.HasKey("Id", "IdTelemetry"); + + b.HasIndex("IdTelemetry"); + + b.ToTable("t_drill_test"); + + b.HasComment("Drill_test"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Faq", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id") + .HasComment("Идентификатор"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Answer") + .HasColumnType("text") + .HasColumnName("answer") + .HasComment("Текст ответа"); + + b.Property("CounterQuestion") + .HasColumnType("integer") + .HasColumnName("counter_question") + .HasComment("Счетчик повторений вопроса"); + + b.Property("DateAnswer") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_answer") + .HasComment("Дата ответа"); + + b.Property("DateCreatedQuestion") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created_question") + .HasComment("Дата создания вопроса"); + + b.Property("DateLastEditedQuestion") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_edited_question") + .HasComment("Дата последнего редактирования вопроса"); + + b.Property("IdAuthorAnswer") + .HasColumnType("integer") + .HasColumnName("id_author_answer") + .HasComment("id автора ответа"); + + b.Property("IdAuthorQuestion") + .HasColumnType("integer") + .HasColumnName("id_author_question") + .HasComment("id автора вопроса"); + + b.Property("IdReplacementQuestion") + .HasColumnType("integer") + .HasColumnName("id_replacement_question") + .HasComment("Ключ заменяющего вопроса"); + + b.Property("IsFrequently") + .HasColumnType("boolean") + .HasColumnName("is_frequently") + .HasComment("Частый вопрос"); + + b.Property("Question") + .IsRequired() + .HasColumnType("text") + .HasColumnName("question") + .HasComment("Текст вопроса"); + + b.Property("State") + .HasColumnType("integer") + .HasColumnName("state") + .HasComment("Статус вопроса"); + + b.HasKey("Id"); + + b.HasIndex("IdAuthorAnswer"); + + b.HasIndex("IdAuthorQuestion"); + + b.ToTable("t_faq"); + + b.HasComment("вопросы пользователей"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.FileCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name") + .HasComment("Название категории"); + + b.Property("ShortName") + .HasColumnType("text") + .HasColumnName("short_name") + .HasComment("Короткое название категории"); + + b.HasKey("Id"); + + b.ToTable("t_file_category"); + + b.HasComment("Категории файлов"); + + b.HasData( + new + { + Id = 1, + Name = "Растворный сервис", + ShortName = "fluidService" + }, + new + { + Id = 2, + Name = "Цементирование", + ShortName = "cement" + }, + new + { + Id = 3, + Name = "ННБ", + ShortName = "nnb" + }, + new + { + Id = 4, + Name = "ГТИ", + ShortName = "gti" + }, + new + { + Id = 5, + Name = "Документы по скважине", + ShortName = "wellDocuments" + }, + new + { + Id = 6, + Name = "Супервайзер", + ShortName = "supervisor" + }, + new + { + Id = 7, + Name = "Мастер", + ShortName = "master" + }, + new + { + Id = 8, + Name = "Долотный сервис", + ShortName = "toolService" + }, + new + { + Id = 9, + Name = "Буровой подрядчик", + ShortName = "drillService" + }, + new + { + Id = 10, + Name = "Сервис по заканчиванию скважины", + ShortName = "closingService" + }, + new + { + Id = 12, + Name = "Рапорт", + ShortName = "report" + }, + new + { + Id = 1000, + Name = "Программа бурения" + }, + new + { + Id = 1001, + Name = "Задание от геологов" + }, + new + { + Id = 1002, + Name = "Профиль ствола скважины (ННБ)" + }, + new + { + Id = 1003, + Name = "Технологические расчеты (ННБ)" + }, + new + { + Id = 1004, + Name = "Долотная программа" + }, + new + { + Id = 1005, + Name = "Программа по растворам" + }, + new + { + Id = 1006, + Name = "Программа геофизических исследований" + }, + new + { + Id = 1007, + Name = "Планы спусков обсадных колонн" + }, + new + { + Id = 1008, + Name = "Программы цементирования обсадных колонн" + }, + new + { + Id = 10000, + Name = "Проект на бурение транспортного и горизонтального участков скважины" + }, + new + { + Id = 10001, + Name = "Программа на бурение транспортного и горизонтального участков скважины" + }, + new + { + Id = 10002, + Name = "Акт о начале бурения" + }, + new + { + Id = 10003, + Name = "План работ спуска и цементирования направления" + }, + new + { + Id = 10004, + Name = "Программа цементирования направления" + }, + new + { + Id = 10005, + Name = "Мера обсадных труб (направление)" + }, + new + { + Id = 10006, + Name = "Акт на выполненные работы по цементированию направления" + }, + new + { + Id = 10007, + Name = "Отчет по цементированию направления (график)" + }, + new + { + Id = 10008, + Name = "План работ спуска и цементирования кондуктора" + }, + new + { + Id = 10009, + Name = "Программа цементирования (кондуктор)" + }, + new + { + Id = 10010, + Name = "Мера обсадных труб (кондуктор)" + }, + new + { + Id = 10011, + Name = "Карта крепления кондуктора" + }, + new + { + Id = 10012, + Name = "Акт на выполненные работы по цементированию кондуктора" + }, + new + { + Id = 10013, + Name = "Отчет по цементированию кондуктора (график)" + }, + new + { + Id = 10014, + Name = "Акт о замере расстояния от стола ротора до муфты кондуктора" + }, + new + { + Id = 10015, + Name = "Акт опресовки цементного кольца за кондуктором" + }, + new + { + Id = 10016, + Name = "Акт опресовки ППГ с глухими плашками совместно с кондуктором" + }, + new + { + Id = 10017, + Name = "Акт опресовки ПУГ, ППГ с трубными плашками совместно с кондуктором" + }, + new + { + Id = 10018, + Name = "План работ на крепление обсадной колонны (эк. колонна)" + }, + new + { + Id = 10019, + Name = "Программа цементирования (эк. колонна)" + }, + new + { + Id = 10020, + Name = "Мера труб эксплуатационной колонны" + }, + new + { + Id = 10021, + Name = "Карта по креплению скважины (эк. колонна)" + }, + new + { + Id = 10022, + Name = "Акт на установку пружинных центраторов" + }, + new + { + Id = 10023, + Name = "Отчет по цементированию эксплуатационной колонны (график)" + }, + new + { + Id = 10024, + Name = "Акт на выполненные работы по цементированию эксплуатационной колонны" + }, + new + { + Id = 10025, + Name = "Акт об испытании эк. колонны на герметичность (СТОП)" + }, + new + { + Id = 10026, + Name = "Акт опресовки ППГ с глухими плашками совместно с э/колонной" + }, + new + { + Id = 10027, + Name = "Акт опресовки ПУГ, ППГ с трубными плашками совместно с э/колонной" + }, + new + { + Id = 10028, + Name = "Акт на вскрытие продуктивного пласта" + }, + new + { + Id = 10029, + Name = "Акт замера параметров раствора при бурении горизонтального участка" + }, + new + { + Id = 10030, + Name = "Разрешение на спуск «хвостовика» (телефонограмма)" + }, + new + { + Id = 10031, + Name = "План работ на спуск «хвостовика»" + }, + new + { + Id = 10032, + Name = "Акт готовности бурового и энергетического оборудования к спуску «хвостовика»" + }, + new + { + Id = 10033, + Name = "Акт шаблонировки ствола скважины перед спуском «хвостовика»" + }, + new + { + Id = 10034, + Name = "Мера обсадных труб (хвостовик)" + }, + new + { + Id = 10035, + Name = "Акт выполненных работ по спуску хвостовика с закачкой (нефти, солевого раствора" + }, + new + { + Id = 10036, + Name = "Акт о переводе скважины на тех. воду" + }, + new + { + Id = 10037, + Name = "Акт об окончании бурения" + }, + new + { + Id = 10038, + Name = "Акт на передачу скважины в освоение (КРС)" + }, + new + { + Id = 10039, + Name = "Акт на опресовку межколонного пространства с КРС" + }, + new + { + Id = 10040, + Name = "Акт на сдачу скважины в ЦДНГ" + }, + new + { + Id = 10041, + Name = "Паспорт ОУС (заполняется геологами)" + }, + new + { + Id = 10042, + Name = "Паспорт скважины (заполняется геологами)" + }, + new + { + Id = 10043, + Name = "Фактические данные бурения (вставляются в паспорт скважины)" + }, + new + { + Id = 20000, + Name = "Справки по страницам" + }, + new + { + Id = 30000, + Name = "Инструкции" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.FileInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("IdAuthor") + .HasColumnType("integer") + .HasColumnName("id_author") + .HasComment("Id пользователя, загрузившего файл"); + + b.Property("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category") + .HasComment("id категории файла"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("id скважины"); + + b.Property("IsDeleted") + .HasColumnType("boolean") + .HasColumnName("is_deleted") + .HasComment("Удален ли файл"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name") + .HasComment("Название файла"); + + b.Property("Size") + .HasColumnType("bigint") + .HasColumnName("file_size") + .HasComment("Размер файла"); + + b.Property("UploadDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.HasKey("Id"); + + b.HasIndex("IdAuthor"); + + b.HasIndex("IdCategory"); + + b.HasIndex("IdWell"); + + b.ToTable("t_file_info"); + + b.HasComment("Файлы всех категорий"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.FileMark", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Comment") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("comment") + .HasComment("Комментарий"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created") + .HasComment("Дата совершенного действия"); + + b.Property("IdFile") + .HasColumnType("integer") + .HasColumnName("id_file") + .HasComment("id файла"); + + b.Property("IdMarkType") + .HasColumnType("integer") + .HasColumnName("id_mark_type") + .HasComment("0 - отклонен, 1 - согласован"); + + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user") + .HasComment("id пользователя"); + + b.Property("IsDeleted") + .HasColumnType("boolean") + .HasColumnName("is_deleted") + .HasComment("Помечен ли файл как удаленный"); + + b.HasKey("Id"); + + b.HasIndex("IdFile"); + + b.HasIndex("IdUser"); + + b.ToTable("t_file_mark"); + + b.HasComment("Действия с файлами."); + }); + + modelBuilder.Entity("AsbCloudDb.Model.GTR.WitsItemFloat", b => + { + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property("IdRecord") + .HasColumnType("integer") + .HasColumnName("id_record"); + + b.Property("IdItem") + .HasColumnType("integer") + .HasColumnName("id_item"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("Value") + .HasColumnType("real") + .HasColumnName("value"); + + b.HasKey("IdTelemetry", "IdRecord", "IdItem", "DateTime"); + + b.ToTable("t_wits_float"); + + b.HasComment("таблица данных ГТИ с типом значения float"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.GTR.WitsItemInt", b => + { + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property("IdRecord") + .HasColumnType("integer") + .HasColumnName("id_record"); + + b.Property("IdItem") + .HasColumnType("integer") + .HasColumnName("id_item"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("Value") + .HasColumnType("integer") + .HasColumnName("value"); + + b.HasKey("IdTelemetry", "IdRecord", "IdItem", "DateTime"); + + b.ToTable("t_wits_int"); + + b.HasComment("таблица данных ГТИ с типом значения int"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.GTR.WitsItemString", b => + { + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property("IdRecord") + .HasColumnType("integer") + .HasColumnName("id_record"); + + b.Property("IdItem") + .HasColumnType("integer") + .HasColumnName("id_item"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text") + .HasColumnName("value"); + + b.HasKey("IdTelemetry", "IdRecord", "IdItem", "DateTime"); + + b.ToTable("t_wits_string"); + + b.HasComment("таблица данных ГТИ с типом значения string"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.HelpPage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category") + .HasComment("Id категории файла"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name") + .HasComment("Название файла"); + + b.Property("Size") + .HasColumnType("bigint") + .HasColumnName("file_size") + .HasComment("Размер файла"); + + b.Property("UrlPage") + .IsRequired() + .HasColumnType("text") + .HasColumnName("url_page") + .HasComment("Url страницы"); + + b.HasKey("Id"); + + b.HasIndex("IdCategory"); + + b.ToTable("t_help_page"); + + b.HasComment("Справки"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.LimitingParameter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateEnd") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_end"); + + b.Property("DateStart") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_start"); + + b.Property("DepthEnd") + .HasColumnType("real") + .HasColumnName("depth_end"); + + b.Property("DepthStart") + .HasColumnType("real") + .HasColumnName("depth_start"); + + b.Property("IdFeedRegulator") + .HasColumnType("smallint") + .HasColumnName("id_feed_regulator"); + + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.HasKey("Id"); + + b.HasIndex("IdTelemetry"); + + b.ToTable("t_limiting_parameter"); + + b.HasComment("Ограничения по параметрам телеметрии"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Manuals.Manual", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateDownload") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_download") + .HasComment("Дата загрузки"); + + b.Property("IdAuthor") + .HasColumnType("integer") + .HasColumnName("id_author") + .HasComment("Id автора"); + + b.Property("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category") + .HasComment("Id категории файла"); + + b.Property("IdDirectory") + .HasColumnType("integer") + .HasColumnName("id_directory") + .HasComment("Id директории"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name") + .HasComment("Название"); + + b.HasKey("Id"); + + b.HasIndex("IdAuthor"); + + b.HasIndex("IdCategory"); + + b.HasIndex("IdDirectory"); + + b.ToTable("t_manual"); + + b.HasComment("Инструкции"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Manuals.ManualDirectory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("IdParent") + .HasColumnType("integer") + .HasColumnName("id_parent") + .HasComment("Id родительской директории"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name") + .HasComment("Название"); + + b.HasKey("Id"); + + b.HasIndex("IdParent"); + + b.ToTable("t_manual_directory"); + + b.HasComment("Директория для инструкций"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Measure", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Data") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("data") + .HasComment("Данные таблицы последних данных"); + + b.Property("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category") + .HasComment("id категории"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("id скважины"); + + b.Property("IsDeleted") + .HasColumnType("boolean") + .HasColumnName("is_deleted") + .HasComment("Пометка удаленным"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp") + .HasComment("время добавления"); + + b.HasKey("Id"); + + b.HasIndex("IdCategory"); + + b.HasIndex("IdWell"); + + b.ToTable("t_measure"); + + b.HasComment("Таблица c данными для вкладки 'Последние данные'"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.MeasureCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name") + .HasComment("Название категории"); + + b.Property("ShortName") + .HasColumnType("text") + .HasColumnName("short_name") + .HasComment("Короткое название категории"); + + b.HasKey("Id"); + + b.ToTable("t_measure_category"); + + b.HasComment("Категория последних данных"); + + b.HasData( + new + { + Id = 1, + Name = "Показатели бурового раствора", + ShortName = "Раствор" + }, + new + { + Id = 2, + Name = "Шламограмма", + ShortName = "Шламограмма" + }, + new + { + Id = 3, + Name = "ННБ", + ShortName = "ННБ" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("IdNotificationCategory") + .HasColumnType("integer") + .HasColumnName("id_notification_category") + .HasComment("Id категории уведомления"); + + b.Property("IdTransportType") + .HasColumnType("integer") + .HasColumnName("id_transport_type") + .HasComment("Id типа доставки уведомления"); + + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user") + .HasComment("Id получателя"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text") + .HasColumnName("message") + .HasComment("Сообщение уведомления"); + + b.Property("ReadDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("read_date") + .HasComment("Дата прочтения уведомления"); + + b.Property("RegistrationDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("registration_date") + .HasComment("Дата регистрации уведомления"); + + b.Property("SentDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("sent_date") + .HasComment("Дата отправки уведомления"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text") + .HasColumnName("title") + .HasComment("Заголовок уведомления"); + + b.HasKey("Id"); + + b.HasIndex("IdNotificationCategory"); + + b.HasIndex("IdUser"); + + b.ToTable("t_notification"); + + b.HasComment("Уведомления"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.NotificationCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id"); + + b.ToTable("t_notification_category"); + + b.HasComment("Категории уведомлений"); + + b.HasData( + new + { + Id = 1, + Name = "Системные уведомления" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.OperationValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id") + .HasComment("Идентификатор"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("depth_end") + .HasComment("Конечная глубина"); + + b.Property("DepthStart") + .HasColumnType("double precision") + .HasColumnName("depth_start") + .HasComment("Старотовая глубина"); + + b.Property("IdOperationCategory") + .HasColumnType("integer") + .HasColumnName("id_operation_category") + .HasComment("Ид категории операции"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("Ид скважины"); + + b.Property("StandardValue") + .HasColumnType("double precision") + .HasColumnName("standard_value") + .HasComment("Нормативный показатель"); + + b.Property("TargetValue") + .HasColumnType("double precision") + .HasColumnName("target_value") + .HasComment("Целевой показатель"); + + b.HasKey("Id"); + + b.HasIndex("IdOperationCategory"); + + b.HasIndex("IdWell"); + + b.ToTable("t_operationvalue"); + + b.HasComment("Целевые/нормативные показатели операции"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("description") + .HasComment("Краткое описание"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name") + .HasComment("Название"); + + b.HasKey("Id"); + + b.ToTable("t_permission"); + + b.HasComment("Разрешения на доступ к данным"); + + b.HasData( + new + { + Id = 100, + Description = "Разрешение удалять админ. Кусты", + Name = "AdminCluster.delete" + }, + new + { + Id = 101, + Description = "Разрешение редактировать админ. Кусты", + Name = "AdminCluster.edit" + }, + new + { + Id = 102, + Description = "Разрешение просматривать админ. Кусты", + Name = "AdminCluster.get" + }, + new + { + Id = 103, + Description = "Разрешение удалять админ. Компании", + Name = "AdminCompany.delete" + }, + new + { + Id = 104, + Description = "Разрешение редактировать админ. Компании", + Name = "AdminCompany.edit" + }, + new + { + Id = 105, + Description = "Разрешение просматривать админ. Компании", + Name = "AdminCompany.get" + }, + new + { + Id = 106, + Description = "Разрешение удалять админ. Типы компаний", + Name = "AdminCompanyType.delete" + }, + new + { + Id = 107, + Description = "Разрешение редактировать админ. Типы компаний", + Name = "AdminCompanyType.edit" + }, + new + { + Id = 108, + Description = "Разрешение просматривать админ. Типы компаний", + Name = "AdminCompanyType.get" + }, + new + { + Id = 109, + Description = "Разрешение удалять админ. Месторождения", + Name = "AdminDeposit.delete" + }, + new + { + Id = 110, + Description = "Разрешение редактировать админ. Месторождения", + Name = "AdminDeposit.edit" + }, + new + { + Id = 111, + Description = "Разрешение просматривать админ. Месторождения", + Name = "AdminDeposit.get" + }, + new + { + Id = 112, + Description = "Разрешение удалять админ. Разрешения", + Name = "AdminPermission.delete" + }, + new + { + Id = 113, + Description = "Разрешение редактировать админ. Разрешения", + Name = "AdminPermission.edit" + }, + new + { + Id = 114, + Description = "Разрешение просматривать админ. Разрешения", + Name = "AdminPermission.get" + }, + new + { + Id = 115, + Description = "Разрешение удалять админ. Телеметрию", + Name = "AdminTelemetry.delete" + }, + new + { + Id = 116, + Description = "Разрешение редактировать админ. Телеметрию", + Name = "AdminTelemetry.edit" + }, + new + { + Id = 117, + Description = "Разрешение просматривать админ. Телеметрию", + Name = "AdminTelemetry.get" + }, + new + { + Id = 118, + Description = "Разрешение удалять админ. Пользователей", + Name = "AdminUser.delete" + }, + new + { + Id = 119, + Description = "Разрешение редактировать админ. Пользователей", + Name = "AdminUser.edit" + }, + new + { + Id = 120, + Description = "Разрешение просматривать админ. Пользователей", + Name = "AdminUser.get" + }, + new + { + Id = 121, + Description = "Разрешение удалять админ. Роли пользователей", + Name = "AdminUserRole.delete" + }, + new + { + Id = 122, + Description = "Разрешение редактировать админ. Роли пользователей", + Name = "AdminUserRole.edit" + }, + new + { + Id = 123, + Description = "Разрешение просматривать админ. Роли пользователей", + Name = "AdminUserRole.get" + }, + new + { + Id = 124, + Description = "Разрешение удалять админ. Скважины", + Name = "AdminWell.delete" + }, + new + { + Id = 125, + Description = "Разрешение редактировать админ. Скважины", + Name = "AdminWell.edit" + }, + new + { + Id = 126, + Description = "Разрешение просматривать админ. Скважины", + Name = "AdminWell.get" + }, + new + { + Id = 127, + Description = "Разрешение удалять админ. Подсистемы", + Name = "AdminSubsytem.delete" + }, + new + { + Id = 128, + Description = "Разрешение редактировать админ. Подсистемы", + Name = "AdminSubsytem.edit" + }, + new + { + Id = 129, + Description = "Разрешение просматривать админ. Подсистемы", + Name = "AdminSubsytem.get" + }, + new + { + Id = 200, + Description = "Разрешение редактировать 0", + Name = "Auth.edit" + }, + new + { + Id = 201, + Description = "Разрешение просматривать 0", + Name = "Auth.get" + }, + new + { + Id = 202, + Description = "Разрешение просматривать Кусты", + Name = "Cluster.get" + }, + new + { + Id = 203, + Description = "Разрешение просматривать Месторождения", + Name = "Deposit.get" + }, + new + { + Id = 204, + Description = "Разрешение удалять РТК", + Name = "DrillFlowChart.delete" + }, + new + { + Id = 205, + Description = "Разрешение редактировать РТК", + Name = "DrillFlowChart.edit" + }, + new + { + Id = 206, + Description = "Разрешение просматривать РТК", + Name = "DrillFlowChart.get" + }, + new + { + Id = 207, + Description = "Разрешение удалять Программу бурения", + Name = "DrillingProgram.delete" + }, + new + { + Id = 208, + Description = "Разрешение редактировать Программу бурения", + Name = "DrillingProgram.edit" + }, + new + { + Id = 209, + Description = "Разрешение просматривать Программу бурения", + Name = "DrillingProgram.get" + }, + new + { + Id = 210, + Description = "Разрешение удалять Режимы бурения", + Name = "DrillParams.delete" + }, + new + { + Id = 211, + Description = "Разрешение редактировать Режимы бурения", + Name = "DrillParams.edit" + }, + new + { + Id = 212, + Description = "Разрешение просматривать Режимы бурения", + Name = "DrillParams.get" + }, + new + { + Id = 213, + Description = "Разрешение удалять Файлы", + Name = "File.delete" + }, + new + { + Id = 214, + Description = "Разрешение редактировать Файлы", + Name = "File.edit" + }, + new + { + Id = 215, + Description = "Разрешение просматривать Файлы", + Name = "File.get" + }, + new + { + Id = 216, + Description = "Разрешение удалять Измерения", + Name = "Measure.delete" + }, + new + { + Id = 217, + Description = "Разрешение редактировать Измерения", + Name = "Measure.edit" + }, + new + { + Id = 218, + Description = "Разрешение просматривать Измерения", + Name = "Measure.get" + }, + new + { + Id = 219, + Description = "Разрешение просматривать Сообщения телеметрии", + Name = "Message.get" + }, + new + { + Id = 220, + Description = "Разрешение просматривать Статистику по операциям", + Name = "OperationStat.get" + }, + new + { + Id = 221, + Description = "Разрешение редактировать Рапорта", + Name = "Report.edit" + }, + new + { + Id = 222, + Description = "Разрешение просматривать Рапорта", + Name = "Report.get" + }, + new + { + Id = 223, + Description = "Разрешение просматривать админ. Системная статистика", + Name = "RequestTracker.get" + }, + new + { + Id = 224, + Description = "Разрешение удалять Рекомендации уставок", + Name = "Setpoints.delete" + }, + new + { + Id = 225, + Description = "Разрешение редактировать Рекомендации уставок", + Name = "Setpoints.edit" + }, + new + { + Id = 226, + Description = "Разрешение просматривать Рекомендации уставок", + Name = "Setpoints.get" + }, + new + { + Id = 227, + Description = "Разрешение редактировать Телеметрии", + Name = "Telemetry.edit" + }, + new + { + Id = 228, + Description = "Разрешение просматривать Анализ телеметрии", + Name = "TelemetryAnalytics.get" + }, + new + { + Id = 229, + Description = "Разрешение редактировать Данные телеметрии по САУБ", + Name = "TelemetryDataSaub.edit" + }, + new + { + Id = 230, + Description = "Разрешение просматривать Данные телеметрии по САУБ", + Name = "TelemetryDataSaub.get" + }, + new + { + Id = 231, + Description = "Разрешение редактировать Данные телеметрии по SpinMaster", + Name = "TelemetryDataSpin.edit" + }, + new + { + Id = 232, + Description = "Разрешение просматривать Данные телеметрии по SpinMaster", + Name = "TelemetryDataSpin.get" + }, + new + { + Id = 233, + Description = "Разрешение редактировать Скважины", + Name = "Well.edit" + }, + new + { + Id = 234, + Description = "Разрешение просматривать Скважины", + Name = "Well.get" + }, + new + { + Id = 235, + Description = "Разрешение редактировать Композитные скважины", + Name = "WellComposite.edit" + }, + new + { + Id = 236, + Description = "Разрешение просматривать Композитные скважины", + Name = "WellComposite.get" + }, + new + { + Id = 237, + Description = "Разрешение удалять Операции по скважинам", + Name = "WellOperation.delete" + }, + new + { + Id = 238, + Description = "Разрешение редактировать Операции по скважинам", + Name = "WellOperation.edit" + }, + new + { + Id = 239, + Description = "Разрешение просматривать Операции по скважинам", + Name = "WellOperation.get" + }, + new + { + Id = 240, + Description = "Разрешение редактировать Файлы категории 1 (Растворный сервис)", + Name = "File.edit1" + }, + new + { + Id = 241, + Description = "Разрешение редактировать Файлы категории 2 (Цементирование)", + Name = "File.edit2" + }, + new + { + Id = 242, + Description = "Разрешение редактировать Файлы категории 3 (ННБ)", + Name = "File.edit3" + }, + new + { + Id = 243, + Description = "Разрешение редактировать Файлы категории 4 (ГТИ)", + Name = "File.edit4" + }, + new + { + Id = 244, + Description = "Разрешение редактировать Файлы категории 5 (Документы по скважине)", + Name = "File.edit5" + }, + new + { + Id = 245, + Description = "Разрешение редактировать Файлы категории 6 (Супервайзер)", + Name = "File.edit6" + }, + new + { + Id = 246, + Description = "Разрешение редактировать Файлы категории 7 (Мастер)", + Name = "File.edit7" + }, + new + { + Id = 247, + Description = "Разрешение редактировать Файлы категории 8 (Долотный сервис)", + Name = "File.edit8" + }, + new + { + Id = 248, + Description = "Разрешение редактировать Файлы категории 9 (Буровой подрядчик)", + Name = "File.edit9" + }, + new + { + Id = 249, + Description = "Разрешение редактировать Файлы категории 10 (Сервис по заканчиванию скважины)", + Name = "File.edit10" + }, + new + { + Id = 250, + Description = "Разрешение редактировать Файлы категории 11 (Рапорт)", + Name = "File.edit11" + }, + new + { + Id = 251, + Description = "Разрешение редактировать Файлы категории 12", + Name = "File.edit12" + }, + new + { + Id = 252, + Description = "Разрешение редактировать Файлы категории 12", + Name = "File.edit13" + }, + new + { + Id = 253, + Description = "Разрешение редактировать Файлы категории 13", + Name = "File.edit14" + }, + new + { + Id = 254, + Description = "Разрешение редактировать Файлы категории 14", + Name = "File.edit15" + }, + new + { + Id = 255, + Description = "Разрешение редактировать Файлы категории 15", + Name = "File.edit16" + }, + new + { + Id = 256, + Description = "Разрешение редактировать Файлы категории 16", + Name = "File.edit17" + }, + new + { + Id = 257, + Description = "Разрешение редактировать Файлы категории 17", + Name = "File.edit18" + }, + new + { + Id = 258, + Description = "Разрешение редактировать Файлы категории 18", + Name = "File.edit19" + }, + new + { + Id = 259, + Description = "Разрешение редактировать Файлы категории 19", + Name = "File.edit20" + }, + new + { + Id = 260, + Description = "Разрешение редактировать Файлы категории 20", + Name = "File.edit21" + }, + new + { + Id = 261, + Description = "Разрешение редактировать Файлы категории 21", + Name = "File.edit22" + }, + new + { + Id = 262, + Description = "Разрешение редактировать Файлы категории 22", + Name = "File.edit23" + }, + new + { + Id = 263, + Description = "Разрешение редактировать Файлы категории 23", + Name = "File.edit24" + }, + new + { + Id = 264, + Description = "Разрешение редактировать Файлы категории 24", + Name = "File.edit25" + }, + new + { + Id = 265, + Description = "Разрешение редактировать Файлы категории 25", + Name = "File.edit26" + }, + new + { + Id = 266, + Description = "Разрешение редактировать Файлы категории 26", + Name = "File.edit27" + }, + new + { + Id = 267, + Description = "Разрешение редактировать Файлы категории 27", + Name = "File.edit28" + }, + new + { + Id = 268, + Description = "Разрешение редактировать Файлы категории 28", + Name = "File.edit29" + }, + new + { + Id = 269, + Description = "Разрешение редактировать Файлы категории 29", + Name = "File.edit30" + }, + new + { + Id = 380, + Description = "Разрешение просматривать список бурильщиков", + Name = "Driller.get" + }, + new + { + Id = 381, + Description = "Разрешение редактировать бурильщика", + Name = "Driller.edit" + }, + new + { + Id = 382, + Description = "Разрешение удалять бурильщик", + Name = "Driller.delete" + }, + new + { + Id = 383, + Description = "Разрешение просматривать графики бурильщиков", + Name = "Schedule.get" + }, + new + { + Id = 384, + Description = "Разрешение редактировать график бурильщика", + Name = "Schedule.edit" + }, + new + { + Id = 385, + Description = "Разрешение удалять график бурильщика", + Name = "Schedule.delete" + }, + new + { + Id = 386, + Description = "Разрешение просматривать суточный рапорт", + Name = "DailyReport.get" + }, + new + { + Id = 387, + Description = "Разрешение редактировать суточный рапорт", + Name = "DailyReport.edit" + }, + new + { + Id = 388, + Description = "Разрешение просматривать авто. определенные операции", + Name = "DetectedOperation.get" + }, + new + { + Id = 389, + Description = "Разрешение просматривать целевые значения", + Name = "OperationValue.get" + }, + new + { + Id = 390, + Description = "Разрешение редактировать целевые значения", + Name = "OperationValue.edit" + }, + new + { + Id = 391, + Description = "Разрешение удалять целевые значения", + Name = "OperationValue.delete" + }, + new + { + Id = 400, + Description = "Разрешение просматривать инфо по wits параметрам", + Name = "WitsInfo.get" + }, + new + { + Id = 401, + Description = "Разрешение просматривать WITS record 1", + Name = "WitsRecord1.get" + }, + new + { + Id = 407, + Description = "Разрешение просматривать WITS record 7", + Name = "WitsRecord7.get" + }, + new + { + Id = 408, + Description = "Разрешение просматривать WITS record 8", + Name = "WitsRecord8.get" + }, + new + { + Id = 450, + Description = "Разрешение просматривать WITS record 50", + Name = "WitsRecord50.get" + }, + new + { + Id = 460, + Description = "Разрешение просматривать WITS record 60", + Name = "WitsRecord60.get" + }, + new + { + Id = 461, + Description = "Разрешение просматривать WITS record 61", + Name = "WitsRecord61.get" + }, + new + { + Id = 500, + Description = "Разрешение удалять Категорий документов файлов", + Name = "FileCategory.delete" + }, + new + { + Id = 501, + Description = "Разрешение редактировать Категорий документов файлов", + Name = "FileCategory.edit" + }, + new + { + Id = 502, + Description = "Разрешение просматривать Категорий документов файлов", + Name = "FileCategory.get" + }, + new + { + Id = 503, + Description = "Разрешение удалять Дело скважины", + Name = "WellFinalDocuments.delete" + }, + new + { + Id = 504, + Description = "Разрешение редактировать Дело скважины", + Name = "WellFinalDocuments.edit" + }, + new + { + Id = 505, + Description = "Разрешение просматривать Дело скважины", + Name = "WellFinalDocuments.get" + }, + new + { + Id = 506, + Description = "Разрешение редактировать ответственных за загрузку файла Дело скважины", + Name = "WellFinalDocuments.editPublisher" + }, + new + { + Id = 507, + Description = "Разрешение просматривать наработка талевого каната", + Name = "TelemetryWirelineRunOut.get" + }, + new + { + Id = 510, + Description = "Разрешение просматривать плановая траектория", + Name = "PlannedTrajectory.get" + }, + new + { + Id = 511, + Description = "Разрешение редактировать плановая траектория", + Name = "PlannedTrajectory.edit" + }, + new + { + Id = 512, + Description = "Разрешение удалять плановая траектория", + Name = "PlannedTrajectory.delete" + }, + new + { + Id = 516, + Description = "Разрешение просматривать статистику вопросов", + Name = "FaqStatistics.get" + }, + new + { + Id = 517, + Description = "Разрешение редактировать вопрос", + Name = "FaqStatistics.edit" + }, + new + { + Id = 518, + Description = "Разрешение удалять вопрос", + Name = "FaqStatistics.delete" + }, + new + { + Id = 519, + Description = "Разрешение просматривать список контактов", + Name = "WellContact.get" + }, + new + { + Id = 520, + Description = "Разрешение редактировать список контактов", + Name = "WellContact.edit" + }, + new + { + Id = 521, + Description = "Разрешить создание справок по страницам", + Name = "HelpPage.edit" + }, + new + { + Id = 522, + Description = "Разрешить удаление всех настроек пользователя", + Name = "UserSettings.delete" + }, + new + { + Id = 523, + Description = "Разрешить редактирование инструкций", + Name = "Manual.edit" + }, + new + { + Id = 524, + Description = "Разрешить получение инструкций", + Name = "Manual.get" + }, + new + { + Id = 525, + Description = "Разрешение на редактирование РТК у завершенной скважины", + Name = "ProcessMap.editCompletedWell" + }, + new + { + Id = 526, + Description = "Разрешение на редактирование операций у завершенной скважины", + Name = "WellOperation.editCompletedWell" + }, + new + { + Id = 527, + Description = "Разрешение на удаление инструкций", + Name = "Manual.delete" + }, + new + { + Id = 528, + Description = "Разрешение на удаление контакта", + Name = "WellContact.delete" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.ProcessMaps.ProcessMapWellDrilling", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AxialLoadLimitMax") + .HasColumnType("double precision") + .HasColumnName("axial_load_limit_max") + .HasComment("Нагрузка, допустимый максимум"); + + b.Property("AxialLoadPlan") + .HasColumnType("double precision") + .HasColumnName("axial_load_plan") + .HasComment("Нагрузка, план"); + + b.Property("Comment") + .HasColumnType("text") + .HasColumnName("comment") + .HasComment("Комментарий"); + + b.Property("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("depth_end") + .HasComment("Глубина по стволу до, м"); + + b.Property("DepthStart") + .HasColumnType("double precision") + .HasColumnName("depth_start") + .HasComment("Глубина по стволу от, м"); + + b.Property("FlowLimitMax") + .HasColumnType("double precision") + .HasColumnName("flow_limit_max") + .HasComment("Расход, допустимый максимум"); + + b.Property("FlowPlan") + .HasColumnType("double precision") + .HasColumnName("flow_plan") + .HasComment("Расход, план"); + + b.Property("IdMode") + .HasColumnType("integer") + .HasColumnName("id_mode") + .HasComment("Id режима (1- ротор, 2 слайд)"); + + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user") + .HasComment("Id пользователя"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("Id скважины"); + + b.Property("IdWellSectionType") + .HasColumnType("integer") + .HasColumnName("id_wellsection_type") + .HasComment("Тип секции"); + + b.Property("LastUpdate") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_update") + .HasComment("Дата последнего изменения"); + + b.Property("PressureLimitMax") + .HasColumnType("double precision") + .HasColumnName("pressure_limit_max") + .HasComment("Перепад давления, допустимый максимум"); + + b.Property("PressurePlan") + .HasColumnType("double precision") + .HasColumnName("pressure_plan") + .HasComment("Перепад давления, план"); + + b.Property("RopPlan") + .HasColumnType("double precision") + .HasColumnName("rop_plan") + .HasComment("Плановая механическая скорость, м/ч"); + + b.Property("TopDriveSpeedLimitMax") + .HasColumnType("double precision") + .HasColumnName("top_drive_speed_limit_max") + .HasComment("Обороты на ВСП, допустимый максимум"); + + b.Property("TopDriveSpeedPlan") + .HasColumnType("double precision") + .HasColumnName("top_drive_speed_plan") + .HasComment("Обороты на ВСП, план"); + + b.Property("TopDriveTorqueLimitMax") + .HasColumnType("double precision") + .HasColumnName("top_drive_torque_limit_max") + .HasComment("Момент на ВСП, допустимый максимум"); + + b.Property("TopDriveTorquePlan") + .HasColumnType("double precision") + .HasColumnName("top_drive_torque_plan") + .HasComment("Момент на ВСП, план"); + + b.Property("UsageSaub") + .HasColumnType("double precision") + .HasColumnName("usage_saub") + .HasComment("Плановый процент использования АКБ"); + + b.Property("UsageSpin") + .HasColumnType("double precision") + .HasColumnName("usage_spin") + .HasComment("Плановый процент использования spin master"); + + b.HasKey("Id"); + + b.HasIndex("IdUser"); + + b.HasIndex("IdWell"); + + b.HasIndex("IdWellSectionType"); + + b.ToTable("t_process_map_well_drilling"); + + b.HasComment("РТК бурение скважины"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.ProcessMaps.ProcessMapWellReam", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Comment") + .HasColumnType("text") + .HasColumnName("comment") + .HasComment("Комментарий"); + + b.Property("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("depth_end") + .HasComment("Глубина по стволу до, м"); + + b.Property("DepthStart") + .HasColumnType("double precision") + .HasColumnName("depth_start") + .HasComment("Глубина по стволу от, м"); + + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user") + .HasComment("Id пользователя"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("Id скважины"); + + b.Property("IdWellSectionType") + .HasColumnType("integer") + .HasColumnName("id_wellsection_type") + .HasComment("Тип секции"); + + b.Property("LastUpdate") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_update") + .HasComment("Дата последнего изменения"); + + b.Property("Pressure") + .HasColumnType("double precision") + .HasColumnName("pressure") + .HasComment("Давление, атм"); + + b.Property("Repeats") + .HasColumnType("double precision") + .HasColumnName("repeats") + .HasComment("Количество повторений"); + + b.Property("SetpointDrag") + .HasColumnType("double precision") + .HasColumnName("setpoint_drag") + .HasComment("Уставка зятяжки, т"); + + b.Property("SetpointTight") + .HasColumnType("double precision") + .HasColumnName("setpoint_tight") + .HasComment("Уставка посадки, т"); + + b.Property("SpeedDownward") + .HasColumnType("double precision") + .HasColumnName("speed_downward") + .HasComment("Скорость спуска, м/ч"); + + b.Property("SpeedUpward") + .HasColumnType("double precision") + .HasColumnName("speed_upward") + .HasComment("Скорость подъёма, м/ч"); + + b.Property("SpinDownward") + .HasColumnType("double precision") + .HasColumnName("spin_downward") + .HasComment("Вращение при движении вниз, об/мин"); + + b.Property("SpinUpward") + .HasColumnType("double precision") + .HasColumnName("spin_upward") + .HasComment("Вращение при движении вверх, об/мин"); + + b.Property("Torque") + .HasColumnType("double precision") + .HasColumnName("torque") + .HasComment("Момент, кН*м"); + + b.HasKey("Id"); + + b.HasIndex("IdUser"); + + b.HasIndex("IdWell"); + + b.HasIndex("IdWellSectionType"); + + b.ToTable("t_process_map_well_ream"); + + b.HasComment("РТК проработка скважины"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationCompanyWell", b => + { + b.Property("IdCompany") + .HasColumnType("integer") + .HasColumnName("id_company"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well"); + + b.HasKey("IdCompany", "IdWell"); + + b.HasIndex("IdWell"); + + b.ToTable("t_relation_company_well"); + + b.HasComment("отношение скважин и компаний"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationContactWell", b => + { + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well"); + + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user"); + + b.HasKey("IdWell", "IdUser"); + + b.HasIndex("IdUser"); + + b.ToTable("t_relation_contact_well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationUserDrillingProgramPart", b => + { + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user"); + + b.Property("IdDrillingProgramPart") + .HasColumnType("integer") + .HasColumnName("id_drilling_program_part"); + + b.Property("IdUserRole") + .HasColumnType("integer") + .HasColumnName("id_role") + .HasComment("1 - publisher, 2 - approver"); + + b.HasKey("IdUser", "IdDrillingProgramPart") + .HasName("t_relation_user_drilling_program_part_pk"); + + b.HasIndex("IdDrillingProgramPart"); + + b.ToTable("t_relation_user_drilling_program_part"); + + b.HasComment("Отношение пользователей и частей ПБ"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationUserRolePermission", b => + { + b.Property("IdUserRole") + .HasColumnType("integer") + .HasColumnName("id_user_role"); + + b.Property("IdPermission") + .HasColumnType("integer") + .HasColumnName("id_permission"); + + b.HasKey("IdUserRole", "IdPermission"); + + b.HasIndex("IdPermission"); + + b.ToTable("t_relation_user_role_permission"); + + b.HasComment("Отношение ролей пользователей и разрешений доступа"); + + b.HasData( + new + { + IdUserRole = 1100, + IdPermission = 102 + }, + new + { + IdUserRole = 1100, + IdPermission = 111 + }, + new + { + IdUserRole = 1101, + IdPermission = 101 + }, + new + { + IdUserRole = 1101, + IdPermission = 100 + }, + new + { + IdUserRole = 1102, + IdPermission = 105 + }, + new + { + IdUserRole = 1102, + IdPermission = 108 + }, + new + { + IdUserRole = 1103, + IdPermission = 104 + }, + new + { + IdUserRole = 1103, + IdPermission = 103 + }, + new + { + IdUserRole = 1104, + IdPermission = 108 + }, + new + { + IdUserRole = 1105, + IdPermission = 107 + }, + new + { + IdUserRole = 1105, + IdPermission = 106 + }, + new + { + IdUserRole = 1106, + IdPermission = 111 + }, + new + { + IdUserRole = 1107, + IdPermission = 110 + }, + new + { + IdUserRole = 1107, + IdPermission = 109 + }, + new + { + IdUserRole = 1108, + IdPermission = 114 + }, + new + { + IdUserRole = 1109, + IdPermission = 113 + }, + new + { + IdUserRole = 1109, + IdPermission = 112 + }, + new + { + IdUserRole = 1110, + IdPermission = 123 + }, + new + { + IdUserRole = 1110, + IdPermission = 114 + }, + new + { + IdUserRole = 1111, + IdPermission = 122 + }, + new + { + IdUserRole = 1111, + IdPermission = 121 + }, + new + { + IdUserRole = 1112, + IdPermission = 117 + }, + new + { + IdUserRole = 1113, + IdPermission = 105 + }, + new + { + IdUserRole = 1113, + IdPermission = 123 + }, + new + { + IdUserRole = 1113, + IdPermission = 120 + }, + new + { + IdUserRole = 1114, + IdPermission = 119 + }, + new + { + IdUserRole = 1114, + IdPermission = 118 + }, + new + { + IdUserRole = 1114, + IdPermission = 200 + }, + new + { + IdUserRole = 1115, + IdPermission = 223 + }, + new + { + IdUserRole = 1116, + IdPermission = 105 + }, + new + { + IdUserRole = 1116, + IdPermission = 102 + }, + new + { + IdUserRole = 1116, + IdPermission = 117 + }, + new + { + IdUserRole = 1116, + IdPermission = 126 + }, + new + { + IdUserRole = 1117, + IdPermission = 125 + }, + new + { + IdUserRole = 1117, + IdPermission = 124 + }, + new + { + IdUserRole = 1200, + IdPermission = 203 + }, + new + { + IdUserRole = 1200, + IdPermission = 230 + }, + new + { + IdUserRole = 1201, + IdPermission = 202 + }, + new + { + IdUserRole = 1201, + IdPermission = 203 + }, + new + { + IdUserRole = 1201, + IdPermission = 220 + }, + new + { + IdUserRole = 1202, + IdPermission = 203 + }, + new + { + IdUserRole = 1202, + IdPermission = 220 + }, + new + { + IdUserRole = 1202, + IdPermission = 236 + }, + new + { + IdUserRole = 1202, + IdPermission = 212 + }, + new + { + IdUserRole = 1203, + IdPermission = 235 + }, + new + { + IdUserRole = 1204, + IdPermission = 202 + }, + new + { + IdUserRole = 1204, + IdPermission = 203 + }, + new + { + IdUserRole = 1205, + IdPermission = 215 + }, + new + { + IdUserRole = 1206, + IdPermission = 203 + }, + new + { + IdUserRole = 1206, + IdPermission = 206 + }, + new + { + IdUserRole = 1207, + IdPermission = 205 + }, + new + { + IdUserRole = 1208, + IdPermission = 218 + }, + new + { + IdUserRole = 1209, + IdPermission = 217 + }, + new + { + IdUserRole = 1210, + IdPermission = 203 + }, + new + { + IdUserRole = 1210, + IdPermission = 230 + }, + new + { + IdUserRole = 1210, + IdPermission = 219 + }, + new + { + IdUserRole = 1211, + IdPermission = 203 + }, + new + { + IdUserRole = 1211, + IdPermission = 220 + }, + new + { + IdUserRole = 1211, + IdPermission = 239 + }, + new + { + IdUserRole = 1212, + IdPermission = 238 + }, + new + { + IdUserRole = 1212, + IdPermission = 237 + }, + new + { + IdUserRole = 1213, + IdPermission = 203 + }, + new + { + IdUserRole = 1213, + IdPermission = 239 + }, + new + { + IdUserRole = 1213, + IdPermission = 212 + }, + new + { + IdUserRole = 1214, + IdPermission = 211 + }, + new + { + IdUserRole = 1214, + IdPermission = 210 + }, + new + { + IdUserRole = 1215, + IdPermission = 203 + }, + new + { + IdUserRole = 1215, + IdPermission = 222 + }, + new + { + IdUserRole = 1216, + IdPermission = 221 + }, + new + { + IdUserRole = 1217, + IdPermission = 226 + }, + new + { + IdUserRole = 1218, + IdPermission = 225 + }, + new + { + IdUserRole = 1218, + IdPermission = 224 + }, + new + { + IdUserRole = 1219, + IdPermission = 203 + }, + new + { + IdUserRole = 1219, + IdPermission = 206 + }, + new + { + IdUserRole = 1219, + IdPermission = 230 + }, + new + { + IdUserRole = 1219, + IdPermission = 232 + }, + new + { + IdUserRole = 1220, + IdPermission = 203 + }, + new + { + IdUserRole = 1220, + IdPermission = 228 + }, + new + { + IdUserRole = 1221, + IdPermission = 202 + }, + new + { + IdUserRole = 1221, + IdPermission = 203 + }, + new + { + IdUserRole = 1221, + IdPermission = 220 + }, + new + { + IdUserRole = 1221, + IdPermission = 234 + }, + new + { + IdUserRole = 1500, + IdPermission = 507 + }, + new + { + IdUserRole = 1500, + IdPermission = 510 + }, + new + { + IdUserRole = 1501, + IdPermission = 214 + }, + new + { + IdUserRole = 1501, + IdPermission = 213 + }, + new + { + IdUserRole = 1502, + IdPermission = 207 + }, + new + { + IdUserRole = 1502, + IdPermission = 208 + }, + new + { + IdUserRole = 2000, + IdPermission = 205 + }, + new + { + IdUserRole = 2000, + IdPermission = 204 + }, + new + { + IdUserRole = 2000, + IdPermission = 245 + }, + new + { + IdUserRole = 2001, + IdPermission = 244 + }, + new + { + IdUserRole = 2001, + IdPermission = 245 + }, + new + { + IdUserRole = 2002, + IdPermission = 244 + }, + new + { + IdUserRole = 2002, + IdPermission = 246 + }, + new + { + IdUserRole = 2002, + IdPermission = 237 + }, + new + { + IdUserRole = 2002, + IdPermission = 238 + }, + new + { + IdUserRole = 2003, + IdPermission = 240 + }, + new + { + IdUserRole = 2003, + IdPermission = 217 + }, + new + { + IdUserRole = 2003, + IdPermission = 216 + }, + new + { + IdUserRole = 2004, + IdPermission = 242 + }, + new + { + IdUserRole = 2004, + IdPermission = 217 + }, + new + { + IdUserRole = 2004, + IdPermission = 216 + }, + new + { + IdUserRole = 2004, + IdPermission = 205 + }, + new + { + IdUserRole = 2004, + IdPermission = 204 + }, + new + { + IdUserRole = 2005, + IdPermission = 247 + }, + new + { + IdUserRole = 2005, + IdPermission = 205 + }, + new + { + IdUserRole = 2005, + IdPermission = 204 + }, + new + { + IdUserRole = 2006, + IdPermission = 243 + }, + new + { + IdUserRole = 2006, + IdPermission = 205 + }, + new + { + IdUserRole = 2006, + IdPermission = 204 + }, + new + { + IdUserRole = 2007, + IdPermission = 241 + }, + new + { + IdUserRole = 2007, + IdPermission = 205 + }, + new + { + IdUserRole = 2007, + IdPermission = 204 + }, + new + { + IdUserRole = 1, + IdPermission = 100 + }, + new + { + IdUserRole = 1, + IdPermission = 101 + }, + new + { + IdUserRole = 1, + IdPermission = 102 + }, + new + { + IdUserRole = 1, + IdPermission = 103 + }, + new + { + IdUserRole = 1, + IdPermission = 104 + }, + new + { + IdUserRole = 1, + IdPermission = 105 + }, + new + { + IdUserRole = 1, + IdPermission = 106 + }, + new + { + IdUserRole = 1, + IdPermission = 107 + }, + new + { + IdUserRole = 1, + IdPermission = 108 + }, + new + { + IdUserRole = 1, + IdPermission = 109 + }, + new + { + IdUserRole = 1, + IdPermission = 110 + }, + new + { + IdUserRole = 1, + IdPermission = 111 + }, + new + { + IdUserRole = 1, + IdPermission = 112 + }, + new + { + IdUserRole = 1, + IdPermission = 113 + }, + new + { + IdUserRole = 1, + IdPermission = 114 + }, + new + { + IdUserRole = 1, + IdPermission = 115 + }, + new + { + IdUserRole = 1, + IdPermission = 116 + }, + new + { + IdUserRole = 1, + IdPermission = 117 + }, + new + { + IdUserRole = 1, + IdPermission = 118 + }, + new + { + IdUserRole = 1, + IdPermission = 119 + }, + new + { + IdUserRole = 1, + IdPermission = 120 + }, + new + { + IdUserRole = 1, + IdPermission = 121 + }, + new + { + IdUserRole = 1, + IdPermission = 122 + }, + new + { + IdUserRole = 1, + IdPermission = 123 + }, + new + { + IdUserRole = 1, + IdPermission = 124 + }, + new + { + IdUserRole = 1, + IdPermission = 125 + }, + new + { + IdUserRole = 1, + IdPermission = 126 + }, + new + { + IdUserRole = 1, + IdPermission = 127 + }, + new + { + IdUserRole = 1, + IdPermission = 128 + }, + new + { + IdUserRole = 1, + IdPermission = 129 + }, + new + { + IdUserRole = 1, + IdPermission = 200 + }, + new + { + IdUserRole = 1, + IdPermission = 201 + }, + new + { + IdUserRole = 1, + IdPermission = 202 + }, + new + { + IdUserRole = 1, + IdPermission = 203 + }, + new + { + IdUserRole = 1, + IdPermission = 204 + }, + new + { + IdUserRole = 1, + IdPermission = 205 + }, + new + { + IdUserRole = 1, + IdPermission = 206 + }, + new + { + IdUserRole = 1, + IdPermission = 207 + }, + new + { + IdUserRole = 1, + IdPermission = 208 + }, + new + { + IdUserRole = 1, + IdPermission = 209 + }, + new + { + IdUserRole = 1, + IdPermission = 210 + }, + new + { + IdUserRole = 1, + IdPermission = 211 + }, + new + { + IdUserRole = 1, + IdPermission = 212 + }, + new + { + IdUserRole = 1, + IdPermission = 213 + }, + new + { + IdUserRole = 1, + IdPermission = 214 + }, + new + { + IdUserRole = 1, + IdPermission = 215 + }, + new + { + IdUserRole = 1, + IdPermission = 216 + }, + new + { + IdUserRole = 1, + IdPermission = 217 + }, + new + { + IdUserRole = 1, + IdPermission = 218 + }, + new + { + IdUserRole = 1, + IdPermission = 219 + }, + new + { + IdUserRole = 1, + IdPermission = 220 + }, + new + { + IdUserRole = 1, + IdPermission = 221 + }, + new + { + IdUserRole = 1, + IdPermission = 222 + }, + new + { + IdUserRole = 1, + IdPermission = 223 + }, + new + { + IdUserRole = 1, + IdPermission = 224 + }, + new + { + IdUserRole = 1, + IdPermission = 225 + }, + new + { + IdUserRole = 1, + IdPermission = 226 + }, + new + { + IdUserRole = 1, + IdPermission = 227 + }, + new + { + IdUserRole = 1, + IdPermission = 228 + }, + new + { + IdUserRole = 1, + IdPermission = 229 + }, + new + { + IdUserRole = 1, + IdPermission = 230 + }, + new + { + IdUserRole = 1, + IdPermission = 231 + }, + new + { + IdUserRole = 1, + IdPermission = 232 + }, + new + { + IdUserRole = 1, + IdPermission = 233 + }, + new + { + IdUserRole = 1, + IdPermission = 234 + }, + new + { + IdUserRole = 1, + IdPermission = 235 + }, + new + { + IdUserRole = 1, + IdPermission = 236 + }, + new + { + IdUserRole = 1, + IdPermission = 237 + }, + new + { + IdUserRole = 1, + IdPermission = 238 + }, + new + { + IdUserRole = 1, + IdPermission = 239 + }, + new + { + IdUserRole = 1, + IdPermission = 240 + }, + new + { + IdUserRole = 1, + IdPermission = 241 + }, + new + { + IdUserRole = 1, + IdPermission = 242 + }, + new + { + IdUserRole = 1, + IdPermission = 243 + }, + new + { + IdUserRole = 1, + IdPermission = 244 + }, + new + { + IdUserRole = 1, + IdPermission = 245 + }, + new + { + IdUserRole = 1, + IdPermission = 246 + }, + new + { + IdUserRole = 1, + IdPermission = 247 + }, + new + { + IdUserRole = 1, + IdPermission = 248 + }, + new + { + IdUserRole = 1, + IdPermission = 249 + }, + new + { + IdUserRole = 1, + IdPermission = 250 + }, + new + { + IdUserRole = 1, + IdPermission = 251 + }, + new + { + IdUserRole = 1, + IdPermission = 252 + }, + new + { + IdUserRole = 1, + IdPermission = 253 + }, + new + { + IdUserRole = 1, + IdPermission = 254 + }, + new + { + IdUserRole = 1, + IdPermission = 255 + }, + new + { + IdUserRole = 1, + IdPermission = 256 + }, + new + { + IdUserRole = 1, + IdPermission = 257 + }, + new + { + IdUserRole = 1, + IdPermission = 258 + }, + new + { + IdUserRole = 1, + IdPermission = 259 + }, + new + { + IdUserRole = 1, + IdPermission = 260 + }, + new + { + IdUserRole = 1, + IdPermission = 261 + }, + new + { + IdUserRole = 1, + IdPermission = 262 + }, + new + { + IdUserRole = 1, + IdPermission = 263 + }, + new + { + IdUserRole = 1, + IdPermission = 264 + }, + new + { + IdUserRole = 1, + IdPermission = 265 + }, + new + { + IdUserRole = 1, + IdPermission = 266 + }, + new + { + IdUserRole = 1, + IdPermission = 267 + }, + new + { + IdUserRole = 1, + IdPermission = 268 + }, + new + { + IdUserRole = 1, + IdPermission = 269 + }, + new + { + IdUserRole = 1, + IdPermission = 380 + }, + new + { + IdUserRole = 1, + IdPermission = 381 + }, + new + { + IdUserRole = 1, + IdPermission = 382 + }, + new + { + IdUserRole = 1, + IdPermission = 383 + }, + new + { + IdUserRole = 1, + IdPermission = 384 + }, + new + { + IdUserRole = 1, + IdPermission = 385 + }, + new + { + IdUserRole = 1, + IdPermission = 386 + }, + new + { + IdUserRole = 1, + IdPermission = 387 + }, + new + { + IdUserRole = 1, + IdPermission = 388 + }, + new + { + IdUserRole = 1, + IdPermission = 389 + }, + new + { + IdUserRole = 1, + IdPermission = 390 + }, + new + { + IdUserRole = 1, + IdPermission = 391 + }, + new + { + IdUserRole = 1, + IdPermission = 400 + }, + new + { + IdUserRole = 1, + IdPermission = 401 + }, + new + { + IdUserRole = 1, + IdPermission = 407 + }, + new + { + IdUserRole = 1, + IdPermission = 408 + }, + new + { + IdUserRole = 1, + IdPermission = 450 + }, + new + { + IdUserRole = 1, + IdPermission = 460 + }, + new + { + IdUserRole = 1, + IdPermission = 461 + }, + new + { + IdUserRole = 1, + IdPermission = 500 + }, + new + { + IdUserRole = 1, + IdPermission = 501 + }, + new + { + IdUserRole = 1, + IdPermission = 502 + }, + new + { + IdUserRole = 1, + IdPermission = 503 + }, + new + { + IdUserRole = 1, + IdPermission = 504 + }, + new + { + IdUserRole = 1, + IdPermission = 505 + }, + new + { + IdUserRole = 1, + IdPermission = 506 + }, + new + { + IdUserRole = 1, + IdPermission = 507 + }, + new + { + IdUserRole = 1, + IdPermission = 510 + }, + new + { + IdUserRole = 1, + IdPermission = 511 + }, + new + { + IdUserRole = 1, + IdPermission = 512 + }, + new + { + IdUserRole = 1, + IdPermission = 516 + }, + new + { + IdUserRole = 1, + IdPermission = 517 + }, + new + { + IdUserRole = 1, + IdPermission = 518 + }, + new + { + IdUserRole = 1, + IdPermission = 519 + }, + new + { + IdUserRole = 1, + IdPermission = 520 + }, + new + { + IdUserRole = 1, + IdPermission = 521 + }, + new + { + IdUserRole = 1, + IdPermission = 522 + }, + new + { + IdUserRole = 1, + IdPermission = 523 + }, + new + { + IdUserRole = 1, + IdPermission = 524 + }, + new + { + IdUserRole = 1, + IdPermission = 525 + }, + new + { + IdUserRole = 1, + IdPermission = 526 + }, + new + { + IdUserRole = 1, + IdPermission = 527 + }, + new + { + IdUserRole = 1, + IdPermission = 528 + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationUserRoleUserRole", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id_user_role"); + + b.Property("IdInclude") + .HasColumnType("integer") + .HasColumnName("id_include_user_role"); + + b.HasKey("Id", "IdInclude") + .HasName("t_relation_user_role_user_role_pk"); + + b.HasIndex("IdInclude"); + + b.ToTable("t_relation_user_role_user_role"); + + b.HasComment("Отношение ролей к ролям"); + + b.HasData( + new + { + Id = 1101, + IdInclude = 1100 + }, + new + { + Id = 1103, + IdInclude = 1102 + }, + new + { + Id = 1105, + IdInclude = 1104 + }, + new + { + Id = 1107, + IdInclude = 1106 + }, + new + { + Id = 1109, + IdInclude = 1108 + }, + new + { + Id = 1111, + IdInclude = 1110 + }, + new + { + Id = 1114, + IdInclude = 1113 + }, + new + { + Id = 1117, + IdInclude = 1116 + }, + new + { + Id = 1203, + IdInclude = 1202 + }, + new + { + Id = 1207, + IdInclude = 1206 + }, + new + { + Id = 1209, + IdInclude = 1208 + }, + new + { + Id = 1212, + IdInclude = 1211 + }, + new + { + Id = 1214, + IdInclude = 1213 + }, + new + { + Id = 1216, + IdInclude = 1215 + }, + new + { + Id = 1218, + IdInclude = 1217 + }, + new + { + Id = 2000, + IdInclude = 1200 + }, + new + { + Id = 2000, + IdInclude = 1201 + }, + new + { + Id = 2000, + IdInclude = 1202 + }, + new + { + Id = 2000, + IdInclude = 1204 + }, + new + { + Id = 2000, + IdInclude = 1205 + }, + new + { + Id = 2000, + IdInclude = 1206 + }, + new + { + Id = 2000, + IdInclude = 1208 + }, + new + { + Id = 2000, + IdInclude = 1210 + }, + new + { + Id = 2000, + IdInclude = 1211 + }, + new + { + Id = 2000, + IdInclude = 1213 + }, + new + { + Id = 2000, + IdInclude = 1215 + }, + new + { + Id = 2000, + IdInclude = 1217 + }, + new + { + Id = 2000, + IdInclude = 1219 + }, + new + { + Id = 2000, + IdInclude = 1220 + }, + new + { + Id = 2000, + IdInclude = 1221 + }, + new + { + Id = 2000, + IdInclude = 1500 + }, + new + { + Id = 2000, + IdInclude = 1501 + }, + new + { + Id = 2000, + IdInclude = 1502 + }, + new + { + Id = 2001, + IdInclude = 1500 + }, + new + { + Id = 2001, + IdInclude = 1501 + }, + new + { + Id = 2001, + IdInclude = 1502 + }, + new + { + Id = 2002, + IdInclude = 1500 + }, + new + { + Id = 2002, + IdInclude = 1501 + }, + new + { + Id = 2002, + IdInclude = 1502 + }, + new + { + Id = 2003, + IdInclude = 1500 + }, + new + { + Id = 2003, + IdInclude = 1501 + }, + new + { + Id = 2003, + IdInclude = 1502 + }, + new + { + Id = 2004, + IdInclude = 1500 + }, + new + { + Id = 2004, + IdInclude = 1501 + }, + new + { + Id = 2004, + IdInclude = 1502 + }, + new + { + Id = 2005, + IdInclude = 1500 + }, + new + { + Id = 2005, + IdInclude = 1501 + }, + new + { + Id = 2005, + IdInclude = 1502 + }, + new + { + Id = 2006, + IdInclude = 1500 + }, + new + { + Id = 2006, + IdInclude = 1501 + }, + new + { + Id = 2006, + IdInclude = 1502 + }, + new + { + Id = 2007, + IdInclude = 1500 + }, + new + { + Id = 2007, + IdInclude = 1501 + }, + new + { + Id = 2007, + IdInclude = 1502 + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationUserUserRole", b => + { + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user"); + + b.Property("IdUserRole") + .HasColumnType("integer") + .HasColumnName("id_user_role"); + + b.HasKey("IdUser", "IdUserRole"); + + b.HasIndex("IdUserRole"); + + b.ToTable("t_relation_user_user_role"); + + b.HasComment("Отношение пользователей и ролей"); + + b.HasData( + new + { + IdUser = 1, + IdUserRole = 1 + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.ReportProperty", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Begin") + .HasColumnType("timestamp with time zone") + .HasColumnName("begin"); + + b.Property("End") + .HasColumnType("timestamp with time zone") + .HasColumnName("end") + .HasComment("timestamp with time zone"); + + b.Property("Format") + .HasColumnType("integer") + .HasColumnName("format") + .HasComment("Формат отчета"); + + b.Property("IdFile") + .HasColumnType("integer") + .HasColumnName("id_file") + .HasComment("id файла-родителя"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("id скважины"); + + b.Property("Step") + .HasColumnType("integer") + .HasColumnName("step") + .HasComment("размер шага в секундах"); + + b.HasKey("Id"); + + b.HasIndex("IdFile"); + + b.HasIndex("IdWell"); + + b.ToTable("t_report_property"); + + b.HasComment("Отчеты с данными по буровым"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Schedule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id") + .HasComment("Идентификатор"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DrillEnd") + .HasColumnType("timestamp with time zone") + .HasColumnName("drill_end") + .HasComment("Конец вахты"); + + b.Property("DrillStart") + .HasColumnType("timestamp with time zone") + .HasColumnName("drill_start") + .HasComment("Начало вахты"); + + b.Property("IdDriller") + .HasColumnType("integer") + .HasColumnName("id_driller") + .HasComment("Идентификатор бурильщика"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("Идентификатор скважины"); + + b.Property("ShiftEnd") + .HasColumnType("time without time zone") + .HasColumnName("shift_end") + .HasComment("Конец смены"); + + b.Property("ShiftStart") + .HasColumnType("time without time zone") + .HasColumnName("shift_start") + .HasComment("Начало смены"); + + b.HasKey("Id"); + + b.HasIndex("IdDriller"); + + b.HasIndex("IdWell"); + + b.ToTable("t_schedule"); + + b.HasComment("График работы бурильщика"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.SetpointsRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Comment") + .HasColumnType("text") + .HasColumnName("comment") + .HasComment("комментарий для оператора"); + + b.Property("IdAuthor") + .HasColumnType("integer") + .HasColumnName("id_author") + .HasComment("Id пользователя, загрузившего файл"); + + b.Property("IdState") + .HasColumnType("integer") + .HasColumnName("id_state") + .HasComment("0: неизвестно, 1:ожидает отправки, 2: отправлено, 3: принято оператором, 4: отклонено оператором, 5: устарело"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("id скважины"); + + b.Property("ObsolescenceSec") + .HasColumnType("integer") + .HasColumnName("obsolescence") + .HasComment("сек. до устаревания"); + + b.Property("Setpoints") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("setpoint_set") + .HasComment("Набор уставок"); + + b.Property("UploadDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.HasKey("Id"); + + b.HasIndex("IdAuthor"); + + b.HasIndex("IdWell"); + + b.ToTable("t_setpoints_rquest"); + + b.HasComment("Запросы на изменение уставок панели оператора"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Subsystems.Subsystem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("description"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name"); + + b.HasKey("Id"); + + b.ToTable("t_subsystem"); + + b.HasComment("Описание подсистем"); + + b.HasData( + new + { + Id = 1, + Description = "Совместная работа режимов \"Бурение в роторе\" и \"Бурение в слайде\"", + Name = "АКБ" + }, + new + { + Id = 11, + Description = "Режим работы \"Бурение в роторе\"", + Name = "АПД ротор" + }, + new + { + Id = 12, + Description = "Режим работы \"Бурение в слайде\"", + Name = "АПД слайд" + }, + new + { + Id = 2, + Description = "Алгоритм поиска оптимальных параметров бурения САУБ", + Name = "MSE" + }, + new + { + Id = 65536, + Description = "Осцилляция", + Name = "Осцилляция" + }, + new + { + Id = 65537, + Description = "Демпфер", + Name = "Демпфер" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Subsystems.SubsystemOperationTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateEnd") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_end") + .HasComment("дата/время выключения подсистемы"); + + b.Property("DateStart") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_start") + .HasComment("дата/время включения подсистемы"); + + b.Property("DepthEnd") + .HasColumnType("real") + .HasColumnName("depth_end") + .HasComment("глубина забоя на момент выключения подсистемы"); + + b.Property("DepthStart") + .HasColumnType("real") + .HasColumnName("depth_start") + .HasComment("глубина забоя на момент включения подсистемы"); + + b.Property("IdSubsystem") + .HasColumnType("integer") + .HasColumnName("id_subsystem"); + + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry") + .HasComment("ИД телеметрии по которой выдается информация"); + + b.HasKey("Id"); + + b.HasIndex("IdSubsystem"); + + b.HasIndex("IdTelemetry"); + + b.ToTable("t_subsystem_operation_time"); + + b.HasComment("наработки подсистем"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Telemetry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Info") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("info") + .HasComment("Информация с панели о скважине"); + + b.Property("RemoteUid") + .IsRequired() + .HasColumnType("text") + .HasColumnName("remote_uid") + .HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв."); + + b.Property("TimeZone") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("timezone") + .HasComment("Смещение часового пояса от UTC"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "RemoteUid" }, "t_telemetry_remote_uid_index"); + + b.ToTable("t_telemetry"); + + b.HasComment("таблица привязки телеметрии от комплектов к конкретной скважине."); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryDataSaub", b => + { + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date") + .HasComment("'2021-10-19 18:23:54+05'"); + + b.Property("AxialLoad") + .HasColumnType("real") + .HasColumnName("axial_load") + .HasComment("Осевая нагрузка"); + + b.Property("AxialLoadLimitMax") + .HasColumnType("real") + .HasColumnName("axial_load_limit_max") + .HasComment("Осевая нагрузка. Аварийная макс."); + + b.Property("AxialLoadSp") + .HasColumnType("real") + .HasColumnName("axial_load_sp") + .HasComment("Осевая нагрузка. Задание"); + + b.Property("BitDepth") + .HasColumnType("real") + .HasColumnName("bit_depth") + .HasComment("Положение инструмента"); + + b.Property("BlockPosition") + .HasColumnType("real") + .HasColumnName("block_position") + .HasComment("Высота талевого блока"); + + b.Property("BlockPositionMax") + .HasColumnType("real") + .HasColumnName("block_position_max") + .HasComment("Талевый блок. Макс положение"); + + b.Property("BlockPositionMin") + .HasColumnType("real") + .HasColumnName("block_position_min") + .HasComment("Талевый блок. Мин положение"); + + b.Property("BlockSpeed") + .HasColumnType("real") + .HasColumnName("block_speed") + .HasComment("Скорость талевого блока"); + + b.Property("BlockSpeedSp") + .HasColumnType("real") + .HasColumnName("block_speed_sp") + .HasComment("Скорости талевого блока. Задание"); + + b.Property("BlockSpeedSpDevelop") + .HasColumnType("real") + .HasColumnName("block_speed_sp_develop") + .HasComment("Талевый блок. Задание скорости для проработки"); + + b.Property("BlockSpeedSpRotor") + .HasColumnType("real") + .HasColumnName("block_speed_sp_rotor") + .HasComment("Талевый блок. Задание скорости для роторного бурения"); + + b.Property("BlockSpeedSpSlide") + .HasColumnType("real") + .HasColumnName("block_speed_sp_slide") + .HasComment("Талевый блок. Задание скорости для режима слайда"); + + b.Property("Flow") + .HasColumnType("real") + .HasColumnName("flow") + .HasComment("Расход"); + + b.Property("FlowDeltaLimitMax") + .HasColumnType("real") + .HasColumnName("flow_delta_limit_max") + .HasComment("Расход. Аварийный макс."); + + b.Property("FlowIdle") + .HasColumnType("real") + .HasColumnName("flow_idle") + .HasComment("Расход. Холостой ход"); + + b.Property("HookWeight") + .HasColumnType("real") + .HasColumnName("hook_weight") + .HasComment("Вес на крюке"); + + b.Property("HookWeightIdle") + .HasColumnType("real") + .HasColumnName("hook_weight_idle") + .HasComment("Вес на крюке. Холостой ход"); + + b.Property("HookWeightLimitMax") + .HasColumnType("real") + .HasColumnName("hook_weight_limit_max") + .HasComment("Вес на крюке. Затяжка"); + + b.Property("HookWeightLimitMin") + .HasColumnType("real") + .HasColumnName("hook_weight_limit_min") + .HasComment("Вес на крюке. Посадка"); + + b.Property("IdFeedRegulator") + .HasColumnType("smallint") + .HasColumnName("id_feed_regulator") + .HasComment("Текущий критерий бурения"); + + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user") + .HasComment("Пользователь САУБ"); + + b.Property("Mode") + .HasColumnType("smallint") + .HasColumnName("mode") + .HasComment("Режим САУБ"); + + b.Property("Mse") + .HasColumnType("real") + .HasColumnName("mse") + .HasComment("MSE"); + + b.Property("MseState") + .HasColumnType("smallint") + .HasColumnName("mse_state") + .HasComment("Текущее состояние работы MSE"); + + b.Property("Pressure") + .HasColumnType("real") + .HasColumnName("pressure") + .HasComment("Давление"); + + b.Property("PressureDeltaLimitMax") + .HasColumnType("real") + .HasColumnName("pressure_delta_limit_max") + .HasComment("Давление дифф. Аварийное макс."); + + b.Property("PressureIdle") + .HasColumnType("real") + .HasColumnName("pressure_idle") + .HasComment("Давление. Холостой ход"); + + b.Property("PressureSp") + .HasColumnType("real") + .HasColumnName("pressure_sp") + .HasComment("Давление. Задание"); + + b.Property("PressureSpDevelop") + .HasColumnType("real") + .HasColumnName("pressure_sp_develop") + .HasComment("Давление. Задание для проработки"); + + b.Property("PressureSpRotor") + .HasColumnType("real") + .HasColumnName("pressure_sp_rotor") + .HasComment("Давление. Задание для роторного бурения"); + + b.Property("PressureSpSlide") + .HasColumnType("real") + .HasColumnName("pressure_sp_slide") + .HasComment("Давление. Задание для режима слайда"); + + b.Property("Pump0Flow") + .HasColumnType("real") + .HasColumnName("pump0_flow") + .HasComment("Расход. Буровой насос 1"); + + b.Property("Pump1Flow") + .HasColumnType("real") + .HasColumnName("pump1_flow") + .HasComment("Расход. Буровой насос 2"); + + b.Property("Pump2Flow") + .HasColumnType("real") + .HasColumnName("pump2_flow") + .HasComment("Расход. Буровой насос 3"); + + b.Property("RotorSpeed") + .HasColumnType("real") + .HasColumnName("rotor_speed") + .HasComment("Обороты ротора"); + + b.Property("RotorTorque") + .HasColumnType("real") + .HasColumnName("rotor_torque") + .HasComment("Момент на роторе"); + + b.Property("RotorTorqueIdle") + .HasColumnType("real") + .HasColumnName("rotor_torque_idle") + .HasComment("Момент на роторе. Холостой ход"); + + b.Property("RotorTorqueLimitMax") + .HasColumnType("real") + .HasColumnName("rotor_torque_limit_max") + .HasComment("Момент на роторе. Аварийный макс."); + + b.Property("RotorTorqueSp") + .HasColumnType("real") + .HasColumnName("rotor_torque_sp") + .HasComment("Момент на роторе. Задание"); + + b.Property("WellDepth") + .HasColumnType("real") + .HasColumnName("well_depth") + .HasComment("Глубина забоя"); + + b.HasKey("IdTelemetry", "DateTime"); + + b.ToTable("t_telemetry_data_saub"); + + b.HasComment("набор основных данных по SAUB"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryDataSaubStat", b => + { + b.Property("Count") + .HasColumnType("bigint") + .HasColumnName("count_items"); + + b.Property("DateMax") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_max"); + + b.Property("DateMin") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_min"); + + b.Property("DepthMax") + .HasColumnType("real") + .HasColumnName("depth_max"); + + b.Property("DepthMin") + .HasColumnType("real") + .HasColumnName("depth_min"); + + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.ToView("mw_telemetry_datas_saub_stat"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryDataSpin", b => + { + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date") + .HasComment("'2021-10-19 18:23:54+05'"); + + b.Property("Mode") + .HasColumnType("smallint") + .HasColumnName("mode") + .HasComment("Выбранный режим управления"); + + b.Property("PositionRight") + .HasColumnType("real") + .HasColumnName("position_right") + .HasComment("Крайний правый угол осцилляции"); + + b.Property("PositionZero") + .HasColumnType("real") + .HasColumnName("position_zero") + .HasComment("Нулевая позиция осцилляции"); + + b.Property("RevolsLeftLimit") + .HasColumnType("real") + .HasColumnName("revols_left_limit") + .HasComment("Ограничение числа оборотов влево"); + + b.Property("RevolsLeftTotal") + .HasColumnType("real") + .HasColumnName("revols_left_total") + .HasComment("Суммарное количество оборотов влево"); + + b.Property("RevolsRightLimit") + .HasColumnType("real") + .HasColumnName("revols_right_limit") + .HasComment("Ограничение числа оборотов вправо"); + + b.Property("RevolsRightTotal") + .HasColumnType("real") + .HasColumnName("revols_right_total") + .HasComment("Суммарное количество оборотов вправо"); + + b.Property("SpeedLeftSp") + .HasColumnType("real") + .HasColumnName("speed_left_sp") + .HasComment("Заданная скорость вращения влево"); + + b.Property("SpeedRightSp") + .HasColumnType("real") + .HasColumnName("speed_right_sp") + .HasComment("Заданная скорость вращения вправо"); + + b.Property("State") + .HasColumnType("smallint") + .HasColumnName("state") + .HasComment("Переменная этапа"); + + b.HasKey("IdTelemetry", "DateTime"); + + b.ToTable("t_telemetry_data_spin"); + + b.HasComment("набор основных данных по SpinMaster"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryEvent", b => + { + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property("IdEvent") + .HasColumnType("integer") + .HasColumnName("id_event"); + + b.Property("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category"); + + b.Property("MessageTemplate") + .IsRequired() + .HasColumnType("text") + .HasColumnName("message_template"); + + b.HasKey("IdTelemetry", "IdEvent"); + + b.ToTable("t_telemetry_event"); + + b.HasComment("Справочник событий. События формируют сообщения. Разделено по версиям посылок от телеметрии."); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Arg0") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("arg0") + .HasComment("Аргумент №0 для вставки в шаблон сообщения"); + + b.Property("Arg1") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("arg1"); + + b.Property("Arg2") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("arg2"); + + b.Property("Arg3") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("arg3"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("IdEvent") + .HasColumnType("integer") + .HasColumnName("id_event"); + + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property("IdTelemetryUser") + .HasColumnType("integer") + .HasColumnName("id_telemetry_user") + .HasComment("Пользователь панели отправляющей телеметрию. не пользователь облака."); + + b.Property("WellDepth") + .HasColumnType("double precision") + .HasColumnName("well_depth"); + + b.HasKey("Id"); + + b.HasIndex("IdTelemetry"); + + b.ToTable("t_telemetry_message"); + + b.HasComment("Сообщения на буровых"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryUser", b => + { + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user"); + + b.Property("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property("Name") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name"); + + b.Property("Patronymic") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("patronymic"); + + b.Property("Surname") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("surname"); + + b.HasKey("IdTelemetry", "IdUser"); + + b.ToTable("t_telemetry_user"); + + b.HasComment("Пользователи панели САУБ. Для сообщений."); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryWirelineRunOut", b => + { + b.Property("IdTelemetry") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id_telemetry") + .HasComment("Идентификатор телеметрии"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("IdTelemetry")); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_time") + .HasComment("Отметка времени"); + + b.Property("Hauling") + .HasColumnType("real") + .HasColumnName("hauling") + .HasComment("Наработка талевого каната с момента перетяжки каната, т*км"); + + b.Property("HaulingWarnSp") + .HasColumnType("real") + .HasColumnName("hauling_warn_sp") + .HasComment("Наработка талевого каната до сигнализации о необходимости перетяжки, т*км"); + + b.Property("Replace") + .HasColumnType("real") + .HasColumnName("replace") + .HasComment("Наработка талевого каната с момента замены каната, т*км"); + + b.Property("ReplaceWarnSp") + .HasColumnType("real") + .HasColumnName("replace_warn_sp") + .HasComment("Наработка талевого каната до сигнализации о необходимости замены, т*км"); + + b.HasKey("IdTelemetry"); + + b.ToTable("t_telemetry_wireline_run_out"); + + b.HasComment("Наработка талевого каната"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Trajectory.TrajectoryFact", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AzimuthGeo") + .HasColumnType("double precision") + .HasColumnName("azimuth_geo") + .HasComment("Азимут Географ."); + + b.Property("AzimuthMagnetic") + .HasColumnType("double precision") + .HasColumnName("azimuth_magnetic") + .HasComment("Азимут Магнитный"); + + b.Property("Comment") + .HasColumnType("text") + .HasColumnName("comment") + .HasComment("Комментарии"); + + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user") + .HasComment("ID пользователя который внес/изменил запись"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("ID скважины"); + + b.Property("UpdateDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("update_date") + .HasComment("Дата загрузки траектории"); + + b.Property("VerticalDepth") + .HasColumnType("double precision") + .HasColumnName("vertical_depth") + .HasComment("Глубина вертикальная"); + + b.Property("WellboreDepth") + .HasColumnType("double precision") + .HasColumnName("wellbore_depth") + .HasComment("Глубина по стволу"); + + b.Property("ZenithAngle") + .HasColumnType("double precision") + .HasColumnName("zenith_angle") + .HasComment("Угол зенитный"); + + b.HasKey("Id"); + + b.HasIndex("IdUser"); + + b.HasIndex("IdWell"); + + b.ToTable("t_trajectory_fact"); + + b.HasComment("Загрузка фактической траектории"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Trajectory.TrajectoryPlan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AzimuthGeo") + .HasColumnType("double precision") + .HasColumnName("azimuth_geo") + .HasComment("Азимут Географ."); + + b.Property("AzimuthMagnetic") + .HasColumnType("double precision") + .HasColumnName("azimuth_magnetic") + .HasComment("Азимут Магнитный"); + + b.Property("Comment") + .HasColumnType("text") + .HasColumnName("comment") + .HasComment("Комментарии"); + + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user") + .HasComment("ID пользователя который внес/изменил запись"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("ID скважины"); + + b.Property("Radius") + .HasColumnType("double precision") + .HasColumnName("radius") + .HasComment("Радиус цели"); + + b.Property("UpdateDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("update_date") + .HasComment("Дата загрузки траектории"); + + b.Property("VerticalDepth") + .HasColumnType("double precision") + .HasColumnName("vertical_depth") + .HasComment("Глубина вертикальная"); + + b.Property("WellboreDepth") + .HasColumnType("double precision") + .HasColumnName("wellbore_depth") + .HasComment("Глубина по стволу"); + + b.Property("ZenithAngle") + .HasColumnType("double precision") + .HasColumnName("zenith_angle") + .HasComment("Угол зенитный"); + + b.HasKey("Id"); + + b.HasIndex("IdUser"); + + b.HasIndex("IdWell"); + + b.ToTable("t_trajectory_plan"); + + b.HasComment("Загрузка плановой траектории"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Email") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("email") + .HasComment("должность"); + + b.Property("IdCompany") + .HasColumnType("integer") + .HasColumnName("id_company"); + + b.Property("IdState") + .HasColumnType("smallint") + .HasColumnName("state") + .HasComment("состояние:\n0 - не активен, \n1 - активен, \n2 - заблокирован"); + + b.Property("Login") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("login"); + + b.Property("Name") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name") + .HasComment("имя"); + + b.Property("PasswordHash") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("password_hash") + .HasComment("соленый хэш пароля.\nпервые 5 символов - соль"); + + b.Property("Patronymic") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("patronymic") + .HasComment("отчество"); + + b.Property("Phone") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("phone") + .HasComment("номер телефона"); + + b.Property("Position") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("position") + .HasComment("email"); + + b.Property("Surname") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("surname") + .HasComment("фамилия"); + + b.HasKey("Id"); + + b.HasIndex("IdCompany"); + + b.HasIndex("Login") + .IsUnique(); + + b.ToTable("t_user"); + + b.HasComment("Пользователи облака"); + + b.HasData( + new + { + Id = 1, + Email = "", + IdCompany = 1, + IdState = (short)1, + Login = "dev", + Name = "Разработчик", + PasswordHash = "Vlcj|4fa529103dde7ff72cfe76185f344d4aa87931f8e1b2044e8a7739947c3d18923464eaad93843e4f809c5e126d013072" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.UserRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Caption") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption") + .HasComment("Название"); + + b.Property("IdType") + .HasColumnType("integer") + .HasColumnName("id_type") + .HasComment("0-роль из стандартной матрицы, \n1-специальная роль для какого-либо пользователя"); + + b.HasKey("Id"); + + b.ToTable("t_user_role"); + + b.HasComment("Роли пользователей в системе"); + + b.HasData( + new + { + Id = 1, + Caption = "root", + IdType = 1 + }, + new + { + Id = 1100, + Caption = "admin_cluster.view", + IdType = 1 + }, + new + { + Id = 1101, + Caption = "admin_cluster.edit", + IdType = 1 + }, + new + { + Id = 1102, + Caption = "admin_company.view", + IdType = 1 + }, + new + { + Id = 1103, + Caption = "admin_company.edit", + IdType = 1 + }, + new + { + Id = 1104, + Caption = "admin_company_type.view", + IdType = 1 + }, + new + { + Id = 1105, + Caption = "admin_company_type.edit", + IdType = 1 + }, + new + { + Id = 1106, + Caption = "admin_deposit.view", + IdType = 1 + }, + new + { + Id = 1107, + Caption = "admin_deposit.edit", + IdType = 1 + }, + new + { + Id = 1108, + Caption = "admin_permission.view", + IdType = 1 + }, + new + { + Id = 1109, + Caption = "admin_permission.edit", + IdType = 1 + }, + new + { + Id = 1110, + Caption = "admin_role.view", + IdType = 1 + }, + new + { + Id = 1111, + Caption = "admin_role.edit", + IdType = 1 + }, + new + { + Id = 1112, + Caption = "admin_telemetry.view", + IdType = 1 + }, + new + { + Id = 1113, + Caption = "admin_user.view", + IdType = 1 + }, + new + { + Id = 1114, + Caption = "admin_user.edit", + IdType = 1 + }, + new + { + Id = 1115, + Caption = "admin_visit_log.view", + IdType = 1 + }, + new + { + Id = 1116, + Caption = "admin_well.view", + IdType = 1 + }, + new + { + Id = 1117, + Caption = "admin_well.edit", + IdType = 1 + }, + new + { + Id = 1200, + Caption = "archive.view", + IdType = 1 + }, + new + { + Id = 1201, + Caption = "cluster.view", + IdType = 1 + }, + new + { + Id = 1202, + Caption = "composite.view", + IdType = 1 + }, + new + { + Id = 1203, + Caption = "composite.edit", + IdType = 1 + }, + new + { + Id = 1204, + Caption = "deposit.view", + IdType = 1 + }, + new + { + Id = 1205, + Caption = "document.view", + IdType = 1 + }, + new + { + Id = 1206, + Caption = "drillProcessFlow.view", + IdType = 1 + }, + new + { + Id = 1207, + Caption = "drillProcessFlow.edit", + IdType = 1 + }, + new + { + Id = 1208, + Caption = "measure.view", + IdType = 1 + }, + new + { + Id = 1209, + Caption = "measure.edit", + IdType = 1 + }, + new + { + Id = 1210, + Caption = "message.view", + IdType = 1 + }, + new + { + Id = 1211, + Caption = "operations.view", + IdType = 1 + }, + new + { + Id = 1212, + Caption = "operations.edit", + IdType = 1 + }, + new + { + Id = 1213, + Caption = "params.view", + IdType = 1 + }, + new + { + Id = 1214, + Caption = "params.edit", + IdType = 1 + }, + new + { + Id = 1215, + Caption = "report.view", + IdType = 1 + }, + new + { + Id = 1216, + Caption = "report.edit", + IdType = 1 + }, + new + { + Id = 1217, + Caption = "setpoints.view", + IdType = 1 + }, + new + { + Id = 1218, + Caption = "setpoints.edit", + IdType = 1 + }, + new + { + Id = 1219, + Caption = "telemetry.view", + IdType = 1 + }, + new + { + Id = 1220, + Caption = "telemetryAnalysis.view", + IdType = 1 + }, + new + { + Id = 1221, + Caption = "well.view", + IdType = 1 + }, + new + { + Id = 1500, + Caption = "Просмотр всего", + IdType = 1 + }, + new + { + Id = 1501, + Caption = "file.edit", + IdType = 1 + }, + new + { + Id = 1502, + Caption = "drillingProgram.edit", + IdType = 1 + }, + new + { + Id = 2000, + Caption = "Заказчик", + IdType = 0 + }, + new + { + Id = 2001, + Caption = "Супервайзер", + IdType = 0 + }, + new + { + Id = 2002, + Caption = "Буровой подрядчик", + IdType = 0 + }, + new + { + Id = 2003, + Caption = "Растворщик", + IdType = 0 + }, + new + { + Id = 2004, + Caption = "Телеметрист", + IdType = 0 + }, + new + { + Id = 2005, + Caption = "Долотный сервис", + IdType = 0 + }, + new + { + Id = 2006, + Caption = "ГТИ", + IdType = 0 + }, + new + { + Id = 2007, + Caption = "Цементирование", + IdType = 0 + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.UserSetting", b => + { + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user"); + + b.Property("Key") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("key") + .HasComment("Ключ настроек пользователя"); + + b.Property("Value") + .HasColumnType("jsonb") + .HasColumnName("setting_value") + .HasComment("Значение настроек пользователя"); + + b.HasKey("IdUser", "Key"); + + b.ToTable("t_user_settings"); + + b.HasComment("настройки интерфейса пользователя"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Well", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Caption") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption"); + + b.Property("IdCluster") + .HasColumnType("integer") + .HasColumnName("id_cluster"); + + b.Property("IdState") + .HasColumnType("integer") + .HasColumnName("state") + .HasComment("0 - неизвестно, 1 - в работе, 2 - завершена"); + + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property("IdWellType") + .HasColumnType("integer") + .HasColumnName("id_well_type"); + + b.Property("Latitude") + .HasColumnType("double precision") + .HasColumnName("latitude"); + + b.Property("Longitude") + .HasColumnType("double precision") + .HasColumnName("longitude"); + + b.Property("Timezone") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("timezone") + .HasComment("Смещение часового пояса от UTC"); + + b.HasKey("Id"); + + b.HasIndex("IdCluster"); + + b.HasIndex("IdTelemetry") + .IsUnique(); + + b.HasIndex("IdWellType"); + + b.ToTable("t_well"); + + b.HasComment("скважины"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellComposite", b => + { + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("Id скважины получателя"); + + b.Property("IdWellSrc") + .HasColumnType("integer") + .HasColumnName("id_well_src") + .HasComment("Id скважины композита"); + + b.Property("IdWellSectionType") + .HasColumnType("integer") + .HasColumnName("id_well_section_type") + .HasComment("Id тип секции композита"); + + b.HasKey("IdWell", "IdWellSrc", "IdWellSectionType"); + + b.HasIndex("IdWellSectionType"); + + b.HasIndex("IdWellSrc"); + + b.ToTable("t_well_composite"); + + b.HasComment("Композитная скважина"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellFinalDocument", b => + { + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well"); + + b.Property("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user"); + + b.Property("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category"); + + b.HasKey("IdWell", "IdUser", "IdCategory") + .HasName("t_well_final_documents_pk"); + + b.HasIndex("IdCategory"); + + b.HasIndex("IdUser"); + + b.ToTable("t_well_final_documents"); + + b.HasComment("Дело скважины"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellOperation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CategoryInfo") + .HasColumnType("text") + .HasColumnName("category_info") + .HasComment("Доп. информация к выбраной категории"); + + b.Property("Comment") + .HasColumnType("text") + .HasColumnName("comment") + .HasComment("Комментарий"); + + b.Property("DateStart") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_start") + .HasComment("Дата начала операции"); + + b.Property("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("depth_end") + .HasComment("Глубина после завершения операции, м"); + + b.Property("DepthStart") + .HasColumnType("double precision") + .HasColumnName("depth_start") + .HasComment("Глубина на начало операции, м"); + + b.Property("DurationHours") + .HasColumnType("double precision") + .HasColumnName("duration_hours") + .HasComment("Продолжительность, часы"); + + b.Property("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category") + .HasComment("Id категории операции"); + + b.Property("IdPlan") + .HasColumnType("integer") + .HasColumnName("id_plan") + .HasComment("Id плановой операции"); + + b.Property("IdType") + .HasColumnType("integer") + .HasColumnName("id_type") + .HasComment("0 = План или 1 = Факт"); + + b.Property("IdUser") + .HasColumnType("integer"); + + b.Property("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("Id скважины"); + + b.Property("IdWellSectionType") + .HasColumnType("integer") + .HasColumnName("id_well_section_type") + .HasComment("Id тип секции скважины"); + + b.Property("LastUpdateDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("DateStart"); + + b.HasIndex("DepthEnd"); + + b.HasIndex("IdCategory"); + + b.HasIndex("IdPlan"); + + b.HasIndex("IdWell"); + + b.HasIndex("IdWellSectionType"); + + b.ToTable("t_well_operation"); + + b.HasComment("Данные по операциям на скважине"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellOperationCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("IdParent") + .HasColumnType("integer") + .HasColumnName("id_parent") + .HasComment("id родительской категории"); + + b.Property("KeyValueName") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("key_value_name") + .HasComment("Название ключевого показателя операции"); + + b.Property("KeyValueUnits") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("key_value_units") + .HasComment("Единицы измерения ключевого показателя операции"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name") + .HasComment("Название категории операции"); + + b.HasKey("Id"); + + b.HasIndex("IdParent"); + + b.ToTable("t_well_operation_category"); + + b.HasComment("Справочник операций на скважине"); + + b.HasData( + new + { + Id = 3000, + KeyValueName = "dT", + KeyValueUnits = "м/ч", + Name = "БУРЕНИЕ" + }, + new + { + Id = 3001, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "СПО" + }, + new + { + Id = 3002, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "КРЕПЛЕНИЕ" + }, + new + { + Id = 3003, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "ГФР" + }, + new + { + Id = 3004, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Вспомогательные операции" + }, + new + { + Id = 3005, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Непроизводительное время (НПВ)" + }, + new + { + Id = 4000, + IdParent = 3000, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "КНБК" + }, + new + { + Id = 4001, + IdParent = 3000, + KeyValueName = "dT", + KeyValueUnits = "м/ч", + Name = "Механическое. бурение" + }, + new + { + Id = 4002, + IdParent = 3000, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Статический замер" + }, + new + { + Id = 4003, + IdParent = 3000, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Нормализация диаметра скважины" + }, + new + { + Id = 4004, + IdParent = 3000, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Наращивание" + }, + new + { + Id = 4005, + IdParent = 3001, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "СПО" + }, + new + { + Id = 4006, + IdParent = 3002, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Спуск обсадной колонны" + }, + new + { + Id = 4018, + IdParent = 3002, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Крепление" + }, + new + { + Id = 4007, + IdParent = 3002, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Цементирование" + }, + new + { + Id = 4008, + IdParent = 3002, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Вспомогательные работы при креплении" + }, + new + { + Id = 4009, + IdParent = 3003, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Сборка/разборка приборов ГИС" + }, + new + { + Id = 4010, + IdParent = 3003, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "СПО" + }, + new + { + Id = 4011, + IdParent = 3003, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "ГИС" + }, + new + { + Id = 4012, + IdParent = 3004, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Промывка, ОБР" + }, + new + { + Id = 4013, + IdParent = 3004, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Вспомогательные работы" + }, + new + { + Id = 4014, + IdParent = 3005, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Ремонт оборудования" + }, + new + { + Id = 4015, + IdParent = 3005, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Аварийные работы" + }, + new + { + Id = 4016, + IdParent = 3005, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Осложнение" + }, + new + { + Id = 4017, + IdParent = 3005, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Незаложенные в ГГД операции" + }, + new + { + Id = 5000, + IdParent = 4000, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Разборка КНБК" + }, + new + { + Id = 5001, + IdParent = 4000, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Сборка КНБК" + }, + new + { + Id = 5002, + IdParent = 4001, + KeyValueName = "МСП", + KeyValueUnits = "м/ч", + Name = "Бурение слайдом" + }, + new + { + Id = 5003, + IdParent = 4001, + KeyValueName = "МСП", + KeyValueUnits = "м/ч", + Name = "Бурение ротором" + }, + new + { + Id = 5004, + IdParent = 4002, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Замер ЗТС (запись MWD)" + }, + new + { + Id = 5005, + IdParent = 4003, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Промывка перед наращиванием" + }, + new + { + Id = 5006, + IdParent = 4003, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Проработка во время бурения" + }, + new + { + Id = 5007, + IdParent = 4003, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Проработка перед наращиванием" + }, + new + { + Id = 5008, + IdParent = 4003, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Шаблонировка во время бурения" + }, + new + { + Id = 5009, + IdParent = 4003, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Шаблонировка перед наращиванием" + }, + new + { + Id = 5010, + IdParent = 4004, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Наращивание" + }, + new + { + Id = 5011, + IdParent = 4004, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Удержание в клиньях" + }, + new + { + Id = 5012, + IdParent = 4005, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Подъем инструмента" + }, + new + { + Id = 5013, + IdParent = 4005, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Подъем КНБК" + }, + new + { + Id = 5014, + IdParent = 4005, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Спуск инструмента" + }, + new + { + Id = 5015, + IdParent = 4005, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Спуск КНБК" + }, + new + { + Id = 5016, + IdParent = 4006, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Промывка при спуске ОК" + }, + new + { + Id = 5017, + IdParent = 4006, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Спуск ОК" + }, + new + { + Id = 5018, + IdParent = 4007, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "ОЗЦ" + }, + new + { + Id = 5019, + IdParent = 4007, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Цементирование" + }, + new + { + Id = 5020, + IdParent = 4008, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Опрессовка БИ" + }, + new + { + Id = 5021, + IdParent = 4008, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Опрессовка ОК" + }, + new + { + Id = 5022, + IdParent = 4008, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "ПЗР при спуске ОК" + }, + new + { + Id = 5023, + IdParent = 4008, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "ПЗР при цементировании" + }, + new + { + Id = 5024, + IdParent = 4009, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Разборка комплекса приборов ГИС" + }, + new + { + Id = 5025, + IdParent = 4009, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Сборка комплекса приборов ГИС" + }, + new + { + Id = 5026, + IdParent = 4010, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Подъем приборов ГИС (на трубах)" + }, + new + { + Id = 5027, + IdParent = 4010, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Спуск приборов ГИС (на трубах)" + }, + new + { + Id = 5028, + IdParent = 4011, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Комплекс ГИС на жестком кабеле" + }, + new + { + Id = 5029, + IdParent = 4011, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Комплекс ГИС на кабеле" + }, + new + { + Id = 5030, + IdParent = 4011, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Комплекс ГИС на трубах" + }, + new + { + Id = 5031, + IdParent = 4012, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Закачка/прокачка пачки" + }, + new + { + Id = 5032, + IdParent = 4012, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Обработка БР" + }, + new + { + Id = 5033, + IdParent = 4012, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Ориентирование ТС при бурении" + }, + new + { + Id = 5034, + IdParent = 4012, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Перезапись гаммы-каротажа" + }, + new + { + Id = 5035, + IdParent = 4012, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Приготовление БР" + }, + new + { + Id = 5036, + IdParent = 4012, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Промывка" + }, + new + { + Id = 5037, + IdParent = 4012, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Разбуривание тех.оснастки" + }, + new + { + Id = 5038, + IdParent = 4012, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Спуск инструмента с проработкой" + }, + new + { + Id = 5039, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "ВМР" + }, + new + { + Id = 5040, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Демонтаж ПВО" + }, + new + { + Id = 5041, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Долив затруба при подъёме" + }, + new + { + Id = 5042, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Монтаж ПВО" + }, + new + { + Id = 5043, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Наработка жёлоба" + }, + new + { + Id = 5044, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Обвязка устья с циркуляционной системой" + }, + new + { + Id = 5045, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Оборудование устья" + }, + new + { + Id = 5046, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Опрессовка ПВО" + }, + new + { + Id = 5047, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Перемонтаж ПВО " + }, + new + { + Id = 5048, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Перетяжка талевого каната" + }, + new + { + Id = 5049, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "ПЗР при сборке КНБК" + }, + new + { + Id = 5050, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Полная замена талевого каната" + }, + new + { + Id = 5051, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "ПР перед забуркой направления" + }, + new + { + Id = 5052, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Продувка манифольда" + }, + new + { + Id = 5053, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Срезка" + }, + new + { + Id = 5054, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Тайм-дриллинг" + }, + new + { + Id = 5055, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Тех.отстой" + }, + new + { + Id = 5056, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Учебная тревога \"Выброс\"" + }, + new + { + Id = 5057, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Чистка ЦСГО/емкостного блока" + }, + new + { + Id = 5058, + IdParent = 4014, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Ремонт бурового оборудования" + }, + new + { + Id = 5059, + IdParent = 4015, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Ловильные работы" + }, + new + { + Id = 5060, + IdParent = 4015, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Ожидание" + }, + new + { + Id = 5061, + IdParent = 4015, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Определение места прихвата и ЛМ" + }, + new + { + Id = 5062, + IdParent = 4015, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Работа яссом" + }, + new + { + Id = 5063, + IdParent = 4015, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Расхаживание" + }, + new + { + Id = 5064, + IdParent = 4015, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "СПО - колокол" + }, + new + { + Id = 5065, + IdParent = 4015, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "СПО - метчик" + }, + new + { + Id = 5066, + IdParent = 4015, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "СПО - овершот" + }, + new + { + Id = 5067, + IdParent = 4015, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "СПО - труболовка" + }, + new + { + Id = 5068, + IdParent = 4015, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Торпедирование (встряхивание)" + }, + new + { + Id = 5069, + IdParent = 4015, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Торпедирование (отстрел)" + }, + new + { + Id = 5070, + IdParent = 4015, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Установка ванн" + }, + new + { + Id = 5071, + IdParent = 4015, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Фрезеровка" + }, + new + { + Id = 5072, + IdParent = 4016, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Контролируемое ГНВП" + }, + new + { + Id = 5073, + IdParent = 4016, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Поглощение" + }, + new + { + Id = 5074, + IdParent = 4016, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Сальникообразование" + }, + new + { + Id = 5075, + IdParent = 4016, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Утяжеление БР" + }, + new + { + Id = 5076, + IdParent = 4017, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "НПВ / прочее" + }, + new + { + Id = 5077, + IdParent = 4017, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Обработка раствора (несоответствие параметров)" + }, + new + { + Id = 5078, + IdParent = 4017, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "подъем ОК" + }, + new + { + Id = 5079, + IdParent = 4017, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Ревизия КНБК/инструмента/ЗТС" + }, + new + { + Id = 5082, + IdParent = 4000, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Сборка устройства ориентирования КО" + }, + new + { + Id = 5083, + IdParent = 4003, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Проработка принудительная" + }, + new + { + Id = 5084, + IdParent = 4005, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Шаблонировка подъем БИ, продувка" + }, + new + { + Id = 5085, + IdParent = 4005, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Спуск бурильного инструмента со сборкой с мостков" + }, + new + { + Id = 5086, + IdParent = 4005, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Подъем БИ с выбросом на мостки" + }, + new + { + Id = 5087, + IdParent = 4005, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Спуск БИ со сборкой с мостков" + }, + new + { + Id = 5088, + IdParent = 4005, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Сборка и спуск ТБТ" + }, + new + { + Id = 5089, + IdParent = 4005, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Спуск КО на транспотрной колонне" + }, + new + { + Id = 5090, + IdParent = 4008, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Отворот допускной трубы" + }, + new + { + Id = 5091, + IdParent = 4008, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Активация подвески, опрессовка" + }, + new + { + Id = 5092, + IdParent = 4008, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Монтаж, опрессовка ФА" + }, + new + { + Id = 5093, + IdParent = 4008, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Сборка хвостовика 114мм (согласно схеме)" + }, + new + { + Id = 5094, + IdParent = 4008, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "ПЗР к спуску УЭЦН" + }, + new + { + Id = 5095, + IdParent = 4008, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Активация подвески (потайной колонны, хвостовика)" + }, + new + { + Id = 5096, + IdParent = 4008, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Шаблонирование перед спуском" + }, + new + { + Id = 5097, + IdParent = 4012, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Промывка - перевод скважины на новый раствор" + }, + new + { + Id = 5098, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Сборка БИ с мостков на подсвечник" + }, + new + { + Id = 5099, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Подготовка ствола скважины. Перезапись ГК в интервале установки КО." + }, + new + { + Id = 5100, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Смена рабочего переводника ВСП" + }, + new + { + Id = 5101, + IdParent = 4014, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Ремонт" + }, + new + { + Id = 5102, + IdParent = 4018, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Спуск пакера" + }, + new + { + Id = 5103, + IdParent = 4011, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Запись гамма-каратожа" + }, + new + { + Id = 5104, + IdParent = 4013, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Шаблонирование спуск БИ" + }, + new + { + Id = 5105, + IdParent = 4018, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Сборка клин-отклонителя" + }, + new + { + Id = 5106, + IdParent = 4018, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Ориентирование и посадка клина-отклонителя" + }, + new + { + Id = 5107, + IdParent = 4018, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Протяжка подъемного патрубка подвески" + }, + new + { + Id = 5108, + IdParent = 4018, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Подъем клина-отклонителя" + }, + new + { + Id = 5109, + IdParent = 4018, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Стыковка стингера с хвостовиком основного ствола" + }, + new + { + Id = 5110, + IdParent = 4018, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Ориентирование и установка стыковочного узла хвостовика" + }, + new + { + Id = 5111, + IdParent = 4001, + KeyValueName = "МСП", + KeyValueUnits = "м/ч", + Name = "Бурение с отбором керна" + }, + new + { + Id = 5112, + IdParent = 4018, + KeyValueName = "dT", + KeyValueUnits = "мин", + Name = "Работа пакером в обсадной колонне" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellSectionType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Caption") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption") + .HasComment("Название"); + + b.Property("Order") + .HasColumnType("real") + .HasColumnName("order") + .HasComment("Порядок"); + + b.HasKey("Id"); + + b.ToTable("t_well_section_type"); + + b.HasComment("конструкция секции скважины"); + + b.HasData( + new + { + Id = 1, + Caption = "Пилотный ствол", + Order = 4f + }, + new + { + Id = 2, + Caption = "Направление", + Order = 0f + }, + new + { + Id = 3, + Caption = "Кондуктор", + Order = 1f + }, + new + { + Id = 4, + Caption = "Эксплуатационная колонна", + Order = 3f + }, + new + { + Id = 5, + Caption = "Транспортный ствол", + Order = 5f + }, + new + { + Id = 6, + Caption = "Хвостовик", + Order = 6f + }, + new + { + Id = 7, + Caption = "Пилотный ствол 2", + Order = 4.1f + }, + new + { + Id = 8, + Caption = "Направление 2", + Order = 0.1f + }, + new + { + Id = 9, + Caption = "Кондуктор 2", + Order = 1.1f + }, + new + { + Id = 10, + Caption = "Эксплуатационная колонна 2", + Order = 3.1f + }, + new + { + Id = 11, + Caption = "Транспортный ствол 2", + Order = 5.1f + }, + new + { + Id = 12, + Caption = "Хвостовик 2", + Order = 6.1f + }, + new + { + Id = 13, + Caption = "Пилотный ствол 3", + Order = 4.2f + }, + new + { + Id = 14, + Caption = "Направление 3", + Order = 0.2f + }, + new + { + Id = 15, + Caption = "Кондуктор 3", + Order = 1.2f + }, + new + { + Id = 16, + Caption = "Эксплуатационная колонна 3", + Order = 3.2f + }, + new + { + Id = 17, + Caption = "Транспортный ствол 3", + Order = 5.2f + }, + new + { + Id = 18, + Caption = "Хвостовик 3", + Order = 6.2f + }, + new + { + Id = 19, + Caption = "Пилотный ствол 4", + Order = 4.3f + }, + new + { + Id = 20, + Caption = "Направление 4", + Order = 0.3f + }, + new + { + Id = 21, + Caption = "Кондуктор 4", + Order = 1.3f + }, + new + { + Id = 22, + Caption = "Эксплуатационная колонна 4", + Order = 3.3f + }, + new + { + Id = 23, + Caption = "Транспортный ствол 4", + Order = 5.3f + }, + new + { + Id = 24, + Caption = "Хвостовик 4", + Order = 6.3f + }, + new + { + Id = 25, + Caption = "Пилотный ствол 5", + Order = 4.4f + }, + new + { + Id = 26, + Caption = "Направление 5", + Order = 0.4f + }, + new + { + Id = 27, + Caption = "Кондуктор 5", + Order = 1.4f + }, + new + { + Id = 28, + Caption = "Эксплуатационная колонна 5", + Order = 3.4f + }, + new + { + Id = 29, + Caption = "Транспортный ствол 5", + Order = 5.4f + }, + new + { + Id = 30, + Caption = "Хвостовик 5", + Order = 6.4f + }, + new + { + Id = 31, + Caption = "Техническая колонна", + Order = 2f + }, + new + { + Id = 32, + Caption = "Техническая колонна 2", + Order = 2.1f + }, + new + { + Id = 33, + Caption = "Техническая колонна 3", + Order = 2.2f + }, + new + { + Id = 34, + Caption = "Хвостовик 6", + Order = 6.5f + }, + new + { + Id = 35, + Caption = "Хвостовик 7", + Order = 6.6f + }, + new + { + Id = 36, + Caption = "Хвостовик 8", + Order = 6.7f + }, + new + { + Id = 37, + Caption = "Хвостовик 9", + Order = 6.8f + }, + new + { + Id = 38, + Caption = "Хвостовик 10", + Order = 6.9f + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Caption") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption") + .HasComment("Название"); + + b.HasKey("Id"); + + b.ToTable("t_well_type"); + + b.HasComment("конструкция скважины"); + + b.HasData( + new + { + Id = 1, + Caption = "Наклонно-направленная" + }, + new + { + Id = 2, + Caption = "Горизонтальная" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.RecordBase", b => + { + b.Property("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("Actcod") + .HasColumnType("smallint") + .HasColumnName("ACTCOD"); + + b.Property("Date") + .HasColumnType("integer") + .HasColumnName("DATE"); + + b.Property("Recid") + .HasColumnType("smallint") + .HasColumnName("RECID"); + + b.Property("Seqid") + .HasColumnType("integer") + .HasColumnName("SEQID"); + + b.Property("Stknum") + .HasColumnType("smallint") + .HasColumnName("STKNUM"); + + b.Property("Time") + .HasColumnType("integer") + .HasColumnName("TIME"); + + b.Property("Wellid") + .HasColumnType("text") + .HasColumnName("WELLID"); + + b.HasKey("IdTelemetry", "DateTime"); + + b.ToTable("t_telemetry_wits_base"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record1", b => + { + b.HasBaseType("AsbCloudDb.Model.WITS.RecordBase"); + + b.Property("Blkpos") + .HasColumnType("real") + .HasColumnName("BLKPOS"); + + b.Property("Chkp") + .HasColumnType("real") + .HasColumnName("CHKP"); + + b.Property("Deptbitm") + .HasColumnType("real") + .HasColumnName("DEPTBITM"); + + b.Property("Deptbitv") + .HasColumnType("real") + .HasColumnName("DEPTBITV"); + + b.Property("Deptmeas") + .HasColumnType("real") + .HasColumnName("DEPTMEAS"); + + b.Property("Deptretm") + .HasColumnType("real") + .HasColumnName("DEPTRETM"); + + b.Property("Deptvert") + .HasColumnType("real") + .HasColumnName("DEPTVERT"); + + b.Property("Gasa") + .HasColumnType("real") + .HasColumnName("GASA"); + + b.Property("Hkla") + .HasColumnType("real") + .HasColumnName("HKLA"); + + b.Property("Hklx") + .HasColumnType("real") + .HasColumnName("HKLX"); + + b.Property("Lagstks") + .HasColumnType("smallint") + .HasColumnName("LAGSTKS"); + + b.Property("Mcia") + .HasColumnType("real") + .HasColumnName("MCIA"); + + b.Property("Mcoa") + .HasColumnType("real") + .HasColumnName("MCOA"); + + b.Property("Mdia") + .HasColumnType("real") + .HasColumnName("MDIA"); + + b.Property("Mdoa") + .HasColumnType("real") + .HasColumnName("MDOA"); + + b.Property("Mfia") + .HasColumnType("real") + .HasColumnName("MFIA"); + + b.Property("Mfoa") + .HasColumnType("real") + .HasColumnName("MFOA"); + + b.Property("Mfop") + .HasColumnType("smallint") + .HasColumnName("MFOP"); + + b.Property("Mtia") + .HasColumnType("real") + .HasColumnName("MTIA"); + + b.Property("Mtoa") + .HasColumnType("real") + .HasColumnName("MTOA"); + + b.Property("Ropa") + .HasColumnType("real") + .HasColumnName("ROPA"); + + b.Property("Rpma") + .HasColumnType("smallint") + .HasColumnName("RPMA"); + + b.Property("Spare1") + .HasColumnType("real") + .HasColumnName("SPARE1"); + + b.Property("Spare2") + .HasColumnType("real") + .HasColumnName("SPARE2"); + + b.Property("Spare3") + .HasColumnType("real") + .HasColumnName("SPARE3"); + + b.Property("Spare4") + .HasColumnType("real") + .HasColumnName("SPARE4"); + + b.Property("Spare5") + .HasColumnType("real") + .HasColumnName("SPARE5"); + + b.Property("Spm1") + .HasColumnType("smallint") + .HasColumnName("SPM1"); + + b.Property("Spm2") + .HasColumnType("smallint") + .HasColumnName("SPM2"); + + b.Property("Spm3") + .HasColumnType("smallint") + .HasColumnName("SPM3"); + + b.Property("Sppa") + .HasColumnType("real") + .HasColumnName("SPPA"); + + b.Property("Stkc") + .HasColumnType("integer") + .HasColumnName("STKC"); + + b.Property("TelemetryId") + .HasColumnType("integer"); + + b.Property("Torqa") + .HasColumnType("real") + .HasColumnName("TORQA"); + + b.Property("Torqx") + .HasColumnType("real") + .HasColumnName("TORQX"); + + b.Property("Tvolact") + .HasColumnType("real") + .HasColumnName("TVOLACT"); + + b.Property("Tvolcact") + .HasColumnType("real") + .HasColumnName("TVOLCACT"); + + b.Property("Woba") + .HasColumnType("real") + .HasColumnName("WOBA"); + + b.Property("Wobx") + .HasColumnType("real") + .HasColumnName("WOBX"); + + b.HasIndex("TelemetryId"); + + b.ToTable("t_telemetry_wits_1"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record50", b => + { + b.HasBaseType("AsbCloudDb.Model.WITS.RecordBase"); + + b.Property("Deptbitm") + .HasColumnType("real") + .HasColumnName("DEPTBITM"); + + b.Property("DeptmeasGdpMc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_GDP_mc"); + + b.Property("DeptmeasMcrstat") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_MCRSTAT"); + + b.Property("DeptmeasRa33Mc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_RA33_mc"); + + b.Property("DeptmeasRa33f2Mc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_RA33F2_mc"); + + b.Property("DeptmeasRa33f4Mc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_RA33F4_mc"); + + b.Property("DeptmeasRp33Mc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_RP33_mc"); + + b.Property("DeptmeasRp33f2Mc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_RP33F2_mc"); + + b.Property("DeptmeasRp33f4Mc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_RP33F4_mc"); + + b.Property("DeptmeasSlvlMc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_SLVL_mc"); + + b.Property("GdpMc") + .HasColumnType("real") + .HasColumnName("GDP_mc"); + + b.Property("Mcrstat") + .HasColumnType("real") + .HasColumnName("MCRSTAT"); + + b.Property("Ra33Mc") + .HasColumnType("real") + .HasColumnName("RA33_mc"); + + b.Property("Ra33f2Mc") + .HasColumnType("real") + .HasColumnName("RA33F2_mc"); + + b.Property("Ra33f4Mc") + .HasColumnType("real") + .HasColumnName("RA33F4_mc"); + + b.Property("Rp33Mc") + .HasColumnType("real") + .HasColumnName("RP33_mc"); + + b.Property("Rp33f2Mc") + .HasColumnType("real") + .HasColumnName("RP33F2_mc"); + + b.Property("Rp33f4Mc") + .HasColumnType("real") + .HasColumnName("RP33F4_mc"); + + b.Property("SlvlMc") + .HasColumnType("real") + .HasColumnName("SLVL_mc"); + + b.Property("TelemetryId") + .HasColumnType("integer"); + + b.HasIndex("TelemetryId"); + + b.ToTable("t_telemetry_wits_50"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record60", b => + { + b.HasBaseType("AsbCloudDb.Model.WITS.RecordBase"); + + b.Property("Btot") + .HasColumnType("real") + .HasColumnName("Btot"); + + b.Property("Bx") + .HasColumnType("real") + .HasColumnName("Bx"); + + b.Property("By") + .HasColumnType("real") + .HasColumnName("By"); + + b.Property("Bz") + .HasColumnType("real") + .HasColumnName("Bz"); + + b.Property("Deptbitm") + .HasColumnType("real") + .HasColumnName("DEPTBITM"); + + b.Property("Deptmeas") + .HasColumnType("real") + .HasColumnName("DEPTMEAS"); + + b.Property("Gtot") + .HasColumnType("real") + .HasColumnName("Gtot"); + + b.Property("Gx") + .HasColumnType("real") + .HasColumnName("Gx"); + + b.Property("Gy") + .HasColumnType("real") + .HasColumnName("Gy"); + + b.Property("Gz") + .HasColumnType("real") + .HasColumnName("Gz"); + + b.Property("TelemetryId") + .HasColumnType("integer"); + + b.HasIndex("TelemetryId"); + + b.ToTable("t_telemetry_wits_60"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record61", b => + { + b.HasBaseType("AsbCloudDb.Model.WITS.RecordBase"); + + b.Property("Att06h") + .HasColumnType("real") + .HasColumnName("ATT06H"); + + b.Property("Att06l") + .HasColumnType("real") + .HasColumnName("ATT06L"); + + b.Property("Att10h") + .HasColumnType("real") + .HasColumnName("ATT10H"); + + b.Property("Att10l") + .HasColumnType("real") + .HasColumnName("ATT10L"); + + b.Property("Deptbitm") + .HasColumnType("real") + .HasColumnName("DEPTBITM"); + + b.Property("Deptmeas") + .HasColumnType("real") + .HasColumnName("DEPTMEAS"); + + b.Property("Phl1f1") + .HasColumnType("real") + .HasColumnName("PHL1F1"); + + b.Property("Phl1f2") + .HasColumnType("real") + .HasColumnName("PHL1F2"); + + b.Property("Phl2f1") + .HasColumnType("real") + .HasColumnName("PHL2F1"); + + b.Property("Phl2f2") + .HasColumnType("real") + .HasColumnName("PHL2F2"); + + b.Property("Status") + .HasColumnType("real") + .HasColumnName("Status"); + + b.Property("TelemetryId") + .HasColumnType("integer"); + + b.HasIndex("TelemetryId"); + + b.ToTable("t_telemetry_wits_61"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record7", b => + { + b.HasBaseType("AsbCloudDb.Model.WITS.RecordBase"); + + b.Property("Deptmeas") + .HasColumnType("real") + .HasColumnName("DEPTMEAS"); + + b.Property("Deptsvym") + .HasColumnType("real") + .HasColumnName("DEPTSVYM"); + + b.Property("Deptsvyv") + .HasColumnType("real") + .HasColumnName("DEPTSVYV"); + + b.Property("Passnum") + .HasColumnType("smallint") + .HasColumnName("PASSNUM"); + + b.Property("Spare1") + .HasColumnType("real") + .HasColumnName("SPARE1"); + + b.Property("Spare2") + .HasColumnType("real") + .HasColumnName("SPARE2"); + + b.Property("Spare3") + .HasColumnType("real") + .HasColumnName("SPARE3"); + + b.Property("Spare4") + .HasColumnType("real") + .HasColumnName("SPARE4"); + + b.Property("Spare5") + .HasColumnType("real") + .HasColumnName("SPARE5"); + + b.Property("Svyazc") + .HasColumnType("real") + .HasColumnName("SVYAZC"); + + b.Property("Svyazu") + .HasColumnType("real") + .HasColumnName("SVYAZU"); + + b.Property("Svydls") + .HasColumnType("real") + .HasColumnName("SVYDLS"); + + b.Property("Svyew") + .HasColumnType("real") + .HasColumnName("SVYEW"); + + b.Property("Svygtf") + .HasColumnType("real") + .HasColumnName("SVYGTF"); + + b.Property("Svyinc") + .HasColumnType("real") + .HasColumnName("SVYINC"); + + b.Property("Svymtf") + .HasColumnType("real") + .HasColumnName("SVYMTF"); + + b.Property("Svyns") + .HasColumnType("real") + .HasColumnName("SVYNS"); + + b.Property("Svytype") + .HasColumnType("text") + .HasColumnName("SVYTYPE"); + + b.Property("Svywalk") + .HasColumnType("real") + .HasColumnName("SVYWALK"); + + b.Property("TelemetryId") + .HasColumnType("integer"); + + b.HasIndex("TelemetryId"); + + b.ToTable("t_telemetry_wits_7"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record8", b => + { + b.HasBaseType("AsbCloudDb.Model.WITS.RecordBase"); + + b.Property("Deptbitm") + .HasColumnType("real") + .HasColumnName("DEPTBITM"); + + b.Property("Deptbitv") + .HasColumnType("real") + .HasColumnName("DEPTBITV"); + + b.Property("Deptcalm") + .HasColumnType("real") + .HasColumnName("DEPTCALM"); + + b.Property("Deptcalv") + .HasColumnType("real") + .HasColumnName("DEPTCALV"); + + b.Property("Deptfdm") + .HasColumnType("real") + .HasColumnName("DEPTFDM"); + + b.Property("Deptfdv") + .HasColumnType("real") + .HasColumnName("DEPTFDV"); + + b.Property("Deptgr1m") + .HasColumnType("real") + .HasColumnName("DEPTGR1M"); + + b.Property("Deptgr1v") + .HasColumnType("real") + .HasColumnName("DEPTGR1V"); + + b.Property("Deptgr2m") + .HasColumnType("real") + .HasColumnName("DEPTGR2M"); + + b.Property("Deptgr2v") + .HasColumnType("real") + .HasColumnName("DEPTGR2V"); + + b.Property("Deptmeas") + .HasColumnType("real") + .HasColumnName("DEPTMEAS"); + + b.Property("Deptp1m") + .HasColumnType("real") + .HasColumnName("DEPTP1M"); + + b.Property("Deptp1v") + .HasColumnType("real") + .HasColumnName("DEPTP1V"); + + b.Property("Deptp2m") + .HasColumnType("real") + .HasColumnName("DEPTP2M"); + + b.Property("Deptp2v") + .HasColumnType("real") + .HasColumnName("DEPTP2V"); + + b.Property("Deptrs1m") + .HasColumnType("real") + .HasColumnName("DEPTRS1M"); + + b.Property("Deptrs1v") + .HasColumnType("real") + .HasColumnName("DEPTRS1V"); + + b.Property("Deptrs2m") + .HasColumnType("real") + .HasColumnName("DEPTRS2M"); + + b.Property("Deptrs2v") + .HasColumnType("real") + .HasColumnName("DEPTRS2V"); + + b.Property("Deptvert") + .HasColumnType("real") + .HasColumnName("DEPTVERT"); + + b.Property("Mclp") + .HasColumnType("real") + .HasColumnName("MCLP"); + + b.Property("Mfd") + .HasColumnType("real") + .HasColumnName("MFD"); + + b.Property("Mffp") + .HasColumnType("real") + .HasColumnName("MFFP"); + + b.Property("Mfpp") + .HasColumnType("real") + .HasColumnName("MFPP"); + + b.Property("Mfrann") + .HasColumnType("real") + .HasColumnName("MFRANN"); + + b.Property("Mfrpipe") + .HasColumnType("real") + .HasColumnName("MFRPIPE"); + + b.Property("Mftann") + .HasColumnType("real") + .HasColumnName("MFTANN"); + + b.Property("Mftpipe") + .HasColumnType("real") + .HasColumnName("MFTPIPE"); + + b.Property("Mg1") + .HasColumnType("real") + .HasColumnName("MG1"); + + b.Property("Mg1c") + .HasColumnType("real") + .HasColumnName("MG1C"); + + b.Property("Mg2") + .HasColumnType("real") + .HasColumnName("MG2"); + + b.Property("Mg2c") + .HasColumnType("real") + .HasColumnName("MG2C"); + + b.Property("Mpo1") + .HasColumnType("real") + .HasColumnName("MPO1"); + + b.Property("Mpo2") + .HasColumnType("real") + .HasColumnName("MPO2"); + + b.Property("Mr1") + .HasColumnType("real") + .HasColumnName("MR1"); + + b.Property("Mr1c") + .HasColumnType("real") + .HasColumnName("MR1C"); + + b.Property("Mr2") + .HasColumnType("real") + .HasColumnName("MR2"); + + b.Property("Mr2c") + .HasColumnType("real") + .HasColumnName("MR2C"); + + b.Property("Passnum") + .HasColumnType("smallint") + .HasColumnName("PASSNUM"); + + b.Property("Spare1") + .HasColumnType("real") + .HasColumnName("SPARE1"); + + b.Property("Spare2") + .HasColumnType("real") + .HasColumnName("SPARE2"); + + b.Property("Spare3") + .HasColumnType("real") + .HasColumnName("SPARE3"); + + b.Property("Spare4") + .HasColumnType("real") + .HasColumnName("SPARE4"); + + b.Property("Spare5") + .HasColumnType("real") + .HasColumnName("SPARE5"); + + b.Property("Spare6") + .HasColumnType("real") + .HasColumnName("SPARE6"); + + b.Property("Spare7") + .HasColumnType("real") + .HasColumnName("SPARE7"); + + b.Property("Spare8") + .HasColumnType("real") + .HasColumnName("SPARE8"); + + b.Property("Spare9") + .HasColumnType("real") + .HasColumnName("SPARE9"); + + b.Property("TelemetryId") + .HasColumnType("integer"); + + b.HasIndex("TelemetryId"); + + b.ToTable("t_telemetry_wits_8"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Cluster", b => + { + b.HasOne("AsbCloudDb.Model.Deposit", "Deposit") + .WithMany("Clusters") + .HasForeignKey("IdDeposit") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_cluster_t_deposit_id_fk"); + + b.Navigation("Deposit"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Company", b => + { + b.HasOne("AsbCloudDb.Model.CompanyType", "CompanyType") + .WithMany("Companies") + .HasForeignKey("IdCompanyType") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CompanyType"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Contact", b => + { + b.HasOne("AsbCloudDb.Model.CompanyType", "CompanyType") + .WithMany("Contacts") + .HasForeignKey("IdCompanyType") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany("Contacts") + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CompanyType"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DailyReports.DailyReport", b => + { + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DetectedOperation", b => + { + b.HasOne("AsbCloudDb.Model.WellOperationCategory", "OperationCategory") + .WithMany() + .HasForeignKey("IdCategory") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OperationCategory"); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DrillingProgramPart", b => + { + b.HasOne("AsbCloudDb.Model.FileCategory", "FileCategory") + .WithMany() + .HasForeignKey("IdFileCategory") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany("DrillingProgramParts") + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FileCategory"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DrillTest", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Faq", b => + { + b.HasOne("AsbCloudDb.Model.User", "AuthorAnswer") + .WithMany() + .HasForeignKey("IdAuthorAnswer"); + + b.HasOne("AsbCloudDb.Model.User", "AuthorQuestion") + .WithMany() + .HasForeignKey("IdAuthorQuestion") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AuthorAnswer"); + + b.Navigation("AuthorQuestion"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.FileInfo", b => + { + b.HasOne("AsbCloudDb.Model.User", "Author") + .WithMany("Files") + .HasForeignKey("IdAuthor"); + + b.HasOne("AsbCloudDb.Model.FileCategory", "FileCategory") + .WithMany() + .HasForeignKey("IdCategory") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("FileCategory"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.FileMark", b => + { + b.HasOne("AsbCloudDb.Model.FileInfo", "FileInfo") + .WithMany("FileMarks") + .HasForeignKey("IdFile") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_file_mark_t_file_info_fk"); + + b.HasOne("AsbCloudDb.Model.User", "User") + .WithMany("FileMarks") + .HasForeignKey("IdUser") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_user_t_file_mark_fk"); + + b.Navigation("FileInfo"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.GTR.WitsItemFloat", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.GTR.WitsItemInt", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.GTR.WitsItemString", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.HelpPage", b => + { + b.HasOne("AsbCloudDb.Model.FileCategory", "FileCategory") + .WithMany() + .HasForeignKey("IdCategory") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FileCategory"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.LimitingParameter", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Manuals.Manual", b => + { + b.HasOne("AsbCloudDb.Model.User", "Author") + .WithMany() + .HasForeignKey("IdAuthor") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.FileCategory", "Category") + .WithMany() + .HasForeignKey("IdCategory") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Manuals.ManualDirectory", "Directory") + .WithMany("Manuals") + .HasForeignKey("IdDirectory") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("Category"); + + b.Navigation("Directory"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Manuals.ManualDirectory", b => + { + b.HasOne("AsbCloudDb.Model.Manuals.ManualDirectory", "Parent") + .WithMany("Children") + .HasForeignKey("IdParent") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Measure", b => + { + b.HasOne("AsbCloudDb.Model.MeasureCategory", "Category") + .WithMany("Measures") + .HasForeignKey("IdCategory") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Notification", b => + { + b.HasOne("AsbCloudDb.Model.NotificationCategory", "NotificationCategory") + .WithMany("Notifications") + .HasForeignKey("IdNotificationCategory") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.User", "User") + .WithMany() + .HasForeignKey("IdUser") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NotificationCategory"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.OperationValue", b => + { + b.HasOne("AsbCloudDb.Model.WellOperationCategory", "OperationCategory") + .WithMany() + .HasForeignKey("IdOperationCategory") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OperationCategory"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.ProcessMaps.ProcessMapWellDrilling", b => + { + b.HasOne("AsbCloudDb.Model.User", "User") + .WithMany() + .HasForeignKey("IdUser") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.WellSectionType", "WellSectionType") + .WithMany() + .HasForeignKey("IdWellSectionType") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + + b.Navigation("Well"); + + b.Navigation("WellSectionType"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.ProcessMaps.ProcessMapWellReam", b => + { + b.HasOne("AsbCloudDb.Model.User", "User") + .WithMany() + .HasForeignKey("IdUser") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.WellSectionType", "WellSectionType") + .WithMany() + .HasForeignKey("IdWellSectionType") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + + b.Navigation("Well"); + + b.Navigation("WellSectionType"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationCompanyWell", b => + { + b.HasOne("AsbCloudDb.Model.Company", "Company") + .WithMany("RelationCompaniesWells") + .HasForeignKey("IdCompany") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_relation_company_well_t_company_id_fk"); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany("RelationCompaniesWells") + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_relation_company_well_t_well_id_fk"); + + b.Navigation("Company"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationContactWell", b => + { + b.HasOne("AsbCloudDb.Model.User", "User") + .WithMany("RelationContactsWells") + .HasForeignKey("IdUser") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationUserDrillingProgramPart", b => + { + b.HasOne("AsbCloudDb.Model.DrillingProgramPart", "DrillingProgramPart") + .WithMany("RelatedUsers") + .HasForeignKey("IdDrillingProgramPart") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.User", "User") + .WithMany() + .HasForeignKey("IdUser") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DrillingProgramPart"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationUserRolePermission", b => + { + b.HasOne("AsbCloudDb.Model.Permission", "Permission") + .WithMany("RelationUserRolePermissions") + .HasForeignKey("IdPermission") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.UserRole", "UserRole") + .WithMany("RelationUserRolePermissions") + .HasForeignKey("IdUserRole") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("UserRole"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationUserRoleUserRole", b => + { + b.HasOne("AsbCloudDb.Model.UserRole", "Role") + .WithMany("RelationUserRoleUserRoles") + .HasForeignKey("Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.UserRole", "IncludeRole") + .WithMany() + .HasForeignKey("IdInclude") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("IncludeRole"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationUserUserRole", b => + { + b.HasOne("AsbCloudDb.Model.User", "User") + .WithMany("RelationUsersUserRoles") + .HasForeignKey("IdUser") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.UserRole", "UserRole") + .WithMany("RelationUsersUserRoles") + .HasForeignKey("IdUserRole") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + + b.Navigation("UserRole"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.ReportProperty", b => + { + b.HasOne("AsbCloudDb.Model.FileInfo", "File") + .WithMany() + .HasForeignKey("IdFile") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("File"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Schedule", b => + { + b.HasOne("AsbCloudDb.Model.Driller", "Driller") + .WithMany("Schedule") + .HasForeignKey("IdDriller") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_schedule_t_driller_id_driller"); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Driller"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.SetpointsRequest", b => + { + b.HasOne("AsbCloudDb.Model.User", "Author") + .WithMany() + .HasForeignKey("IdAuthor") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Author"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Subsystems.SubsystemOperationTime", b => + { + b.HasOne("AsbCloudDb.Model.Subsystems.Subsystem", "Subsystem") + .WithMany() + .HasForeignKey("IdSubsystem") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Subsystem"); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryDataSaub", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany("DataSaub") + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_telemetry_data_saub_t_telemetry_id_fk"); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryDataSpin", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany("DataSpin") + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_telemetry_data_spin_t_telemetry_id_fk"); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryEvent", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany("Events") + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_event_t_telemetry_id_fk"); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryMessage", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany("Messages") + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_messages_t_telemetry_id_fk"); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryUser", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany("Users") + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_telemetry_user_t_telemetry_id_fk"); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Trajectory.TrajectoryFact", b => + { + b.HasOne("AsbCloudDb.Model.User", "User") + .WithMany() + .HasForeignKey("IdUser") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Trajectory.TrajectoryPlan", b => + { + b.HasOne("AsbCloudDb.Model.User", "User") + .WithMany() + .HasForeignKey("IdUser") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.User", b => + { + b.HasOne("AsbCloudDb.Model.Company", "Company") + .WithMany("Users") + .HasForeignKey("IdCompany") + .OnDelete(DeleteBehavior.SetNull) + .IsRequired() + .HasConstraintName("t_user_t_company_id_fk"); + + b.Navigation("Company"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.UserSetting", b => + { + b.HasOne("AsbCloudDb.Model.User", "User") + .WithMany() + .HasForeignKey("IdUser") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Well", b => + { + b.HasOne("AsbCloudDb.Model.Cluster", "Cluster") + .WithMany("Wells") + .HasForeignKey("IdCluster") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_well_t_cluster_id_fk"); + + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithOne("Well") + .HasForeignKey("AsbCloudDb.Model.Well", "IdTelemetry") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("t_well_t_telemetry_id_fk"); + + b.HasOne("AsbCloudDb.Model.WellType", "WellType") + .WithMany("Wells") + .HasForeignKey("IdWellType") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Cluster"); + + b.Navigation("Telemetry"); + + b.Navigation("WellType"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellComposite", b => + { + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany("WellComposites") + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_well_сomposite_t_well_id_fk"); + + b.HasOne("AsbCloudDb.Model.WellSectionType", "WellSectionType") + .WithMany("WellComposites") + .HasForeignKey("IdWellSectionType") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_well_сomposite_t_well_section_type_id_fk"); + + b.HasOne("AsbCloudDb.Model.Well", "WellSrc") + .WithMany("WellCompositeSrcs") + .HasForeignKey("IdWellSrc") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("t_well_сomposite_src_t_well_id_fk"); + + b.Navigation("Well"); + + b.Navigation("WellSectionType"); + + b.Navigation("WellSrc"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellFinalDocument", b => + { + b.HasOne("AsbCloudDb.Model.FileCategory", "Category") + .WithMany() + .HasForeignKey("IdCategory") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.User", "User") + .WithMany() + .HasForeignKey("IdUser") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + + b.Navigation("User"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellOperation", b => + { + b.HasOne("AsbCloudDb.Model.WellOperationCategory", "OperationCategory") + .WithMany() + .HasForeignKey("IdCategory") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.WellOperation", "OperationPlan") + .WithMany() + .HasForeignKey("IdPlan") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany("WellOperations") + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.WellSectionType", "WellSectionType") + .WithMany("WellOperations") + .HasForeignKey("IdWellSectionType") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OperationCategory"); + + b.Navigation("OperationPlan"); + + b.Navigation("Well"); + + b.Navigation("WellSectionType"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellOperationCategory", b => + { + b.HasOne("AsbCloudDb.Model.WellOperationCategory", "Parent") + .WithMany() + .HasForeignKey("IdParent"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record1", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("TelemetryId"); + + b.HasOne("AsbCloudDb.Model.WITS.RecordBase", null) + .WithOne() + .HasForeignKey("AsbCloudDb.Model.WITS.Record1", "IdTelemetry", "DateTime") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record50", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("TelemetryId"); + + b.HasOne("AsbCloudDb.Model.WITS.RecordBase", null) + .WithOne() + .HasForeignKey("AsbCloudDb.Model.WITS.Record50", "IdTelemetry", "DateTime") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record60", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("TelemetryId"); + + b.HasOne("AsbCloudDb.Model.WITS.RecordBase", null) + .WithOne() + .HasForeignKey("AsbCloudDb.Model.WITS.Record60", "IdTelemetry", "DateTime") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record61", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("TelemetryId"); + + b.HasOne("AsbCloudDb.Model.WITS.RecordBase", null) + .WithOne() + .HasForeignKey("AsbCloudDb.Model.WITS.Record61", "IdTelemetry", "DateTime") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record7", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("TelemetryId"); + + b.HasOne("AsbCloudDb.Model.WITS.RecordBase", null) + .WithOne() + .HasForeignKey("AsbCloudDb.Model.WITS.Record7", "IdTelemetry", "DateTime") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record8", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("TelemetryId"); + + b.HasOne("AsbCloudDb.Model.WITS.RecordBase", null) + .WithOne() + .HasForeignKey("AsbCloudDb.Model.WITS.Record8", "IdTelemetry", "DateTime") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Telemetry"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Cluster", b => + { + b.Navigation("Wells"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Company", b => + { + b.Navigation("RelationCompaniesWells"); + + b.Navigation("Users"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.CompanyType", b => + { + b.Navigation("Companies"); + + b.Navigation("Contacts"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Deposit", b => + { + b.Navigation("Clusters"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Driller", b => + { + b.Navigation("Schedule"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DrillingProgramPart", b => + { + b.Navigation("RelatedUsers"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.FileInfo", b => + { + b.Navigation("FileMarks"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Manuals.ManualDirectory", b => + { + b.Navigation("Children"); + + b.Navigation("Manuals"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.MeasureCategory", b => + { + b.Navigation("Measures"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.NotificationCategory", b => + { + b.Navigation("Notifications"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Permission", b => + { + b.Navigation("RelationUserRolePermissions"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Telemetry", b => + { + b.Navigation("DataSaub"); + + b.Navigation("DataSpin"); + + b.Navigation("Events"); + + b.Navigation("Messages"); + + b.Navigation("Users"); + + b.Navigation("Well"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.User", b => + { + b.Navigation("FileMarks"); + + b.Navigation("Files"); + + b.Navigation("RelationContactsWells"); + + b.Navigation("RelationUsersUserRoles"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.UserRole", b => + { + b.Navigation("RelationUserRolePermissions"); + + b.Navigation("RelationUserRoleUserRoles"); + + b.Navigation("RelationUsersUserRoles"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Well", b => + { + b.Navigation("Contacts"); + + b.Navigation("DrillingProgramParts"); + + b.Navigation("RelationCompaniesWells"); + + b.Navigation("WellCompositeSrcs"); + + b.Navigation("WellComposites"); + + b.Navigation("WellOperations"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellSectionType", b => + { + b.Navigation("WellComposites"); + + b.Navigation("WellOperations"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellType", b => + { + b.Navigation("Wells"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/AsbCloudDb/Migrations/20231205061148_DetectedOperation_add_subsystems_and_extraData.cs b/AsbCloudDb/Migrations/20231205061148_DetectedOperation_add_subsystems_and_extraData.cs new file mode 100644 index 00000000..72cfe669 --- /dev/null +++ b/AsbCloudDb/Migrations/20231205061148_DetectedOperation_add_subsystems_and_extraData.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace AsbCloudDb.Migrations +{ + public partial class DetectedOperation_add_subsystems_and_extraData : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "id_reason_of_end", + table: "t_detected_operation"); + + migrationBuilder.AddColumn( + name: "enabled_subsystems", + table: "t_detected_operation", + type: "integer", + nullable: false, + defaultValue: 0, + comment: "флаги аключенных подсистем"); + + migrationBuilder.AddColumn>( + name: "extra_data", + table: "t_detected_operation", + type: "jsonb", + nullable: false, + comment: "доп. инфо по операции"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "enabled_subsystems", + table: "t_detected_operation"); + + migrationBuilder.DropColumn( + name: "extra_data", + table: "t_detected_operation"); + + migrationBuilder.AddColumn( + name: "id_reason_of_end", + table: "t_detected_operation", + type: "integer", + nullable: false, + defaultValue: 0, + comment: "Код признака окончания операции"); + } + } +} diff --git a/AsbCloudDb/Migrations/AsbCloudDbContextModelSnapshot.cs b/AsbCloudDb/Migrations/AsbCloudDbContextModelSnapshot.cs index 2ed6ec03..018f140a 100644 --- a/AsbCloudDb/Migrations/AsbCloudDbContextModelSnapshot.cs +++ b/AsbCloudDb/Migrations/AsbCloudDbContextModelSnapshot.cs @@ -1,5 +1,6 @@ // using System; +using System.Collections.Generic; using System.Text.Json; using AsbCloudDb.Model; using Microsoft.EntityFrameworkCore; @@ -382,16 +383,22 @@ namespace AsbCloudDb.Migrations .HasColumnName("depth_start") .HasComment("Глубина на начало операции, м"); + b.Property("EnabledSubsystems") + .HasColumnType("integer") + .HasColumnName("enabled_subsystems") + .HasComment("флаги аключенных подсистем"); + + b.Property>("ExtraData") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("extra_data") + .HasComment("доп. инфо по операции"); + b.Property("IdCategory") .HasColumnType("integer") .HasColumnName("id_category") .HasComment("Id категории операции"); - b.Property("IdReasonOfEnd") - .HasColumnType("integer") - .HasColumnName("id_reason_of_end") - .HasComment("Код признака окончания операции"); - b.Property("IdTelemetry") .HasColumnType("integer") .HasColumnName("id_telemetry"); From e550ac9d13a34595804018bb98f2d16f07c7d379 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 5 Dec 2023 11:35:11 +0500 Subject: [PATCH 08/10] fix migration DetectedOperation_add_subsystems_and_extraData --- ..._add_subsystems_and_extraData.Designer.cs} | 2 +- ...Operation_add_subsystems_and_extraData.cs} | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) rename AsbCloudDb/Migrations/{20231205061148_DetectedOperation_add_subsystems_and_extraData.Designer.cs => 20231205063450_DetectedOperation_add_subsystems_and_extraData.Designer.cs} (99%) rename AsbCloudDb/Migrations/{20231205061148_DetectedOperation_add_subsystems_and_extraData.cs => 20231205063450_DetectedOperation_add_subsystems_and_extraData.cs} (65%) diff --git a/AsbCloudDb/Migrations/20231205061148_DetectedOperation_add_subsystems_and_extraData.Designer.cs b/AsbCloudDb/Migrations/20231205063450_DetectedOperation_add_subsystems_and_extraData.Designer.cs similarity index 99% rename from AsbCloudDb/Migrations/20231205061148_DetectedOperation_add_subsystems_and_extraData.Designer.cs rename to AsbCloudDb/Migrations/20231205063450_DetectedOperation_add_subsystems_and_extraData.Designer.cs index e3461b2f..188c3aaf 100644 --- a/AsbCloudDb/Migrations/20231205061148_DetectedOperation_add_subsystems_and_extraData.Designer.cs +++ b/AsbCloudDb/Migrations/20231205063450_DetectedOperation_add_subsystems_and_extraData.Designer.cs @@ -14,7 +14,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace AsbCloudDb.Migrations { [DbContext(typeof(AsbCloudDbContext))] - [Migration("20231205061148_DetectedOperation_add_subsystems_and_extraData")] + [Migration("20231205063450_DetectedOperation_add_subsystems_and_extraData")] partial class DetectedOperation_add_subsystems_and_extraData { protected override void BuildTargetModel(ModelBuilder modelBuilder) diff --git a/AsbCloudDb/Migrations/20231205061148_DetectedOperation_add_subsystems_and_extraData.cs b/AsbCloudDb/Migrations/20231205063450_DetectedOperation_add_subsystems_and_extraData.cs similarity index 65% rename from AsbCloudDb/Migrations/20231205061148_DetectedOperation_add_subsystems_and_extraData.cs rename to AsbCloudDb/Migrations/20231205063450_DetectedOperation_add_subsystems_and_extraData.cs index 72cfe669..c295f1cd 100644 --- a/AsbCloudDb/Migrations/20231205061148_DetectedOperation_add_subsystems_and_extraData.cs +++ b/AsbCloudDb/Migrations/20231205063450_DetectedOperation_add_subsystems_and_extraData.cs @@ -9,6 +9,16 @@ namespace AsbCloudDb.Migrations { protected override void Up(MigrationBuilder migrationBuilder) { + migrationBuilder.DeleteData( + table: "t_relation_user_role_permission", + keyColumns: new[] { "id_permission", "id_user_role" }, + keyValues: new object[] { 529, 1 }); + + migrationBuilder.DeleteData( + table: "t_permission", + keyColumn: "id", + keyValue: 529); + migrationBuilder.DropColumn( name: "id_reason_of_end", table: "t_detected_operation"); @@ -46,6 +56,16 @@ namespace AsbCloudDb.Migrations nullable: false, defaultValue: 0, comment: "Код признака окончания операции"); + + migrationBuilder.InsertData( + table: "t_permission", + columns: new[] { "id", "description", "name" }, + values: new object[] { 529, "Разрешение редактировать фактические траектории", "FactTrajectory.edit" }); + + migrationBuilder.InsertData( + table: "t_relation_user_role_permission", + columns: new[] { "id_permission", "id_user_role" }, + values: new object[] { 529, 1 }); } } } From 2ceac00a4fe59f410a0586bb953bebd49f4d3e81 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 5 Dec 2023 11:37:52 +0500 Subject: [PATCH 09/10] fix2 migration DetectedOperation_add_subsystems_and_extraData --- ...31205063450_DetectedOperation_add_subsystems_and_extraData.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/AsbCloudDb/Migrations/20231205063450_DetectedOperation_add_subsystems_and_extraData.cs b/AsbCloudDb/Migrations/20231205063450_DetectedOperation_add_subsystems_and_extraData.cs index c295f1cd..de054b29 100644 --- a/AsbCloudDb/Migrations/20231205063450_DetectedOperation_add_subsystems_and_extraData.cs +++ b/AsbCloudDb/Migrations/20231205063450_DetectedOperation_add_subsystems_and_extraData.cs @@ -36,6 +36,7 @@ namespace AsbCloudDb.Migrations table: "t_detected_operation", type: "jsonb", nullable: false, + defaultValue: new { }, comment: "доп. инфо по операции"); } From 371083bd3882273a3b02aa96442a99575e09daed Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Tue, 5 Dec 2023 12:10:30 +0500 Subject: [PATCH 10/10] DetectedOperationExportService fix comment --- .../DetectedOperationExportService.cs | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs index bb5f2663..15dab40f 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs @@ -6,12 +6,10 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; -using System.Text; using System.Threading; using System.Threading.Tasks; using AsbCloudInfrastructure.Services.DetectOperations.Detectors; using AsbCloudApp.Repositories; -using AsbCloudInfrastructure.Repository; namespace AsbCloudInfrastructure.Services.DetectOperations; @@ -69,8 +67,7 @@ public class DetectedOperationExportService if (!well.IdTelemetry.HasValue) throw new ArgumentNullException(nameof(well)); - var operations = await DetectOperationsAsync(well.IdTelemetry.Value, new DateTime(2023, 10, 14) - .ToUtcDateTimeOffset(well.Timezone.Hours), cancellationToken); + var operations = await DetectOperationsAsync(well.IdTelemetry.Value, DateTime.UnixEpoch, cancellationToken); return await GenerateExcelFileStreamAsync(well, idDomain, operations, cancellationToken); } @@ -200,19 +197,15 @@ public class DetectedOperationExportService { case WellOperationCategory.IdRotor: case WellOperationCategory.IdSlide: - { - var avgRotorSpeed = operation.ExtraData[DetectorDrilling.ExtraDataKeyAvgRotorSpeed]; - var dispersionOfNormalizedRotorSpeed = operation.ExtraData[DetectorDrilling.ExtraDataKeyDispersionOfNormalizedRotorSpeed]; - var isAfbEnabledObject = operation.ExtraData[DetectorDrilling.ExtraDataKeyIsAfbEnabled]; - var AfbState = ""; - if (isAfbEnabledObject is bool isAfbEnabled && isAfbEnabled) - AfbState = "АКБ - вкл"; + var comment = ""; + if (operation.ExtraData.TryGetValue(DetectorDrilling.ExtraDataKeyAvgRotorSpeed, out object? oAvgRotorSpeed)) + comment += $"Средняя скорость оборотов ротора: {oAvgRotorSpeed}\r\n"; - var comment = $"Средняя скорость оборотов ротора: {avgRotorSpeed}\r\n" + - $"Дисперсия нормированных оборотов ротора: {dispersionOfNormalizedRotorSpeed} \r\n" + - $"{AfbState}"; + if (operation.ExtraData.TryGetValue(DetectorDrilling.ExtraDataKeyDispersionOfNormalizedRotorSpeed, out object? oDispersionOfNormalizedRotorSpeed)) + comment += $"Дисперсия нормированных оборотов ротора: {oDispersionOfNormalizedRotorSpeed}"; + return comment; - } + default: return string.Empty; }