diff --git a/AsbCloudApp/Data/DailyReport/DailyReportDto.cs b/AsbCloudApp/Data/DailyReport/DailyReportDto.cs index d8d9d4c8..c31dd73c 100644 --- a/AsbCloudApp/Data/DailyReport/DailyReportDto.cs +++ b/AsbCloudApp/Data/DailyReport/DailyReportDto.cs @@ -74,7 +74,7 @@ public class DailyReportDto : IId, /// <summary> /// Дата последнего обновления /// </summary> - public DateTime? DateLastUpdate { get; set; } + public DateTimeOffset? DateLastUpdate { get; set; } /// <summary> /// Блок фактической траектории diff --git a/AsbCloudApp/Data/DataSaubStatDto.cs b/AsbCloudApp/Data/DataSaubStatDto.cs index a3b80a5d..ceae4f9d 100644 --- a/AsbCloudApp/Data/DataSaubStatDto.cs +++ b/AsbCloudApp/Data/DataSaubStatDto.cs @@ -1,4 +1,5 @@ using System; +using AsbCloudApp.Data.WellOperation; namespace AsbCloudApp.Data { diff --git a/AsbCloudApp/Data/DatesRangeDto.cs b/AsbCloudApp/Data/DatesRangeDto.cs index 3f12acb7..a61034b6 100644 --- a/AsbCloudApp/Data/DatesRangeDto.cs +++ b/AsbCloudApp/Data/DatesRangeDto.cs @@ -12,12 +12,12 @@ namespace AsbCloudApp.Data /// Дата начала диапазона /// </summary> [Required] - public DateTime From { get; set; } + public DateTimeOffset From { get; set; } /// <summary> /// Дата окончания диапазона /// </summary> [Required] - public DateTime To { get; set; } + public DateTimeOffset To { get; set; } } } diff --git a/AsbCloudApp/Data/DetectedOperation/DetectedOperationDto.cs b/AsbCloudApp/Data/DetectedOperation/DetectedOperationDto.cs index e81a45fb..c8b1e15a 100644 --- a/AsbCloudApp/Data/DetectedOperation/DetectedOperationDto.cs +++ b/AsbCloudApp/Data/DetectedOperation/DetectedOperationDto.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using AsbCloudApp.Data.WellOperation; namespace AsbCloudApp.Data.DetectedOperation; diff --git a/AsbCloudApp/Data/DrillTestReport/DrillTestReportDataDto.cs b/AsbCloudApp/Data/DrillTestReport/DrillTestReportDataDto.cs index ee63bf9b..b45783e6 100644 --- a/AsbCloudApp/Data/DrillTestReport/DrillTestReportDataDto.cs +++ b/AsbCloudApp/Data/DrillTestReport/DrillTestReportDataDto.cs @@ -21,6 +21,6 @@ namespace AsbCloudApp.Data.DrillTestReport /// <summary> /// Дата отчета /// </summary> - public DateTime Date { get; set; } = DateTime.Now; + public DateTimeOffset Date { get; set; } = DateTimeOffset.Now; } } diff --git a/AsbCloudApp/Data/DrillTestReport/DrillTestReportInfoDto.cs b/AsbCloudApp/Data/DrillTestReport/DrillTestReportInfoDto.cs index 39d37a11..a178e6fe 100644 --- a/AsbCloudApp/Data/DrillTestReport/DrillTestReportInfoDto.cs +++ b/AsbCloudApp/Data/DrillTestReport/DrillTestReportInfoDto.cs @@ -24,6 +24,6 @@ namespace AsbCloudApp.Data.DrillTestReport /// Дата и время /// </summary> [Required] - public DateTime DateTime { get; set; } + public DateTimeOffset DateTime { get; set; } } } diff --git a/AsbCloudApp/Data/FileInfoDto.cs b/AsbCloudApp/Data/FileInfoDto.cs index 8e006661..ab44b317 100644 --- a/AsbCloudApp/Data/FileInfoDto.cs +++ b/AsbCloudApp/Data/FileInfoDto.cs @@ -43,7 +43,7 @@ namespace AsbCloudApp.Data /// дата загрузки /// </summary> [Required] - public DateTime UploadDate { get; set; } + public DateTimeOffset UploadDate { get; set; } /// <summary> /// размер в байтах diff --git a/AsbCloudApp/Data/FileMarkDto.cs b/AsbCloudApp/Data/FileMarkDto.cs index 7329821b..305fad5c 100644 --- a/AsbCloudApp/Data/FileMarkDto.cs +++ b/AsbCloudApp/Data/FileMarkDto.cs @@ -33,7 +33,7 @@ namespace AsbCloudApp.Data /// ������������� ��������� � ������� �� ��������. /// </summary> [Required] - public DateTime DateCreated { get; set; } + public DateTimeOffset DateCreated { get; set; } /// <summary> /// �������� ����������� diff --git a/AsbCloudApp/Data/LimitingParameterDataDto.cs b/AsbCloudApp/Data/LimitingParameterDataDto.cs index 1bf982dc..c5692729 100644 --- a/AsbCloudApp/Data/LimitingParameterDataDto.cs +++ b/AsbCloudApp/Data/LimitingParameterDataDto.cs @@ -20,12 +20,12 @@ namespace AsbCloudApp.Data /// <summary> /// Дата начала ограничения /// </summary> - public DateTime DateStart { get; set; } + public DateTimeOffset DateStart { get; set; } /// <summary> /// Дата окончания ограничения /// </summary> - public DateTime DateEnd { get; set; } + public DateTimeOffset DateEnd { get; set; } /// <summary> /// Глубина начала ограничения diff --git a/AsbCloudApp/Data/Manuals/ManualDto.cs b/AsbCloudApp/Data/Manuals/ManualDto.cs index bb89dfbe..c5aa92c4 100644 --- a/AsbCloudApp/Data/Manuals/ManualDto.cs +++ b/AsbCloudApp/Data/Manuals/ManualDto.cs @@ -18,7 +18,7 @@ public class ManualDto : IId /// <summary> /// Дата загрузки /// </summary> - public DateTime DateDownload { get; set; } + public DateTimeOffset DateDownload { get; set; } /// <summary> /// Id автора diff --git a/AsbCloudApp/Data/MeasureDto.cs b/AsbCloudApp/Data/MeasureDto.cs index 9f823a91..4eddd78f 100644 --- a/AsbCloudApp/Data/MeasureDto.cs +++ b/AsbCloudApp/Data/MeasureDto.cs @@ -36,7 +36,7 @@ namespace AsbCloudApp.Data /// отметка времени замера /// </summary> [Required] - public DateTime Timestamp { get; set; } + public DateTimeOffset Timestamp { get; set; } /// <summary> /// данные замера diff --git a/AsbCloudApp/Data/MessageDto.cs b/AsbCloudApp/Data/MessageDto.cs index 071967d9..7234db7a 100644 --- a/AsbCloudApp/Data/MessageDto.cs +++ b/AsbCloudApp/Data/MessageDto.cs @@ -16,7 +16,7 @@ namespace AsbCloudApp.Data /// дата появления события /// </summary> [Required] - public DateTime DateTime { get; set; } + public DateTimeOffset DateTime { get; set; } /// <summary> /// категория события diff --git a/AsbCloudApp/Data/NotificationDto.cs b/AsbCloudApp/Data/NotificationDto.cs index ee42f8d7..0fd8b673 100644 --- a/AsbCloudApp/Data/NotificationDto.cs +++ b/AsbCloudApp/Data/NotificationDto.cs @@ -42,17 +42,17 @@ public class NotificationDto : IId /// Дата регистрации уведомления /// </summary> [Required] - public DateTime RegistrationDate { get; set; } + public DateTimeOffset RegistrationDate { get; set; } /// <summary> /// Дата отправки уведомления /// </summary> - public DateTime? SentDate { get; set; } + public DateTimeOffset? SentDate { get; set; } /// <summary> /// Дата прочтения уведомления /// </summary> - public DateTime? ReadDate { get; set; } + public DateTimeOffset? ReadDate { get; set; } /// <summary> /// Состояние уведомления @@ -82,12 +82,12 @@ public class NotificationDto : IId ReadDate = null; break; case 1: - SentDate = DateTime.UtcNow; + SentDate = DateTimeOffset.UtcNow; ReadDate = null; break; case 2: - SentDate = DateTime.UtcNow; - ReadDate = DateTime.UtcNow; + SentDate = DateTimeOffset.UtcNow; + ReadDate = DateTimeOffset.UtcNow; break; } } diff --git a/AsbCloudApp/Data/ParserResultDto.cs b/AsbCloudApp/Data/ParserResultDto.cs index 5b6eca8d..ffb24d50 100644 --- a/AsbCloudApp/Data/ParserResultDto.cs +++ b/AsbCloudApp/Data/ParserResultDto.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; namespace AsbCloudApp.Data; @@ -9,4 +10,8 @@ namespace AsbCloudApp.Data; public class ParserResultDto<TDto> : ValidationResultDto<IEnumerable<ValidationResultDto<TDto>>> where TDto : class, IId { + /// <summary> + /// Объекты полученные из файла + /// </summary> + public override IEnumerable<ValidationResultDto<TDto>> Item { get; set; } = Enumerable.Empty<ValidationResultDto<TDto>>(); } \ No newline at end of file diff --git a/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatDto.cs b/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatDto.cs index 6255726f..4bf221de 100644 --- a/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatDto.cs +++ b/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportDataSaubStatDto.cs @@ -44,7 +44,7 @@ public class ProcessMapReportDataSaubStatDto /// на начало интервала /// </para> /// </summary> - public DateTime DateStart { get; set; } + public DateTimeOffset DateStart { get; set; } /// <summary> /// Режим бурения (Ротор/слайд/ручной) diff --git a/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportWellDrillingDto.cs b/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportWellDrillingDto.cs index 16a9749c..cee53050 100644 --- a/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportWellDrillingDto.cs +++ b/AsbCloudApp/Data/ProcessMaps/Report/ProcessMapReportWellDrillingDto.cs @@ -44,7 +44,7 @@ public class ProcessMapReportWellDrillingDto /// на начало интервала /// </para> /// </summary> - public DateTime DateStart { get; set; } + public DateTimeOffset DateStart { get; set; } /// <summary> /// Время мех бурения, ч diff --git a/AsbCloudApp/Data/ReportPropertiesDto.cs b/AsbCloudApp/Data/ReportPropertiesDto.cs index 82caa77e..f802a7e0 100644 --- a/AsbCloudApp/Data/ReportPropertiesDto.cs +++ b/AsbCloudApp/Data/ReportPropertiesDto.cs @@ -29,17 +29,17 @@ namespace AsbCloudApp.Data /// <summary> /// Дата формирования /// </summary> - public DateTime Date { get; set; } + public DateTimeOffset Date { get; set; } /// <summary> /// Дата начала рапорта /// </summary> - public DateTime Begin { get; set; } + public DateTimeOffset Begin { get; set; } /// <summary> /// Дата окончания рапорта /// </summary> - public DateTime End { get; set; } + public DateTimeOffset End { get; set; } /// <summary> /// шаг между точками диаграммы diff --git a/AsbCloudApp/Data/SAUB/SetpointsRequestDto.cs b/AsbCloudApp/Data/SAUB/SetpointsRequestDto.cs index ed81c0ef..192805a6 100644 --- a/AsbCloudApp/Data/SAUB/SetpointsRequestDto.cs +++ b/AsbCloudApp/Data/SAUB/SetpointsRequestDto.cs @@ -33,7 +33,7 @@ namespace AsbCloudApp.Data.SAUB /// <summary> /// отметка времени создания запроса /// </summary> - public DateTime UploadDate { get; set; } = DateTime.Now; + public DateTimeOffset UploadDate { get; set; } = DateTimeOffset.Now; /// <summary> /// время в секундах актуальности этого запроса diff --git a/AsbCloudApp/Data/SAUB/TelemetryMessageDto.cs b/AsbCloudApp/Data/SAUB/TelemetryMessageDto.cs index 6c246f16..ee86fc46 100644 --- a/AsbCloudApp/Data/SAUB/TelemetryMessageDto.cs +++ b/AsbCloudApp/Data/SAUB/TelemetryMessageDto.cs @@ -15,7 +15,7 @@ namespace AsbCloudApp.Data.SAUB /// <summary> /// отметка времени /// </summary> - public DateTime Date { get; set; } + public DateTimeOffset Date { get; set; } /// <summary> /// глубина забоя diff --git a/AsbCloudApp/Data/SAUB/TelemetryWirelineRunOutDto.cs b/AsbCloudApp/Data/SAUB/TelemetryWirelineRunOutDto.cs index 69ac6929..213b67ec 100644 --- a/AsbCloudApp/Data/SAUB/TelemetryWirelineRunOutDto.cs +++ b/AsbCloudApp/Data/SAUB/TelemetryWirelineRunOutDto.cs @@ -10,7 +10,7 @@ namespace AsbCloudApp.Data.SAUB /// <summary> /// отметка времени /// </summary> - public DateTime DateTime { get; set; } + public DateTimeOffset DateTime { get; set; } /// <summary> /// Наработка талевого каната с момента перетяжки каната, т*км diff --git a/AsbCloudApp/Data/ScheduleDto.cs b/AsbCloudApp/Data/ScheduleDto.cs index 84cbe515..a8c8d652 100644 --- a/AsbCloudApp/Data/ScheduleDto.cs +++ b/AsbCloudApp/Data/ScheduleDto.cs @@ -39,13 +39,13 @@ namespace AsbCloudApp.Data /// Начало бурения /// </summary> [Required] - public DateTime DrillStart { get; set; } + public DateTimeOffset DrillStart { get; set; } /// <summary> /// Конец бурения /// </summary> [Required] - public DateTime DrillEnd { get; set; } + public DateTimeOffset DrillEnd { get; set; } /// <summary> /// Бурильщик diff --git a/AsbCloudApp/Data/StatOperationsDto.cs b/AsbCloudApp/Data/StatOperationsDto.cs index 7d082648..ec59eae0 100644 --- a/AsbCloudApp/Data/StatOperationsDto.cs +++ b/AsbCloudApp/Data/StatOperationsDto.cs @@ -11,12 +11,12 @@ namespace AsbCloudApp.Data /// <summary> /// Дата и время начала /// </summary> - public DateTime? Start { get; set; } + public DateTimeOffset? Start { get; set; } /// <summary> /// Дата и время окончания /// </summary> - public DateTime? End { get; set; } + public DateTimeOffset? End { get; set; } /// <summary> /// Глубина, м diff --git a/AsbCloudApp/Data/StatWellDto.cs b/AsbCloudApp/Data/StatWellDto.cs index ece9756c..9cf27fe4 100644 --- a/AsbCloudApp/Data/StatWellDto.cs +++ b/AsbCloudApp/Data/StatWellDto.cs @@ -42,7 +42,7 @@ namespace AsbCloudApp.Data /// дата прихода последней телеметрии /// </summary> [Required] - public DateTime LastTelemetryDate { get; set; } + public DateTimeOffset LastTelemetryDate { get; set; } /// <summary> /// Статистика по секциям diff --git a/AsbCloudApp/Data/Trajectory/TrajectoryGeoDto.cs b/AsbCloudApp/Data/Trajectory/TrajectoryGeoDto.cs index 237c20b2..11b88141 100644 --- a/AsbCloudApp/Data/Trajectory/TrajectoryGeoDto.cs +++ b/AsbCloudApp/Data/Trajectory/TrajectoryGeoDto.cs @@ -46,7 +46,7 @@ namespace AsbCloudApp.Data.Trajectory /// <summary> /// Дата загрузки /// </summary> - public DateTime UpdateDate { get; set; } + public DateTimeOffset UpdateDate { get; set; } /// <summary> /// ИД пользователя diff --git a/AsbCloudApp/Data/ValidationResultDto.cs b/AsbCloudApp/Data/ValidationResultDto.cs index 0116fe0a..1fe0f918 100644 --- a/AsbCloudApp/Data/ValidationResultDto.cs +++ b/AsbCloudApp/Data/ValidationResultDto.cs @@ -18,7 +18,7 @@ public class ValidationResultDto<T> /// <summary> /// Объект валидации /// </summary> - public T Item { get; set; } = null!; + public virtual T Item { get; set; } = null!; /// <summary> /// Предупреждения diff --git a/AsbCloudApp/Data/WellDto.cs b/AsbCloudApp/Data/WellDto.cs index 30f524c2..368e58c9 100644 --- a/AsbCloudApp/Data/WellDto.cs +++ b/AsbCloudApp/Data/WellDto.cs @@ -67,12 +67,12 @@ namespace AsbCloudApp.Data /// <summary> /// Дата/время первой операции /// </summary> - public DateTime? StartDate { get; set; } + public DateTimeOffset? StartDate { get; set; } /// <summary> /// Дата/время кода приходили данные последний раз /// </summary> - public DateTime LastTelemetryDate { get; set; } + public DateTimeOffset LastTelemetryDate { get; set; } /// <summary> /// ID телеметрии diff --git a/AsbCloudApp/Data/WellMapInfoDto.cs b/AsbCloudApp/Data/WellMapInfoDto.cs index a677a1e3..55098f4b 100644 --- a/AsbCloudApp/Data/WellMapInfoDto.cs +++ b/AsbCloudApp/Data/WellMapInfoDto.cs @@ -82,14 +82,14 @@ namespace AsbCloudApp.Data /// <para>Дата начала первой фактической операции</para> /// <para>Используется как дата начала бурения</para> /// </summary> - public DateTime? FirstFactOperationDateStart { get; set; } + public DateTimeOffset? FirstFactOperationDateStart { get; set; } /// <summary> /// <para>Дата окончания последней прогнозируемой операции</para> /// <para>Если скважина завершена, то дата окончания последней фактической операции</para> /// <para>Используется как прогноз окончания бурения</para> /// </summary> - public DateTime? LastPredictOperationDateEnd { get; set; } + public DateTimeOffset? LastPredictOperationDateEnd { get; set; } /// <summary> /// Рейсовая скорость проходки, последнего рейса diff --git a/AsbCloudApp/Data/WellGroupOpertionDto.cs b/AsbCloudApp/Data/WellOperation/WellGroupOpertionDto.cs similarity index 100% rename from AsbCloudApp/Data/WellGroupOpertionDto.cs rename to AsbCloudApp/Data/WellOperation/WellGroupOpertionDto.cs diff --git a/AsbCloudApp/Data/WellOperationCategoryDto.cs b/AsbCloudApp/Data/WellOperation/WellOperationCategoryDto.cs similarity index 96% rename from AsbCloudApp/Data/WellOperationCategoryDto.cs rename to AsbCloudApp/Data/WellOperation/WellOperationCategoryDto.cs index 108a31f0..2fe0b177 100644 --- a/AsbCloudApp/Data/WellOperationCategoryDto.cs +++ b/AsbCloudApp/Data/WellOperation/WellOperationCategoryDto.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data.WellOperation { /// <summary> /// DTO категория операции diff --git a/AsbCloudApp/Data/WellOperation/WellOperationDto.cs b/AsbCloudApp/Data/WellOperation/WellOperationDto.cs new file mode 100644 index 00000000..17015451 --- /dev/null +++ b/AsbCloudApp/Data/WellOperation/WellOperationDto.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace AsbCloudApp.Data.WellOperation; + +public class WellOperationDto : ItemInfoDto, + IId, + IWellRelated, + IValidatableObject +{ + /// <inheritdoc/> + [Required] + public int Id { get; set; } + + /// <inheritdoc/> + [Required] + public int IdWell { get; set; } + + /// <summary> + /// Id секции скважины + /// </summary> + public int IdWellSectionType { get; set; } + + /// <summary> + /// 0 = план или 1 = факт или прогноз = 2 + /// </summary> + [Required] + public int IdType { get; set; } + + /// <summary> + /// id категории операции + /// </summary> + public int IdCategory { get; set; } + + /// <summary> + /// Глубина на начало операции, м + /// </summary> + public double DepthStart { get; set; } + + /// <summary> + /// Глубина после завершения операции, м + /// </summary> + [Required] + [Range(0, 50_000)] + public double DepthEnd { get; set; } + + /// <summary> + /// Дата начала операции + /// </summary> + [Required] + public DateTimeOffset DateStart { get; set; } + + /// <summary> + /// Продолжительность, часы + /// </summary> + public double DurationHours { get; set; } + + /// <summary> + /// Наименование секции + /// </summary> + public string? WellSectionTypeCaption { get; set; } + + /// <summary> + /// Наименование категории + /// </summary> + public string? OperationCategoryName { get; set; } + + /// <summary> + /// id плановой операции для сопоставления + /// </summary> + public int? IdPlan { get; set; } + + /// <summary> + /// Ключ родителя у категории + /// </summary> + public int? IdParentCategory { get; set; } + + /// <summary> + /// дополнительная информация по операции + /// </summary> + [StringLength(8192)] + public string? CategoryInfo { get; set; } + + /// <summary> + /// Кол-во дней от даты начала первой плановой (а если её нет, то фактической) операции + /// </summary> + [Required] + public double Day { get; set; } + + /// <summary> + /// Кол-во часов НПВ от даты начала первой плановой (а если её нет, то фактической) операции + /// </summary> + [Required] + public double NptHours { get; set; } + + /// <summary> + /// Полезный комментарий + /// </summary> + [StringLength(4096, ErrorMessage = "Комментарий не может быть длиннее 4096 символов")] + public string? Comment { get; set; } + + /// <summary> + /// Валидация даты + /// </summary> + /// <param name="validationContext"></param> + /// <returns></returns> + public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) + { + var gtDate = new DateTimeOffset(2010, 1, 1, 0, 0, 0, TimeSpan.Zero); + if (DateStart <= gtDate) + yield return new ValidationResult( + $"{nameof(DateStart)}: DateStart не может быть меньше {gtDate}", + new[] { nameof(DateStart) }); + } +} \ No newline at end of file diff --git a/AsbCloudApp/Data/WellOperationDataDto.cs b/AsbCloudApp/Data/WellOperationDataDto.cs deleted file mode 100644 index 874bd65c..00000000 --- a/AsbCloudApp/Data/WellOperationDataDto.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace AsbCloudApp.Data -{ - /// Операция на скважине - public class WellOperationDataDto : IWellRelated - { - /// <inheritdoc/> - public int IdWell { get; set; } - - /// <summary> - /// id секции скважины - /// </summary> - public int IdWellSectionType { get; set; } - - /// <summary> - /// id категории операции - /// </summary> - public int IdCategory { get; set; } - - /// <summary> - /// Глубина на начало операции, м - /// </summary> - public double DepthStart { get; set; } - - /// <summary> - /// Продолжительность, часы - /// </summary> - public double DurationHours { get; set; } - - /// <summary> - /// Наименование секции - /// </summary> - public string WellSectionTypeCaption { get; set; } = string.Empty; - - /// <summary> - /// Наименование категории - /// </summary> - public string OperationCategoryName { get; set; } = string.Empty; - } -} diff --git a/AsbCloudApp/Data/WellOperationDto.cs b/AsbCloudApp/Data/WellOperationDto.cs deleted file mode 100644 index 725debfd..00000000 --- a/AsbCloudApp/Data/WellOperationDto.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; - -namespace AsbCloudApp.Data -{ - /// <summary> - /// Операции на скважине (заведенные пользователем) - /// </summary> - public class WellOperationDto : ItemInfoDto, IId, IWellRelated, IValidatableObject - { - /// <inheritdoc/> - [Required] - public int Id { get; set; } - - /// <inheritdoc/> - [Required] - public int IdWell { get; set; } - - /// <summary> - /// id секции скважины - /// </summary> - [Required] - public int IdWellSectionType { get; set; } - - /// <summary> - /// название секции скважины - /// </summary> - public string? WellSectionTypeName { get; set; } - - /// <summary> - /// id категории операции - /// </summary> - [Required] - [Range(5000, int.MaxValue)] - public int IdCategory { get; set; } - - /// <summary> - /// id плановой операции для сопоставления - /// </summary> - public int? IdPlan { get; set; } - - /// <summary> - /// название категории операции - /// </summary> - public string? CategoryName { get; set; } - - /// <summary> - /// ключ родителя у категории - /// </summary> - public int? IdParentCategory { get; set; } - - /// <summary> - /// дополнительная информация по операции - /// </summary> - [StringLength(8192)] - public string? CategoryInfo { get; set; } - - /// <summary> - /// 0 = план или 1 = факт или прогноз = 2 - /// </summary> - [Required] - public int IdType { get; set; } - - /// <summary> - /// Глубина на начало операции, м - /// </summary> - [Required] - [Range(0, 50_000)] - public double DepthStart { get; set; } - - /// <summary> - /// Глубина после завершения операции, м - /// </summary> - [Required] - [Range(0, 50_000)] - public double DepthEnd { get; set; } - - /// <summary> - /// Кол-во дней от даты начала первой плановой (а если её нет, то фактической) операции - /// </summary> - [Required] - public double Day { get; set; } - - /// <summary> - /// Кол-во часов НПВ от даты начала первой плановой (а если её нет, то фактической) операции - /// </summary> - [Required] - public double NptHours { get; set; } - - /// <summary> - /// Дата начала операции - /// </summary> - [Required] - public DateTimeOffset DateStart { get; set; } - - /// <summary> - /// Продолжительность, часы - /// </summary> - [Required] - [Range(0, 50)] - public double DurationHours { get; set; } - - /// <summary> - /// Полезный комментарий - /// </summary> - [StringLength(4096, ErrorMessage = "Комментарий не может быть длиннее 4096 символов")] - public string? Comment { get; set; } - - /// <summary> - /// Валидация даты - /// </summary> - /// <param name="validationContext"></param> - /// <returns></returns> - public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) - { - var gtDate = new DateTimeOffset(2010, 1, 1, 0, 0, 0, TimeSpan.Zero); - if (DateStart <= gtDate) - yield return new ValidationResult( - $"{nameof(DateStart)}: DateStart не может быть меньше {gtDate}", - new[] { nameof(DateStart) }); - } - } -} diff --git a/AsbCloudApp/Data/WellOperationPlanDto.cs b/AsbCloudApp/Data/WellOperationPlanDto.cs deleted file mode 100644 index 5c1bac9f..00000000 --- a/AsbCloudApp/Data/WellOperationPlanDto.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; - -namespace AsbCloudApp.Data -{ - /// <summary> - /// класс, который хранит список плановых операций для сопоставления - /// и даты последней сопоставленной плановой операции - /// </summary> -#nullable enable - public class WellOperationPlanDto - { - /// <summary> - /// коллекция плановых операций - /// </summary> - [Required] - public IEnumerable<WellOperationDto> WellOperationsPlan { get; set; } = Enumerable.Empty<WellOperationDto>(); - - /// <summary> - /// дата последней сопоставленной плановой операции - /// </summary> - public DateTime? DateLastAssosiatedPlanOperation { get; set; } - - } - -} diff --git a/AsbCloudApp/Repositories/IWellOperationCategoryRepository.cs b/AsbCloudApp/Repositories/IWellOperationCategoryRepository.cs index 4e18c231..ecf915cd 100644 --- a/AsbCloudApp/Repositories/IWellOperationCategoryRepository.cs +++ b/AsbCloudApp/Repositories/IWellOperationCategoryRepository.cs @@ -1,5 +1,5 @@ -using AsbCloudApp.Data; -using System.Collections.Generic; +using System.Collections.Generic; +using AsbCloudApp.Data.WellOperation; namespace AsbCloudApp.Repositories { diff --git a/AsbCloudApp/Repositories/IWellOperationRepository.cs b/AsbCloudApp/Repositories/IWellOperationRepository.cs index dd39ce52..0409969e 100644 --- a/AsbCloudApp/Repositories/IWellOperationRepository.cs +++ b/AsbCloudApp/Repositories/IWellOperationRepository.cs @@ -1,9 +1,9 @@ using AsbCloudApp.Data; -using AsbCloudApp.Requests; -using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Data.WellOperation; +using AsbCloudApp.Requests; namespace AsbCloudApp.Repositories { @@ -17,24 +17,8 @@ namespace AsbCloudApp.Repositories /// </summary> /// <returns></returns> IEnumerable<WellSectionTypeDto> GetSectionTypes(); - - /// <summary> - /// список плановых операций для сопоставления - /// <param name="idWell"></param> - /// <param name="currentDate"></param> - /// <param name="token"></param> - /// </summary> - /// <returns></returns> - Task<WellOperationPlanDto> GetOperationsPlanAsync(int idWell, DateTime? currentDate, CancellationToken token); - - /// <summary> - /// дата/время первой операции по скважине - /// </summary> - /// <param name="idWell"></param> - /// <returns></returns> - DateTimeOffset? FirstOperationDate(int idWell); - - /// <summary> + + /// <summary> /// Получить страницу списка операций /// </summary> /// <param name="request"></param> @@ -42,15 +26,7 @@ namespace AsbCloudApp.Repositories /// <returns></returns> Task<IEnumerable<WellOperationDto>> GetAsync(WellOperationRequest request, CancellationToken token); - /// <summary> - /// Получить список операций по запросу - /// </summary> - /// <param name="request"></param> - /// <param name="token"></param> - /// <returns></returns> - Task<IEnumerable<WellOperationDataDto>> GetAsync(WellsOperationRequest request, CancellationToken token); - - /// <summary> + /// <summary> /// Получить страницу списка операций /// </summary> /// <param name="request"></param> @@ -58,31 +34,22 @@ namespace AsbCloudApp.Repositories /// <returns></returns> Task<PaginationContainer<WellOperationDto>> GetPageAsync(WellOperationRequest request, CancellationToken token); - /// <summary> - /// Получить операцию по id - /// </summary> - /// <param name="id"></param> - /// <param name="token"></param> - /// <returns></returns> - Task<WellOperationDto?> GetOrDefaultAsync(int id, CancellationToken token); - - /// <summary> + /// <summary> /// Получить статистику операции по скважине с группировкой по категориям /// </summary> /// <param name="request"></param> /// <param name="token"></param> /// <returns></returns> - Task<IEnumerable<WellGroupOpertionDto>> GetGroupOperationsStatAsync( - WellOperationRequest request, - CancellationToken token); + Task<IEnumerable<WellGroupOpertionDto>> GetGroupOperationsStatAsync(WellOperationRequest request, CancellationToken token); - /// <summary> - /// Добавить несколько операций за один раз - /// </summary> - /// <param name="wellOperationDtos"></param> - /// <param name="token"></param> - /// <returns></returns> - Task<int> InsertRangeAsync(IEnumerable<WellOperationDto> wellOperationDtos, CancellationToken token); + /// <summary> + /// Добавить несколько операций + /// </summary> + /// <param name="dtos"></param> + /// <param name="deleteBeforeInsert"></param> + /// <param name="token"></param> + /// <returns></returns> + Task<int> InsertRangeAsync(IEnumerable<WellOperationDto> dtos, bool deleteBeforeInsert, CancellationToken token); /// <summary> /// Обновить существующую операцию @@ -90,7 +57,7 @@ namespace AsbCloudApp.Repositories /// <param name="dto"></param> /// <param name="token"></param> /// <returns></returns> - Task<int> UpdateAsync(WellOperationDto dto, CancellationToken token); + Task<int> UpdateRangeAsync(IEnumerable<WellOperationDto> dtos, CancellationToken token); /// <summary> /// Удалить операции по id @@ -98,7 +65,7 @@ namespace AsbCloudApp.Repositories /// <param name="ids"></param> /// <param name="token"></param> /// <returns></returns> - Task<int> DeleteAsync(IEnumerable<int> ids, CancellationToken token); + Task<int> DeleteRangeAsync(IEnumerable<int> ids, CancellationToken token); /// <summary> /// Получить секции скважин из операций ГГД. Секцие поделены на плановые и фактические. @@ -115,24 +82,6 @@ namespace AsbCloudApp.Repositories /// <param name="idType"></param> /// <param name="cancellationToken"></param> /// <returns></returns> - Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, int idType, CancellationToken cancellationToken); - - /// <summary> - /// Удаление полных дубликатов операций по всем скважинам - /// </summary> - /// <param name="onProgressCallback"></param> - /// <param name="token"></param> - /// <returns></returns> - Task<int> RemoveDuplicates(Action<string, double?> onProgressCallback, CancellationToken token); - - /// <summary> - /// Усечение пересекающейся последующей операции по дате и глубине забоя - /// </summary> - /// <param name="geDate">Фильтр по дате. Если хоть одна операция попадет в в фильтр, то будет обработана вся скважина, а не только эта операция</param> - /// <param name="leDate">Фильтр по дате. Если хоть одна операция попадет в в фильтр, то будет обработана вся скважина, а не только эта операция</param> - /// <param name="onProgressCallback"></param> - /// <param name="token"></param> - /// <returns></returns> - Task<int> TrimOverlapping(DateTimeOffset? geDate, DateTimeOffset leDate, Action<string, double?> onProgressCallback, CancellationToken token); - } + Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, int idType, CancellationToken cancellationToken); + } } \ No newline at end of file diff --git a/AsbCloudApp/Requests/ExportOptions/WellOperationExportRequest.cs b/AsbCloudApp/Requests/ExportOptions/WellOperationExportRequest.cs new file mode 100644 index 00000000..facbba72 --- /dev/null +++ b/AsbCloudApp/Requests/ExportOptions/WellOperationExportRequest.cs @@ -0,0 +1,20 @@ +namespace AsbCloudApp.Requests.ExportOptions; + +/// <summary> +/// Параметры экспорта ГГД +/// </summary> +public class WellOperationExportRequest : WellRelatedExportRequest +{ + /// <inheritdoc /> + public WellOperationExportRequest(int idWell, + int idType) + : base(idWell) + { + IdType = idType; + } + + /// <summary> + /// Тип операций + /// </summary> + public int IdType { get; } +} \ No newline at end of file diff --git a/AsbCloudApp/Requests/FileRequest.cs b/AsbCloudApp/Requests/FileRequest.cs index 7ea84c7e..403c0655 100644 --- a/AsbCloudApp/Requests/FileRequest.cs +++ b/AsbCloudApp/Requests/FileRequest.cs @@ -33,12 +33,12 @@ namespace AsbCloudApp.Requests /// <summary> /// Дата начала периода /// </summary> - public DateTime? Begin { get; set; } + public DateTimeOffset? Begin { get; set; } /// <summary> /// Дата окончания периода /// </summary> - public DateTime? End { get; set; } + public DateTimeOffset? End { get; set; } /// <summary> /// Признак удаления diff --git a/AsbCloudApp/Requests/LimitingParameterRequest.cs b/AsbCloudApp/Requests/LimitingParameterRequest.cs index 31fb02f0..4e1b5d98 100644 --- a/AsbCloudApp/Requests/LimitingParameterRequest.cs +++ b/AsbCloudApp/Requests/LimitingParameterRequest.cs @@ -17,12 +17,12 @@ namespace AsbCloudApp.Requests /// <summary> /// Больше или равно дате /// </summary> - public DateTime? GtDate { get; set; } + public DateTimeOffset? GtDate { get; set; } /// <summary> /// Меньше или равно дате /// </summary> - public DateTime? LtDate { get; set; } + public DateTimeOffset? LtDate { get; set; } /// <summary> /// Больше или равно глубины забоя diff --git a/AsbCloudApp/Requests/MessageRequest.cs b/AsbCloudApp/Requests/MessageRequest.cs index 1bfba1a2..a474c7b9 100644 --- a/AsbCloudApp/Requests/MessageRequest.cs +++ b/AsbCloudApp/Requests/MessageRequest.cs @@ -17,12 +17,12 @@ namespace AsbCloudApp.Requests /// <summary> /// начальная дата /// </summary> - public DateTime? Begin { get; set; } + public DateTimeOffset? Begin { get; set; } /// <summary> /// конечная дата /// </summary> - public DateTime? End { get; set; } + public DateTimeOffset? End { get; set; } /// <summary> /// строка поиска diff --git a/AsbCloudApp/Requests/NotificationDeleteRequest.cs b/AsbCloudApp/Requests/NotificationDeleteRequest.cs index ec2026f3..56921d70 100644 --- a/AsbCloudApp/Requests/NotificationDeleteRequest.cs +++ b/AsbCloudApp/Requests/NotificationDeleteRequest.cs @@ -15,10 +15,10 @@ public class NotificationDeleteRequest /// <summary> /// Меньше или равно дате отправки /// </summary> - public DateTime? LtSentDate { get; set; } + public DateTimeOffset? LtSentDate { get; set; } /// <summary> /// Меньше или равно дате прочтения /// </summary> - public DateTime? LtReadDate { get; set; } + public DateTimeOffset? LtReadDate { get; set; } } \ No newline at end of file diff --git a/AsbCloudApp/Requests/ParserOptions/WellOperationParserRequest.cs b/AsbCloudApp/Requests/ParserOptions/WellOperationParserRequest.cs new file mode 100644 index 00000000..efb9aad2 --- /dev/null +++ b/AsbCloudApp/Requests/ParserOptions/WellOperationParserRequest.cs @@ -0,0 +1,29 @@ +using AsbCloudApp.Data; + +namespace AsbCloudApp.Requests.ParserOptions; + +/// <summary> +/// Параметры парсинга ГГД +/// </summary> +public class WellOperationParserRequest : WellRelatedParserRequest +{ + /// <inheritdoc /> + public WellOperationParserRequest(int idWell, + int idType, + SimpleTimezoneDto wellTimezone) + : base(idWell) + { + IdType = idType; + WellTimezone = wellTimezone; + } + + /// <summary> + /// Тип операции + /// </summary> + public int IdType { get; } + + /// <summary> + /// Часовой пояс в котором находится скважина + /// </summary> + public SimpleTimezoneDto WellTimezone { get; } +} \ No newline at end of file diff --git a/AsbCloudApp/Requests/ProcessMapPlanRequest.cs b/AsbCloudApp/Requests/ProcessMapPlanRequest.cs index b614b8c3..b3247ce2 100644 --- a/AsbCloudApp/Requests/ProcessMapPlanRequest.cs +++ b/AsbCloudApp/Requests/ProcessMapPlanRequest.cs @@ -20,5 +20,5 @@ public class ProcessMapPlanRequest /// <summary> /// Дата обновления /// </summary> - public DateTime? UpdateFrom { get; set; } + public DateTimeOffset? UpdateFrom { get; set; } } \ No newline at end of file diff --git a/AsbCloudApp/Requests/ReportParametersRequest.cs b/AsbCloudApp/Requests/ReportParametersRequest.cs index 57b83e4d..74bc358a 100644 --- a/AsbCloudApp/Requests/ReportParametersRequest.cs +++ b/AsbCloudApp/Requests/ReportParametersRequest.cs @@ -24,12 +24,12 @@ public class ReportParametersRequest: IValidatableObject /// <summary> /// Дата начала интервала /// </summary> - public DateTime Begin { get; set; } = default; + public DateTimeOffset Begin { get; set; } = default; /// <summary> /// Дата окончания интервала /// </summary> - public DateTime End { get; set; } = default; + public DateTimeOffset End { get; set; } = default; /// <inheritdoc/> public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) @@ -37,7 +37,7 @@ public class ReportParametersRequest: IValidatableObject if (End < Begin) yield return new("End mast be less then begin"); - if (Begin < new DateTime(2000, 1, 1)) + if (Begin < new DateTimeOffset(2000, 1, 1, 0, 0, 0, TimeSpan.Zero)) yield return new("Begin mast be > 2000-1-1"); } } \ No newline at end of file diff --git a/AsbCloudApp/Requests/SubsystemRequest.cs b/AsbCloudApp/Requests/SubsystemRequest.cs index 23a7e70a..08b980ab 100644 --- a/AsbCloudApp/Requests/SubsystemRequest.cs +++ b/AsbCloudApp/Requests/SubsystemRequest.cs @@ -9,7 +9,7 @@ namespace AsbCloudApp.Requests /// </summary> public class SubsystemRequest: RequestBase, IValidatableObject { - private static readonly DateTime validationMinDate = new DateTime(2020,01,01,0,0,0,DateTimeKind.Utc); + private static readonly DateTimeOffset validationMinDate = new DateTimeOffset(2020,01,01,0,0,0, TimeSpan.Zero); /// <summary> /// идентификатор скважины diff --git a/AsbCloudApp/Requests/TrajectoryRequest.cs b/AsbCloudApp/Requests/TrajectoryRequest.cs index 954879bc..35eca8c3 100644 --- a/AsbCloudApp/Requests/TrajectoryRequest.cs +++ b/AsbCloudApp/Requests/TrajectoryRequest.cs @@ -15,10 +15,10 @@ public class TrajectoryRequest : RequestBase /// <summary> /// Больше или равно дате /// </summary> - public DateTime? GeDate { get; set; } + public DateTimeOffset? GeDate { get; set; } /// <summary> /// Меньше или равно дате /// </summary> - public DateTime? LeDate { get; set; } + public DateTimeOffset? LeDate { get; set; } } \ No newline at end of file diff --git a/AsbCloudApp/Requests/WellOperationRequest.cs b/AsbCloudApp/Requests/WellOperationRequest.cs index 1d190018..356ef52d 100644 --- a/AsbCloudApp/Requests/WellOperationRequest.cs +++ b/AsbCloudApp/Requests/WellOperationRequest.cs @@ -1,112 +1,84 @@ using System; using System.Collections.Generic; -namespace AsbCloudApp.Requests +namespace AsbCloudApp.Requests; + +/// <summary> +/// Запрос получения ГГД +/// </summary> +public class WellOperationRequestBase : RequestBase { - /// <summary> - /// параметры для запроса списка операций - /// </summary> - public class WellOperationRequestBase : RequestBase - { - /// <summary> - /// фильтр по дате начала операции - /// </summary> - public DateTime? GeDate { get; set; } + /// <summary> + /// Больше или равно дате начала операции + /// </summary> + public DateTimeOffset? GeDate { get; set; } - /// <summary> - /// фильтр по дате окончания операции - /// </summary> - public DateTime? LtDate { get; set; } + /// <summary> + /// Меньше или равно дате окончания операции + /// </summary> + public DateTimeOffset? LeDate { get; set; } - /// <summary> - /// фильтр. Больше или равно глубины скважины на начало операции. - /// </summary> - public double? GeDepth { get; set; } + /// <summary> + /// Больше или равно глубины скважины на начало операции. + /// </summary> + public double? GeDepth { get; set; } - /// <summary> - /// фильтр. Меньше или равно глубины скважины на конец операции. - /// </summary> - public double? LeDepth { get; set; } + /// <summary> + /// Меньше или равно глубины скважины на конец операции. + /// </summary> + public double? LeDepth { get; set; } - /// <summary> - /// фильтр по списку id категорий операции - /// </summary> - public IEnumerable<int>? OperationCategoryIds { get; set; } + /// <summary> + /// Идентификаторы категорий операции + /// </summary> + public IEnumerable<int>? OperationCategoryIds { get; set; } - /// <summary> - /// фильтр по план = 0, факт = 1 - /// </summary> - public int? OperationType { get; set; } + /// <summary> + /// Тип операций + /// <list type="bullet"> + /// <item>0 - плановая операция</item> + /// <item>1 - фактическая операция</item> + /// </list> + /// </summary> + public int? OperationType { get; set; } - /// <summary> - /// фильтр по списку id конструкций секции - /// </summary> - public IEnumerable<int>? SectionTypeIds { get; set; } - - /// <summary> - /// Параметры для запроса списка операций. - /// Базовый конструктор - /// </summary> - public WellOperationRequestBase() - { } - - /// <summary> - /// Параметры для запроса списка операций. - /// Копирующий конструктор - /// </summary> - /// <param name="request"></param> - public WellOperationRequestBase(WellOperationRequestBase request) - { - GeDepth = request.GeDepth; - LeDepth = request.LeDepth; - GeDate = request.GeDate; - LtDate = request.LtDate; - - OperationCategoryIds = request.OperationCategoryIds; - OperationType = request.OperationType; - SectionTypeIds = request.SectionTypeIds; - - Skip = request.Skip; - Take = request.Take; - SortFields = request.SortFields; - } - } - - /// <summary> - /// Параметры для запроса списка операций (с id скважины) - /// </summary> - public class WellOperationRequest : WellOperationRequestBase - { - /// <summary> - /// id скважины - /// </summary> - public int IdWell { get; set; } - - /// <summary> - /// ctor - /// </summary> - public WellOperationRequest() { } - - /// <summary> - /// копирующий конструктор - /// </summary> - /// <param name="request"></param> - /// <param name="idWell"></param> - public WellOperationRequest(WellOperationRequestBase request, int idWell) - :base(request) - { - IdWell = idWell; - } - } - - /// <summary> - /// Параметры для запроса списка операций (с массивом id скважин) - /// </summary> - public class WellsOperationRequest : WellOperationRequestBase - { - /// <summary> - /// ids скважин - /// </summary> - public IEnumerable<int> IdsWell { get; set; } = null!; - } + /// <summary> + /// Идентификаторы конструкций секции + /// </summary> + public IEnumerable<int>? SectionTypeIds { get; set; } } + +/// <summary> +/// Запрос получения ГГД с идентификаторами скважин +/// </summary> +public class WellOperationRequest : WellOperationRequestBase +{ + /// <inheritdoc /> + public WellOperationRequest(IEnumerable<int> idsWell) + { + IdsWell = idsWell; + } + + /// <inheritdoc /> + public WellOperationRequest(WellOperationRequestBase request, IEnumerable<int> idsWell) + : this(idsWell) + { + GeDepth = request.GeDepth; + LeDepth = request.LeDepth; + GeDate = request.GeDate; + LeDate = request.LeDate; + + OperationCategoryIds = request.OperationCategoryIds; + OperationType = request.OperationType; + SectionTypeIds = request.SectionTypeIds; + + Skip = request.Skip; + Take = request.Take; + SortFields = request.SortFields; + } + + /// <summary> + /// Идентификаторы скважин + /// </summary> + public IEnumerable<int>? IdsWell { get; } +} \ No newline at end of file diff --git a/AsbCloudApp/Services/DailyReport/IDailyReportService.cs b/AsbCloudApp/Services/DailyReport/IDailyReportService.cs index f0318025..b39375a6 100644 --- a/AsbCloudApp/Services/DailyReport/IDailyReportService.cs +++ b/AsbCloudApp/Services/DailyReport/IDailyReportService.cs @@ -42,12 +42,4 @@ public interface IDailyReportService /// <param name="cancellationToken"></param> /// <returns></returns> Task<PaginationContainer<DailyReportDto>> GetAsync(int idWell, FileReportRequest request, CancellationToken cancellationToken); - - /// <summary> - /// Получить диапазон дат по которым возможно сформировать суточный отчёты - /// </summary> - /// <param name="idWell"></param> - /// <param name="cancellationToken"></param> - /// <returns></returns> - Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, CancellationToken cancellationToken); } \ No newline at end of file diff --git a/AsbCloudApp/Services/IExportService.cs b/AsbCloudApp/Services/Export/IExportService.cs similarity index 70% rename from AsbCloudApp/Services/IExportService.cs rename to AsbCloudApp/Services/Export/IExportService.cs index b921fec5..ddfd50f9 100644 --- a/AsbCloudApp/Services/IExportService.cs +++ b/AsbCloudApp/Services/Export/IExportService.cs @@ -3,12 +3,12 @@ using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Requests.ExportOptions; -namespace AsbCloudApp.Services; +namespace AsbCloudApp.Services.Export; /// <summary> /// Экспорт данных /// </summary> -public interface IExportService<in TOptions> +public interface IExportService<in TOptions> : IExportService where TOptions : IExportOptionsRequest { /// <summary> @@ -18,4 +18,12 @@ public interface IExportService<in TOptions> /// <param name="token"></param> /// <returns></returns> Task<(string FileName, Stream File)> ExportAsync(TOptions options, CancellationToken token); +} + +/// <summary> +/// Экспорт данных +/// </summary> +public interface IExportService +{ + } \ No newline at end of file diff --git a/AsbCloudApp/Services/Export/IExportServiceFactory.cs b/AsbCloudApp/Services/Export/IExportServiceFactory.cs new file mode 100644 index 00000000..fb6b5fc9 --- /dev/null +++ b/AsbCloudApp/Services/Export/IExportServiceFactory.cs @@ -0,0 +1,20 @@ +using AsbCloudApp.Requests.ExportOptions; + +namespace AsbCloudApp.Services.Export; + +/// <summary> +/// Фабрика создания сервисов для экспорта +/// </summary> +/// <typeparam name="TId"></typeparam> +public interface IExportServiceFactory<in TId> + where TId : struct +{ + /// <summary> + /// Создать сервис экспорта + /// </summary> + /// <param name="id"></param> + /// <typeparam name="TOptions"></typeparam> + /// <returns></returns> + IExportService<TOptions> CreateExportService<TOptions>(TId id) + where TOptions : IExportOptionsRequest; +} \ No newline at end of file diff --git a/AsbCloudApp/Services/IDetectedOperationService.cs b/AsbCloudApp/Services/IDetectedOperationService.cs index 998032ba..208706f7 100644 --- a/AsbCloudApp/Services/IDetectedOperationService.cs +++ b/AsbCloudApp/Services/IDetectedOperationService.cs @@ -1,10 +1,10 @@ using System; -using AsbCloudApp.Data; using AsbCloudApp.Data.DetectedOperation; using AsbCloudApp.Requests; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Data.WellOperation; namespace AsbCloudApp.Services { diff --git a/AsbCloudApp/Services/IOperationsStatService.cs b/AsbCloudApp/Services/IOperationsStatService.cs index a92d0553..f5ec7c7c 100644 --- a/AsbCloudApp/Services/IOperationsStatService.cs +++ b/AsbCloudApp/Services/IOperationsStatService.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Data.WellOperation; namespace AsbCloudApp.Services { diff --git a/AsbCloudApp/Services/IReportService.cs b/AsbCloudApp/Services/IReportService.cs index 5f992a20..4b259240 100644 --- a/AsbCloudApp/Services/IReportService.cs +++ b/AsbCloudApp/Services/IReportService.cs @@ -46,7 +46,7 @@ namespace AsbCloudApp.Services /// <param name="stepSeconds"></param> /// <param name="format"></param> /// <returns></returns> - int GetReportPagesCount(int idWell, DateTime begin, DateTime end, + int GetReportPagesCount(int idWell, DateTimeOffset begin, DateTimeOffset end, int stepSeconds, int format); /// <summary> diff --git a/AsbCloudApp/Services/IScheduleService.cs b/AsbCloudApp/Services/IScheduleService.cs index 5a28b4c2..81c0d385 100644 --- a/AsbCloudApp/Services/IScheduleService.cs +++ b/AsbCloudApp/Services/IScheduleService.cs @@ -19,7 +19,7 @@ namespace AsbCloudApp.Services /// <param name="workTime"></param> /// <param name="token"></param> /// <returns></returns> - Task<IEnumerable<ScheduleDto>> GetAsync(int idWell, DateTime workTime, CancellationToken token); + Task<IEnumerable<ScheduleDto>> GetAsync(int idWell, DateTimeOffset workTime, CancellationToken token); /// <summary> /// получить бурильщика по idWell и времени @@ -28,7 +28,7 @@ namespace AsbCloudApp.Services /// <param name="workTime"></param> /// <param name="token"></param> /// <returns></returns> - Task<DrillerDto?> GetOrDefaultDrillerAsync(int idWell, DateTime workTime, CancellationToken token); + Task<DrillerDto?> GetOrDefaultDrillerAsync(int idWell, DateTimeOffset workTime, CancellationToken token); /// <summary> /// Получить расписание смен diff --git a/AsbCloudApp/Services/IWellCompositeOperationService.cs b/AsbCloudApp/Services/IWellCompositeOperationService.cs index 94ba1f93..96dbcf2b 100644 --- a/AsbCloudApp/Services/IWellCompositeOperationService.cs +++ b/AsbCloudApp/Services/IWellCompositeOperationService.cs @@ -1,7 +1,7 @@ -using AsbCloudApp.Data; -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Data.WellOperation; namespace AsbCloudApp.Services { @@ -16,6 +16,6 @@ namespace AsbCloudApp.Services /// <param name="idsWells"></param> /// <param name="token"></param> /// <returns></returns> - Task<List<Dictionary<int, WellOperationDataDto>>> GetAsync(IEnumerable<int> idsWells, CancellationToken token); + Task<IEnumerable<Dictionary<int, WellOperationDto>>> GetAsync(IEnumerable<int> idsWells, CancellationToken token); } } diff --git a/AsbCloudApp/Services/IWellService.cs b/AsbCloudApp/Services/IWellService.cs index edea98ae..4279f587 100644 --- a/AsbCloudApp/Services/IWellService.cs +++ b/AsbCloudApp/Services/IWellService.cs @@ -72,7 +72,7 @@ namespace AsbCloudApp.Services /// </summary> /// <param name="idWell"></param> /// <returns></returns> - DateTime GetLastTelemetryDate(int idWell); + DateTimeOffset GetLastTelemetryDate(int idWell); //TODO: выяснить и удалить отсюда /// <summary> diff --git a/AsbCloudApp/Services/Notifications/NotificationService.cs b/AsbCloudApp/Services/Notifications/NotificationService.cs index d703ffb4..97b8bfb5 100644 --- a/AsbCloudApp/Services/Notifications/NotificationService.cs +++ b/AsbCloudApp/Services/Notifications/NotificationService.cs @@ -49,7 +49,7 @@ public class NotificationService var notification = new NotificationDto { IdUser = request.IdUser, - RegistrationDate = DateTime.UtcNow, + RegistrationDate = DateTimeOffset.UtcNow, IdNotificationCategory = notificationCategory.Id, Title = request.Title, Message = request.Message, @@ -71,7 +71,7 @@ public class NotificationService Console.WriteLine(ex.Message); } - notification.SentDate = DateTime.UtcNow; + notification.SentDate = DateTimeOffset.UtcNow; await notificationRepository.UpdateAsync(notification, cancellationToken); } @@ -92,7 +92,7 @@ public class NotificationService if(isRead && !notification.SentDate.HasValue) throw new ArgumentInvalidException(nameof(isRead), "Уведомление не может быть прочитано"); - notification.ReadDate = isRead ? DateTime.UtcNow : null; + notification.ReadDate = isRead ? DateTimeOffset.UtcNow : null; await notificationRepository.UpdateAsync(notification, cancellationToken); @@ -119,7 +119,7 @@ public class NotificationService var tasks = notifications.Select(notification => { - notification.SentDate = DateTime.UtcNow; + notification.SentDate = DateTimeOffset.UtcNow; return notificationRepository.UpdateAsync(notification, cancellationToken); }); diff --git a/AsbCloudApp/Services/Parsers/IParserFactory.cs b/AsbCloudApp/Services/Parsers/IParserFactory.cs new file mode 100644 index 00000000..e0fc1aa2 --- /dev/null +++ b/AsbCloudApp/Services/Parsers/IParserFactory.cs @@ -0,0 +1,23 @@ +using AsbCloudApp.Data; +using AsbCloudApp.Requests.ParserOptions; + +namespace AsbCloudApp.Services.Parsers; + +/// <summary> +/// Фабрика для создания сервиса парсинга +/// </summary> +/// <typeparam name="TId"></typeparam> +/// <typeparam name="TDto"></typeparam> +public interface IParserFactory<in TId, TDto> + where TId : struct + where TDto : class, IId +{ + /// <summary> + /// Создать парсер + /// </summary> + /// <param name="id"></param> + /// <typeparam name="TOptions"></typeparam> + /// <returns></returns> + IParserService<TDto, TOptions> CreateParser<TOptions>(TId id) + where TOptions : IParserOptionsRequest; +} \ No newline at end of file diff --git a/AsbCloudApp/Services/IParserService.cs b/AsbCloudApp/Services/Parsers/IParserService.cs similarity index 76% rename from AsbCloudApp/Services/IParserService.cs rename to AsbCloudApp/Services/Parsers/IParserService.cs index 89212ba7..672c9e2b 100644 --- a/AsbCloudApp/Services/IParserService.cs +++ b/AsbCloudApp/Services/Parsers/IParserService.cs @@ -2,14 +2,14 @@ using System.IO; using AsbCloudApp.Data; using AsbCloudApp.Requests.ParserOptions; -namespace AsbCloudApp.Services; +namespace AsbCloudApp.Services.Parsers; /// <summary> /// Сервис парсинга /// </summary> /// <typeparam name="TDto"></typeparam> /// <typeparam name="TOptions"></typeparam> -public interface IParserService<TDto, in TOptions> +public interface IParserService<TDto, in TOptions> : IParserService where TDto : class, IId where TOptions : IParserOptionsRequest { @@ -26,4 +26,11 @@ public interface IParserService<TDto, in TOptions> /// </summary> /// <returns></returns> Stream GetTemplateFile(); +} + +/// <summary> +/// Сервис парсинга +/// </summary> +public interface IParserService +{ } \ No newline at end of file diff --git a/AsbCloudApp/Services/WellOperationImport/IWellOperationExcelParser.cs b/AsbCloudApp/Services/WellOperationImport/IWellOperationExcelParser.cs deleted file mode 100644 index 7a695beb..00000000 --- a/AsbCloudApp/Services/WellOperationImport/IWellOperationExcelParser.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.IO; -using AsbCloudApp.Data.WellOperationImport; -using AsbCloudApp.Data.WellOperationImport.Options; - -namespace AsbCloudApp.Services.WellOperationImport; - -/// <summary> -/// Парсинг операций из excel файла -/// </summary> -public interface IWellOperationExcelParser<in TOptions> - where TOptions : IWellOperationImportOptions -{ - /// <summary> - /// Метод парсинга документа - /// </summary> - /// <param name="stream"></param> - /// <param name="options"></param> - /// <returns></returns> - SheetDto Parse(Stream stream, TOptions options); -} \ No newline at end of file diff --git a/AsbCloudApp/Services/WellOperationImport/IWellOperationExportService.cs b/AsbCloudApp/Services/WellOperationImport/IWellOperationExportService.cs deleted file mode 100644 index 9b0a96ac..00000000 --- a/AsbCloudApp/Services/WellOperationImport/IWellOperationExportService.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace AsbCloudApp.Services.WellOperationImport; - -/// <summary> -/// Экспорт ГГД -/// </summary> -public interface IWellOperationExportService -{ - /// <summary> - /// Скачать в excel - /// </summary> - /// <param name="idWell"></param> - /// <param name="cancellationToken"></param> - /// <returns></returns> - Task<Stream> ExportAsync(int idWell, CancellationToken cancellationToken); -} \ No newline at end of file diff --git a/AsbCloudApp/Services/WellOperationImport/IWellOperationImportService.cs b/AsbCloudApp/Services/WellOperationImport/IWellOperationImportService.cs deleted file mode 100644 index f65d8888..00000000 --- a/AsbCloudApp/Services/WellOperationImport/IWellOperationImportService.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Collections.Generic; -using AsbCloudApp.Data; -using AsbCloudApp.Data.WellOperationImport; - -namespace AsbCloudApp.Services.WellOperationImport; - -/// <summary> -/// Импорт ГГД -/// </summary> -public interface IWellOperationImportService -{ - /// <summary> - /// Загрузить из excel список операций - /// </summary> - /// <param name="idWell"></param> - /// <param name="idUser"></param> - /// <param name="idType"></param> - /// <param name="sheet"></param> - IEnumerable<WellOperationDto> Import(int idWell, int idUser, int idType, SheetDto sheet); -} \ No newline at end of file diff --git a/AsbCloudApp/Services/WellOperationImport/IWellOperationImportTemplateService.cs b/AsbCloudApp/Services/WellOperationImport/IWellOperationImportTemplateService.cs deleted file mode 100644 index 817f3ae5..00000000 --- a/AsbCloudApp/Services/WellOperationImport/IWellOperationImportTemplateService.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.IO; - -namespace AsbCloudApp.Services.WellOperationImport; - -/// <summary> -/// Сервис для получения шаблонов ГГД -/// </summary> -public interface IWellOperationImportTemplateService -{ - /// <summary> - /// Скачать шаблон для заполнения - /// </summary> - /// <returns></returns> - Stream GetExcelTemplateStream(); -} \ No newline at end of file diff --git a/AsbCloudDb/Migrations/20240329070104_Update_WellOperationCategory_IdConditioning.Designer.cs b/AsbCloudDb/Migrations/20240329070104_Update_WellOperationCategory_IdConditioning.Designer.cs new file mode 100644 index 00000000..9a85b491 --- /dev/null +++ b/AsbCloudDb/Migrations/20240329070104_Update_WellOperationCategory_IdConditioning.Designer.cs @@ -0,0 +1,9389 @@ +// <auto-generated /> +using System; +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("20240329070104_Update_WellOperationCategory_IdConditioning")] + partial class Update_WellOperationCategory_IdConditioning + { + /// <inheritdoc /> + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .UseCollation("Russian_Russia.1251") + .HasAnnotation("ProductVersion", "8.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack"); + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("AsbCloudDb.Model.Cluster", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Caption") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption") + .HasComment("Название"); + + b.Property<int>("IdDeposit") + .HasColumnType("integer") + .HasColumnName("id_deposit"); + + b.Property<double?>("Latitude") + .HasColumnType("double precision") + .HasColumnName("latitude"); + + b.Property<double?>("Longitude") + .HasColumnType("double precision") + .HasColumnName("longitude"); + + b.Property<string>("Timezone") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("timezone") + .HasComment("Смещение часового пояса от UTC"); + + b.HasKey("Id"); + + b.HasIndex("IdDeposit"); + + b.ToTable("t_cluster", t => + { + t.HasComment("Кусты"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Company", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Caption") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption"); + + b.Property<int>("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<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Caption") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption"); + + b.Property<bool>("IsContact") + .HasColumnType("boolean") + .HasColumnName("is_contact"); + + b.Property<int>("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<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Company") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("company") + .HasComment("компания"); + + b.Property<string>("Email") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("email") + .HasComment("email"); + + b.Property<string>("FullName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("full_name") + .HasComment("ФИО"); + + b.Property<int>("IdCompanyType") + .HasMaxLength(255) + .HasColumnType("integer") + .HasColumnName("id_company_type") + .HasComment("вид деятельности"); + + b.Property<int>("IdWell") + .HasMaxLength(255) + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("ключ скважины"); + + b.Property<string>("Phone") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("phone") + .HasComment("номер телефона"); + + b.Property<string>("Position") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("position") + .HasComment("должность"); + + b.HasKey("Id"); + + b.HasIndex("IdCompanyType"); + + b.HasIndex("IdWell"); + + b.ToTable("t_contact", t => + { + t.HasComment("Контакты"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DailyReports.DailyReport", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<DateOnly>("Date") + .HasColumnType("date") + .HasColumnName("date") + .HasComment("Дата формирования отчёта"); + + b.Property<DateTime?>("DateLastUpdate") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_update") + .HasComment("Дата последнего обновления"); + + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("ID скважины"); + + b.Property<string>("SignBlock") + .HasColumnType("jsonb") + .HasColumnName("sign_block") + .HasComment("Подпись"); + + b.Property<string>("SubsystemBlock") + .HasColumnType("jsonb") + .HasColumnName("subsystem_block") + .HasComment("Наработкой подсистем"); + + b.Property<string>("TimeBalanceBlock") + .HasColumnType("jsonb") + .HasColumnName("time_balance_block") + .HasComment("Баланс времени"); + + b.HasKey("Id"); + + b.HasIndex("IdWell", "Date") + .IsUnique(); + + b.ToTable("t_daily_report", t => + { + t.HasComment("Ежедневные отчёты"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DataSaubStat", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<double>("AxialLoad") + .HasColumnType("double precision") + .HasColumnName("axial_load") + .HasComment("Фактическая нагрузка"); + + b.Property<double?>("AxialLoadLimitMax") + .HasColumnType("double precision") + .HasColumnName("axial_load_limit_max") + .HasComment("Максимально допустимая нагрузка"); + + b.Property<double?>("AxialLoadSp") + .HasColumnType("double precision") + .HasColumnName("axial_load_sp") + .HasComment("Ограничение факт. нагрузки"); + + b.Property<double?>("BlockSpeedSp") + .HasColumnType("double precision") + .HasColumnName("block_speed_sp") + .HasComment("Ограничение скорости блока"); + + b.Property<DateTimeOffset>("DateEnd") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_end") + .HasComment("Дата и время окончания"); + + b.Property<DateTimeOffset>("DateStart") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_start") + .HasComment("Дата и время начала"); + + b.Property<double>("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("depth_end") + .HasComment("Глубина забоя по стволу конечная"); + + b.Property<double>("DepthStart") + .HasColumnType("double precision") + .HasColumnName("depth_start") + .HasComment("Глубина забоя по стволу начальная"); + + b.Property<int>("EnabledSubsystems") + .HasColumnType("integer") + .HasColumnName("enabled_subsystems") + .HasComment("Флаги подсистем"); + + b.Property<double>("Flow") + .HasColumnType("double precision") + .HasColumnName("flow") + .HasComment("Фактический расход"); + + b.Property<bool>("HasOscillation") + .HasColumnType("boolean") + .HasColumnName("has_oscillation") + .HasComment("Наличие или отсутствие осцилляции"); + + b.Property<int>("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category") + .HasComment("Название автоопределённой операции"); + + b.Property<short?>("IdFeedRegulator") + .HasColumnType("smallint") + .HasColumnName("id_feed_regulator") + .HasComment("Работа при достижении ограничения"); + + b.Property<int>("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry") + .HasComment("Ключ телеметрии"); + + b.Property<double>("Pressure") + .HasColumnType("double precision") + .HasColumnName("pressure") + .HasComment("Давление"); + + b.Property<double?>("PressureIdle") + .HasColumnType("double precision") + .HasColumnName("pressure_idle") + .HasComment("Давление холостого хода"); + + b.Property<double?>("PressureSp") + .HasColumnType("double precision") + .HasColumnName("pressure_sp") + .HasComment("Ограничение фактического давления"); + + b.Property<double>("RotorSpeed") + .HasColumnType("double precision") + .HasColumnName("rotor_speed") + .HasComment("Фактическая скорость оборотов ВСП"); + + b.Property<double>("RotorTorque") + .HasColumnType("double precision") + .HasColumnName("rotor_torque") + .HasComment("Фактический момент"); + + b.Property<double?>("RotorTorqueLimitMax") + .HasColumnType("double precision") + .HasColumnName("rotor_torque_limit_max") + .HasComment("Максимально допустимый момент"); + + b.Property<double?>("RotorTorqueSp") + .HasColumnType("double precision") + .HasColumnName("rotor_torque_sp") + .HasComment("Ограничение факт. момента"); + + b.Property<double>("Speed") + .HasColumnType("double precision") + .HasColumnName("speed") + .HasComment("Скорость бурения"); + + b.HasKey("Id"); + + b.HasIndex("IdCategory"); + + b.HasIndex("IdTelemetry"); + + b.ToTable("t_data_saub_stat", t => + { + t.HasComment("Кеш-таблица для хранения данных для РТК-отчета"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Deposit", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Caption") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption"); + + b.Property<double?>("Latitude") + .HasColumnType("double precision") + .HasColumnName("latitude"); + + b.Property<double?>("Longitude") + .HasColumnType("double precision") + .HasColumnName("longitude"); + + b.Property<string>("Timezone") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("timezone") + .HasComment("Смещение часового пояса от UTC"); + + b.HasKey("Id"); + + b.ToTable("t_deposit", t => + { + t.HasComment("Месторождение"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DetectedOperation", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<DateTimeOffset>("DateEnd") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_end") + .HasComment("Дата начала операции"); + + b.Property<DateTimeOffset>("DateStart") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_start") + .HasComment("Дата начала операции"); + + b.Property<double>("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("depth_end") + .HasComment("Глубина после завершения операции, м"); + + b.Property<double>("DepthStart") + .HasColumnType("double precision") + .HasColumnName("depth_start") + .HasComment("Глубина на начало операции, м"); + + b.Property<int>("EnabledSubsystems") + .HasColumnType("integer") + .HasColumnName("enabled_subsystems") + .HasComment("флаги включенных подсистем"); + + b.Property<string>("ExtraData") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("extra_data") + .HasComment("доп. инфо по операции"); + + b.Property<int>("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category") + .HasComment("Id категории операции"); + + b.Property<int>("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property<int>("IdUsersAtStart") + .HasColumnType("integer") + .HasColumnName("id_user") + .HasComment("Id пользователя по телеметрии на момент начала операции"); + + b.Property<double>("Value") + .HasColumnType("double precision") + .HasColumnName("value") + .HasComment("Ключевой показатель операции"); + + b.HasKey("Id"); + + b.HasIndex("IdCategory"); + + b.HasIndex("IdTelemetry"); + + b.ToTable("t_detected_operation", t => + { + t.HasComment("автоматически определенные операции по телеметрии"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DrillTest", b => + { + b.Property<int>("Id") + .HasColumnType("integer") + .HasColumnName("id") + .HasComment("Идентификатор"); + + b.Property<int>("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry") + .HasComment("Идентификатор телеметрии"); + + b.Property<float>("DepthStart") + .HasColumnType("real") + .HasColumnName("depthStart") + .HasComment("Глубина начала"); + + b.Property<string>("Params") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("t_drill_test_params") + .HasComment("Параметры записи drill test"); + + b.Property<DateTimeOffset>("TimeStampStart") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp_start") + .HasComment("Время начала"); + + b.HasKey("Id", "IdTelemetry"); + + b.HasIndex("IdTelemetry"); + + b.ToTable("t_drill_test", t => + { + t.HasComment("Drill_test"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Driller", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id") + .HasComment("Идентификатор"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name") + .HasComment("Имя"); + + b.Property<string>("Patronymic") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("patronymic") + .HasComment("Отчество"); + + b.Property<string>("Surname") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("surname") + .HasComment("Фамилия"); + + b.HasKey("Id"); + + b.ToTable("t_driller", t => + { + t.HasComment("Бурильщик"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DrillingProgramPart", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<int>("IdFileCategory") + .HasColumnType("integer") + .HasColumnName("id_file_category"); + + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well"); + + b.HasKey("Id"); + + b.HasIndex("IdFileCategory"); + + b.HasIndex("IdWell", "IdFileCategory") + .IsUnique(); + + b.ToTable("t_drilling_program_part", t => + { + t.HasComment("части программ бурения"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Faq", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id") + .HasComment("Идентификатор"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Answer") + .HasColumnType("text") + .HasColumnName("answer") + .HasComment("Текст ответа"); + + b.Property<int>("CounterQuestion") + .HasColumnType("integer") + .HasColumnName("counter_question") + .HasComment("Счетчик повторений вопроса"); + + b.Property<DateTimeOffset?>("DateAnswer") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_answer") + .HasComment("Дата ответа"); + + b.Property<DateTimeOffset>("DateCreatedQuestion") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created_question") + .HasComment("Дата создания вопроса"); + + b.Property<DateTimeOffset>("DateLastEditedQuestion") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_edited_question") + .HasComment("Дата последнего редактирования вопроса"); + + b.Property<int?>("IdAuthorAnswer") + .HasColumnType("integer") + .HasColumnName("id_author_answer") + .HasComment("id автора ответа"); + + b.Property<int>("IdAuthorQuestion") + .HasColumnType("integer") + .HasColumnName("id_author_question") + .HasComment("id автора вопроса"); + + b.Property<int?>("IdReplacementQuestion") + .HasColumnType("integer") + .HasColumnName("id_replacement_question") + .HasComment("Ключ заменяющего вопроса"); + + b.Property<bool>("IsFrequently") + .HasColumnType("boolean") + .HasColumnName("is_frequently") + .HasComment("Частый вопрос"); + + b.Property<string>("Question") + .IsRequired() + .HasColumnType("text") + .HasColumnName("question") + .HasComment("Текст вопроса"); + + b.Property<int>("State") + .HasColumnType("integer") + .HasColumnName("state") + .HasComment("Статус вопроса"); + + b.HasKey("Id"); + + b.HasIndex("IdAuthorAnswer"); + + b.HasIndex("IdAuthorQuestion"); + + b.ToTable("t_faq", t => + { + t.HasComment("вопросы пользователей"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.FileCategory", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name") + .HasComment("Название категории"); + + b.Property<string>("ShortName") + .HasColumnType("text") + .HasColumnName("short_name") + .HasComment("Короткое название категории"); + + b.HasKey("Id"); + + b.ToTable("t_file_category", t => + { + t.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<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<int?>("IdAuthor") + .HasColumnType("integer") + .HasColumnName("id_author") + .HasComment("Id пользователя, загрузившего файл"); + + b.Property<int>("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category") + .HasComment("id категории файла"); + + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("id скважины"); + + b.Property<bool>("IsDeleted") + .HasColumnType("boolean") + .HasColumnName("is_deleted") + .HasComment("Удален ли файл"); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name") + .HasComment("Название файла"); + + b.Property<long>("Size") + .HasColumnType("bigint") + .HasColumnName("file_size") + .HasComment("Размер файла"); + + b.Property<DateTimeOffset>("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", t => + { + t.HasComment("Файлы всех категорий"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.FileMark", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Comment") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("comment") + .HasComment("Комментарий"); + + b.Property<DateTimeOffset>("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created") + .HasComment("Дата совершенного действия"); + + b.Property<int>("IdFile") + .HasColumnType("integer") + .HasColumnName("id_file") + .HasComment("id файла"); + + b.Property<int>("IdMarkType") + .HasColumnType("integer") + .HasColumnName("id_mark_type") + .HasComment("0 - отклонен, 1 - согласован"); + + b.Property<int>("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user") + .HasComment("id пользователя"); + + b.Property<bool>("IsDeleted") + .HasColumnType("boolean") + .HasColumnName("is_deleted") + .HasComment("Помечен ли файл как удаленный"); + + b.HasKey("Id"); + + b.HasIndex("IdFile"); + + b.HasIndex("IdUser"); + + b.ToTable("t_file_mark", t => + { + t.HasComment("Действия с файлами."); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.GTR.WitsItemFloat", b => + { + b.Property<int>("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property<int>("IdRecord") + .HasColumnType("integer") + .HasColumnName("id_record"); + + b.Property<int>("IdItem") + .HasColumnType("integer") + .HasColumnName("id_item"); + + b.Property<DateTimeOffset>("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property<float>("Value") + .HasColumnType("real") + .HasColumnName("value"); + + b.HasKey("IdTelemetry", "IdRecord", "IdItem", "DateTime"); + + b.ToTable("t_wits_float", t => + { + t.HasComment("таблица данных ГТИ с типом значения float"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.GTR.WitsItemInt", b => + { + b.Property<int>("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property<int>("IdRecord") + .HasColumnType("integer") + .HasColumnName("id_record"); + + b.Property<int>("IdItem") + .HasColumnType("integer") + .HasColumnName("id_item"); + + b.Property<DateTimeOffset>("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property<int>("Value") + .HasColumnType("integer") + .HasColumnName("value"); + + b.HasKey("IdTelemetry", "IdRecord", "IdItem", "DateTime"); + + b.ToTable("t_wits_int", t => + { + t.HasComment("таблица данных ГТИ с типом значения int"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.GTR.WitsItemString", b => + { + b.Property<int>("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property<int>("IdRecord") + .HasColumnType("integer") + .HasColumnName("id_record"); + + b.Property<int>("IdItem") + .HasColumnType("integer") + .HasColumnName("id_item"); + + b.Property<DateTimeOffset>("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property<string>("Value") + .IsRequired() + .HasColumnType("text") + .HasColumnName("value"); + + b.HasKey("IdTelemetry", "IdRecord", "IdItem", "DateTime"); + + b.ToTable("t_wits_string", t => + { + t.HasComment("таблица данных ГТИ с типом значения string"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.HelpPage", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<int>("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category") + .HasComment("Id категории файла"); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name") + .HasComment("Название файла"); + + b.Property<long>("Size") + .HasColumnType("bigint") + .HasColumnName("file_size") + .HasComment("Размер файла"); + + b.Property<string>("UrlPage") + .IsRequired() + .HasColumnType("text") + .HasColumnName("url_page") + .HasComment("Url страницы"); + + b.HasKey("Id"); + + b.HasIndex("IdCategory"); + + b.ToTable("t_help_page", t => + { + t.HasComment("Справки"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.LimitingParameter", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<DateTimeOffset>("DateEnd") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_end"); + + b.Property<DateTimeOffset>("DateStart") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_start"); + + b.Property<float>("DepthEnd") + .HasColumnType("real") + .HasColumnName("depth_end"); + + b.Property<float>("DepthStart") + .HasColumnType("real") + .HasColumnName("depth_start"); + + b.Property<short>("IdFeedRegulator") + .HasColumnType("smallint") + .HasColumnName("id_feed_regulator"); + + b.Property<int>("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.HasKey("Id"); + + b.HasIndex("IdTelemetry"); + + b.ToTable("t_limiting_parameter", t => + { + t.HasComment("Ограничения по параметрам телеметрии"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Manuals.Manual", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<DateTime>("DateDownload") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_download") + .HasComment("Дата загрузки"); + + b.Property<int>("IdAuthor") + .HasColumnType("integer") + .HasColumnName("id_author") + .HasComment("Id автора"); + + b.Property<int>("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category") + .HasComment("Id категории файла"); + + b.Property<int>("IdDirectory") + .HasColumnType("integer") + .HasColumnName("id_directory") + .HasComment("Id директории"); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name") + .HasComment("Название"); + + b.HasKey("Id"); + + b.HasIndex("IdAuthor"); + + b.HasIndex("IdCategory"); + + b.HasIndex("IdDirectory"); + + b.ToTable("t_manual", t => + { + t.HasComment("Инструкции"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Manuals.ManualDirectory", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<int?>("IdParent") + .HasColumnType("integer") + .HasColumnName("id_parent") + .HasComment("Id родительской директории"); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name") + .HasComment("Название"); + + b.HasKey("Id"); + + b.HasIndex("IdParent"); + + b.ToTable("t_manual_directory", t => + { + t.HasComment("Директория для инструкций"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Measure", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Data") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("data") + .HasComment("Данные таблицы последних данных"); + + b.Property<int>("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category") + .HasComment("id категории"); + + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("id скважины"); + + b.Property<bool>("IsDeleted") + .HasColumnType("boolean") + .HasColumnName("is_deleted") + .HasComment("Пометка удаленным"); + + b.Property<DateTimeOffset>("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp") + .HasComment("время добавления"); + + b.HasKey("Id"); + + b.HasIndex("IdCategory"); + + b.HasIndex("IdWell"); + + b.ToTable("t_measure", t => + { + t.HasComment("Таблица c данными для вкладки 'Последние данные'"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.MeasureCategory", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name") + .HasComment("Название категории"); + + b.Property<string>("ShortName") + .HasColumnType("text") + .HasColumnName("short_name") + .HasComment("Короткое название категории"); + + b.HasKey("Id"); + + b.ToTable("t_measure_category", t => + { + t.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<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<int>("IdNotificationCategory") + .HasColumnType("integer") + .HasColumnName("id_notification_category") + .HasComment("Id категории уведомления"); + + b.Property<int>("IdTransportType") + .HasColumnType("integer") + .HasColumnName("id_transport_type") + .HasComment("Id типа доставки уведомления"); + + b.Property<int>("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user") + .HasComment("Id получателя"); + + b.Property<string>("Message") + .IsRequired() + .HasColumnType("text") + .HasColumnName("message") + .HasComment("Сообщение уведомления"); + + b.Property<DateTime?>("ReadDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("read_date") + .HasComment("Дата прочтения уведомления"); + + b.Property<DateTime>("RegistrationDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("registration_date") + .HasComment("Дата регистрации уведомления"); + + b.Property<DateTime?>("SentDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("sent_date") + .HasComment("Дата отправки уведомления"); + + b.Property<string>("Title") + .IsRequired() + .HasColumnType("text") + .HasColumnName("title") + .HasComment("Заголовок уведомления"); + + b.HasKey("Id"); + + b.HasIndex("IdNotificationCategory"); + + b.HasIndex("IdUser"); + + b.ToTable("t_notification", t => + { + t.HasComment("Уведомления"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.NotificationCategory", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id"); + + b.ToTable("t_notification_category", t => + { + t.HasComment("Категории уведомлений"); + }); + + b.HasData( + new + { + Id = 1, + Name = "Системные уведомления" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.OperationValue", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id") + .HasComment("Идентификатор"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<double>("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("depth_end") + .HasComment("Конечная глубина"); + + b.Property<double>("DepthStart") + .HasColumnType("double precision") + .HasColumnName("depth_start") + .HasComment("Старотовая глубина"); + + b.Property<int>("IdOperationCategory") + .HasColumnType("integer") + .HasColumnName("id_operation_category") + .HasComment("Ид категории операции"); + + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("Ид скважины"); + + b.Property<double>("StandardValue") + .HasColumnType("double precision") + .HasColumnName("standard_value") + .HasComment("Нормативный показатель"); + + b.Property<double>("TargetValue") + .HasColumnType("double precision") + .HasColumnName("target_value") + .HasComment("Целевой показатель"); + + b.HasKey("Id"); + + b.HasIndex("IdOperationCategory"); + + b.HasIndex("IdWell"); + + b.ToTable("t_operationvalue", t => + { + t.HasComment("Целевые/нормативные показатели операции"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Permission", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Description") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("description") + .HasComment("Краткое описание"); + + b.Property<string>("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name") + .HasComment("Название"); + + b.HasKey("Id"); + + b.ToTable("t_permission", t => + { + t.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" + }, + new + { + Id = 530, + Description = "Разрешение на редактирование плановой конструкции скважины", + Name = "WellSectionPlan.edit" + }, + new + { + Id = 531, + Description = "Разрешение на удаление плановой конструкции скважины", + Name = "WellSectionPlan.delete" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.ProcessMaps.ProcessMapPlanDrilling", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id") + .HasComment("Идентификатор"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<double>("AxialLoadLimitMax") + .HasColumnType("double precision") + .HasColumnName("axial_load_limit_max") + .HasComment("Осевая нагрузка, т, допустимый максимум"); + + b.Property<double>("AxialLoadPlan") + .HasColumnType("double precision") + .HasColumnName("axial_load_plan") + .HasComment("Осевая нагрузка, т, план"); + + b.Property<string>("Comment") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("comment") + .HasComment("Комментарий"); + + b.Property<DateTimeOffset>("Creation") + .HasColumnType("timestamp with time zone") + .HasColumnName("creation") + .HasComment("дата создания"); + + b.Property<double>("DeltaPressureLimitMax") + .HasColumnType("double precision") + .HasColumnName("delta_pressure_limit_max") + .HasComment("Перепад давления, атм, допустимый максимум"); + + b.Property<double>("DeltaPressurePlan") + .HasColumnType("double precision") + .HasColumnName("delta_pressure_plan") + .HasComment("Перепад давления, атм, план"); + + b.Property<double>("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("depth_end") + .HasComment("Глубина по стволу до, м"); + + b.Property<double>("DepthStart") + .HasColumnType("double precision") + .HasColumnName("depth_start") + .HasComment("Глубина по стволу от, м"); + + b.Property<double>("FlowLimitMax") + .HasColumnType("double precision") + .HasColumnName("flow_limit_max") + .HasComment("Расход, л/с, допустимый максимум"); + + b.Property<double>("FlowPlan") + .HasColumnType("double precision") + .HasColumnName("flow_plan") + .HasComment("Расход, л/с, план"); + + b.Property<int>("IdAuthor") + .HasColumnType("integer") + .HasColumnName("id_author") + .HasComment("Автор"); + + b.Property<int?>("IdEditor") + .HasColumnType("integer") + .HasColumnName("id_editor") + .HasComment("Редактор"); + + b.Property<int>("IdMode") + .HasColumnType("integer") + .HasColumnName("id_mode") + .HasComment("Id режима (1- ротор, 2 слайд)"); + + b.Property<int?>("IdPrevious") + .HasColumnType("integer") + .HasColumnName("id_previous") + .HasComment("ИД состояния записи: \n0 - актуальная\n1 - замененная\n2 - удаленная"); + + b.Property<int>("IdState") + .HasColumnType("integer") + .HasColumnName("id_state") + .HasComment("ИД состояния записи: \n0 - актуальная\n1 - замененная\n2 - удаленная"); + + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("Id скважины"); + + b.Property<int>("IdWellSectionType") + .HasColumnType("integer") + .HasColumnName("id_wellsection_type") + .HasComment("Тип секции"); + + b.Property<DateTimeOffset?>("Obsolete") + .HasColumnType("timestamp with time zone") + .HasColumnName("obsolete") + .HasComment("дата устаревания"); + + b.Property<double>("RopPlan") + .HasColumnType("double precision") + .HasColumnName("rop_plan") + .HasComment("Плановая механическая скорость, м/ч"); + + b.Property<double>("TopDriveSpeedLimitMax") + .HasColumnType("double precision") + .HasColumnName("top_drive_speed_limit_max") + .HasComment("Обороты на ВСП, допустимый максимум"); + + b.Property<double>("TopDriveSpeedPlan") + .HasColumnType("double precision") + .HasColumnName("top_drive_speed_plan") + .HasComment("Обороты на ВСП, план"); + + b.Property<double>("TopDriveTorqueLimitMax") + .HasColumnType("double precision") + .HasColumnName("top_drive_torque_limit_max") + .HasComment("Момент на ВСП, допустимый максимум"); + + b.Property<double>("TopDriveTorquePlan") + .HasColumnType("double precision") + .HasColumnName("top_drive_torque_plan") + .HasComment("Момент на ВСП, план"); + + b.Property<double>("UsageSaub") + .HasColumnType("double precision") + .HasColumnName("usage_saub") + .HasComment("Плановый процент использования АКБ"); + + b.Property<double>("UsageSpin") + .HasColumnType("double precision") + .HasColumnName("usage_spin") + .HasComment("Плановый процент использования spin master"); + + b.HasKey("Id"); + + b.HasIndex("IdAuthor"); + + b.HasIndex("IdEditor"); + + b.HasIndex("IdPrevious"); + + b.HasIndex("IdWell"); + + b.HasIndex("IdWellSectionType"); + + b.ToTable("t_process_map_plan_drilling", t => + { + t.HasComment("РТК план бурение"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.ProcessMaps.ProcessMapPlanReam", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id") + .HasComment("Идентификатор"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<DateTimeOffset>("Creation") + .HasColumnType("timestamp with time zone") + .HasColumnName("creation") + .HasComment("дата создания"); + + b.Property<double>("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("depth_end") + .HasComment("Глубина по стволу до, м"); + + b.Property<double>("DepthStart") + .HasColumnType("double precision") + .HasColumnName("depth_start") + .HasComment("Глубина по стволу от, м"); + + b.Property<int>("IdAuthor") + .HasColumnType("integer") + .HasColumnName("id_author") + .HasComment("Автор"); + + b.Property<int?>("IdEditor") + .HasColumnType("integer") + .HasColumnName("id_editor") + .HasComment("Редактор"); + + b.Property<int?>("IdPrevious") + .HasColumnType("integer") + .HasColumnName("id_previous") + .HasComment("ИД состояния записи: \n0 - актуальная\n1 - замененная\n2 - удаленная"); + + b.Property<int>("IdState") + .HasColumnType("integer") + .HasColumnName("id_state") + .HasComment("ИД состояния записи: \n0 - актуальная\n1 - замененная\n2 - удаленная"); + + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("Id скважины"); + + b.Property<int>("IdWellSectionType") + .HasColumnType("integer") + .HasColumnName("id_wellsection_type") + .HasComment("Тип секции"); + + b.Property<DateTimeOffset?>("Obsolete") + .HasColumnType("timestamp with time zone") + .HasColumnName("obsolete") + .HasComment("дата устаревания"); + + b.Property<double>("Pressure") + .HasColumnType("double precision") + .HasColumnName("pressure") + .HasComment("Давление, атм"); + + b.Property<double>("Repeats") + .HasColumnType("double precision") + .HasColumnName("repeats") + .HasComment("Количество повторений"); + + b.Property<double>("SetpointDrag") + .HasColumnType("double precision") + .HasColumnName("setpoint_drag") + .HasComment("Уставка зятяжки, т"); + + b.Property<double>("SetpointTight") + .HasColumnType("double precision") + .HasColumnName("setpoint_tight") + .HasComment("Уставка посадки, т"); + + b.Property<double>("SpeedDownward") + .HasColumnType("double precision") + .HasColumnName("speed_downward") + .HasComment("Скорость спуска, м/ч"); + + b.Property<double>("SpeedUpward") + .HasColumnType("double precision") + .HasColumnName("speed_upward") + .HasComment("Скорость подъёма, м/ч"); + + b.Property<double>("SpinDownward") + .HasColumnType("double precision") + .HasColumnName("spin_downward") + .HasComment("Вращение при движении вниз, об/мин"); + + b.Property<double>("SpinUpward") + .HasColumnType("double precision") + .HasColumnName("spin_upward") + .HasComment("Вращение при движении вверх, об/мин"); + + b.Property<double>("Torque") + .HasColumnType("double precision") + .HasColumnName("torque") + .HasComment("Момент, кН*м"); + + b.HasKey("Id"); + + b.HasIndex("IdAuthor"); + + b.HasIndex("IdEditor"); + + b.HasIndex("IdWell"); + + b.HasIndex("IdWellSectionType"); + + b.ToTable("t_process_map_plan_ream", t => + { + t.HasComment("РТК проработка скважины"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationCompanyWell", b => + { + b.Property<int>("IdCompany") + .HasColumnType("integer") + .HasColumnName("id_company"); + + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well"); + + b.HasKey("IdCompany", "IdWell"); + + b.HasIndex("IdWell"); + + b.ToTable("t_relation_company_well", t => + { + t.HasComment("отношение скважин и компаний"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationContactWell", b => + { + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well"); + + b.Property<int>("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<int>("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user"); + + b.Property<int>("IdDrillingProgramPart") + .HasColumnType("integer") + .HasColumnName("id_drilling_program_part"); + + b.Property<int>("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", t => + { + t.HasComment("Отношение пользователей и частей ПБ"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationUserRolePermission", b => + { + b.Property<int>("IdUserRole") + .HasColumnType("integer") + .HasColumnName("id_user_role"); + + b.Property<int>("IdPermission") + .HasColumnType("integer") + .HasColumnName("id_permission"); + + b.HasKey("IdUserRole", "IdPermission"); + + b.HasIndex("IdPermission"); + + b.ToTable("t_relation_user_role_permission", t => + { + t.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 + }, + new + { + IdUserRole = 1, + IdPermission = 530 + }, + new + { + IdUserRole = 1, + IdPermission = 531 + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.RelationUserRoleUserRole", b => + { + b.Property<int>("Id") + .HasColumnType("integer") + .HasColumnName("id_user_role"); + + b.Property<int>("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", t => + { + t.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<int>("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user"); + + b.Property<int>("IdUserRole") + .HasColumnType("integer") + .HasColumnName("id_user_role"); + + b.HasKey("IdUser", "IdUserRole"); + + b.HasIndex("IdUserRole"); + + b.ToTable("t_relation_user_user_role", t => + { + t.HasComment("Отношение пользователей и ролей"); + }); + + b.HasData( + new + { + IdUser = 1, + IdUserRole = 1 + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.ReportProperty", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<DateTimeOffset>("Begin") + .HasColumnType("timestamp with time zone") + .HasColumnName("begin"); + + b.Property<DateTimeOffset>("End") + .HasColumnType("timestamp with time zone") + .HasColumnName("end") + .HasComment("timestamp with time zone"); + + b.Property<int>("Format") + .HasColumnType("integer") + .HasColumnName("format") + .HasComment("Формат отчета"); + + b.Property<int>("IdFile") + .HasColumnType("integer") + .HasColumnName("id_file") + .HasComment("id файла-родителя"); + + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("id скважины"); + + b.Property<int>("Step") + .HasColumnType("integer") + .HasColumnName("step") + .HasComment("размер шага в секундах"); + + b.HasKey("Id"); + + b.HasIndex("IdFile"); + + b.HasIndex("IdWell"); + + b.ToTable("t_report_property", t => + { + t.HasComment("Отчеты с данными по буровым"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Schedule", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id") + .HasComment("Идентификатор"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<DateTimeOffset>("DrillEnd") + .HasColumnType("timestamp with time zone") + .HasColumnName("drill_end") + .HasComment("Конец вахты"); + + b.Property<DateTimeOffset>("DrillStart") + .HasColumnType("timestamp with time zone") + .HasColumnName("drill_start") + .HasComment("Начало вахты"); + + b.Property<int>("IdDriller") + .HasColumnType("integer") + .HasColumnName("id_driller") + .HasComment("Идентификатор бурильщика"); + + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("Идентификатор скважины"); + + b.Property<TimeOnly>("ShiftEnd") + .HasColumnType("time without time zone") + .HasColumnName("shift_end") + .HasComment("Конец смены"); + + b.Property<TimeOnly>("ShiftStart") + .HasColumnType("time without time zone") + .HasColumnName("shift_start") + .HasComment("Начало смены"); + + b.HasKey("Id"); + + b.HasIndex("IdDriller"); + + b.HasIndex("IdWell"); + + b.ToTable("t_schedule", t => + { + t.HasComment("График работы бурильщика"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.SetpointsRequest", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Comment") + .HasColumnType("text") + .HasColumnName("comment") + .HasComment("комментарий для оператора"); + + b.Property<int>("IdAuthor") + .HasColumnType("integer") + .HasColumnName("id_author") + .HasComment("Id пользователя, загрузившего файл"); + + b.Property<int>("IdState") + .HasColumnType("integer") + .HasColumnName("id_state") + .HasComment("0: неизвестно, 1:ожидает отправки, 2: отправлено, 3: принято оператором, 4: отклонено оператором, 5: устарело"); + + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("id скважины"); + + b.Property<int>("ObsolescenceSec") + .HasColumnType("integer") + .HasColumnName("obsolescence") + .HasComment("сек. до устаревания"); + + b.Property<string>("Setpoints") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("setpoint_set") + .HasComment("Набор уставок"); + + b.Property<DateTimeOffset>("UploadDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.HasKey("Id"); + + b.HasIndex("IdAuthor"); + + b.HasIndex("IdWell"); + + b.ToTable("t_setpoints_rquest", t => + { + t.HasComment("Запросы на изменение уставок панели оператора"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Subsystem", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Description") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("description"); + + b.Property<string>("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name"); + + b.HasKey("Id"); + + b.ToTable("t_subsystem", t => + { + t.HasComment("Описание подсистем"); + }); + + b.HasData( + new + { + Id = 1, + Description = "Совместная работа режимов \"Бурение в роторе\" и \"Бурение в слайде\"", + Name = "АПД" + }, + new + { + Id = 11, + Description = "Режим работы \"Бурение в роторе\"", + Name = "АПД ротор" + }, + new + { + Id = 12, + Description = "Режим работы \"Бурение в слайде\"", + Name = "АПД слайд" + }, + new + { + Id = 65536, + Description = "Осцилляция", + Name = "Осцилляция" + }, + new + { + Id = 65537, + Description = "Демпфер", + Name = "Демпфер" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Telemetry", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Info") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("info") + .HasComment("Информация с панели о скважине"); + + b.Property<string>("RemoteUid") + .IsRequired() + .HasColumnType("text") + .HasColumnName("remote_uid") + .HasComment("Идентификатор передающего устройства. Может повторяться в списке, так как комплекты оборудования переезжают от скв. к скв."); + + b.Property<string>("TimeZone") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("timezone") + .HasComment("Смещение часового пояса от UTC"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "RemoteUid" }, "t_telemetry_remote_uid_index"); + + b.ToTable("t_telemetry", t => + { + t.HasComment("таблица привязки телеметрии от комплектов к конкретной скважине."); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryDataSaub", b => + { + b.Property<int>("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property<DateTimeOffset>("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date") + .HasComment("'2021-10-19 18:23:54+05'"); + + b.Property<float>("AxialLoad") + .HasColumnType("real") + .HasColumnName("axial_load") + .HasComment("Осевая нагрузка"); + + b.Property<float?>("AxialLoadLimitMax") + .HasColumnType("real") + .HasColumnName("axial_load_limit_max") + .HasComment("Осевая нагрузка. Аварийная макс."); + + b.Property<float?>("AxialLoadSp") + .HasColumnType("real") + .HasColumnName("axial_load_sp") + .HasComment("Осевая нагрузка. Задание"); + + b.Property<float>("BitDepth") + .HasColumnType("real") + .HasColumnName("bit_depth") + .HasComment("Положение инструмента"); + + b.Property<float>("BlockPosition") + .HasColumnType("real") + .HasColumnName("block_position") + .HasComment("Высота талевого блока"); + + b.Property<float?>("BlockPositionMax") + .HasColumnType("real") + .HasColumnName("block_position_max") + .HasComment("Талевый блок. Макс положение"); + + b.Property<float?>("BlockPositionMin") + .HasColumnType("real") + .HasColumnName("block_position_min") + .HasComment("Талевый блок. Мин положение"); + + b.Property<float?>("BlockSpeed") + .HasColumnType("real") + .HasColumnName("block_speed") + .HasComment("Скорость талевого блока"); + + b.Property<float?>("BlockSpeedSp") + .HasColumnType("real") + .HasColumnName("block_speed_sp") + .HasComment("Скорости талевого блока. Задание"); + + b.Property<float?>("BlockSpeedSpDevelop") + .HasColumnType("real") + .HasColumnName("block_speed_sp_develop") + .HasComment("Талевый блок. Задание скорости для проработки"); + + b.Property<float?>("BlockSpeedSpRotor") + .HasColumnType("real") + .HasColumnName("block_speed_sp_rotor") + .HasComment("Талевый блок. Задание скорости для роторного бурения"); + + b.Property<float?>("BlockSpeedSpSlide") + .HasColumnType("real") + .HasColumnName("block_speed_sp_slide") + .HasComment("Талевый блок. Задание скорости для режима слайда"); + + b.Property<float?>("Flow") + .HasColumnType("real") + .HasColumnName("flow") + .HasComment("Расход"); + + b.Property<float?>("FlowDeltaLimitMax") + .HasColumnType("real") + .HasColumnName("flow_delta_limit_max") + .HasComment("Расход. Аварийный макс."); + + b.Property<float?>("FlowIdle") + .HasColumnType("real") + .HasColumnName("flow_idle") + .HasComment("Расход. Холостой ход"); + + b.Property<float>("HookWeight") + .HasColumnType("real") + .HasColumnName("hook_weight") + .HasComment("Вес на крюке"); + + b.Property<float?>("HookWeightIdle") + .HasColumnType("real") + .HasColumnName("hook_weight_idle") + .HasComment("Вес на крюке. Холостой ход"); + + b.Property<float?>("HookWeightLimitMax") + .HasColumnType("real") + .HasColumnName("hook_weight_limit_max") + .HasComment("Вес на крюке. Затяжка"); + + b.Property<float?>("HookWeightLimitMin") + .HasColumnType("real") + .HasColumnName("hook_weight_limit_min") + .HasComment("Вес на крюке. Посадка"); + + b.Property<short?>("IdFeedRegulator") + .HasColumnType("smallint") + .HasColumnName("id_feed_regulator") + .HasComment("Текущий критерий бурения"); + + b.Property<int?>("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user") + .HasComment("Пользователь САУБ"); + + b.Property<short>("Mode") + .HasColumnType("smallint") + .HasColumnName("mode") + .HasComment("Режим САУБ"); + + b.Property<float?>("Mse") + .HasColumnType("real") + .HasColumnName("mse") + .HasComment("MSE"); + + b.Property<short?>("MseState") + .HasColumnType("smallint") + .HasColumnName("mse_state") + .HasComment("Текущее состояние работы MSE"); + + b.Property<float>("Pressure") + .HasColumnType("real") + .HasColumnName("pressure") + .HasComment("Давление"); + + b.Property<float?>("PressureDeltaLimitMax") + .HasColumnType("real") + .HasColumnName("pressure_delta_limit_max") + .HasComment("Давление дифф. Аварийное макс."); + + b.Property<float?>("PressureIdle") + .HasColumnType("real") + .HasColumnName("pressure_idle") + .HasComment("Давление. Холостой ход"); + + b.Property<float?>("PressureSp") + .HasColumnType("real") + .HasColumnName("pressure_sp") + .HasComment("Давление. Задание"); + + b.Property<float?>("PressureSpDevelop") + .HasColumnType("real") + .HasColumnName("pressure_sp_develop") + .HasComment("Давление. Задание для проработки"); + + b.Property<float?>("PressureSpRotor") + .HasColumnType("real") + .HasColumnName("pressure_sp_rotor") + .HasComment("Давление. Задание для роторного бурения"); + + b.Property<float?>("PressureSpSlide") + .HasColumnType("real") + .HasColumnName("pressure_sp_slide") + .HasComment("Давление. Задание для режима слайда"); + + b.Property<float?>("Pump0Flow") + .HasColumnType("real") + .HasColumnName("pump0_flow") + .HasComment("Расход. Буровой насос 1"); + + b.Property<float?>("Pump1Flow") + .HasColumnType("real") + .HasColumnName("pump1_flow") + .HasComment("Расход. Буровой насос 2"); + + b.Property<float?>("Pump2Flow") + .HasColumnType("real") + .HasColumnName("pump2_flow") + .HasComment("Расход. Буровой насос 3"); + + b.Property<float>("RotorSpeed") + .HasColumnType("real") + .HasColumnName("rotor_speed") + .HasComment("Обороты ротора"); + + b.Property<float>("RotorTorque") + .HasColumnType("real") + .HasColumnName("rotor_torque") + .HasComment("Момент на роторе"); + + b.Property<float?>("RotorTorqueIdle") + .HasColumnType("real") + .HasColumnName("rotor_torque_idle") + .HasComment("Момент на роторе. Холостой ход"); + + b.Property<float?>("RotorTorqueLimitMax") + .HasColumnType("real") + .HasColumnName("rotor_torque_limit_max") + .HasComment("Момент на роторе. Аварийный макс."); + + b.Property<float?>("RotorTorqueSp") + .HasColumnType("real") + .HasColumnName("rotor_torque_sp") + .HasComment("Момент на роторе. Задание"); + + b.Property<float>("WellDepth") + .HasColumnType("real") + .HasColumnName("well_depth") + .HasComment("Глубина забоя"); + + b.HasKey("IdTelemetry", "DateTime"); + + b.ToTable("t_telemetry_data_saub", t => + { + t.HasComment("набор основных данных по SAUB"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryDataSaubStat", b => + { + b.Property<long?>("Count") + .HasColumnType("bigint") + .HasColumnName("count_items"); + + b.Property<DateTimeOffset?>("DateMax") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_max"); + + b.Property<DateTimeOffset?>("DateMin") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_min"); + + b.Property<float?>("DepthMax") + .HasColumnType("real") + .HasColumnName("depth_max"); + + b.Property<float?>("DepthMin") + .HasColumnType("real") + .HasColumnName("depth_min"); + + b.Property<int>("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.ToTable((string)null); + + b.ToView("mw_telemetry_datas_saub_stat", (string)null); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryDataSpin", b => + { + b.Property<int>("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property<DateTimeOffset>("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date") + .HasComment("'2021-10-19 18:23:54+05'"); + + b.Property<short?>("Mode") + .HasColumnType("smallint") + .HasColumnName("mode") + .HasComment("Выбранный режим управления"); + + b.Property<float?>("PositionRight") + .HasColumnType("real") + .HasColumnName("position_right") + .HasComment("Крайний правый угол осцилляции"); + + b.Property<float?>("PositionZero") + .HasColumnType("real") + .HasColumnName("position_zero") + .HasComment("Нулевая позиция осцилляции"); + + b.Property<float?>("RevolsLeftLimit") + .HasColumnType("real") + .HasColumnName("revols_left_limit") + .HasComment("Ограничение числа оборотов влево"); + + b.Property<float?>("RevolsLeftTotal") + .HasColumnType("real") + .HasColumnName("revols_left_total") + .HasComment("Суммарное количество оборотов влево"); + + b.Property<float?>("RevolsRightLimit") + .HasColumnType("real") + .HasColumnName("revols_right_limit") + .HasComment("Ограничение числа оборотов вправо"); + + b.Property<float?>("RevolsRightTotal") + .HasColumnType("real") + .HasColumnName("revols_right_total") + .HasComment("Суммарное количество оборотов вправо"); + + b.Property<float?>("SpeedLeftSp") + .HasColumnType("real") + .HasColumnName("speed_left_sp") + .HasComment("Заданная скорость вращения влево"); + + b.Property<float?>("SpeedRightSp") + .HasColumnType("real") + .HasColumnName("speed_right_sp") + .HasComment("Заданная скорость вращения вправо"); + + b.Property<short?>("State") + .HasColumnType("smallint") + .HasColumnName("state") + .HasComment("Переменная этапа"); + + b.HasKey("IdTelemetry", "DateTime"); + + b.ToTable("t_telemetry_data_spin", t => + { + t.HasComment("набор основных данных по SpinMaster"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryEvent", b => + { + b.Property<int>("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property<int>("IdEvent") + .HasColumnType("integer") + .HasColumnName("id_event"); + + b.Property<int>("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category"); + + b.Property<string>("MessageTemplate") + .IsRequired() + .HasColumnType("text") + .HasColumnName("message_template"); + + b.HasKey("IdTelemetry", "IdEvent"); + + b.ToTable("t_telemetry_event", t => + { + t.HasComment("Справочник событий. События формируют сообщения. Разделено по версиям посылок от телеметрии."); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryMessage", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Arg0") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("arg0") + .HasComment("Аргумент №0 для вставки в шаблон сообщения"); + + b.Property<string>("Arg1") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("arg1"); + + b.Property<string>("Arg2") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("arg2"); + + b.Property<string>("Arg3") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("arg3"); + + b.Property<DateTimeOffset>("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property<int>("IdEvent") + .HasColumnType("integer") + .HasColumnName("id_event"); + + b.Property<int>("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property<int?>("IdTelemetryUser") + .HasColumnType("integer") + .HasColumnName("id_telemetry_user") + .HasComment("Пользователь панели отправляющей телеметрию. не пользователь облака."); + + b.Property<double>("WellDepth") + .HasColumnType("double precision") + .HasColumnName("well_depth"); + + b.HasKey("Id"); + + b.HasIndex("IdTelemetry"); + + b.ToTable("t_telemetry_message", t => + { + t.HasComment("Сообщения на буровых"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryUser", b => + { + b.Property<int>("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property<int>("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user"); + + b.Property<int?>("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property<string>("Name") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name"); + + b.Property<string>("Patronymic") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("patronymic"); + + b.Property<string>("Surname") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("surname"); + + b.HasKey("IdTelemetry", "IdUser"); + + b.ToTable("t_telemetry_user", t => + { + t.HasComment("Пользователи панели САУБ. Для сообщений."); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.TelemetryWirelineRunOut", b => + { + b.Property<int>("IdTelemetry") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id_telemetry") + .HasComment("Идентификатор телеметрии"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("IdTelemetry")); + + b.Property<DateTimeOffset>("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_time") + .HasComment("Отметка времени"); + + b.Property<float>("Hauling") + .HasColumnType("real") + .HasColumnName("hauling") + .HasComment("Наработка талевого каната с момента перетяжки каната, т*км"); + + b.Property<float>("HaulingWarnSp") + .HasColumnType("real") + .HasColumnName("hauling_warn_sp") + .HasComment("Наработка талевого каната до сигнализации о необходимости перетяжки, т*км"); + + b.Property<float>("Replace") + .HasColumnType("real") + .HasColumnName("replace") + .HasComment("Наработка талевого каната с момента замены каната, т*км"); + + b.Property<float>("ReplaceWarnSp") + .HasColumnType("real") + .HasColumnName("replace_warn_sp") + .HasComment("Наработка талевого каната до сигнализации о необходимости замены, т*км"); + + b.HasKey("IdTelemetry"); + + b.ToTable("t_telemetry_wireline_run_out", t => + { + t.HasComment("Наработка талевого каната"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Trajectory.TrajectoryFact", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<double>("AzimuthGeo") + .HasColumnType("double precision") + .HasColumnName("azimuth_geo") + .HasComment("Азимут Географ."); + + b.Property<double>("AzimuthMagnetic") + .HasColumnType("double precision") + .HasColumnName("azimuth_magnetic") + .HasComment("Азимут Магнитный"); + + b.Property<string>("Comment") + .HasColumnType("text") + .HasColumnName("comment") + .HasComment("Комментарии"); + + b.Property<int>("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user") + .HasComment("ID пользователя который внес/изменил запись"); + + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("ID скважины"); + + b.Property<DateTimeOffset>("UpdateDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("update_date") + .HasComment("Дата загрузки траектории"); + + b.Property<double>("VerticalDepth") + .HasColumnType("double precision") + .HasColumnName("vertical_depth") + .HasComment("Глубина вертикальная"); + + b.Property<double>("WellboreDepth") + .HasColumnType("double precision") + .HasColumnName("wellbore_depth") + .HasComment("Глубина по стволу"); + + b.Property<double>("ZenithAngle") + .HasColumnType("double precision") + .HasColumnName("zenith_angle") + .HasComment("Угол зенитный"); + + b.HasKey("Id"); + + b.HasIndex("IdUser"); + + b.HasIndex("IdWell"); + + b.ToTable("t_trajectory_fact", t => + { + t.HasComment("Загрузка фактической траектории"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Trajectory.TrajectoryPlan", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<double>("AzimuthGeo") + .HasColumnType("double precision") + .HasColumnName("azimuth_geo") + .HasComment("Азимут Географ."); + + b.Property<double>("AzimuthMagnetic") + .HasColumnType("double precision") + .HasColumnName("azimuth_magnetic") + .HasComment("Азимут Магнитный"); + + b.Property<string>("Comment") + .HasColumnType("text") + .HasColumnName("comment") + .HasComment("Комментарии"); + + b.Property<int>("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user") + .HasComment("ID пользователя который внес/изменил запись"); + + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("ID скважины"); + + b.Property<double?>("Radius") + .HasColumnType("double precision") + .HasColumnName("radius") + .HasComment("Радиус цели"); + + b.Property<DateTimeOffset>("UpdateDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("update_date") + .HasComment("Дата загрузки траектории"); + + b.Property<double>("VerticalDepth") + .HasColumnType("double precision") + .HasColumnName("vertical_depth") + .HasComment("Глубина вертикальная"); + + b.Property<double>("WellboreDepth") + .HasColumnType("double precision") + .HasColumnName("wellbore_depth") + .HasComment("Глубина по стволу"); + + b.Property<double>("ZenithAngle") + .HasColumnType("double precision") + .HasColumnName("zenith_angle") + .HasComment("Угол зенитный"); + + b.HasKey("Id"); + + b.HasIndex("IdUser"); + + b.HasIndex("IdWell"); + + b.ToTable("t_trajectory_plan", t => + { + t.HasComment("Загрузка плановой траектории"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.User", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Email") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("email") + .HasComment("должность"); + + b.Property<int>("IdCompany") + .HasColumnType("integer") + .HasColumnName("id_company"); + + b.Property<short>("IdState") + .HasColumnType("smallint") + .HasColumnName("state") + .HasComment("состояние:\n0 - не активен, \n1 - активен, \n2 - заблокирован"); + + b.Property<string>("Login") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("login"); + + b.Property<string>("Name") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name") + .HasComment("имя"); + + b.Property<string>("PasswordHash") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("password_hash") + .HasComment("соленый хэш пароля.\nпервые 5 символов - соль"); + + b.Property<string>("Patronymic") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("patronymic") + .HasComment("отчество"); + + b.Property<string>("Phone") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("phone") + .HasComment("номер телефона"); + + b.Property<string>("Position") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("position") + .HasComment("email"); + + b.Property<string>("Surname") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("surname") + .HasComment("фамилия"); + + b.HasKey("Id"); + + b.HasIndex("IdCompany"); + + b.HasIndex("Login") + .IsUnique(); + + b.ToTable("t_user", t => + { + t.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<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Caption") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption") + .HasComment("Название"); + + b.Property<int>("IdType") + .HasColumnType("integer") + .HasColumnName("id_type") + .HasComment("0-роль из стандартной матрицы, \n1-специальная роль для какого-либо пользователя"); + + b.HasKey("Id"); + + b.ToTable("t_user_role", t => + { + t.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<int>("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user"); + + b.Property<string>("Key") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("key") + .HasComment("Ключ настроек пользователя"); + + b.Property<JsonDocument>("Value") + .HasColumnType("jsonb") + .HasColumnName("setting_value") + .HasComment("Значение настроек пользователя"); + + b.HasKey("IdUser", "Key"); + + b.ToTable("t_user_settings", t => + { + t.HasComment("настройки интерфейса пользователя"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.RecordBase", b => + { + b.Property<int>("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property<DateTimeOffset>("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property<short?>("Actcod") + .HasColumnType("smallint") + .HasColumnName("ACTCOD"); + + b.Property<int?>("Date") + .HasColumnType("integer") + .HasColumnName("DATE"); + + b.Property<short?>("Recid") + .HasColumnType("smallint") + .HasColumnName("RECID"); + + b.Property<int?>("Seqid") + .HasColumnType("integer") + .HasColumnName("SEQID"); + + b.Property<short?>("Stknum") + .HasColumnType("smallint") + .HasColumnName("STKNUM"); + + b.Property<int?>("Time") + .HasColumnType("integer") + .HasColumnName("TIME"); + + b.Property<string>("Wellid") + .HasColumnType("text") + .HasColumnName("WELLID"); + + b.HasKey("IdTelemetry", "DateTime"); + + b.ToTable("t_telemetry_wits_base"); + + b.UseTptMappingStrategy(); + }); + + modelBuilder.Entity("AsbCloudDb.Model.Well", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Caption") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption"); + + b.Property<int>("IdCluster") + .HasColumnType("integer") + .HasColumnName("id_cluster"); + + b.Property<int>("IdState") + .HasColumnType("integer") + .HasColumnName("state") + .HasComment("0 - неизвестно, 1 - в работе, 2 - завершена"); + + b.Property<int?>("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property<int>("IdWellType") + .HasColumnType("integer") + .HasColumnName("id_well_type"); + + b.Property<double?>("Latitude") + .HasColumnType("double precision") + .HasColumnName("latitude"); + + b.Property<double?>("Longitude") + .HasColumnType("double precision") + .HasColumnName("longitude"); + + b.Property<string>("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", t => + { + t.HasComment("скважины"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellComposite", b => + { + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("Id скважины получателя"); + + b.Property<int>("IdWellSrc") + .HasColumnType("integer") + .HasColumnName("id_well_src") + .HasComment("Id скважины композита"); + + b.Property<int>("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", t => + { + t.HasComment("Композитная скважина"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellFinalDocument", b => + { + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well"); + + b.Property<int>("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user"); + + b.Property<int>("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", t => + { + t.HasComment("Дело скважины"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellOperation", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("CategoryInfo") + .HasColumnType("text") + .HasColumnName("category_info") + .HasComment("Доп. информация к выбраной категории"); + + b.Property<string>("Comment") + .HasColumnType("text") + .HasColumnName("comment") + .HasComment("Комментарий"); + + b.Property<DateTimeOffset>("DateStart") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_start") + .HasComment("Дата начала операции"); + + b.Property<double>("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("depth_end") + .HasComment("Глубина после завершения операции, м"); + + b.Property<double>("DepthStart") + .HasColumnType("double precision") + .HasColumnName("depth_start") + .HasComment("Глубина на начало операции, м"); + + b.Property<double>("DurationHours") + .HasColumnType("double precision") + .HasColumnName("duration_hours") + .HasComment("Продолжительность, часы"); + + b.Property<int>("IdCategory") + .HasColumnType("integer") + .HasColumnName("id_category") + .HasComment("Id категории операции"); + + b.Property<int?>("IdPlan") + .HasColumnType("integer") + .HasColumnName("id_plan") + .HasComment("Id плановой операции"); + + b.Property<int>("IdType") + .HasColumnType("integer") + .HasColumnName("id_type") + .HasComment("0 = План или 1 = Факт"); + + b.Property<int?>("IdUser") + .HasColumnType("integer"); + + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("Id скважины"); + + b.Property<int>("IdWellSectionType") + .HasColumnType("integer") + .HasColumnName("id_well_section_type") + .HasComment("Id тип секции скважины"); + + b.Property<DateTimeOffset>("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", t => + { + t.HasComment("Данные по операциям на скважине"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellOperationCategory", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<int?>("IdParent") + .HasColumnType("integer") + .HasColumnName("id_parent") + .HasComment("id родительской категории"); + + b.Property<string>("KeyValueName") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("key_value_name") + .HasComment("Название ключевого показателя операции"); + + b.Property<string>("KeyValueUnits") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("key_value_units") + .HasComment("Единицы измерения ключевого показателя операции"); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name") + .HasComment("Название категории операции"); + + b.HasKey("Id"); + + b.HasIndex("IdParent"); + + b.ToTable("t_well_operation_category", t => + { + t.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<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Caption") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption") + .HasComment("Название"); + + b.Property<float>("Order") + .HasColumnType("real") + .HasColumnName("order") + .HasComment("Порядок"); + + b.HasKey("Id"); + + b.ToTable("t_well_section_type", t => + { + t.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.WellSections.WellSectionPlan", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<double>("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("depth_end") + .HasComment("Конечная глубина бурения, м"); + + b.Property<double>("DepthStart") + .HasColumnType("double precision") + .HasColumnName("depth_start") + .HasComment("Начальная глубина бурения, м"); + + b.Property<int>("IdSectionType") + .HasColumnType("integer") + .HasColumnName("id_section_type") + .HasComment("Тип секции"); + + b.Property<int>("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user") + .HasComment("Id пользователя"); + + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("Id скважины"); + + b.Property<double?>("InnerDiameter") + .HasColumnType("double precision") + .HasColumnName("inner_diameter") + .HasComment("Внутренний диаметр"); + + b.Property<DateTimeOffset?>("LastUpdateDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_update") + .HasComment("Дата последнего обновления"); + + b.Property<double?>("OuterDiameter") + .HasColumnType("double precision") + .HasColumnName("outer_diameter") + .HasComment("Внешний диаметр"); + + b.HasKey("Id"); + + b.HasIndex("IdSectionType"); + + b.HasIndex("IdWell", "IdSectionType") + .IsUnique(); + + b.ToTable("t_well_section_plan"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WellType", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Caption") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("caption") + .HasComment("Название"); + + b.HasKey("Id"); + + b.ToTable("t_well_type", t => + { + t.HasComment("конструкция скважины"); + }); + + b.HasData( + new + { + Id = 1, + Caption = "Наклонно-направленная" + }, + new + { + Id = 2, + Caption = "Горизонтальная" + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.WITS.Record1", b => + { + b.HasBaseType("AsbCloudDb.Model.WITS.RecordBase"); + + b.Property<float?>("Blkpos") + .HasColumnType("real") + .HasColumnName("BLKPOS"); + + b.Property<float?>("Chkp") + .HasColumnType("real") + .HasColumnName("CHKP"); + + b.Property<float?>("Deptbitm") + .HasColumnType("real") + .HasColumnName("DEPTBITM"); + + b.Property<float?>("Deptbitv") + .HasColumnType("real") + .HasColumnName("DEPTBITV"); + + b.Property<float?>("Deptmeas") + .HasColumnType("real") + .HasColumnName("DEPTMEAS"); + + b.Property<float?>("Deptretm") + .HasColumnType("real") + .HasColumnName("DEPTRETM"); + + b.Property<float?>("Deptvert") + .HasColumnType("real") + .HasColumnName("DEPTVERT"); + + b.Property<float?>("Gasa") + .HasColumnType("real") + .HasColumnName("GASA"); + + b.Property<float?>("Hkla") + .HasColumnType("real") + .HasColumnName("HKLA"); + + b.Property<float?>("Hklx") + .HasColumnType("real") + .HasColumnName("HKLX"); + + b.Property<short?>("Lagstks") + .HasColumnType("smallint") + .HasColumnName("LAGSTKS"); + + b.Property<float?>("Mcia") + .HasColumnType("real") + .HasColumnName("MCIA"); + + b.Property<float?>("Mcoa") + .HasColumnType("real") + .HasColumnName("MCOA"); + + b.Property<float?>("Mdia") + .HasColumnType("real") + .HasColumnName("MDIA"); + + b.Property<float?>("Mdoa") + .HasColumnType("real") + .HasColumnName("MDOA"); + + b.Property<float?>("Mfia") + .HasColumnType("real") + .HasColumnName("MFIA"); + + b.Property<float?>("Mfoa") + .HasColumnType("real") + .HasColumnName("MFOA"); + + b.Property<short?>("Mfop") + .HasColumnType("smallint") + .HasColumnName("MFOP"); + + b.Property<float?>("Mtia") + .HasColumnType("real") + .HasColumnName("MTIA"); + + b.Property<float?>("Mtoa") + .HasColumnType("real") + .HasColumnName("MTOA"); + + b.Property<float?>("Ropa") + .HasColumnType("real") + .HasColumnName("ROPA"); + + b.Property<short?>("Rpma") + .HasColumnType("smallint") + .HasColumnName("RPMA"); + + b.Property<float?>("Spare1") + .HasColumnType("real") + .HasColumnName("SPARE1"); + + b.Property<float?>("Spare2") + .HasColumnType("real") + .HasColumnName("SPARE2"); + + b.Property<float?>("Spare3") + .HasColumnType("real") + .HasColumnName("SPARE3"); + + b.Property<float?>("Spare4") + .HasColumnType("real") + .HasColumnName("SPARE4"); + + b.Property<float?>("Spare5") + .HasColumnType("real") + .HasColumnName("SPARE5"); + + b.Property<short?>("Spm1") + .HasColumnType("smallint") + .HasColumnName("SPM1"); + + b.Property<short?>("Spm2") + .HasColumnType("smallint") + .HasColumnName("SPM2"); + + b.Property<short?>("Spm3") + .HasColumnType("smallint") + .HasColumnName("SPM3"); + + b.Property<float?>("Sppa") + .HasColumnType("real") + .HasColumnName("SPPA"); + + b.Property<int?>("Stkc") + .HasColumnType("integer") + .HasColumnName("STKC"); + + b.Property<int?>("TelemetryId") + .HasColumnType("integer"); + + b.Property<float?>("Torqa") + .HasColumnType("real") + .HasColumnName("TORQA"); + + b.Property<float?>("Torqx") + .HasColumnType("real") + .HasColumnName("TORQX"); + + b.Property<float?>("Tvolact") + .HasColumnType("real") + .HasColumnName("TVOLACT"); + + b.Property<float?>("Tvolcact") + .HasColumnType("real") + .HasColumnName("TVOLCACT"); + + b.Property<float?>("Woba") + .HasColumnType("real") + .HasColumnName("WOBA"); + + b.Property<float?>("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<float?>("Deptbitm") + .HasColumnType("real") + .HasColumnName("DEPTBITM"); + + b.Property<float?>("DeptmeasGdpMc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_GDP_mc"); + + b.Property<float?>("DeptmeasMcrstat") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_MCRSTAT"); + + b.Property<float?>("DeptmeasRa33Mc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_RA33_mc"); + + b.Property<float?>("DeptmeasRa33f2Mc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_RA33F2_mc"); + + b.Property<float?>("DeptmeasRa33f4Mc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_RA33F4_mc"); + + b.Property<float?>("DeptmeasRp33Mc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_RP33_mc"); + + b.Property<float?>("DeptmeasRp33f2Mc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_RP33F2_mc"); + + b.Property<float?>("DeptmeasRp33f4Mc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_RP33F4_mc"); + + b.Property<float?>("DeptmeasSlvlMc") + .HasColumnType("real") + .HasColumnName("DEPTMEAS_SLVL_mc"); + + b.Property<float?>("GdpMc") + .HasColumnType("real") + .HasColumnName("GDP_mc"); + + b.Property<float?>("Mcrstat") + .HasColumnType("real") + .HasColumnName("MCRSTAT"); + + b.Property<float?>("Ra33Mc") + .HasColumnType("real") + .HasColumnName("RA33_mc"); + + b.Property<float?>("Ra33f2Mc") + .HasColumnType("real") + .HasColumnName("RA33F2_mc"); + + b.Property<float?>("Ra33f4Mc") + .HasColumnType("real") + .HasColumnName("RA33F4_mc"); + + b.Property<float?>("Rp33Mc") + .HasColumnType("real") + .HasColumnName("RP33_mc"); + + b.Property<float?>("Rp33f2Mc") + .HasColumnType("real") + .HasColumnName("RP33F2_mc"); + + b.Property<float?>("Rp33f4Mc") + .HasColumnType("real") + .HasColumnName("RP33F4_mc"); + + b.Property<float?>("SlvlMc") + .HasColumnType("real") + .HasColumnName("SLVL_mc"); + + b.Property<int?>("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<float?>("Btot") + .HasColumnType("real") + .HasColumnName("Btot"); + + b.Property<float?>("Bx") + .HasColumnType("real") + .HasColumnName("Bx"); + + b.Property<float?>("By") + .HasColumnType("real") + .HasColumnName("By"); + + b.Property<float?>("Bz") + .HasColumnType("real") + .HasColumnName("Bz"); + + b.Property<float?>("Deptbitm") + .HasColumnType("real") + .HasColumnName("DEPTBITM"); + + b.Property<float?>("Deptmeas") + .HasColumnType("real") + .HasColumnName("DEPTMEAS"); + + b.Property<float?>("Gtot") + .HasColumnType("real") + .HasColumnName("Gtot"); + + b.Property<float?>("Gx") + .HasColumnType("real") + .HasColumnName("Gx"); + + b.Property<float?>("Gy") + .HasColumnType("real") + .HasColumnName("Gy"); + + b.Property<float?>("Gz") + .HasColumnType("real") + .HasColumnName("Gz"); + + b.Property<int?>("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<float?>("Att06h") + .HasColumnType("real") + .HasColumnName("ATT06H"); + + b.Property<float?>("Att06l") + .HasColumnType("real") + .HasColumnName("ATT06L"); + + b.Property<float?>("Att10h") + .HasColumnType("real") + .HasColumnName("ATT10H"); + + b.Property<float?>("Att10l") + .HasColumnType("real") + .HasColumnName("ATT10L"); + + b.Property<float?>("Deptbitm") + .HasColumnType("real") + .HasColumnName("DEPTBITM"); + + b.Property<float?>("Deptmeas") + .HasColumnType("real") + .HasColumnName("DEPTMEAS"); + + b.Property<float?>("Phl1f1") + .HasColumnType("real") + .HasColumnName("PHL1F1"); + + b.Property<float?>("Phl1f2") + .HasColumnType("real") + .HasColumnName("PHL1F2"); + + b.Property<float?>("Phl2f1") + .HasColumnType("real") + .HasColumnName("PHL2F1"); + + b.Property<float?>("Phl2f2") + .HasColumnType("real") + .HasColumnName("PHL2F2"); + + b.Property<float?>("Status") + .HasColumnType("real") + .HasColumnName("Status"); + + b.Property<int?>("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<float?>("Deptmeas") + .HasColumnType("real") + .HasColumnName("DEPTMEAS"); + + b.Property<float?>("Deptsvym") + .HasColumnType("real") + .HasColumnName("DEPTSVYM"); + + b.Property<float?>("Deptsvyv") + .HasColumnType("real") + .HasColumnName("DEPTSVYV"); + + b.Property<short?>("Passnum") + .HasColumnType("smallint") + .HasColumnName("PASSNUM"); + + b.Property<float?>("Spare1") + .HasColumnType("real") + .HasColumnName("SPARE1"); + + b.Property<float?>("Spare2") + .HasColumnType("real") + .HasColumnName("SPARE2"); + + b.Property<float?>("Spare3") + .HasColumnType("real") + .HasColumnName("SPARE3"); + + b.Property<float?>("Spare4") + .HasColumnType("real") + .HasColumnName("SPARE4"); + + b.Property<float?>("Spare5") + .HasColumnType("real") + .HasColumnName("SPARE5"); + + b.Property<float?>("Svyazc") + .HasColumnType("real") + .HasColumnName("SVYAZC"); + + b.Property<float?>("Svyazu") + .HasColumnType("real") + .HasColumnName("SVYAZU"); + + b.Property<float?>("Svydls") + .HasColumnType("real") + .HasColumnName("SVYDLS"); + + b.Property<float?>("Svyew") + .HasColumnType("real") + .HasColumnName("SVYEW"); + + b.Property<float?>("Svygtf") + .HasColumnType("real") + .HasColumnName("SVYGTF"); + + b.Property<float?>("Svyinc") + .HasColumnType("real") + .HasColumnName("SVYINC"); + + b.Property<float?>("Svymtf") + .HasColumnType("real") + .HasColumnName("SVYMTF"); + + b.Property<float?>("Svyns") + .HasColumnType("real") + .HasColumnName("SVYNS"); + + b.Property<string>("Svytype") + .HasColumnType("text") + .HasColumnName("SVYTYPE"); + + b.Property<float?>("Svywalk") + .HasColumnType("real") + .HasColumnName("SVYWALK"); + + b.Property<int?>("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<float?>("Deptbitm") + .HasColumnType("real") + .HasColumnName("DEPTBITM"); + + b.Property<float?>("Deptbitv") + .HasColumnType("real") + .HasColumnName("DEPTBITV"); + + b.Property<float?>("Deptcalm") + .HasColumnType("real") + .HasColumnName("DEPTCALM"); + + b.Property<float?>("Deptcalv") + .HasColumnType("real") + .HasColumnName("DEPTCALV"); + + b.Property<float?>("Deptfdm") + .HasColumnType("real") + .HasColumnName("DEPTFDM"); + + b.Property<float?>("Deptfdv") + .HasColumnType("real") + .HasColumnName("DEPTFDV"); + + b.Property<float?>("Deptgr1m") + .HasColumnType("real") + .HasColumnName("DEPTGR1M"); + + b.Property<float?>("Deptgr1v") + .HasColumnType("real") + .HasColumnName("DEPTGR1V"); + + b.Property<float?>("Deptgr2m") + .HasColumnType("real") + .HasColumnName("DEPTGR2M"); + + b.Property<float?>("Deptgr2v") + .HasColumnType("real") + .HasColumnName("DEPTGR2V"); + + b.Property<float?>("Deptmeas") + .HasColumnType("real") + .HasColumnName("DEPTMEAS"); + + b.Property<float?>("Deptp1m") + .HasColumnType("real") + .HasColumnName("DEPTP1M"); + + b.Property<float?>("Deptp1v") + .HasColumnType("real") + .HasColumnName("DEPTP1V"); + + b.Property<float?>("Deptp2m") + .HasColumnType("real") + .HasColumnName("DEPTP2M"); + + b.Property<float?>("Deptp2v") + .HasColumnType("real") + .HasColumnName("DEPTP2V"); + + b.Property<float?>("Deptrs1m") + .HasColumnType("real") + .HasColumnName("DEPTRS1M"); + + b.Property<float?>("Deptrs1v") + .HasColumnType("real") + .HasColumnName("DEPTRS1V"); + + b.Property<float?>("Deptrs2m") + .HasColumnType("real") + .HasColumnName("DEPTRS2M"); + + b.Property<float?>("Deptrs2v") + .HasColumnType("real") + .HasColumnName("DEPTRS2V"); + + b.Property<float?>("Deptvert") + .HasColumnType("real") + .HasColumnName("DEPTVERT"); + + b.Property<float?>("Mclp") + .HasColumnType("real") + .HasColumnName("MCLP"); + + b.Property<float?>("Mfd") + .HasColumnType("real") + .HasColumnName("MFD"); + + b.Property<float?>("Mffp") + .HasColumnType("real") + .HasColumnName("MFFP"); + + b.Property<float?>("Mfpp") + .HasColumnType("real") + .HasColumnName("MFPP"); + + b.Property<float?>("Mfrann") + .HasColumnType("real") + .HasColumnName("MFRANN"); + + b.Property<float?>("Mfrpipe") + .HasColumnType("real") + .HasColumnName("MFRPIPE"); + + b.Property<float?>("Mftann") + .HasColumnType("real") + .HasColumnName("MFTANN"); + + b.Property<float?>("Mftpipe") + .HasColumnType("real") + .HasColumnName("MFTPIPE"); + + b.Property<float?>("Mg1") + .HasColumnType("real") + .HasColumnName("MG1"); + + b.Property<float?>("Mg1c") + .HasColumnType("real") + .HasColumnName("MG1C"); + + b.Property<float?>("Mg2") + .HasColumnType("real") + .HasColumnName("MG2"); + + b.Property<float?>("Mg2c") + .HasColumnType("real") + .HasColumnName("MG2C"); + + b.Property<float?>("Mpo1") + .HasColumnType("real") + .HasColumnName("MPO1"); + + b.Property<float?>("Mpo2") + .HasColumnType("real") + .HasColumnName("MPO2"); + + b.Property<float?>("Mr1") + .HasColumnType("real") + .HasColumnName("MR1"); + + b.Property<float?>("Mr1c") + .HasColumnType("real") + .HasColumnName("MR1C"); + + b.Property<float?>("Mr2") + .HasColumnType("real") + .HasColumnName("MR2"); + + b.Property<float?>("Mr2c") + .HasColumnType("real") + .HasColumnName("MR2C"); + + b.Property<short?>("Passnum") + .HasColumnType("smallint") + .HasColumnName("PASSNUM"); + + b.Property<float?>("Spare1") + .HasColumnType("real") + .HasColumnName("SPARE1"); + + b.Property<float?>("Spare2") + .HasColumnType("real") + .HasColumnName("SPARE2"); + + b.Property<float?>("Spare3") + .HasColumnType("real") + .HasColumnName("SPARE3"); + + b.Property<float?>("Spare4") + .HasColumnType("real") + .HasColumnName("SPARE4"); + + b.Property<float?>("Spare5") + .HasColumnType("real") + .HasColumnName("SPARE5"); + + b.Property<float?>("Spare6") + .HasColumnType("real") + .HasColumnName("SPARE6"); + + b.Property<float?>("Spare7") + .HasColumnType("real") + .HasColumnName("SPARE7"); + + b.Property<float?>("Spare8") + .HasColumnType("real") + .HasColumnName("SPARE8"); + + b.Property<float?>("Spare9") + .HasColumnType("real") + .HasColumnName("SPARE9"); + + b.Property<int?>("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.DataSaubStat", 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.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.DrillTest", b => + { + b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry") + .WithMany() + .HasForeignKey("IdTelemetry") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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.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.ProcessMapPlanDrilling", b => + { + b.HasOne("AsbCloudDb.Model.User", "Author") + .WithMany() + .HasForeignKey("IdAuthor") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.User", "Editor") + .WithMany() + .HasForeignKey("IdEditor") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("AsbCloudDb.Model.ProcessMaps.ProcessMapPlanDrilling", "Previous") + .WithMany() + .HasForeignKey("IdPrevious"); + + 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("Author"); + + b.Navigation("Editor"); + + b.Navigation("Previous"); + + b.Navigation("Well"); + + b.Navigation("WellSectionType"); + }); + + modelBuilder.Entity("AsbCloudDb.Model.ProcessMaps.ProcessMapPlanReam", b => + { + b.HasOne("AsbCloudDb.Model.User", "Author") + .WithMany() + .HasForeignKey("IdAuthor") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.User", "Editor") + .WithMany() + .HasForeignKey("IdEditor"); + + 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("Author"); + + b.Navigation("Editor"); + + 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.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.WellSections.WellSectionPlan", b => + { + b.HasOne("AsbCloudDb.Model.WellSectionType", "SectionType") + .WithMany() + .HasForeignKey("IdSectionType") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AsbCloudDb.Model.Well", "Well") + .WithMany() + .HasForeignKey("IdWell") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("SectionType"); + + b.Navigation("Well"); + }); + + 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/20240329070104_Update_WellOperationCategory_IdConditioning.cs b/AsbCloudDb/Migrations/20240329070104_Update_WellOperationCategory_IdConditioning.cs new file mode 100644 index 00000000..e539a2be --- /dev/null +++ b/AsbCloudDb/Migrations/20240329070104_Update_WellOperationCategory_IdConditioning.cs @@ -0,0 +1,32 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace AsbCloudDb.Migrations +{ + /// <inheritdoc /> + public partial class Update_WellOperationCategory_IdConditioning : Migration + { + /// <inheritdoc /> + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.UpdateData( + table: "t_well_operation_category", + keyColumn: "id", + keyValue: 5007, + column: "name", + value: "Проработка"); + } + + /// <inheritdoc /> + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.UpdateData( + table: "t_well_operation_category", + keyColumn: "id", + keyValue: 5007, + column: "name", + value: "Проработка перед наращиванием"); + } + } +} diff --git a/AsbCloudDb/Migrations/AsbCloudDbContextModelSnapshot.cs b/AsbCloudDb/Migrations/AsbCloudDbContextModelSnapshot.cs index 9957e235..949de090 100644 --- a/AsbCloudDb/Migrations/AsbCloudDbContextModelSnapshot.cs +++ b/AsbCloudDb/Migrations/AsbCloudDbContextModelSnapshot.cs @@ -63,9 +63,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdDeposit"); - b.ToTable("t_cluster"); - - b.HasComment("Кусты"); + b.ToTable("t_cluster", t => + { + t.HasComment("Кусты"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.Company", b => @@ -264,9 +265,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdWell"); - b.ToTable("t_contact"); - - b.HasComment("Контакты"); + b.ToTable("t_contact", t => + { + t.HasComment("Контакты"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.DailyReports.DailyReport", b => @@ -312,9 +314,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdWell", "Date") .IsUnique(); - b.ToTable("t_daily_report"); - - b.HasComment("Ежедневные отчёты"); + b.ToTable("t_daily_report", t => + { + t.HasComment("Ежедневные отчёты"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.DataSaubStat", b => @@ -442,9 +445,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdTelemetry"); - b.ToTable("t_data_saub_stat"); - - b.HasComment("Кеш-таблица для хранения данных для РТК-отчета"); + b.ToTable("t_data_saub_stat", t => + { + t.HasComment("Кеш-таблица для хранения данных для РТК-отчета"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.Deposit", b => @@ -478,9 +482,10 @@ namespace AsbCloudDb.Migrations b.HasKey("Id"); - b.ToTable("t_deposit"); - - b.HasComment("Месторождение"); + b.ToTable("t_deposit", null, t => + { + t.HasComment("Месторождение"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.DetectedOperation", b => @@ -548,75 +553,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdTelemetry"); - b.ToTable("t_detected_operation"); - - b.HasComment("автоматически определенные операции по телеметрии"); - }); - - modelBuilder.Entity("AsbCloudDb.Model.Driller", b => - { - b.Property<int>("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id") - .HasComment("Идентификатор"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); - - b.Property<string>("Name") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("character varying(255)") - .HasColumnName("name") - .HasComment("Имя"); - - b.Property<string>("Patronymic") - .HasMaxLength(255) - .HasColumnType("character varying(255)") - .HasColumnName("patronymic") - .HasComment("Отчество"); - - b.Property<string>("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<int>("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); - - b.Property<int>("IdFileCategory") - .HasColumnType("integer") - .HasColumnName("id_file_category"); - - b.Property<int>("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("части программ бурения"); + b.ToTable("t_detected_operation", null, t => + { + t.HasComment("автоматически определенные операции по телеметрии"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.DrillTest", b => @@ -651,9 +591,78 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdTelemetry"); - b.ToTable("t_drill_test"); + b.ToTable("t_drill_test", null, t => + { + t.HasComment("Drill_test"); + }); + }); - b.HasComment("Drill_test"); + modelBuilder.Entity("AsbCloudDb.Model.Driller", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id") + .HasComment("Идентификатор"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<string>("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("name") + .HasComment("Имя"); + + b.Property<string>("Patronymic") + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("patronymic") + .HasComment("Отчество"); + + b.Property<string>("Surname") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("surname") + .HasComment("Фамилия"); + + b.HasKey("Id"); + + b.ToTable("t_driller", null, t => + { + t.HasComment("Бурильщик"); + }); + }); + + modelBuilder.Entity("AsbCloudDb.Model.DrillingProgramPart", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<int>("IdFileCategory") + .HasColumnType("integer") + .HasColumnName("id_file_category"); + + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well"); + + b.HasKey("Id"); + + b.HasIndex("IdFileCategory"); + + b.HasIndex("IdWell", "IdFileCategory") + .IsUnique(); + + b.ToTable("t_drilling_program_part", null, t => + { + t.HasComment("части программ бурения"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.Faq", b => @@ -728,9 +737,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdAuthorQuestion"); - b.ToTable("t_faq"); - - b.HasComment("вопросы пользователей"); + b.ToTable("t_faq", null, t => + { + t.HasComment("вопросы пользователей"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.FileCategory", b => @@ -755,9 +765,10 @@ namespace AsbCloudDb.Migrations b.HasKey("Id"); - b.ToTable("t_file_category"); - - b.HasComment("Категории файлов"); + b.ToTable("t_file_category", null, t => + { + t.HasComment("Категории файлов"); + }); b.HasData( new @@ -1155,9 +1166,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdWell"); - b.ToTable("t_file_info"); - - b.HasComment("Файлы всех категорий"); + b.ToTable("t_file_info", null, t => + { + t.HasComment("Файлы всех категорий"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.FileMark", b => @@ -1206,9 +1218,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdUser"); - b.ToTable("t_file_mark"); - - b.HasComment("Действия с файлами."); + b.ToTable("t_file_mark", null, t => + { + t.HasComment("Действия с файлами."); + }); }); modelBuilder.Entity("AsbCloudDb.Model.GTR.WitsItemFloat", b => @@ -1235,9 +1248,10 @@ namespace AsbCloudDb.Migrations b.HasKey("IdTelemetry", "IdRecord", "IdItem", "DateTime"); - b.ToTable("t_wits_float"); - - b.HasComment("таблица данных ГТИ с типом значения float"); + b.ToTable("t_wits_float", null, t => + { + t.HasComment("таблица данных ГТИ с типом значения float"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.GTR.WitsItemInt", b => @@ -1264,9 +1278,10 @@ namespace AsbCloudDb.Migrations b.HasKey("IdTelemetry", "IdRecord", "IdItem", "DateTime"); - b.ToTable("t_wits_int"); - - b.HasComment("таблица данных ГТИ с типом значения int"); + b.ToTable("t_wits_int", null, t => + { + t.HasComment("таблица данных ГТИ с типом значения int"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.GTR.WitsItemString", b => @@ -1294,9 +1309,10 @@ namespace AsbCloudDb.Migrations b.HasKey("IdTelemetry", "IdRecord", "IdItem", "DateTime"); - b.ToTable("t_wits_string"); - - b.HasComment("таблица данных ГТИ с типом значения string"); + b.ToTable("t_wits_string", null, t => + { + t.HasComment("таблица данных ГТИ с типом значения string"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.HelpPage", b => @@ -1334,9 +1350,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdCategory"); - b.ToTable("t_help_page"); - - b.HasComment("Справки"); + b.ToTable("t_help_page", null, t => + { + t.HasComment("Справки"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.LimitingParameter", b => @@ -1376,9 +1393,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdTelemetry"); - b.ToTable("t_limiting_parameter"); - - b.HasComment("Ограничения по параметрам телеметрии"); + b.ToTable("t_limiting_parameter", null, t => + { + t.HasComment("Ограничения по параметрам телеметрии"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.Manuals.Manual", b => @@ -1424,9 +1442,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdDirectory"); - b.ToTable("t_manual"); - - b.HasComment("Инструкции"); + b.ToTable("t_manual", null, t => + { + t.HasComment("Инструкции"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.Manuals.ManualDirectory", b => @@ -1453,9 +1472,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdParent"); - b.ToTable("t_manual_directory"); - - b.HasComment("Директория для инструкций"); + b.ToTable("t_manual_directory", null, t => + { + t.HasComment("Директория для инструкций"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.Measure", b => @@ -1499,9 +1519,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdWell"); - b.ToTable("t_measure"); - - b.HasComment("Таблица c данными для вкладки 'Последние данные'"); + b.ToTable("t_measure", null, t => + { + t.HasComment("Таблица c данными для вкладки 'Последние данные'"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.MeasureCategory", b => @@ -1526,9 +1547,10 @@ namespace AsbCloudDb.Migrations b.HasKey("Id"); - b.ToTable("t_measure_category"); - - b.HasComment("Категория последних данных"); + b.ToTable("t_measure_category", null, t => + { + t.HasComment("Категория последних данных"); + }); b.HasData( new @@ -1608,9 +1630,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdUser"); - b.ToTable("t_notification"); - - b.HasComment("Уведомления"); + b.ToTable("t_notification", null, t => + { + t.HasComment("Уведомления"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.NotificationCategory", b => @@ -1629,9 +1652,10 @@ namespace AsbCloudDb.Migrations b.HasKey("Id"); - b.ToTable("t_notification_category"); - - b.HasComment("Категории уведомлений"); + b.ToTable("t_notification_category", null, t => + { + t.HasComment("Категории уведомлений"); + }); b.HasData( new @@ -1687,9 +1711,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdWell"); - b.ToTable("t_operationvalue"); - - b.HasComment("Целевые/нормативные показатели операции"); + b.ToTable("t_operationvalue", null, t => + { + t.HasComment("Целевые/нормативные показатели операции"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.Permission", b => @@ -1716,9 +1741,10 @@ namespace AsbCloudDb.Migrations b.HasKey("Id"); - b.ToTable("t_permission"); - - b.HasComment("Разрешения на доступ к данным"); + b.ToTable("t_permission", null, t => + { + t.HasComment("Разрешения на доступ к данным"); + }); b.HasData( new @@ -2742,9 +2768,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdWellSectionType"); - b.ToTable("t_process_map_plan_drilling"); - - b.HasComment("РТК план бурение"); + b.ToTable("t_process_map_plan_drilling", null, t => + { + t.HasComment("РТК план бурение"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.ProcessMaps.ProcessMapPlanReam", b => @@ -2862,9 +2889,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdWellSectionType"); - b.ToTable("t_process_map_plan_ream"); - - b.HasComment("РТК проработка скважины"); + b.ToTable("t_process_map_plan_ream", null, t => + { + t.HasComment("РТК проработка скважины"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.RelationCompanyWell", b => @@ -2881,9 +2909,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdWell"); - b.ToTable("t_relation_company_well"); - - b.HasComment("отношение скважин и компаний"); + b.ToTable("t_relation_company_well", null, t => + { + t.HasComment("отношение скважин и компаний"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.RelationContactWell", b => @@ -2900,7 +2929,7 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdUser"); - b.ToTable("t_relation_contact_well"); + b.ToTable("t_relation_contact_well", (string)null); }); modelBuilder.Entity("AsbCloudDb.Model.RelationUserDrillingProgramPart", b => @@ -2923,9 +2952,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdDrillingProgramPart"); - b.ToTable("t_relation_user_drilling_program_part"); - - b.HasComment("Отношение пользователей и частей ПБ"); + b.ToTable("t_relation_user_drilling_program_part", null, t => + { + t.HasComment("Отношение пользователей и частей ПБ"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.RelationUserRolePermission", b => @@ -2942,9 +2972,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdPermission"); - b.ToTable("t_relation_user_role_permission"); - - b.HasComment("Отношение ролей пользователей и разрешений доступа"); + b.ToTable("t_relation_user_role_permission", null, t => + { + t.HasComment("Отношение ролей пользователей и разрешений доступа"); + }); b.HasData( new @@ -4259,9 +4290,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdInclude"); - b.ToTable("t_relation_user_role_user_role"); - - b.HasComment("Отношение ролей к ролям"); + b.ToTable("t_relation_user_role_user_role", null, t => + { + t.HasComment("Отношение ролей к ролям"); + }); b.HasData( new @@ -4550,9 +4582,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdUserRole"); - b.ToTable("t_relation_user_user_role"); - - b.HasComment("Отношение пользователей и ролей"); + b.ToTable("t_relation_user_user_role", null, t => + { + t.HasComment("Отношение пользователей и ролей"); + }); b.HasData( new @@ -4606,9 +4639,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdWell"); - b.ToTable("t_report_property"); - - b.HasComment("Отчеты с данными по буровым"); + b.ToTable("t_report_property", null, t => + { + t.HasComment("Отчеты с данными по буровым"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.Schedule", b => @@ -4657,9 +4691,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdWell"); - b.ToTable("t_schedule"); - - b.HasComment("График работы бурильщика"); + b.ToTable("t_schedule", null, t => + { + t.HasComment("График работы бурильщика"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.SetpointsRequest", b => @@ -4712,9 +4747,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdWell"); - b.ToTable("t_setpoints_rquest"); - - b.HasComment("Запросы на изменение уставок панели оператора"); + b.ToTable("t_setpoints_rquest", null, t => + { + t.HasComment("Запросы на изменение уставок панели оператора"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.Subsystem", b => @@ -4739,9 +4775,10 @@ namespace AsbCloudDb.Migrations b.HasKey("Id"); - b.ToTable("t_subsystem"); - - b.HasComment("Описание подсистем"); + b.ToTable("t_subsystem", null, t => + { + t.HasComment("Описание подсистем"); + }); b.HasData( new @@ -4807,9 +4844,10 @@ namespace AsbCloudDb.Migrations b.HasIndex(new[] { "RemoteUid" }, "t_telemetry_remote_uid_index"); - b.ToTable("t_telemetry"); - - b.HasComment("таблица привязки телеметрии от комплектов к конкретной скважине."); + b.ToTable("t_telemetry", null, t => + { + t.HasComment("таблица привязки телеметрии от комплектов к конкретной скважине."); + }); }); modelBuilder.Entity("AsbCloudDb.Model.TelemetryDataSaub", b => @@ -5025,9 +5063,10 @@ namespace AsbCloudDb.Migrations b.HasKey("IdTelemetry", "DateTime"); - b.ToTable("t_telemetry_data_saub"); - - b.HasComment("набор основных данных по SAUB"); + b.ToTable("t_telemetry_data_saub", null, t => + { + t.HasComment("набор основных данных по SAUB"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.TelemetryDataSaubStat", b => @@ -5056,7 +5095,9 @@ namespace AsbCloudDb.Migrations .HasColumnType("integer") .HasColumnName("id_telemetry"); - b.ToView("mw_telemetry_datas_saub_stat"); + b.ToTable((string)null); + + b.ToView("mw_telemetry_datas_saub_stat", (string)null); }); modelBuilder.Entity("AsbCloudDb.Model.TelemetryDataSpin", b => @@ -5122,9 +5163,10 @@ namespace AsbCloudDb.Migrations b.HasKey("IdTelemetry", "DateTime"); - b.ToTable("t_telemetry_data_spin"); - - b.HasComment("набор основных данных по SpinMaster"); + b.ToTable("t_telemetry_data_spin", null, t => + { + t.HasComment("набор основных данных по SpinMaster"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.TelemetryEvent", b => @@ -5148,9 +5190,10 @@ namespace AsbCloudDb.Migrations b.HasKey("IdTelemetry", "IdEvent"); - b.ToTable("t_telemetry_event"); - - b.HasComment("Справочник событий. События формируют сообщения. Разделено по версиям посылок от телеметрии."); + b.ToTable("t_telemetry_event", null, t => + { + t.HasComment("Справочник событий. События формируют сообщения. Разделено по версиям посылок от телеметрии."); + }); }); modelBuilder.Entity("AsbCloudDb.Model.TelemetryMessage", b => @@ -5208,9 +5251,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdTelemetry"); - b.ToTable("t_telemetry_message"); - - b.HasComment("Сообщения на буровых"); + b.ToTable("t_telemetry_message", null, t => + { + t.HasComment("Сообщения на буровых"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.TelemetryUser", b => @@ -5245,9 +5289,10 @@ namespace AsbCloudDb.Migrations b.HasKey("IdTelemetry", "IdUser"); - b.ToTable("t_telemetry_user"); - - b.HasComment("Пользователи панели САУБ. Для сообщений."); + b.ToTable("t_telemetry_user", null, t => + { + t.HasComment("Пользователи панели САУБ. Для сообщений."); + }); }); modelBuilder.Entity("AsbCloudDb.Model.TelemetryWirelineRunOut", b => @@ -5287,9 +5332,10 @@ namespace AsbCloudDb.Migrations b.HasKey("IdTelemetry"); - b.ToTable("t_telemetry_wireline_run_out"); - - b.HasComment("Наработка талевого каната"); + b.ToTable("t_telemetry_wireline_run_out", null, t => + { + t.HasComment("Наработка талевого каната"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.Trajectory.TrajectoryFact", b => @@ -5352,9 +5398,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdWell"); - b.ToTable("t_trajectory_fact"); - - b.HasComment("Загрузка фактической траектории"); + b.ToTable("t_trajectory_fact", null, t => + { + t.HasComment("Загрузка фактической траектории"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.Trajectory.TrajectoryPlan", b => @@ -5422,9 +5469,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdWell"); - b.ToTable("t_trajectory_plan"); - - b.HasComment("Загрузка плановой траектории"); + b.ToTable("t_trajectory_plan", null, t => + { + t.HasComment("Загрузка плановой траектории"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.User", b => @@ -5502,9 +5550,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("Login") .IsUnique(); - b.ToTable("t_user"); - - b.HasComment("Пользователи облака"); + b.ToTable("t_user", null, t => + { + t.HasComment("Пользователи облака"); + }); b.HasData( new @@ -5542,9 +5591,10 @@ namespace AsbCloudDb.Migrations b.HasKey("Id"); - b.ToTable("t_user_role"); - - b.HasComment("Роли пользователей в системе"); + b.ToTable("t_user_role", null, t => + { + t.HasComment("Роли пользователей в системе"); + }); b.HasData( new @@ -5880,9 +5930,53 @@ namespace AsbCloudDb.Migrations b.HasKey("IdUser", "Key"); - b.ToTable("t_user_settings"); + b.ToTable("t_user_settings", null, t => + { + t.HasComment("настройки интерфейса пользователя"); + }); + }); - b.HasComment("настройки интерфейса пользователя"); + modelBuilder.Entity("AsbCloudDb.Model.WITS.RecordBase", b => + { + b.Property<int>("IdTelemetry") + .HasColumnType("integer") + .HasColumnName("id_telemetry"); + + b.Property<DateTimeOffset>("DateTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property<short?>("Actcod") + .HasColumnType("smallint") + .HasColumnName("ACTCOD"); + + b.Property<int?>("Date") + .HasColumnType("integer") + .HasColumnName("DATE"); + + b.Property<short?>("Recid") + .HasColumnType("smallint") + .HasColumnName("RECID"); + + b.Property<int?>("Seqid") + .HasColumnType("integer") + .HasColumnName("SEQID"); + + b.Property<short?>("Stknum") + .HasColumnType("smallint") + .HasColumnName("STKNUM"); + + b.Property<int?>("Time") + .HasColumnType("integer") + .HasColumnName("TIME"); + + b.Property<string>("Wellid") + .HasColumnType("text") + .HasColumnName("WELLID"); + + b.HasKey("IdTelemetry", "DateTime"); + + b.ToTable("t_telemetry_wits_base", (string)null); }); modelBuilder.Entity("AsbCloudDb.Model.Well", b => @@ -5940,9 +6034,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdWellType"); - b.ToTable("t_well"); - - b.HasComment("скважины"); + b.ToTable("t_well", null, t => + { + t.HasComment("скважины"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.WellComposite", b => @@ -5968,9 +6063,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdWellSrc"); - b.ToTable("t_well_composite"); - - b.HasComment("Композитная скважина"); + b.ToTable("t_well_composite", null, t => + { + t.HasComment("Композитная скважина"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.WellFinalDocument", b => @@ -5994,9 +6090,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdUser"); - b.ToTable("t_well_final_documents"); - - b.HasComment("Дело скважины"); + b.ToTable("t_well_final_documents", null, t => + { + t.HasComment("Дело скважины"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.WellOperation", b => @@ -6083,9 +6180,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdWellSectionType"); - b.ToTable("t_well_operation"); - - b.HasComment("Данные по операциям на скважине"); + b.ToTable("t_well_operation", null, t => + { + t.HasComment("Данные по операциям на скважине"); + }); }); modelBuilder.Entity("AsbCloudDb.Model.WellOperationCategory", b => @@ -6124,9 +6222,10 @@ namespace AsbCloudDb.Migrations b.HasIndex("IdParent"); - b.ToTable("t_well_operation_category"); - - b.HasComment("Справочник операций на скважине"); + b.ToTable("t_well_operation_category", null, t => + { + t.HasComment("Справочник операций на скважине"); + }); b.HasData( new @@ -6385,7 +6484,7 @@ namespace AsbCloudDb.Migrations IdParent = 4003, KeyValueName = "dT", KeyValueUnits = "мин", - Name = "Проработка перед наращиванием" + Name = "Проработка" }, new { @@ -7213,65 +7312,6 @@ namespace AsbCloudDb.Migrations }); }); - modelBuilder.Entity("AsbCloudDb.Model.WellSections.WellSectionPlan", b => - { - b.Property<int>("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); - - b.Property<double>("DepthEnd") - .HasColumnType("double precision") - .HasColumnName("depth_end") - .HasComment("Конечная глубина бурения, м"); - - b.Property<double>("DepthStart") - .HasColumnType("double precision") - .HasColumnName("depth_start") - .HasComment("Начальная глубина бурения, м"); - - b.Property<int>("IdSectionType") - .HasColumnType("integer") - .HasColumnName("id_section_type") - .HasComment("Тип секции"); - - b.Property<int>("IdUser") - .HasColumnType("integer") - .HasColumnName("id_user") - .HasComment("Id пользователя"); - - b.Property<int>("IdWell") - .HasColumnType("integer") - .HasColumnName("id_well") - .HasComment("Id скважины"); - - b.Property<double?>("InnerDiameter") - .HasColumnType("double precision") - .HasColumnName("inner_diameter") - .HasComment("Внутренний диаметр"); - - b.Property<DateTimeOffset?>("LastUpdateDate") - .HasColumnType("timestamp with time zone") - .HasColumnName("date_last_update") - .HasComment("Дата последнего обновления"); - - b.Property<double?>("OuterDiameter") - .HasColumnType("double precision") - .HasColumnName("outer_diameter") - .HasComment("Внешний диаметр"); - - b.HasKey("Id"); - - b.HasIndex("IdSectionType"); - - b.HasIndex("IdWell", "IdSectionType") - .IsUnique(); - - b.ToTable("t_well_section_plan"); - }); - modelBuilder.Entity("AsbCloudDb.Model.WellSectionType", b => { b.Property<int>("Id") @@ -7295,9 +7335,10 @@ namespace AsbCloudDb.Migrations b.HasKey("Id"); - b.ToTable("t_well_section_type"); - - b.HasComment("конструкция секции скважины"); + b.ToTable("t_well_section_type", null, t => + { + t.HasComment("конструкция секции скважины"); + }); b.HasData( new @@ -7530,6 +7571,65 @@ namespace AsbCloudDb.Migrations }); }); + modelBuilder.Entity("AsbCloudDb.Model.WellSections.WellSectionPlan", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); + + b.Property<double>("DepthEnd") + .HasColumnType("double precision") + .HasColumnName("depth_end") + .HasComment("Конечная глубина бурения, м"); + + b.Property<double>("DepthStart") + .HasColumnType("double precision") + .HasColumnName("depth_start") + .HasComment("Начальная глубина бурения, м"); + + b.Property<int>("IdSectionType") + .HasColumnType("integer") + .HasColumnName("id_section_type") + .HasComment("Тип секции"); + + b.Property<int>("IdUser") + .HasColumnType("integer") + .HasColumnName("id_user") + .HasComment("Id пользователя"); + + b.Property<int>("IdWell") + .HasColumnType("integer") + .HasColumnName("id_well") + .HasComment("Id скважины"); + + b.Property<double?>("InnerDiameter") + .HasColumnType("double precision") + .HasColumnName("inner_diameter") + .HasComment("Внутренний диаметр"); + + b.Property<DateTimeOffset?>("LastUpdateDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_update") + .HasComment("Дата последнего обновления"); + + b.Property<double?>("OuterDiameter") + .HasColumnType("double precision") + .HasColumnName("outer_diameter") + .HasComment("Внешний диаметр"); + + b.HasKey("Id"); + + b.HasIndex("IdSectionType"); + + b.HasIndex("IdWell", "IdSectionType") + .IsUnique(); + + b.ToTable("t_well_section_plan", (string)null); + }); + modelBuilder.Entity("AsbCloudDb.Model.WellType", b => { b.Property<int>("Id") @@ -7548,9 +7648,10 @@ namespace AsbCloudDb.Migrations b.HasKey("Id"); - b.ToTable("t_well_type"); - - b.HasComment("конструкция скважины"); + b.ToTable("t_well_type", null, t => + { + t.HasComment("конструкция скважины"); + }); b.HasData( new @@ -7565,49 +7666,6 @@ namespace AsbCloudDb.Migrations }); }); - modelBuilder.Entity("AsbCloudDb.Model.WITS.RecordBase", b => - { - b.Property<int>("IdTelemetry") - .HasColumnType("integer") - .HasColumnName("id_telemetry"); - - b.Property<DateTimeOffset>("DateTime") - .HasColumnType("timestamp with time zone") - .HasColumnName("date"); - - b.Property<short?>("Actcod") - .HasColumnType("smallint") - .HasColumnName("ACTCOD"); - - b.Property<int?>("Date") - .HasColumnType("integer") - .HasColumnName("DATE"); - - b.Property<short?>("Recid") - .HasColumnType("smallint") - .HasColumnName("RECID"); - - b.Property<int?>("Seqid") - .HasColumnType("integer") - .HasColumnName("SEQID"); - - b.Property<short?>("Stknum") - .HasColumnType("smallint") - .HasColumnName("STKNUM"); - - b.Property<int?>("Time") - .HasColumnType("integer") - .HasColumnName("TIME"); - - b.Property<string>("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"); @@ -7769,7 +7827,7 @@ namespace AsbCloudDb.Migrations b.HasIndex("TelemetryId"); - b.ToTable("t_telemetry_wits_1"); + b.ToTable("t_telemetry_wits_1", (string)null); }); modelBuilder.Entity("AsbCloudDb.Model.WITS.Record50", b => @@ -7857,7 +7915,7 @@ namespace AsbCloudDb.Migrations b.HasIndex("TelemetryId"); - b.ToTable("t_telemetry_wits_50"); + b.ToTable("t_telemetry_wits_50", (string)null); }); modelBuilder.Entity("AsbCloudDb.Model.WITS.Record60", b => @@ -7909,7 +7967,7 @@ namespace AsbCloudDb.Migrations b.HasIndex("TelemetryId"); - b.ToTable("t_telemetry_wits_60"); + b.ToTable("t_telemetry_wits_60", (string)null); }); modelBuilder.Entity("AsbCloudDb.Model.WITS.Record61", b => @@ -7965,7 +8023,7 @@ namespace AsbCloudDb.Migrations b.HasIndex("TelemetryId"); - b.ToTable("t_telemetry_wits_61"); + b.ToTable("t_telemetry_wits_61", (string)null); }); modelBuilder.Entity("AsbCloudDb.Model.WITS.Record7", b => @@ -8053,7 +8111,7 @@ namespace AsbCloudDb.Migrations b.HasIndex("TelemetryId"); - b.ToTable("t_telemetry_wits_7"); + b.ToTable("t_telemetry_wits_7", (string)null); }); modelBuilder.Entity("AsbCloudDb.Model.WITS.Record8", b => @@ -8257,7 +8315,7 @@ namespace AsbCloudDb.Migrations b.HasIndex("TelemetryId"); - b.ToTable("t_telemetry_wits_8"); + b.ToTable("t_telemetry_wits_8", (string)null); }); modelBuilder.Entity("AsbCloudDb.Model.Cluster", b => @@ -8351,6 +8409,17 @@ namespace AsbCloudDb.Migrations b.Navigation("Telemetry"); }); + 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.DrillingProgramPart", b => { b.HasOne("AsbCloudDb.Model.FileCategory", "FileCategory") @@ -8370,17 +8439,6 @@ namespace AsbCloudDb.Migrations 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") diff --git a/AsbCloudDb/Model/DailyReports/DailyReport.cs b/AsbCloudDb/Model/DailyReports/DailyReport.cs index c521ca54..8bc99470 100644 --- a/AsbCloudDb/Model/DailyReports/DailyReport.cs +++ b/AsbCloudDb/Model/DailyReports/DailyReport.cs @@ -18,7 +18,7 @@ public class DailyReport : IId public int IdWell { get; set; } [Column("date_last_update", TypeName = "timestamp with time zone"), Comment("Дата последнего обновления")] - public DateTime? DateLastUpdate { get; set; } + public DateTimeOffset? DateLastUpdate { get; set; } [Column("date", TypeName = "date"), Comment("Дата формирования отчёта")] public DateOnly Date { get; set; } diff --git a/AsbCloudDb/Model/ItemInfo.cs b/AsbCloudDb/Model/ItemInfo.cs index 3d7e6793..c93a74bf 100644 --- a/AsbCloudDb/Model/ItemInfo.cs +++ b/AsbCloudDb/Model/ItemInfo.cs @@ -12,6 +12,6 @@ namespace AsbCloudDb.Model /// <summary> /// дата последнего обновления блока /// </summary> - public DateTimeOffset LastUpdateDate { get; set; } = DateTimeOffset.Now; + public DateTimeOffset LastUpdateDate { get; set; } = DateTimeOffset.UtcNow; } } diff --git a/AsbCloudDb/Model/Manuals/Manual.cs b/AsbCloudDb/Model/Manuals/Manual.cs index 35b091b5..8ab64735 100644 --- a/AsbCloudDb/Model/Manuals/Manual.cs +++ b/AsbCloudDb/Model/Manuals/Manual.cs @@ -15,8 +15,8 @@ public class Manual : IId [Column("name"), Comment("Название")] public string Name { get; set; } = null!; - [Column("date_download"), Comment("Дата загрузки")] - public DateTime DateDownload { get; set; } + [Column("date_download", TypeName = "timestamp with time zone"), Comment("Дата загрузки")] + public DateTimeOffset DateDownload { get; set; } [Column("id_directory"), Comment("Id директории")] public int IdDirectory { get; set; } diff --git a/AsbCloudDb/Model/Notification.cs b/AsbCloudDb/Model/Notification.cs index 09f718b1..bed84a2b 100644 --- a/AsbCloudDb/Model/Notification.cs +++ b/AsbCloudDb/Model/Notification.cs @@ -25,13 +25,13 @@ public class Notification : IId public string Message { get; set; } = null!; [Column("registration_date"), Comment("Дата регистрации уведомления")] - public DateTime RegistrationDate { get; set; } + public DateTimeOffset RegistrationDate { get; set; } [Column("sent_date"), Comment("Дата отправки уведомления")] - public DateTime? SentDate { get; set; } + public DateTimeOffset? SentDate { get; set; } [Column("read_date"), Comment("Дата прочтения уведомления")] - public DateTime? ReadDate { get; set; } + public DateTimeOffset? ReadDate { get; set; } [Column("id_transport_type"), Comment("Id типа доставки уведомления")] public int IdTransportType { get; set; } diff --git a/AsbCloudDb/Model/WellOperation.cs b/AsbCloudDb/Model/WellOperation.cs index dda4e3e4..9926f0b1 100644 --- a/AsbCloudDb/Model/WellOperation.cs +++ b/AsbCloudDb/Model/WellOperation.cs @@ -67,23 +67,6 @@ namespace AsbCloudDb.Model [JsonIgnore] [ForeignKey(nameof(IdPlan))] public virtual WellOperation? OperationPlan { get; set; } = null!; - - public bool IsSame(WellOperation other) - { - var isSame = IdWell == other.IdWell && - IdWellSectionType == other.IdWellSectionType && - IdCategory == other.IdCategory && - IdType == other.IdType && - IdPlan == other.IdPlan && - DepthStart == other.DepthStart && - DepthEnd == other.DepthEnd && - DateStart == other.DateStart && - DurationHours == other.DurationHours && - CategoryInfo == other.CategoryInfo && - Comment == other.Comment; - - return isSame; - } } } diff --git a/AsbCloudDb/Model/WellOperationCategory.cs b/AsbCloudDb/Model/WellOperationCategory.cs index edba3581..5014ac14 100644 --- a/AsbCloudDb/Model/WellOperationCategory.cs +++ b/AsbCloudDb/Model/WellOperationCategory.cs @@ -154,9 +154,9 @@ namespace AsbCloudDb.Model /// </summary> public const int IdFlashingBeforeConnection = 5005; /// <summary> - /// Проработка перед наращиванием + /// Проработка /// </summary> - public const int IdDevelopment = 5007; + public const int IdConditioning = 5007; /// <summary> /// Шаблонировка во время бурения /// </summary> @@ -278,7 +278,7 @@ namespace AsbCloudDb.Model new () {Id = IdStaticSurveying, IdParent = 4002, Name = "Замер ЗТС (запись MWD)", KeyValueName = "dT", KeyValueUnits = "мин" }, new () {Id = IdFlashingBeforeConnection, IdParent = 4003, Name = "Промывка перед наращиванием", KeyValueName = "dT", KeyValueUnits = "мин" }, new () {Id = 5006, IdParent = 4003, Name = "Проработка во время бурения", KeyValueName = "dT", KeyValueUnits = "мин" }, - new () {Id = IdDevelopment, IdParent = 4003, Name = "Проработка перед наращиванием", KeyValueName = "dT", KeyValueUnits = "мин" }, + new () {Id = IdConditioning, IdParent = 4003, Name = "Проработка", KeyValueName = "dT", KeyValueUnits = "мин" }, new () {Id = IdTemplatingWhileDrilling, IdParent = 4003, Name = "Шаблонировка во время бурения", KeyValueName = "dT", KeyValueUnits = "мин" }, new () {Id = IdTemplating, IdParent = 4003, Name = "Шаблонировка перед наращиванием", KeyValueName = "dT", KeyValueUnits = "мин" }, new () {Id = 5010, IdParent = 4004, Name = "Наращивание", KeyValueName = "dT", KeyValueUnits = "мин" }, diff --git a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj index 0d56b6bd..6bdaf411 100644 --- a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj +++ b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj @@ -45,11 +45,9 @@ <EmbeddedResource Include="Services\Trajectory\Templates\TrajectoryFactManualTemplate.xlsx" /> <EmbeddedResource Include="Services\Trajectory\Templates\TrajectoryPlanTemplate.xlsx" /> <EmbeddedResource Include="Services\WellOperationService\ScheduleReportTemplate.xlsx" /> - <EmbeddedResource Include="Services\WellOperationImport\Files\WellOperationImportTemplate.xlsx" /> - <EmbeddedResource Include="Services\WellOperationImport\Files\Dictionaries\Operations.txt" /> - <EmbeddedResource Include="Services\WellOperationImport\Files\Dictionaries\Sections.txt" /> - <EmbeddedResource Include="Services\WellOperationImport\Files\Dictionaries\OperationAttributes.txt" /> <EmbeddedResource Include="Services\ProcessMaps\Report\ProcessMapReportTemplate.xlsx" /> + <EmbeddedResource Include="Services\WellOperations\Templates\WellOperationFactTemplate.xlsx" /> + <EmbeddedResource Include="Services\WellOperations\Templates\WellOperationPlanTemplate.xlsx" /> </ItemGroup> <ItemGroup> @@ -77,4 +75,5 @@ <HintPath>CommonLibs\AsbWitsInfo.dll</HintPath> </Reference> </ItemGroup> + </Project> diff --git a/AsbCloudInfrastructure/Background/WorkToSendEmail.cs b/AsbCloudInfrastructure/Background/WorkToSendEmail.cs index 57605438..ef8048e9 100644 --- a/AsbCloudInfrastructure/Background/WorkToSendEmail.cs +++ b/AsbCloudInfrastructure/Background/WorkToSendEmail.cs @@ -27,7 +27,7 @@ namespace AsbCloudInfrastructure.Background await notificationService.SendAsync(notification, token); - notification.SentDate = DateTime.UtcNow; + notification.SentDate = DateTimeOffset.UtcNow; await notificationRepository.UpdateAsync(notification, token); } diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index d07de418..1139dd3a 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -14,7 +14,6 @@ using AsbCloudApp.Services.DailyReport; using AsbCloudApp.Services.Notifications; using AsbCloudApp.Services.ProcessMaps; using AsbCloudApp.Services.ProcessMaps.WellDrilling; -using AsbCloudApp.Services.WellOperationImport; using AsbCloudDb.Model; using AsbCloudDb.Model.DailyReports.Blocks.TimeBalance; using AsbCloudDb.Model.Manuals; @@ -36,8 +35,6 @@ using AsbCloudInfrastructure.Services.Subsystems; using AsbCloudInfrastructure.Services.Trajectory; using AsbCloudInfrastructure.Services.Trajectory.Export; using AsbCloudInfrastructure.Services.Trajectory.Parser; -using AsbCloudInfrastructure.Services.WellOperationImport; -using AsbCloudInfrastructure.Services.WellOperationImport.FileParser; using AsbCloudInfrastructure.Services.WellOperationService; using Mapster; using Microsoft.EntityFrameworkCore; @@ -46,6 +43,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using System; using AsbCloudInfrastructure.Services.ProcessMapPlan.Export; +using AsbCloudInfrastructure.Services.WellOperations.Factories; namespace AsbCloudInfrastructure { @@ -160,7 +158,6 @@ namespace AsbCloudInfrastructure services.AddTransient<ITelemetryUserService, TelemetryUserService>(); services.AddTransient<ITimezoneService, TimezoneService>(); services.AddScoped<IWellService, WellService>(); - services.AddTransient<IWellOperationImportService, WellOperationImportService>(); services.AddTransient<IProcessMapReportDrillingExportService, ProcessMapReportDataSaubStatExportService>(); services.AddTransient<IWellOperationRepository, WellOperationRepository>(); services.AddTransient<IDailyReportService, DailyReportService>(); @@ -270,13 +267,6 @@ namespace AsbCloudInfrastructure services.AddTransient<IWellboreService, WellboreService>(); - services.AddTransient<IWellOperationExportService, WellOperationExportService>(); - services.AddTransient<IWellOperationImportService, WellOperationImportService>(); - services.AddTransient<IWellOperationImportTemplateService, WellOperationImportTemplateService>(); - - services.AddTransient<IWellOperationExcelParser<WellOperationImportDefaultOptionsDto>, WellOperationDefaultExcelParser>(); - services.AddTransient<IWellOperationExcelParser<WellOperationImportGazpromKhantosOptionsDto>, WellOperationGazpromKhantosExcelParser>(); - services.AddTransient<DetectedOperationExportService>(); services.AddTransient<IDailyReportService, DailyReportService>(); @@ -300,6 +290,9 @@ namespace AsbCloudInfrastructure services.AddTransient<ProcessMapPlanDrillingExportService>(); services.AddTransient<ProcessMapPlanReamExportService>(); + + services.AddTransient<WellOperationParserFactory>(); + services.AddTransient<WellOperationExportServiceFactory>(); return services; } diff --git a/AsbCloudInfrastructure/Repository/CrudRepositoryBase.cs b/AsbCloudInfrastructure/Repository/CrudRepositoryBase.cs index f21dd487..f5d11f38 100644 --- a/AsbCloudInfrastructure/Repository/CrudRepositoryBase.cs +++ b/AsbCloudInfrastructure/Repository/CrudRepositoryBase.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore.ChangeTracking; namespace AsbCloudInfrastructure.Repository { @@ -86,7 +87,7 @@ namespace AsbCloudInfrastructure.Repository entity.Id = 0; return entity; }); - var entries = new List<Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry>(items.Count()); + var entries = new List<EntityEntry>(items.Count()); foreach (var entity in entities) { var entry = dbSet.Add(entity); @@ -114,6 +115,27 @@ namespace AsbCloudInfrastructure.Repository entry.State = EntityState.Detached; return entry.Entity.Id; } + + public virtual async Task<int> UpdateRangeAsync(IEnumerable<TDto> dtos, CancellationToken token) + { + if (!dtos.Any()) + return 0; + + var ids = dtos.Select(d => d.Id); + + var countExistingEntities = await dbSet + .Where(d => ids.Contains(d.Id)) + .CountAsync(token); + + if (ids.Count() > countExistingEntities) + return ICrudRepository<TDto>.ErrorIdNotFound; + + var entities = dtos.Select(Convert); + var entries = entities.Select(entity => dbSet.Update(entity)).Cast<EntityEntry>().ToList(); + var affected = await dbContext.SaveChangesAsync(token); + entries.ForEach(e => e.State = EntityState.Detached); + return affected; + } /// <inheritdoc/> public virtual Task<int> DeleteAsync(int id, CancellationToken token) @@ -129,6 +151,25 @@ namespace AsbCloudInfrastructure.Repository return affected; } + public virtual async Task<int> DeleteRangeAsync(IEnumerable<int> ids, CancellationToken token) + { + if (!ids.Any()) + return 0; + + var countExistingEntities = await dbSet + .Where(d => ids.Contains(d.Id)) + .CountAsync(token); + + if (ids.Count() > countExistingEntities) + return ICrudRepository<TDto>.ErrorIdNotFound; + + var entities = dbContext.Set<TEntity>().Where(e => ids.Contains(e.Id)); + var entries = entities.Select(entity => dbSet.Remove(entity)).Cast<EntityEntry>().ToList(); + var affected = await dbContext.SaveChangesAsync(token); + entries.ForEach(e => e.State = EntityState.Detached); + return affected; + } + protected virtual TDto Convert(TEntity src) => src.Adapt<TDto>(); protected virtual TEntity Convert(TDto src) => src.Adapt<TEntity>(); diff --git a/AsbCloudInfrastructure/Repository/DailyReportRepository.cs b/AsbCloudInfrastructure/Repository/DailyReportRepository.cs index b82b0ce1..f7f582fa 100644 --- a/AsbCloudInfrastructure/Repository/DailyReportRepository.cs +++ b/AsbCloudInfrastructure/Repository/DailyReportRepository.cs @@ -1,80 +1,85 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; using AsbCloudApp.Data.DailyReport; using AsbCloudApp.Data.DailyReport.Blocks.Sign; using AsbCloudApp.Data.DailyReport.Blocks.Subsystems; using AsbCloudApp.Data.DailyReport.Blocks.TimeBalance; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; +using AsbCloudApp.Services; using AsbCloudDb; using AsbCloudDb.Model; using AsbCloudDb.Model.DailyReports; using Mapster; using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; namespace AsbCloudInfrastructure.Repository; public class DailyReportRepository : CrudRepositoryBase<DailyReportDto, DailyReport>, - IDailyReportRepository + IDailyReportRepository { - public DailyReportRepository(IAsbCloudDbContext dbContext) - : base(dbContext) - { - } + private IWellService wellService; - public async Task<IEnumerable<DailyReportDto>> GetAsync(int idWell, FileReportRequest request, CancellationToken cancellationToken) - { - var skip = request.Skip ?? 0; - var take = request.Take ?? 10; + public DailyReportRepository(IAsbCloudDbContext dbContext, IWellService wellService) + : base(dbContext) + { + this.wellService = wellService; + } - var query = GetQuery().Where(d => d.IdWell == idWell); + public async Task<IEnumerable<DailyReportDto>> GetAsync(int idWell, FileReportRequest request, CancellationToken cancellationToken) + { + var skip = request.Skip ?? 0; + var take = request.Take ?? 10; - if (request.GeDate.HasValue) - query = query.Where(d => d.Date >= request.GeDate.Value); - - if (request.LeDate.HasValue) - query = query.Where(d => d.Date <= request.LeDate.Value); + var query = GetQuery().Where(d => d.IdWell == idWell); - query = request.SortFields?.Any() == true ? - query.SortBy(request.SortFields) : - query.OrderBy(d => d.Date); + if (request.GeDate.HasValue) + query = query.Where(d => d.Date >= request.GeDate.Value); - var entities = await query - .Skip(skip) - .Take(take) - .AsNoTracking() - .ToArrayAsync(cancellationToken); + if (request.LeDate.HasValue) + query = query.Where(d => d.Date <= request.LeDate.Value); - var dtos = entities.Select(Convert); + query = request.SortFields?.Any() == true ? + query.SortBy(request.SortFields) : + query.OrderBy(d => d.Date); - return dtos; - } + var entities = await query + .Skip(skip) + .Take(take) + .AsNoTracking() + .ToArrayAsync(cancellationToken); - public async Task<DailyReportDto?> GetOrDefaultAsync(int idWell, DateOnly date, CancellationToken cancellationToken) - { - var entity = await GetQuery() - .AsNoTracking() - .SingleOrDefaultAsync(d => d.IdWell == idWell && d.Date == date, cancellationToken); + var timezoneOffset = wellService.GetTimezone(idWell).Offset; + var dtos = entities.Select(entity => Convert(entity, timezoneOffset)); - return entity is null ? null : Convert(entity); - } + return dtos; + } - protected override DailyReportDto Convert(DailyReport src) - { - var dto = new DailyReportDto - { - Id = src.Id, - IdWell = src.IdWell, - DateLastUpdate = src.DateLastUpdate, - Date = src.Date, - SignBlock = src.SignBlock?.Adapt<SignBlockDto>(), - TimeBalanceBlock = src.TimeBalanceBlock?.Adapt<TimeBalanceBlockDto>(), - SubsystemBlock = src.SubsystemBlock?.Adapt<SubsystemBlockDto>() - }; - - return dto; - } + public async Task<DailyReportDto?> GetOrDefaultAsync(int idWell, DateOnly date, CancellationToken cancellationToken) + { + var entity = await GetQuery() + .AsNoTracking() + .SingleOrDefaultAsync(d => d.IdWell == idWell && d.Date == date, cancellationToken); + + return entity is null ? null : Convert(entity); + } + + protected DailyReportDto Convert(DailyReport src, TimeSpan timezoneOffset) + { + var dto = new DailyReportDto + { + Id = src.Id, + IdWell = src.IdWell, + DateLastUpdate = src.DateLastUpdate?.ToOffset(timezoneOffset), + Date = src.Date, + SignBlock = src.SignBlock?.Adapt<SignBlockDto>(), + TimeBalanceBlock = src.TimeBalanceBlock?.Adapt<TimeBalanceBlockDto>(), + SubsystemBlock = src.SubsystemBlock?.Adapt<SubsystemBlockDto>() + }; + + return dto; + } } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Repository/DepositRepository.cs b/AsbCloudInfrastructure/Repository/DepositRepository.cs index 7f19f1d7..804d130e 100644 --- a/AsbCloudInfrastructure/Repository/DepositRepository.cs +++ b/AsbCloudInfrastructure/Repository/DepositRepository.cs @@ -4,6 +4,7 @@ using AsbCloudApp.Services; using AsbCloudDb.Model; using Mapster; using Microsoft.EntityFrameworkCore; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -111,7 +112,8 @@ namespace AsbCloudInfrastructure.Repository { var dto = well.Adapt<WellDto>(); dto.WellType = well.WellType.Caption; - dto.LastTelemetryDate = wellService.GetLastTelemetryDate(well.Id); + dto.LastTelemetryDate = wellService.GetLastTelemetryDate(well.Id) + .ToOffset(TimeSpan.FromHours(well.Timezone.Hours)); dto.Cluster = gCluster.Key.Caption; dto.Deposit = gDeposit.Key.Caption; return dto; diff --git a/AsbCloudInfrastructure/Repository/FileRepository.cs b/AsbCloudInfrastructure/Repository/FileRepository.cs index cafc5649..3e97da03 100644 --- a/AsbCloudInfrastructure/Repository/FileRepository.cs +++ b/AsbCloudInfrastructure/Repository/FileRepository.cs @@ -36,9 +36,6 @@ namespace AsbCloudInfrastructure.Repository var query = dbSetConfigured .Where(e => e.IdWell == request.IdWell); - double timezoneOffsetHours = query.FirstOrDefault() - ?.Well.Timezone.Hours ?? 5d; - if (request.IdCategory is not null) query = query.Where(x => x.IdCategory == request.IdCategory); @@ -53,13 +50,13 @@ namespace AsbCloudInfrastructure.Repository if (request.Begin is not null) { - var beginUtc = request.Begin.Value.ToUtcDateTimeOffset(timezoneOffsetHours); + var beginUtc = request.Begin.Value.ToUniversalTime(); query = query.Where(e => e.UploadDate >= beginUtc); } if (request.End is not null) { - var endUtc = request.End.Value.ToUtcDateTimeOffset(timezoneOffsetHours); + var endUtc = request.End.Value.ToUniversalTime(); query = query.Where(e => e.UploadDate <= endUtc); } @@ -184,7 +181,7 @@ namespace AsbCloudInfrastructure.Repository var newFileMark = fileMarkDto.Adapt<FileMark>(); newFileMark.Id = default; - newFileMark.DateCreated = DateTime.UtcNow; + newFileMark.DateCreated = DateTimeOffset.UtcNow; newFileMark.IdUser = idUser; newFileMark.User = null!; @@ -244,7 +241,7 @@ namespace AsbCloudInfrastructure.Repository IdAuthor = newItem.IdAuthor, IdCategory = newItem.IdCategory, Name = newItem.Name, - UploadDate = DateTime.UtcNow, + UploadDate = DateTimeOffset.UtcNow, IsDeleted = false, Size = newItem.Size, }; @@ -278,11 +275,11 @@ namespace AsbCloudInfrastructure.Repository private static FileInfoDto Convert(FileInfo entity, double timezoneOffset) { var dto = entity.Adapt<FileInfoDto>(); - dto.UploadDate = entity.UploadDate.ToRemoteDateTime(timezoneOffset); + dto.UploadDate = entity.UploadDate.ToOffset(TimeSpan.FromHours(timezoneOffset)); dto.FileMarks = entity.FileMarks.Select(m => { var mark = m.Adapt<FileMarkDto>(); - mark.DateCreated = m.DateCreated.ToRemoteDateTime(timezoneOffset); + mark.DateCreated = m.DateCreated.ToOffset(TimeSpan.FromHours(timezoneOffset)); return mark; }); return dto; diff --git a/AsbCloudInfrastructure/Repository/LimitingParameterRepository.cs b/AsbCloudInfrastructure/Repository/LimitingParameterRepository.cs index 8f3c42c1..67fc5960 100644 --- a/AsbCloudInfrastructure/Repository/LimitingParameterRepository.cs +++ b/AsbCloudInfrastructure/Repository/LimitingParameterRepository.cs @@ -39,8 +39,8 @@ namespace AsbCloudInfrastructure.Repository IdWell = request.IdWell, IdTelemetry = x.IdTelemetry, IdFeedRegulator = x.IdFeedRegulator, - DateStart = DateTime.SpecifyKind(x.DateStart.UtcDateTime + timezoneSpan, DateTimeKind.Unspecified), - DateEnd = DateTime.SpecifyKind(x.DateEnd.UtcDateTime + timezoneSpan, DateTimeKind.Unspecified), + DateStart = x.DateStart.ToOffset(timezoneSpan), + DateEnd = x.DateEnd.ToOffset(timezoneSpan), DepthStart = x.DepthStart, DepthEnd = x.DepthEnd }); @@ -56,13 +56,13 @@ namespace AsbCloudInfrastructure.Repository if (request.GtDate.HasValue) { - var gtDate = request.GtDate.Value.ToUtcDateTimeOffset(timezoneHours); + var gtDate = request.GtDate.Value.ToUniversalTime(); query = query.Where(x => x.DateEnd >= gtDate); } if (request.LtDate.HasValue) { - var ltDate = request.LtDate.Value.ToUtcDateTimeOffset(timezoneHours); + var ltDate = request.LtDate.Value.ToUniversalTime(); query = query.Where(x => x.DateStart <= ltDate); } diff --git a/AsbCloudInfrastructure/Repository/NotificationRepository.cs b/AsbCloudInfrastructure/Repository/NotificationRepository.cs index 6f1e4a98..7e184f02 100644 --- a/AsbCloudInfrastructure/Repository/NotificationRepository.cs +++ b/AsbCloudInfrastructure/Repository/NotificationRepository.cs @@ -110,10 +110,10 @@ public class NotificationRepository : CrudRepositoryBase<NotificationDto, Notifi query = query.Where(n => n.IdNotificationCategory == request.IdCategory.Value); if (request.LtSentDate.HasValue) - query = query.Where(n => n.SentDate <= request.LtSentDate.Value); + query = query.Where(n => n.SentDate <= request.LtSentDate.Value.ToUniversalTime()); if (request.LtReadDate.HasValue) - query = query.Where(n => n.ReadDate <= request.LtReadDate.Value); + query = query.Where(n => n.ReadDate <= request.LtReadDate.Value.ToUniversalTime()); dbContext.Notifications.RemoveRange(query); diff --git a/AsbCloudInfrastructure/Repository/ScheduleRepository.cs b/AsbCloudInfrastructure/Repository/ScheduleRepository.cs index 29bf4f5b..e1fa83b8 100644 --- a/AsbCloudInfrastructure/Repository/ScheduleRepository.cs +++ b/AsbCloudInfrastructure/Repository/ScheduleRepository.cs @@ -24,7 +24,7 @@ namespace AsbCloudInfrastructure.Repository this.wellService = wellService; } - public async Task<IEnumerable<ScheduleDto>> GetAsync(int idWell, DateTime workTime, CancellationToken token) + public async Task<IEnumerable<ScheduleDto>> GetAsync(int idWell, DateTimeOffset workTime, CancellationToken token) { var entities = await BuildQuery(idWell, workTime) .AsNoTracking() @@ -33,7 +33,7 @@ namespace AsbCloudInfrastructure.Repository return entities.Select(Convert); } - public async Task<DrillerDto?> GetOrDefaultDrillerAsync(int idWell, DateTime workTime, CancellationToken token) + public async Task<DrillerDto?> GetOrDefaultDrillerAsync(int idWell, DateTimeOffset workTime, CancellationToken token) { var entities = await BuildQuery(idWell, workTime) .AsNoTracking() @@ -43,8 +43,7 @@ namespace AsbCloudInfrastructure.Repository return null; var hoursOffset = wellService.GetTimezone(idWell).Hours; - var remoteDate = workTime.ToUtcDateTimeOffset(hoursOffset).ToRemoteDateTime(hoursOffset); - var time = new TimeOnly(remoteDate.Hour, remoteDate.Minute, remoteDate.Second); + var time = new TimeOnly(workTime.Hour, workTime.Minute, workTime.Second); var entity = entities.FirstOrDefault(s => s.ShiftStart > s.ShiftEnd ^ @@ -69,11 +68,11 @@ namespace AsbCloudInfrastructure.Repository } - private IQueryable<Schedule> BuildQuery(int idWell, DateTime workTime) + private IQueryable<Schedule> BuildQuery(int idWell, DateTimeOffset workTime) { var hoursOffset = wellService.GetTimezone(idWell).Hours; - var workTimeDateTime = workTime.ToUtcDateTimeOffset(hoursOffset); + var workTimeDateTime = workTime.ToUniversalTime(); return GetQuery().Where(s => s.IdWell == idWell && s.DrillStart <= workTimeDateTime @@ -82,19 +81,20 @@ namespace AsbCloudInfrastructure.Repository protected override Schedule Convert(ScheduleDto dto) { - var hoursOffset = wellService.GetTimezone(dto.IdWell).Hours; var entity = base.Convert(dto); - entity.DrillStart = dto.DrillStart.ToUtcDateTimeOffset(hoursOffset); - entity.DrillEnd = dto.DrillEnd.ToUtcDateTimeOffset(hoursOffset); + entity.DrillStart = dto.DrillStart.ToUniversalTime(); + entity.DrillEnd = dto.DrillEnd.ToUniversalTime(); return entity; } protected override ScheduleDto Convert(Schedule entity) { var hoursOffset = wellService.GetTimezone(entity.IdWell).Hours; + var timeSpan = TimeSpan.FromHours(hoursOffset); + var dto = base.Convert(entity); - dto.DrillStart = entity.DrillStart.ToRemoteDateTime(hoursOffset); - dto.DrillEnd = entity.DrillEnd.ToRemoteDateTime(hoursOffset); + dto.DrillStart = entity.DrillStart.ToOffset(timeSpan); + dto.DrillEnd = entity.DrillEnd.ToOffset(timeSpan); return dto; } } diff --git a/AsbCloudInfrastructure/Repository/SetpointsRequestRepository.cs b/AsbCloudInfrastructure/Repository/SetpointsRequestRepository.cs index 838ae15b..2c1f7905 100644 --- a/AsbCloudInfrastructure/Repository/SetpointsRequestRepository.cs +++ b/AsbCloudInfrastructure/Repository/SetpointsRequestRepository.cs @@ -50,15 +50,14 @@ namespace AsbCloudInfrastructure.Repository { var result = base.Convert(src); var timezoneOffsetHours = wellService.GetTimezone(src.IdWell).Hours; - result.UploadDate = src.UploadDate.ToRemoteDateTime(timezoneOffsetHours); + result.UploadDate = src.UploadDate.ToOffset(TimeSpan.FromHours(timezoneOffsetHours)); return result; } protected override SetpointsRequest Convert(SetpointsRequestDto src) { var result = base.Convert(src); - var timezoneOffsetHours = wellService.GetTimezone(src.IdWell).Hours; - result.UploadDate = src.UploadDate.ToUtcDateTimeOffset(timezoneOffsetHours); + result.UploadDate = src.UploadDate.ToUniversalTime(); return result; } } diff --git a/AsbCloudInfrastructure/Repository/TelemetryWirelineRunOutRepository.cs b/AsbCloudInfrastructure/Repository/TelemetryWirelineRunOutRepository.cs index 81427cf6..af2b6438 100644 --- a/AsbCloudInfrastructure/Repository/TelemetryWirelineRunOutRepository.cs +++ b/AsbCloudInfrastructure/Repository/TelemetryWirelineRunOutRepository.cs @@ -5,6 +5,7 @@ using AsbCloudApp.Services; using AsbCloudDb.Model; using Mapster; using Microsoft.EntityFrameworkCore; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -93,14 +94,14 @@ namespace AsbCloudInfrastructure.Repository { var entity = dto.Adapt<TelemetryWirelineRunOut>(); entity.IdTelemetry = idTelemetry; - entity.DateTime = dto.DateTime.ToUtcDateTimeOffset(timezoneOffset); + entity.DateTime = dto.DateTime.ToUniversalTime(); return entity; } private static TelemetryWirelineRunOutDto Convert(TelemetryWirelineRunOut entity, WellDto well, double timezoneOffset) { var dto = entity.Adapt<TelemetryWirelineRunOutDto>(); - dto.DateTime = entity.DateTime.ToRemoteDateTime(timezoneOffset); + dto.DateTime = entity.DateTime.ToOffset(TimeSpan.FromHours(timezoneOffset)); dto.WellInfo = well; return dto; } diff --git a/AsbCloudInfrastructure/Repository/TrajectoryEditableRepository.cs b/AsbCloudInfrastructure/Repository/TrajectoryEditableRepository.cs index 4c8ab283..6aca2284 100644 --- a/AsbCloudInfrastructure/Repository/TrajectoryEditableRepository.cs +++ b/AsbCloudInfrastructure/Repository/TrajectoryEditableRepository.cs @@ -37,11 +37,10 @@ namespace AsbCloudInfrastructure.Repository if (!trajectoryRows.All(r => r.IdWell == idWell)) throw new ArgumentInvalidException(nameof(trajectoryRows), "Все строки должны относиться к одной скважине"); - var offsetHours = wellService.GetTimezone(idWell).Hours; var entities = trajectoryRows .Select(e => { - var entity = Convert(e, offsetHours); + var entity = Convert(e); entity.Id = 0; return entity; }); @@ -52,8 +51,7 @@ namespace AsbCloudInfrastructure.Repository public async Task<int> AddAsync(Tdto trajectoryRow, CancellationToken token) { - var offsetHours = wellService.GetTimezone(trajectoryRow.IdWell).Hours; - var entity = Convert(trajectoryRow, offsetHours); + var entity = Convert(trajectoryRow); entity.Id = 0; db.Set<TEntity>().Add(entity); return await db.SaveChangesAsync(token) @@ -98,8 +96,7 @@ namespace AsbCloudInfrastructure.Repository public async Task<int> UpdateAsync(Tdto row, CancellationToken token) { - var offsetHours = wellService.GetTimezone(row.IdWell).Hours; - var entity = Convert(row, offsetHours); + var entity = Convert(row); db.Set<TEntity>().Update(entity); return await db.SaveChangesAsync(token) .ConfigureAwait(false); @@ -108,14 +105,14 @@ namespace AsbCloudInfrastructure.Repository private static Tdto Convert(TEntity entity, double offsetHours) { var dto = entity.Adapt<Tdto>(); - dto.UpdateDate = entity.UpdateDate.ToRemoteDateTime(offsetHours); + dto.UpdateDate = entity.UpdateDate.ToOffset(TimeSpan.FromHours(offsetHours)); return dto; } - private static TEntity Convert(Tdto dto, double offsetHours) + private static TEntity Convert(Tdto dto) { var entity = dto.Adapt<TEntity>(); - entity.UpdateDate = DateTime.Now.ToUtcDateTimeOffset(offsetHours); + entity.UpdateDate = DateTimeOffset.UtcNow; return entity; } } diff --git a/AsbCloudInfrastructure/Repository/TrajectoryNnbRepository.cs b/AsbCloudInfrastructure/Repository/TrajectoryNnbRepository.cs index a55e465f..69c2cccc 100644 --- a/AsbCloudInfrastructure/Repository/TrajectoryNnbRepository.cs +++ b/AsbCloudInfrastructure/Repository/TrajectoryNnbRepository.cs @@ -38,13 +38,13 @@ namespace AsbCloudInfrastructure.Repository if (request.GeDate.HasValue) { - var geDate = request.GeDate.Value.ToUtcDateTimeOffset(timezone.Hours); + var geDate = request.GeDate.Value.ToUniversalTime(); query = query.Where(r => r.DateTime >= geDate); } if (request.LeDate.HasValue) { - var leDate = request.LeDate.Value.ToUtcDateTimeOffset(timezone.Hours); + var leDate = request.LeDate.Value.ToUniversalTime(); query = query.Where(r => r.DateTime <= leDate); } diff --git a/AsbCloudInfrastructure/Repository/WellOperationCategoryRepository.cs b/AsbCloudInfrastructure/Repository/WellOperationCategoryRepository.cs index 84da5f3d..927a424e 100644 --- a/AsbCloudInfrastructure/Repository/WellOperationCategoryRepository.cs +++ b/AsbCloudInfrastructure/Repository/WellOperationCategoryRepository.cs @@ -1,11 +1,10 @@ -using AsbCloudApp.Data; -using AsbCloudApp.Repositories; +using AsbCloudApp.Repositories; using AsbCloudDb.Model; using Mapster; using Microsoft.Extensions.Caching.Memory; -using System; using System.Collections.Generic; using System.Linq; +using AsbCloudApp.Data.WellOperation; namespace AsbCloudInfrastructure.Repository; diff --git a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs index acdb1ef0..3b67eb54 100644 --- a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs +++ b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs @@ -1,4 +1,11 @@ -using AsbCloudApp.Data; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using AsbCloudApp.Data; +using AsbCloudApp.Data.WellOperation; +using AsbCloudApp.Exceptions; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; @@ -7,697 +14,350 @@ using AsbCloudDb.Model; using Mapster; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Diagnostics; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; namespace AsbCloudInfrastructure.Repository; -/// <summary> -/// репозиторий операций по скважине -/// </summary> -public class WellOperationRepository : IWellOperationRepository +public class WellOperationRepository : CrudRepositoryBase<WellOperationDto, WellOperation>, + IWellOperationRepository { - private const string KeyCacheSections = "OperationsBySectionSummarties"; - - private readonly IAsbCloudDbContext db; - private readonly IMemoryCache memoryCache; - private readonly IWellService wellService; - private readonly IWellOperationCategoryRepository wellOperationCategoryRepository; - - public WellOperationRepository(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService, IWellOperationCategoryRepository wellOperationCategoryRepository) - { - this.db = db; - this.memoryCache = memoryCache; - this.wellService = wellService; - this.wellOperationCategoryRepository = wellOperationCategoryRepository; - } - - public IEnumerable<WellSectionTypeDto> GetSectionTypes() => - memoryCache - .GetOrCreateBasic(db.Set<WellSectionType>()) - .OrderBy(s => s.Order) - .Select(s => s.Adapt<WellSectionTypeDto>()); - - public async Task<WellOperationPlanDto> GetOperationsPlanAsync(int idWell, DateTime? currentDate, CancellationToken token) - { - var timezone = wellService.GetTimezone(idWell); - var request = new WellOperationRequest() - { - IdWell = idWell, - OperationType = WellOperation.IdOperationTypePlan, - }; - - var dtos = await BuildQuery(request) - .AsNoTracking() - .ToArrayAsync(token); - - var dateLastAssosiatedPlanOperation = await GetDateLastAssosiatedPlanOperationAsync(idWell, currentDate, timezone.Hours, token); - - var result = new WellOperationPlanDto() - { - WellOperationsPlan = dtos.Select(Convert), - DateLastAssosiatedPlanOperation = dateLastAssosiatedPlanOperation - }; - - return result; - } - - private async Task<DateTime?> GetDateLastAssosiatedPlanOperationAsync( - int idWell, - DateTime? lessThenDate, - double timeZoneHours, - CancellationToken token) - { - if (lessThenDate is null) - return null; - - var currentDateOffset = lessThenDate.Value.ToUtcDateTimeOffset(timeZoneHours); - var timeZoneOffset = TimeSpan.FromHours(timeZoneHours); - - var lastFactOperation = await db.WellOperations - .Where(o => o.IdWell == idWell) - .Where(o => o.IdType == WellOperation.IdOperationTypeFact) - .Where(o => o.IdPlan != null) - .Where(o => o.DateStart < currentDateOffset) - .Include(x => x.OperationPlan) - .OrderByDescending(x => x.DateStart) - .FirstOrDefaultAsync(token) - .ConfigureAwait(false); - - if (lastFactOperation is not null) - return DateTime.SpecifyKind(lastFactOperation.OperationPlan!.DateStart.UtcDateTime + timeZoneOffset, DateTimeKind.Unspecified); - - return null; - } - - /// <inheritdoc/> - public async Task<IEnumerable<SectionByOperationsDto>> GetSectionsAsync(IEnumerable<int> idsWells, CancellationToken token) - { - var cache = await memoryCache.GetOrCreateAsync(KeyCacheSections, async (entry) => - { - entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30); - - var query = db.Set<WellOperation>() - .GroupBy(operation => new - { - operation.IdWell, - operation.IdType, - operation.IdWellSectionType, - operation.WellSectionType.Caption, - }) - .Select(group => new - { - group.Key.IdWell, - group.Key.IdType, - group.Key.IdWellSectionType, - group.Key.Caption, - - First = group - .OrderBy(operation => operation.DateStart) - .Select(operation => new - { - operation.DateStart, - operation.DepthStart, - }) - .First(), - - Last = group - .OrderByDescending(operation => operation.DateStart) - .Select(operation => new - { - operation.DateStart, - operation.DurationHours, - operation.DepthEnd, - }) - .First(), - }); - var dbData = await query.ToArrayAsync(token); - var sections = dbData.Select( - item => new SectionByOperationsDto - { - IdWell = item.IdWell, - IdType = item.IdType, - IdWellSectionType = item.IdWellSectionType, - - Caption = item.Caption, - - DateStart = item.First.DateStart, - DepthStart = item.First.DepthStart, - - DateEnd = item.Last.DateStart.AddHours(item.Last.DurationHours), - DepthEnd = item.Last.DepthEnd, - }) - .ToArray() - .AsEnumerable(); - - entry.Value = sections; - return sections; - }); - - var sections = cache.Where(s => idsWells.Contains(s.IdWell)); - return sections; - } - - public async Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, int idType, CancellationToken cancellationToken) - { - var timezone = wellService.GetTimezone(idWell); - - var query = db.WellOperations.Where(o => o.IdWell == idWell && o.IdType == idType); - - if (!await query.AnyAsync(cancellationToken)) - return null; - - var minDate = await query.MinAsync(o => o.DateStart, cancellationToken); - var maxDate = await query.MaxAsync(o => o.DateStart, cancellationToken); - - return new DatesRangeDto - { - From = minDate.ToRemoteDateTime(timezone.Hours), - To = maxDate.ToRemoteDateTime(timezone.Hours) - }; - } - - /// <inheritdoc/> - public DateTimeOffset? FirstOperationDate(int idWell) - { - var sections = GetSectionsAsync(new[] { idWell }, CancellationToken.None).Result; - var first = sections.FirstOrDefault(section => section.IdType == WellOperation.IdOperationTypeFact) - ?? sections.FirstOrDefault(section => section.IdType == WellOperation.IdOperationTypePlan); - - return first?.DateStart; - } - - /// <inheritdoc/> - public async Task<IEnumerable<WellOperationDto>> GetAsync( - WellOperationRequest request, - CancellationToken token) - { - var query = BuildQuery(request) - .AsNoTracking(); - - var dtos = await query.ToArrayAsync(token); - - return dtos.Select(Convert); - } - - public async Task<IEnumerable<WellOperationDataDto>> GetAsync( - WellsOperationRequest request, - CancellationToken token) - { - var query = BuildQuery(request) - .AsNoTracking(); - - var dtos = await query.ToArrayAsync(token); - return dtos; - } - - /// <inheritdoc/> - public async Task<PaginationContainer<WellOperationDto>> GetPageAsync( - WellOperationRequest request, - CancellationToken token) - { - var query = BuildQuery(request); - - var result = new PaginationContainer<WellOperationDto> - { - Skip = request.Skip ?? 0, - Take = request.Take ?? 32, - Count = await query.CountAsync(token), - }; - - var dtos = await query.ToArrayAsync(token); - - result.Items = dtos.Select(Convert); - - return result; - } - - /// <inheritdoc/> - public async Task<WellOperationDto?> GetOrDefaultAsync(int id, - CancellationToken token) - { - var entity = await db.WellOperations - .Include(s => s.WellSectionType) - .Include(s => s.OperationCategory) - .FirstOrDefaultAsync(e => e.Id == id, token) - .ConfigureAwait(false); - - if (entity is null) - return null; - - var timezone = wellService.GetTimezone(entity.IdWell); - - var dto = entity.Adapt<WellOperationDto>(); - dto.WellSectionTypeName = entity.WellSectionType.Caption; - dto.DateStart = entity.DateStart.ToRemoteDateTime(timezone.Hours); - dto.CategoryName = entity.OperationCategory.Name; - return dto; - } - - /// <inheritdoc/> - public async Task<IEnumerable<WellGroupOpertionDto>> GetGroupOperationsStatAsync( - WellOperationRequest request, - CancellationToken token) - { - // TODO: Rename controller method - request.OperationType = WellOperation.IdOperationTypeFact; - var query = BuildQuery(request); - var entities = await query - .Select(o => new - { - o.IdCategory, - DurationMinutes = o.DurationHours * 60, - DurationDepth = o.DepthEnd - o.DepthStart - }) - .ToListAsync(token); - var parentRelationDictionary = wellOperationCategoryRepository.Get(true) - .ToDictionary(c => c.Id, c => new - { - c.Name, - c.IdParent - }); - - var dtos = entities - .GroupBy(o => o.IdCategory) - .Select(g => new WellGroupOpertionDto - { - IdCategory = g.Key, - Category = parentRelationDictionary[g.Key].Name, - Count = g.Count(), - MinutesAverage = g.Average(o => o.DurationMinutes), - MinutesMin = g.Min(o => o.DurationMinutes), - MinutesMax = g.Max(o => o.DurationMinutes), - TotalMinutes = g.Sum(o => o.DurationMinutes), - DeltaDepth = g.Sum(o => o.DurationDepth), - IdParent = parentRelationDictionary[g.Key].IdParent - }); - - while (dtos.All(x => x.IdParent != null)) - { - dtos = dtos - .GroupBy(o => o.IdParent!) - .Select(g => - { - var idCategory = g.Key ?? int.MinValue; - var category = parentRelationDictionary.GetValueOrDefault(idCategory); - var newDto = new WellGroupOpertionDto - { - IdCategory = idCategory, - Category = category?.Name ?? "unknown", - Count = g.Sum(o => o.Count), - DeltaDepth = g.Sum(o => o.DeltaDepth), - TotalMinutes = g.Sum(o => o.TotalMinutes), - Items = g.ToList(), - IdParent = category?.IdParent, - }; - return newDto; - }); - } - return dtos; - } - - /// <inheritdoc/> - public async Task<int> InsertRangeAsync( - IEnumerable<WellOperationDto> wellOperationDtos, - CancellationToken token) - { - var firstOperation = wellOperationDtos - .FirstOrDefault(); - if (firstOperation is null) - return 0; - - var idWell = firstOperation.IdWell; - - var timezone = wellService.GetTimezone(idWell); - foreach (var dto in wellOperationDtos) - { - var entity = dto.Adapt<WellOperation>(); - entity.Id = default; - entity.DateStart = dto.DateStart.DateTime.ToUtcDateTimeOffset(timezone.Hours); - entity.IdWell = idWell; - entity.LastUpdateDate = DateTimeOffset.UtcNow; - db.WellOperations.Add(entity); - } - - var result = await db.SaveChangesAsync(token); - if (result > 0) - memoryCache.Remove(KeyCacheSections); - return result; - - } - - /// <inheritdoc/> - public async Task<int> UpdateAsync( - WellOperationDto dto, CancellationToken token) - { - var timezone = wellService.GetTimezone(dto.IdWell); - var entity = dto.Adapt<WellOperation>(); - entity.DateStart = dto.DateStart.DateTime.ToUtcDateTimeOffset(timezone.Hours); - entity.LastUpdateDate = DateTimeOffset.UtcNow; - db.WellOperations.Update(entity); - - var result = await db.SaveChangesAsync(token); - if (result > 0) - memoryCache.Remove(KeyCacheSections); - return result; - } - - /// <inheritdoc/> - public async Task<int> DeleteAsync(IEnumerable<int> ids, - CancellationToken token) - { - var query = db.WellOperations.Where(e => ids.Contains(e.Id)); - db.WellOperations.RemoveRange(query); - - var result = await db.SaveChangesAsync(token); - if (result > 0) - memoryCache.Remove(KeyCacheSections); - return result; - } - - /// <summary> - /// В результате попрежнему требуется конвертировать дату - /// </summary> - /// <param name="request"></param> - /// <param name="token"></param> - /// <returns></returns> - private IQueryable<WellOperationDto> BuildQuery(WellOperationRequest request) - { - var timezone = wellService.GetTimezone(request.IdWell); - var timeZoneOffset = timezone.Hours; - - var query = db.WellOperations - .Include(s => s.WellSectionType) - .Include(s => s.OperationCategory) - .Where(o => o.IdWell == request.IdWell); - - if (request.OperationType.HasValue) - query = query.Where(e => e.IdType == request.OperationType.Value); - - if (request.SectionTypeIds?.Any() == true) - query = query.Where(e => request.SectionTypeIds.Contains(e.IdWellSectionType)); - - if (request.OperationCategoryIds?.Any() == true) - query = query.Where(e => request.OperationCategoryIds.Contains(e.IdCategory)); - - if (request.GeDepth.HasValue) - query = query.Where(e => e.DepthEnd >= request.GeDepth.Value); - - if (request.LeDepth.HasValue) - query = query.Where(e => e.DepthEnd <= request.LeDepth.Value); - - if (request.GeDate.HasValue) - { - var geDateOffset = request.GeDate.Value.ToUtcDateTimeOffset(timeZoneOffset); - query = query.Where(e => e.DateStart >= geDateOffset); - } - - if (request.LtDate.HasValue) - { - var ltDateOffset = request.LtDate.Value.ToUtcDateTimeOffset(timeZoneOffset); - query = query.Where(e => e.DateStart < ltDateOffset); - } - - var currentWellOperations = db.WellOperations - .Where(subOp => subOp.IdWell == request.IdWell); - - var wellOperationsWithCategoryNpt = currentWellOperations - .Where(subOp => subOp.IdType == 1) - .Where(subOp => WellOperationCategory.NonProductiveTimeSubIds.Contains(subOp.IdCategory)); - - var firstOperations = db.Set<WellOperation>() - .Where(o => o.IdWell == request.IdWell) - .GroupBy(o => o.IdType) - .Select(group => new { - idType = group.Key, - Date = group.Min(o => o.DateStart), - }).ToDictionary(e => e.idType, e => e.Date); - - var dtos = query.Select(o => new WellOperationDto - { - Id = o.Id, - IdPlan = o.IdPlan, - IdType = o.IdType, - IdWell = o.IdWell, - IdWellSectionType = o.IdWellSectionType, - IdCategory = o.IdCategory, - IdParentCategory = o.OperationCategory.IdParent, - - CategoryName = o.OperationCategory.Name, - WellSectionTypeName = o.WellSectionType.Caption, - DateStart = o.DateStart, - DepthStart = o.DepthStart, - DepthEnd = o.DepthEnd, - DurationHours = o.DurationHours, - CategoryInfo = o.CategoryInfo, - Comment = o.Comment, - - NptHours = wellOperationsWithCategoryNpt - .Where(subOp => subOp.DateStart <= o.DateStart) - .Select(subOp => subOp.DurationHours) - .Sum(), - - Day = (o.DateStart - firstOperations[o.IdType]) - .TotalDays, - IdUser = o.IdUser, - LastUpdateDate = o.LastUpdateDate, - }); - - if (request.SortFields?.Any() == true) - { - dtos = dtos.SortBy(request.SortFields); - } - - dtos = dtos - .OrderBy(e => e.DateStart) - .ThenBy(e => e.DepthEnd) - .ThenBy(e => e.Id); - - if (request.Skip.HasValue) - dtos = dtos.Skip(request.Skip.Value); - - if (request.Take.HasValue) - dtos = dtos.Take(request.Take.Value); - - return dtos.AsNoTracking(); - } - - /// <summary> - /// Получение данных по запросу - /// </summary> - /// <param name="request"></param> - /// <param name="token"></param> - /// <returns></returns> - private IQueryable<WellOperationDataDto> BuildQuery(WellsOperationRequest request) - { - var query = db.WellOperations - .Where(o => request.IdsWell.Contains(o.IdWell)) - .Where(o => request.OperationType == o.IdType); - - if (request.SectionTypeIds?.Any() == true) - query = query.Where(o => request.SectionTypeIds.Contains(o.IdWellSectionType)); - - if (request.OperationCategoryIds?.Any() == true) - query = query.Where(o => request.OperationCategoryIds.Contains(o.IdCategory)); - - // TODO: Вынести query.Select из метода BuildQuery - var dtos = query.Select(o => new WellOperationDataDto - { - DepthStart = o.DepthStart, - DurationHours = o.DurationHours, - IdCategory = o.IdCategory, - IdWell = o.IdWell, - IdWellSectionType = o.IdWellSectionType, - OperationCategoryName = o.OperationCategory.Name, - WellSectionTypeCaption = o.WellSectionType.Caption, - }); - - if (request.SortFields?.Any() == true) - { - dtos = dtos.SortBy(request.SortFields); - } - - if (request.Skip.HasValue) - dtos = dtos.Skip(request.Skip.Value); - - if (request.Take.HasValue) - dtos = dtos.Take(request.Take.Value); - - return dtos.AsNoTracking(); - } - - private WellOperationDto Convert(WellOperationDto dto) - { - var timezone = wellService.GetTimezone(dto.IdWell); - var timezoneOffset = TimeSpan.FromHours(timezone.Hours); - - var dtoWithRemoteDateTime = dto.Adapt<WellOperationDto>(); - - dtoWithRemoteDateTime.DateStart = dto.DateStart.ToOffset(TimeSpan.FromHours(timezoneOffset.Hours)); - dtoWithRemoteDateTime.LastUpdateDate = dto.LastUpdateDate?.ToOffset(TimeSpan.FromHours(timezoneOffset.Hours)); - - return dtoWithRemoteDateTime; - } - - public async Task<int> RemoveDuplicates(Action<string, double?> onProgressCallback, CancellationToken token) - { - IQueryable<WellOperation> dbset = db.Set<WellOperation>(); - var query = dbset - .GroupBy(o => new { o.IdWell, o.IdType }) - .Select(g => new { g.Key.IdWell, g.Key.IdType }); - - var groups = await query - .ToArrayAsync(token); - - var count = groups.Count(); - var i = 0; - var totalRemoved = 0; - var total = 0; - foreach (var group in groups) - { - var result = await RemoveDuplicatesInGroup(group.IdWell, group.IdType, token); - totalRemoved += result.removed; - total += result.total; - var percent = i++ / count; - var message = $"RemoveDuplicates [{i} of {count}] wellId: {group.IdWell}, opType: {group.IdType}, affected: {result.removed} of {result.total}"; - onProgressCallback?.Invoke(message, percent); - Trace.TraceInformation(message); - } - var messageDone = $"RemoveDuplicates done [{i} of {count}] totalAffected: {totalRemoved} of {total}"; - Trace.TraceInformation(messageDone); - onProgressCallback?.Invoke(messageDone, 1); - return totalRemoved; - } - - private async Task<(int removed, int total)> RemoveDuplicatesInGroup(int idWell, int idType, CancellationToken token) - { - var dbset = db.Set<WellOperation>(); - var entities = await dbset - .Where(o => o.IdWell == idWell && o.IdType == idType) - .OrderBy(o => o.DateStart) - .ToListAsync(token); - - using var entitiesEnumerator = entities.GetEnumerator(); - - if (!entitiesEnumerator.MoveNext()) - return (0, 0); - - var preEntity = entitiesEnumerator.Current; - while (entitiesEnumerator.MoveNext()) - { - var entity = entitiesEnumerator.Current; - if (preEntity.IsSame(entity)) - dbset.Remove(entity); - else - preEntity = entity; - } - var removed = await db.SaveChangesAsync(token); - return (removed, entities.Count); - } - - public async Task<int> TrimOverlapping(DateTimeOffset? geDate, DateTimeOffset leDate, Action<string, double?> onProgressCallback, CancellationToken token) - { - var leDateUtc = leDate.ToUniversalTime(); - IQueryable<WellOperation> query = db.Set<WellOperation>(); - if (geDate.HasValue) - { - var geDateUtc = geDate.Value.ToUniversalTime(); - query = query.Where(e => e.DateStart >= geDateUtc); - } - - var groups = await query - .GroupBy(o => new { o.IdWell, o.IdType }) - .Select(g => new{ - MaxDate = g.Max(o => o.DateStart), - g.Key.IdWell, - g.Key.IdType, - }) - .Where(g => g.MaxDate <= leDateUtc) - .ToArrayAsync(token); - - var count = groups.Count(); - var i = 0; - (int takeover, int trimmed,int total) totalResult = (0, 0, 0); - foreach (var group in groups) - { - var result = await TrimOverlapping(group.IdWell, group.IdType, token); - totalResult.takeover += result.takeover; - totalResult.trimmed += result.trimmed; - totalResult.total += result.total; - var percent = i++ / count; - var message = $"TrimOverlapping [{i} of {count}] wellId: {group.IdWell}, opType: {group.IdType}, takeover:{result.takeover}, trimmed:{result.trimmed}, of {result.total}"; - onProgressCallback?.Invoke(message, percent); - Trace.TraceInformation(message); - } - var messageDone = $"TrimOverlapping done [{i} of {count}] total takeover:{totalResult.takeover}, total trimmed:{totalResult.trimmed} of {totalResult.total}"; - Trace.TraceInformation(messageDone); - onProgressCallback?.Invoke(messageDone, 1); - return totalResult.takeover + totalResult.trimmed; - } - - private async Task<(int takeover, int trimmed, int total)> TrimOverlapping(int idWell, int idType, CancellationToken token) - { - var dbset = db.Set<WellOperation>(); - var query = dbset - .Where(o => o.IdWell == idWell) - .Where(o => o.IdType == idType) - .OrderBy(o => o.DateStart) - .ThenBy(o => o.DepthStart); - - var entities = await query - .ToListAsync(token); - - using var entitiesEnumerator = entities.GetEnumerator(); - - if (!entitiesEnumerator.MoveNext()) - return (0, 0, 0); - - int takeover = 0; - int trimmed = 0; - var preEntity = entitiesEnumerator.Current; - while (entitiesEnumerator.MoveNext()) - { - var entity = entitiesEnumerator.Current; - var preDepth = preEntity.DepthEnd; - - if (preEntity.DepthEnd >= entity.DepthEnd) - { - dbset.Remove(entity); - takeover++; - continue; - } - - if (preEntity.DepthEnd > entity.DepthStart) - { - entity.DepthStart = preEntity.DepthEnd; - trimmed++; - } - - var preDate = preEntity.DateStart.AddHours(preEntity.DurationHours); - - if (preDate >= entity.DateStart.AddHours(entity.DurationHours)) - { - dbset.Remove(entity); - takeover++; - continue; - } - - if (preDate > entity.DateStart) - { - var entityDateEnd = entity.DateStart.AddHours(entity.DurationHours); - entity.DateStart = preDate; - entity.DurationHours = (entityDateEnd - entity.DateStart).TotalHours; - trimmed++; - } - - preEntity = entity; - } - var affected = await db.SaveChangesAsync(token); - return (takeover, trimmed, entities.Count); - } -} + private readonly IMemoryCache memoryCache; + private readonly IWellOperationCategoryRepository wellOperationCategoryRepository; + private readonly IWellService wellService; + + public WellOperationRepository(IAsbCloudDbContext context, + IMemoryCache memoryCache, + IWellOperationCategoryRepository wellOperationCategoryRepository, + IWellService wellService) + : base(context, dbSet => dbSet.Include(e => e.WellSectionType) + .Include(e => e.OperationCategory)) + { + this.memoryCache = memoryCache; + this.wellOperationCategoryRepository = wellOperationCategoryRepository; + this.wellService = wellService; + } + + public IEnumerable<WellSectionTypeDto> GetSectionTypes() => + memoryCache + .GetOrCreateBasic(dbContext.WellSectionTypes) + .OrderBy(s => s.Order) + .Select(s => s.Adapt<WellSectionTypeDto>()); + + public async Task<IEnumerable<WellOperationDto>> GetAsync(WellOperationRequest request, CancellationToken token) + { + var query = BuildQuery(request); + + if (request.Skip.HasValue) + query = query.Skip(request.Skip.Value); + + if (request.Take.HasValue) + query = query.Take(request.Take.Value); + + var entities = await query.AsNoTracking() + .ToArrayAsync(token); + + return await ConvertWithDrillingDaysAndNpvHoursAsync(entities, token); + } + + public async Task<PaginationContainer<WellOperationDto>> GetPageAsync(WellOperationRequest request, CancellationToken token) + { + var skip = request.Skip ?? 0; + var take = request.Take ?? 32; + + var query = BuildQuery(request); + + var entities = await query.Skip(skip) + .Take(take) + .AsNoTracking() + .ToArrayAsync(token); + + var paginationContainer = new PaginationContainer<WellOperationDto> + { + Skip = skip, + Take = take, + Count = await query.CountAsync(token), + Items = await ConvertWithDrillingDaysAndNpvHoursAsync(entities, token) + }; + + return paginationContainer; + } + + public async Task<IEnumerable<WellGroupOpertionDto>> GetGroupOperationsStatAsync(WellOperationRequest request, CancellationToken token) + { + var query = BuildQuery(request); + var entities = await query + .Select(o => new + { + o.IdCategory, + DurationMinutes = o.DurationHours * 60, + DurationDepth = o.DepthEnd - o.DepthStart + }) + .ToArrayAsync(token); + + var parentRelationDictionary = wellOperationCategoryRepository.Get(true) + .ToDictionary(c => c.Id, c => new + { + c.Name, + c.IdParent + }); + + var dtos = entities + .GroupBy(o => o.IdCategory) + .Select(g => new WellGroupOpertionDto + { + IdCategory = g.Key, + Category = parentRelationDictionary[g.Key].Name, + Count = g.Count(), + MinutesAverage = g.Average(o => o.DurationMinutes), + MinutesMin = g.Min(o => o.DurationMinutes), + MinutesMax = g.Max(o => o.DurationMinutes), + TotalMinutes = g.Sum(o => o.DurationMinutes), + DeltaDepth = g.Sum(o => o.DurationDepth), + IdParent = parentRelationDictionary[g.Key].IdParent + }); + + while (dtos.All(x => x.IdParent != null)) + { + dtos = dtos + .GroupBy(o => o.IdParent!) + .Select(g => + { + var idCategory = g.Key ?? int.MinValue; + var category = parentRelationDictionary.GetValueOrDefault(idCategory); + var newDto = new WellGroupOpertionDto + { + IdCategory = idCategory, + Category = category?.Name ?? "unknown", + Count = g.Sum(o => o.Count), + DeltaDepth = g.Sum(o => o.DeltaDepth), + TotalMinutes = g.Sum(o => o.TotalMinutes), + Items = g.ToList(), + IdParent = category?.IdParent, + }; + return newDto; + }); + } + + return dtos; + } + + public async Task<int> InsertRangeAsync(IEnumerable<WellOperationDto> dtos, + bool deleteBeforeInsert, + CancellationToken token) + { + EnsureValidWellOperations(dtos); + + if (!deleteBeforeInsert) + return await InsertRangeAsync(dtos, token); + + var idType = dtos.First().IdType; + var idWell = dtos.First().IdWell; + + var existingOperationIds = await dbContext.WellOperations + .Where(e => e.IdWell == idWell && e.IdType == idType) + .Select(e => e.Id) + .ToArrayAsync(token); + + await DeleteRangeAsync(existingOperationIds, token); + + return await InsertRangeAsync(dtos, token); + } + + public override Task<int> UpdateRangeAsync(IEnumerable<WellOperationDto> dtos, CancellationToken token) + { + EnsureValidWellOperations(dtos); + + return base.UpdateRangeAsync(dtos, token); + } + + private static void EnsureValidWellOperations(IEnumerable<WellOperationDto> dtos) + { + if (dtos.GroupBy(d => d.IdType).Count() > 1) + throw new ArgumentInvalidException(nameof(dtos), "Все операции должны быть одного типа"); + + if (dtos.GroupBy(d => d.IdType).Count() > 1) + throw new ArgumentInvalidException(nameof(dtos), "Все операции должны принадлежать одной скважине"); + } + + private IQueryable<WellOperation> BuildQuery(WellOperationRequest request) + { + var query = GetQuery() + .Where(e => request.IdsWell != null && request.IdsWell.Contains(e.IdWell)) + .OrderBy(e => e.DateStart) + .AsQueryable(); + + if (request.OperationType.HasValue) + query = query.Where(e => e.IdType == request.OperationType.Value); + + if (request.SectionTypeIds?.Any() is true) + query = query.Where(e => request.SectionTypeIds.Contains(e.IdWellSectionType)); + + if (request.OperationCategoryIds?.Any() is true) + query = query.Where(e => request.OperationCategoryIds.Contains(e.IdCategory)); + + if (request.GeDepth.HasValue) + query = query.Where(e => e.DepthEnd >= request.GeDepth.Value); + + if (request.LeDepth.HasValue) + query = query.Where(e => e.DepthEnd <= request.LeDepth.Value); + + if (request.GeDate.HasValue) + { + var geDateUtc = request.GeDate.Value.UtcDateTime; + query = query.Where(e => e.DateStart >= geDateUtc); + } + + if (request.LeDate.HasValue) + { + var leDateUtc = request.LeDate.Value.UtcDateTime; + query = query.Where(e => e.DateStart <= leDateUtc); + } + + if (request.SortFields?.Any() is true) + query = query.SortBy(request.SortFields); + + return query; + } + + public async Task<IEnumerable<SectionByOperationsDto>> GetSectionsAsync(IEnumerable<int> idsWells, CancellationToken token) + { + const string keyCacheSections = "OperationsBySectionSummarties"; + + var cache = await memoryCache.GetOrCreateAsync(keyCacheSections, async (entry) => + { + entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30); + + var query = dbContext.Set<WellOperation>() + .GroupBy(operation => new + { + operation.IdWell, + operation.IdType, + operation.IdWellSectionType, + operation.WellSectionType.Caption, + }) + .Select(group => new + { + group.Key.IdWell, + group.Key.IdType, + group.Key.IdWellSectionType, + group.Key.Caption, + + First = group + .OrderBy(operation => operation.DateStart) + .Select(operation => new + { + operation.DateStart, + operation.DepthStart, + }) + .First(), + + Last = group + .OrderByDescending(operation => operation.DateStart) + .Select(operation => new + { + operation.DateStart, + operation.DurationHours, + operation.DepthEnd, + }) + .First(), + }) + .Where(s => idsWells.Contains(s.IdWell)); + var dbData = await query.ToArrayAsync(token); + var sections = dbData.Select( + item => new SectionByOperationsDto + { + IdWell = item.IdWell, + IdType = item.IdType, + IdWellSectionType = item.IdWellSectionType, + + Caption = item.Caption, + + DateStart = item.First.DateStart, + DepthStart = item.First.DepthStart, + + DateEnd = item.Last.DateStart.AddHours(item.Last.DurationHours), + DepthEnd = item.Last.DepthEnd, + }) + .ToArray() + .AsEnumerable(); + + entry.Value = sections; + return sections; + }); + + return cache; + } + + public async Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, int idType, CancellationToken cancellationToken) + { + var query = dbContext.WellOperations.Where(o => o.IdWell == idWell && o.IdType == idType); + + if (!await query.AnyAsync(cancellationToken)) + return null; + + var timeZoneOffset = wellService.GetTimezone(idWell).Offset; + + var minDate = await query.MinAsync(o => o.DateStart, cancellationToken); + var maxDate = await query.MaxAsync(o => o.DateStart, cancellationToken); + + return new DatesRangeDto + { + From = minDate.ToOffset(timeZoneOffset), + To = maxDate.ToOffset(timeZoneOffset) + }; + } + + private async Task<IEnumerable<WellOperationDto>> ConvertWithDrillingDaysAndNpvHoursAsync(IEnumerable<WellOperation> entities, + CancellationToken token) + { + var idsWell = entities.Select(e => e.IdWell).Distinct(); + + var currentWellOperations = GetQuery() + .Where(entity => idsWell.Contains(entity.IdWell)); + + var dateFirstDrillingOperationByIdWell = await currentWellOperations + .Where(entity => entity.IdType == WellOperation.IdOperationTypeFact) + .GroupBy(entity => entity.IdWell) + .ToDictionaryAsync(g => g.Key, g => g.Min(o => o.DateStart), token); + + var operationsWithNptByIdWell = await currentWellOperations.Where(entity => + entity.IdType == WellOperation.IdOperationTypeFact && + WellOperationCategory.NonProductiveTimeSubIds.Contains(entity.IdCategory)) + .GroupBy(entity => entity.IdWell) + .ToDictionaryAsync(g => g.Key, g => g.Select(o => o), token); + + var dtos = entities.Select(entity => + { + var dto = Convert(entity); + + if (dateFirstDrillingOperationByIdWell.TryGetValue(entity.IdWell, out var dateFirstDrillingOperation)) + dto.Day = (entity.DateStart - dateFirstDrillingOperation).TotalDays; + + if (operationsWithNptByIdWell.TryGetValue(entity.IdWell, out var wellOperationsWithNtp)) + dto.NptHours = wellOperationsWithNtp + .Where(o => o.DateStart <= entity.DateStart) + .Sum(e => e.DurationHours); + + return dto; + }); + + return dtos; + } + + protected override WellOperation Convert(WellOperationDto src) + { + var entity = src.Adapt<WellOperation>(); + entity.DateStart = src.DateStart.UtcDateTime; + return entity; + } + + protected override WellOperationDto Convert(WellOperation src) + { + //TODO: пока такое получение TimeZone скважины, нужно исправить на Lazy + //Хоть мы и тянем данные из кэша, но от получения TimeZone в этом методе нужно избавиться, пока так + var timeZoneOffset = wellService.GetTimezone(src.IdWell).Offset; + var dto = src.Adapt<WellOperationDto>(); + dto.DateStart = src.DateStart.ToOffset(timeZoneOffset); + dto.LastUpdateDate = src.LastUpdateDate.ToOffset(timeZoneOffset); + return dto; + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs index 43fb0abf..21fba541 100644 --- a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs +++ b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs @@ -13,6 +13,7 @@ using AsbCloudApp.Data.DailyReport.Blocks.Sign; using AsbCloudApp.Data.DailyReport.Blocks.Subsystems; using AsbCloudApp.Data.DailyReport.Blocks.TimeBalance; using AsbCloudApp.Data.DailyReport.Blocks.WellOperation; +using AsbCloudApp.Data.WellOperation; using AsbCloudApp.Requests; using AsbCloudApp.Services.DailyReport; using AsbCloudApp.Services.ProcessMaps.WellDrilling; @@ -83,7 +84,7 @@ public class DailyReportService : IDailyReportService editableBlock.IdUser = idUser; editableBlock.LastUpdateDate = DateTime.UtcNow; - dailyReport.DateLastUpdate = DateTime.UtcNow; + dailyReport.DateLastUpdate = DateTimeOffset.UtcNow; if (dailyReport.Id == 0) return await dailyReportRepository.InsertAsync(dailyReport, cancellationToken); @@ -106,15 +107,15 @@ public class DailyReportService : IDailyReportService IdWell = well.Id }; - var geDate = dailyReport.Date.ToDateTime(TimeOnly.MinValue, DateTimeKind.Unspecified); - var ltDate = dailyReport.Date.AddDays(1).ToDateTime(TimeOnly.MinValue, DateTimeKind.Unspecified); - - var factOperationRequest = new WellOperationRequest - { - IdWell = idWell, + var offsetHours = wellService.GetTimezone(dailyReport.IdWell).Hours; + var geDate = new DateTimeOffset(dailyReport.Date, TimeOnly.MinValue, TimeSpan.FromHours(offsetHours)); + var leDate = new DateTimeOffset(dailyReport.Date.AddDays(1), TimeOnly.MinValue, TimeSpan.FromHours(offsetHours)); + + var factOperationRequest = new WellOperationRequest(new []{ idWell }) + { OperationType = WellOperation.IdOperationTypeFact, GeDate = geDate, - LtDate = ltDate + LeDate = leDate }; var factWellOperations = (await wellOperationRepository.GetAsync(factOperationRequest, cancellationToken)) @@ -130,12 +131,12 @@ public class DailyReportService : IDailyReportService dailyReport.DepthStart = factWellOperations.FirstOrDefault()?.DepthStart; dailyReport.DepthEnd = factWellOperations.LastOrDefault()?.DepthEnd; - await UpdateTimeBalanceBlockAsync(dailyReport, factWellOperations, cancellationToken); - await UpdateSubsystemBlockAsync(dailyReport, cancellationToken); + await UpdateTimeBalanceBlockAsync(dailyReport, factWellOperations, geDate, leDate, cancellationToken); + await UpdateSubsystemBlockAsync(dailyReport, geDate, leDate, cancellationToken); - await AddTrajectoryBlockAsync(dailyReport, cancellationToken); - await AddScheduleBlockAsync(dailyReport, cancellationToken); - await AddProcessMapWellDrillingBlockAsync(dailyReport, cancellationToken); + await AddTrajectoryBlockAsync(dailyReport, geDate, leDate, cancellationToken); + await AddScheduleBlockAsync(dailyReport, geDate, cancellationToken); + await AddProcessMapWellDrillingBlockAsync(dailyReport, geDate, leDate, cancellationToken); AddFactWellOperationBlock(dailyReport, factWellOperations); @@ -152,46 +153,43 @@ public class DailyReportService : IDailyReportService Items = Enumerable.Empty<DailyReportDto>() }; - var datesRange = await GetDatesRangeAsync(idWell, cancellationToken); + var datesRange = await wellOperationRepository.GetDatesRangeAsync(idWell, WellOperation.IdOperationTypeFact, cancellationToken); if (datesRange is null) return result; var dailyReports = new List<DailyReportDto>(); - - if (request.GeDate.HasValue) - { - var startDate = new DateTime(request.GeDate.Value.Year, request.GeDate.Value.Month, - request.GeDate.Value.Day); + TimeSpan offset = wellService.GetTimezone(idWell).Offset; - if (startDate.Date >= datesRange.From.Date) + if (request.GeDate.HasValue) + { + var startDate = new DateTimeOffset(request.GeDate.Value, TimeOnly.MinValue, offset); + + if (startDate >= datesRange.From) datesRange.From = startDate; } if (request.LeDate.HasValue) { - var finishDate = new DateTime(request.LeDate.Value.Year, request.LeDate.Value.Month, - request.LeDate.Value.Day); + var finishDate = new DateTimeOffset(request.LeDate.Value, TimeOnly.MinValue, offset); - if (finishDate.Date <= datesRange.To.Date) + if (finishDate <= datesRange.To) datesRange.To = finishDate; } - if (datesRange.From.AddDays(result.Skip) <= datesRange.To) - result.Count = (int)(Math.Ceiling((datesRange.To - DateTime.UnixEpoch).TotalDays) - - Math.Floor((datesRange.From - DateTime.UnixEpoch).TotalDays)) + 1; + result.Count = (int)(Math.Ceiling((datesRange.To - DateTimeOffset.UnixEpoch).TotalDays) + - Math.Floor((datesRange.From - DateTimeOffset.UnixEpoch).TotalDays)); var existingDailyReports = await dailyReportRepository.GetAsync(idWell, request, cancellationToken); var geDateFactWellOperation = datesRange.From.AddDays(result.Skip); - var ltDateFactWellOperation = geDateFactWellOperation.AddDays(result.Take); + var leDateFactWellOperation = geDateFactWellOperation.AddDays(result.Take); - var factWellOperationRequest = new WellOperationRequest + var factWellOperationRequest = new WellOperationRequest(new[] { idWell }) { - IdWell = idWell, OperationType = WellOperation.IdOperationTypeFact, GeDate = geDateFactWellOperation, - LtDate = ltDateFactWellOperation + LeDate = leDateFactWellOperation }; var factWellOperations = await wellOperationRepository.GetAsync(factWellOperationRequest, cancellationToken); @@ -200,7 +198,7 @@ public class DailyReportService : IDailyReportService { for (var day = result.Skip; day - result.Skip < result.Take && datesRange.To.AddDays(-day) >= datesRange.From; day++) { - var dateDailyReport = DateOnly.FromDateTime(datesRange.To.AddDays(-day)); + var dateDailyReport = DateOnly.FromDateTime(datesRange.To.AddDays(-day).DateTime); AddDailyReport(dateDailyReport); } @@ -209,7 +207,7 @@ public class DailyReportService : IDailyReportService { for (var day = result.Skip; day - result.Skip < result.Take && datesRange.From.AddDays(day) <= datesRange.To; day++) { - var dateDailyReport = DateOnly.FromDateTime(datesRange.From.AddDays(day)); + var dateDailyReport = DateOnly.FromDateTime(datesRange.From.AddDays(day).DateTime); AddDailyReport(dateDailyReport); } @@ -228,11 +226,11 @@ public class DailyReportService : IDailyReportService IdWell = idWell }; - var geDate = date.ToDateTime(TimeOnly.MinValue, DateTimeKind.Unspecified); - var leDate = date.AddDays(1).ToDateTime(TimeOnly.MinValue, DateTimeKind.Unspecified); + var geDate = new DateTimeOffset(date, TimeOnly.MinValue, offset); + var leDate = new DateTimeOffset(date.AddDays(1), TimeOnly.MinValue, offset); - var factWellOperationPerDay = factWellOperations.Where(o => o.DateStart.Date >= geDate && - o.DateStart.Date <= leDate); + var factWellOperationPerDay = factWellOperations.Where(o => o.DateStart >= geDate && + o.DateStart <= leDate); AddFactWellOperationBlock(dailyReport, factWellOperationPerDay); @@ -240,36 +238,8 @@ public class DailyReportService : IDailyReportService } } - public async Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, CancellationToken cancellationToken) - { - var timezone = wellService.GetTimezone(idWell); - var currentDate = DateTimeOffset.UtcNow.ToRemoteDateTime(timezone.Hours); - - var factOperationDatesRange = await wellOperationRepository.GetDatesRangeAsync(idWell, WellOperation.IdOperationTypeFact, - cancellationToken); - - if (factOperationDatesRange is null) - return null; - - var from = (factOperationDatesRange.From.AddDays(1) <= DateTime.UtcNow ? - factOperationDatesRange.From : - currentDate.AddDays(-1)) - .Date; - - var to = (factOperationDatesRange.To.AddDays(1) <= DateTime.UtcNow ? - factOperationDatesRange.To : - currentDate.AddDays(-1)) - .Date; - - return new DatesRangeDto - { - From = from, - To = to - }; - } - private async Task UpdateTimeBalanceBlockAsync(DailyReportDto dailyReport, IEnumerable<WellOperationDto> factWellOperations, - CancellationToken cancellationToken) + DateTimeOffset geDateStart, DateTimeOffset leDateEnd, CancellationToken cancellationToken) { const int idWellOperationSlipsTime = 5011; @@ -278,10 +248,7 @@ public class DailyReportService : IDailyReportService dailyReport.TimeBalanceBlock.SectionName = wellOperationRepository.GetSectionTypes() .FirstOrDefault(s => s.Id == dailyReport.TimeBalanceBlock.IdSection)?.Caption; - var geDateStart = dailyReport.Date.ToDateTime(TimeOnly.MinValue, DateTimeKind.Unspecified); - var leDateEnd = dailyReport.Date.AddDays(1).ToDateTime(TimeOnly.MinValue, DateTimeKind.Unspecified); - - dailyReport.TimeBalanceBlock.WellOperationSlipsTimeCount = (await detectedOperationService.GetAsync( + dailyReport.TimeBalanceBlock.WellOperationSlipsTimeCount = (await detectedOperationService.GetAsync( new DetectedOperationByWellRequest { IdsCategories = new[] { idWellOperationSlipsTime }, @@ -296,11 +263,9 @@ public class DailyReportService : IDailyReportService } } - private async Task AddTrajectoryBlockAsync(DailyReportDto dailyReport, CancellationToken cancellationToken) + private async Task AddTrajectoryBlockAsync(DailyReportDto dailyReport, + DateTimeOffset geDate, DateTimeOffset leDate, CancellationToken cancellationToken) { - var geDate = dailyReport.Date.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc); - var leDate = dailyReport.Date.AddDays(1).ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc); - var trajectory = (await trajectoryFactNnbRepository.GetByRequestAsync(new TrajectoryRequest { IdWell = dailyReport.IdWell, @@ -317,11 +282,9 @@ public class DailyReportService : IDailyReportService }; } - private async Task AddScheduleBlockAsync(DailyReportDto dailyReport, CancellationToken cancellationToken) + private async Task AddScheduleBlockAsync(DailyReportDto dailyReport, DateTimeOffset workDate, CancellationToken cancellationToken) { - var workDate = dailyReport.Date.ToDateTime(TimeOnly.MinValue, DateTimeKind.Unspecified); - - dailyReport.ScheduleBlock = (await scheduleRepository.GetAsync(dailyReport.IdWell, workDate, cancellationToken)) + dailyReport.ScheduleBlock = (await scheduleRepository.GetAsync(dailyReport.IdWell, workDate, cancellationToken)) .Select(s => new ScheduleRecordDto { ShiftStart = s.ShiftStart, @@ -332,7 +295,8 @@ public class DailyReportService : IDailyReportService }); } - private async Task UpdateSubsystemBlockAsync(DailyReportDto dailyReport, CancellationToken cancellationToken) + private async Task UpdateSubsystemBlockAsync(DailyReportDto dailyReport, + DateTimeOffset geDate, DateTimeOffset leDate, CancellationToken cancellationToken) { dailyReport.SubsystemBlock ??= new SubsystemBlockDto(); @@ -344,9 +308,6 @@ public class DailyReportService : IDailyReportService { IdWell = dailyReport.IdWell }, cancellationToken); - - var geDate = dailyReport.Date.ToDateTime(TimeOnly.MinValue, DateTimeKind.Unspecified); - var leDate = dailyReport.Date.AddDays(1).ToDateTime(TimeOnly.MinValue, DateTimeKind.Unspecified); var subsystemsStatPerDay = await subsystemService.GetStatAsync(new SubsystemRequest { @@ -370,11 +331,9 @@ public class DailyReportService : IDailyReportService } } - private async Task AddProcessMapWellDrillingBlockAsync(DailyReportDto dailyReport, CancellationToken cancellationToken) + private async Task AddProcessMapWellDrillingBlockAsync(DailyReportDto dailyReport, + DateTimeOffset geDate, DateTimeOffset leDate, CancellationToken cancellationToken) { - var geDate = dailyReport.Date.ToDateTime(TimeOnly.MinValue, DateTimeKind.Unspecified); - var leDate = dailyReport.Date.AddDays(1).ToDateTime(TimeOnly.MinValue, DateTimeKind.Unspecified); - var request = new DataSaubStatRequest(); dailyReport.ProcessMapWellDrillingBlock = (await processMapReportDrillingService.GetAsync(dailyReport.IdWell, request, cancellationToken)).Where(p => p.DateStart >= geDate && p.DateStart <= leDate) @@ -401,7 +360,7 @@ public class DailyReportService : IDailyReportService WellOperations = factWellOperations.GroupBy(o => o.IdCategory) .Select(g => new WellOperationRecordDto { - CategoryName = g.First().CategoryName, + CategoryName = g.First().OperationCategoryName, DurationHours = g.Sum(o => o.DurationHours) }), @@ -413,13 +372,12 @@ public class DailyReportService : IDailyReportService private async Task<bool> IsDateDailyReportInRangeAsync(int idWell, DateOnly dateDailyReport, CancellationToken cancellationToken) { - var datesRange = await GetDatesRangeAsync(idWell, cancellationToken); + var datesRange = await wellOperationRepository.GetDatesRangeAsync(idWell, WellOperation.IdOperationTypeFact, cancellationToken); if (datesRange is null) return false; - - var from = DateOnly.FromDateTime(datesRange.From); - var to = DateOnly.FromDateTime(datesRange.To); + var from = DateOnly.FromDateTime(datesRange.From.DateTime); + var to = DateOnly.FromDateTime(datesRange.To.DateTime); return dateDailyReport >= from && dateDailyReport <= to; } diff --git a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs index fd33c32a..6ed731f6 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs @@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Http.Extensions; using AsbCloudApp.Exceptions; using AsbCloudApp.Services; using AsbCloudApp.Data; +using AsbCloudApp.Data.WellOperation; using AsbCloudInfrastructure.Services.DetectOperations.Detectors; namespace AsbCloudInfrastructure.Services.DetectOperations; diff --git a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs index 36809ec3..b07b6af9 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs @@ -10,8 +10,8 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Data.WellOperation; using AsbCloudInfrastructure.Services.DetectOperations.Detectors; -using AsbCloudInfrastructure.Services.SAUB; namespace AsbCloudInfrastructure.Services.DetectOperations; @@ -20,6 +20,7 @@ public class DetectedOperationService : IDetectedOperationService private readonly IDetectedOperationRepository operationRepository; private readonly IWellOperationCategoryRepository wellOperationCategoryRepository; private readonly IWellService wellService; + private readonly ITelemetryService telemetryService; private readonly IRepositoryWellRelated<OperationValueDto> operationValueRepository; private readonly IScheduleRepository scheduleRepository; private readonly ITelemetryDataSaubService telemetryDataSaubService; @@ -28,12 +29,14 @@ public class DetectedOperationService : IDetectedOperationService new DetectorDrilling(), new DetectorSlipsTime(), new DetectorFlashing(), + new DetectorConditioning(), }; public DetectedOperationService( IDetectedOperationRepository operationRepository, IWellOperationCategoryRepository wellOperationCategoryRepository, IWellService wellService, + ITelemetryService telemetryService, IRepositoryWellRelated<OperationValueDto> operationValueRepository, IScheduleRepository scheduleRepository, ITelemetryDataSaubService telemetryDataSaubService) @@ -41,6 +44,7 @@ public class DetectedOperationService : IDetectedOperationService this.operationRepository = operationRepository; this.wellOperationCategoryRepository = wellOperationCategoryRepository; this.wellService = wellService; + this.telemetryService = telemetryService; this.operationValueRepository = operationValueRepository; this.scheduleRepository = scheduleRepository; this.telemetryDataSaubService = telemetryDataSaubService; @@ -143,6 +147,7 @@ public class DetectedOperationService : IDetectedOperationService const int minOperationLength = 5; const int maxDetectorsInterpolationFrameLength = 30; const int gap = maxDetectorsInterpolationFrameLength + minOperationLength; + var timezone = telemetryService.GetTimezone(idTelemetry); while (true) { @@ -153,13 +158,12 @@ public class DetectedOperationService : IDetectedOperationService Order = 0 }; - var detectableTelemetries = (await telemetryDataSaubService.GetByTelemetryAsync(idTelemetry, request, token)) + var dtos = await telemetryDataSaubService.GetByTelemetryAsync(idTelemetry, request, token); + var detectableTelemetries = dtos .Where(t => t.BlockPosition >= 0) - .Select(t => t as TelemetryNewDataSaubDto) - .Where (t => t is not null) .Select(t => new DetectableTelemetry { - DateTime = t.DateTime, + DateTime = new DateTimeOffset(t.DateTime, timezone.Offset), IdUser = t.IdUser, Mode = t.Mode, WellDepth = t.WellDepth, @@ -269,8 +273,8 @@ public class DetectedOperationService : IDetectedOperationService dto.OperationValue = operationValues.FirstOrDefault(v => v.IdOperationCategory == dto.IdCategory && v.DepthStart <= dto.DepthStart && v.DepthEnd > dto.DepthStart); - - var dateStart = dto.DateStart; + + var dateStart = dto.DateStart.ToUniversalTime(); var timeStart = new TimeDto(dateStart); var driller = schedules.FirstOrDefault(s => s.DrillStart <= dateStart && diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorConditioning.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorConditioning.cs new file mode 100644 index 00000000..9336fb27 --- /dev/null +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorConditioning.cs @@ -0,0 +1,55 @@ +using AsbCloudApp.Data.DetectedOperation; +using AsbCloudDb.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors +{ + public class DetectorConditioning : DetectorAbstract + { + protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end) => + CalcDeltaMinutes(telemetry, begin, end); + + protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation) + { + var currentPoint = telemetry[position]; + if (currentPoint.Pressure < 10) + return false; + + if (currentPoint.RotorSpeed <= 8) + return false; + + var delta = currentPoint.WellDepth - currentPoint.BitDepth; + if (delta < 0.03d) + return false; + + if (currentPoint.BitDepth < 150) + return false; + + return true; + } + + protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation) + { + var currentPoint = telemetry[position]; + + if (currentPoint.Pressure < 10) + return IdReasonOfEnd_PressureIsLo; + if (currentPoint.RotorSpeed <=8) + return IdReasonOfEnd_RotorSpeedIsHi; + if ((currentPoint.WellDepth - currentPoint.BitDepth) < 0.03d) + return IdReasonOfEnd_DeltaWellDepthAndBithDepthIsLo; + if (currentPoint.BitDepth < 150) + return IdReasonOfEnd_BithDepthIsLo; + return IdReasonOfEnd_NotDetected; + } + + protected override (int IdCategory, IDictionary<string, object> ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry, int begin, int end) + { + return (WellOperationCategory.IdConditioning, new Dictionary<string, object>()); + } + } +} diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorFlashing.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorFlashing.cs index e6d8a0dd..f5d0add5 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorFlashing.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorFlashing.cs @@ -23,7 +23,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors return false; var delta = currentPoint.WellDepth - currentPoint.BitDepth; - if (delta < 0.03d) + if (delta < 0.01d) return false; if (currentPoint.RotorSpeed > 8) @@ -47,7 +47,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors if (currentPoint.Pressure < 10) return IdReasonOfEnd_PressureIsLo; - if ((currentPoint.WellDepth - currentPoint.BitDepth) < 0.03d) + if ((currentPoint.WellDepth - currentPoint.BitDepth) < 0.01d) return IdReasonOfEnd_DeltaWellDepthAndBithDepthIsLo; if (currentPoint.RotorSpeed > 8) return IdReasonOfEnd_RotorSpeedIsHi; diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Specifications/Промывка.md b/AsbCloudInfrastructure/Services/DetectOperations/Specifications/Промывка.md index 760d28cb..15e56d47 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Specifications/Промывка.md +++ b/AsbCloudInfrastructure/Services/DetectOperations/Specifications/Промывка.md @@ -13,13 +13,13 @@ Признак начала операции = ( давление >= 10 атм ) И ( обороты ротора <= 8 об/мин) И - ( расстояние от долота до забоя >= 0.03 м) И + ( расстояние от долота до забоя >= 0.01 м) И ( глубина забоя не изменяется) И ( глубина долота >= 150 м); Признак окончания операции = ( давление < 10 атм ) ИЛИ - ( расстояние от долота до забоя < 0.03 м ) ИЛИ + ( расстояние от долота до забоя < 0.01 м ) ИЛИ ( обороты ротора > 8 об/мин) ИЛИ ( глубина долота < 150 м); diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Specifications/Проработка.md b/AsbCloudInfrastructure/Services/DetectOperations/Specifications/Проработка.md new file mode 100644 index 00000000..91ddd293 --- /dev/null +++ b/AsbCloudInfrastructure/Services/DetectOperations/Specifications/Проработка.md @@ -0,0 +1,29 @@ +# Алгоритм определения проработки +## Описание + +Проработка – операция, во время которой производится подъем или спуск бурильного инструмента с вращением и циркуляцией. Следующей операцией после проработки будет либо шаблонировка (аналогично проработке, но БЕЗ вращением и циркуляции), либо разгрузка инструмента в клинья (снижение веса на крюке) – наращивание или отворот бурильного инструмента. + +Проработка определяется как время между: +- начало подъема/спуска бурильного инструмента с циркуляцией и вращением; +- разгрузкой инструмента на клинья (остается только вес крюкоблока и ВСП). При этом давление менее 20 атм. ЛИБО +- начало подъема/спуска бурильного инструмента с циркуляцией, НО БЕЗ вращения +Разделяется два вида проработки: + 1. перед наращиванием - соотношение глубины забоя и глубины долота <= 30 метров; + 2. при спуско-подъёмных операциях (СПО)соотношение глубины забоя - глубины долота > 30 метров. + +## Метод определения + + Признак начала операции = + ( давление >= 10 атм ) И + ( обороты ротора > 8 об/мин ) И + ( расстояние от долота до забоя >= 0.03м ) И + ( глубина долота >= 150м); + + Признак окончания операции = + ( обороты ротора <= 8 об/мин ) ИЛИ + ( давление < 10 атм ) ИЛИ + ( расстояние от долота до забоя < 0.03м ) ИЛИ + ( глубина долота < 150м); + +## Ключевой параметр +Продолжительность операции. diff --git a/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportService.cs b/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportService.cs index 983d1f7c..ff29ed0f 100644 --- a/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportService.cs +++ b/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportService.cs @@ -49,7 +49,7 @@ namespace AsbCloudInfrastructure.Services.DrillTestReport well.Deposit ?? "-", well.Cluster ?? "-", well.Caption ?? "-"), - Date = DateTime.Now, + Date = DateTimeOffset.Now, }; var fileName = string.Format("Drill_test_{0}.xlsx", dto.TimeStampStart.ToString("dd.mm.yyyy_HH_MM_ss")); @@ -78,15 +78,15 @@ namespace AsbCloudInfrastructure.Services.DrillTestReport var dtos = await drillTestRepository.GetAllAsync(telemetry.Id, request, cancellationToken); foreach (var dto in dtos) { - var remoteDateTime = dto.TimeStampStart.ToRemoteDateTime(timezone.Hours); + var remoteDateTime = dto.TimeStampStart.ToOffset(TimeSpan.FromHours(timezone.Hours)); reports.Add(new DrillTestReportInfoDto { - FileName = string.Format("Drill_test_{0}", dto.TimeStampStart.DateTime), + FileName = string.Format("Drill_test_{0}", remoteDateTime), DrillDepth = (dto.Params .Where(p => p.DepthDrillStep.HasValue) .Sum(x => x.DepthDrillStep) ?? 0) + dto.DepthStart, - DateTime = dto.TimeStampStart.DateTime, + DateTime = remoteDateTime, Id = dto.Id, }); } diff --git a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs index 3e8349ad..18e6acf2 100644 --- a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs +++ b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs @@ -480,7 +480,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram IdWell = fileEntity.IdWell, Name = fileEntity.Name, Size = fileEntity.Size, - UploadDate = fileEntity.UploadDate.ToRemoteDateTime(timezoneOffset), + UploadDate = fileEntity.UploadDate.ToOffset(TimeSpan.FromHours(timezoneOffset)), }; var marks = fileEntity.FileMarks?.Where(m => !m.IsDeleted); @@ -489,7 +489,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram part.File.FileMarks = marks.Select(m => { var mark = m.Adapt<FileMarkDto>(); - mark.DateCreated = m.DateCreated.ToRemoteDateTime(timezoneOffset); + mark.DateCreated = m.DateCreated.ToOffset(TimeSpan.FromHours(timezoneOffset)); return mark; }); var hasReject = marks.Any(m => m.IdMarkType == idMarkTypeReject); diff --git a/AsbCloudInfrastructure/Services/DrillingProgram/TitleListSheet.cs b/AsbCloudInfrastructure/Services/DrillingProgram/TitleListSheet.cs index 3d6482a7..7c9355d8 100644 --- a/AsbCloudInfrastructure/Services/DrillingProgram/TitleListSheet.cs +++ b/AsbCloudInfrastructure/Services/DrillingProgram/TitleListSheet.cs @@ -11,7 +11,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram { private const string directionDirectorPositionName = "Руководитель направления по ТСБ"; - private readonly DateTime totalDate; + private readonly DateTimeOffset totalDate; private readonly FileMarkDto? acceptDirectionDirector; private readonly List<FileMarkDto> acceptsOthers; private readonly WellDto well; @@ -157,7 +157,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Left); } - private static string FormatDate(DateTime dateTime) + private static string FormatDate(DateTimeOffset dateTime) => $"{dateTime.Day:00}.{dateTime.Month:00}.{dateTime.Year:00}"; } diff --git a/AsbCloudInfrastructure/Services/ExcelServices/ExcelExportService.cs b/AsbCloudInfrastructure/Services/ExcelServices/ExcelExportService.cs new file mode 100644 index 00000000..74e2d5fb --- /dev/null +++ b/AsbCloudInfrastructure/Services/ExcelServices/ExcelExportService.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using AsbCloudApp.Requests.ExportOptions; +using AsbCloudApp.Services.Export; +using AsbCloudInfrastructure.Services.ExcelServices.Templates; +using ClosedXML.Excel; +using Mapster; + +namespace AsbCloudInfrastructure.Services.ExcelServices; + +public abstract class ExcelExportService<TDto, TOptions, TTemplate> : IExportService<TOptions> + where TOptions : IExportOptionsRequest + where TTemplate : class, ITemplateParameters, new() +{ + protected TTemplate TemplateParameters => new(); + + protected abstract Task<string> BuildFileNameAsync(TOptions options, CancellationToken token); + + protected abstract Task<IEnumerable<TDto>> GetDtosAsync(TOptions options, CancellationToken token); + + public async Task<(string FileName, Stream File)> ExportAsync(TOptions options, CancellationToken token) + { + var dtos = await GetDtosAsync(options, token); + + var fileName = await BuildFileNameAsync(options, token); + var file = BuildFile(dtos); + return (fileName, file); + } + + private Stream BuildFile(IEnumerable<TDto> dtos) + { + using var template = GetTemplateFile(); + using var workbook = new XLWorkbook(template); + AddDtosToWorkbook(workbook, dtos); + + var memoryStream = new MemoryStream(); + workbook.SaveAs(memoryStream, new SaveOptions { }); + memoryStream.Seek(0, SeekOrigin.Begin); + return memoryStream; + } + + private void AddDtosToWorkbook(XLWorkbook workbook, IEnumerable<TDto> dtos) + { + var dtosToArray = dtos.ToArray(); + + if (!dtosToArray.Any()) + return; + + var sheet = workbook.GetWorksheet(TemplateParameters.SheetName); + for (var i = 0; i < dtosToArray.Length; i++) + { + var row = sheet.Row(1 + i + TemplateParameters.HeaderRowsCount); + AddRow(row, dtosToArray[i]); + } + } + + private void AddRow(IXLRow xlRow, TDto dto) + { + var properties = dto.Adapt<IDictionary<string, object>>(); + + foreach (var (name, cellValue) in properties) + { + if (TemplateParameters.Cells.TryGetValue(name, out var cell)) + xlRow.Cell(cell.ColumnNumber).SetCellValue(cellValue); + } + } + + private Stream GetTemplateFile() => + Assembly.GetExecutingAssembly().GetTemplateCopyStream(TemplateParameters.FileName) + ?? throw new ArgumentNullException($"Файл '{TemplateParameters.FileName}' не найден"); +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/ExcelServices/ExcelParser.cs b/AsbCloudInfrastructure/Services/ExcelServices/ExcelParser.cs new file mode 100644 index 00000000..924e7477 --- /dev/null +++ b/AsbCloudInfrastructure/Services/ExcelServices/ExcelParser.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.IO; +using System.Linq; +using System.Reflection; +using AsbCloudApp.Data; +using AsbCloudApp.Requests.ParserOptions; +using AsbCloudApp.Services.Parsers; +using AsbCloudInfrastructure.Services.ExcelServices.Templates; +using ClosedXML.Excel; +using Mapster; + +namespace AsbCloudInfrastructure.Services.ExcelServices; + +public abstract class ExcelParser<TDto, TOptions, TTemplate> : IParserService<TDto, TOptions> + where TDto : class, IValidatableObject, IId + where TOptions : IParserOptionsRequest + where TTemplate : class, ITemplateParameters, new() +{ + protected TTemplate TemplateParameters => new(); + + public virtual ParserResultDto<TDto> Parse(Stream file, TOptions options) + { + using var workbook = new XLWorkbook(file); + var sheet = workbook.GetWorksheet(TemplateParameters.SheetName); + var dtos = ParseExcelSheet(sheet); + return dtos; + } + + public virtual Stream GetTemplateFile() => + Assembly.GetExecutingAssembly().GetTemplateCopyStream(TemplateParameters.FileName) + ?? throw new ArgumentNullException($"Файл '{TemplateParameters.FileName}' не найден"); + + + protected virtual IDictionary<string, object?> ParseRow(IXLRow xlRow) + { + var cells = TemplateParameters.Cells.ToDictionary(x => x.Key, x => + { + var columnNumber = x.Value.ColumnNumber; + var xlCell = xlRow.Cell(columnNumber); + var cellValue = x.Value.GetValueFromCell(xlCell); + return cellValue; + }); + + return cells; + } + + protected virtual TDto BuildDto(IDictionary<string, object?> row, int rowNumber) + { + var dto = row.Adapt<TDto>(); + return dto; + } + + private ValidationResultDto<TDto> Validate(TDto dto, int rowNumber) + { + var validationResults = new List<ValidationResult>(); + + var isValid = dto.Validate(validationResults); + + if (isValid) + { + var validDto = new ValidationResultDto<TDto> + { + Item = dto + }; + + return validDto; + } + + var columnsDict = TemplateParameters.Cells.ToDictionary(x => x.Key, x => x.Value.ColumnNumber); + + var invalidDto = new ValidationResultDto<TDto> + { + Item = dto, + Warnings = validationResults + .SelectMany(v => v.MemberNames + .Where(columnsDict.ContainsKey) + .Select(m => + { + var columnNumber = columnsDict[m]; + var errorMessage = v.ErrorMessage; + var warningMessage = string.Format(XLExtentions.ProblemDetailsTemplate, + TemplateParameters.SheetName, + rowNumber, + columnNumber, + errorMessage); + var warning = new ValidationResult(warningMessage, new[] { m }); + return warning; + })) + }; + + return invalidDto; + } + + protected virtual ParserResultDto<TDto> ParseExcelSheet(IXLWorksheet sheet) + { + var count = sheet.RowsUsed().Count() - TemplateParameters.HeaderRowsCount; + if (count <= 0) + return new ParserResultDto<TDto>(); + + var valiationResults = new List<ValidationResultDto<TDto>>(count); + var warnings = new List<ValidationResult>(); + + for (var i = 0; i < count; i++) + { + var xlRow = sheet.Row(1 + i + TemplateParameters.HeaderRowsCount); + var rowNumber = xlRow.RowNumber(); + + try + { + var row = ParseRow(xlRow); + var dto = BuildDto(row, rowNumber); + var validationResult = Validate(dto, rowNumber); + valiationResults.Add(validationResult); + } + catch (FileFormatException ex) + { + var warning = new ValidationResult(ex.Message); + warnings.Add(warning); + } + } + + var parserResult = new ParserResultDto<TDto> + { + Item = valiationResults + }; + + if (warnings.Any()) + parserResult.Warnings = warnings; + + return parserResult; + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/ExcelServices/ExcelWellRelatedParser.cs b/AsbCloudInfrastructure/Services/ExcelServices/ExcelWellRelatedParser.cs new file mode 100644 index 00000000..55485f77 --- /dev/null +++ b/AsbCloudInfrastructure/Services/ExcelServices/ExcelWellRelatedParser.cs @@ -0,0 +1,23 @@ +using System.ComponentModel.DataAnnotations; +using System.IO; +using AsbCloudApp.Data; +using AsbCloudApp.Requests.ParserOptions; +using AsbCloudInfrastructure.Services.ExcelServices.Templates; + +namespace AsbCloudInfrastructure.Services.ExcelServices; + +public abstract class ExcelWellRelatedParser<TDto, TOptions, TTemplate> : ExcelParser<TDto, TOptions, TTemplate> + where TDto : class, IValidatableObject, IId, IWellRelated + where TOptions : WellRelatedParserRequest + where TTemplate : class, ITemplateParameters, new() +{ + public override ParserResultDto<TDto> Parse(Stream file, TOptions options) + { + var result = base.Parse(file, options); + + foreach (var dto in result.Item) + dto.Item.IdWell = options.IdWell; + + return result; + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/ExcelServices/ExportExcelService.cs b/AsbCloudInfrastructure/Services/ExcelServices/ExportExcelService.cs index 086eba97..cc068ba0 100644 --- a/AsbCloudInfrastructure/Services/ExcelServices/ExportExcelService.cs +++ b/AsbCloudInfrastructure/Services/ExcelServices/ExportExcelService.cs @@ -6,13 +6,14 @@ using System.Reflection; using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Requests.ExportOptions; -using AsbCloudApp.Services; +using AsbCloudApp.Services.Export; using AsbCloudInfrastructure.Services.ExcelServices.Templates; using ClosedXML.Excel; using Mapster; namespace AsbCloudInfrastructure.Services.ExcelServices; +[Obsolete] public abstract class ExportExcelService<TDto, TOptions> : IExportService<TOptions> where TOptions : IExportOptionsRequest { diff --git a/AsbCloudInfrastructure/Services/ExcelServices/ParserExcelService.cs b/AsbCloudInfrastructure/Services/ExcelServices/ParserExcelService.cs index 64e0259c..a74cab70 100644 --- a/AsbCloudInfrastructure/Services/ExcelServices/ParserExcelService.cs +++ b/AsbCloudInfrastructure/Services/ExcelServices/ParserExcelService.cs @@ -6,13 +6,14 @@ using System.Linq; using System.Reflection; using AsbCloudApp.Data; using AsbCloudApp.Requests.ParserOptions; -using AsbCloudApp.Services; +using AsbCloudApp.Services.Parsers; using AsbCloudInfrastructure.Services.ExcelServices.Templates; using ClosedXML.Excel; using Mapster; namespace AsbCloudInfrastructure.Services.ExcelServices; +[Obsolete] public abstract class ParserExcelService<TDto, TOptions> : IParserService<TDto, TOptions> where TDto : class, IValidatableObject, IId where TOptions : IParserOptionsRequest diff --git a/AsbCloudInfrastructure/Services/ExcelServices/Templates/WellOperations/WellOperationFactTemplate.cs b/AsbCloudInfrastructure/Services/ExcelServices/Templates/WellOperations/WellOperationFactTemplate.cs new file mode 100644 index 00000000..afb5fe19 --- /dev/null +++ b/AsbCloudInfrastructure/Services/ExcelServices/Templates/WellOperations/WellOperationFactTemplate.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using AsbCloudApp.Data.WellOperation; + +namespace AsbCloudInfrastructure.Services.ExcelServices.Templates.WellOperations; + +public class WellOperationFactTemplate : ITemplateParameters +{ + public string SheetName => "Факт"; + + public int HeaderRowsCount => 1; + + public string FileName => "WellOperationFactTemplate.xlsx"; + + public IDictionary<string, Cell> Cells => new Dictionary<string, Cell> + { + { nameof(WellOperationDto.WellSectionTypeCaption), new Cell(1, typeof(string)) }, + { nameof(WellOperationDto.OperationCategoryName), new Cell(2, typeof(string)) }, + { nameof(WellOperationDto.CategoryInfo), new Cell(3, typeof(string)) }, + { nameof(WellOperationDto.DepthStart), new Cell(4, typeof(double)) }, + { nameof(WellOperationDto.DepthEnd), new Cell(5, typeof(double)) }, + { nameof(WellOperationDto.DateStart), new Cell(6, typeof(DateTime)) }, + { nameof(WellOperationDto.DurationHours), new Cell(7, typeof(double)) }, + { nameof(WellOperationDto.Comment), new Cell(8, typeof(string)) } + }; +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/ExcelServices/Templates/WellOperations/WellOperationPlanTemplate.cs b/AsbCloudInfrastructure/Services/ExcelServices/Templates/WellOperations/WellOperationPlanTemplate.cs new file mode 100644 index 00000000..85e88db7 --- /dev/null +++ b/AsbCloudInfrastructure/Services/ExcelServices/Templates/WellOperations/WellOperationPlanTemplate.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using AsbCloudApp.Data.WellOperation; + +namespace AsbCloudInfrastructure.Services.ExcelServices.Templates.WellOperations; + +public class WellOperationPlanTemplate : ITemplateParameters +{ + public string SheetName => "План"; + + public int HeaderRowsCount => 1; + + public string FileName => "WellOperationPlanTemplate.xlsx"; + + public IDictionary<string, Cell> Cells => new Dictionary<string, Cell>() + { + { nameof(WellOperationDto.WellSectionTypeCaption), new Cell(1, typeof(string)) }, + { nameof(WellOperationDto.OperationCategoryName), new Cell(2, typeof(string)) }, + { nameof(WellOperationDto.CategoryInfo), new Cell(3, typeof(string)) }, + { nameof(WellOperationDto.DepthStart), new Cell(4, typeof(double)) }, + { nameof(WellOperationDto.DepthEnd), new Cell(5, typeof(double)) }, + { nameof(WellOperationDto.DateStart), new Cell(6, typeof(DateTime)) }, + { nameof(WellOperationDto.DurationHours), new Cell(7, typeof(double)) }, + { nameof(WellOperationDto.Comment), new Cell(8, typeof(string)) } + }; +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/LimitingParameterService.cs b/AsbCloudInfrastructure/Services/LimitingParameterService.cs index c4323597..5dee9f53 100644 --- a/AsbCloudInfrastructure/Services/LimitingParameterService.cs +++ b/AsbCloudInfrastructure/Services/LimitingParameterService.cs @@ -106,7 +106,7 @@ namespace AsbCloudInfrastructure.Services return (float)result; } - private DateTime GetDate(double depth, LimitingParameterDataDto dto) + private DateTimeOffset GetDate(double depth, LimitingParameterDataDto dto) { var a = depth - dto.DepthStart; var b = dto.DepthEnd - dto.DepthStart; diff --git a/AsbCloudInfrastructure/Services/ManualCatalogService.cs b/AsbCloudInfrastructure/Services/ManualCatalogService.cs index c8713ab1..8c779bc7 100644 --- a/AsbCloudInfrastructure/Services/ManualCatalogService.cs +++ b/AsbCloudInfrastructure/Services/ManualCatalogService.cs @@ -57,7 +57,7 @@ public class ManualCatalogService : IManualCatalogService var manual = new ManualDto { Name = name, - DateDownload = DateTime.UtcNow, + DateDownload = DateTimeOffset.UtcNow, IdDirectory = idDirectory, IdCategory = IdFileCategory, IdAuthor = idAuthor diff --git a/AsbCloudInfrastructure/Services/MeasureService.cs b/AsbCloudInfrastructure/Services/MeasureService.cs index 58c5c295..7a349450 100644 --- a/AsbCloudInfrastructure/Services/MeasureService.cs +++ b/AsbCloudInfrastructure/Services/MeasureService.cs @@ -87,8 +87,7 @@ namespace AsbCloudInfrastructure.Services throw new ArgumentInvalidException(nameof(dto), "wrong idCategory"); if (!dto.Data.Any()) throw new ArgumentInvalidException(nameof(dto), "data.data is not optional"); - var timezone = wellService.GetTimezone(idWell); - var entity = Convert(dto, timezone.Hours); + var entity = Convert(dto); entity.IdWell = idWell; db.Measures.Add(entity); return db.SaveChangesAsync(token); @@ -110,7 +109,7 @@ namespace AsbCloudInfrastructure.Services var timezone = wellService.GetTimezone(idWell); entity.IdWell = idWell; - entity.Timestamp = dto.Timestamp.ToUtcDateTimeOffset(timezone.Hours); + entity.Timestamp = dto.Timestamp.ToOffset(TimeSpan.FromHours(timezone.Hours)); entity.Data = dto.Data.Adapt<RawData>(); return await db.SaveChangesAsync(token).ConfigureAwait(false); @@ -142,13 +141,13 @@ namespace AsbCloudInfrastructure.Services { var dto = entity.Adapt<MeasureDto>(); dto.CategoryName = entity.Category?.Name ?? String.Empty; - dto.Timestamp = entity.Timestamp.ToRemoteDateTime(hours); + dto.Timestamp = entity.Timestamp.ToOffset(TimeSpan.FromHours(hours)); return dto; } - private Measure Convert(MeasureDto dto, double hours) + private Measure Convert(MeasureDto dto) { var entity = dto.Adapt<Measure>(); - entity.Timestamp = dto.Timestamp.ToUtcDateTimeOffset(hours); + entity.Timestamp = dto.Timestamp.ToUniversalTime(); return entity; } } diff --git a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDrillingService.cs b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDrillingService.cs index dae4f39b..313f76e7 100644 --- a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDrillingService.cs +++ b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDrillingService.cs @@ -13,6 +13,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Data.WellOperation; namespace AsbCloudInfrastructure.Services.ProcessMaps.Report; @@ -55,9 +56,8 @@ public class ProcessMapReportDrillingService : IProcessMapReportDrillingService var geDepth = processMapPlanWellDrillings.Min(p => p.DepthStart); var leDepth = processMapPlanWellDrillings.Max(p => p.DepthEnd); - var requestWellOperationFact = new WellOperationRequest() + var requestWellOperationFact = new WellOperationRequest(new[] { idWell }) { - IdWell = idWell, OperationType = WellOperation.IdOperationTypeFact, GeDepth = geDepth, LeDepth = leDepth @@ -111,7 +111,7 @@ public class ProcessMapReportDrillingService : IProcessMapReportDrillingService .OrderBy(o => o.DateStart) .ToArray(); - var lastFoundIndex = 1; + var lastFoundIndex = 0; int GetSection(DataSaubStatDto data) { @@ -196,7 +196,7 @@ public class ProcessMapReportDrillingService : IProcessMapReportDrillingService var result = new ProcessMapReportDataSaubStatDto() { IdWellSectionType = wellSectionType.Id, - DateStart = firstElemInInterval.DateStart.DateTime, + DateStart = firstElemInInterval.DateStart, WellSectionTypeName = wellSectionType.Caption, DepthStart = firstElemInInterval.DepthStart, DepthEnd = lastElemInInterval.DepthEnd, diff --git a/AsbCloudInfrastructure/Services/ReportService.cs b/AsbCloudInfrastructure/Services/ReportService.cs index fd7d86a3..4d321525 100644 --- a/AsbCloudInfrastructure/Services/ReportService.cs +++ b/AsbCloudInfrastructure/Services/ReportService.cs @@ -64,11 +64,11 @@ public class ReportService : IReportService return work.Id; } - public int GetReportPagesCount(int idWell, DateTime begin, DateTime end, int stepSeconds, int format) + public int GetReportPagesCount(int idWell, DateTimeOffset begin, DateTimeOffset end, int stepSeconds, int format) { var timezoneOffset = wellService.GetTimezone(idWell).Hours; - var beginRemote = begin.ToTimeZoneOffsetHours(timezoneOffset); - var endRemote = end.ToTimeZoneOffsetHours(timezoneOffset); + var beginRemote = begin.DateTime.ToTimeZoneOffsetHours(timezoneOffset); + var endRemote = end.DateTime.ToTimeZoneOffsetHours(timezoneOffset); var generator = GetReportGenerator(idWell, beginRemote, endRemote, stepSeconds, format, db); var pagesCount = generator.GetPagesCount(); @@ -87,6 +87,7 @@ public class ReportService : IReportService public async Task<IEnumerable<ReportPropertiesDto>> GetAllReportsByWellAsync(int idWell, CancellationToken token) { var timezoneOffset = wellService.GetTimezone(idWell).Hours; + var timeSpan = TimeSpan.FromHours(timezoneOffset); var propertiesQuery = db.ReportProperties.Include(r => r.File) .Where(p => p.IdWell == idWell) .OrderBy(o => o.File.UploadDate) @@ -106,12 +107,12 @@ public class ReportService : IReportService IdWell = p.File.IdWell, Name = p.File.Name, Size = p.File.Size, - UploadDate = p.File.UploadDate.ToRemoteDateTime(timezoneOffset), + UploadDate = p.File.UploadDate.ToOffset(timeSpan), }, IdWell = p.IdWell, - Date = p.File.UploadDate.ToRemoteDateTime(timezoneOffset), - Begin = p.Begin.ToRemoteDateTime(timezoneOffset), - End = p.End.ToRemoteDateTime(timezoneOffset), + Date = p.File.UploadDate.ToOffset(timeSpan), + Begin = p.Begin.ToOffset(timeSpan), + End = p.End.ToOffset(timeSpan), Step = p.Step, Format = p.Format == 0 ? ".pdf" : ".las" }); @@ -127,10 +128,10 @@ public class ReportService : IReportService CancellationToken token) { var timezoneOffset = wellService.GetTimezone(idWell).Hours; - var beginRemote = request.Begin.ToTimeZoneOffsetHours(timezoneOffset); - var endRemote = request.End.ToTimeZoneOffsetHours(timezoneOffset); - var beginUtc = request.Begin.ToUtcDateTimeOffset(timezoneOffset); - var endUtc = request.End.ToUtcDateTimeOffset(timezoneOffset); + var beginRemote = request.Begin.DateTime; + var endRemote = request.End.DateTime; + var beginUtc = request.Begin.ToUniversalTime(); + var endUtc = request.End.ToUniversalTime(); var tempDir = Path.Combine(Path.GetTempPath(), "report"); diff --git a/AsbCloudInfrastructure/Services/SAUB/MessageService.cs b/AsbCloudInfrastructure/Services/SAUB/MessageService.cs index 350829e1..17d92d8d 100644 --- a/AsbCloudInfrastructure/Services/SAUB/MessageService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/MessageService.cs @@ -68,17 +68,15 @@ namespace AsbCloudInfrastructure.Services.SAUB query = query.OrderByDescending(m => m.DateTime); - var timezone = telemetryService.GetTimezone(telemetry.Id); - if (request.Begin is not null) { - var beginUtc = request.Begin.Value.ToUtcDateTimeOffset(timezone.Hours); + var beginUtc = request.Begin.Value.ToUniversalTime(); query = query.Where(m => m.DateTime >= beginUtc); } if (request.End is not null) { - var endUtc = request.End.Value.ToUtcDateTimeOffset(timezone.Hours); + var endUtc = request.End.Value.ToUniversalTime(); query = query.Where(m => m.DateTime <= endUtc); } @@ -102,6 +100,7 @@ namespace AsbCloudInfrastructure.Services.SAUB var usersDict = users.ToDictionary(x => x.IdUser, x => x); var messagesDtoList = new List<MessageDto>(); + var timezone = telemetryService.GetTimezone(telemetry.Id); foreach (var message in messagesList) { @@ -111,7 +110,7 @@ namespace AsbCloudInfrastructure.Services.SAUB WellDepth = message.WellDepth }; - messageDto.DateTime = message.DateTime.ToRemoteDateTime(timezone.Hours); + messageDto.DateTime = message.DateTime.ToOffset(TimeSpan.FromHours(timezone.Hours)); if (message.IdTelemetryUser is not null) { @@ -150,7 +149,7 @@ namespace AsbCloudInfrastructure.Services.SAUB var entity = dto.Adapt<TelemetryMessage>(); entity.Id = 0; entity.IdTelemetry = telemetry.Id; - entity.DateTime = dto.Date.ToUtcDateTimeOffset(timezone.Hours); + entity.DateTime = dto.Date.ToOffset(TimeSpan.FromHours(timezone.Hours)); db.TelemetryMessages.Add(entity); } diff --git a/AsbCloudInfrastructure/Services/SAUB/SetpointsService.cs b/AsbCloudInfrastructure/Services/SAUB/SetpointsService.cs index b0f5c824..d06e0b4c 100644 --- a/AsbCloudInfrastructure/Services/SAUB/SetpointsService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/SetpointsService.cs @@ -41,7 +41,7 @@ namespace AsbCloudInfrastructure.Services.SAUB public async Task<int> InsertAsync(SetpointsRequestDto setpointsRequest, CancellationToken token) { setpointsRequest.IdState = 1; - setpointsRequest.UploadDate = DateTime.UtcNow; + setpointsRequest.UploadDate = DateTimeOffset.UtcNow; var result = await setpointsRepository.InsertAsync(setpointsRequest, token); return result; } @@ -72,7 +72,6 @@ namespace AsbCloudInfrastructure.Services.SAUB foreach (var item in filtered) { item.IdState = 2; - item.UploadDate = DateTime.SpecifyKind(item.UploadDate, DateTimeKind.Utc); } await setpointsRepository.UpdateRangeAsync(filtered, token); diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs index f9cc64ee..53ed062b 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs @@ -102,7 +102,7 @@ namespace AsbCloudInfrastructure.Services.SAUB if (dateBegin == default) { var dateRange = telemetryDataCache.GetOrDefaultDataDateRange(telemetry.Id); - dateBeginUtc = (dateRange?.To.ToUtcDateTimeOffset(timezone.Hours) ?? DateTime.UtcNow) + dateBeginUtc = (dateRange?.To ?? DateTimeOffset.UtcNow) .AddSeconds(-intervalSec); } else diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs index 74643429..a75c7bf3 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs @@ -156,7 +156,9 @@ namespace AsbCloudInfrastructure.Services.SAUB var to = cacheItem.LastData[^1].DateTime; from = from ?? cacheItem.LastData[0].DateTime; - return new DatesRangeDto { From = from.Value, To = to }; + return new DatesRangeDto { + From = from.Value.ToUtcDateTimeOffset(cacheItem.TimezoneHours), + To = to.ToUtcDateTimeOffset(cacheItem.TimezoneHours) }; } public DatesRangeDto? GetOrDefaultCachedDateRange(int idTelemetry) diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs index e6fb372b..9bca69bd 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs @@ -129,10 +129,10 @@ public class TelemetryDataSaubService : TelemetryDataBaseService<TelemetryDataSa protected override TelemetryDataSaubDto Convert(TelemetryDataSaub src, double timezoneOffset) { - var dto = src.Adapt<TelemetryNewDataSaubDto>(); + var dto = src.Adapt<TelemetryDataSaubDto>(); var telemetryUser = telemetryUserService.GetOrDefault(src.IdTelemetry, src.IdUser ?? int.MinValue); dto.User = telemetryUser?.MakeDisplayName(); - dto.DateTime = src.DateTime.ToOffset(TimeSpan.FromHours(timezoneOffset)); // src.DateTime.ToRemoteDateTime(timezoneOffset); + dto.DateTime = src.DateTime.ToRemoteDateTime(timezoneOffset); dto.BitDepth = src.BitDepth <= src.WellDepth ? src.BitDepth : src.WellDepth; diff --git a/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs b/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs index 6ba97ea0..8beb3c3e 100644 --- a/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs +++ b/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Data.WellOperation; namespace AsbCloudInfrastructure.Services { @@ -133,7 +134,7 @@ namespace AsbCloudInfrastructure.Services this.wellOperationRepository = wellOperationRepository; } - public async Task<List<Dictionary<int, WellOperationDataDto>>> GetAsync(IEnumerable<int> idsWells, CancellationToken token) + public async Task<IEnumerable<Dictionary<int, WellOperationDto>>> GetAsync(IEnumerable<int> idsWells, CancellationToken token) { var sections = await wellSectionTypeRepository.GetAllAsync(token); var sectionsDict = sections.ToDictionary(s => s.Id, s => s.Caption); @@ -144,9 +145,8 @@ namespace AsbCloudInfrastructure.Services var idsWellSectionTypes = WellSectionTypesWithCategories.Select(t => t.IdSectionType).Distinct(); var usedCategories = WellSectionTypesWithCategories.Select(c => c.IdCategory).Distinct(); - var wellOperationRequest = new WellsOperationRequest() + var wellOperationRequest = new WellOperationRequest(idsWells) { - IdsWell = idsWells, OperationCategoryIds = usedCategories, SectionTypeIds = idsWellSectionTypes, OperationType = WellOperation.IdOperationTypeFact @@ -155,7 +155,7 @@ namespace AsbCloudInfrastructure.Services var renamedOperations = operations.Select(o => UpdateIdWellSectionAndIdCategory(o, sectionsDict, categoriesDict)); - var wellOperationsWithComposite = new List<Dictionary<int, WellOperationDataDto>>(); + var wellOperationsWithComposite = new List<Dictionary<int, WellOperationDto>>(); var compositeDepth = 0d; foreach ((int IdSection, int IdCategory) in WellSectionTypesWithCategories) { @@ -168,7 +168,7 @@ namespace AsbCloudInfrastructure.Services var groupedByWell = filteredByTemplate.GroupBy(o => o.IdWell); - var aggreagtedByWell = groupedByWell.Select(g => new WellOperationDataDto + var aggreagtedByWell = groupedByWell.Select(g => new WellOperationDto { IdCategory = IdCategory, IdWell = g.Key, @@ -197,15 +197,15 @@ namespace AsbCloudInfrastructure.Services return wellOperationsWithComposite; } - private static WellOperationDataDto UpdateIdWellSectionAndIdCategory( - WellOperationDataDto dto, - Dictionary<int, string> sectionTypes, - Dictionary<int, string> operationCategories) + private static WellOperationDto UpdateIdWellSectionAndIdCategory( + WellOperationDto dto, + IDictionary<int, string> sectionTypes, + IDictionary<int, string> operationCategories) { if (dto.IdWellSectionType == wellSectionTransportTable) { dto.IdWellSectionType = wellSectionProductionString; - dto.WellSectionTypeCaption = sectionTypes[dto.IdWellSectionType] ?? string.Empty; + dto.WellSectionTypeCaption = sectionTypes[dto.IdWellSectionType]; } if ((SettingsForSectionCategoryChange.TryGetValue((dto.IdWellSectionType, dto.IdCategory), out int newIdCategory))) diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/Constants/DefaultTemplateInfo.cs b/AsbCloudInfrastructure/Services/WellOperationImport/Constants/DefaultTemplateInfo.cs deleted file mode 100644 index 96f3272b..00000000 --- a/AsbCloudInfrastructure/Services/WellOperationImport/Constants/DefaultTemplateInfo.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace AsbCloudInfrastructure.Services.WellOperationImport.Constants; - -public static class DefaultTemplateInfo -{ - public const string SheetNamePlan = "План"; - public const string SheetNameFact = "Факт"; - - public const int HeaderRowsCount = 1; - public const int ColumnSection = 1; - public const int ColumnCategory = 2; - public const int ColumnCategoryInfo = 3; - public const int ColumnDepthStart = 4; - public const int ColumnDepthEnd = 5; - public const int ColumnDate = 6; - public const int ColumnDuration = 7; - public const int ColumnComment = 8; -} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/Constants/OperationAttributes.cs b/AsbCloudInfrastructure/Services/WellOperationImport/Constants/OperationAttributes.cs deleted file mode 100644 index c4049d03..00000000 --- a/AsbCloudInfrastructure/Services/WellOperationImport/Constants/OperationAttributes.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace AsbCloudInfrastructure.Services.WellOperationImport.Constants; - -public static class OperationAttributes -{ - public const string CategoryInfo = "Описание"; - public const string SectionDiameter = "ОК"; - public const string Depth = "Забой"; - public const string Duration = "Время операции"; - public const string Date = "Дата окончания операции"; -} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/Constants/Templates.cs b/AsbCloudInfrastructure/Services/WellOperationImport/Constants/Templates.cs deleted file mode 100644 index 631dc170..00000000 --- a/AsbCloudInfrastructure/Services/WellOperationImport/Constants/Templates.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace AsbCloudInfrastructure.Services.WellOperationImport.Constants; - -public static class Templates -{ - public const int IdDefaultTemplate = 0; - public const int IdGazpromKhantosTemplate = 1; -} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/StringSimilarity/CosineSimilarity.cs b/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/StringSimilarity/CosineSimilarity.cs deleted file mode 100644 index ae69f7f9..00000000 --- a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/StringSimilarity/CosineSimilarity.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; - -namespace AsbCloudInfrastructure.Services.WellOperationImport.FileParser.StringSimilarity; - -public class CosineSimilarity -{ - private const int DefaultK = 2; - - protected int K { get; } - - public CosineSimilarity(int k) - { - if (k <= 0) - { - throw new ArgumentOutOfRangeException(nameof(k), "k should be positive!"); - } - - K = k; - } - - public CosineSimilarity() : this(DefaultK) { } - - public double Similarity(IDictionary<string, int> profile1, IDictionary<string, int> profile2) - => DotProduct(profile1, profile2) - / (Norm(profile1) * Norm(profile2)); - - public Dictionary<string, int> GetProfile(string s) - { - var shingles = new Dictionary<string, int>(); - - if (string.IsNullOrWhiteSpace(s)) - return shingles; - - var cleanString = Stemming(s); - - for (int i = 0; i < (cleanString.Length - K + 1); i++) - { - var shingle = cleanString.Substring(i, K); - - if (shingles.TryGetValue(shingle, out var old)) - { - shingles[shingle] = old + 1; - } - else - { - shingles[shingle] = 1; - } - } - - return shingles; - } - - private static string Stemming(string s) - { - var cleaned = Regex.Replace(s.ToLower(), "[^a-zа-я0-9]", ""); - var words = cleaned.Split(' '); - var filteredWords = words.Where(word => word.Length > 1).ToArray(); - return string.Concat(filteredWords); - } - - private static double Norm(IDictionary<string, int> profile) - { - double agg = 0; - - foreach (var entry in profile) - { - agg += 1.0 * entry.Value * entry.Value; - } - - return Math.Sqrt(agg); - } - - private static double DotProduct(IDictionary<string, int> profile1, IDictionary<string, int> profile2) - { - var smallProfile = profile2; - var largeProfile = profile1; - - if (profile1.Count < profile2.Count) - { - smallProfile = profile1; - largeProfile = profile2; - } - - double agg = 0; - foreach (var entry in smallProfile) - { - if (!largeProfile.TryGetValue(entry.Key, out var i)) - continue; - - agg += 1.0 * entry.Value * i; - } - - return agg; - } -} diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationDefaultExcelParser.cs b/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationDefaultExcelParser.cs deleted file mode 100644 index 2996d642..00000000 --- a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationDefaultExcelParser.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using AsbCloudApp.Data.WellOperationImport; -using AsbCloudApp.Data.WellOperationImport.Options; -using AsbCloudApp.Services.WellOperationImport; -using AsbCloudDb.Model; -using AsbCloudInfrastructure.Services.WellOperationImport.Constants; -using ClosedXML.Excel; - -namespace AsbCloudInfrastructure.Services.WellOperationImport.FileParser; - -public class WellOperationDefaultExcelParser : IWellOperationExcelParser<WellOperationImportDefaultOptionsDto> -{ - public SheetDto Parse(Stream stream, WellOperationImportDefaultOptionsDto options) - { - using var workbook = new XLWorkbook(stream); - - return ParseWorkbook(workbook, options); - } - - private static SheetDto ParseWorkbook(IXLWorkbook workbook, WellOperationImportDefaultOptionsDto options) - { - var sheetName = options.IdType == WellOperation.IdOperationTypePlan - ? DefaultTemplateInfo.SheetNamePlan - : DefaultTemplateInfo.SheetNameFact; - - var sheet = workbook.GetWorksheet(sheetName); - - return ParseSheet(sheet); - } - - private static SheetDto ParseSheet(IXLWorksheet sheet) - { - if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < 7) - throw new FileFormatException($"Лист {sheet.Name} содержит меньшее количество столбцов."); - - var count = sheet.RowsUsed().Count() - DefaultTemplateInfo.HeaderRowsCount; - - switch (count) - { - case > 1024: - throw new FileFormatException($"Лист {sheet.Name} содержит слишком большое количество операций."); - case <= 0: - return new SheetDto { Name = sheet.Name }; - } - - var rows = new RowDto[count]; - - var cellValuesErrors = new List<string>(); - - for (int i = 0; i < rows.Length; i++) - { - try - { - var xlRow = sheet.Row(1 + i + DefaultTemplateInfo.HeaderRowsCount); - - rows[i] = ParseRow(xlRow); - } - catch (FileFormatException ex) - { - cellValuesErrors.Add(ex.Message); - } - } - - if (cellValuesErrors.Any()) - throw new FileFormatException(string.Join("\r\n", cellValuesErrors)); - - return new SheetDto - { - Name = sheet.Name, - Rows = rows - }; - } - - private static RowDto ParseRow(IXLRow xlRow) - { - return new RowDto - { - Number = xlRow.RowNumber(), - Section = xlRow.Cell(DefaultTemplateInfo.ColumnSection).GetCellValue<string>(), - Category = xlRow.Cell(DefaultTemplateInfo.ColumnCategory).GetCellValue<string>(), - CategoryInfo = xlRow.Cell(DefaultTemplateInfo.ColumnCategoryInfo).GetCellValue<string?>(), - DepthStart = xlRow.Cell(DefaultTemplateInfo.ColumnDepthStart).GetCellValue<double>(), - DepthEnd = xlRow.Cell(DefaultTemplateInfo.ColumnDepthEnd).GetCellValue<double>(), - Date = xlRow.Cell(DefaultTemplateInfo.ColumnDate).GetCellValue<DateTime>(), - Duration = xlRow.Cell(DefaultTemplateInfo.ColumnDuration).GetCellValue<double>(), - Comment = xlRow.Cell(DefaultTemplateInfo.ColumnComment).GetCellValue<string?>() - }; - } -} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationGazpromKhantosExcelParser.cs b/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationGazpromKhantosExcelParser.cs deleted file mode 100644 index 7eb62839..00000000 --- a/AsbCloudInfrastructure/Services/WellOperationImport/FileParser/WellOperationGazpromKhantosExcelParser.cs +++ /dev/null @@ -1,227 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using AsbCloudApp.Data.WellOperationImport; -using AsbCloudApp.Data.WellOperationImport.Options; -using AsbCloudApp.Exceptions; -using AsbCloudApp.Services.WellOperationImport; -using AsbCloudInfrastructure.Services.WellOperationImport.Constants; -using AsbCloudInfrastructure.Services.WellOperationImport.FileParser.StringSimilarity; -using ClosedXML.Excel; - -namespace AsbCloudInfrastructure.Services.WellOperationImport.FileParser; - -public class WellOperationGazpromKhantosExcelParser : IWellOperationExcelParser<WellOperationImportGazpromKhantosOptionsDto> -{ - private class Operation - { - public int RowNumber { get; set; } - - public string? CategoryInfo { get; set; } - - public double SectionDiameter { get; set; } - - public double Depth { get; set; } - - public double Duration { get; set; } - - public DateTime Date { get; set; } - } - - private readonly CosineSimilarity cosineSimilarity = new(); - - private readonly Dictionary<string, string> operationDict = InitDict("Operations.txt", '='); - private readonly Dictionary<string, string> sectionDict = InitDict("Sections.txt", '='); - private readonly Dictionary<string, string> operationAttributesDict = InitDict("OperationAttributes.txt", '='); - - public SheetDto Parse(Stream stream, WellOperationImportGazpromKhantosOptionsDto options) - { - using var workbook = new XLWorkbook(stream); - - return ParseWorkBook(workbook, options); - } - - private SheetDto ParseWorkBook(IXLWorkbook workbook, WellOperationImportGazpromKhantosOptionsDto options) - { - if (options.StartRow is < 1 or > 1048576) - throw new ArgumentInvalidException(nameof(options.StartRow), "Некорректное значение начальной строки"); - - if (options.EndRow is < 1 or > 1048576) - throw new ArgumentInvalidException(nameof(options.EndRow), "Некорректное значение конечной строки"); - - if (options.EndRow < options.StartRow) - throw new ArgumentInvalidException(nameof(options.EndRow), "Конечный номер строки не может быть больше начального"); - - var sheet = workbook.GetWorksheet(options.SheetName); - return ParseSheet(sheet, options.StartRow, options.EndRow); - } - - private SheetDto ParseSheet(IXLWorksheet sheet, int startRow, int endRow) - { - var operationAttributes = GetOperationAttributes(sheet.RowsUsed()); - - if (operationAttributes is null) - return new SheetDto { Name = sheet.Name }; - - var rowsCount = endRow - startRow + 1; - - var operations = new List<Operation>(); - - var cellValuesErrors = new List<string>(); - - for (int i = 0; i < rowsCount; i++) - { - var xlRow = sheet.Row(startRow + i); - - try - { - operations.Add(new Operation - { - RowNumber = xlRow.RowNumber(), - CategoryInfo = xlRow.Cell(operationAttributes[OperationAttributes.CategoryInfo]).GetCellValue<string?>(), - SectionDiameter =xlRow.Cell(operationAttributes[OperationAttributes.SectionDiameter]).GetCellValue<double>(), - Depth = xlRow.Cell(operationAttributes[OperationAttributes.Depth]).GetCellValue<double>(), - Duration = xlRow.Cell(operationAttributes[OperationAttributes.Duration]).GetCellValue<double>(), - Date = xlRow.Cell(operationAttributes[OperationAttributes.Date]).GetCellValue<DateTime>() - }); - } - catch (FileFormatException ex) - { - cellValuesErrors.Add(ex.Message); - } - } - - if (cellValuesErrors.Any()) - throw new FileFormatException(string.Join("\r\n", cellValuesErrors)); - - return new SheetDto() - { - Name = sheet.Name, - Rows = BuildRows() - }; - - IEnumerable<(double Diameter, string Name)> BuildSections() - { - var groupedOperations = operations.GroupBy(o => o.SectionDiameter) - .Select(s => new - { - Diameter = s.Key, - CategoryInfo = string.Concat(s.Select(o => o.CategoryInfo)) - }); - - var repeatedSections = new[] { "xвостовик" }; - - var sections = new List<(double diameter, string section)>(); - - foreach (var groupedOperation in groupedOperations) - { - var sectionNamesSet = new HashSet<string>(sections.Select(s => s.section)); - - sections.Add(new ValueTuple<double, string>(groupedOperation.Diameter, sectionDict.FirstOrDefault(item => - groupedOperation.CategoryInfo.Contains(item.Key) && - (!sectionNamesSet.Contains(item.Value) || repeatedSections.Contains(item.Value.ToLowerInvariant()))).Value)); - } - - return sections; - } - - IEnumerable<RowDto> BuildRows() - { - if (!operations.Any()) - return Enumerable.Empty<RowDto>(); - - var rows = new List<RowDto>(); - - for (int i = 0; i < operations.Count; i++) - { - var currentOperation = operations[i]; - var nextOperation = i + 1 < operations.Count ? operations[i + 1] : currentOperation; - - rows.Add(new RowDto - { - Number = currentOperation.RowNumber, - Section = BuildSections().FirstOrDefault(s => Math.Abs(s.Diameter - currentOperation.SectionDiameter) < 0.1).Name, - Category = GetValueDictionary(operationDict, currentOperation.CategoryInfo, 0.3), - CategoryInfo = currentOperation.CategoryInfo, - DepthStart = currentOperation.Depth, - DepthEnd = nextOperation.Depth, - Duration = currentOperation.Duration, - Date = currentOperation.Date.AddHours(-currentOperation.Duration) - }); - } - - return rows; - } - } - - private IDictionary<string, int>? GetOperationAttributes(IXLRows xlRows) - { - const int countOperationAttributes = 5; - - IDictionary<string, int>? operationAttributes = null; - - foreach (var xlRow in xlRows) - { - operationAttributes = new Dictionary<string, int>(); - - var cells = xlRow.CellsUsed().ToArray(); - - foreach (var cell in cells) - { - var operationAttribute = GetValueDictionary(operationAttributesDict, cell.GetCellValue<string>(), 0.7); - - if (operationAttribute is null || operationAttributes.Any(a => a.Key == operationAttribute)) - continue; - - operationAttributes.Add(operationAttribute, cell.Address.ColumnNumber); - } - - if (operationAttributes.Count >= countOperationAttributes) - break; - } - - return operationAttributes is not null && operationAttributes.Count == countOperationAttributes ? operationAttributes : null; - } - - private string? GetValueDictionary(IDictionary<string, string> dict, string? cellValue, double? minSimilarity) - { - if (string.IsNullOrWhiteSpace(cellValue)) - return null; - - var similarValues = new List<(double similarity, string value)>(); - - var profile1 = cosineSimilarity.GetProfile(cellValue); - - foreach (var item in dict) - { - var profile2 = cosineSimilarity.GetProfile(item.Key); - - var similarity = cosineSimilarity.Similarity(profile1, profile2); - - similarValues.Add((similarity, item.Value)); - } - - var mostSimilarValue = similarValues.MaxBy(v => v.similarity); - - return minSimilarity.HasValue && mostSimilarValue.similarity >= minSimilarity ? mostSimilarValue.value : null; - } - - private static Dictionary<string, string> InitDict(string fileName, char separator) - { - var resourceName = Assembly.GetExecutingAssembly() - .GetManifestResourceNames() - .FirstOrDefault(n => n.EndsWith(fileName))!; - - var stream = Assembly.GetExecutingAssembly() - .GetManifestResourceStream(resourceName)!; - - using var reader = new StreamReader(stream); - - return reader.ReadToEnd().Split('\r') - .Where(s => !string.IsNullOrWhiteSpace(s)) - .Select(line => line.Split(separator)) - .ToDictionary(parts => parts[0].Trim(), parts => parts[1].Trim()); - } -} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/Files/Dictionaries/OperationAttributes.txt b/AsbCloudInfrastructure/Services/WellOperationImport/Files/Dictionaries/OperationAttributes.txt deleted file mode 100644 index 7127ce99..00000000 --- a/AsbCloudInfrastructure/Services/WellOperationImport/Files/Dictionaries/OperationAttributes.txt +++ /dev/null @@ -1,8 +0,0 @@ -Описание=Описание -ОК=ОК -Секция=ОК -Забой, м=Забой -Время=Время операции -Плановое время бурения, сут=Время операции -Окончание=Дата окончания операции -Дата окончания План РГ=Дата окончания операции \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/Files/Dictionaries/Operations.txt b/AsbCloudInfrastructure/Services/WellOperationImport/Files/Dictionaries/Operations.txt deleted file mode 100644 index 68bc28c7..00000000 --- a/AsbCloudInfrastructure/Services/WellOperationImport/Files/Dictionaries/Operations.txt +++ /dev/null @@ -1,201 +0,0 @@ -Сборка КНБК=Сборка КНБК -Сборка роторной КНБК=Сборка КНБК -Шаблонирование спуск КНБК=Шаблонирование перед спуском -Бурение под направлением=Бурение ротором -Шаблонирование перед спуском=Шаблонирование перед спуском -Шаблонировка пробуренного интервала + промывка на забое+ подъем КНБК=Шаблонирование перед спуском -Разборка КНБК=Разборка КНБК -ПР к спуску направления 324мм=ПЗР при спуске ОК -Спуск направления=Спуск ОК -Спуск направления 324мм=Спуск ОК -Цементаж направления 324мм=Цементирование -ОЗЦ. Оборудование устья.=ОЗЦ -ОЗЦ. Чистка забурочной ямы. Чистка ВШН. Отворот доп. патрубка. ЗГР=ОЗЦ -Перетяжка талевого каната / замена.=Перетяжка талевого каната -Шаблонирование подъём КНБК=Шаблонировка подъем БИ, продувка -Сборка СБТ 127мм-300м=Сборка БИ с мостков на подсвечник -Сборка КНБК для бурения кондуктора=Сборка КНБК -Сборка КНБК для бурения. Компоновка БК согласно собранного БИ в п.10=Сборка КНБК -Cпуск КНБК=Спуск КНБК -Cпуск КНБК со сборкой БИ с мостков=Спуск бурильного инструмента со сборкой с мостков -Разбурка оснастки (ЦКОД, цем.стакан, БК), замена раствора=Разбуривание тех.оснастки -Бурение под кондуктор. Наращивание св.=Бурение ротором -Промывка, ОБР, МBТ БР<70 кг/м3=Промывка -Промывка на забое=Промывка -Шаблонирование (подъем)=Шаблонировка во время бурения -Шаблонирование (спуск)=Шаблонировка во время бурения -Промывка на забое. Прокачка ВУС, ОБР, МBТ БР <70 кг/м3=Промывка -Подъем=Подъем КНБК -Разборка КНБК с телесистемой=Разборка КНБК -ПЗР к спуску ОК 245мм=ПЗР при спуске ОК -Спуск ОК 245мм с промежуточными промывками (500 м, 1000м). Вывоз БР с БДЕ=Спуск ОК -Промывка перед цементажем=Промывка при спуске ОК -Цементаж кондуктора 245мм=Цементирование -Монтаж ОУС. Вывоз БР, Чистка емкостей=Чистка ЦСГО/емкостного блока -Монтаж ОУС=Монтаж ПВО -Заготовка бурового раствора, чистка емкостей.=Опрессовка ПВО -Монтаж ПВО, монтаж разрезной воронки и устьевого желоба. Вывоз БР, заготовка БР=Монтаж ПВО -Опрессовка глухих плашек ППГ, БГ, БД , выкидных линий, крестовины с коренными задвижками. ЗБР=Опрессовка ПВО -Сборка КНБК на бурение=Сборка КНБК -Сборка СБТ 127мм-465м=Сборка БИ с мостков на подсвечник -Спуск КНБК со сборкой с мостков СБТ -127 (1700м)=Спуск КНБК -Сборка КНБК на бурение транспортного ствола=Сборка КНБК -Опрессовка трубных плашек, ПУГ=Опрессовка ПВО -Разбурка оснастки (ЦКОД, цем.стакан, БК, углубление на 2 метра ниже БК, опрессовка цементного кольца)=Разбуривание тех.оснастки -Разбурка БК, ЦКОДа и цем.стакана=Разбуривание тех.оснастки -Перевод скважины на новый раствор, чистка ЦСГО=Промывка - перевод скважины на новый раствор -Перевод скважины на новый буровой раствор=Промывка - перевод скважины на новый раствор -Бурение транспортного ствола наращ.св. (прокачка укрепляющих пачек ч/з каждые 150-200м)=Бурение ротором -Промывка после ХМ св TVD - 1660 м (ниже на 50 м)=Промывка -Чистка ЦСГО (опрессовка цем. кольца кондуктора во время чистки ЦСГО)=Чистка ЦСГО/емкостного блока -Промывка после Алымской св TVD - 2140 м (ниже на 50 м)=Промывка -Бурение транспортного ствола наращ. cв. (прокачка укрепляющих пачек ч/з каждые 150-200м).=Бурение ротором -Бурение транспортного ствола (1000м первые сутки бурения)=Бурение ротором -Подъем КНБК шаблонировка ствола скважины=Шаблонировка подъем БИ, продувка -Промывка (по согласованию с ЦУСС)=Промывка -Шаблонировка. Подъем КНБК (по согласованию с ЦУСС)=Шаблонировка во время бурения -Шаблонировка.Спуск КНБК со сборкой БИ 300м (по согласованию с ЦУСС)=Шаблонировка во время бурения -Промывка=Промывка -Шаблонировка. Подъем КНБК=Шаблонировка во время бурения -Шаблонировка.Спуск КНБК=Шаблонировка во время бурения -Разборка КНБК с т/с=Разборка КНБК -Промывка на забое, прокачка кольмат. пачки=Помывка -ПЗР к спуску ОК-178мм.=ПЗР при спуске ОК -Спуск ОК 178 мм (до устья, не потайная) с промежуточными промывками=Спуск ОК -Цементирование ОК-178мм=Цементирование -Отворот и выброс допускной трубы, демонтаж ПВО, замыв шурфа для выброса СБТ-127мм, чистка емкостей, приготовление БР=Демонтаж ПВО -Промывка, установка смазывающей пачки=Промывка -Выброс СБТ-127мм на мостки, чистка емкостей, приготовление БР=Подъем БИ с выбросом на мостки -Подъем КНБК с выбросом БИ - 500м (выброс согласовать с куратором ЦУСС)=Подъем КНБК -Монтаж ПВО, замена трубных плашек 127мм на 102мм, замена рабочего переводника на СВП, приготовление БР=Перетяжка талевого каната -ПЗР к спуску ОК 178мм=ПЗР при спуске ОК -Спуск ОК 178мм с промывками. Вывоз БР с БДЕ=Спуск ОК -Цементирование 178мм ОК. Вывоз БР с БДЕ=Цементирование -Частичный демонтаж ПВО=Демонтаж ПВО -Выброс БИ 127 на мостки - 1600м (Оставляем БИ 127 1400 м на бурение под кондуктор). Вывоз БР, чистка емкостей=Подъем БИ с выбросом на мостки -Частичный монтаж ПВО=Монтаж ПВО -Опрессовка (200 атм) глухих плашек ППГ, БГ, БД, выкидных линий, крестовины с коренными задвижками, ЗБР. Сборка БИ-102мм - 1000м для бурения ГС свечами.=Опрессовка ПВО -Сборка КНБК на бурение секции под хвостовик 114мм=Сборка КНБК -Спуск КНБК со сборкой БИ 102 и промежуточными промывками.=Промывка - перевод скважины на новый раствор -Опрессовка трубных плашек ППГ, ПУГ. Промывка, перезапись гаммы=Опрессовка ПВО -Разбурка оснастки (ЦКОД, цем.стакан, БК)=Разбуривание тех.оснастки -Перевод на новый раствор=Промывка - перевод скважины на новый раствор -Чистка ЦСГО=Чистка ЦСГО/емкостного блока -Бурение горизонтального участка скважины (прокачка укрепляющих пачек ч/з каждые 100 м)=Бурение ротором -Подъем БИ в БК Ø178мм.=Подъем КНБК -Спуск БИ со сборкой ТБТ 88,9мм на опрессовку (20м до БК 178)=Спуск КНБК -Опрессовка БИ, установка на подсвечник ТБТ=Опрессовка БИ -Проработка в 2 этапа:1 этап - прямая принудительная проработка; 2 этап - спуск на "сухую"(имитация спуска хвостовика)=Проработка принудительная -Cборка хвостовика=Сборка хвостовика 114мм (согласно схеме) -Промывка, прокачка ВУС=Промывка -Подъем КНБК=Подъем КНБК -ПЗР к спуску хвостовика=ПЗР при спуске ОК -Сборка хвостовика 114мм (согласно схеме)=Сборка хвостовика 114мм (согласно схеме) -Спуск хвостовика 114мм на БИ. В БК 178 перевод на тех.воду (по согл.с ЦУСС)=Спуск ОК -Активация подвески (4ч). Перевод на жидкость заканчивания (2ч).=Активация подвески, опрессовка -Подъем БИ с выбросом на мостки. Оставляем ТБТ 89 (800 м) на следующую скв=Подъем БИ с выбросом на мостки -Демонтаж ПВО=Демонтаж ПВО -Монтаж, опрессовка ФА=Монтаж, опрессовка ФА -5% времени на ТО БУ=Ремонт -Монтаж ФА=Монтаж, опрессовка ФА -Подъем разъединителя с выбросом СБТ-102мм на мостки=Подъем инструмента -Активация подвески. Перевод на жидкость заканчивания. Опрессовка пакера подвески хвостовика.=Активация подвески (потайной колонны, хвостовика) -ПР к спуску хвостовика=ПЗР при спуске ОК -Подъем КНБК с частичным выбросом СБТ-102мм на приемные мостки=Подъем БИ с выбросом на мостки -Бурение горизонтального участка скважины (прокачка укрепляющих пачек ч/з каждые 100м)=Бурение ротором -Промывка перезапись ГК=Промывка -Спуск КНБК со сборкой СБТ-102мм с приемных мостков, с промежуточными промывками каждые 500м=Спуск бурильного инструмента со сборкой с мостков -Сборка КНБК для бурения горизонтального участка скважины=Сборка БИ с мостков на подсвечник -Опрессовка глухих плашек ППГ, БГ, БД, выкидных линий, крестовины с коренными задвижками, приготовление бур.раствора=Опрессовка ПВО -ВМР=ВМР -Долив затруба при подъёме=Долив затруба при подъёме -Закачка/прокачка пачки=Закачка/прокачка пачки -Комплекс ГИС на жестком кабеле=Комплекс ГИС на жестком кабеле -Комплекс ГИС на кабеле=Комплекс ГИС на кабеле -Комплекс ГИС на трубах=Комплекс ГИС на трубах -Контролируемое ГНВП=Контролируемое ГНВП -Ловильные работы=Ловильные работы -Наработка жёлоба=Наработка жёлоба -Наращивание=Наращивание -НПВ / прочее=НПВ / прочее -Обвязка устья с циркуляционной системой=Обвязка устья с циркуляционной системой -Оборудование устья=Оборудование устья -Обработка БР=Обработка БР -Обработка раствора (несоответствие параметров)=Обработка раствора (несоответствие параметров) -Ожидание=Ожидание -Определение места прихвата и ЛМ=Определение места прихвата и ЛМ -Опрессовка ОК=Опрессовка ОК -Ориентирование ТС при бурении=Ориентирование ТС при бурении -Отворот допускной трубы=Отворот допускной трубы -Перезапись гаммы-каротажа=Перезапись гаммы-каротажа -Перемонтаж ПВО=Перемонтаж ПВО -ПЗР к спуску УЭЦН=ПЗР к спуску УЭЦН -ПЗР при сборке КНБК=ПЗР при сборке КНБК -ПЗР при цементировании=ПЗР при цементировании -Поглощение=Поглощение -Подготовка ствола скважины. Перезапись ГК в интервале установки КО.=Подготовка ствола скважины. Перезапись ГК в интервале установки КО. -Подъем БИ с выбросом на мостки=Подъем БИ с выбросом на мостки -подъем ОК=подъем ОК -Подъем приборов ГИС (на трубах)=Подъем приборов ГИС (на трубах) -Полная замена талевого каната=Полная замена талевого каната -ПР перед забуркой направления=ПР перед забуркой направления -Приготовление БР=Приготовление БР -Продувка манифольда=Продувка манифольда -Промывка перед наращиванием=Промывка перед наращиванием -Проработка во время бурения=Проработка во время бурения -Проработка перед наращиванием=Проработка перед наращиванием -Работа яссом=Работа яссом -Разборка комплекса приборов ГИС=Разборка комплекса приборов ГИС -Разбуривание тех.оснастк=Разбуривание тех.оснастки -Расхаживани=Расхаживание -Ревизия КНБК/инструмента/ЗТС=Ревизия КНБК/инструмента/ЗТС -Ремонт бурового оборудования=Ремонт бурового оборудования -Сальникообразование=Сальникообразование -Сборка и спуск ТБТ=Сборка и спуск ТБТ -Сборка комплекса приборов ГИС=Сборка комплекса приборов ГИС -Сборка устройства ориентирования КО=Сборка устройства ориентирования КО -Смена рабочего переводника ВСП=Смена рабочего переводника ВСП -СПО - колокол=СПО - колокол -СПО - метчик=СПО - метчик -СПО - овершот=СПО - овершот -СПО - труболовка=СПО - труболовка -Спуск БИ со сборкой с мостков=Спуск БИ со сборкой с мостков -Спуск инструмента=Спуск инструмента -Спуск инструмента с проработкой=Спуск инструмента с проработкой -Спуск КО на транспотрной колонне=Спуск КО на транспотрной колонне -Спуск приборов ГИС (на трубах)=Спуск приборов ГИС (на трубах) -Срезка=Срезка -Тайм-дриллинг=Тайм-дриллинг -Тех.отстой=Тех.отстой -Торпедирование (встряхивание)=Торпедирование (встряхивание) -Торпедирование (отстрел)=Торпедирование (отстрел) -Удержание в клиньях=Удержание в клиньях -Установка ванн=Установка ванн -Утяжеление БР=Утяжеление БР -Учебная тревога "Выброс"=Учебная тревога "Выброс" -Фрезеровка=Фрезеровка -Шаблонировка подъем БИ, продувка=Шаблонировка подъем БИ, продувка -Шаблонировка перед наращиванием=Шаблонировка перед наращиванием -Демонтаж ПВО ( переоборудование устья скважины). Вывоз БР=Демонтаж ПВО -Сборка БИ 127/147с мостков установкой на подсвечник=Сборка БИ с мостков на подсвечник -Спуск приборов комплекса АМАК.=Спуск приборов ГИС (на трубах) -Подъем с записью=Подъем приборов ГИС (на трубах) -ОЗЦ под давлением (по согласованию с ЦУСС)=ОЗЦ -"Демонтаж ПВО ( переоборудование устья скважины). Вывоз БР=Демонтаж ПВО -Сборка CБТ-127 (0м) с мостков установкой на подсвечник (оставлено СБТ-127 (1500м) с пердыдущей скв). Заготовка БР=Сборка БИ с мостков на подсвечник -ПЗР к спуску ОК=ПЗР при спуске ОК -Выброс СБТ 127 (2100м), оставляется СБТ-127 (700 м) на след скв. ЗБР, чистка емкостей, вывоз БР.=Подъем БИ с выбросом на мостки -Монтаж ПВО повторный (смена плашек ПВО). ЗБР, чистка емкостей, вывоз БР=Монтаж ПВО -Опрессовка ПВО (200 атм), глухие=Опрессовка ПВО -Сборка ТБТ на 2 этапе (кол-во по согласованию с ЦУСС). Подъем/спуск БИ со сборкой ТБТ 102 мм. Опрессовка БИ (1.5 ч)=Сборка и спуск ТБТ -Спуск пакера=Спуск пакера -Запись гамма-каратожа=Запись гамма-каратожа -Шаблонирование спуск БИ=Шаблонирование спуск БИ -Сборка клин-отклонителя=Сборка клин-отклонителя -Ориентирование и посадка клина-отклонителя=Ориентирование и посадка клина-отклонителя -Протяжка подъемного патрубка подвески=Протяжка подъемного патрубка подвески -Подъем клина-отклонителя=Подъем клина-отклонителя -Стыковка стингера с хвостовиком основного ствола=Стыковка стингера с хвостовиком основного ствола -Ориентирование и установка стыковочного узла хвостовика=Ориентирование и установка стыковочного узла хвостовика -Бурение с отбором керна=Бурение с отбором керна -Работа пакером в обсадной колонне=Работа пакером в обсадной колонне \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/Files/Dictionaries/Sections.txt b/AsbCloudInfrastructure/Services/WellOperationImport/Files/Dictionaries/Sections.txt deleted file mode 100644 index b0b2df54..00000000 --- a/AsbCloudInfrastructure/Services/WellOperationImport/Files/Dictionaries/Sections.txt +++ /dev/null @@ -1,7 +0,0 @@ -направ=Направление -конд=Кондуктор -техн=Техническая колонна -экспл=Эксплуатационная колонна -транс=Транспортный ствол -пилот=Пилотный ствол -хвост=Хвостовик \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/Files/WellOperationImportTemplate.xlsx b/AsbCloudInfrastructure/Services/WellOperationImport/Files/WellOperationImportTemplate.xlsx deleted file mode 100644 index 6f53ccfb..00000000 Binary files a/AsbCloudInfrastructure/Services/WellOperationImport/Files/WellOperationImportTemplate.xlsx and /dev/null differ diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationExportService.cs b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationExportService.cs deleted file mode 100644 index 96e640b8..00000000 --- a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationExportService.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using AsbCloudApp.Data; -using AsbCloudApp.Repositories; -using AsbCloudApp.Requests; -using AsbCloudApp.Services.WellOperationImport; -using AsbCloudInfrastructure.Services.WellOperationImport.Constants; -using ClosedXML.Excel; - -namespace AsbCloudInfrastructure.Services.WellOperationImport; - -public class WellOperationExportService : IWellOperationExportService -{ - private readonly IWellOperationRepository wellOperationRepository; - private readonly IWellOperationImportTemplateService wellOperationImportTemplateService; - private readonly IWellOperationCategoryRepository wellOperationCategoryRepository; - - public WellOperationExportService( - IWellOperationRepository wellOperationRepository, - IWellOperationImportTemplateService wellOperationImportTemplateService, - IWellOperationCategoryRepository wellOperationCategoryRepository) - { - this.wellOperationRepository = wellOperationRepository; - this.wellOperationImportTemplateService = wellOperationImportTemplateService; - this.wellOperationCategoryRepository = wellOperationCategoryRepository; - } - - public async Task<Stream> ExportAsync(int idWell, CancellationToken cancellationToken) - { - var operations = await wellOperationRepository.GetAsync(new WellOperationRequest() - { - IdWell = idWell - }, cancellationToken); - - return MakeExcelFileStream(operations); - } - - private Stream MakeExcelFileStream(IEnumerable<WellOperationDto> operations) - { - using Stream ecxelTemplateStream = wellOperationImportTemplateService.GetExcelTemplateStream(); - - using var workbook = new XLWorkbook(ecxelTemplateStream); - AddOperationsToWorkbook(workbook, operations); - - var memoryStream = new MemoryStream(); - workbook.SaveAs(memoryStream, new SaveOptions { }); - memoryStream.Seek(0, SeekOrigin.Begin); - return memoryStream; - } - - private void AddOperationsToWorkbook(XLWorkbook workbook, IEnumerable<WellOperationDto> operations) - { - var planOperations = operations.Where(o => o.IdType == 0); - if (planOperations.Any()) - { - var sheetPlan = workbook.GetWorksheet(DefaultTemplateInfo.SheetNamePlan); - - AddOperationsToSheet(sheetPlan, planOperations); - } - - var factOperations = operations.Where(o => o.IdType == 1); - if (factOperations.Any()) - { - var sheetFact = workbook.GetWorksheet(DefaultTemplateInfo.SheetNameFact); - - AddOperationsToSheet(sheetFact, factOperations); - } - } - - private void AddOperationsToSheet(IXLWorksheet sheet, IEnumerable<WellOperationDto> operations) - { - var operationsToArray = operations.ToArray(); - - var sections = wellOperationRepository.GetSectionTypes(); - var categories = wellOperationCategoryRepository.Get(false); - - for (int i = 0; i < operationsToArray.Length; i++) - { - var row = sheet.Row(1 + i + DefaultTemplateInfo.HeaderRowsCount); - AddOperationToRow(row, operationsToArray[i], sections, categories); - } - } - - private static void AddOperationToRow(IXLRow row, WellOperationDto operation, IEnumerable<WellSectionTypeDto> sections, - IEnumerable<WellOperationCategoryDto> categories) - { - var sectionCaption = sections.First(s => s.Id == operation.IdWellSectionType).Caption; - var categoryName = categories.First(o => o.Id == operation.IdCategory).Name; - - row.Cell(DefaultTemplateInfo.ColumnSection).SetCellValue(sectionCaption); - row.Cell(DefaultTemplateInfo.ColumnCategory).SetCellValue(categoryName); - row.Cell(DefaultTemplateInfo.ColumnCategoryInfo).SetCellValue(operation.CategoryInfo); - row.Cell(DefaultTemplateInfo.ColumnDepthStart).SetCellValue(operation.DepthStart); - row.Cell(DefaultTemplateInfo.ColumnDepthEnd).SetCellValue(operation.DepthEnd); - row.Cell(DefaultTemplateInfo.ColumnDate).SetCellValue(operation.DateStart.DateTime); - row.Cell(DefaultTemplateInfo.ColumnDuration).SetCellValue(operation.DurationHours); - row.Cell(DefaultTemplateInfo.ColumnComment).SetCellValue(operation.Comment); - } -} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs deleted file mode 100644 index 6ad227a3..00000000 --- a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using AsbCloudApp.Data; -using AsbCloudApp.Data.WellOperationImport; -using AsbCloudApp.Repositories; -using AsbCloudApp.Services; -using AsbCloudApp.Services.WellOperationImport; - -namespace AsbCloudInfrastructure.Services.WellOperationImport; - -public class WellOperationImportService : IWellOperationImportService -{ - private readonly IWellService wellService; - private readonly IWellOperationRepository wellOperationRepository; - private readonly IWellOperationCategoryRepository wellOperationCategoryRepository; - private static readonly DateTime dateLimitMin = new(2001, 1, 1, 0, 0, 0); - private static readonly DateTime dateLimitMax = new(2099, 1, 1, 0, 0, 0); - private static readonly TimeSpan drillingDurationLimitMax = TimeSpan.FromDays(366); - - public WellOperationImportService( - IWellService wellService, - IWellOperationRepository wellOperationRepository, - IWellOperationCategoryRepository wellOperationCategoryRepository - ) - { - this.wellService = wellService; - this.wellOperationRepository = wellOperationRepository; - this.wellOperationCategoryRepository = wellOperationCategoryRepository; - } - - public IEnumerable<WellOperationDto> Import(int idWell, int idUser, int idType, SheetDto sheet) - { - var validationErrors = new List<string>(); - - var sections = wellOperationRepository.GetSectionTypes(); - var categories = wellOperationCategoryRepository.Get(false); - - var wellOperations = new List<WellOperationDto>(); - - var rows = sheet.Rows.OrderBy(r => r.Date); - - var prevRow = new RowDto(); - - foreach (var row in rows) - { - try - { - var section = sections.FirstOrDefault(s => - string.Equals(s.Caption, row.Section, StringComparison.CurrentCultureIgnoreCase)); - - if (section is null) - throw new FileFormatException($"Лист '{sheet.Name}'. В строке '{row.Number}' не удалось определить секцию"); - - var category = categories.FirstOrDefault(c => - string.Equals(c.Name, row.Category, StringComparison.CurrentCultureIgnoreCase)); - - if (category is null) - throw new FileFormatException($"Лист '{sheet.Name}'. В строке '{row.Number}' не удалось определить операцию"); - - if (row.DepthStart is not (>= 0d and <= 20_000d)) - throw new FileFormatException( - $"Лист '{sheet.Name}'. Строка '{row.Number}' некорректная глубина на начало операции"); - - if (row.DepthEnd is not (>= 0d and <= 20_000d)) - throw new FileFormatException( - $"Лист '{sheet.Name}'. Строка '{row.Number}' некорректная глубина на конец операции"); - - if (row.Date < dateLimitMin && row.Date > dateLimitMax) - throw new FileFormatException( - $"Лист '{sheet.Name}'. Строка '{row.Number}' неправильно получена дата начала операции"); - - if (prevRow.Date > row.Date) - throw new FileFormatException( - $"Лист '{sheet.Name}' строка '{row.Number}' дата позднее даты предыдущей операции"); - - if (row.Duration is not (>= 0d and <= 240d)) - throw new FileFormatException($"Лист '{sheet.Name}'. Строка '{row.Number}' некорректная длительность операции"); - - var timezone = wellService.GetTimezone(idWell); - var timezoneOffset = TimeSpan.FromHours(timezone.Hours); - - var wellOperation = new WellOperationDto - { - IdWell = idWell, - IdUser = idUser, - IdType = idType, - IdWellSectionType = section.Id, - WellSectionTypeName = section.Caption, - IdCategory = category.Id, - CategoryName = category.Name, - CategoryInfo = row.CategoryInfo, - DepthStart = row.DepthStart, - DepthEnd = row.DepthEnd, - DateStart = new DateTimeOffset(row.Date, timezoneOffset), - DurationHours = row.Duration, - Comment = row.Comment - }; - - wellOperations.Add(wellOperation); - - prevRow = row; - } - catch (FileFormatException ex) - { - validationErrors.Add(ex.Message); - } - } - - if (wellOperations.Any() && wellOperations.Min(o => o.DateStart) - wellOperations.Max(o => o.DateStart) > drillingDurationLimitMax) - validationErrors.Add($"Лист {sheet.Name} содержит диапазон дат больше {drillingDurationLimitMax}"); - - if (validationErrors.Any()) - throw new FileFormatException(string.Join("\r\n", validationErrors)); - - return wellOperations; - } -} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportTemplateService.cs b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportTemplateService.cs deleted file mode 100644 index edb71c14..00000000 --- a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportTemplateService.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.IO; -using System.Linq; -using System.Reflection; -using AsbCloudApp.Services.WellOperationImport; - -namespace AsbCloudInfrastructure.Services.WellOperationImport; - -public class WellOperationImportTemplateService : IWellOperationImportTemplateService -{ - public Stream GetExcelTemplateStream() - { - var resourceName = Assembly.GetExecutingAssembly() - .GetManifestResourceNames() - .FirstOrDefault(n => n.EndsWith("WellOperationImportTemplate.xlsx"))!; - - var stream = Assembly.GetExecutingAssembly() - .GetManifestResourceStream(resourceName)!; - - return stream; - } -} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs b/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs index c9018051..638232f3 100644 --- a/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs +++ b/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data.SAUB; +using AsbCloudApp.Data.WellOperation; using AsbCloudApp.Repositories; namespace AsbCloudInfrastructure.Services.WellOperationService; @@ -145,6 +146,8 @@ public class OperationsStatService : IOperationsStatService private async Task<StatWellDto> CalcWellStatAsync(Well well, CancellationToken token) { + var timezone = wellService.GetTimezone(well.Id); + var wellType = (await memoryCache .GetOrCreateBasicAsync(db.Set<WellType>(), token)) .FirstOrDefault(t => t.Id == well.IdWellType); @@ -169,9 +172,8 @@ public class OperationsStatService : IOperationsStatService if (!wellOperations.Any()) return statWellDto; - var timezoneOffsetH = wellService.GetTimezone(well.Id).Hours; - statWellDto.Sections = CalcSectionsStats(wellOperations, timezoneOffsetH); - statWellDto.Total = GetStatTotal(wellOperations, well.IdState, timezoneOffsetH); + statWellDto.Sections = CalcSectionsStats(wellOperations, timezone.Hours); + statWellDto.Total = GetStatTotal(wellOperations, well.IdState, timezone.Hours); statWellDto.TvdLagDays = CalcTvdLagDays(wellOperations); statWellDto.TvdDrillingDays = CalcDrillingDays(wellOperations); @@ -287,8 +289,8 @@ public class OperationsStatService : IOperationsStatService var section = new StatOperationsDto { - Start = operations.FirstOrDefault()?.DateStart.ToRemoteDateTime(timezoneOffsetHours), - End = operations.Max(o => o.DateStart.ToRemoteDateTime(timezoneOffsetHours).AddHours(o.DurationHours)), + Start = operations.FirstOrDefault()?.DateStart.ToOffset(TimeSpan.FromHours(timezoneOffsetHours)), + End = operations.Max(o => o.DateStart.ToOffset(TimeSpan.FromHours(timezoneOffsetHours)).AddHours(o.DurationHours)), WellDepthStart = operations.Min(o => o.DepthStart), WellDepthEnd = operations.Max(o => o.DepthStart), Rop = CalcROP(operations), @@ -552,8 +554,8 @@ public class OperationsStatService : IOperationsStatService private static WellOperationDto Convert(WellOperation source, double tzOffsetHours) { var destination = source.Adapt<WellOperationDto>(); - destination.CategoryName = source.OperationCategory?.Name; - destination.WellSectionTypeName = source.WellSectionType?.Caption; + destination.OperationCategoryName = source.OperationCategory.Name; + destination.WellSectionTypeCaption = source.WellSectionType.Caption; destination.DateStart = source.DateStart.ToRemoteDateTime(tzOffsetHours); return destination; } diff --git a/AsbCloudInfrastructure/Services/WellOperationService/ScheduleReportService.cs b/AsbCloudInfrastructure/Services/WellOperationService/ScheduleReportService.cs index 39ad3cd6..96ef7b85 100644 --- a/AsbCloudInfrastructure/Services/WellOperationService/ScheduleReportService.cs +++ b/AsbCloudInfrastructure/Services/WellOperationService/ScheduleReportService.cs @@ -9,6 +9,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Data.WellOperation; namespace AsbCloudInfrastructure.Services.WellOperationService { @@ -89,7 +90,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService { var row = sheet.Row(i + headerRowsCount); SetCell(row, columnRowNumber, $"{i}"); - SetCell(row, columnCaption, $"{tvdItem.CategoryName} {tvdItem.CategoryInfo}".Trim()); + SetCell(row, columnCaption, $"{tvdItem.OperationCategoryName} {tvdItem.CategoryInfo}".Trim()); SetCell(row, columnWellDepthStart, tvdItem.DepthStart); SetCell(row, columnWellDepthEnd, tvdItem.DepthEnd); SetCell(row, columnDuration, tvdItem.DurationHours); @@ -150,7 +151,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService var row = sheet.Row(1 + i + headerRowsCount); SetCell(row, columnRowNumber, $"{1 + i}"); - SetCell(row, columnCaption, $"{operation.CategoryName} {operation.CategoryInfo}".Trim()); + SetCell(row, columnCaption, $"{operation.OperationCategoryName} {operation.CategoryInfo}".Trim()); SetCell(row, columnWellDepthStartPlan, tvdItem.Plan?.DepthStart); SetCell(row, columnWellDepthStartFact, tvdItem.Fact?.DepthStart); diff --git a/AsbCloudInfrastructure/Services/WellOperations/Factories/WellOperationExportServiceFactory.cs b/AsbCloudInfrastructure/Services/WellOperations/Factories/WellOperationExportServiceFactory.cs new file mode 100644 index 00000000..1dc1d2a7 --- /dev/null +++ b/AsbCloudInfrastructure/Services/WellOperations/Factories/WellOperationExportServiceFactory.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests.ExportOptions; +using AsbCloudApp.Services; +using AsbCloudApp.Services.Export; +using AsbCloudDb.Model; +using AsbCloudInfrastructure.Services.ExcelServices.Templates.WellOperations; +using Microsoft.Extensions.DependencyInjection; + +namespace AsbCloudInfrastructure.Services.WellOperations.Factories; + +public class WellOperationExportServiceFactory : IExportServiceFactory<int> +{ + private readonly IDictionary<int, Func<IExportService>> exportServices; + + public WellOperationExportServiceFactory(IServiceProvider serviceProvider) + { + var wellOperationRepository = serviceProvider.GetRequiredService<IWellOperationRepository>(); + var wellService = serviceProvider.GetRequiredService<IWellService>(); + + exportServices = new Dictionary<int, Func<IExportService>> + { + { + WellOperation.IdOperationTypeFact, + () => new WellOperationExport<WellOperationFactTemplate>(wellOperationRepository, wellService) + }, + { + WellOperation.IdOperationTypePlan, + () => new WellOperationExport<WellOperationPlanTemplate>(wellOperationRepository, wellService) + } + }; + } + + public IExportService<TOptions> CreateExportService<TOptions>(int id) + where TOptions : IExportOptionsRequest + { + var parser = exportServices[id].Invoke(); + + return parser as IExportService<TOptions> + ?? throw new ArgumentNullException(nameof(id), "Не удалось экспортировать файл"); + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellOperations/Factories/WellOperationParserFactory.cs b/AsbCloudInfrastructure/Services/WellOperations/Factories/WellOperationParserFactory.cs new file mode 100644 index 00000000..4107a7dd --- /dev/null +++ b/AsbCloudInfrastructure/Services/WellOperations/Factories/WellOperationParserFactory.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using AsbCloudApp.Data.WellOperation; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests.ParserOptions; +using AsbCloudApp.Services.Parsers; +using AsbCloudDb.Model; +using AsbCloudInfrastructure.Services.ExcelServices.Templates.WellOperations; +using Microsoft.Extensions.DependencyInjection; + +namespace AsbCloudInfrastructure.Services.WellOperations.Factories; + +public class WellOperationParserFactory : IParserFactory<int, WellOperationDto> +{ + private readonly IDictionary<int, Func<IParserService>> parsers; + + public WellOperationParserFactory(IServiceProvider serviceProvider) + { + var wellOperationRepository = serviceProvider.GetRequiredService<IWellOperationRepository>(); + var categoryRepository = serviceProvider.GetRequiredService<IWellOperationCategoryRepository>(); + + parsers = new Dictionary<int, Func<IParserService>> + { + { + WellOperation.IdOperationTypeFact, + () => new WellOperationParser<WellOperationFactTemplate>(wellOperationRepository, categoryRepository) + }, + { + WellOperation.IdOperationTypePlan, + () => new WellOperationParser<WellOperationPlanTemplate>(wellOperationRepository, categoryRepository) + } + }; + } + + public IParserService<WellOperationDto, TOptions> CreateParser<TOptions>(int id) + where TOptions : IParserOptionsRequest + { + var parser = parsers[id].Invoke(); + + return parser as IParserService<WellOperationDto, TOptions> + ?? throw new ArgumentNullException(nameof(id), "Не удалось распознать файл"); + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellOperations/Templates/WellOperationFactTemplate.xlsx b/AsbCloudInfrastructure/Services/WellOperations/Templates/WellOperationFactTemplate.xlsx new file mode 100644 index 00000000..065dc207 Binary files /dev/null and b/AsbCloudInfrastructure/Services/WellOperations/Templates/WellOperationFactTemplate.xlsx differ diff --git a/AsbCloudInfrastructure/Services/WellOperations/Templates/WellOperationPlanTemplate.xlsx b/AsbCloudInfrastructure/Services/WellOperations/Templates/WellOperationPlanTemplate.xlsx new file mode 100644 index 00000000..c5d53089 Binary files /dev/null and b/AsbCloudInfrastructure/Services/WellOperations/Templates/WellOperationPlanTemplate.xlsx differ diff --git a/AsbCloudInfrastructure/Services/WellOperations/WellOperationExport.cs b/AsbCloudInfrastructure/Services/WellOperations/WellOperationExport.cs new file mode 100644 index 00000000..430bf92f --- /dev/null +++ b/AsbCloudInfrastructure/Services/WellOperations/WellOperationExport.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using AsbCloudApp.Data.WellOperation; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests; +using AsbCloudApp.Requests.ExportOptions; +using AsbCloudApp.Services; +using AsbCloudDb.Model; +using AsbCloudInfrastructure.Services.ExcelServices; +using AsbCloudInfrastructure.Services.ExcelServices.Templates; + +namespace AsbCloudInfrastructure.Services.WellOperations; + +public class WellOperationExport<TTemplate> : ExcelExportService<WellOperationDto, WellOperationExportRequest, TTemplate> + where TTemplate : class, ITemplateParameters, new() +{ + private readonly IWellService wellService; + private readonly IWellOperationRepository wellOperationRepository; + + public WellOperationExport(IWellOperationRepository wellOperationRepository, + IWellService wellService) + { + this.wellOperationRepository = wellOperationRepository; + this.wellService = wellService; + } + + protected override async Task<string> BuildFileNameAsync(WellOperationExportRequest options, CancellationToken token) + { + var caption = await wellService.GetWellCaptionByIdAsync(options.IdWell, token); + + return options.IdType switch + { + WellOperation.IdOperationTypeFact => $"{caption}_Фактические_операции.xlsx", + WellOperation.IdOperationTypePlan => $"{caption}_Плановые_операции.xlsx", + _ => throw new ArgumentOutOfRangeException(nameof(options.IdType)) + }; + } + + protected override Task<IEnumerable<WellOperationDto>> GetDtosAsync(WellOperationExportRequest options, CancellationToken token) + { + var request = new WellOperationRequest(new[] { options.IdWell }) + { + OperationType = options.IdType + }; + + return wellOperationRepository.GetAsync(request, token); + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellOperations/WellOperationParser.cs b/AsbCloudInfrastructure/Services/WellOperations/WellOperationParser.cs new file mode 100644 index 00000000..65bda0a2 --- /dev/null +++ b/AsbCloudInfrastructure/Services/WellOperations/WellOperationParser.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using AsbCloudApp.Data; +using AsbCloudApp.Data.WellOperation; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests.ParserOptions; +using AsbCloudInfrastructure.Services.ExcelServices; +using AsbCloudInfrastructure.Services.ExcelServices.Templates; + +namespace AsbCloudInfrastructure.Services.WellOperations; + +public class WellOperationParser<TTemplateParameters> : ExcelWellRelatedParser<WellOperationDto, WellOperationParserRequest, TTemplateParameters> + where TTemplateParameters : class, ITemplateParameters, new() +{ + private readonly IEnumerable<WellSectionTypeDto> sectionTypes; + private readonly IEnumerable<WellOperationCategoryDto> categories; + + public WellOperationParser(IWellOperationRepository wellOperationRepository, + IWellOperationCategoryRepository categoryRepository) + { + categories = categoryRepository.Get(false); + sectionTypes = wellOperationRepository.GetSectionTypes(); + } + + public override ParserResultDto<WellOperationDto> Parse(Stream file, WellOperationParserRequest options) + { + var result = base.Parse(file, options); + + foreach (var dto in result.Item) + { + dto.Item.IdWell = options.IdWell; + dto.Item.IdType = options.IdType; + dto.Item.DateStart = new DateTimeOffset(dto.Item.DateStart.DateTime, options.WellTimezone.Offset); + } + + return result; + } + + protected override WellOperationDto BuildDto(IDictionary<string, object?> row, int rowNumber) + { + var dto = base.BuildDto(row, rowNumber); + + var sectionType = sectionTypes.FirstOrDefault(s => + string.Equals(s.Caption.Trim(), dto.WellSectionTypeCaption?.Trim(), StringComparison.CurrentCultureIgnoreCase)); + + if (sectionType is null) + { + var message = string.Format(XLExtentions.ProblemDetailsTemplate, + TemplateParameters.SheetName, + rowNumber, + TemplateParameters.Cells[nameof(WellOperationDto.WellSectionTypeCaption)], + "Указана некорректная секция"); + throw new FileFormatException(message); + } + + var category = categories.FirstOrDefault(c => + string.Equals(c.Name.Trim(), dto.OperationCategoryName?.Trim(), StringComparison.CurrentCultureIgnoreCase)); + + if (category is null) + { + var message = string.Format(XLExtentions.ProblemDetailsTemplate, + TemplateParameters.SheetName, + rowNumber, + TemplateParameters.Cells[nameof(WellOperationDto.OperationCategoryName)], + "Указана некорректная операция"); + throw new FileFormatException(message); + } + + dto.IdWellSectionType = sectionType.Id; + dto.IdCategory = category.Id; + dto.IdParentCategory = category.IdParent; + + return dto; + } +} \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellService.cs b/AsbCloudInfrastructure/Services/WellService.cs index 4d6ec10a..6ed241a0 100644 --- a/AsbCloudInfrastructure/Services/WellService.cs +++ b/AsbCloudInfrastructure/Services/WellService.cs @@ -47,7 +47,7 @@ namespace AsbCloudInfrastructure.Services this.telemetryService = telemetryService; this.timezoneService = timezoneService; this.wellInfoService = wellInfoService; - this.wellOperationRepository = new WellOperationRepository(db, memoryCache, this, wellOperationCategoryRepository); + wellOperationRepository = new WellOperationRepository(db, memoryCache, wellOperationCategoryRepository, this); companyTypesService = new CrudCacheRepositoryBase<CompanyTypeDto, CompanyType>(dbContext, memoryCache); } @@ -63,15 +63,15 @@ namespace AsbCloudInfrastructure.Services private void DropCacheRelationCompanyWell() => memoryCache.DropBasic<RelationCompanyWell>(); - public DateTime GetLastTelemetryDate(int idWell) + public DateTimeOffset GetLastTelemetryDate(int idWell) { var well = GetOrDefault(idWell); if (well?.IdTelemetry is null) - return DateTime.MinValue; + return DateTimeOffset.MinValue; var datesRange = telemetryService.GetDatesRange(well.IdTelemetry.Value); - return datesRange.To; + return datesRange.To.DateTime; } /// <inheritdoc/> @@ -272,13 +272,14 @@ namespace AsbCloudInfrastructure.Services if (entity.Timezone is null) dto.Timezone = GetTimezone(entity.Id); - - dto.StartDate = wellOperationRepository.FirstOperationDate(entity.Id)?.ToRemoteDateTime(dto.Timezone.Hours); + + dto.StartDate = dbContext.WellOperations.Where(e => e.IdType == WellOperation.IdOperationTypeFact) + .MinOrDefault(e => e.DateStart)?.ToRemoteDateTime(dto.Timezone.Hours); dto.WellType = entity.WellType.Caption; dto.Cluster = entity.Cluster.Caption; dto.Deposit = entity.Cluster.Deposit.Caption; if (entity.IdTelemetry is not null) - dto.LastTelemetryDate = telemetryService.GetDatesRange(entity.IdTelemetry.Value).To; + dto.LastTelemetryDate = telemetryService.GetDatesRange(entity.IdTelemetry.Value).To.ToOffset(dto.Timezone.Offset); dto.Companies = entity.RelationCompaniesWells .Select(r => Convert(r.Company)) .ToList(); @@ -296,47 +297,10 @@ namespace AsbCloudInfrastructure.Services public SimpleTimezoneDto GetTimezone(int idWell) { - var well = GetOrDefault(idWell) + var cache = GetCache(); + var cacheItem = cache.FirstOrDefault(d => d.Id == idWell) ?? throw new ArgumentInvalidException(nameof(idWell), $"idWell: {idWell} does not exist."); - return GetTimezone(well); - } - - private SimpleTimezoneDto GetTimezone(WellDto wellDto) - { - if (wellDto.Timezone is not null) - return wellDto.Timezone; - - if (wellDto.Telemetry is not null) - { - var timezone = telemetryService.GetTimezone(wellDto.Telemetry.Id); - if (timezone is not null) - return timezone; - } - - var well = GetQuery().FirstOrDefault(w => w.Id == wellDto.Id); - - if (well is not null) - { - var point = GetCoordinates(well); - if (point is not null) - { - if (point.Timezone is not null) - { - return point.Timezone.Adapt<SimpleTimezoneDto>(); - } - - if (point.Latitude is not null & point.Longitude is not null) - { - var timezone = timezoneService.GetOrDefaultByCoordinates(point.Latitude!.Value, point.Longitude!.Value); - if (timezone is not null) - { - return timezone; - } - } - } - } - - throw new Exception($"Can't find timezone for well {wellDto.Caption} id: {wellDto.Id}"); + return cacheItem.Timezone.Adapt<SimpleTimezoneDto>(); } private bool IsTelemetryAssignedToDifferentWell(WellDto wellDto) @@ -349,7 +313,7 @@ namespace AsbCloudInfrastructure.Services if (existingWellWithAssignedTelemetry is null) return false; - + return existingWellWithAssignedTelemetry.Id != wellDto.Id; } diff --git a/AsbCloudInfrastructure/XLExtentions.cs b/AsbCloudInfrastructure/XLExtentions.cs index e9cf11f5..b542c1d1 100644 --- a/AsbCloudInfrastructure/XLExtentions.cs +++ b/AsbCloudInfrastructure/XLExtentions.cs @@ -17,10 +17,16 @@ public static class XLExtentions public static IXLCell SetCellValue<T>(this IXLCell cell, T value, string? format = null) { - if (typeof(T) == typeof(DateTime)) + if (value is DateTime || value is DateTimeOffset) { cell.Style.DateFormat.Format = format ?? "DD.MM.YYYY HH:MM:SS"; - } + + if (value is DateTimeOffset dateTimeOffset) + { + cell.Value = XLCellValue.FromObject(dateTimeOffset.DateTime); + return cell; + } + } cell.Value = XLCellValue.FromObject(value); diff --git a/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj b/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj index b97bed80..b23176e3 100644 --- a/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj +++ b/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj @@ -23,6 +23,8 @@ </ItemGroup> <ItemGroup> + <EmbeddedResource Include="Controllers\WellOperations\Files\PlanWellOperations.xlsx" /> + <EmbeddedResource Include="Controllers\WellOperations\Files\FactWellOperations.xlsx" /> <EmbeddedResource Include="WellOperationsPlan.xlsx" /> </ItemGroup> diff --git a/AsbCloudWebApi.IntegrationTests/Clients/IWellOperationClient.cs b/AsbCloudWebApi.IntegrationTests/Clients/IWellOperationClient.cs index 8e2db98f..84906a77 100644 --- a/AsbCloudWebApi.IntegrationTests/Clients/IWellOperationClient.cs +++ b/AsbCloudWebApi.IntegrationTests/Clients/IWellOperationClient.cs @@ -1,5 +1,7 @@ using AsbCloudApp.Data; +using AsbCloudApp.Data.WellOperation; using AsbCloudApp.Requests; +using Microsoft.AspNetCore.Mvc; using Refit; namespace AsbCloudWebApi.IntegrationTests.Clients; @@ -8,20 +10,23 @@ public interface IWellOperationClient { private const string BaseRoute = "/api/well/{idWell}/wellOperations"; - [Post(BaseRoute + "/{idType}/{deleteBeforeInsert}")] - Task<IApiResponse<int>> InsertRangeAsync(int idWell, int idType, bool deleteBeforeInsert, [Body] IEnumerable<WellOperationDto> dtos); + [Post(BaseRoute + "/{deleteBeforeInsert}")] + Task<IApiResponse<int>> InsertRangeAsync(int idWell, + bool deleteBeforeInsert, + [Body] IEnumerable<WellOperationDto> dtos); - [Put(BaseRoute + "/{idOperation}")] - Task<IApiResponse<int>> UpdateAsync(int idWell, int idOperation, [Body] WellOperationDto value, CancellationToken token); + [Put(BaseRoute)] + Task<IApiResponse<int>> UpdateRangeAsync(int idWell, [Body] IEnumerable<WellOperationDto> dtos); - [Get(BaseRoute + "/plan")] - Task<IApiResponse<PaginationContainer<WellOperationDto>>> GetPageOperationsPlanAsync(int idWell, - [Query] WellOperationRequestBase request, - CancellationToken token); + [Get(BaseRoute)] + Task<IApiResponse<PaginationContainer<WellOperationDto>>> GetPageOperationsPlanAsync(int idWell, [Query] WellOperationRequestBase request); [Multipart] - [Post(BaseRoute + "/import/plan/default")] - Task<IApiResponse<IEnumerable<WellOperationDto>>> ImportPlanDefaultExcelFileAsync(int idWell, - [AliasAs("files")] IEnumerable<StreamPart> streams, - CancellationToken token); + [Post(BaseRoute + "/parse/{idType}")] + Task<IApiResponse<ParserResultDto<WellOperationDto>>> ParseAsync(int idWell, + int idType, + [AliasAs("file")] StreamPart file); + + [Get(BaseRoute + "/export")] + Task<IApiResponse<PhysicalFileResult>> ExportAsync(int idWell, int idType); } \ No newline at end of file diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/WellOperations/Files/FactWellOperations.xlsx b/AsbCloudWebApi.IntegrationTests/Controllers/WellOperations/Files/FactWellOperations.xlsx new file mode 100644 index 00000000..45ee8a0b Binary files /dev/null and b/AsbCloudWebApi.IntegrationTests/Controllers/WellOperations/Files/FactWellOperations.xlsx differ diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/WellOperations/Files/PlanWellOperations.xlsx b/AsbCloudWebApi.IntegrationTests/Controllers/WellOperations/Files/PlanWellOperations.xlsx new file mode 100644 index 00000000..3083297e Binary files /dev/null and b/AsbCloudWebApi.IntegrationTests/Controllers/WellOperations/Files/PlanWellOperations.xlsx differ diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/WellOperationControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/WellOperations/WellOperationControllerTest.cs similarity index 55% rename from AsbCloudWebApi.IntegrationTests/Controllers/WellOperationControllerTest.cs rename to AsbCloudWebApi.IntegrationTests/Controllers/WellOperations/WellOperationControllerTest.cs index 830f2e14..4d6dd3c0 100644 --- a/AsbCloudWebApi.IntegrationTests/Controllers/WellOperationControllerTest.cs +++ b/AsbCloudWebApi.IntegrationTests/Controllers/WellOperations/WellOperationControllerTest.cs @@ -1,16 +1,16 @@ -using AsbCloudApp.Data; -using AsbCloudDb.Model; -using AsbCloudWebApi.IntegrationTests.Clients; using System.Net; using System.Reflection; +using AsbCloudApp.Data.WellOperation; using AsbCloudApp.Requests; +using AsbCloudDb.Model; +using AsbCloudWebApi.IntegrationTests.Clients; using AsbCloudWebApi.IntegrationTests.Data; using Mapster; using Microsoft.EntityFrameworkCore; using Refit; using Xunit; -namespace AsbCloudWebApi.IntegrationTests.Controllers; +namespace AsbCloudWebApi.IntegrationTests.Controllers.WellOperations; public class WellOperationControllerTest : BaseIntegrationTest { @@ -37,7 +37,7 @@ public class WellOperationControllerTest : BaseIntegrationTest var dtos = new[] { entity.Adapt<WellOperationDto>() }; //act - var response = await client.InsertRangeAsync(well.Id, 1, false, dtos); + var response = await client.InsertRangeAsync(well.Id, false, dtos); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -56,18 +56,18 @@ public class WellOperationControllerTest : BaseIntegrationTest var dtos = new[] { entity.Adapt<WellOperationDto>() }; //act - var response = await client.InsertRangeAsync(well.Id, 1, true, dtos); + var response = await client.InsertRangeAsync(well.Id, true, dtos); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); } /// <summary> - /// Успешное обновление операции + /// Успешное обновление операций /// </summary> /// <returns></returns> [Fact] - public async Task UpdateAsync_returns_success() + public async Task UpdateRangeAsync_returns_success() { //arrange var well = await dbContext.Wells.FirstAsync(); @@ -75,10 +75,10 @@ public class WellOperationControllerTest : BaseIntegrationTest dbContext.WellOperations.Add(entity); await dbContext.SaveChangesAsync(); - var dto = entity.Adapt<WellOperationDto>(); + var dtos = new[] { entity.Adapt<WellOperationDto>() }; //act - var response = await client.UpdateAsync(well.Id, entity.Id, dto, CancellationToken.None); + var response = await client.UpdateRangeAsync(well.Id, dtos); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -100,6 +100,7 @@ public class WellOperationControllerTest : BaseIntegrationTest var dto = entity.Adapt<WellOperationDto>(); var timezoneOffset = TimeSpan.FromHours(well.Timezone.Hours); dto.DateStart = dto.DateStart.ToOffset(timezoneOffset); + dto.LastUpdateDate = dto.LastUpdateDate?.ToOffset(timezoneOffset); var request = new WellOperationRequestBase { @@ -107,59 +108,93 @@ public class WellOperationControllerTest : BaseIntegrationTest }; //act - var response = await client.GetPageOperationsPlanAsync(well.Id, request, CancellationToken.None); + var response = await client.GetPageOperationsPlanAsync(well.Id, request); //assert + Assert.Equal(response.StatusCode, HttpStatusCode.OK); Assert.NotNull(response.Content); Assert.Single(response.Content.Items); var actualDto = response.Content.Items.First(); - var excludeProps = new[] - { - nameof(WellOperationDto.LastUpdateDate) - }; - MatchHelper.Match(dto, actualDto, excludeProps); + MatchHelper.Match(dto, actualDto); } - [Fact] - public async Task ImportPlanDefaultExcelFileAsync_returns_success() + [Theory] + [InlineData(WellOperation.IdOperationTypePlan, "PlanWellOperations.xlsx")] + [InlineData(WellOperation.IdOperationTypeFact, "FactWellOperations.xlsx")] + public async Task ParseAsync_returns_success(int idType, string fileName) { //arrange - var stream = Assembly.GetExecutingAssembly().GetFileCopyStream("WellOperationsPlan.xlsx"); - - var memoryStream = new MemoryStream(); - await stream.CopyToAsync(memoryStream); - memoryStream.Position = 0; - var well = await dbContext.Wells.FirstAsync(); - //act - var streamPart = new StreamPart(memoryStream, "WellOperations.xlsx", "application/octet-stream"); + var expectedDto = new WellOperationDto + { + IdWell = well.Id, + IdWellSectionType = 2, + IdCategory = WellOperationCategory.IdSlide, + IdPlan = null, + CategoryInfo = "Доп.инфо", + IdType = idType, + DepthStart = 10.0, + DepthEnd = 20.0, + DateStart = new DateTimeOffset(new DateTime(2023, 1, 10), TimeSpan.FromHours(well.Timezone.Hours)), + DurationHours = 1.0, + Comment = "123", + }; - var response = await client.ImportPlanDefaultExcelFileAsync(well.Id, new[] { streamPart }, CancellationToken.None); + var stream = Assembly.GetExecutingAssembly().GetFileCopyStream(fileName); + + var streamPart = new StreamPart(stream, fileName, "application/octet-stream"); + + //act + var response = await client.ParseAsync(well.Id, idType, streamPart); //assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.NotNull(response.Content); - Assert.Equal(4, response.Content.Count()); - Assert.True(response.Content.All(w => Math.Abs(w.DateStart.Offset.Hours - Defaults.Timezone.Hours) < 0.1)); + + var actualDto = response.Content.Item.First().Item; + + MatchHelper.Match(expectedDto, actualDto); } - private static WellOperation CreateWellOperation(int idWell) => + [Theory] + [InlineData(WellOperation.IdOperationTypePlan)] + [InlineData(WellOperation.IdOperationTypeFact)] + public async Task ExportAsync_returns_success(int idType) + { + //arrange + var well = await dbContext.Wells.FirstAsync(); + + var entity = CreateWellOperation(well.Id, idType); + dbContext.WellOperations.Add(entity); + await dbContext.SaveChangesAsync(); + + //act + var response = await client.ExportAsync(well.Id, idType); + + //assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal("application/octet-stream", response.ContentHeaders?.ContentType?.MediaType); + Assert.True(response.ContentHeaders?.ContentLength > 0); + } + + private static WellOperation CreateWellOperation(int idWell, int idType = WellOperation.IdOperationTypePlan) => new() { IdWell = idWell, IdWellSectionType = 2, - LastUpdateDate = DateTimeOffset.UtcNow, - IdCategory = 5000, + IdCategory = WellOperationCategory.IdSlide, IdPlan = null, - CategoryInfo = "1", - IdType = 0, + CategoryInfo = "Доп.инфо", + LastUpdateDate = new DateTimeOffset(new DateTime(2023, 1, 10)).ToUniversalTime(), + IdType = idType, DepthStart = 10.0, DepthEnd = 20.0, DateStart = new DateTimeOffset(new DateTime(2023, 1, 10), TimeSpan.FromHours(Defaults.Timezone.Hours)).ToUniversalTime(), DurationHours = 1.0, Comment = "1", - IdUser = 1 + IdUser = 1, }; } \ No newline at end of file diff --git a/AsbCloudWebApi.Tests/Services/DailyReportServiceTest.cs b/AsbCloudWebApi.Tests/Services/DailyReportServiceTest.cs index 58f23ccc..38f1959e 100644 --- a/AsbCloudWebApi.Tests/Services/DailyReportServiceTest.cs +++ b/AsbCloudWebApi.Tests/Services/DailyReportServiceTest.cs @@ -12,6 +12,7 @@ using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudApp.Services.ProcessMaps.WellDrilling; +using AsbCloudDb.Model; using AsbCloudInfrastructure.Services.DailyReport; using NSubstitute; using System; @@ -19,6 +20,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Data.WellOperation; using Xunit; namespace AsbCloudWebApi.Tests.Services; @@ -113,7 +115,7 @@ public class DailyReportServiceTest private readonly ProcessMapReportDataSaubStatDto fakeProcessMapReportWellDrilling = new() { DrillingMode = "Ротор", - DateStart = new DateTime(2023, 10, 26), + DateStart = new DateTimeOffset(2023, 10, 26, 0, 0, 0, TimeSpan.Zero), DeltaDepth = 500, Rop = new PlanFactDto<double?> { @@ -154,7 +156,7 @@ public class DailyReportServiceTest IdWell = idWell, IdParentCategory = 4001, IdWellSectionType = 1, - CategoryName = "Механическое. бурение", + OperationCategoryName = "Механическое. бурение", DateStart = new DateTime(2023, 10, 26), DepthStart = 80, DepthEnd = 150, @@ -164,7 +166,7 @@ public class DailyReportServiceTest private readonly WellOperationDto fakeLastFactWellOperation = new() { IdWell = idWell, - CategoryName = "Механическое. бурение", + OperationCategoryName = "Механическое. бурение", IdWellSectionType = 1, IdParentCategory = 4001, DateStart = new DateTime(2023, 10, 26), @@ -178,8 +180,8 @@ public class DailyReportServiceTest IdWell = idWell, ShiftStart = new TimeDto(1), ShiftEnd = new TimeDto(5), - DrillStart = new DateTime(2023, 01, 26), - DrillEnd = new DateTime(2023, 12, 26), + DrillStart = new DateTimeOffset(2023, 01, 26, 0, 0, 0, TimeSpan.Zero), + DrillEnd = new DateTimeOffset(2023, 12, 26, 0, 0, 0, TimeSpan.Zero), Driller = new() { Name = "Иван", @@ -282,7 +284,7 @@ public class DailyReportServiceTest subsystemServiceMock.GetStatAsync(Arg.Any<SubsystemRequest>(), Arg.Any<CancellationToken>()) .ReturnsForAnyArgs(new[] { fakeSubsystemsStat }); - scheduleRepositoryMock.GetAsync(Arg.Any<int>(), Arg.Any<DateTime>(), Arg.Any<CancellationToken>()) + scheduleRepositoryMock.GetAsync(Arg.Any<int>(), Arg.Any<DateTimeOffset>(), Arg.Any<CancellationToken>()) .ReturnsForAnyArgs(new[] { fakeShedule }); processMapReportWellDrillingServiceMock.GetAsync(Arg.Any<int>(), fakeRequest, Arg.Any<CancellationToken>()) @@ -523,12 +525,12 @@ public class DailyReportServiceTest .Returns(datesRange); //act - var result = await dailyReportService.GetDatesRangeAsync(idWell, CancellationToken.None); + var result = await wellOperationRepositoryMock.GetDatesRangeAsync(idWell, WellOperation.IdOperationTypeFact, CancellationToken.None); //assert Assert.NotNull(result); Assert.True(result.From <= result.To); - Assert.True(result.To < DateTime.UtcNow.Date); + Assert.True(result.To < DateTimeOffset.UtcNow); } public static IEnumerable<object[]> DateDailyReport() diff --git a/AsbCloudWebApi.Tests/Services/DetectedOperations/Detectors/DetectorConditioning.cs b/AsbCloudWebApi.Tests/Services/DetectedOperations/Detectors/DetectorConditioning.cs new file mode 100644 index 00000000..0a9829f5 --- /dev/null +++ b/AsbCloudWebApi.Tests/Services/DetectedOperations/Detectors/DetectorConditioning.cs @@ -0,0 +1,92 @@ +using AsbCloudDb.Model; +using AsbCloudInfrastructure.Services.DetectOperations; +using AsbCloudInfrastructure.Services.DetectOperations.Detectors; +using System; +using Xunit; + +namespace AsbCloudWebApi.Tests.Services.DetectedOperations.Detectors; + +/// <summary> +/// Тестирование автоопределения операции "Проработка" +/// </summary> +public class DetectorConditioningTests : DetectorFlashing +{ + private readonly DetectorConditioning detector = new(); + + /// <summary> + /// Операция, попадающая под автоопределение операции промывки + /// </summary> + private readonly DetectableTelemetry telemetry = new() + { + Pressure = 21, + RotorSpeed = 9, + WellDepth = 152, + BitDepth = 151, + DateTime = DateTimeOffset.Now, + }; + + + [Fact] + public void DetectOperation_find_startOperation_notFind_endOperation() + { + //arrange + var point0 = telemetry.Copy(); + var point1 = telemetry.Copy(); + point1.DateTime = point0.DateTime.AddMinutes(3); + + var telemetries = new[] { point0, point1 }; + + //act + var isDetectOperation = detector.TryDetect(0, telemetries, 0, telemetries.Length - 1, null, out var result); + + //assert + Assert.True(isDetectOperation); + Assert.NotNull(result); + Assert.Equal(WellOperationCategory.IdConditioning, result.Operation.IdCategory); + Assert.Equal(IdReasonOfEnd_NotDetected, result.Operation.ExtraData["IdReasonOfEnd"]); + } + + [Fact] + public void DetectOperation_with_BitDepth_LE_150_is_fail() + { + //arrange + var point0 = telemetry.Copy(); + point0.BitDepth = 150; + + var point1 = telemetry.Copy(); + + var telemetries = new[] { point0, point1 }; + + //act + + var isDetectOperation = detector.TryDetect(0, telemetries, 0, telemetries.Length - 1, null, out var result); + + //assert + Assert.False(isDetectOperation); + Assert.NotNull(result); + Assert.Equal(WellOperationCategory.IdConditioning, result.Operation.IdCategory); + Assert.Equal(IdReasonOfEnd_NotDetected, result.Operation.ExtraData["IdReasonOfEnd"]); + } + + + + [Fact] + public void DetectOperations_Begin_And_End_by_Pressure_Less_10_is_success() + { + //arrange + var point0 = telemetry.Copy(); + var point1 = telemetry.Copy(); + point1.Pressure = 9; + + var telemetries = new[] { point0, point1 }; + + //act + var isDetectOperation = detector.TryDetect(0, telemetries, 0, telemetries.Length - 1, null, out var result); + + //assert + Assert.False(isDetectOperation); + Assert.NotNull(result); + Assert.Equal(WellOperationCategory.IdConditioning, result.Operation.IdCategory); + Assert.Equal(IdReasonOfEnd_PressureIsLo, result.Operation.ExtraData["IdReasonOfEnd"]); + } +} \ No newline at end of file diff --git a/AsbCloudWebApi.Tests/Services/FileServiceTest.cs b/AsbCloudWebApi.Tests/Services/FileServiceTest.cs index 311e483f..b1200160 100644 --- a/AsbCloudWebApi.Tests/Services/FileServiceTest.cs +++ b/AsbCloudWebApi.Tests/Services/FileServiceTest.cs @@ -39,7 +39,7 @@ public class FileServiceTest IdCategory = idCategory, Name = fileName, Size = 0, - UploadDate = DateTime.Now + UploadDate = DateTimeOffset.Now }; private static FileMarkDto fileMark = new() diff --git a/AsbCloudWebApi.Tests/Services/Notification/EmailNotificationTransportServiceTests.cs b/AsbCloudWebApi.Tests/Services/Notification/EmailNotificationTransportServiceTests.cs index 724f1e7b..5b6bcb1d 100644 --- a/AsbCloudWebApi.Tests/Services/Notification/EmailNotificationTransportServiceTests.cs +++ b/AsbCloudWebApi.Tests/Services/Notification/EmailNotificationTransportServiceTests.cs @@ -26,7 +26,7 @@ namespace AsbCloudWebApi.Tests.Services.Notification IdUser = 1, IdTransportType = 1, IdState = 0, - RegistrationDate = DateTime.Now, + RegistrationDate = DateTimeOffset.Now, IdNotificationCategory = 10000, }; private readonly UserExtendedDto user = new UserExtendedDto() diff --git a/AsbCloudWebApi.Tests/Services/ProcessMaps/ProcessMapReportDataSaubStatServiceTest.cs b/AsbCloudWebApi.Tests/Services/ProcessMaps/ProcessMapReportDataSaubStatServiceTest.cs index 68751e00..a5cba844 100644 --- a/AsbCloudWebApi.Tests/Services/ProcessMaps/ProcessMapReportDataSaubStatServiceTest.cs +++ b/AsbCloudWebApi.Tests/Services/ProcessMaps/ProcessMapReportDataSaubStatServiceTest.cs @@ -5,6 +5,7 @@ using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data; using AsbCloudApp.Data.ProcessMaps; +using AsbCloudApp.Data.WellOperation; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; diff --git a/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryExportTest.cs b/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryExportTest.cs index 34d2077c..bffab69f 100644 --- a/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryExportTest.cs +++ b/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryExportTest.cs @@ -34,7 +34,7 @@ namespace AsbCloudWebApi.Tests.Services.Trajectory IdUser = 1, IdWell = 4, Radius = 3, - UpdateDate = DateTime.Now, + UpdateDate = DateTimeOffset.Now, VerticalDepth = 100, WellboreDepth = 100, ZenithAngle = 10 @@ -47,7 +47,7 @@ namespace AsbCloudWebApi.Tests.Services.Trajectory IdUser = 1, IdWell = 4, Radius = 3, - UpdateDate = DateTime.Now, + UpdateDate = DateTimeOffset.Now, VerticalDepth = 100, WellboreDepth = 100, ZenithAngle = 10 @@ -62,7 +62,7 @@ namespace AsbCloudWebApi.Tests.Services.Trajectory Comment = "комментарий", IdUser = 1, IdWell = 4, - UpdateDate = DateTime.Now, + UpdateDate = DateTimeOffset.Now, VerticalDepth = 100, WellboreDepth = 100, ZenithAngle = 10 @@ -74,7 +74,7 @@ namespace AsbCloudWebApi.Tests.Services.Trajectory Comment = "комментарий", IdUser = 1, IdWell = 4, - UpdateDate = DateTime.Now, + UpdateDate = DateTimeOffset.Now, VerticalDepth = 100, WellboreDepth = 100, ZenithAngle = 10 diff --git a/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs b/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs index d4659d8a..4018417c 100644 --- a/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs +++ b/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs @@ -15,6 +15,7 @@ using System.Threading.Tasks; using Xunit; using AsbCloudApp.Repositories; using AsbCloudApp.Data; +using AsbCloudApp.Data.WellOperation; using AsbCloudApp.Services; namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation @@ -50,9 +51,9 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation new() {Id = 31, Caption = "Техническая колонна", Order = 2} }; - private readonly static IEnumerable<WellOperationDataDto> wellOperations1 = new List<WellOperationDataDto>() + private readonly static IEnumerable<WellOperationDto> wellOperations1 = new List<WellOperationDto>() { - new WellOperationDataDto() + new() { DepthStart = 50, DurationHours = 1, @@ -62,7 +63,7 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation OperationCategoryName = "Шаблонирование перед спуском", WellSectionTypeCaption = "Направление" }, - new WellOperationDataDto() + new() { DepthStart = 84, DurationHours = 1, @@ -74,9 +75,9 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation } }; - private readonly static IEnumerable<WellOperationDataDto> wellOperations2 = new List<WellOperationDataDto>() + private readonly static IEnumerable<WellOperationDto> wellOperations2 = new List<WellOperationDto>() { - new WellOperationDataDto() + new() { DepthStart = 10, DurationHours = 1.5, @@ -86,7 +87,7 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation OperationCategoryName = "Бурение ротором", WellSectionTypeCaption = "Направление" }, - new WellOperationDataDto() + new() { DepthStart = 20, DurationHours = 3.5, @@ -98,9 +99,9 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation } }; - private readonly static IEnumerable<WellOperationDataDto> wellOperations3 = new List<WellOperationDataDto>() + private readonly static IEnumerable<WellOperationDto> wellOperations3 = new List<WellOperationDto>() { - new WellOperationDataDto() + new() { DepthStart = 1372, DurationHours = 3, @@ -110,7 +111,7 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation OperationCategoryName = "Промывка", WellSectionTypeCaption = "Кондуктор" }, - new WellOperationDataDto() + new() { DepthStart = 1435, DurationHours = 4, @@ -122,9 +123,9 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation } }; - private readonly static IEnumerable<WellOperationDataDto> wellOperations4 = new List<WellOperationDataDto>() + private readonly static IEnumerable<WellOperationDto> wellOperations4 = new List<WellOperationDto>() { - new WellOperationDataDto() + new() { DepthStart = 1000, DurationHours = 10, @@ -134,7 +135,7 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation OperationCategoryName = "Подъем инструмента", WellSectionTypeCaption = "Техническая колонна" }, - new WellOperationDataDto() + new() { DepthStart = 500, DurationHours = 5, @@ -144,7 +145,7 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation OperationCategoryName = "Проработка принудительная", WellSectionTypeCaption = "Техническая колонна" }, - new WellOperationDataDto() + new() { DepthStart = 600, DurationHours = 5, @@ -181,7 +182,7 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation public async Task GetAsync_return_composite_and_others_with_category_5013() { // arrange - wellOperationRepository.GetAsync(Arg.Any<WellsOperationRequest>(), Arg.Any<CancellationToken>()) + wellOperationRepository.GetAsync(Arg.Any<WellOperationRequest>(), Arg.Any<CancellationToken>()) .Returns(wellOperations1); var idsWell = new List<int>() { 55, 64 }; @@ -216,7 +217,7 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation public async Task GetAsync_return_composite_with_minimum_depth_start() { // arrange - wellOperationRepository.GetAsync(Arg.Any<WellsOperationRequest>(), Arg.Any<CancellationToken>()) + wellOperationRepository.GetAsync(Arg.Any<WellOperationRequest>(), Arg.Any<CancellationToken>()) .Returns(wellOperations2); var idsWell = new List<int>() { 55, 64 }; @@ -242,7 +243,7 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation public async Task GetAsync_return_data3() { // arrange - wellOperationRepository.GetAsync(Arg.Any<WellsOperationRequest>(), Arg.Any<CancellationToken>()) + wellOperationRepository.GetAsync(Arg.Any<WellOperationRequest>(), Arg.Any<CancellationToken>()) .Returns(wellOperations3); var idsWell = new List<int>() { 55, 64 }; @@ -272,7 +273,7 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation public async Task GetAsync_return_data4() { // arrange - wellOperationRepository.GetAsync(Arg.Any<WellsOperationRequest>(), Arg.Any<CancellationToken>()) + wellOperationRepository.GetAsync(Arg.Any<WellOperationRequest>(), Arg.Any<CancellationToken>()) .Returns(wellOperations4); var idsWell = new List<int>() { 55, 64 }; @@ -312,13 +313,13 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation public async Task GetAsync_return_data5() { // arrange - var wellOperations = new List<WellOperationDataDto>(); + var wellOperations = new List<WellOperationDto>(); wellOperations.AddRange(wellOperations1); wellOperations.AddRange(wellOperations2); wellOperations.AddRange(wellOperations3); wellOperations.AddRange(wellOperations4); - wellOperationRepository.GetAsync(Arg.Any<WellsOperationRequest>(), Arg.Any<CancellationToken>()) + wellOperationRepository.GetAsync(Arg.Any<WellOperationRequest>(), Arg.Any<CancellationToken>()) .Returns(wellOperations); var idsWell = new List<int>() { 55, 64 }; diff --git a/AsbCloudWebApi.Tests/Services/WellOperationExport/WellOperationExportServiceTest.cs b/AsbCloudWebApi.Tests/Services/WellOperationExport/WellOperationExportServiceTest.cs deleted file mode 100644 index ad3d3895..00000000 --- a/AsbCloudWebApi.Tests/Services/WellOperationExport/WellOperationExportServiceTest.cs +++ /dev/null @@ -1,216 +0,0 @@ -using AsbCloudApp.Data; -using AsbCloudApp.Data.WellOperationImport.Options; -using AsbCloudApp.Repositories; -using AsbCloudApp.Requests; -using AsbCloudApp.Services; -using AsbCloudApp.Services.WellOperationImport; -using AsbCloudDb.Model; -using AsbCloudInfrastructure.Services.WellOperationImport; -using AsbCloudInfrastructure.Services.WellOperationImport.FileParser; -using NSubstitute; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; -using Xunit; -using Xunit.Abstractions; - -namespace AsbCloudWebApi.Tests.Services.WellOperationExport -{ - public class WellOperationExportServiceTest - { - private const int idWell = 4; - - private IWellService wellService; - private IWellOperationRepository wellOperationRepository; - private IWellOperationCategoryRepository wellOperationCategoryRepository; - private IWellOperationImportTemplateService wellOperationImportTemplateService; - private WellOperationExportService wellOperationExportService; - private WellOperationImportService wellOperationImportService; - private IWellOperationExcelParser<WellOperationImportDefaultOptionsDto> wellOperationDefaultExcelParser; - - private readonly WellSectionTypeDto[] sectionTypes = new WellSectionTypeDto[2] - { - new WellSectionTypeDto() - { - Caption = "1", - Id = 1, - Order = 0 - }, - new WellSectionTypeDto() - { - Caption = "2", - Id = 2, - Order = 1 - } - }; - - private readonly WellOperationCategoryDto[] categories = new WellOperationCategoryDto[2] - { - new WellOperationCategoryDto() - { - Id = 1, - IdParent = 1, - KeyValueName = "1", - KeyValueUnits = "1", - Name = "1" - }, - new WellOperationCategoryDto() - { - Id = 2, - IdParent = 2, - KeyValueName = "2", - KeyValueUnits = "2", - Name = "2" - } - }; - private readonly ITestOutputHelper output; - - public WellOperationExportServiceTest(ITestOutputHelper output) - { - wellService = Substitute.For<IWellService>(); - wellOperationRepository = Substitute.For<IWellOperationRepository>(); - wellOperationCategoryRepository = Substitute.For<IWellOperationCategoryRepository>(); - wellOperationImportTemplateService = new WellOperationImportTemplateService(); - wellOperationExportService = new WellOperationExportService(wellOperationRepository, wellOperationImportTemplateService, wellOperationCategoryRepository); - - wellOperationImportService = new WellOperationImportService(wellService, wellOperationRepository, wellOperationCategoryRepository); - wellOperationDefaultExcelParser = new WellOperationDefaultExcelParser(); - this.output = output; - - wellService.GetTimezone(idWell).Returns(new SimpleTimezoneDto() - { - Hours = 5 - }); - } - - [Fact] - public async Task Check_Exported_WellOperations_With_Operations_In_Db() - { - var operations = getOperations(); - - var localOperations = operations.ToArray(); - - foreach (var operation in localOperations) - operation.Id = 0; - - wellOperationRepository.GetAsync(Arg.Any<WellOperationRequest>(), Arg.Any<CancellationToken>()) - .ReturnsForAnyArgs(localOperations); - wellOperationRepository.GetSectionTypes().Returns(sectionTypes); - wellOperationCategoryRepository.Get(false).Returns(categories); - - var stream = await wellOperationExportService.ExportAsync(idWell, CancellationToken.None); - - var options = new WellOperationImportDefaultOptionsDto - { - IdType = WellOperation.IdOperationTypePlan - }; - var sheet = wellOperationDefaultExcelParser.Parse(stream, options); - var result = wellOperationImportService.Import(idWell, 1, options.IdType, sheet); - - var expected = JsonSerializer.Serialize(localOperations); - var actual = JsonSerializer.Serialize(result); - - Assert.Equal(expected, actual); - } - - [Fact] - public void TestDataContainsNotDefaultProps() - { - var initOk = true; - var operations = getOperations(); - for (int i = 0; i < operations.Length; i++) - { - var operation = operations[i]; - var propsWithDefault = GetPropsWithDefaultValue(operation, - nameof(WellOperationDto.Id), - nameof(WellOperationDto.IdType), - nameof(WellOperationDto.IdPlan), - nameof(WellOperationDto.IdParentCategory), - nameof(WellOperationDto.Day), - nameof(WellOperationDto.NptHours), - nameof(WellOperationDto.UserName), - nameof(WellOperationDto.LastUpdateDate) - ) - .ToArray(); - - if (propsWithDefault.Any()) - { - initOk = false; - foreach (var propertyName in propsWithDefault) - output.WriteLine($"{nameof(operations)}[{i}].{propertyName} is default"); - } - } - - Assert.True(initOk); - } - - private static IEnumerable<string> GetPropsWithDefaultValue<T>(T dto, params string[] excludeProps) - { - IEnumerable<PropertyInfo> props = typeof(T).GetProperties( - BindingFlags.Public - | BindingFlags.Instance); - - props = props - .Where(prop => prop.CanWrite) - .Where(prop => !excludeProps.Contains(prop.Name)); - - foreach (var prop in props) - { - var value = prop.GetValue(dto); - if (prop.PropertyType.IsDefaultValue(value)) - yield return prop.Name; - } - } - - private WellOperationDto[] getOperations() - { - - var timezone = wellService.GetTimezone(idWell); - - DateTimeOffset GetDate(int days) - { - var date = DateTimeOffset.UtcNow.AddDays(days); - return new DateTimeOffset(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, TimeSpan.FromHours(timezone.Hours)); - } - - return new WellOperationDto[2] { - new WellOperationDto() { - Id = 5, - IdWell = idWell, - IdUser = 1, - IdType = 0, - IdWellSectionType = 1, - WellSectionTypeName = "1", - IdCategory = 1, - CategoryName = "1", - CategoryInfo = "CategoryInfo 1", - DepthStart = 10, - DepthEnd = 20, - DateStart = GetDate(days: 0), - DurationHours = 10, - Comment = "Комментарий 1", - }, - new WellOperationDto() { - Id = 6, - IdWell = idWell, - IdUser = 1, - IdType = 0, - IdWellSectionType = 2, - WellSectionTypeName = "2", - IdCategory = 2, - CategoryName = "2", - CategoryInfo = "CategoryInfo 2", - DepthStart = 20, - DepthEnd = 30, - DateStart = GetDate(days: 1), - DurationHours = 20, - Comment = "Комментарий 2", - } - }; - } - } -} diff --git a/AsbCloudWebApi.Tests/Services/WellboreServiceTest.cs b/AsbCloudWebApi.Tests/Services/WellboreServiceTest.cs index 7f647158..f256c384 100644 --- a/AsbCloudWebApi.Tests/Services/WellboreServiceTest.cs +++ b/AsbCloudWebApi.Tests/Services/WellboreServiceTest.cs @@ -21,7 +21,7 @@ public class WellboreServiceTest Id = 1, IdState = 1, IdTelemetry = 1, - LastTelemetryDate = DateTime.Now, + LastTelemetryDate = DateTimeOffset.Now, Caption = "well 1" }; @@ -30,7 +30,7 @@ public class WellboreServiceTest Id = 2, IdState = 1, IdTelemetry = 100, - LastTelemetryDate = DateTime.Now, + LastTelemetryDate = DateTimeOffset.Now, Caption = "well 2" }; diff --git a/AsbCloudWebApi/Controllers/DailyReportController.cs b/AsbCloudWebApi/Controllers/DailyReportController.cs index e36868f1..682dc74d 100644 --- a/AsbCloudWebApi/Controllers/DailyReportController.cs +++ b/AsbCloudWebApi/Controllers/DailyReportController.cs @@ -13,6 +13,7 @@ using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudApp.Services.DailyReport; +using AsbCloudDb.Model; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -156,7 +157,7 @@ public class DailyReportController : ControllerBase { await AssertUserAccessToWell(idWell, cancellationToken); - var datesRanges = await dailyReportService.GetDatesRangeAsync(idWell, cancellationToken); + var datesRanges = await wellOperationRepository.GetDatesRangeAsync(idWell, WellOperation.IdOperationTypeFact, cancellationToken); return Ok(datesRanges); } diff --git a/AsbCloudWebApi/Controllers/OperationStatController.cs b/AsbCloudWebApi/Controllers/OperationStatController.cs index d4346255..7126c5f5 100644 --- a/AsbCloudWebApi/Controllers/OperationStatController.cs +++ b/AsbCloudWebApi/Controllers/OperationStatController.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Data.WellOperation; namespace AsbCloudWebApi.Controllers { diff --git a/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanBaseController.cs b/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanBaseController.cs index a7d1763e..f4df65cc 100644 --- a/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanBaseController.cs +++ b/AsbCloudWebApi/Controllers/ProcessMaps/ProcessMapPlanBaseController.cs @@ -16,6 +16,8 @@ using AsbCloudApp.Requests.ParserOptions; using AsbCloudApp.Data.ProcessMaps; using System.ComponentModel.DataAnnotations; using AsbCloudApp.Requests.ExportOptions; +using AsbCloudApp.Services.Export; +using AsbCloudApp.Services.Parsers; namespace AsbCloudWebApi.Controllers.ProcessMaps; diff --git a/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs b/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs index c6bd6dda..9b478a2d 100644 --- a/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs @@ -1,5 +1,4 @@ -using AsbCloudApp.Data; -using AsbCloudApp.Data.DetectedOperation; +using AsbCloudApp.Data.DetectedOperation; using AsbCloudApp.Requests; using AsbCloudApp.Services; using Microsoft.AspNetCore.Authorization; @@ -7,6 +6,7 @@ using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Data.WellOperation; using AsbCloudInfrastructure.Services.DetectOperations; using Microsoft.AspNetCore.Http; diff --git a/AsbCloudWebApi/Controllers/ScheduleController.cs b/AsbCloudWebApi/Controllers/ScheduleController.cs index a8c73d30..cc56a296 100644 --- a/AsbCloudWebApi/Controllers/ScheduleController.cs +++ b/AsbCloudWebApi/Controllers/ScheduleController.cs @@ -33,7 +33,7 @@ namespace AsbCloudWebApi.Controllers /// <param name="token"></param> /// <returns>бурильщик</returns> [HttpGet("driller")] - public async Task<ActionResult<DrillerDto?>> GetDrillerAsync(int idWell, DateTime workTime, CancellationToken token) + public async Task<ActionResult<DrillerDto?>> GetDrillerAsync(int idWell, DateTimeOffset workTime, CancellationToken token) { if (!await UserHasAccesToWellAsync(idWell, token)) return Forbid(); diff --git a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs index 56a08c1e..2a734d21 100644 --- a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs +++ b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs @@ -10,6 +10,7 @@ using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data; using AsbCloudApp.Requests.ParserOptions; +using AsbCloudApp.Services.Parsers; using AsbCloudInfrastructure.Services.Trajectory.Export; namespace AsbCloudWebApi.Controllers.Trajectory diff --git a/AsbCloudWebApi/Controllers/WellCompositeOperationController.cs b/AsbCloudWebApi/Controllers/WellCompositeOperationController.cs index d662e4e8..ab4555c0 100644 --- a/AsbCloudWebApi/Controllers/WellCompositeOperationController.cs +++ b/AsbCloudWebApi/Controllers/WellCompositeOperationController.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Data.WellOperation; namespace AsbCloudWebApi.Controllers { @@ -24,7 +25,7 @@ namespace AsbCloudWebApi.Controllers } [HttpGet] - [ProducesResponseType(typeof(IList<IDictionary<int, WellOperationDataDto>>), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType(typeof(IList<IDictionary<int, WellOperationDto>>), (int)System.Net.HttpStatusCode.OK)] public async Task<IActionResult> GetAsync([FromQuery] IEnumerable<int> idsWells, CancellationToken token) { foreach (var idWell in idsWells) diff --git a/AsbCloudWebApi/Controllers/WellOperationController.cs b/AsbCloudWebApi/Controllers/WellOperationController.cs index d624e89a..96d5f5f9 100644 --- a/AsbCloudWebApi/Controllers/WellOperationController.cs +++ b/AsbCloudWebApi/Controllers/WellOperationController.cs @@ -1,13 +1,7 @@ using AsbCloudApp.Data; -using AsbCloudApp.Data.WellOperationImport; -using AsbCloudApp.Data.WellOperationImport.Options; -using AsbCloudApp.Exceptions; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; -using AsbCloudApp.Services.WellOperationImport; -using AsbCloudDb.Model; -using AsbCloudInfrastructure; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -15,598 +9,341 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.IO; -using System.Linq; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Data.WellOperation; +using AsbCloudApp.Requests.ExportOptions; +using AsbCloudApp.Requests.ParserOptions; +using AsbCloudDb.Model; +using AsbCloudInfrastructure.Services.WellOperations.Factories; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// <summary> +/// Буровые операции (вводимые вручную) +/// </summary> +[Route("api/well/{idWell}/wellOperations")] +[ApiController] +[Authorize] +public class WellOperationController : ControllerBase { - - /// <summary> - /// Буровые операции (вводимые вручную) - /// </summary> - [Route("api/well/{idWell}/wellOperations")] - [ApiController] - [Authorize] - public class WellOperationController : ControllerBase - { - private readonly IWellOperationRepository operationRepository; - private readonly IWellService wellService; - private readonly IWellOperationExportService wellOperationExportService; - private readonly IWellOperationImportTemplateService wellOperationImportTemplateService; - private readonly IWellOperationImportService wellOperationImportService; - private readonly IWellOperationCategoryRepository wellOperationCategoryRepository; - private readonly IWellOperationExcelParser<WellOperationImportDefaultOptionsDto> wellOperationDefaultExcelParser; - private readonly IWellOperationExcelParser<WellOperationImportGazpromKhantosOptionsDto> wellOperationGazpromKhantosExcelParser; - private readonly IUserRepository userRepository; - - public WellOperationController(IWellOperationRepository operationRepository, - IWellService wellService, - IWellOperationImportTemplateService wellOperationImportTemplateService, - IWellOperationExportService wellOperationExportService, - IWellOperationImportService wellOperationImportService, - IWellOperationCategoryRepository wellOperationCategoryRepository, - IWellOperationExcelParser<WellOperationImportDefaultOptionsDto> wellOperationDefaultExcelParser, - IWellOperationExcelParser<WellOperationImportGazpromKhantosOptionsDto> wellOperationGazpromKhantosExcelParser, - IUserRepository userRepository) - { - this.operationRepository = operationRepository; - this.wellService = wellService; - this.wellOperationImportTemplateService = wellOperationImportTemplateService; - this.wellOperationExportService = wellOperationExportService; - this.wellOperationImportService = wellOperationImportService; - this.wellOperationCategoryRepository = wellOperationCategoryRepository; - this.wellOperationDefaultExcelParser = wellOperationDefaultExcelParser; - this.wellOperationGazpromKhantosExcelParser = wellOperationGazpromKhantosExcelParser; - this.userRepository = userRepository; - } - - /// <summary> - /// Возвращает словарь типов секций - /// </summary> - /// <returns></returns> - [HttpGet("sectionTypes")] - [Permission] - [ProducesResponseType(typeof(IEnumerable<WellSectionTypeDto>), (int)System.Net.HttpStatusCode.OK)] - public IActionResult GetSectionTypes() - { - var result = operationRepository.GetSectionTypes(); - return Ok(result); - } - - /// <summary> - /// Возвращает список имен типов операций на скважине - /// </summary> - /// <param name="includeParents">флаг, нужно ли включать родителей в список</param> - /// <returns></returns> - [HttpGet("categories")] - [Permission] - [ProducesResponseType(typeof(IEnumerable<WellOperationCategoryDto>), (int)System.Net.HttpStatusCode.OK)] - public IActionResult GetCategories(bool includeParents = true) - { - var result = wellOperationCategoryRepository.Get(includeParents); - return Ok(result); - } - - /// <summary> - /// Возвращает список плановых операций для сопоставления - /// </summary> - /// <param name="idWell">id скважины</param> - /// <param name="currentDate">дата для нахождения последней сопоставленной плановой операции</param> - /// <param name="token"></param> - /// <returns></returns> - [HttpGet("operationsPlan")] - [ProducesResponseType(typeof(WellOperationPlanDto), (int)System.Net.HttpStatusCode.OK)] - public async Task<IActionResult> GetOperationsPlanAsync( - [FromRoute] int idWell, - [FromQuery] DateTime currentDate, - CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var result = await operationRepository - .GetOperationsPlanAsync(idWell, currentDate, token) - .ConfigureAwait(false); - return Ok(result); - } - - /// <summary> - /// Отфильтрованный список фактических операций на скважине. - /// Если не применять фильтр, то вернется весь список. Сортированный по глубине затем по дате - /// </summary> - /// <param name="idWell">id скважины</param> - /// <param name="request"></param> - /// <param name="token"></param> - /// <returns>Список операций на скважине</returns> - [HttpGet("fact")] - [Permission] - [ProducesResponseType(typeof(IEnumerable<WellOperationDto>), (int)System.Net.HttpStatusCode.OK)] - public async Task<IActionResult> GetPageOperationsFactAsync( - [FromRoute] int idWell, - [FromQuery] WellOperationRequestBase request, - CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var requestToService = new WellOperationRequest(request, idWell); - var result = await operationRepository.GetAsync( - requestToService, - token) - .ConfigureAwait(false); - return Ok(result); - } - - /// <summary> - /// Отфильтрованный список плановых операций на скважине. - /// Если не применять фильтр, то вернется весь список. Сортированный по глубине затем по дате - /// </summary> - /// <param name="idWell">id скважины</param> - /// <param name="request"></param> - /// <param name="token"></param> - /// <returns>Список операций на скважине в контейнере для постраничного просмотра</returns> - [HttpGet("plan")] - [Permission] - [ProducesResponseType(typeof(PaginationContainer<WellOperationDto>), (int)System.Net.HttpStatusCode.OK)] - public async Task<IActionResult> GetPageOperationsPlanAsync( - [FromRoute] int idWell, - [FromQuery] WellOperationRequestBase request, - CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var requestToService = new WellOperationRequest(request, idWell); - var result = await operationRepository.GetPageAsync( - requestToService, - token) - .ConfigureAwait(false); - return Ok(result); - } - - /// <summary> - /// Статистика операций по скважине, группированная по категориям - /// </summary> - /// <param name="idWell">id скважины</param> - /// <param name="request"></param> - /// <param name="token"></param> - /// <returns></returns> - [HttpGet("groupStat")] - [Permission] - [ProducesResponseType(typeof(IEnumerable<WellGroupOpertionDto>), (int)System.Net.HttpStatusCode.OK)] - public async Task<IActionResult> GetGroupOperationsAsync( - [FromRoute] int idWell, - [FromQuery] WellOperationRequestBase request, - CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var requestToService = new WellOperationRequest(request, idWell); - var result = await operationRepository.GetGroupOperationsStatAsync( - requestToService, - token) - .ConfigureAwait(false); - return Ok(result); - } - - /// <summary> - /// Возвращает нужную операцию на скважине - /// </summary> - /// <param name="idWell">id скважины</param> - /// <param name="idOperation">id нужной операции</param> - /// <param name="token">Токен отмены задачи</param> - /// <returns>Нужную операцию на скважине</returns> - [HttpGet("{idOperation}")] - [Permission] - [ProducesResponseType(typeof(WellOperationDto), (int)System.Net.HttpStatusCode.OK)] - public async Task<IActionResult> GetOrDefaultAsync(int idWell, int idOperation, - CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var result = await operationRepository.GetOrDefaultAsync(idOperation, token).ConfigureAwait(false); - return Ok(result); - } - - /// <summary> - /// Добавляет новую операцию на скважину - /// </summary> - /// <param name="idWell">Id скважины</param> - /// <param name="idType">Тип добавляемой операции</param> - /// <param name="wellOperation">Добавляемая операция</param> - /// <param name="cancellationToken"></param> - /// <returns>Количество добавленных в БД записей</returns> - [HttpPost("{idType:int}")] - [Permission] - [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] - public async Task<IActionResult> InsertAsync( - [Range(1, int.MaxValue, ErrorMessage = "Id скважины не может быть меньше 1")] int idWell, - [Range(0, 1, ErrorMessage = "Тип операции недопустим. Допустимые: 0, 1")] int idType, - WellOperationDto wellOperation, - CancellationToken cancellationToken) - { - if (!await CanUserAccessToWellAsync(idWell, cancellationToken)) - return Forbid(); - - if (!await CanUserEditWellOperationsAsync(idWell, cancellationToken)) - return Forbid(); - - wellOperation.IdWell = idWell; - wellOperation.IdUser = User.GetUserId(); - wellOperation.IdType = idType; - - var result = await operationRepository.InsertRangeAsync(new[] { wellOperation }, cancellationToken); - - return Ok(result); - } - - /// <summary> - /// Добавляет новые операции на скважине - /// </summary> - /// <param name="idWell">Id скважины</param> - /// <param name="wellOperations">Добавляемые операции</param> - /// <param name="idType">Тип добавляемых операций</param> - /// <param name="deleteBeforeInsert">Удалить операции перед сохранением</param> - /// <param name="cancellationToken"></param> - /// <returns>Количество добавленных в БД записей</returns> - [HttpPost("{idType:int}/{deleteBeforeInsert:bool}")] - [Permission] - [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] - public async Task<IActionResult> InsertRangeAsync( - [Range(1, int.MaxValue, ErrorMessage = "Id скважины не может быть меньше 1")] int idWell, - [Range(0, 1, ErrorMessage = "Тип операции недопустим. Допустимые: 0, 1")] int idType, - bool deleteBeforeInsert, - [FromBody] IEnumerable<WellOperationDto> wellOperations, - CancellationToken cancellationToken) - { - if (!await CanUserAccessToWellAsync(idWell, cancellationToken)) - return Forbid(); - - if (!await CanUserEditWellOperationsAsync(idWell, cancellationToken)) - return Forbid(); - - if (deleteBeforeInsert) - { - var existingOperations = await operationRepository.GetAsync(new WellOperationRequest - { - IdWell = idWell, - OperationType = idType - }, cancellationToken); - - await operationRepository.DeleteAsync(existingOperations.Select(o => o.Id), cancellationToken); - } - - foreach (var wellOperation in wellOperations) - { - wellOperation.IdWell = idWell; - wellOperation.IdUser = User.GetUserId(); - wellOperation.IdType = idType; - } - - var result = await operationRepository.InsertRangeAsync(wellOperations, cancellationToken); - - return Ok(result); - } - - /// <summary> - /// Обновляет выбранную операцию на скважине - /// </summary> - /// <param name="idWell">id скважины</param> - /// <param name="idOperation">id выбранной операции</param> - /// <param name="value">Новые данные для выбранной операции</param> - /// <param name="token">Токен отмены задачи</param> - /// <returns>Количество обновленных в БД строк</returns> - [HttpPut("{idOperation}")] - [Permission] - [ProducesResponseType(typeof(WellOperationDto), (int)System.Net.HttpStatusCode.OK)] - public async Task<IActionResult> UpdateAsync(int idWell, int idOperation, - [FromBody] WellOperationDto value, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token)) - return Forbid(); - - if (!await CanUserEditWellOperationsAsync(idWell, token)) - return Forbid(); - - value.IdWell = idWell; - value.Id = idOperation; - value.IdUser = User.GetUserId(); - - var result = await operationRepository.UpdateAsync(value, token) - .ConfigureAwait(false); - return Ok(result); - } - - /// <summary> - /// Удаляет выбранную операцию на скважине - /// </summary> - /// <param name="idWell">id скважины</param> - /// <param name="idOperation">id выбранной операции</param> - /// <param name="token">Токен отмены задачи</param> - /// <returns>Количество удаленных из БД строк</returns> - [HttpDelete("{idOperation}")] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task<IActionResult> DeleteAsync(int idWell, int idOperation, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token)) - return Forbid(); - - if (!await CanUserEditWellOperationsAsync(idWell, token)) - return Forbid(); - - var result = await operationRepository.DeleteAsync(new int[] { idOperation }, token) - .ConfigureAwait(false); - - return Ok(result); - } - - /// <summary> - /// Импорт фактических операций из excel (xlsx) файла. Стандартный заполненный шаблон - /// </summary> - /// <param name="idWell">id скважины</param> - /// <param name="files">Коллекция из одного файла xlsx</param> - /// <param name="deleteBeforeInsert">Удалить операции перед сохранением</param> - /// <param name="cancellationToken"></param> - /// <returns></returns> - [HttpPost("import/fact/default/{deleteBeforeInsert:bool}")] - [ProducesResponseType(typeof(IEnumerable<WellOperationDto>), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] - [Permission] - public Task<IActionResult> ImportFactDefaultExcelFileAsync(int idWell, - [FromForm] IFormFileCollection files, - bool deleteBeforeInsert, - CancellationToken cancellationToken) - { - var options = new WellOperationImportDefaultOptionsDto - { - IdType = WellOperation.IdOperationTypeFact - }; - - return ImportExcelFileAsync(idWell, files, options, - (stream, _) => wellOperationDefaultExcelParser.Parse(stream, options), - deleteBeforeInsert, - cancellationToken); - } - - /// <summary> - /// Импорт плановых операций из excel (xlsx) файла. Стандартный заполненный шаблон - /// </summary> - /// <param name="idWell">id скважины</param> - /// <param name="files">Коллекция из одного файла xlsx</param> - /// <param name="cancellationToken"></param> - /// <returns></returns> - [HttpPost("import/plan/default")] - [ProducesResponseType(typeof(IEnumerable<WellOperationDto>), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] - [Permission] - public Task<IActionResult> ImportPlanDefaultExcelFileAsync(int idWell, - [FromForm] IFormFileCollection files, - CancellationToken cancellationToken) - { - var options = new WellOperationImportDefaultOptionsDto - { - IdType = WellOperation.IdOperationTypePlan - }; - - return ImportExcelFileAsync(idWell, files, options, - (stream, _) => wellOperationDefaultExcelParser.Parse(stream, options), - null, - cancellationToken); - } - - /// <summary> - /// Импорт операций из excel (xlsx) файла. ГПНХ (Хантос) - /// </summary> - /// <param name="idWell">Id скважины</param> - /// <param name="options">Параметры парсинга</param> - /// <param name="files">Коллекция из одного файла xlsx</param> - /// <param name="cancellationToken"></param> - /// <returns></returns> - [HttpPost("import/plan/gazpromKhantos")] - [ProducesResponseType(typeof(IEnumerable<WellOperationDto>), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] - [Permission] - public Task<IActionResult> ImportPlanGazpromKhantosExcelFileAsync(int idWell, - [FromQuery] WellOperationImportGazpromKhantosOptionsDto options, - [FromForm] IFormFileCollection files, - CancellationToken cancellationToken) - { - options.IdType = WellOperation.IdOperationTypePlan; - - return ImportExcelFileAsync(idWell, files, options, - (stream, _) => wellOperationGazpromKhantosExcelParser.Parse(stream, options), - null, - cancellationToken); - } - - /// <summary> - /// Создает excel файл с операциями по скважине - /// </summary> - /// <param name="idWell">id скважины</param> - /// <param name="token">Токен отмены задачи </param> - /// <returns>Запрашиваемый файл</returns> - [HttpGet("export")] - [Permission] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] - [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task<IActionResult> ExportAsync([FromRoute] int idWell, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - - if (idCompany is null) - return Forbid(); - - if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) - return Forbid(); - - var stream = await wellOperationExportService.ExportAsync(idWell, token); - var fileName = await wellService.GetWellCaptionByIdAsync(idWell, token) + "_operations.xlsx"; - return File(stream, "application/octet-stream", fileName); - } - - /// <summary> - /// Создает excel файл с "сетевым графиком" - /// </summary> - /// <param name="idWell">id скважины</param> - /// <param name="scheduleReportService"></param> - /// <param name="token"> Токен отмены задачи</param> - /// <returns>Запрашиваемый файл</returns> - [HttpGet("scheduleReport")] - [Permission] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] - public async Task<IActionResult> ScheduleReportAsync([FromRoute] int idWell, [FromServices] IScheduleReportService scheduleReportService, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - - if (idCompany is null) - return Forbid(); - - if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) - return Forbid(); - - var stream = await scheduleReportService.MakeReportAsync(idWell, token); - var fileName = await wellService.GetWellCaptionByIdAsync(idWell, token) + "_ScheduleReport.xlsx"; - return File(stream, "application/octet-stream", fileName); - } - - /// <summary> - /// Удаляет полые дубликаты операций - /// </summary> - /// <param name="token"></param> - /// <returns></returns> - [HttpPost("/api/well/wellOperations/RemoveDuplicates")] - [Permission] - [Obsolete] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task<IActionResult> RemoveDuplicates(CancellationToken token) - { - var result = await operationRepository.RemoveDuplicates((_, _) => { }, token); - return Ok(result); - } - - /// <summary> - /// Удаляет полностью пересекающиеся операции или "подрезает" более поздние их по глубине и дате. - /// </summary> - /// <param name="geDate"></param> - /// <param name="leDate"></param> - /// <param name="token"></param> - /// <returns></returns> - [HttpPost("/api/well/wellOperations/TrimOverlapping")] - [Permission] - [Obsolete] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task<IActionResult> TrimOverlapping(DateTimeOffset? geDate, DateTimeOffset leDate, CancellationToken token) - { - var result = await operationRepository.TrimOverlapping(geDate, leDate, (_, _) => { }, token); - return Ok(result); - } - - /// <summary> - /// Возвращает шаблон файла импорта - /// </summary> - /// <returns>Запрашиваемый файл</returns> - [HttpGet("template")] - [AllowAnonymous] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] - public IActionResult GetTemplate() - { - var stream = wellOperationImportTemplateService.GetExcelTemplateStream(); - var fileName = "ЕЦП_шаблон_файла_операций.xlsx"; - return File(stream, "application/octet-stream", fileName); - } - - //TODO: deleteBeforeInsert тоже быстрый костыль - private async Task<IActionResult> ImportExcelFileAsync<TOptions>(int idWell, [FromForm] IFormFileCollection files, - TOptions options, - Func<Stream, TOptions, SheetDto> parseMethod, - bool? deleteBeforeInsert, - CancellationToken cancellationToken) - where TOptions : IWellOperationImportOptions - { - var idCompany = User.GetCompanyId(); - var idUser = User.GetUserId(); - - if (!idCompany.HasValue || !idUser.HasValue) - throw new ForbidException("Неизвестный пользователь"); - - if (!await CanUserAccessToWellAsync(idWell, cancellationToken)) - throw new ForbidException("Нет доступа к скважине"); - - if (!await CanUserEditWellOperationsAsync(idWell, cancellationToken)) - throw new ForbidException("Недостаточно прав для редактирования ГГД на завершенной скважине"); - - if (!await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, idWell, cancellationToken)) - throw new ForbidException("Скважина недоступна для компании"); - - if (files.Count < 1) - return this.ValidationBadRequest(nameof(files), "Нет файла"); - - var file = files[0]; - if (Path.GetExtension(file.FileName).ToLower() != ".xlsx") - return this.ValidationBadRequest(nameof(files), "Требуется xlsx файл."); - - using Stream stream = file.OpenReadStream(); - - try - { - var sheet = parseMethod(stream, options); - - var wellOperations = wellOperationImportService.Import(idWell, idUser.Value, options.IdType, sheet) - .OrderBy(w => w.DateStart); - - var dateStart = wellOperations.MinOrDefault(w => w.DateStart); - - foreach (var wellOperation in wellOperations) - { - if (dateStart.HasValue) - wellOperation.Day = (wellOperation.DateStart - dateStart.Value).TotalDays; - } - - //TODO: очень быстрый костыль - if (deleteBeforeInsert is not null && options.IdType == WellOperation.IdOperationTypeFact) - { - return await InsertRangeAsync(idWell, options.IdType, - deleteBeforeInsert.Value, - wellOperations, - cancellationToken); - } - - return Ok(wellOperations); - } - catch (FileFormatException ex) - { - return this.ValidationBadRequest(nameof(files), ex.Message); - } - } - - private async Task<bool> CanUserAccessToWellAsync(int idWell, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false); - } - - private async Task<bool> CanUserEditWellOperationsAsync(int idWell, CancellationToken token) - { - var idUser = User.GetUserId(); - - if (!idUser.HasValue) - return false; - - var well = await wellService.GetOrDefaultAsync(idWell, token); - - if (well is null) - return false; - - return well.IdState != 2 || userRepository.HasPermission(idUser.Value, "WellOperation.editCompletedWell"); - } - } + private readonly IDictionary<int, string> templateNames = new Dictionary<int, string> + { + { WellOperation.IdOperationTypeFact, "ЕЦП_шаблон_файла_фактические_операции.xlsx" }, + { WellOperation.IdOperationTypePlan, "ЕЦП_шаблон_файла_плановые_операции.xlsx" } + }; + + private readonly IUserRepository userRepository; + private readonly IWellOperationRepository wellOperationRepository; + private readonly IWellOperationCategoryRepository wellOperationCategoryRepository; + private readonly IWellService wellService; + + private readonly WellOperationParserFactory wellOperationParserFactory; + private readonly WellOperationExportServiceFactory wellOperationExportServiceFactory; + + public WellOperationController(IWellOperationRepository wellOperationRepository, + IWellOperationCategoryRepository wellOperationCategoryRepository, + IWellService wellService, + IUserRepository userRepository, + WellOperationParserFactory wellOperationParserFactory, + WellOperationExportServiceFactory wellOperationExportServiceFactory) + { + this.wellOperationRepository = wellOperationRepository; + this.wellOperationCategoryRepository = wellOperationCategoryRepository; + this.wellService = wellService; + this.userRepository = userRepository; + this.wellOperationParserFactory = wellOperationParserFactory; + this.wellOperationExportServiceFactory = wellOperationExportServiceFactory; + } + + /// <summary> + /// Добавляет новые операции на скважине + /// </summary> + /// <param name="idWell">Id скважины</param> + /// <param name="dtos">Добавляемые операции</param> + /// <param name="deleteBeforeInsert">Удалить операции перед сохранением</param> + /// <param name="cancellationToken"></param> + /// <returns>Количество добавленных в БД записей</returns> + [HttpPost("{deleteBeforeInsert:bool}")] + [Permission] + [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] + public async Task<IActionResult> InsertRangeAsync( + [Range(1, int.MaxValue, ErrorMessage = "Id скважины не может быть меньше 1")] + int idWell, + bool deleteBeforeInsert, + [FromBody] IEnumerable<WellOperationDto> dtos, + CancellationToken cancellationToken) + { + if (!await CanUserAccessToWellAsync(idWell, cancellationToken)) + return Forbid(); + + if (!await CanUserEditWellOperationsAsync(idWell, cancellationToken)) + return Forbid(); + + foreach (var dto in dtos) + { + dto.IdWell = idWell; + dto.LastUpdateDate = null; + dto.IdUser = User.GetUserId(); + } + + var result = await wellOperationRepository.InsertRangeAsync(dtos, deleteBeforeInsert, cancellationToken); + + return Ok(result); + } + + /// <summary> + /// Обновляет выбранную операцию на скважине + /// </summary> + /// <param name="idWell">id скважины</param> + /// <param name="dtos"></param> + /// <param name="token">Токен отмены задачи</param> + /// <returns>Количество обновленных в БД строк</returns> + [HttpPut] + [Permission] + [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] + public async Task<IActionResult> UpdateRangeAsync(int idWell, + [FromBody] IEnumerable<WellOperationDto> dtos, + CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token)) + return Forbid(); + + if (!await CanUserEditWellOperationsAsync(idWell, token)) + return Forbid(); + + foreach (var dto in dtos) + { + dto.IdWell = idWell; + dto.IdUser = User.GetUserId(); + dto.LastUpdateDate = DateTimeOffset.UtcNow; + } + + var result = await wellOperationRepository.UpdateRangeAsync(dtos, token); + + return Ok(result); + } + + /// <summary> + /// Возвращает словарь типов секций + /// </summary> + /// <returns></returns> + [HttpGet("sectionTypes")] + [Permission] + [ProducesResponseType(typeof(IEnumerable<WellSectionTypeDto>), StatusCodes.Status200OK)] + public IActionResult GetSectionTypes() + { + var result = wellOperationRepository.GetSectionTypes(); + return Ok(result); + } + + /// <summary> + /// Статистика операций по скважине, группированная по категориям + /// </summary> + /// <param name="idWell">id скважины</param> + /// <param name="request"></param> + /// <param name="token"></param> + /// <returns></returns> + [HttpGet("groupStat")] + [Permission] + [ProducesResponseType(typeof(IEnumerable<WellGroupOpertionDto>), (int)System.Net.HttpStatusCode.OK)] + public async Task<IActionResult> GetGroupOperationsAsync( + [FromRoute] int idWell, + [FromQuery] WellOperationRequestBase request, + CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); + + var requestToservice = new WellOperationRequest(request, new[] { idWell }); + + var result = await wellOperationRepository.GetGroupOperationsStatAsync(requestToservice, token); + return Ok(result); + } + + /// <summary> + /// Возвращает список имен типов операций на скважине + /// </summary> + /// <param name="includeParents">флаг, нужно ли включать родителей в список</param> + /// <returns></returns> + [HttpGet("categories")] + [Permission] + [ProducesResponseType(typeof(IEnumerable<WellOperationCategoryDto>), StatusCodes.Status200OK)] + public IActionResult GetCategories(bool includeParents = true) + { + var result = wellOperationCategoryRepository.Get(includeParents); + return Ok(result); + } + + /// <summary> + /// Постраничный список операций на скважине. + /// </summary> + /// <param name="idWell">id скважины</param> + /// <param name="request"></param> + /// <param name="token"></param> + /// <returns>Список операций на скважине</returns> + [HttpGet] + [Permission] + [ProducesResponseType(typeof(PaginationContainer<WellOperationDto>), StatusCodes.Status200OK)] + public async Task<IActionResult> GetPageOperationsAsync( + [FromRoute] int idWell, + [FromQuery] WellOperationRequestBase request, + CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token)) + return Forbid(); + + var requestToService = new WellOperationRequest(request, new[] { idWell }); + + var result = await wellOperationRepository.GetPageAsync(requestToService, token); + return Ok(result); + } + + /// <summary> + /// Создает excel файл с "сетевым графиком" + /// </summary> + /// <param name="idWell">id скважины</param> + /// <param name="scheduleReportService"></param> + /// <param name="token"></param> + /// <returns>Запрашиваемый файл</returns> + [HttpGet("scheduleReport")] + [Permission] + [ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK)] + public async Task<IActionResult> ScheduleReportAsync([FromRoute] int idWell, + [FromServices] IScheduleReportService scheduleReportService, + CancellationToken token) + { + var idCompany = User.GetCompanyId(); + + if (idCompany is null) + return Forbid(); + + if (!await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, idWell, token)) + return Forbid(); + + var stream = await scheduleReportService.MakeReportAsync(idWell, token); + var fileName = await wellService.GetWellCaptionByIdAsync(idWell, token) + "_ScheduleReport.xlsx"; + return File(stream, "application/octet-stream", fileName); + } + + /// <summary> + /// Удаляет выбранную операцию на скважине + /// </summary> + /// <param name="idWell">id скважины</param> + /// <param name="idOperation">id выбранной операции</param> + /// <param name="token">Токен отмены задачи</param> + /// <returns>Количество удаленных из БД строк</returns> + [HttpDelete("{idOperation}")] + [Permission] + [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] + public async Task<IActionResult> DeleteAsync(int idWell, int idOperation, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token)) + return Forbid(); + + if (!await CanUserEditWellOperationsAsync(idWell, token)) + return Forbid(); + + var result = await wellOperationRepository.DeleteRangeAsync(new[] { idOperation }, token); + + return Ok(result); + } + + /// <summary> + /// Формирование excel файла с операциями на скважине + /// </summary> + /// <param name="idWell"></param> + /// <param name="idType"></param> + /// <param name="token"></param> + /// <returns></returns> + [HttpGet("export")] + [ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK, "application/octet-stream")] + public async Task<IActionResult> ExportAsync(int idWell, + int idType, + CancellationToken token) + { + var options = new WellOperationExportRequest(idWell, idType); + var exportService = wellOperationExportServiceFactory.CreateExportService<WellOperationExportRequest>(idType); + + var (fileName, file) = await exportService.ExportAsync(options, token); + + return File(file, "application/octet-stream", fileName); + } + + /// <summary> + /// Парсинг ГГД из excel (xlsx) файла + /// </summary> + /// <param name="idWell"></param> + /// <param name="idType"></param> + /// <param name="file"></param> + /// <param name="token"></param> + /// <returns></returns> + [HttpPost("parse/{idType}")] + [Permission] + [ProducesResponseType(typeof(ParserResultDto<WellOperationDto>), StatusCodes.Status200OK)] + public async Task<IActionResult> ParseAsync(int idWell, + int idType, + [Required] IFormFile file, + CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token)) + return Forbid(); + + if (!await CanUserEditWellOperationsAsync(idWell, token)) + return Forbid(); + + var stream = file.GetExcelFile(); + + try + { + var timezone = wellService.GetTimezone(idWell); + var options = new WellOperationParserRequest(idWell, idType, timezone); + var parser = wellOperationParserFactory.CreateParser<WellOperationParserRequest>(idType); + var result = parser.Parse(stream, options); + + return Ok(result); + } + catch (FileFormatException ex) + { + return this.ValidationBadRequest(nameof(file), ex.Message); + } + } + + /// <summary> + /// Получение шаблона для заполнения ГГД + /// </summary> + /// <returns></returns> + [HttpGet("template")] + [AllowAnonymous] + [ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK, "application/octet-stream")] + public IActionResult GetTemplate(int idType) + { + var parser = wellOperationParserFactory.CreateParser<WellOperationParserRequest>(idType); + var stream = parser.GetTemplateFile(); + + return File(stream, "application/octet-stream", templateNames[idType]); + } + + private async Task<bool> CanUserAccessToWellAsync(int idWell, CancellationToken token) + { + var idCompany = User.GetCompanyId(); + return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false); + } + + private async Task<bool> CanUserEditWellOperationsAsync(int idWell, CancellationToken token) + { + var idUser = User.GetUserId(); + + if (!idUser.HasValue) + return false; + + var well = await wellService.GetOrDefaultAsync(idWell, token); + + if (well is null) + return false; + + return well.IdState != 2 || userRepository.HasPermission(idUser.Value, "WellOperation.editCompletedWell"); + } } \ No newline at end of file diff --git a/AsbCloudWebApi/Converters/DateOnlyTypeConverter.cs b/AsbCloudWebApi/Converters/DateOnlyTypeConverter.cs index 581a070d..71d8730d 100644 --- a/AsbCloudWebApi/Converters/DateOnlyTypeConverter.cs +++ b/AsbCloudWebApi/Converters/DateOnlyTypeConverter.cs @@ -22,7 +22,10 @@ namespace AsbCloudWebApi.Converters { if (value is string str) { - return DateOnly.Parse(str); + if (DateTimeOffset.TryParse(str, out DateTimeOffset dateTime)) + return DateOnly.FromDateTime(dateTime.Date); + if (DateTime.TryParse(str, out DateTime date)) + return DateOnly.FromDateTime(date); } return base.ConvertFrom(context, culture, value); } diff --git a/AsbCloudWebApi/SignalR/Services/NotificationPublisher.cs b/AsbCloudWebApi/SignalR/Services/NotificationPublisher.cs index 6799e71d..05c93a29 100644 --- a/AsbCloudWebApi/SignalR/Services/NotificationPublisher.cs +++ b/AsbCloudWebApi/SignalR/Services/NotificationPublisher.cs @@ -35,7 +35,7 @@ public class NotificationPublisher { foreach (var notification in groupedNotifications) { - notification.SentDate = DateTime.UtcNow; + notification.SentDate = DateTimeOffset.UtcNow; } var notifications = groupedNotifications.Select(n => n);