diff --git a/AsbCloudApp/Comparators/ComparerIId.cs b/AsbCloudApp/Comparators/ComparerIId.cs index b3fb0e15..76fd40de 100644 --- a/AsbCloudApp/Comparators/ComparerIId.cs +++ b/AsbCloudApp/Comparators/ComparerIId.cs @@ -2,53 +2,52 @@ using AsbCloudApp.Data; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -namespace AsbCloudApp.Comparators +namespace AsbCloudApp.Comparators; + +/// +/// Компаратор для сравнения сущностей по ID +/// +public class ComparerIId : IComparer, IEqualityComparer { + private static readonly ComparerIId instance = new(); + private ComparerIId() { } + /// - /// Компаратор для сравнения сущностей по ID + /// Singleton ссылка /// - public class ComparerIId : IComparer, IEqualityComparer - { - private static readonly ComparerIId instance = new(); - private ComparerIId() { } + /// + public static ComparerIId GetInstance() => instance; - /// - /// Singleton ссылка - /// - /// - public static ComparerIId GetInstance() => instance; + /// + /// + /// + /// + /// + /// + public int Compare(IId? x, IId? y) + => (x?.Id??0).CompareTo(y?.Id??0); + - /// - /// - /// - /// - /// - /// - public int Compare(IId? x, IId? y) - => (x?.Id??0).CompareTo(y?.Id??0); - - - /// - /// - /// - /// - /// - /// - public bool Equals(IId? x, IId? y) - { - if (x is not null && y is not null) - return x.Id == y.Id; - - return x == y; - } - - /// - /// - /// - /// - /// - public int GetHashCode([DisallowNull] IId obj) => - obj.GetHashCode(); + /// + /// + /// + /// + /// + /// + public bool Equals(IId? x, IId? y) + { + if (x is not null && y is not null) + return x.Id == y.Id; + return x == y; } + + /// + /// + /// + /// + /// + public int GetHashCode([DisallowNull] IId obj) => + obj.GetHashCode(); + } diff --git a/AsbCloudApp/Comparators/TelemetryUserDtoComparer.cs b/AsbCloudApp/Comparators/TelemetryUserDtoComparer.cs index d993cc3d..2ad87efb 100644 --- a/AsbCloudApp/Comparators/TelemetryUserDtoComparer.cs +++ b/AsbCloudApp/Comparators/TelemetryUserDtoComparer.cs @@ -1,21 +1,20 @@ using AsbCloudApp.Data.SAUB; using System.Collections.Generic; -namespace AsbCloudApp.Comparators +namespace AsbCloudApp.Comparators; + +/// +public class TelemetryUserDtoComparer : IEqualityComparer { /// - public class TelemetryUserDtoComparer : IEqualityComparer + public bool Equals(TelemetryUserDto? prevUser, TelemetryUserDto? nextUser) { - /// - public bool Equals(TelemetryUserDto? prevUser, TelemetryUserDto? nextUser) - { - if (prevUser is not null && nextUser is not null) - return prevUser.Id == nextUser.Id; + if (prevUser is not null && nextUser is not null) + return prevUser.Id == nextUser.Id; - return prevUser == nextUser; - } - - /// - public int GetHashCode(TelemetryUserDto user) => user.Id.GetHashCode(); + return prevUser == nextUser; } + + /// + public int GetHashCode(TelemetryUserDto user) => user.Id.GetHashCode(); } diff --git a/AsbCloudApp/CyclicArray.cs b/AsbCloudApp/CyclicArray.cs index b9a87956..3735e519 100644 --- a/AsbCloudApp/CyclicArray.cs +++ b/AsbCloudApp/CyclicArray.cs @@ -1,196 +1,195 @@ using System.Linq; -namespace System.Collections.Generic +namespace System.Collections.Generic; + +/// +/// Цикличный массив +/// +/// +public class CyclicArray : IEnumerable { + readonly T[] array; + int used, current = -1; + /// - /// Цикличный массив + /// constructor /// - /// - public class CyclicArray : IEnumerable + /// + public CyclicArray(int capacity) { - readonly T[] array; - int used, current = -1; + array = new T[capacity]; + } - /// - /// constructor - /// - /// - public CyclicArray(int capacity) + /// + /// Количество элементов в массиве + /// + public int Count => used; + + /// + /// Добавить новый элемент
+ /// Если capacity достигнуто, то вытеснит самый первый элемент + ///
+ /// + public void Add(T item) + { + current = (++current) % array.Length; + array[current] = item; + if (used < array.Length) + used++; + UpdatedInvoke(current, item); + } + + /// + /// Добавить новые элементы.
+ /// Если capacity достигнуто, то вытеснит самые первые элементы.
+ /// Не вызывает Updated! + ///
+ /// + public void AddRange(IEnumerable items) + { + var capacity = array.Length; + var newItems = items.TakeLast(capacity).ToArray(); + if (newItems.Length == capacity) { - array = new T[capacity]; + Array.Copy(newItems, array, capacity); + current = capacity - 1; } - - /// - /// Количество элементов в массиве - /// - public int Count => used; - - /// - /// Добавить новый элемент
- /// Если capacity достигнуто, то вытеснит самый первый элемент - ///
- /// - public void Add(T item) + else { - current = (++current) % array.Length; - array[current] = item; - if (used < array.Length) - used++; - UpdatedInvoke(current, item); - } - - /// - /// Добавить новые элементы.
- /// Если capacity достигнуто, то вытеснит самые первые элементы.
- /// Не вызывает Updated! - ///
- /// - public void AddRange(IEnumerable items) - { - var capacity = array.Length; - var newItems = items.TakeLast(capacity).ToArray(); - if (newItems.Length == capacity) + current = (++current) % capacity; + var countToEndOfArray = capacity - current; + if (newItems.Length <= countToEndOfArray) { - Array.Copy(newItems, array, capacity); - current = capacity - 1; + Array.Copy(newItems, 0, array, current, newItems.Length); + current += newItems.Length - 1; } else { - current = (++current) % capacity; - var countToEndOfArray = capacity - current; - if (newItems.Length <= countToEndOfArray) - { - Array.Copy(newItems, 0, array, current, newItems.Length); - current += newItems.Length - 1; - } - else - { - var firstStepLength = countToEndOfArray; - Array.Copy(newItems, 0, array, current, firstStepLength); - var secondStepCount = newItems.Length - firstStepLength; - Array.Copy(newItems, firstStepLength, array, 0, secondStepCount); - current = secondStepCount - 1; - } - } - - if (used < capacity) - { - used += newItems.Length; - used = used > capacity ? capacity : used; + var firstStepLength = countToEndOfArray; + Array.Copy(newItems, 0, array, current, firstStepLength); + var secondStepCount = newItems.Length - firstStepLength; + Array.Copy(newItems, firstStepLength, array, 0, secondStepCount); + current = secondStepCount - 1; } } - /// - /// Индекс - /// - /// - /// - public T this[int index] + if (used < capacity) + { + used += newItems.Length; + used = used > capacity ? capacity : used; + } + } + + /// + /// Индекс + /// + /// + /// + public T this[int index] + { + get + { + if (used == 0) + throw new IndexOutOfRangeException(); + + var i = (current + 1 + index) % used; + return array[i]; + } + set + { + var devider = used > 0 ? used : array.Length; + var i = (current + 1 + index) % devider; + array[i] = value; + UpdatedInvoke(current, value); + } + } + + /// + /// событие на изменение элемента в массиве + /// + public event EventHandler<(int index, T value)>? Updated; + private void UpdatedInvoke(int index, T value) + { + Updated?.Invoke(this, (index, value)); + } + + /// + /// Агрегирование значения по всему массиву + /// + /// + /// + /// + /// + public Tout Aggregate(Func func, Tout startValue) + { + Tout result = startValue; + for (int i = 0; i < used; i++) + result = func(this[i], result); + return result; + } + + /// + public IEnumerator GetEnumerator() + => new CyclycListEnumerator(array, current, used); + + /// + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + class CyclycListEnumerator : IEnumerator + { + private readonly Te[] array; + private readonly int used; + private readonly int first; + private int current = -1; + + public CyclycListEnumerator(Te[] array, int first, int used) + { + this.array = new Te[array.Length]; + array.CopyTo(this.array, 0); + this.used = used; + this.first = first; + } + + public Te Current { get { - if (used == 0) - throw new IndexOutOfRangeException(); - - var i = (current + 1 + index) % used; - return array[i]; - } - set - { - var devider = used > 0 ? used : array.Length; - var i = (current + 1 + index) % devider; - array[i] = value; - UpdatedInvoke(current, value); - } - } - - /// - /// событие на изменение элемента в массиве - /// - public event EventHandler<(int index, T value)>? Updated; - private void UpdatedInvoke(int index, T value) - { - Updated?.Invoke(this, (index, value)); - } - - /// - /// Агрегирование значения по всему массиву - /// - /// - /// - /// - /// - public Tout Aggregate(Func func, Tout startValue) - { - Tout result = startValue; - for (int i = 0; i < used; i++) - result = func(this[i], result); - return result; - } - - /// - public IEnumerator GetEnumerator() - => new CyclycListEnumerator(array, current, used); - - /// - IEnumerator IEnumerable.GetEnumerator() - => GetEnumerator(); - - class CyclycListEnumerator : IEnumerator - { - private readonly Te[] array; - private readonly int used; - private readonly int first; - private int current = -1; - - public CyclycListEnumerator(Te[] array, int first, int used) - { - this.array = new Te[array.Length]; - array.CopyTo(this.array, 0); - this.used = used; - this.first = first; - } - - public Te Current - { - get + if (IsCurrentOk()) { - if (IsCurrentOk()) - { - var i = (current + first + 1) % used; - return array[i]; - } - else - return default!; + var i = (current + first + 1) % used; + return array[i]; } - } - - object? IEnumerator.Current => Current; - - public void Dispose() {; } - - private bool IsCurrentOk() => current >= 0 && current < used; - - public bool MoveNext() - { - if (current < used) - current++; - return IsCurrentOk(); - } - - public void Reset() - { - current = -1; + else + return default!; } } - /// - /// Очистить весь массив - /// - public void Clear() + object? IEnumerator.Current => Current; + + public void Dispose() {; } + + private bool IsCurrentOk() => current >= 0 && current < used; + + public bool MoveNext() + { + if (current < used) + current++; + return IsCurrentOk(); + } + + public void Reset() { - used = 0; current = -1; } } + + /// + /// Очистить весь массив + /// + public void Clear() + { + used = 0; + current = -1; + } } \ No newline at end of file diff --git a/AsbCloudApp/Data/AuthDto.cs b/AsbCloudApp/Data/AuthDto.cs index f2e2c20d..164f22c4 100644 --- a/AsbCloudApp/Data/AuthDto.cs +++ b/AsbCloudApp/Data/AuthDto.cs @@ -1,24 +1,23 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO для авторизации +/// +public class AuthDto { /// - /// DTO для авторизации + /// Имя пользователя для входа /// - public class AuthDto - { - /// - /// Имя пользователя для входа - /// - [Required(ErrorMessage = "Логин не должен быть пустым")] - [StringLength(50, MinimumLength = 1, ErrorMessage = "Допустимая длина логина от 1 до 50 символов")] - public string Login { get; set; } = null!; + [Required(ErrorMessage = "Логин не должен быть пустым")] + [StringLength(50, MinimumLength = 1, ErrorMessage = "Допустимая длина логина от 1 до 50 символов")] + public string Login { get; set; } = null!; - /// - /// Пароль пользователя для входа - /// - [Required(ErrorMessage = "Пароль не должен быть пустым")] - [StringLength(50, MinimumLength = 1, ErrorMessage = "Допустимая длина пароля от 1 до 50 символов")] - public string Password { get; set; } = null!; - } + /// + /// Пароль пользователя для входа + /// + [Required(ErrorMessage = "Пароль не должен быть пустым")] + [StringLength(50, MinimumLength = 1, ErrorMessage = "Допустимая длина пароля от 1 до 50 символов")] + public string Password { get; set; } = null!; } diff --git a/AsbCloudApp/Data/BackgroundWorkDto.cs b/AsbCloudApp/Data/BackgroundWorkDto.cs index d0e15b50..eccf6f1c 100644 --- a/AsbCloudApp/Data/BackgroundWorkDto.cs +++ b/AsbCloudApp/Data/BackgroundWorkDto.cs @@ -1,206 +1,205 @@ using System; using System.Diagnostics; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Информация о фоновой работе +/// +public class BackgroundWorkDto { /// - /// Информация о фоновой работе + /// Идентификатор работы. Должен быть уникальным. Используется в логах и передается в колбэки. /// - public class BackgroundWorkDto + public string Id { get; init; } = null!; + + /// + /// Класс описания состояния + /// + public class CurrentStateInfo + { + private string state = "start"; + + /// + /// Время последнего запуска + /// + public DateTime Start { get; } = DateTime.Now; + + /// + /// Текущее время выполнения + /// + public TimeSpan ExecutionTime => DateTime.Now - Start; + + /// + /// Текстовое описание того, что происходит в задаче. + /// + public string State + { + get => state; + internal set + { + state = value; + StateUpdate = DateTime.Now; + } + } + + /// + /// Прогресс + /// + public double Progress { get; internal set; } = 0; + + /// + /// Время последнего запуска + /// + public DateTime StateUpdate { get; private set; } = DateTime.Now; + } + + /// + /// Инфо о последней ошибке + /// + public class LastErrorInfo : LastCompleteInfo { /// - /// Идентификатор работы. Должен быть уникальным. Используется в логах и передается в колбэки. + /// /// - public string Id { get; init; } = null!; - - /// - /// Класс описания состояния - /// - public class CurrentStateInfo + /// + /// + public LastErrorInfo(CurrentStateInfo state, string errorText) + : base(state) { - private string state = "start"; - - /// - /// Время последнего запуска - /// - public DateTime Start { get; } = DateTime.Now; - - /// - /// Текущее время выполнения - /// - public TimeSpan ExecutionTime => DateTime.Now - Start; - - /// - /// Текстовое описание того, что происходит в задаче. - /// - public string State - { - get => state; - internal set - { - state = value; - StateUpdate = DateTime.Now; - } - } - - /// - /// Прогресс - /// - public double Progress { get; internal set; } = 0; - - /// - /// Время последнего запуска - /// - public DateTime StateUpdate { get; private set; } = DateTime.Now; + ErrorText = errorText; } - /// - /// Инфо о последней ошибке - /// - public class LastErrorInfo : LastCompleteInfo - { - /// - /// - /// - /// - /// - public LastErrorInfo(CurrentStateInfo state, string errorText) - : base(state) - { - ErrorText = errorText; - } - - /// - /// Последняя ошибка - /// - public string ErrorText { get; init; } = null!; - } - - /// - /// Инфо о последнем завершении - /// - public class LastCompleteInfo - { - /// - /// Дата запуска - /// - public DateTime Start { get; init; } - - /// - /// Дата завершения - /// - public DateTime End { get; init; } - - /// - /// Продолжительность последнего выполнения - /// - public TimeSpan ExecutionTime => End - Start; - - /// - /// Состояние на момент завершения - /// - public string State { get; init; } - - /// - /// ctor - /// - /// - public LastCompleteInfo(CurrentStateInfo state) - { - Start = state.Start; - End = DateTime.Now; - State = state.State; - } - } - - /// - /// Текущее состояние - /// - public CurrentStateInfo? CurrentState { get; private set; } - /// /// Последняя ошибка /// - public LastErrorInfo? LastError { get; private set; } + public string ErrorText { get; init; } = null!; + } + + /// + /// Инфо о последнем завершении + /// + public class LastCompleteInfo + { + /// + /// Дата запуска + /// + public DateTime Start { get; init; } /// - /// Последняя завершенная + /// Дата завершения /// - public LastCompleteInfo? LastComplete { get; private set; } + public DateTime End { get; init; } /// - /// Кол-во запусков + /// Продолжительность последнего выполнения /// - public int CountStart { get; private set; } + public TimeSpan ExecutionTime => End - Start; /// - /// Кол-во завершений + /// Состояние на момент завершения /// - public int CountComplete { get; private set; } + public string State { get; init; } /// - /// Кол-во ошибок + /// ctor /// - public int CountErrors { get; private set; } - - /// - /// Максимально допустимое время выполнения работы - /// - public TimeSpan Timeout { get; set; } = TimeSpan.FromMinutes(1); - - private string WorkNameForTrace => $"Backgroud work:\"{Id}\""; - - /// - /// Обновления состояния при запуске работы - /// - protected void SetStatusStart() + /// + public LastCompleteInfo(CurrentStateInfo state) { - CurrentState = new(); - CountStart++; - Trace.TraceInformation($"{WorkNameForTrace} state: starting"); - } - - /// - /// Обновления состояния в процессе работы - /// - protected void UpdateStatus(string newState, double? progress) - { - if (CurrentState is null) - return; - - CurrentState.State = newState; - if (progress.HasValue) - CurrentState.Progress = progress.Value; - - Trace.TraceInformation($"{WorkNameForTrace} state[{100*progress:#}%]: {newState}"); - } - - /// - /// Обновления состояния при успешном завершении работы - /// - protected void SetStatusComplete() - { - CountComplete++; - if (CurrentState is null) - return; - - LastComplete = new(CurrentState); - CurrentState = null; - Trace.TraceInformation($"{WorkNameForTrace} state: completed"); - } - - /// - /// Обновления состояния при ошибке в работе - /// - protected void SetLastError(string errorMessage) - { - CountErrors++; - if (CurrentState is null) - return; - - LastError = new LastErrorInfo(CurrentState, errorMessage); - CurrentState = null; - Trace.TraceError($"{WorkNameForTrace} throw exception[{CountErrors}]: {errorMessage}"); + Start = state.Start; + End = DateTime.Now; + State = state.State; } } + + /// + /// Текущее состояние + /// + public CurrentStateInfo? CurrentState { get; private set; } + + /// + /// Последняя ошибка + /// + public LastErrorInfo? LastError { get; private set; } + + /// + /// Последняя завершенная + /// + public LastCompleteInfo? LastComplete { get; private set; } + + /// + /// Кол-во запусков + /// + public int CountStart { get; private set; } + + /// + /// Кол-во завершений + /// + public int CountComplete { get; private set; } + + /// + /// Кол-во ошибок + /// + public int CountErrors { get; private set; } + + /// + /// Максимально допустимое время выполнения работы + /// + public TimeSpan Timeout { get; set; } = TimeSpan.FromMinutes(1); + + private string WorkNameForTrace => $"Backgroud work:\"{Id}\""; + + /// + /// Обновления состояния при запуске работы + /// + protected void SetStatusStart() + { + CurrentState = new(); + CountStart++; + Trace.TraceInformation($"{WorkNameForTrace} state: starting"); + } + + /// + /// Обновления состояния в процессе работы + /// + protected void UpdateStatus(string newState, double? progress) + { + if (CurrentState is null) + return; + + CurrentState.State = newState; + if (progress.HasValue) + CurrentState.Progress = progress.Value; + + Trace.TraceInformation($"{WorkNameForTrace} state[{100*progress:#}%]: {newState}"); + } + + /// + /// Обновления состояния при успешном завершении работы + /// + protected void SetStatusComplete() + { + CountComplete++; + if (CurrentState is null) + return; + + LastComplete = new(CurrentState); + CurrentState = null; + Trace.TraceInformation($"{WorkNameForTrace} state: completed"); + } + + /// + /// Обновления состояния при ошибке в работе + /// + protected void SetLastError(string errorMessage) + { + CountErrors++; + if (CurrentState is null) + return; + + LastError = new LastErrorInfo(CurrentState, errorMessage); + CurrentState = null; + Trace.TraceError($"{WorkNameForTrace} throw exception[{CountErrors}]: {errorMessage}"); + } } \ No newline at end of file diff --git a/AsbCloudApp/Data/ClusterDto.cs b/AsbCloudApp/Data/ClusterDto.cs index 80eedfe4..36e5db20 100644 --- a/AsbCloudApp/Data/ClusterDto.cs +++ b/AsbCloudApp/Data/ClusterDto.cs @@ -2,39 +2,38 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO кустов +/// +public class ClusterDto : MapPointBaseDto { /// - /// DTO кустов + /// ИД месторождения, необязательный /// - public class ClusterDto : MapPointBaseDto - { - /// - /// ИД месторождения, необязательный - /// - [Required] - [Range(1, int.MaxValue, ErrorMessage = "Id месторождения не может быть меньше 1")] - public int IdDeposit { get; set; } - - /// - /// DTO месторождения - /// - public DepositBaseDto? Deposit { get; set; } - - /// - /// Список скважин куста - /// - public IEnumerable Wells { get; set; } = Enumerable.Empty(); - } + [Required] + [Range(1, int.MaxValue, ErrorMessage = "Id месторождения не может быть меньше 1")] + public int IdDeposit { get; set; } /// - /// DTO кустов + /// DTO месторождения /// - public class ClusterBranchDto : MapPointBaseDto - { - /// - /// Список скважин куста - /// - public IEnumerable Wells { get; set; } = Enumerable.Empty(); - } + public DepositBaseDto? Deposit { get; set; } + + /// + /// Список скважин куста + /// + public IEnumerable Wells { get; set; } = Enumerable.Empty(); +} + +/// +/// DTO кустов +/// +public class ClusterBranchDto : MapPointBaseDto +{ + /// + /// Список скважин куста + /// + public IEnumerable Wells { get; set; } = Enumerable.Empty(); } diff --git a/AsbCloudApp/Data/ClusterRopStatDto.cs b/AsbCloudApp/Data/ClusterRopStatDto.cs index 386614dc..ecfee99e 100644 --- a/AsbCloudApp/Data/ClusterRopStatDto.cs +++ b/AsbCloudApp/Data/ClusterRopStatDto.cs @@ -1,22 +1,21 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Статистика механической скорости проходки (МСП) по кусту +/// +public class ClusterRopStatDto { /// - /// Статистика механической скорости проходки (МСП) по кусту + /// Макс. механическая скорость проходки по кусту /// - public class ClusterRopStatDto - { - /// - /// Макс. механическая скорость проходки по кусту - /// - [Required] - public double RopMax { get; set; } + [Required] + public double RopMax { get; set; } - /// - /// Средняя механическая скорость проходки по кусту - /// - [Required] - public double RopAverage { get; set; } - } + /// + /// Средняя механическая скорость проходки по кусту + /// + [Required] + public double RopAverage { get; set; } } \ No newline at end of file diff --git a/AsbCloudApp/Data/CompanyDto.cs b/AsbCloudApp/Data/CompanyDto.cs index 84ac8cb6..4e54faae 100644 --- a/AsbCloudApp/Data/CompanyDto.cs +++ b/AsbCloudApp/Data/CompanyDto.cs @@ -1,33 +1,32 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO компании +/// +public class CompanyDto : IId { + /// + public int Id { get; set; } + /// - /// DTO компании + /// Название /// - public class CompanyDto : IId - { - /// - public int Id { get; set; } + [Required] + [StringLength(50, MinimumLength = 1, ErrorMessage = "Допустимое имя компании от 1 до 50 символов")] + public string Caption { get; set; } = null!; - /// - /// Название - /// - [Required] - [StringLength(50, MinimumLength = 1, ErrorMessage = "Допустимое имя компании от 1 до 50 символов")] - public string Caption { get; set; } = null!; + /// + /// ИД типа компании + /// + [Required] + public int IdCompanyType { get; set; } - /// - /// ИД типа компании - /// - [Required] - public int IdCompanyType { get; set; } + /// + /// Название типа компании + /// + [StringLength(255, MinimumLength = 1, ErrorMessage = "Допустимое имя типа компании от 1 до 255 символов")] + public string? CompanyTypeCaption { get; set; } = null!; - /// - /// Название типа компании - /// - [StringLength(255, MinimumLength = 1, ErrorMessage = "Допустимое имя типа компании от 1 до 255 символов")] - public string? CompanyTypeCaption { get; set; } = null!; - - } } diff --git a/AsbCloudApp/Data/CompanyTypeDto.cs b/AsbCloudApp/Data/CompanyTypeDto.cs index b543a1ae..6041d60d 100644 --- a/AsbCloudApp/Data/CompanyTypeDto.cs +++ b/AsbCloudApp/Data/CompanyTypeDto.cs @@ -1,33 +1,32 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO тип компании +/// +public class CompanyTypeDto : IId { + /// + [Required] + public int Id { get; set; } + /// - /// DTO тип компании + /// Название типа компании /// - public class CompanyTypeDto : IId - { - /// - [Required] - public int Id { get; set; } + [Required] + public string Caption { get; set; } = null!; - /// - /// Название типа компании - /// - [Required] - public string Caption { get; set; } = null!; + /// + /// Порядок + /// + [Required] + public int Order { get; set; } - /// - /// Порядок - /// - [Required] - public int Order { get; set; } + /// + /// Является ли контактом + /// + [Required] + public bool IsContact { get; set; } - /// - /// Является ли контактом - /// - [Required] - public bool IsContact { get; set; } - - } } diff --git a/AsbCloudApp/Data/DataSaubStatDto.cs b/AsbCloudApp/Data/DataSaubStatDto.cs index b8e27b37..3bb46d6d 100644 --- a/AsbCloudApp/Data/DataSaubStatDto.cs +++ b/AsbCloudApp/Data/DataSaubStatDto.cs @@ -1,136 +1,135 @@ using System; using AsbCloudApp.Data.WellOperation; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// dto для хранения данных статистики сауб +/// +public class DataSaubStatDto:IId { /// - /// dto для хранения данных статистики сауб + /// /// - public class DataSaubStatDto:IId - { - /// - /// - /// - public int Id { get; set; } + public int Id { get; set; } - /// - /// Дата и время начала - /// - public DateTimeOffset DateStart { get; set; } + /// + /// Дата и время начала + /// + public DateTimeOffset DateStart { get; set; } - /// - /// Дата и время окончания - /// - public DateTimeOffset DateEnd { get; set; } + /// + /// Дата и время окончания + /// + public DateTimeOffset DateEnd { get; set; } - /// - /// Глубина забоя по стволу начальная - /// - public double DepthStart { get; set; } + /// + /// Глубина забоя по стволу начальная + /// + public double DepthStart { get; set; } - /// - /// Глубина забоя по стволу конечная - /// - public double DepthEnd { get; set; } + /// + /// Глубина забоя по стволу конечная + /// + public double DepthEnd { get; set; } - /// - /// Скорость бурения - /// - public double Speed { get; set; } + /// + /// Скорость бурения + /// + public double Speed { get; set; } - /// - /// Ограничение скорости блока - /// - public double? BlockSpeedSp { get; set; } + /// + /// Ограничение скорости блока + /// + public double? BlockSpeedSp { get; set; } - /// - /// Давление - /// - public double Pressure { get; set; } + /// + /// Давление + /// + public double Pressure { get; set; } - /// - /// Давление холостого хода - /// - public double? PressureIdle { get; set; } + /// + /// Давление холостого хода + /// + public double? PressureIdle { get; set; } - /// - /// Ограничение фактического давления - /// - public double? PressureSp { get; set; } + /// + /// Ограничение фактического давления + /// + public double? PressureSp { get; set; } - /// - /// Фактическая нагрузка - /// - public double AxialLoad { get; set; } + /// + /// Фактическая нагрузка + /// + public double AxialLoad { get; set; } - /// - /// Ограничение факт. нагрузки - /// - public double? AxialLoadSp { get; set; } + /// + /// Ограничение факт. нагрузки + /// + public double? AxialLoadSp { get; set; } - /// - /// Максимально допустимая нагрузка - /// - public double? AxialLoadLimitMax { get; set; } + /// + /// Максимально допустимая нагрузка + /// + public double? AxialLoadLimitMax { get; set; } - /// - /// Фактический момент - /// - public double RotorTorque { get; set; } + /// + /// Фактический момент + /// + public double RotorTorque { get; set; } - /// - /// Ограничение факт. момента - /// - public double? RotorTorqueSp { get; set; } + /// + /// Ограничение факт. момента + /// + public double? RotorTorqueSp { get; set; } - /// - /// Максимально допустимый момент - /// - public double? RotorTorqueLimitMax { get; set; } + /// + /// Максимально допустимый момент + /// + public double? RotorTorqueLimitMax { get; set; } - /// - /// Работа при достижении ограничения - /// - public short? IdFeedRegulator { get; set; } + /// + /// Работа при достижении ограничения + /// + public short? IdFeedRegulator { get; set; } - /// - /// Фактическая скорость оборотов ВСП - /// - public double RotorSpeed { get; set; } + /// + /// Фактическая скорость оборотов ВСП + /// + public double RotorSpeed { get; set; } - /// - /// Название автоопределённой операции - /// - public int IdCategory { get; set; } + /// + /// Название автоопределённой операции + /// + public int IdCategory { get; set; } - /// - /// Флаги подсистем - /// - public int EnabledSubsystems { get; set; } + /// + /// Флаги подсистем + /// + public int EnabledSubsystems { get; set; } - /// - /// Наличие или отсутствие осцилляции - /// - public bool HasOscillation { get; set; } + /// + /// Наличие или отсутствие осцилляции + /// + public bool HasOscillation { get; set; } - /// - /// Фактический расход - /// - public double Flow { get; set; } + /// + /// Фактический расход + /// + public double Flow { get; set; } - /// - /// Ключ телеметрии - /// - public int IdTelemetry { get; set; } + /// + /// Ключ телеметрии + /// + public int IdTelemetry { get; set; } - /// - /// Телеметрия - /// - public TelemetryDto Telemetry { get; set; } = null!; + /// + /// Телеметрия + /// + public TelemetryDto Telemetry { get; set; } = null!; - /// - /// Категория автоопределенной операции - /// - public WellOperationCategoryDto OperationCategory { get; set; } = null!; - } + /// + /// Категория автоопределенной операции + /// + public WellOperationCategoryDto OperationCategory { get; set; } = null!; } diff --git a/AsbCloudApp/Data/DatesRangeDto.cs b/AsbCloudApp/Data/DatesRangeDto.cs index 0b0e5ef9..8be2a6f7 100644 --- a/AsbCloudApp/Data/DatesRangeDto.cs +++ b/AsbCloudApp/Data/DatesRangeDto.cs @@ -1,23 +1,22 @@ using System; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Диапазон дат +/// +public class DatesRangeDto { /// - /// Диапазон дат + /// Дата начала диапазона /// - public class DatesRangeDto - { - /// - /// Дата начала диапазона - /// - [Required] - public DateTimeOffset From { get; set; } + [Required] + public DateTimeOffset From { get; set; } - /// - /// Дата окончания диапазона - /// - [Required] - public DateTimeOffset To { get; set; } - } + /// + /// Дата окончания диапазона + /// + [Required] + public DateTimeOffset To { get; set; } } diff --git a/AsbCloudApp/Data/DepositDto.cs b/AsbCloudApp/Data/DepositDto.cs index a0011022..01121955 100644 --- a/AsbCloudApp/Data/DepositDto.cs +++ b/AsbCloudApp/Data/DepositDto.cs @@ -2,39 +2,38 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -namespace AsbCloudApp.Data -{ +namespace AsbCloudApp.Data; + #nullable enable - /// - /// DTO Месторождения - /// - public class DepositBaseDto : MapPointBaseDto - { - } - - /// - /// DTO Месторождения с кустами - /// - public class DepositDto : MapPointBaseDto - { - /// - /// Кусты месторождения - /// - [Required] - public IEnumerable Clusters { get; set; } = Enumerable.Empty(); - } - - /// - /// DTO Месторождения с кустами - /// - public class DepositBranchDto : MapPointBaseDto - { - /// - /// Кусты месторождения - /// - [Required] - public IEnumerable Clusters { get; set; } = Enumerable.Empty(); - } +/// +/// DTO Месторождения +/// +public class DepositBaseDto : MapPointBaseDto +{ +} + +/// +/// DTO Месторождения с кустами +/// +public class DepositDto : MapPointBaseDto +{ + /// + /// Кусты месторождения + /// + [Required] + public IEnumerable Clusters { get; set; } = Enumerable.Empty(); +} + +/// +/// DTO Месторождения с кустами +/// +public class DepositBranchDto : MapPointBaseDto +{ + /// + /// Кусты месторождения + /// + [Required] + public IEnumerable Clusters { get; set; } = Enumerable.Empty(); } diff --git a/AsbCloudApp/Data/DetectedOperation/DetectedOperationDrillersStatDto.cs b/AsbCloudApp/Data/DetectedOperation/DetectedOperationDrillersStatDto.cs index 122ad081..7c93adf4 100644 --- a/AsbCloudApp/Data/DetectedOperation/DetectedOperationDrillersStatDto.cs +++ b/AsbCloudApp/Data/DetectedOperation/DetectedOperationDrillersStatDto.cs @@ -1,42 +1,41 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data.DetectedOperation +namespace AsbCloudApp.Data.DetectedOperation; + +/// +/// Статистика по операциям бурильщика +/// +public class DetectedOperationDrillersStatDto { /// - /// Статистика по операциям бурильщика + /// Бурильщик /// - public class DetectedOperationDrillersStatDto - { - /// - /// Бурильщик - /// - public DrillerDto? Driller { get; set; } + public DrillerDto? Driller { get; set; } - /// - /// Количество операции - /// - [Required] - public int Count { get; set; } + /// + /// Количество операции + /// + [Required] + public int Count { get; set; } - /// - /// Среднее по ключевому показателю - /// - [Required] - public double AverageValue { get; set; } + /// + /// Среднее по ключевому показателю + /// + [Required] + public double AverageValue { get; set; } - /// - /// Среднее целевого показателя - /// - public double? AverageTargetValue { get; set; } + /// + /// Среднее целевого показателя + /// + public double? AverageTargetValue { get; set; } - /// - /// Коэффициент эффективности, % - /// - public double? Efficiency { get; set; } + /// + /// Коэффициент эффективности, % + /// + public double? Efficiency { get; set; } - /// - /// Коэффициент потерь - /// - public double? Loss { get; set; } - } + /// + /// Коэффициент потерь + /// + public double? Loss { get; set; } } diff --git a/AsbCloudApp/Data/DetectedOperation/DetectedOperationListDto.cs b/AsbCloudApp/Data/DetectedOperation/DetectedOperationListDto.cs index 08c6b108..c9b29a62 100644 --- a/AsbCloudApp/Data/DetectedOperation/DetectedOperationListDto.cs +++ b/AsbCloudApp/Data/DetectedOperation/DetectedOperationListDto.cs @@ -2,23 +2,22 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -namespace AsbCloudApp.Data.DetectedOperation +namespace AsbCloudApp.Data.DetectedOperation; + +/// +/// Автоматически определяемая операция +/// +public class DetectedOperationListDto { /// - /// Автоматически определяемая операция + /// Список всех операций /// - public class DetectedOperationListDto - { - /// - /// Список всех операций - /// - [Required] - public IEnumerable Operations { get; set; } = Enumerable.Empty(); + [Required] + public IEnumerable Operations { get; set; } = Enumerable.Empty(); - /// - /// Статистика по бурильщикам - /// - [Required] - public IEnumerable Stats { get; set; } = Enumerable.Empty(); - } + /// + /// Статистика по бурильщикам + /// + [Required] + public IEnumerable Stats { get; set; } = Enumerable.Empty(); } diff --git a/AsbCloudApp/Data/DetectedOperation/DetectedOperationStatDto.cs b/AsbCloudApp/Data/DetectedOperation/DetectedOperationStatDto.cs index b8007c85..2624c307 100644 --- a/AsbCloudApp/Data/DetectedOperation/DetectedOperationStatDto.cs +++ b/AsbCloudApp/Data/DetectedOperation/DetectedOperationStatDto.cs @@ -1,69 +1,68 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data.DetectedOperation +namespace AsbCloudApp.Data.DetectedOperation; + +/// +/// Статистика по операциям например за период. +/// +public class DetectedOperationStatDto { /// - /// Статистика по операциям например за период. + /// Id названия/описания операции /// - public class DetectedOperationStatDto - { - /// - /// Id названия/описания операции - /// - [Required] - public int IdCategory { get; set; } + [Required] + public int IdCategory { get; set; } - /// - /// Название операции - /// - public string Category { get; set; } = string.Empty; + /// + /// Название операции + /// + public string Category { get; set; } = string.Empty; - /// - /// Количество операций - /// - [Required] - public int Count { get; set; } + /// + /// Количество операций + /// + [Required] + public int Count { get; set; } - /// - /// Среднее по ключевому показателю - /// - [Required] - public double ValueAverage { get; set; } + /// + /// Среднее по ключевому показателю + /// + [Required] + public double ValueAverage { get; set; } - /// - /// Мин по ключевому показателю - /// - [Required] - public double ValueMin { get; set; } + /// + /// Мин по ключевому показателю + /// + [Required] + public double ValueMin { get; set; } - /// - /// Макс по ключевому показателю - /// - [Required] - public double ValueMax { get; set; } + /// + /// Макс по ключевому показателю + /// + [Required] + public double ValueMax { get; set; } - /// - /// Суммарное время операций, мин - /// - [Required] - public double MinutesTotal { get; set; } + /// + /// Суммарное время операций, мин + /// + [Required] + public double MinutesTotal { get; set; } - /// - /// Мин продолжительность операции, мин - /// - [Required] - public double MinutesMin { get; set; } + /// + /// Мин продолжительность операции, мин + /// + [Required] + public double MinutesMin { get; set; } - /// - /// Макс продолжительность операции, мин - /// - [Required] - public double MinutesMax { get; set; } + /// + /// Макс продолжительность операции, мин + /// + [Required] + public double MinutesMax { get; set; } - /// - /// Средняя продолжительность операции, мин - /// - [Required] - public double MinutesAverage { get; set; } - } + /// + /// Средняя продолжительность операции, мин + /// + [Required] + public double MinutesAverage { get; set; } } diff --git a/AsbCloudApp/Data/DetectedOperation/DetectedOperationWithDrillerDto.cs b/AsbCloudApp/Data/DetectedOperation/DetectedOperationWithDrillerDto.cs index af5ff539..87990a6d 100644 --- a/AsbCloudApp/Data/DetectedOperation/DetectedOperationWithDrillerDto.cs +++ b/AsbCloudApp/Data/DetectedOperation/DetectedOperationWithDrillerDto.cs @@ -1,18 +1,17 @@ -namespace AsbCloudApp.Data.DetectedOperation +namespace AsbCloudApp.Data.DetectedOperation; + +/// +/// Автоматически определяемая операция +/// +public class DetectedOperationWithDrillerDto : DetectedOperationDto { /// - /// Автоматически определяемая операция + /// Бурильщик /// - public class DetectedOperationWithDrillerDto : DetectedOperationDto - { - /// - /// Бурильщик - /// - public DrillerDto? Driller { get; set; } + public DrillerDto? Driller { get; set; } - /// - /// Целевые/нормативные показатели - /// - public OperationValueDto? OperationValue { get; set; } - } + /// + /// Целевые/нормативные показатели + /// + public OperationValueDto? OperationValue { get; set; } } diff --git a/AsbCloudApp/Data/DrillParamsDto.cs b/AsbCloudApp/Data/DrillParamsDto.cs index 788d5207..d367b53a 100644 --- a/AsbCloudApp/Data/DrillParamsDto.cs +++ b/AsbCloudApp/Data/DrillParamsDto.cs @@ -1,52 +1,51 @@ using System.Linq; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + + +/// +/// DTO параметров бурения +/// +public class DrillParamsDto : IId, IWellRelated { + /// + public int Id { get; set; } + + /// + public int IdWell { get; set; } /// - /// DTO параметров бурения + /// Глубина интервала /// - public class DrillParamsDto : IId, IWellRelated - { - /// - public int Id { get; set; } + public MinMaxDto Depth { get; set; } = null!; - /// - public int IdWell { get; set; } + /// + /// id well section type. + /// + public int IdWellSectionType { get; set; } - /// - /// Глубина интервала - /// - public MinMaxDto Depth { get; set; } = null!; + /// + /// axial load + /// + public MinMaxExtendedViewDto AxialLoad { get; set; } = null!; - /// - /// id well section type. - /// - public int IdWellSectionType { get; set; } + /// + /// pressure + /// + public MinMaxExtendedViewDto Pressure { get; set; } = null!; - /// - /// axial load - /// - public MinMaxExtendedViewDto AxialLoad { get; set; } = null!; + /// + /// rotor torque + /// + public MinMaxExtendedViewDto RotorTorque { get; set; } = null!; - /// - /// pressure - /// - public MinMaxExtendedViewDto Pressure { get; set; } = null!; + /// + /// rotor speed + /// + public MinMaxExtendedViewDto RotorSpeed { get; set; } = null!; - /// - /// rotor torque - /// - public MinMaxExtendedViewDto RotorTorque { get; set; } = null!; - - /// - /// rotor speed - /// - public MinMaxExtendedViewDto RotorSpeed { get; set; } = null!; - - /// - /// flow - /// - public MinMaxExtendedViewDto Flow { get; set; } = null!; - } + /// + /// flow + /// + public MinMaxExtendedViewDto Flow { get; set; } = null!; } \ No newline at end of file diff --git a/AsbCloudApp/Data/DrillTestReport/DrillTestReportDataDto.cs b/AsbCloudApp/Data/DrillTestReport/DrillTestReportDataDto.cs index 1e7a529e..17d54f85 100644 --- a/AsbCloudApp/Data/DrillTestReport/DrillTestReportDataDto.cs +++ b/AsbCloudApp/Data/DrillTestReport/DrillTestReportDataDto.cs @@ -1,26 +1,25 @@ using AsbCloudApp.Data.SAUB; using System; -namespace AsbCloudApp.Data.DrillTestReport +namespace AsbCloudApp.Data.DrillTestReport; + +/// +/// Информация о drill test, выгружаемая в отчете +/// +public class DrillTestReportDataDto { /// - /// Информация о drill test, выгружаемая в отчете + /// Данные для отчета /// - public class DrillTestReportDataDto - { - /// - /// Данные для отчета - /// - public DrillTestDto Data { get; set; } = null!; + public DrillTestDto Data { get; set; } = null!; - /// - /// Заголовок отчета - /// - public string Caption { get; set; } = null!; + /// + /// Заголовок отчета + /// + public string Caption { get; set; } = null!; - /// - /// Дата отчета - /// - public DateTimeOffset Date { get; set; } = DateTimeOffset.Now; - } + /// + /// Дата отчета + /// + public DateTimeOffset Date { get; set; } = DateTimeOffset.Now; } diff --git a/AsbCloudApp/Data/DrillTestReport/DrillTestReportInfoDto.cs b/AsbCloudApp/Data/DrillTestReport/DrillTestReportInfoDto.cs index 38730eef..18234a6a 100644 --- a/AsbCloudApp/Data/DrillTestReport/DrillTestReportInfoDto.cs +++ b/AsbCloudApp/Data/DrillTestReport/DrillTestReportInfoDto.cs @@ -1,29 +1,28 @@ using System; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data.DrillTestReport +namespace AsbCloudApp.Data.DrillTestReport; + +/// +/// Базовая информация о drill_test отчёте +/// +public class DrillTestReportInfoDto : ReportInfoDto { /// - /// Базовая информация о drill_test отчёте + /// Идентификатор отчета /// - public class DrillTestReportInfoDto : ReportInfoDto - { - /// - /// Идентификатор отчета - /// - [Required] - public int Id { get; set; } + [Required] + public int Id { get; set; } - /// - /// Проходка - /// - [Required] - public float DrillDepth { get; set; } + /// + /// Проходка + /// + [Required] + public float DrillDepth { get; set; } - /// - /// Дата и время - /// - [Required] - public DateTimeOffset DateTime { get; set; } - } + /// + /// Дата и время + /// + [Required] + public DateTimeOffset DateTime { get; set; } } diff --git a/AsbCloudApp/Data/DrillerDto.cs b/AsbCloudApp/Data/DrillerDto.cs index e920f111..1a11bd2a 100644 --- a/AsbCloudApp/Data/DrillerDto.cs +++ b/AsbCloudApp/Data/DrillerDto.cs @@ -1,33 +1,32 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Описание данных для бурильщика +/// +public class DrillerDto : IId { /// - /// Описание данных для бурильщика + /// Идентификатор в БД /// - public class DrillerDto : IId - { - /// - /// Идентификатор в БД - /// - [Required] - public int Id { get; set; } + [Required] + public int Id { get; set; } - /// - /// Имя - /// - [Required] - public string Name { get; set; } = null!; + /// + /// Имя + /// + [Required] + public string Name { get; set; } = null!; - /// - /// Фамилия - /// - [Required] - public string Surname { get; set; } = null!; + /// + /// Фамилия + /// + [Required] + public string Surname { get; set; } = null!; - /// - /// Отчество - /// - public string? Patronymic { get; set; } - } + /// + /// Отчество + /// + public string? Patronymic { get; set; } } diff --git a/AsbCloudApp/Data/DrillingProgramPartDto.cs b/AsbCloudApp/Data/DrillingProgramPartDto.cs index 0e9917ba..bd771fe6 100644 --- a/AsbCloudApp/Data/DrillingProgramPartDto.cs +++ b/AsbCloudApp/Data/DrillingProgramPartDto.cs @@ -3,60 +3,59 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using AsbCloudApp.Data.User; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Часть программы бурения +/// +public class DrillingProgramPartDto { /// - /// Часть программы бурения + /// Название /// - public class DrillingProgramPartDto - { - /// - /// Название - /// - [Required] - public string Name { get; set; } = string.Empty; + [Required] + public string Name { get; set; } = string.Empty; - /// - /// ИД категории файла - /// - [Required] - public int IdFileCategory { get; set; } + /// + /// ИД категории файла + /// + [Required] + public int IdFileCategory { get; set; } - /// - /// 0 - NoFile - /// 1 - approving - /// 2 - completely approved - /// - [Required] - public int IdState { get; set; } + /// + /// 0 - NoFile + /// 1 - approving + /// 2 - completely approved + /// + [Required] + public int IdState { get; set; } - /// - /// Публикаторы. Могут загружать файл этой категории - /// - [Required] - public IEnumerable Publishers { get; set; } = Enumerable.Empty(); + /// + /// Публикаторы. Могут загружать файл этой категории + /// + [Required] + public IEnumerable Publishers { get; set; } = Enumerable.Empty(); - /// - /// Согласованты. Могут согласовывать загруженные файлы этой категории - /// - [Required] - public IEnumerable Approvers { get; set; } = Enumerable.Empty(); + /// + /// Согласованты. Могут согласовывать загруженные файлы этой категории + /// + [Required] + public IEnumerable Approvers { get; set; } = Enumerable.Empty(); - /// - /// Разрешение для текущего пользователя согласовывать документ - /// - [Required] - public bool PermissionToApprove { get; set; } + /// + /// Разрешение для текущего пользователя согласовывать документ + /// + [Required] + public bool PermissionToApprove { get; set; } - /// - /// Разрешение для текущего пользователя загружать документ - /// - [Required] - public bool PermissionToUpload { get; set; } + /// + /// Разрешение для текущего пользователя загружать документ + /// + [Required] + public bool PermissionToUpload { get; set; } - /// - /// Ссылка на документ. - /// - public FileInfoDto? File { get; set; } - } + /// + /// Ссылка на документ. + /// + public FileInfoDto? File { get; set; } } diff --git a/AsbCloudApp/Data/DrillingProgramStateDto.cs b/AsbCloudApp/Data/DrillingProgramStateDto.cs index 4368f4a3..247877a6 100644 --- a/AsbCloudApp/Data/DrillingProgramStateDto.cs +++ b/AsbCloudApp/Data/DrillingProgramStateDto.cs @@ -2,60 +2,59 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO состояния формирования программы бурения +/// +public class DrillingProgramStateDto { /// - /// DTO состояния формирования программы бурения + /// 0 - не инициировано + /// 1 - загрузка и согласование + /// 2 - формируется (несколько минут) + /// 3 - готова /// - public class DrillingProgramStateDto - { - /// - /// 0 - не инициировано - /// 1 - загрузка и согласование - /// 2 - формируется (несколько минут) - /// 3 - готова - /// - [Required] - public int IdState { get; set; } - - /// - /// Ошибка при формировании - /// - public DrillingProgramCreateError? Error { get; set; } - - /// - /// Файл сформированной программы бурения - /// - public FileInfoDto? Program { get; set; } - - /// - /// Разрешение редактировать части программы бурения - /// - [Required] - public bool PermissionToEdit { get; set; } - - /// - /// Список частей программы бурения - /// - [Required] - public IEnumerable Parts { get; set; } = Enumerable.Empty(); - } + [Required] + public int IdState { get; set; } /// - /// DTO ошибки при создании программы бурения + /// Ошибка при формировании /// - public class DrillingProgramCreateError - { - /// - /// Текст ошибки для отображения пользователю - /// - [Required] - public string Message { get; set; } = string.Empty; + public DrillingProgramCreateError? Error { get; set; } - /// - /// Текст ошибки для разработчика - /// - [Required] - public string Exception { get; set; } = string.Empty; - } + /// + /// Файл сформированной программы бурения + /// + public FileInfoDto? Program { get; set; } + + /// + /// Разрешение редактировать части программы бурения + /// + [Required] + public bool PermissionToEdit { get; set; } + + /// + /// Список частей программы бурения + /// + [Required] + public IEnumerable Parts { get; set; } = Enumerable.Empty(); +} + +/// +/// DTO ошибки при создании программы бурения +/// +public class DrillingProgramCreateError +{ + /// + /// Текст ошибки для отображения пользователю + /// + [Required] + public string Message { get; set; } = string.Empty; + + /// + /// Текст ошибки для разработчика + /// + [Required] + public string Exception { get; set; } = string.Empty; } diff --git a/AsbCloudApp/Data/FaqDto.cs b/AsbCloudApp/Data/FaqDto.cs index 28cc829b..ace7c58b 100644 --- a/AsbCloudApp/Data/FaqDto.cs +++ b/AsbCloudApp/Data/FaqDto.cs @@ -1,73 +1,72 @@ using System; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO для faq-вопроса +/// +public class FaqDto : IId { /// - /// DTO для faq-вопроса + /// ключ вопроса /// - public class FaqDto : IId - { - /// - /// ключ вопроса - /// - [Required] - public int Id { get; set; } + [Required] + public int Id { get; set; } - /// - /// ключ автора вопроса - /// - public int? IdAuthorQuestion { get; set; } + /// + /// ключ автора вопроса + /// + public int? IdAuthorQuestion { get; set; } - /// - /// автор ответа - /// - public int? IdAuthorAnswer { get; set; } + /// + /// автор ответа + /// + public int? IdAuthorAnswer { get; set; } - /// - /// дата создания вопроса - /// - public DateTimeOffset? DateCreatedQuestion { get; set; } + /// + /// дата создания вопроса + /// + public DateTimeOffset? DateCreatedQuestion { get; set; } - /// - /// текст вопроса - /// - [Required] - public string Question { get; set; } = null!; + /// + /// текст вопроса + /// + [Required] + public string Question { get; set; } = null!; - /// - /// текст ответа - /// - public string? Answer { get; set; } + /// + /// текст ответа + /// + public string? Answer { get; set; } - /// - /// статус вопроса - /// - [Required] - public int State { get; set; } = 0; + /// + /// статус вопроса + /// + [Required] + public int State { get; set; } = 0; - /// - /// Счетчик повторений вопроса - /// - [Required] - public int CounterQuestion { get; set; } = 1; + /// + /// Счетчик повторений вопроса + /// + [Required] + public int CounterQuestion { get; set; } = 1; - /// - /// Частый вопрос - /// - [Required] - public bool IsFrequently { get; set; } = false; + /// + /// Частый вопрос + /// + [Required] + public bool IsFrequently { get; set; } = false; - /// - /// Автор вопроса - /// - [Required] - public string AurhorQuestionName { get; set; } = string.Empty; + /// + /// Автор вопроса + /// + [Required] + public string AurhorQuestionName { get; set; } = string.Empty; - /// - /// Автор ответа - /// - public string? AurhorAnswerName { get; set; } - } + /// + /// Автор ответа + /// + public string? AurhorAnswerName { get; set; } } diff --git a/AsbCloudApp/Data/FileCategoryDto.cs b/AsbCloudApp/Data/FileCategoryDto.cs index f55fdb30..372d6143 100644 --- a/AsbCloudApp/Data/FileCategoryDto.cs +++ b/AsbCloudApp/Data/FileCategoryDto.cs @@ -1,25 +1,24 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO категории файла +/// +public class FileCategoryDto : IId { + /// + [Required] + public int Id { get; set; } + /// - /// DTO категории файла + /// полное название /// - public class FileCategoryDto : IId - { - /// - [Required] - public int Id { get; set; } + [Required] + public string Name { get; set; } = null!; - /// - /// полное название - /// - [Required] - public string Name { get; set; } = null!; - - /// - /// сокращенное название - /// - public string ShortName { get; set; } = string.Empty; - } + /// + /// сокращенное название + /// + public string ShortName { get; set; } = string.Empty; } diff --git a/AsbCloudApp/Data/FileInfoDto.cs b/AsbCloudApp/Data/FileInfoDto.cs index 2e673ed0..e14a9cf1 100644 --- a/AsbCloudApp/Data/FileInfoDto.cs +++ b/AsbCloudApp/Data/FileInfoDto.cs @@ -4,68 +4,67 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using AsbCloudApp.Data.User; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO информации о файле. Используется для загрузки файла. +/// +public class FileInfoDto : IId, IWellRelated { + /// + [Required] + public int Id { get; set; } + + /// + [Required] + [Range(1, int.MaxValue, ErrorMessage = "Id скважины не может быть меньше 1")] + public int IdWell { get; set; } + /// - /// DTO информации о файле. Используется для загрузки файла. + /// id категории файла /// - public class FileInfoDto : IId, IWellRelated - { - /// - [Required] - public int Id { get; set; } + [Required] + [Range(1, int.MaxValue, ErrorMessage = "Id категории файла не может быть меньше 1")] + public int IdCategory { get; set; } - /// - [Required] - [Range(1, int.MaxValue, ErrorMessage = "Id скважины не может быть меньше 1")] - public int IdWell { get; set; } + /// + /// Id автора + /// + public int? IdAuthor { get; set; } - /// - /// id категории файла - /// - [Required] - [Range(1, int.MaxValue, ErrorMessage = "Id категории файла не может быть меньше 1")] - public int IdCategory { get; set; } + /// + /// имя файла + /// + [Required] + [StringLength(260, MinimumLength = 1, ErrorMessage = "Допустимое имя компании от 1 до 260 символов")] + public string Name { get; set; } = null!; - /// - /// Id автора - /// - public int? IdAuthor { get; set; } + /// + /// дата загрузки + /// + [Required] + public DateTimeOffset UploadDate { get; set; } - /// - /// имя файла - /// - [Required] - [StringLength(260, MinimumLength = 1, ErrorMessage = "Допустимое имя компании от 1 до 260 символов")] - public string Name { get; set; } = null!; + /// + /// размер в байтах + /// + [Required] + public long Size { get; set; } - /// - /// дата загрузки - /// - [Required] - public DateTimeOffset UploadDate { get; set; } + /// + /// Помечен как удаленный + /// + [Required] + public bool IsDeleted { get; set; } - /// - /// размер в байтах - /// - [Required] - public long Size { get; set; } + /// + /// DTO автора + /// + public UserDto? Author { get; set; } - /// - /// Помечен как удаленный - /// - [Required] - public bool IsDeleted { get; set; } - - /// - /// DTO автора - /// - public UserDto? Author { get; set; } - - /// - /// список отметок файла - /// - [Required] - public IEnumerable FileMarks { get; set; } = Enumerable.Empty(); - } + /// + /// список отметок файла + /// + [Required] + public IEnumerable FileMarks { get; set; } = Enumerable.Empty(); } diff --git a/AsbCloudApp/Data/FileMarkDto.cs b/AsbCloudApp/Data/FileMarkDto.cs index ad48f018..9c87bf4a 100644 --- a/AsbCloudApp/Data/FileMarkDto.cs +++ b/AsbCloudApp/Data/FileMarkDto.cs @@ -2,55 +2,54 @@ using System; using System.ComponentModel.DataAnnotations; using AsbCloudApp.Data.User; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Отметка для файла +/// +public class FileMarkDto: IId { + /// + [Required] + public int Id { get; set; } + /// - /// Отметка для файла + /// id файла /// - public class FileMarkDto: IId - { - /// - [Required] - public int Id { get; set; } + [Required] + [Range(1, int.MaxValue, ErrorMessage = "Id файла не может быть меньше 1")] + public int IdFile { get; set; } - /// - /// id файла - /// - [Required] - [Range(1, int.MaxValue, ErrorMessage = "Id файла не может быть меньше 1")] - public int IdFile { get; set; } + /// + /// 0 - отклонен + /// 1 - согласован + /// + [Required] + [Range(0, int.MaxValue, ErrorMessage = "Id категории действия с файлом не может быть меньше 1")] + public int IdMarkType { get; set; } - /// - /// 0 - отклонен - /// 1 - согласован - /// - [Required] - [Range(0, int.MaxValue, ErrorMessage = "Id категории действия с файлом не может быть меньше 1")] - public int IdMarkType { get; set; } + /// + /// дата/время добавления. + /// Необязательно указывать в запросе на создание. + /// + [Required] + public DateTimeOffset DateCreated { get; set; } - /// - /// дата/время добавления. - /// Необязательно указывать в запросе на создание. - /// - [Required] - public DateTimeOffset DateCreated { get; set; } + /// + /// Полезный комментарий + /// + [StringLength(4096, MinimumLength = 1, ErrorMessage = "Допустимое имя компании от 1 до 4096 символов")] + public string? Comment { get; set; } - /// - /// Полезный комментарий - /// - [StringLength(4096, MinimumLength = 1, ErrorMessage = "Допустимое имя компании от 1 до 4096 символов")] - public string? Comment { get; set; } + /// + /// признак удаления отметки + /// + [Required] + public bool IsDeleted { get; set; } - /// - /// признак удаления отметки - /// - [Required] - public bool IsDeleted { get; set; } - - /// - /// Пользователь создающий отметку. - /// Необязательно указывать в запросе на создание. - /// - public UserDto? User { get; set; } - } + /// + /// Пользователь создающий отметку. + /// Необязательно указывать в запросе на создание. + /// + public UserDto? User { get; set; } } \ No newline at end of file diff --git a/AsbCloudApp/Data/GTR/JsonValue.cs b/AsbCloudApp/Data/GTR/JsonValue.cs index 15df0604..0da94b98 100644 --- a/AsbCloudApp/Data/GTR/JsonValue.cs +++ b/AsbCloudApp/Data/GTR/JsonValue.cs @@ -1,14 +1,13 @@ -namespace AsbCloudApp.Data.GTR +namespace AsbCloudApp.Data.GTR; + +/// +/// Класс позволяющий хранить значение неопределенного типа. +/// Все возможные типы должны быть описаны в JsonValueJsonConverter. +/// +/// +public record JsonValue(object Value) { - /// - /// Класс позволяющий хранить значение неопределенного типа. - /// Все возможные типы должны быть описаны в JsonValueJsonConverter. - /// - /// - public record JsonValue(object Value) - { - /// - public override string ToString() - => Value.ToString() ?? string.Empty; - } + /// + public override string ToString() + => Value.ToString() ?? string.Empty; } diff --git a/AsbCloudApp/Data/GTR/WitsItemRecordDto.cs b/AsbCloudApp/Data/GTR/WitsItemRecordDto.cs index f6dfde81..e0011c01 100644 --- a/AsbCloudApp/Data/GTR/WitsItemRecordDto.cs +++ b/AsbCloudApp/Data/GTR/WitsItemRecordDto.cs @@ -1,35 +1,34 @@ using System; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data.GTR +namespace AsbCloudApp.Data.GTR; + +/// +/// Запись WITS +/// +public class WitsItemRecordDto { /// - /// Запись WITS + /// Record Id /// - public class WitsItemRecordDto - { - /// - /// Record Id - /// - [Required] - public int IdRecord { get; set; } + [Required] + public int IdRecord { get; set; } - /// - /// Item Id - /// - [Required] - public int IdItem { get; set; } + /// + /// Item Id + /// + [Required] + public int IdItem { get; set; } - /// - /// Дата создания записи - /// - [Required] - public DateTime Date { get; set; } + /// + /// Дата создания записи + /// + [Required] + public DateTime Date { get; set; } - /// - /// Значение - /// - [Required] - public JsonValue Value { get; set; } = default!; - } + /// + /// Значение + /// + [Required] + public JsonValue Value { get; set; } = default!; } \ No newline at end of file diff --git a/AsbCloudApp/Data/GTR/WitsRecordDto.cs b/AsbCloudApp/Data/GTR/WitsRecordDto.cs index e5469b9a..f41330d6 100644 --- a/AsbCloudApp/Data/GTR/WitsRecordDto.cs +++ b/AsbCloudApp/Data/GTR/WitsRecordDto.cs @@ -2,29 +2,28 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data.GTR +namespace AsbCloudApp.Data.GTR; + +/// +/// Запись WITS +/// +public class WitsRecordDto { /// - /// Запись WITS + /// Id записи /// - public class WitsRecordDto - { - /// - /// Id записи - /// - [Required] - public int Id { get; set; } + [Required] + public int Id { get; set; } - /// - /// Дата создания записи - /// - [Required] - public DateTime Date { get; set; } + /// + /// Дата создания записи + /// + [Required] + public DateTime Date { get; set; } - /// - /// Параметры. Ключ - id_item. ValueContainer содержит значение. - /// - [Required] - public Dictionary Items { get; set; } = new(); - } + /// + /// Параметры. Ключ - id_item. ValueContainer содержит значение. + /// + [Required] + public Dictionary Items { get; set; } = new(); } diff --git a/AsbCloudApp/Data/IId.cs b/AsbCloudApp/Data/IId.cs index 4449fa23..0788218a 100644 --- a/AsbCloudApp/Data/IId.cs +++ b/AsbCloudApp/Data/IId.cs @@ -1,13 +1,12 @@ -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Интерфейс данных с Id +/// +public interface IId { /// - /// Интерфейс данных с Id + /// Идентификатор БД /// - public interface IId - { - /// - /// Идентификатор БД - /// - public int Id { get; set; } - } + public int Id { get; set; } } diff --git a/AsbCloudApp/Data/IMapPoint.cs b/AsbCloudApp/Data/IMapPoint.cs index 1c373685..2f23d37b 100644 --- a/AsbCloudApp/Data/IMapPoint.cs +++ b/AsbCloudApp/Data/IMapPoint.cs @@ -1,23 +1,22 @@ -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// точка на карте +/// +public interface IMapPoint { /// - /// точка на карте + /// Широта /// - public interface IMapPoint - { - /// - /// Широта - /// - double? Latitude { get; set; } + double? Latitude { get; set; } - /// - /// Широта - /// - double? Longitude { get; set; } + /// + /// Широта + /// + double? Longitude { get; set; } - /// - /// Часовой пояс - /// - SimpleTimezoneDto Timezone { get; set; } - } + /// + /// Часовой пояс + /// + SimpleTimezoneDto Timezone { get; set; } } diff --git a/AsbCloudApp/Data/ITelemetryData.cs b/AsbCloudApp/Data/ITelemetryData.cs index a2dc4924..d3061294 100644 --- a/AsbCloudApp/Data/ITelemetryData.cs +++ b/AsbCloudApp/Data/ITelemetryData.cs @@ -1,26 +1,25 @@ using System; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Telemetry related dto +/// +public interface ITelemetryRelated { /// - /// Telemetry related dto + /// ИД телеметрии /// - public interface ITelemetryRelated - { - /// - /// ИД телеметрии - /// - int IdTelemetry { get; set; } - } - - /// - /// Интерфейс записи данных телеметрии - /// - public interface ITelemetryData : ITelemetryRelated - { - /// - /// Отметка времени для этой записи - /// - DateTime DateTime { get; set; } - } + int IdTelemetry { get; set; } +} + +/// +/// Интерфейс записи данных телеметрии +/// +public interface ITelemetryData : ITelemetryRelated +{ + /// + /// Отметка времени для этой записи + /// + DateTime DateTime { get; set; } } diff --git a/AsbCloudApp/Data/IWellRelated.cs b/AsbCloudApp/Data/IWellRelated.cs index 55877a9e..fc85e7dd 100644 --- a/AsbCloudApp/Data/IWellRelated.cs +++ b/AsbCloudApp/Data/IWellRelated.cs @@ -1,13 +1,12 @@ -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Well related DTO +/// +public interface IWellRelated { /// - /// Well related DTO + /// Well id in db /// - public interface IWellRelated - { - /// - /// Well id in db - /// - int IdWell { get; set; } - } + int IdWell { get; set; } } diff --git a/AsbCloudApp/Data/ItemInfoDto.cs b/AsbCloudApp/Data/ItemInfoDto.cs index 0022b1c1..fff4154e 100644 --- a/AsbCloudApp/Data/ItemInfoDto.cs +++ b/AsbCloudApp/Data/ItemInfoDto.cs @@ -1,26 +1,25 @@ using System; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// хранение дополнительной информации о записи +/// запись формируется на сервере автоматически +/// +public class ItemInfoDto { /// - /// хранение дополнительной информации о записи - /// запись формируется на сервере автоматически + /// пользователь, внесший изменения (запись формируется на сервере автоматически) /// - public class ItemInfoDto - { - /// - /// пользователь, внесший изменения (запись формируется на сервере автоматически) - /// - public int? IdUser { get; set; } + public int? IdUser { get; set; } - /// - /// имя пользователя, внесшего изменения (запись формируется на сервере автоматически) - /// - public string? UserName { get; set; } + /// + /// имя пользователя, внесшего изменения (запись формируется на сервере автоматически) + /// + public string? UserName { get; set; } - /// - /// дата последнего обновления (запись формируется на сервере автоматически) - /// - public DateTimeOffset? LastUpdateDate { get; set; } - } + /// + /// дата последнего обновления (запись формируется на сервере автоматически) + /// + public DateTimeOffset? LastUpdateDate { get; set; } } diff --git a/AsbCloudApp/Data/JobDto.cs b/AsbCloudApp/Data/JobDto.cs index 0dfb82e3..1f5a7967 100644 --- a/AsbCloudApp/Data/JobDto.cs +++ b/AsbCloudApp/Data/JobDto.cs @@ -1,56 +1,55 @@ using System.Collections; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Состояние фоновой задачи +/// +public enum JobState { /// - /// Состояние фоновой задачи + /// Ожидает в очереди на выполнение /// - public enum JobState - { - /// - /// Ожидает в очереди на выполнение - /// - Waiting, - /// - /// выполняется - /// - Working, - /// - /// успешно выполнена - /// - Done, - /// - /// завершена с ошибкой - /// - Fail - }; + Waiting, + /// + /// выполняется + /// + Working, + /// + /// успешно выполнена + /// + Done, + /// + /// завершена с ошибкой + /// + Fail +}; + +/// +/// работа фоновой задачи +/// +public class JobDto +{ + /// + /// идентификатор + /// + [Required] + public int Id { get; set; } /// - /// работа фоновой задачи + /// Состояние /// - public class JobDto - { - /// - /// идентификатор - /// - [Required] - public int Id { get; set; } + [Required] + public JobState State { get; set; } - /// - /// Состояние - /// - [Required] - public JobState State { get; set; } + /// + /// результат выполнения + /// + public Hashtable? Results { get; set; } - /// - /// результат выполнения - /// - public Hashtable? Results { get; set; } - - /// - /// Исключение, если возникла ошибка - /// - public string? Error { get; set; } - } + /// + /// Исключение, если возникла ошибка + /// + public string? Error { get; set; } } diff --git a/AsbCloudApp/Data/LimitingParameterDataDto.cs b/AsbCloudApp/Data/LimitingParameterDataDto.cs index 11ecde24..cc1a9dec 100644 --- a/AsbCloudApp/Data/LimitingParameterDataDto.cs +++ b/AsbCloudApp/Data/LimitingParameterDataDto.cs @@ -1,45 +1,44 @@ using System; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Статистика по ограничивающим параметрам +/// +public class LimitingParameterDataDto { /// - /// Статистика по ограничивающим параметрам + /// Идентификатор скважины /// - public class LimitingParameterDataDto - { - /// - /// Идентификатор скважины - /// - public int IdWell { get; set; } + public int IdWell { get; set; } - /// - /// Идентификатор телеметрии - /// - public int IdTelemetry { get; set; } + /// + /// Идентификатор телеметрии + /// + public int IdTelemetry { get; set; } - /// - /// Дата начала ограничения - /// - public DateTimeOffset DateStart { get; set; } + /// + /// Дата начала ограничения + /// + public DateTimeOffset DateStart { get; set; } - /// - /// Дата окончания ограничения - /// - public DateTimeOffset DateEnd { get; set; } + /// + /// Дата окончания ограничения + /// + public DateTimeOffset DateEnd { get; set; } - /// - /// Глубина начала ограничения - /// - public float DepthStart { get; set; } + /// + /// Глубина начала ограничения + /// + public float DepthStart { get; set; } - /// - /// Глубина окончания ограничения - /// - public float DepthEnd { get; set; } + /// + /// Глубина окончания ограничения + /// + public float DepthEnd { get; set; } - /// - /// Идентификатор ограничения - /// - public short IdFeedRegulator { get; set; } - } + /// + /// Идентификатор ограничения + /// + public short IdFeedRegulator { get; set; } } diff --git a/AsbCloudApp/Data/LimitingParameterDto.cs b/AsbCloudApp/Data/LimitingParameterDto.cs index 13a23b80..a4883f41 100644 --- a/AsbCloudApp/Data/LimitingParameterDto.cs +++ b/AsbCloudApp/Data/LimitingParameterDto.cs @@ -1,71 +1,70 @@ using System; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Статистика по ограничивающим параметрам +/// +public class LimitingParameterDto { /// - /// Статистика по ограничивающим параметрам + /// Нет ограничения /// - public class LimitingParameterDto - { - /// - /// Нет ограничения - /// - public const int NoLimit = 0; + public const int NoLimit = 0; - /// - /// МСП - /// - public const int RopPlan = 1; + /// + /// МСП + /// + public const int RopPlan = 1; - /// - /// Давление - /// - public const int Pressure = 2; + /// + /// Давление + /// + public const int Pressure = 2; - /// - /// Осевая нагрузка - /// - public const int AxialLoad = 3; + /// + /// Осевая нагрузка + /// + public const int AxialLoad = 3; - /// - /// Момент - /// - public const int RotorTorque = 4; - /// - /// Идентификатор скважины - /// - [Required] - public int IdWell { get; set; } + /// + /// Момент + /// + public const int RotorTorque = 4; + /// + /// Идентификатор скважины + /// + [Required] + public int IdWell { get; set; } - /// - /// Время бурения - /// - [Required] - public float TotalMinutes { get; set; } + /// + /// Время бурения + /// + [Required] + public float TotalMinutes { get; set; } - /// - /// Глубина бурения - /// - [Required] - public float Depth { get; set; } + /// + /// Глубина бурения + /// + [Required] + public float Depth { get; set; } - /// - /// Идентификатор критерия бурения - /// - [Required] - public short IdFeedRegulator { get; set; } + /// + /// Идентификатор критерия бурения + /// + [Required] + public short IdFeedRegulator { get; set; } - /// - /// Наименование критерия бурения - /// - [Required] - public string NameFeedRegulator { get; set; } = string.Empty; + /// + /// Наименование критерия бурения + /// + [Required] + public string NameFeedRegulator { get; set; } = string.Empty; - /// - /// Количество включений - /// - [Required] - public int NumberInclusions { get; set; } - } + /// + /// Количество включений + /// + [Required] + public int NumberInclusions { get; set; } } diff --git a/AsbCloudApp/Data/MapPointBaseDto.cs b/AsbCloudApp/Data/MapPointBaseDto.cs index 61713a8f..1a1ae0bf 100644 --- a/AsbCloudApp/Data/MapPointBaseDto.cs +++ b/AsbCloudApp/Data/MapPointBaseDto.cs @@ -1,30 +1,29 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Точка на карте с названием +/// +public class MapPointBaseDto : IMapPoint, IId { + /// + public int Id { get; set; } + /// - /// Точка на карте с названием + /// Название /// - public class MapPointBaseDto : IMapPoint, IId - { - /// - public int Id { get; set; } + [StringLength(50, MinimumLength = 1, ErrorMessage = "Допустимая длина названия от 1 до 50 символов")] + public string Caption { get; set; } = null!; - /// - /// Название - /// - [StringLength(50, MinimumLength = 1, ErrorMessage = "Допустимая длина названия от 1 до 50 символов")] - public string Caption { get; set; } = null!; + /// + [Range(-90, 90, ErrorMessage = "Допустимые значения широты от -90 до 90")] + public double? Latitude { get; set; } - /// - [Range(-90, 90, ErrorMessage = "Допустимые значения широты от -90 до 90")] - public double? Latitude { get; set; } + /// + [Range(-180, 180, ErrorMessage = "Допустимые значения долготы от -180 до 180")] + public double? Longitude { get; set; } - /// - [Range(-180, 180, ErrorMessage = "Допустимые значения долготы от -180 до 180")] - public double? Longitude { get; set; } - - /// - public SimpleTimezoneDto Timezone { get; set; } = null!; - } + /// + public SimpleTimezoneDto Timezone { get; set; } = null!; } diff --git a/AsbCloudApp/Data/MeasureDto.cs b/AsbCloudApp/Data/MeasureDto.cs index 17ba3968..ee154d69 100644 --- a/AsbCloudApp/Data/MeasureDto.cs +++ b/AsbCloudApp/Data/MeasureDto.cs @@ -2,46 +2,45 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// инфо о результатах замера +/// +public class MeasureDto : IId, IWellRelated { + /// + [Required] + public int Id { get; set; } + + /// + [Required] + [Range(1, int.MaxValue, ErrorMessage = "Id скважины не может быть меньше 1")] + public int IdWell { get; set; } + /// - /// инфо о результатах замера + /// Id категории замера /// - public class MeasureDto : IId, IWellRelated - { - /// - [Required] - public int Id { get; set; } + [Required] + [Range(1, int.MaxValue, ErrorMessage = "Id категории не может быть меньше 1")] + public int IdCategory { get; set; } - /// - [Required] - [Range(1, int.MaxValue, ErrorMessage = "Id скважины не может быть меньше 1")] - public int IdWell { get; set; } + /// + /// название категории замера + /// + [Required] + [StringLength(120, MinimumLength = 1, ErrorMessage = "Название категории не может быть больше 120 символов")] + public string CategoryName { get; set; } = string.Empty; - /// - /// Id категории замера - /// - [Required] - [Range(1, int.MaxValue, ErrorMessage = "Id категории не может быть меньше 1")] - public int IdCategory { get; set; } + /// + /// отметка времени замера + /// + [Required] + public DateTimeOffset Timestamp { get; set; } - /// - /// название категории замера - /// - [Required] - [StringLength(120, MinimumLength = 1, ErrorMessage = "Название категории не может быть больше 120 символов")] - public string CategoryName { get; set; } = string.Empty; - - /// - /// отметка времени замера - /// - [Required] - public DateTimeOffset Timestamp { get; set; } - - /// - /// данные замера - /// - [Required] - public Dictionary Data { get; set; } = new(); - } + /// + /// данные замера + /// + [Required] + public Dictionary Data { get; set; } = new(); } diff --git a/AsbCloudApp/Data/MessageDto.cs b/AsbCloudApp/Data/MessageDto.cs index 5272e237..097f8161 100644 --- a/AsbCloudApp/Data/MessageDto.cs +++ b/AsbCloudApp/Data/MessageDto.cs @@ -1,47 +1,46 @@ using System; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Сообщение для frontend +/// +public class MessageDto : IId { + /// + [Required] + public int Id { get; set; } + /// - /// Сообщение для frontend + /// дата появления события /// - public class MessageDto : IId - { - /// - [Required] - public int Id { get; set; } + [Required] + public DateTimeOffset DateTime { get; set; } - /// - /// дата появления события - /// - [Required] - public DateTimeOffset DateTime { get; set; } + /// + /// категория события + /// + [Required] + [Range(1, int.MaxValue, ErrorMessage = "Id категории не может быть ниже 1")] + public int CategoryId { get; set; } - /// - /// категория события - /// - [Required] - [Range(1, int.MaxValue, ErrorMessage = "Id категории не может быть ниже 1")] - public int CategoryId { get; set; } + /// + /// глубина забоя, при котором событие возникло + /// + [Required] + [Range(-1, int.MaxValue, ErrorMessage = "Id скважины не может быть ниже 1")] + public double WellDepth { get; set; } - /// - /// глубина забоя, при котором событие возникло - /// - [Required] - [Range(-1, int.MaxValue, ErrorMessage = "Id скважины не может быть ниже 1")] - public double WellDepth { get; set; } + /// + /// пользователь панели оператора + /// + public string? User { get; set; } - /// - /// пользователь панели оператора - /// - public string? User { get; set; } - - /// - /// текст сообщения - /// - [Required] - [StringLength(400, MinimumLength = 1, ErrorMessage = "Допустимая длина текста сообщения от 1 до 400 символов")] - public string Message { get; set; } = string.Empty; - } + /// + /// текст сообщения + /// + [Required] + [StringLength(400, MinimumLength = 1, ErrorMessage = "Допустимая длина текста сообщения от 1 до 400 символов")] + public string Message { get; set; } = string.Empty; } diff --git a/AsbCloudApp/Data/MinMaxDto.cs b/AsbCloudApp/Data/MinMaxDto.cs index d7d8703a..d8501b49 100644 --- a/AsbCloudApp/Data/MinMaxDto.cs +++ b/AsbCloudApp/Data/MinMaxDto.cs @@ -1,18 +1,17 @@ -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Минимальное и максимальное значение +/// +public class MinMaxDto { /// - /// Минимальное и максимальное значение + /// Минимальное значение /// - public class MinMaxDto - { - /// - /// Минимальное значение - /// - public T? Min { get; set; } + public T? Min { get; set; } - /// - /// Максимальное значение - /// - public T? Max { get; set; } - } + /// + /// Максимальное значение + /// + public T? Max { get; set; } } diff --git a/AsbCloudApp/Data/MinMaxExtendedViewDto.cs b/AsbCloudApp/Data/MinMaxExtendedViewDto.cs index 6e1aab48..5e7f27ce 100644 --- a/AsbCloudApp/Data/MinMaxExtendedViewDto.cs +++ b/AsbCloudApp/Data/MinMaxExtendedViewDto.cs @@ -1,23 +1,22 @@ -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Расширение для класса MinMaxDto +/// +public class MinMaxExtendedViewDto : MinMaxDto { /// - /// Расширение для класса MinMaxDto + /// Среднее значение /// - public class MinMaxExtendedViewDto : MinMaxDto - { - /// - /// Среднее значение - /// - public double Avg { get; set; } + public double Avg { get; set; } - /// - /// Является максимальным - /// - public bool IsMax { get; set; } + /// + /// Является максимальным + /// + public bool IsMax { get; set; } - /// - /// Является минимальным - /// - public bool IsMin { get; set; } - } + /// + /// Является минимальным + /// + public bool IsMin { get; set; } } diff --git a/AsbCloudApp/Data/OperationValueDto.cs b/AsbCloudApp/Data/OperationValueDto.cs index 587b8e1c..9b94b0c8 100644 --- a/AsbCloudApp/Data/OperationValueDto.cs +++ b/AsbCloudApp/Data/OperationValueDto.cs @@ -1,53 +1,52 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Описание целевых/нормативных показателей операций +/// +public class OperationValueDto : IId, IWellRelated { /// - /// Описание целевых/нормативных показателей операций + /// Идентификатор в БД /// - public class OperationValueDto : IId, IWellRelated - { - /// - /// Идентификатор в БД - /// - [Required] - public int Id { get; set; } + [Required] + public int Id { get; set; } - /// - /// Идентификатор скважины - /// - [Required] - public int IdWell { get; set; } + /// + /// Идентификатор скважины + /// + [Required] + public int IdWell { get; set; } - /// - /// Идентификатор категории операции - /// - [Required] - public int IdOperationCategory { get; set; } + /// + /// Идентификатор категории операции + /// + [Required] + public int IdOperationCategory { get; set; } - /// - /// Целевой показатель - /// - [Required] - public double TargetValue { get; set; } + /// + /// Целевой показатель + /// + [Required] + public double TargetValue { get; set; } - /// - /// Нормативный показатель - /// - [Required] - public double StandardValue { get; set; } + /// + /// Нормативный показатель + /// + [Required] + public double StandardValue { get; set; } - /// - /// Стартовая глубина - /// - [Required] - public double DepthStart { get; set; } + /// + /// Стартовая глубина + /// + [Required] + public double DepthStart { get; set; } - /// - /// Конечная глубина - /// - [Required] - public double DepthEnd { get; set; } + /// + /// Конечная глубина + /// + [Required] + public double DepthEnd { get; set; } - } } diff --git a/AsbCloudApp/Data/PaginationContainer.cs b/AsbCloudApp/Data/PaginationContainer.cs index 30d3bdec..d5a03b22 100644 --- a/AsbCloudApp/Data/PaginationContainer.cs +++ b/AsbCloudApp/Data/PaginationContainer.cs @@ -1,40 +1,39 @@ using System.Collections.Generic; using System.Linq; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Контейнер для поддержки постраничного просмотра таблиц +/// +/// +public class PaginationContainer { /// - /// Контейнер для поддержки постраничного просмотра таблиц + /// конструктор /// - /// - public class PaginationContainer + public PaginationContainer() { - /// - /// конструктор - /// - public PaginationContainer() - { - Items = Enumerable.Empty(); - } - - /// - /// Кол-во записей пропущенных с начала таблицы в запросе от api - /// - public int Skip { get; set; } - - /// - /// Кол-во записей в запросе от api - /// - public int Take { get; set; } - - /// - /// Кол-во записей всего в таблице - /// - public int Count { get; set; } - - /// - /// Данные - /// - public IEnumerable Items { get; set; } + Items = Enumerable.Empty(); } + + /// + /// Кол-во записей пропущенных с начала таблицы в запросе от api + /// + public int Skip { get; set; } + + /// + /// Кол-во записей в запросе от api + /// + public int Take { get; set; } + + /// + /// Кол-во записей всего в таблице + /// + public int Count { get; set; } + + /// + /// Данные + /// + public IEnumerable Items { get; set; } } diff --git a/AsbCloudApp/Data/PermissionDto.cs b/AsbCloudApp/Data/PermissionDto.cs index 8436ae73..db3ecc6b 100644 --- a/AsbCloudApp/Data/PermissionDto.cs +++ b/AsbCloudApp/Data/PermissionDto.cs @@ -1,28 +1,27 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Разрешение для группы пользователей сделать что-либо через web-api.
+/// применяется как возможность доступа к Endpoint.
+///
+public class PermissionDto : IId { + /// + [Required] + public int Id { get; set; } + /// - /// Разрешение для группы пользователей сделать что-либо через web-api.
- /// применяется как возможность доступа к Endpoint.
+ /// Название ///
- public class PermissionDto : IId - { - /// - [Required] - public int Id { get; set; } + [Required] + [StringLength(50, MinimumLength = 1, ErrorMessage = "Допустимая длина названия разрешения от 1 до 50 символов")] + public string Name { get; set; } = string.Empty; - /// - /// Название - /// - [Required] - [StringLength(50, MinimumLength = 1, ErrorMessage = "Допустимая длина названия разрешения от 1 до 50 символов")] - public string Name { get; set; } = string.Empty; - - /// - /// Описание - /// - [StringLength(1024, MinimumLength = 1, ErrorMessage = "Допустимая длина описания от 1 до 1024 символов")] - public string? Description { get; set; } - } + /// + /// Описание + /// + [StringLength(1024, MinimumLength = 1, ErrorMessage = "Допустимая длина описания от 1 до 1024 символов")] + public string? Description { get; set; } } \ No newline at end of file diff --git a/AsbCloudApp/Data/PlanFactDto.cs b/AsbCloudApp/Data/PlanFactDto.cs index 8d20c382..d676e429 100644 --- a/AsbCloudApp/Data/PlanFactDto.cs +++ b/AsbCloudApp/Data/PlanFactDto.cs @@ -1,29 +1,28 @@ -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO объединяющее плановые и фактические значения +/// +/// +public class PlanFactDto : PlanFactBase +{ + +} + +/// +/// DTO объединяющее плановые и фактические значения +/// +/// +/// +public class PlanFactBase { /// - /// DTO объединяющее плановые и фактические значения + /// Плановое значение /// - /// - public class PlanFactDto : PlanFactBase - { - - } + public T? Plan { get; set; } /// - /// DTO объединяющее плановые и фактические значения + /// Фактическое значение /// - /// - /// - public class PlanFactBase - { - /// - /// Плановое значение - /// - public T? Plan { get; set; } - - /// - /// Фактическое значение - /// - public V? Fact { get; set; } - } + public V? Fact { get; set; } } diff --git a/AsbCloudApp/Data/PlanFactPredictBase.cs b/AsbCloudApp/Data/PlanFactPredictBase.cs index ffbd5e61..6f4e1598 100644 --- a/AsbCloudApp/Data/PlanFactPredictBase.cs +++ b/AsbCloudApp/Data/PlanFactPredictBase.cs @@ -1,23 +1,22 @@ -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Lines container for Time Vs Depth chart +/// +public class PlanFactPredictBase { /// - /// Lines container for Time Vs Depth chart + /// плановое значение /// - public class PlanFactPredictBase - { - /// - /// плановое значение - /// - public T? Plan { get; set; } + public T? Plan { get; set; } - /// - /// фактическое значение - /// - public T? Fact { get; set; } + /// + /// фактическое значение + /// + public T? Fact { get; set; } - /// - /// предсказанное значение - /// - public T? Predict { get; set; } - } + /// + /// предсказанное значение + /// + public T? Predict { get; set; } } diff --git a/AsbCloudApp/Data/PlanLimitDto.cs b/AsbCloudApp/Data/PlanLimitDto.cs index 76e9173b..7566ab9c 100644 --- a/AsbCloudApp/Data/PlanLimitDto.cs +++ b/AsbCloudApp/Data/PlanLimitDto.cs @@ -2,85 +2,84 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Плановое значение и максимально допустимое ограничение +/// +public class PlanLimitDto { /// - /// Плановое значение и максимально допустимое ограничение + /// План /// - public class PlanLimitDto + [Required] + public double Plan { get; set; } + + /// + /// Максимальное ограничение + /// + [Required] + public double LimitMax { get; set; } + + /// + /// Валидация + /// + /// Общий диапазон для плана и ограничения + /// + /// + public virtual IEnumerable Validate((double GE, double LE) commonRange, string paramName) + => Validate(commonRange, commonRange, paramName); + + /// + /// Валидация + /// + /// + /// + /// Название параметра для которого задается план и ограничение + /// + public virtual IEnumerable Validate((double GE, double LE) planRange, (double GE, double LE) limitMaxRange, string paramName) { - /// - /// План - /// - [Required] - public double Plan { get; set; } + if (Plan < planRange.GE || Plan > planRange.LE) + yield return new ValidationResult($"{paramName} плановое значение должно быть в диапазоне [{planRange.GE}; {planRange.LE}]."); - /// - /// Максимальное ограничение - /// - [Required] - public double LimitMax { get; set; } - - /// - /// Валидация - /// - /// Общий диапазон для плана и ограничения - /// - /// - public virtual IEnumerable Validate((double GE, double LE) commonRange, string paramName) - => Validate(commonRange, commonRange, paramName); - - /// - /// Валидация - /// - /// - /// - /// Название параметра для которого задается план и ограничение - /// - public virtual IEnumerable Validate((double GE, double LE) planRange, (double GE, double LE) limitMaxRange, string paramName) - { - if (Plan < planRange.GE || Plan > planRange.LE) - yield return new ValidationResult($"{paramName} плановое значение должно быть в диапазоне [{planRange.GE}; {planRange.LE}]."); - - if (Plan < planRange.GE || Plan > planRange.LE) - yield return new ValidationResult($"{paramName} ограничивающее значение должно быть в диапазоне [{limitMaxRange.GE}; {limitMaxRange.LE}]."); - } + if (Plan < planRange.GE || Plan > planRange.LE) + yield return new ValidationResult($"{paramName} ограничивающее значение должно быть в диапазоне [{limitMaxRange.GE}; {limitMaxRange.LE}]."); } +} + +/// +/// Реализация RangeAttribute для PlanLimitDto +/// +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, +AllowMultiple = false)] +public class RangePlanLimitAttribute : ValidationAttribute +{ + private readonly double minimum; + private readonly double maximum; /// /// Реализация RangeAttribute для PlanLimitDto /// - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, - AllowMultiple = false)] - public class RangePlanLimitAttribute : ValidationAttribute + /// + /// + public RangePlanLimitAttribute(double minimum, double maximum) { - private readonly double minimum; - private readonly double maximum; + this.minimum = minimum; + this.maximum = maximum; + } - /// - /// Реализация RangeAttribute для PlanLimitDto - /// - /// - /// - public RangePlanLimitAttribute(double minimum, double maximum) + /// + public override bool IsValid(object? value) + { + try { - this.minimum = minimum; - this.maximum = maximum; - } - - /// - public override bool IsValid(object? value) - { - try + if(value is PlanLimitDto dto) { - if(value is PlanLimitDto dto) - { - var isPlanValid = dto.Plan <= maximum && dto.Plan >= minimum; - var isLimitMaxValid = dto.LimitMax <= maximum && dto.LimitMax >= minimum; - return isPlanValid && isLimitMaxValid; - } - }catch{} - return false; - } + var isPlanValid = dto.Plan <= maximum && dto.Plan >= minimum; + var isLimitMaxValid = dto.LimitMax <= maximum && dto.LimitMax >= minimum; + return isPlanValid && isLimitMaxValid; + } + }catch{} + return false; } } diff --git a/AsbCloudApp/Data/ReportInfoDto.cs b/AsbCloudApp/Data/ReportInfoDto.cs index 277d0eaa..c044deb8 100644 --- a/AsbCloudApp/Data/ReportInfoDto.cs +++ b/AsbCloudApp/Data/ReportInfoDto.cs @@ -1,18 +1,17 @@ -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Справочная информация об отчете +/// +public class ReportInfoDto { /// - /// Справочная информация об отчете + /// Название файла /// - public class ReportInfoDto - { - /// - /// Название файла - /// - public string FileName { get; set; } = null!; + public string FileName { get; set; } = null!; - /// - /// Размер файла - /// - public int FileSize { get; set; } = 0; - } + /// + /// Размер файла + /// + public int FileSize { get; set; } = 0; } diff --git a/AsbCloudApp/Data/ReportPropertiesDto.cs b/AsbCloudApp/Data/ReportPropertiesDto.cs index dc024620..e4a73953 100644 --- a/AsbCloudApp/Data/ReportPropertiesDto.cs +++ b/AsbCloudApp/Data/ReportPropertiesDto.cs @@ -1,54 +1,53 @@ using System; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO формирования рапорта +/// +public class ReportPropertiesDto : IId, IWellRelated { + /// + public int Id { get; set; } + + /// + [Range(1, int.MaxValue, ErrorMessage = "Id скважины не может быть ниже 1")] + public int IdWell { get; set; } + /// - /// DTO формирования рапорта + /// название /// - public class ReportPropertiesDto : IId, IWellRelated - { - /// - public int Id { get; set; } + [StringLength(260, MinimumLength = 1, ErrorMessage = "Допустимая длина имени файла от 1 до 260 символов")] + public string Name { get; set; } = null!; - /// - [Range(1, int.MaxValue, ErrorMessage = "Id скважины не может быть ниже 1")] - public int IdWell { get; set; } + /// + /// + /// + public FileInfoDto File { get; set; } = null!; - /// - /// название - /// - [StringLength(260, MinimumLength = 1, ErrorMessage = "Допустимая длина имени файла от 1 до 260 символов")] - public string Name { get; set; } = null!; + /// + /// Дата формирования + /// + public DateTimeOffset Date { get; set; } - /// - /// - /// - public FileInfoDto File { get; set; } = null!; + /// + /// Дата начала рапорта + /// + public DateTimeOffset Begin { get; set; } - /// - /// Дата формирования - /// - public DateTimeOffset Date { get; set; } + /// + /// Дата окончания рапорта + /// + public DateTimeOffset End { get; set; } - /// - /// Дата начала рапорта - /// - public DateTimeOffset Begin { get; set; } + /// + /// шаг между точками диаграммы + /// + public int Step { get; set; } - /// - /// Дата окончания рапорта - /// - public DateTimeOffset End { get; set; } - - /// - /// шаг между точками диаграммы - /// - public int Step { get; set; } - - /// - /// формат файла - /// - public string Format { get; set; } = string.Empty; - } + /// + /// формат файла + /// + public string Format { get; set; } = string.Empty; } diff --git a/AsbCloudApp/Data/RequestLogDto.cs b/AsbCloudApp/Data/RequestLogDto.cs index e326043f..2a6d9aee 100644 --- a/AsbCloudApp/Data/RequestLogDto.cs +++ b/AsbCloudApp/Data/RequestLogDto.cs @@ -1,70 +1,69 @@ using System; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO журнала запросов +/// +public class RequestLogDto { /// - /// DTO журнала запросов + /// логин пользователя /// - public class RequestLogDto - { - /// - /// логин пользователя - /// - public string UserLogin { get; set; } = string.Empty; + public string UserLogin { get; set; } = string.Empty; - /// - /// Id пользователя - /// - public int UserId { get; set; } + /// + /// Id пользователя + /// + public int UserId { get; set; } - /// - /// IP адрес пользователя - /// - public string? UserIp { get; set; } + /// + /// IP адрес пользователя + /// + public string? UserIp { get; set; } - /// - /// метод запроса (GET, POST,..) - /// - public string RequestMethod { get; set; } = null!; + /// + /// метод запроса (GET, POST,..) + /// + public string RequestMethod { get; set; } = null!; - /// - /// url - /// - public string? RequestPath { get; set; } + /// + /// url + /// + public string? RequestPath { get; set; } - /// - /// Referer - /// - public string Referer { get; set; } = string.Empty; + /// + /// Referer + /// + public string Referer { get; set; } = string.Empty; - /// - /// продолжительность выполнения - /// - public long ElapsedMilliseconds { get; set; } + /// + /// продолжительность выполнения + /// + public long ElapsedMilliseconds { get; set; } - /// - /// http status [200 - Ok, ...] - /// - public int Status { get; set; } - - /// - /// метка времени запроса - /// - public DateTime Date { get; set; } + /// + /// http status [200 - Ok, ...] + /// + public int Status { get; set; } + + /// + /// метка времени запроса + /// + public DateTime Date { get; set; } - /// - /// сообщение об ошибке, если она произошла - /// - public string? ExceptionMessage { get; set; } = null!; + /// + /// сообщение об ошибке, если она произошла + /// + public string? ExceptionMessage { get; set; } = null!; - /// - /// стек вызовов - /// - public string? ExceptionStack { get; set; } = null!; + /// + /// стек вызовов + /// + public string? ExceptionStack { get; set; } = null!; - /// - /// Размер body - /// - public long? RequestContentLength { get; set; } - } + /// + /// Размер body + /// + public long? RequestContentLength { get; set; } } \ No newline at end of file diff --git a/AsbCloudApp/Data/RequestLogUserDto.cs b/AsbCloudApp/Data/RequestLogUserDto.cs index 562acc36..796cb408 100644 --- a/AsbCloudApp/Data/RequestLogUserDto.cs +++ b/AsbCloudApp/Data/RequestLogUserDto.cs @@ -2,58 +2,57 @@ using System; using System.ComponentModel.DataAnnotations; using AsbCloudApp.Data.User; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO статистики запросов по пользователю +/// +public class RequestLogUserDto { /// - /// DTO статистики запросов по пользователю + /// Id пользователя /// - public class RequestLogUserDto - { - /// - /// Id пользователя - /// - [Required] - public int UserId { get; set; } + [Required] + public int UserId { get; set; } - /// - /// логин - /// - [Required] - public string Login { get; set; } = string.Empty; + /// + /// логин + /// + [Required] + public string Login { get; set; } = string.Empty; - /// - /// IP адрес пользователя - /// - public string? Ip { get; set; } + /// + /// IP адрес пользователя + /// + public string? Ip { get; set; } - /// - /// время выполнения запроса - /// - [Required] - public long ElapsedMs { get; set; } + /// + /// время выполнения запроса + /// + [Required] + public long ElapsedMs { get; set; } - /// - /// метка времени последнего запроса - /// - [Required] - public DateTime LastDate { get; set; } + /// + /// метка времени последнего запроса + /// + [Required] + public DateTime LastDate { get; set; } - /// - /// кол-во запросов - /// - [Required] - public long Requests { get; set; } + /// + /// кол-во запросов + /// + [Required] + public long Requests { get; set; } - /// - /// кол-во ошибок - /// - [Required] - public long Errors { get; set; } + /// + /// кол-во ошибок + /// + [Required] + public long Errors { get; set; } - /// - /// DTO пользователя - /// - [Required] - public UserDto User { get; set; } = null!; - } + /// + /// DTO пользователя + /// + [Required] + public UserDto User { get; set; } = null!; } diff --git a/AsbCloudApp/Data/SAUB/DrillTestBaseDto.cs b/AsbCloudApp/Data/SAUB/DrillTestBaseDto.cs index 1a87d73a..1c58bc5d 100644 --- a/AsbCloudApp/Data/SAUB/DrillTestBaseDto.cs +++ b/AsbCloudApp/Data/SAUB/DrillTestBaseDto.cs @@ -3,35 +3,34 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -namespace AsbCloudApp.Data.SAUB +namespace AsbCloudApp.Data.SAUB; + +/// +/// DTO для получения записи drill_test из панели +/// +public class DrillTestBaseDto { /// - /// DTO для получения записи drill_test из панели + /// Идентификатор drill test /// - public class DrillTestBaseDto - { - /// - /// Идентификатор drill test - /// - [Required] - public int Id { get; set; } + [Required] + public int Id { get; set; } - /// - /// Время начала drill test - /// - [Required] - public DateTimeOffset TimeStampStart { get; set; } + /// + /// Время начала drill test + /// + [Required] + public DateTimeOffset TimeStampStart { get; set; } - /// - /// Глубина начала drill test - /// - [Required] - public float DepthStart { get; set; } + /// + /// Глубина начала drill test + /// + [Required] + public float DepthStart { get; set; } - /// - /// Параметры теста - /// - [Required] - public IEnumerable Params { get; set; } = Enumerable.Empty(); - } + /// + /// Параметры теста + /// + [Required] + public IEnumerable Params { get; set; } = Enumerable.Empty(); } diff --git a/AsbCloudApp/Data/SAUB/DrillTestDto.cs b/AsbCloudApp/Data/SAUB/DrillTestDto.cs index 32814d35..a050943f 100644 --- a/AsbCloudApp/Data/SAUB/DrillTestDto.cs +++ b/AsbCloudApp/Data/SAUB/DrillTestDto.cs @@ -1,15 +1,14 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data.SAUB +namespace AsbCloudApp.Data.SAUB; + +/// +/// DTO для отображения записи drill_test +/// +public class DrillTestDto : DrillTestBaseDto { /// - /// DTO для отображения записи drill_test + /// Связанная с drill_test телеметрия /// - public class DrillTestDto : DrillTestBaseDto - { - /// - /// Связанная с drill_test телеметрия - /// - public TelemetryDto? Telemetry { get; set; } - } + public TelemetryDto? Telemetry { get; set; } } diff --git a/AsbCloudApp/Data/SAUB/DrillTestParamsDto.cs b/AsbCloudApp/Data/SAUB/DrillTestParamsDto.cs index adc3d1db..aa94178e 100644 --- a/AsbCloudApp/Data/SAUB/DrillTestParamsDto.cs +++ b/AsbCloudApp/Data/SAUB/DrillTestParamsDto.cs @@ -1,41 +1,40 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data.SAUB +namespace AsbCloudApp.Data.SAUB; + +/// +/// Параметры Drill Test +/// +public class DrillTestParamsDto { /// - /// Параметры Drill Test + /// Шаг /// - public class DrillTestParamsDto - { - /// - /// Шаг - /// - [Required] - public int Step { get; set; } + [Required] + public int Step { get; set; } - /// - /// Нагрузка - /// - public float? Workload { get; set; } + /// + /// Нагрузка + /// + public float? Workload { get; set; } - /// - /// Заданная скорость - /// - public float? Speed { get; set; } + /// + /// Заданная скорость + /// + public float? Speed { get; set; } - /// - /// Скорость проходки - /// - public float? DepthSpeed { get; set; } + /// + /// Скорость проходки + /// + public float? DepthSpeed { get; set; } - /// - /// Время бурения шага, сек - /// - public float? TimeDrillStep { get; set; } + /// + /// Время бурения шага, сек + /// + public float? TimeDrillStep { get; set; } - /// - /// Глубина бурения шага - /// - public float? DepthDrillStep { get; set; } - } + /// + /// Глубина бурения шага + /// + public float? DepthDrillStep { get; set; } } diff --git a/AsbCloudApp/Data/SAUB/EventDto.cs b/AsbCloudApp/Data/SAUB/EventDto.cs index 66b5fa7f..e91b0c82 100644 --- a/AsbCloudApp/Data/SAUB/EventDto.cs +++ b/AsbCloudApp/Data/SAUB/EventDto.cs @@ -1,48 +1,47 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data.SAUB +namespace AsbCloudApp.Data.SAUB; + +/// +/// Описание шаблона события панели оператора +/// +public class EventDto : IId { /// - /// Описание шаблона события панели оператора + /// id события /// - public class EventDto : IId - { - /// - /// id события - /// - [Required] - - public int Id { get; set; } + [Required] + + public int Id { get; set; } - /// - /// шаблон текста сообщения - /// - [Required] - public string Message { get; set; } = string.Empty; + /// + /// шаблон текста сообщения + /// + [Required] + public string Message { get; set; } = string.Empty; - /// - /// id категории события - /// - [Required] - [Range(0, int.MaxValue, ErrorMessage = "Id категории события не может быть отрицательным")] - public int IdCategory { get; set; } + /// + /// id категории события + /// + [Required] + [Range(0, int.MaxValue, ErrorMessage = "Id категории события не может быть отрицательным")] + public int IdCategory { get; set; } - /// - /// переменная сервера обмена информацией с полевым оборудованием - /// - public string Tag { get; set; } = string.Empty; + /// + /// переменная сервера обмена информацией с полевым оборудованием + /// + public string Tag { get; set; } = string.Empty; - /// - /// тип определения наступления события - /// - [Required] - [Range(0, int.MaxValue, ErrorMessage = "Id типа события не может быть отрицательным")] - public int EventType { get; set; } + /// + /// тип определения наступления события + /// + [Required] + [Range(0, int.MaxValue, ErrorMessage = "Id типа события не может быть отрицательным")] + public int EventType { get; set; } - /// - /// флаг, следует ли воспроизводить звук при наступлении события - /// - [Required] - public int IdSound { get; set; } - } + /// + /// флаг, следует ли воспроизводить звук при наступлении события + /// + [Required] + public int IdSound { get; set; } } diff --git a/AsbCloudApp/Data/SAUB/SetpointInfoDto.cs b/AsbCloudApp/Data/SAUB/SetpointInfoDto.cs index a5cc0277..2a075757 100644 --- a/AsbCloudApp/Data/SAUB/SetpointInfoDto.cs +++ b/AsbCloudApp/Data/SAUB/SetpointInfoDto.cs @@ -1,43 +1,42 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data.SAUB +namespace AsbCloudApp.Data.SAUB; + +/// +/// DTO рекомендации уставок передаваемых на панель оператора +/// +public class SetpointInfoDto { /// - /// DTO рекомендации уставок передаваемых на панель оператора + /// отображаемое название уставки /// - public class SetpointInfoDto - { - /// - /// отображаемое название уставки - /// - public string DisplayName { get; set; } = string.Empty; + public string DisplayName { get; set; } = string.Empty; - /// - /// настоящее название уставки (имя переменной в панели оператора) - /// - [Required] - public string Name { get; set; } = null!; + /// + /// настоящее название уставки (имя переменной в панели оператора) + /// + [Required] + public string Name { get; set; } = null!; - /// - /// единицы измерения - /// - public string? Units { get; set; } + /// + /// единицы измерения + /// + public string? Units { get; set; } - /// - /// комментарий - /// - public string? Comment { get; set; } + /// + /// комментарий + /// + public string? Comment { get; set; } - /// - /// макс. значение - /// - [Required] - public double Max { get; set; } = double.MaxValue; + /// + /// макс. значение + /// + [Required] + public double Max { get; set; } = double.MaxValue; - /// - /// мин значение - /// - [Required] - public double Min { get; set; } = double.MinValue; - } + /// + /// мин значение + /// + [Required] + public double Min { get; set; } = double.MinValue; } diff --git a/AsbCloudApp/Data/SAUB/SetpointsRequestDto.cs b/AsbCloudApp/Data/SAUB/SetpointsRequestDto.cs index 003f50c4..bf770c4c 100644 --- a/AsbCloudApp/Data/SAUB/SetpointsRequestDto.cs +++ b/AsbCloudApp/Data/SAUB/SetpointsRequestDto.cs @@ -3,64 +3,63 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using AsbCloudApp.Data.User; -namespace AsbCloudApp.Data.SAUB +namespace AsbCloudApp.Data.SAUB; + +/// +/// DTO запроса для предложения по изменению уставок на панели оператора +/// +public class SetpointsRequestDto : IId, IWellRelated { + /// + [Required] + public int Id { get; set; } + + /// + [Required] + public int IdWell { get; set; } + /// - /// DTO запроса для предложения по изменению уставок на панели оператора + /// Id автора запроса /// - public class SetpointsRequestDto : IId, IWellRelated - { - /// - [Required] - public int Id { get; set; } + [Required] + public int IdAuthor { get; set; } - /// - [Required] - public int IdWell { get; set; } + /// + /// текущее состояние запроса 0: неизвестно, 1:ожидает отправки, 2: отправлено, 3: принято оператором, 4: отклонено оператором, 5: устарело + /// + [Required] + public int IdState { get; set; } - /// - /// Id автора запроса - /// - [Required] - public int IdAuthor { get; set; } + /// + /// отметка времени создания запроса + /// + public DateTimeOffset UploadDate { get; set; } = DateTimeOffset.Now; - /// - /// текущее состояние запроса 0: неизвестно, 1:ожидает отправки, 2: отправлено, 3: принято оператором, 4: отклонено оператором, 5: устарело - /// - [Required] - public int IdState { get; set; } + /// + /// время в секундах актуальности этого запроса + /// + [Required] + [Range(10 * 60, 4 * 60 * 60)] + public int ObsolescenceSec { get; set; } = 10 * 60; - /// - /// отметка времени создания запроса - /// - public DateTimeOffset UploadDate { get; set; } = DateTimeOffset.Now; + /// + /// набор уставок: {"название переменной панели"; "рекомендуемое значение"} + /// + [Required] + public Dictionary Setpoints { get; set; } = new(); - /// - /// время в секундах актуальности этого запроса - /// - [Required] - [Range(10 * 60, 4 * 60 * 60)] - public int ObsolescenceSec { get; set; } = 10 * 60; + /// + /// Комментарий для оператора панели + /// + public string? Comment { get; set; } - /// - /// набор уставок: {"название переменной панели"; "рекомендуемое значение"} - /// - [Required] - public Dictionary Setpoints { get; set; } = new(); + /// + /// DTO скважины + /// + public WellDto? Well { get; set; } - /// - /// Комментарий для оператора панели - /// - public string? Comment { get; set; } - - /// - /// DTO скважины - /// - public WellDto? Well { get; set; } - - /// - /// DTO автора - /// - public UserDto? Author { get; set; } - } + /// + /// DTO автора + /// + public UserDto? Author { get; set; } } diff --git a/AsbCloudApp/Data/SAUB/TelemetryDataSaubDto.cs b/AsbCloudApp/Data/SAUB/TelemetryDataSaubDto.cs index 71c95c20..68b63dab 100644 --- a/AsbCloudApp/Data/SAUB/TelemetryDataSaubDto.cs +++ b/AsbCloudApp/Data/SAUB/TelemetryDataSaubDto.cs @@ -1,236 +1,235 @@ using System; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data.SAUB +namespace AsbCloudApp.Data.SAUB; + +/// +/// Сообщение получаемое по телеметрии и отправляемое в frontend +/// +public class TelemetryDataSaubDto : ITelemetryData { /// - /// Сообщение получаемое по телеметрии и отправляемое в frontend + /// метка времени данных /// - public class TelemetryDataSaubDto : ITelemetryData - { - /// - /// метка времени данных - /// - [Required] - public DateTime DateTime { get; set; } - - /// - /// Пользователь САУБ - /// - public int? IdUser { get; set; } + [Required] + public DateTime DateTime { get; set; } + + /// + /// Пользователь САУБ + /// + public int? IdUser { get; set; } - /// - /// Режим работы САУБ: - /// 0 - "РУЧНОЙ" - /// 1 - "БУРЕНИЕ В РОТОРЕ" - /// 2 - "ПРОРАБОТКА" - /// 3 - "БУРЕНИЕ В СЛАЙДЕ" - /// 4 - "СПУСК СПО" - /// 5 - "ПОДЪЕМ СПО" - /// 6 - "ПОДЪЕМ С ПРОРАБОТКОЙ" - /// 10 - "БЛОКИРОВКА" - /// - [Required] - public short Mode { get; set; } + /// + /// Режим работы САУБ: + /// 0 - "РУЧНОЙ" + /// 1 - "БУРЕНИЕ В РОТОРЕ" + /// 2 - "ПРОРАБОТКА" + /// 3 - "БУРЕНИЕ В СЛАЙДЕ" + /// 4 - "СПУСК СПО" + /// 5 - "ПОДЪЕМ СПО" + /// 6 - "ПОДЪЕМ С ПРОРАБОТКОЙ" + /// 10 - "БЛОКИРОВКА" + /// + [Required] + public short Mode { get; set; } - /// - /// telemetry id - /// - public int IdTelemetry { get; set; } + /// + /// telemetry id + /// + public int IdTelemetry { get; set; } - /// - /// telemetry user - /// - public string? User { get; set; } + /// + /// telemetry user + /// + public string? User { get; set; } - /// - /// Глубина забоя, м - /// - public float WellDepth { get; set; } + /// + /// Глубина забоя, м + /// + public float WellDepth { get; set; } - /// - /// Глубина долота, м - /// - public float BitDepth { get; set; } + /// + /// Глубина долота, м + /// + public float BitDepth { get; set; } - /// - /// Талевый блок. Положение, м - /// - public float BlockPosition { get; set; } + /// + /// Талевый блок. Положение, м + /// + public float BlockPosition { get; set; } - /// - /// Талевый блок. Мин положение, м - /// - public float? BlockPositionMin { get; set; } + /// + /// Талевый блок. Мин положение, м + /// + public float? BlockPositionMin { get; set; } - /// - /// Талевый блок. Макс положение, м - /// - public float? BlockPositionMax { get; set; } + /// + /// Талевый блок. Макс положение, м + /// + public float? BlockPositionMax { get; set; } - /// - /// Талевый блок. Скорость, м/час - /// - public float? BlockSpeed { get; set; } + /// + /// Талевый блок. Скорость, м/час + /// + public float? BlockSpeed { get; set; } - /// - /// Талевый блок. Задание скорости, м/час - /// - public float? BlockSpeedSp { get; set; } + /// + /// Талевый блок. Задание скорости, м/час + /// + public float? BlockSpeedSp { get; set; } - /// - /// Талевый блок. Задание скорости для роторного бурения, м/час - /// - public float? BlockSpeedSpRotor { get; set; } + /// + /// Талевый блок. Задание скорости для роторного бурения, м/час + /// + public float? BlockSpeedSpRotor { get; set; } - /// - /// Талевый блок. Задание скорости для режима слайда, м/час - /// - public float? BlockSpeedSpSlide { get; set; } + /// + /// Талевый блок. Задание скорости для режима слайда, м/час + /// + public float? BlockSpeedSpSlide { get; set; } - /// - /// Талевый блок. Задание скорости для проработки, м/час - /// - public float? BlockSpeedSpDevelop { get; set; } + /// + /// Талевый блок. Задание скорости для проработки, м/час + /// + public float? BlockSpeedSpDevelop { get; set; } - /// - /// Давление, атм - /// - public float Pressure { get; set; } + /// + /// Давление, атм + /// + public float Pressure { get; set; } - /// - /// Давление при холостом ходе, атм - /// - public float? PressureIdle { get; set; } + /// + /// Давление при холостом ходе, атм + /// + public float? PressureIdle { get; set; } - /// - /// действующее задание давления, атм - /// - public float? PressureSp { get; set; } + /// + /// действующее задание давления, атм + /// + public float? PressureSp { get; set; } - /// - /// задание давления для роторного режима, атм - /// - public float? PressureSpRotor { get; set; } + /// + /// задание давления для роторного режима, атм + /// + public float? PressureSpRotor { get; set; } - /// - /// задание давления для режима слайда, атм - /// - public float? PressureSpSlide { get; set; } + /// + /// задание давления для режима слайда, атм + /// + public float? PressureSpSlide { get; set; } - /// - /// задание давления для проработки, атм - /// - public float? PressureSpDevelop { get; set; } + /// + /// задание давления для проработки, атм + /// + public float? PressureSpDevelop { get; set; } - /// - /// ограничение макс перепада давления, атм - /// - public float? PressureDeltaLimitMax { get; set; } + /// + /// ограничение макс перепада давления, атм + /// + public float? PressureDeltaLimitMax { get; set; } - /// - /// осевая нагрузка, т - /// - public float AxialLoad { get; set; } + /// + /// осевая нагрузка, т + /// + public float AxialLoad { get; set; } - /// - /// задание осевой нагрузки, т - /// - public float? AxialLoadSp { get; set; } + /// + /// задание осевой нагрузки, т + /// + public float? AxialLoadSp { get; set; } - /// - /// ограничение макс. осевой нагрузки, т - /// - public float? AxialLoadLimitMax { get; set; } + /// + /// ограничение макс. осевой нагрузки, т + /// + public float? AxialLoadLimitMax { get; set; } - /// - /// Вес на крюке, т - /// - public float HookWeight { get; set; } + /// + /// Вес на крюке, т + /// + public float HookWeight { get; set; } - /// - /// Вес на крюке на х.х., т - /// - public float? HookWeightIdle { get; set; } + /// + /// Вес на крюке на х.х., т + /// + public float? HookWeightIdle { get; set; } - /// - /// ограничение мин веса на крюке, т - /// - public float? HookWeightLimitMin { get; set; } + /// + /// ограничение мин веса на крюке, т + /// + public float? HookWeightLimitMin { get; set; } - /// - /// ограничение макс веса на крюке, т - /// - public float? HookWeightLimitMax { get; set; } + /// + /// ограничение макс веса на крюке, т + /// + public float? HookWeightLimitMax { get; set; } - /// - /// момент ротора, кН*м - /// - public float RotorTorque { get; set; } + /// + /// момент ротора, кН*м + /// + public float RotorTorque { get; set; } - /// - /// момент ротора на х.х., кН*м - /// - public float? RotorTorqueIdle { get; set; } + /// + /// момент ротора на х.х., кН*м + /// + public float? RotorTorqueIdle { get; set; } - /// - /// задание момента ротора, кН*м - /// - public float? RotorTorqueSp { get; set; } + /// + /// задание момента ротора, кН*м + /// + public float? RotorTorqueSp { get; set; } - /// - /// ограничение момента ротора, кН*м - /// - public float? RotorTorqueLimitMax { get; set; } + /// + /// ограничение момента ротора, кН*м + /// + public float? RotorTorqueLimitMax { get; set; } - /// - /// скорость ротора, об/мин - /// - public float RotorSpeed { get; set; } + /// + /// скорость ротора, об/мин + /// + public float RotorSpeed { get; set; } - /// - /// расход, л/с - /// - public float? Flow { get; set; } + /// + /// расход, л/с + /// + public float? Flow { get; set; } - /// - /// расход на х.х., л/с - /// - public float? FlowIdle { get; set; } + /// + /// расход на х.х., л/с + /// + public float? FlowIdle { get; set; } - /// - /// ограничение макс расхода, л/с - /// - public float? FlowDeltaLimitMax { get; set; } + /// + /// ограничение макс расхода, л/с + /// + public float? FlowDeltaLimitMax { get; set; } - /// - /// id текущего критерия бурения - /// - public short? IdFeedRegulator { get; set; } + /// + /// id текущего критерия бурения + /// + public short? IdFeedRegulator { get; set; } - /// - /// Текущее состояние работы MSE - /// - public short? MseState { get; set; } + /// + /// Текущее состояние работы MSE + /// + public short? MseState { get; set; } - /// - /// MSE - /// - public float? Mse { get; set; } + /// + /// MSE + /// + public float? Mse { get; set; } - /// - /// Расход. Буровой насос 1 - /// - public float? Pump0Flow { get; set; } + /// + /// Расход. Буровой насос 1 + /// + public float? Pump0Flow { get; set; } - /// - /// Расход. Буровой насос 2 - /// - public float? Pump1Flow { get; set; } + /// + /// Расход. Буровой насос 2 + /// + public float? Pump1Flow { get; set; } - /// - /// Расход. Буровой насос 3 - /// - public float? Pump2Flow { get; set; } - } + /// + /// Расход. Буровой насос 3 + /// + public float? Pump2Flow { get; set; } } \ No newline at end of file diff --git a/AsbCloudApp/Data/SAUB/TelemetryDataSaubStatDto.cs b/AsbCloudApp/Data/SAUB/TelemetryDataSaubStatDto.cs index 329839be..f2390d92 100644 --- a/AsbCloudApp/Data/SAUB/TelemetryDataSaubStatDto.cs +++ b/AsbCloudApp/Data/SAUB/TelemetryDataSaubStatDto.cs @@ -1,115 +1,114 @@ using System; -namespace AsbCloudApp.Data.SAUB +namespace AsbCloudApp.Data.SAUB; + +/// +/// Статистика телеметрии САУБ (усредненные значения) по интервалам глубины +/// +public class TelemetryDataSaubStatDto { /// - /// Статистика телеметрии САУБ (усредненные значения) по интервалам глубины + /// Кол-во записей в интервале /// - public class TelemetryDataSaubStatDto - { - /// - /// Кол-во записей в интервале - /// - public int Count { get; set; } + public int Count { get; set; } - /// - /// Дата начала интервала - /// - public DateTime DateMin { get; set; } + /// + /// Дата начала интервала + /// + public DateTime DateMin { get; set; } - /// - /// Дата окончания интервала - /// - public DateTime DateMax { get; set; } + /// + /// Дата окончания интервала + /// + public DateTime DateMax { get; set; } - /// - /// Глубина начала интервала - /// - public float WellDepthMin { get; set; } + /// + /// Глубина начала интервала + /// + public float WellDepthMin { get; set; } - /// - /// Глубина окончания интервала - /// - public float WellDepthMax { get; set; } + /// + /// Глубина окончания интервала + /// + public float WellDepthMax { get; set; } - /// - /// Давление - /// - public float Pressure { get; set; } + /// + /// Давление + /// + public float Pressure { get; set; } - /// - /// действующее задание давления - /// - public float PressureSp { get; set; } - - /// - /// действующее задание перепада давления - /// - public float PressureSpDelta { get; set; } + /// + /// действующее задание давления + /// + public float PressureSp { get; set; } + + /// + /// действующее задание перепада давления + /// + public float PressureSpDelta { get; set; } - /// - /// Давление при холостом ходе. - /// - public float PressureIdle { get; set; } + /// + /// Давление при холостом ходе. + /// + public float PressureIdle { get; set; } - /// - /// ограничение макс перепада давления - /// - public float PressureDeltaLimitMax { get; set; } + /// + /// ограничение макс перепада давления + /// + public float PressureDeltaLimitMax { get; set; } - /// - /// Перепад давления - /// - public float PressureDelta { get; set; } + /// + /// Перепад давления + /// + public float PressureDelta { get; set; } - /// - /// осевая нагрузка - /// - public float AxialLoad { get; set; } + /// + /// осевая нагрузка + /// + public float AxialLoad { get; set; } - /// - /// задание осевой нагрузки - /// - public float AxialLoadSp { get; set; } + /// + /// задание осевой нагрузки + /// + public float AxialLoadSp { get; set; } - /// - /// ограничение макс. осевой нагрузки - /// - public float AxialLoadLimitMax { get; set; } + /// + /// ограничение макс. осевой нагрузки + /// + public float AxialLoadLimitMax { get; set; } - /// - /// момент ротора - /// - public float RotorTorque { get; set; } + /// + /// момент ротора + /// + public float RotorTorque { get; set; } - /// - /// задание момента ротора - /// - public float RotorTorqueSp { get; set; } + /// + /// задание момента ротора + /// + public float RotorTorqueSp { get; set; } - /// - /// момент ротора на х.х. - /// - public float RotorTorqueLimitMax { get; set; } + /// + /// момент ротора на х.х. + /// + public float RotorTorqueLimitMax { get; set; } - /// - /// Талевый блок. Скорость - /// - public float BlockSpeed { get; set; } + /// + /// Талевый блок. Скорость + /// + public float BlockSpeed { get; set; } - /// - /// Талевый блок. Задание скорости - /// - public float BlockSpeedSp { get; set; } + /// + /// Талевый блок. Задание скорости + /// + public float BlockSpeedSp { get; set; } - /// - /// Режим САУБ - /// - public short IdMode { get; set; } + /// + /// Режим САУБ + /// + public short IdMode { get; set; } - /// - /// Текущий критерий бурения - /// - public short? IdFeedRegulator { get; set; } - } + /// + /// Текущий критерий бурения + /// + public short? IdFeedRegulator { get; set; } } diff --git a/AsbCloudApp/Data/SAUB/TelemetryDataSpinDto.cs b/AsbCloudApp/Data/SAUB/TelemetryDataSpinDto.cs index 83c55520..ee717583 100644 --- a/AsbCloudApp/Data/SAUB/TelemetryDataSpinDto.cs +++ b/AsbCloudApp/Data/SAUB/TelemetryDataSpinDto.cs @@ -1,84 +1,83 @@ using System; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data.SAUB +namespace AsbCloudApp.Data.SAUB; + +/// +/// телеметрия спин мастер +/// +public class TelemetryDataSpinDto : ITelemetryData { /// - /// телеметрия спин мастер + /// Идентификатор телеметрии /// - public class TelemetryDataSpinDto : ITelemetryData - { - /// - /// Идентификатор телеметрии - /// - public int IdTelemetry { get; set; } + public int IdTelemetry { get; set; } - /// - /// Дата - /// - [Required] - public DateTime DateTime { get; set; } + /// + /// Дата + /// + [Required] + public DateTime DateTime { get; set; } - /// - /// Ограничение числа оборотов вправо - /// - public float? RevolsRightLimit { get; set; } + /// + /// Ограничение числа оборотов вправо + /// + public float? RevolsRightLimit { get; set; } - /// - /// Ограничение числа оборотов влево - /// - public float? RevolsLeftLimit { get; set; } + /// + /// Ограничение числа оборотов влево + /// + public float? RevolsLeftLimit { get; set; } - /// - /// Заданная скорость вращения вправо - /// - public float? SpeedRightSp { get; set; } + /// + /// Заданная скорость вращения вправо + /// + public float? SpeedRightSp { get; set; } - /// - /// Заданная скорость вращения влево - /// - public float? SpeedLeftSp { get; set; } + /// + /// Заданная скорость вращения влево + /// + public float? SpeedLeftSp { get; set; } - /// - /// Суммарное количество оборотов вправо - /// - public float? RevolsRightTotal { get; set; } + /// + /// Суммарное количество оборотов вправо + /// + public float? RevolsRightTotal { get; set; } - /// - /// Суммарное количество оборотов влево - /// - public float? RevolsLeftTotal { get; set; } + /// + /// Суммарное количество оборотов влево + /// + public float? RevolsLeftTotal { get; set; } - /// - /// Нулевая позиция осцилляции - /// - public float? PositionZero { get; set; } + /// + /// Нулевая позиция осцилляции + /// + public float? PositionZero { get; set; } - /// - /// Крайний правый угол осцилляции - /// - public float? PositionRight { get; set; } + /// + /// Крайний правый угол осцилляции + /// + public float? PositionRight { get; set; } - /// - /// Выбранный режим управления - /// - public short? Mode { get; set; } + /// + /// Выбранный режим управления + /// + public short? Mode { get; set; } - /// - /// Переменная этапа - /// - public short? State { get; set; } + /// + /// Переменная этапа + /// + public short? State { get; set; } - /// - /// Осцилляция включена - /// - [Required] - public bool IsOscillating => State != 0 & State != 6 & State != 7; + /// + /// Осцилляция включена + /// + [Required] + public bool IsOscillating => State != 0 & State != 6 & State != 7; - /// - /// Демпфирование включено - /// - [Required] - public bool IsDampening => State == 7 && (Mode & 2) > 0; - } + /// + /// Демпфирование включено + /// + [Required] + public bool IsDampening => State == 7 && (Mode & 2) > 0; } diff --git a/AsbCloudApp/Data/SAUB/TelemetryDataStatDto.cs b/AsbCloudApp/Data/SAUB/TelemetryDataStatDto.cs index c2cb8926..8da5944b 100644 --- a/AsbCloudApp/Data/SAUB/TelemetryDataStatDto.cs +++ b/AsbCloudApp/Data/SAUB/TelemetryDataStatDto.cs @@ -1,30 +1,29 @@ using System; -namespace AsbCloudInfrastructure.Services.SAUB +namespace AsbCloudInfrastructure.Services.SAUB; + +/// +/// Статистика данных телеметрии +/// +public class TelemetryDataStatDto { /// - /// Статистика данных телеметрии + /// ID в БД /// - public class TelemetryDataStatDto - { - /// - /// ID в БД - /// - public int IdTelemetry { get; set; } + public int IdTelemetry { get; set; } - /// - /// дата получения первых данных - /// - public DateTimeOffset DateFirst { get; set; } - - /// - /// дата получения последних полученных данных - /// - public DateTimeOffset DateLast { get; set; } - - /// - /// смещение часового пояса - /// - public double TimezoneOffsetHours { get; set; } - } + /// + /// дата получения первых данных + /// + public DateTimeOffset DateFirst { get; set; } + + /// + /// дата получения последних полученных данных + /// + public DateTimeOffset DateLast { get; set; } + + /// + /// смещение часового пояса + /// + public double TimezoneOffsetHours { get; set; } } \ No newline at end of file diff --git a/AsbCloudApp/Data/SAUB/TelemetryInfoDto.cs b/AsbCloudApp/Data/SAUB/TelemetryInfoDto.cs index 8e89d474..95e64151 100644 --- a/AsbCloudApp/Data/SAUB/TelemetryInfoDto.cs +++ b/AsbCloudApp/Data/SAUB/TelemetryInfoDto.cs @@ -1,65 +1,64 @@ using System; -namespace AsbCloudApp.Data.SAUB +namespace AsbCloudApp.Data.SAUB; + +/// +/// общая информация о панели оператора +/// +public class TelemetryInfoDto { /// - /// общая информация о панели оператора + /// дата начала бурения (заполнения данных на панели) /// - public class TelemetryInfoDto - { - /// - /// дата начала бурения (заполнения данных на панели) - /// - public DateTime DrillingStartDate { get; set; } + public DateTime DrillingStartDate { get; set; } - /// - /// идентификатор временной зоны - /// - public string? TimeZoneId { get; set; } + /// + /// идентификатор временной зоны + /// + public string? TimeZoneId { get; set; } - /// - /// смещение в часах относительно UTC - /// - public double TimeZoneOffsetTotalHours { get; set; } + /// + /// смещение в часах относительно UTC + /// + public double TimeZoneOffsetTotalHours { get; set; } - /// - /// название скважины - /// - public string Well { get; set; } = string.Empty; + /// + /// название скважины + /// + public string Well { get; set; } = string.Empty; - /// - /// название куста - /// - public string Cluster { get; set; } = string.Empty; + /// + /// название куста + /// + public string Cluster { get; set; } = string.Empty; - /// - /// название месторождения - /// - public string Deposit { get; set; } = string.Empty; + /// + /// название месторождения + /// + public string Deposit { get; set; } = string.Empty; - /// - /// название заказчика - /// - public string? Customer { get; set; } - - /// - /// версия ПО панели оператора - /// - public string? HmiVersion { get; set; } + /// + /// название заказчика + /// + public string? Customer { get; set; } + + /// + /// версия ПО панели оператора + /// + public string? HmiVersion { get; set; } - /// - /// версия ПО ПЛК САУБ - /// - public string? SaubPlcVersion { get; set; } + /// + /// версия ПО ПЛК САУБ + /// + public string? SaubPlcVersion { get; set; } - /// - /// версия ПО ПЛК Спин мастер - /// - public string? SpinPlcVersion { get; set; } + /// + /// версия ПО ПЛК Спин мастер + /// + public string? SpinPlcVersion { get; set; } - /// - /// комментарий - /// - public string? Comment { get; set; } - } + /// + /// комментарий + /// + public string? Comment { get; set; } } diff --git a/AsbCloudApp/Data/SAUB/TelemetryMessageDto.cs b/AsbCloudApp/Data/SAUB/TelemetryMessageDto.cs index 7c8e4d92..05562034 100644 --- a/AsbCloudApp/Data/SAUB/TelemetryMessageDto.cs +++ b/AsbCloudApp/Data/SAUB/TelemetryMessageDto.cs @@ -1,55 +1,54 @@ using System; -namespace AsbCloudApp.Data.SAUB +namespace AsbCloudApp.Data.SAUB; + +/// +/// Сообщение получаемое от телеметрии с буровой +/// +public class TelemetryMessageDto : IId { /// - /// Сообщение получаемое от телеметрии с буровой + /// Id сообщения в базе панели оператора /// - public class TelemetryMessageDto : IId - { - /// - /// Id сообщения в базе панели оператора - /// - public int Id { get; set; } + public int Id { get; set; } - /// - /// отметка времени - /// - public DateTimeOffset Date { get; set; } + /// + /// отметка времени + /// + public DateTimeOffset Date { get; set; } - /// - /// глубина забоя - /// - public double WellDepth { get; set; } + /// + /// глубина забоя + /// + public double WellDepth { get; set; } - /// - /// Id события которое генерировало это сообщение - /// - public int IdEvent { get; set; } + /// + /// Id события которое генерировало это сообщение + /// + public int IdEvent { get; set; } - /// - /// идентификатор пользователя телеметрии - /// - public int? IdTelemetryUser { get; set; } + /// + /// идентификатор пользователя телеметрии + /// + public int? IdTelemetryUser { get; set; } - /// - /// аргумент №0 для подстановки в шаблон сообщения - /// - public string? Arg0 { get; set; } + /// + /// аргумент №0 для подстановки в шаблон сообщения + /// + public string? Arg0 { get; set; } - /// - /// аргумент №1 для подстановки в шаблон сообщения - /// - public string? Arg1 { get; set; } + /// + /// аргумент №1 для подстановки в шаблон сообщения + /// + public string? Arg1 { get; set; } - /// - /// аргумент №2 для подстановки в шаблон сообщения - /// - public string? Arg2 { get; set; } + /// + /// аргумент №2 для подстановки в шаблон сообщения + /// + public string? Arg2 { get; set; } - /// - /// аргумент №3 для подстановки в шаблон сообщения - /// - public string? Arg3 { get; set; } - } + /// + /// аргумент №3 для подстановки в шаблон сообщения + /// + public string? Arg3 { get; set; } } diff --git a/AsbCloudApp/Data/SAUB/TelemetryUserDto.cs b/AsbCloudApp/Data/SAUB/TelemetryUserDto.cs index ad7a8aab..a86c54dd 100644 --- a/AsbCloudApp/Data/SAUB/TelemetryUserDto.cs +++ b/AsbCloudApp/Data/SAUB/TelemetryUserDto.cs @@ -1,52 +1,51 @@ -namespace AsbCloudApp.Data.SAUB +namespace AsbCloudApp.Data.SAUB; + +/// +/// Пользователь панели оператора +/// +public class TelemetryUserDto : IId { + /// + public int Id { get; set; } + /// - /// Пользователь панели оператора + /// Имя /// - public class TelemetryUserDto : IId + public string? Name { get; set; } + + /// + /// Фамилия + /// + public string Surname { get; set; } = null!; + + /// + /// Отчество + /// + public string? Patronymic { get; set; } + + /// + /// Уровень доступа + /// + public int? Level { get; set; } + + /// + /// Собрать отображаемое имя пользователя + /// + /// + public string MakeDisplayName() { - /// - public int Id { get; set; } - - /// - /// Имя - /// - public string? Name { get; set; } - - /// - /// Фамилия - /// - public string Surname { get; set; } = null!; - - /// - /// Отчество - /// - public string? Patronymic { get; set; } - - /// - /// Уровень доступа - /// - public int? Level { get; set; } - - /// - /// Собрать отображаемое имя пользователя - /// - /// - public string MakeDisplayName() + if (!string.IsNullOrEmpty(Surname)) { - if (!string.IsNullOrEmpty(Surname)) + var s = Surname; + if (!string.IsNullOrEmpty(Name)) { - var s = Surname; - if (!string.IsNullOrEmpty(Name)) - { - s += $"{Name[0]}."; - if (!string.IsNullOrEmpty(Patronymic)) - s += $" {Patronymic[0]}."; - } - return s; + s += $"{Name[0]}."; + if (!string.IsNullOrEmpty(Patronymic)) + s += $" {Patronymic[0]}."; } - else - return $"User #{Id}"; + return s; } + else + return $"User #{Id}"; } } diff --git a/AsbCloudApp/Data/SAUB/TelemetryWirelineRunOutDto.cs b/AsbCloudApp/Data/SAUB/TelemetryWirelineRunOutDto.cs index c6a52965..a15aca57 100644 --- a/AsbCloudApp/Data/SAUB/TelemetryWirelineRunOutDto.cs +++ b/AsbCloudApp/Data/SAUB/TelemetryWirelineRunOutDto.cs @@ -1,47 +1,46 @@ using System; -namespace AsbCloudApp.Data.SAUB +namespace AsbCloudApp.Data.SAUB; + +/// +/// DTO телеметрии наработки талевого каната от панели бурильщика +/// +public class TelemetryWirelineRunOutBaseDto { /// - /// DTO телеметрии наработки талевого каната от панели бурильщика + /// отметка времени /// - public class TelemetryWirelineRunOutBaseDto - { - /// - /// отметка времени - /// - public DateTimeOffset DateTime { get; set; } - - /// - /// Наработка талевого каната с момента перетяжки каната, т*км - /// - public float Hauling { get; set; } - - /// - /// Наработка талевого каната до сигнализации о необходимости перетяжки, т*км - /// - public float HaulingWarnSp { get; set; } - - /// - /// Наработка талевого каната с момента замены каната, т*км - /// - public float Replace { get; set; } - - /// - /// Наработка талевого каната до сигнализации о необходимости замены, т*км - /// - public float ReplaceWarnSp { get; set; } - } + public DateTimeOffset DateTime { get; set; } /// - /// DTO телеметрии наработки талевого каната + /// Наработка талевого каната с момента перетяжки каната, т*км /// - public class TelemetryWirelineRunOutDto : TelemetryWirelineRunOutBaseDto - { + public float Hauling { get; set; } - /// - /// Информация по скважине - /// - public WellInfoDto WellInfo { get; set; } = null!; - } + /// + /// Наработка талевого каната до сигнализации о необходимости перетяжки, т*км + /// + public float HaulingWarnSp { get; set; } + + /// + /// Наработка талевого каната с момента замены каната, т*км + /// + public float Replace { get; set; } + + /// + /// Наработка талевого каната до сигнализации о необходимости замены, т*км + /// + public float ReplaceWarnSp { get; set; } +} + +/// +/// DTO телеметрии наработки талевого каната +/// +public class TelemetryWirelineRunOutDto : TelemetryWirelineRunOutBaseDto +{ + + /// + /// Информация по скважине + /// + public WellInfoDto WellInfo { get; set; } = null!; } diff --git a/AsbCloudApp/Data/ScheduleDto.cs b/AsbCloudApp/Data/ScheduleDto.cs index e9c8d991..1a981f61 100644 --- a/AsbCloudApp/Data/ScheduleDto.cs +++ b/AsbCloudApp/Data/ScheduleDto.cs @@ -2,61 +2,60 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Описание данных графика работ +/// +public class ScheduleDto : IId, IWellRelated, IValidatableObject { + /// + [Required] + public int Id { get; set; } + + /// + [Required] + public int IdWell { get; set; } + /// - /// Описание данных графика работ + /// Идентификатор бурильщика /// - public class ScheduleDto : IId, IWellRelated, IValidatableObject + [Required] + public int IdDriller { get; set; } + + /// + /// Начало смены + /// + [Required] + public TimeDto ShiftStart { get; set; } = null!; + + /// + /// Конец смены + /// + [Required] + public TimeDto ShiftEnd { get; set; } = null!; + + /// + /// Начало бурения + /// + [Required] + public DateTimeOffset DrillStart { get; set; } + + /// + /// Конец бурения + /// + [Required] + public DateTimeOffset DrillEnd { get; set; } + + /// + /// Бурильщик + /// + public DrillerDto? Driller { get; set; } + + /// + public IEnumerable Validate(ValidationContext validationContext) { - /// - [Required] - public int Id { get; set; } - - /// - [Required] - public int IdWell { get; set; } - - /// - /// Идентификатор бурильщика - /// - [Required] - public int IdDriller { get; set; } - - /// - /// Начало смены - /// - [Required] - public TimeDto ShiftStart { get; set; } = null!; - - /// - /// Конец смены - /// - [Required] - public TimeDto ShiftEnd { get; set; } = null!; - - /// - /// Начало бурения - /// - [Required] - public DateTimeOffset DrillStart { get; set; } - - /// - /// Конец бурения - /// - [Required] - public DateTimeOffset DrillEnd { get; set; } - - /// - /// Бурильщик - /// - public DrillerDto? Driller { get; set; } - - /// - public IEnumerable Validate(ValidationContext validationContext) - { - if(DrillStart >= DrillEnd) - yield return new ValidationResult($"DrillStart > DrillEnd"); - } + if(DrillStart >= DrillEnd) + yield return new ValidationResult($"DrillStart > DrillEnd"); } } diff --git a/AsbCloudApp/Data/SimpleTimezoneDto.cs b/AsbCloudApp/Data/SimpleTimezoneDto.cs index 5d2e1f8f..b869dbc9 100644 --- a/AsbCloudApp/Data/SimpleTimezoneDto.cs +++ b/AsbCloudApp/Data/SimpleTimezoneDto.cs @@ -1,51 +1,50 @@ using System; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// временная зона +/// +public class SimpleTimezoneDto { /// - /// временная зона + /// смещение в часах относительно UTC /// - public class SimpleTimezoneDto + public double Hours { get; set; } + + /// + /// идентификатор часовой зоны + /// + public string? TimezoneId { get; set; } + + /// + /// запрет на переопределение + /// + public bool IsOverride { get; set; } + + /// + /// Смещение часового пояса + /// + public TimeSpan Offset => TimeSpan.FromHours(Hours); + + /// + public override bool Equals(object? obj) { - /// - /// смещение в часах относительно UTC - /// - public double Hours { get; set; } - - /// - /// идентификатор часовой зоны - /// - public string? TimezoneId { get; set; } - - /// - /// запрет на переопределение - /// - public bool IsOverride { get; set; } - - /// - /// Смещение часового пояса - /// - public TimeSpan Offset => TimeSpan.FromHours(Hours); - - /// - public override bool Equals(object? obj) - { - if (obj is SimpleTimezoneDto tTimeZone - && tTimeZone.Hours == Hours - && tTimeZone.TimezoneId == TimezoneId - && tTimeZone.IsOverride == IsOverride) - return true; - return false; - } - - /// - public override int GetHashCode() - => Hours.GetHashCode() - | TimezoneId?.GetHashCode()??-1 - | IsOverride.GetHashCode(); - - /// - public override string ToString() - => $"{TimezoneId} (UTC+{Hours:00.##})"; + if (obj is SimpleTimezoneDto tTimeZone + && tTimeZone.Hours == Hours + && tTimeZone.TimezoneId == TimezoneId + && tTimeZone.IsOverride == IsOverride) + return true; + return false; } + + /// + public override int GetHashCode() + => Hours.GetHashCode() + | TimezoneId?.GetHashCode()??-1 + | IsOverride.GetHashCode(); + + /// + public override string ToString() + => $"{TimezoneId} (UTC+{Hours:00.##})"; } \ No newline at end of file diff --git a/AsbCloudApp/Data/SlipsStatDto.cs b/AsbCloudApp/Data/SlipsStatDto.cs index 13e381fa..b24854d8 100644 --- a/AsbCloudApp/Data/SlipsStatDto.cs +++ b/AsbCloudApp/Data/SlipsStatDto.cs @@ -4,41 +4,40 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO, описывающая аналитику удержания в клиньях +/// +public class SlipsStatDto { /// - /// DTO, описывающая аналитику удержания в клиньях + /// ФИО бурильщика /// - public class SlipsStatDto - { - /// - /// ФИО бурильщика - /// - public string DrillerName { get; set; } = null!; + public string DrillerName { get; set; } = null!; - /// - /// Количество скважин - /// - public int WellCount { get; set; } + /// + /// Количество скважин + /// + public int WellCount { get; set; } - /// - /// Название секции - /// - public string SectionCaption { get; set; } = null!; + /// + /// Название секции + /// + public string SectionCaption { get; set; } = null!; - /// - /// Количество удержаний в клиньях, шт. - /// - public int SlipsCount { get; set; } + /// + /// Количество удержаний в клиньях, шт. + /// + public int SlipsCount { get; set; } - /// - /// Время удержания в клиньях, мин. - /// - public double SlipsTimeInMinutes { get; set; } + /// + /// Время удержания в клиньях, мин. + /// + public double SlipsTimeInMinutes { get; set; } - /// - /// Проходка, м. - /// - public double SectionDepth { get; set; } - } + /// + /// Проходка, м. + /// + public double SectionDepth { get; set; } } diff --git a/AsbCloudApp/Data/StatClusterDto.cs b/AsbCloudApp/Data/StatClusterDto.cs index d407dda8..9e6aea41 100644 --- a/AsbCloudApp/Data/StatClusterDto.cs +++ b/AsbCloudApp/Data/StatClusterDto.cs @@ -2,27 +2,26 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO статистики скважин куста +/// +public class StatClusterDto : IId { + /// + [Required] + public int Id { get; set; } + /// - /// DTO статистики скважин куста + /// название куста /// - public class StatClusterDto : IId - { - /// - [Required] - public int Id { get; set; } + [Required] + public string Caption { get; set; } = string.Empty; - /// - /// название куста - /// - [Required] - public string Caption { get; set; } = string.Empty; - - /// - /// список статистик скважин куста - /// - [Required] - public IEnumerable StatsWells { get; set; } = Enumerable.Empty(); - } + /// + /// список статистик скважин куста + /// + [Required] + public IEnumerable StatsWells { get; set; } = Enumerable.Empty(); } diff --git a/AsbCloudApp/Data/StatOperationsDto.cs b/AsbCloudApp/Data/StatOperationsDto.cs index 06d4cd8b..8e95392d 100644 --- a/AsbCloudApp/Data/StatOperationsDto.cs +++ b/AsbCloudApp/Data/StatOperationsDto.cs @@ -1,69 +1,68 @@ using System; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO статистики операций +/// +public class StatOperationsDto { /// - /// DTO статистики операций + /// Дата и время начала /// - public class StatOperationsDto - { - /// - /// Дата и время начала - /// - public DateTimeOffset? Start { get; set; } + public DateTimeOffset? Start { get; set; } - /// - /// Дата и время окончания - /// - public DateTimeOffset? End { get; set; } + /// + /// Дата и время окончания + /// + public DateTimeOffset? End { get; set; } - /// - /// Глубина, м - /// - [Required] - public double WellDepthStart { get; set; } + /// + /// Глубина, м + /// + [Required] + public double WellDepthStart { get; set; } - /// - /// Глубина, м - /// - [Required] - public double WellDepthEnd { get; set; } + /// + /// Глубина, м + /// + [Required] + public double WellDepthEnd { get; set; } - /// - /// Рейсовая скорость, м/час - /// - [Required] - public double RouteSpeed { get; set; } + /// + /// Рейсовая скорость, м/час + /// + [Required] + public double RouteSpeed { get; set; } - /// - /// Механическая скорость проходки, м/час - /// - [Required] - public double Rop { get; set; } + /// + /// Механическая скорость проходки, м/час + /// + [Required] + public double Rop { get; set; } - /// - /// Скорость подъема КНБК - /// - [Required] - public double BhaUpSpeed { get; set; } + /// + /// Скорость подъема КНБК + /// + [Required] + public double BhaUpSpeed { get; set; } - /// - /// Скорость спуска КНБК - /// - [Required] - public double BhaDownSpeed { get; set; } + /// + /// Скорость спуска КНБК + /// + [Required] + public double BhaDownSpeed { get; set; } - /// - /// Скорость спуска обсадной колонны - /// - [Required] - public double CasingDownSpeed { get; set; } + /// + /// Скорость спуска обсадной колонны + /// + [Required] + public double CasingDownSpeed { get; set; } - /// - /// Непроизводительное время - /// - [Required] - public double NonProductiveHours { get; set; } - } + /// + /// Непроизводительное время + /// + [Required] + public double NonProductiveHours { get; set; } } diff --git a/AsbCloudApp/Data/StatSectionDto.cs b/AsbCloudApp/Data/StatSectionDto.cs index e1cb8d91..39432f51 100644 --- a/AsbCloudApp/Data/StatSectionDto.cs +++ b/AsbCloudApp/Data/StatSectionDto.cs @@ -1,20 +1,19 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data -{ - /// - /// План-факт статистики по операциям за секцию скважины - /// - public class StatSectionDto : PlanFactDto, IId - { - /// - [Required] - public int Id { get; set; } +namespace AsbCloudApp.Data; - /// - /// название секции - /// - [Required] - public string Caption { get; set; } = string.Empty; - } +/// +/// План-факт статистики по операциям за секцию скважины +/// +public class StatSectionDto : PlanFactDto, IId +{ + /// + [Required] + public int Id { get; set; } + + /// + /// название секции + /// + [Required] + public string Caption { get; set; } = string.Empty; } diff --git a/AsbCloudApp/Data/StatWellDto.cs b/AsbCloudApp/Data/StatWellDto.cs index 2906267d..93413112 100644 --- a/AsbCloudApp/Data/StatWellDto.cs +++ b/AsbCloudApp/Data/StatWellDto.cs @@ -3,73 +3,72 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO статистики по операциям за скважину +/// +public class StatWellDto : IId { + /// + [Required] + public int Id { get; set; } + /// - /// DTO статистики по операциям за скважину + /// название /// - public class StatWellDto : IId - { - /// - [Required] - public int Id { get; set; } + [Required] + public string Caption { get; set; } = string.Empty; - /// - /// название - /// - [Required] - public string Caption { get; set; } = string.Empty; + /// + /// тип скважины + /// + [Required] + public string WellType { get; set; } = string.Empty; - /// - /// тип скважины - /// - [Required] - public string WellType { get; set; } = string.Empty; + /// + /// ИД состояния скважины + /// + [Required] + public int IdState { get; set; } - /// - /// ИД состояния скважины - /// - [Required] - public int IdState { get; set; } + /// + /// текст состояния скважины + /// + [Required] + public string State { get; set; } = string.Empty; - /// - /// текст состояния скважины - /// - [Required] - public string State { get; set; } = string.Empty; + /// + /// дата прихода последней телеметрии + /// + [Required] + public DateTimeOffset LastTelemetryDate { get; set; } - /// - /// дата прихода последней телеметрии - /// - [Required] - public DateTimeOffset LastTelemetryDate { get; set; } + /// + /// Статистика по секциям + /// + [Required] + public IEnumerable Sections { get; set; } = Enumerable.Empty(); - /// - /// Статистика по секциям - /// - [Required] - public IEnumerable Sections { get; set; } = Enumerable.Empty(); + /// + /// статистика за всю скважину + /// + [Required] + public PlanFactDto Total { get; set; } = new(); - /// - /// статистика за всю скважину - /// - [Required] - public PlanFactDto Total { get; set; } = new(); + /// + /// компании участвующие в строительстве скважины + /// + [Required] + public IEnumerable Companies { get; set; } = Enumerable.Empty(); - /// - /// компании участвующие в строительстве скважины - /// - [Required] - public IEnumerable Companies { get; set; } = Enumerable.Empty(); - - /// - /// Отставание от ГГД, дни - /// - public double? TvdLagDays { get; set; } - - /// - /// Кол-во дней бурения по ГГД - /// - public double? TvdDrillingDays { get; set; } - } + /// + /// Отставание от ГГД, дни + /// + public double? TvdLagDays { get; set; } + + /// + /// Кол-во дней бурения по ГГД + /// + public double? TvdDrillingDays { get; set; } } diff --git a/AsbCloudApp/Data/Subsystems/SubsystemDto.cs b/AsbCloudApp/Data/Subsystems/SubsystemDto.cs index fa5c02d1..bd0c1b21 100644 --- a/AsbCloudApp/Data/Subsystems/SubsystemDto.cs +++ b/AsbCloudApp/Data/Subsystems/SubsystemDto.cs @@ -1,26 +1,25 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data.Subsystems +namespace AsbCloudApp.Data.Subsystems; + +/// +/// Описание параметров подсистемы +/// +public class SubsystemDto : IId { /// - /// Описание параметров подсистемы + /// Идентификатор подсистемы /// - public class SubsystemDto : IId - { - /// - /// Идентификатор подсистемы - /// - [Required] - public int Id { get; set; } - /// - /// Наименование подсистемы - /// - [Required] - public string Name { get; set; } = null!; - /// - /// Детальное описание подсистемы - /// - [Required] - public string Description { get; set; } = string.Empty; - } + [Required] + public int Id { get; set; } + /// + /// Наименование подсистемы + /// + [Required] + public string Name { get; set; } = null!; + /// + /// Детальное описание подсистемы + /// + [Required] + public string Description { get; set; } = string.Empty; } diff --git a/AsbCloudApp/Data/Subsystems/SubsystemStatDto.cs b/AsbCloudApp/Data/Subsystems/SubsystemStatDto.cs index 3c566dea..78dd9b5c 100644 --- a/AsbCloudApp/Data/Subsystems/SubsystemStatDto.cs +++ b/AsbCloudApp/Data/Subsystems/SubsystemStatDto.cs @@ -1,52 +1,51 @@ using System; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data.Subsystems +namespace AsbCloudApp.Data.Subsystems; + +/// +/// Статистика подсистемы +/// +public class SubsystemStatDto { /// - /// Статистика подсистемы + /// Идентификатор подсистемы /// - public class SubsystemStatDto - { - /// - /// Идентификатор подсистемы - /// - [Required] - public int IdSubsystem { get; set; } - /// - /// Название подсистемы - /// - [Required] - public string SubsystemName { get; set; } = null!; - /// - /// наработка подсистемы - /// - [Required] - public double UsedTimeHours { get; set; } - /// - /// коэффициент использования - /// - [Required] - public double KUsage { get; set; } - /// - /// сумма изменения глубин при включеной подсистеме - /// - [Required] - public double SumDepthInterval { get; set; } - /// - /// сумма проходок автоопределенных операций выполняемых подсистемой - /// - [Required] - public double SumOperationDepthInterval { get; set; } - /// - /// сумма продолжительности автоопределенных операций выполняемых подсистемой - /// - [Required] - public double SumOperationDurationHours { get; set; } - /// - /// количество включений подсистемы - /// - [Required] - public int OperationCount { get; set; } - } + [Required] + public int IdSubsystem { get; set; } + /// + /// Название подсистемы + /// + [Required] + public string SubsystemName { get; set; } = null!; + /// + /// наработка подсистемы + /// + [Required] + public double UsedTimeHours { get; set; } + /// + /// коэффициент использования + /// + [Required] + public double KUsage { get; set; } + /// + /// сумма изменения глубин при включеной подсистеме + /// + [Required] + public double SumDepthInterval { get; set; } + /// + /// сумма проходок автоопределенных операций выполняемых подсистемой + /// + [Required] + public double SumOperationDepthInterval { get; set; } + /// + /// сумма продолжительности автоопределенных операций выполняемых подсистемой + /// + [Required] + public double SumOperationDurationHours { get; set; } + /// + /// количество включений подсистемы + /// + [Required] + public int OperationCount { get; set; } } diff --git a/AsbCloudApp/Data/TelemetryDto.cs b/AsbCloudApp/Data/TelemetryDto.cs index 2934b721..6584a8df 100644 --- a/AsbCloudApp/Data/TelemetryDto.cs +++ b/AsbCloudApp/Data/TelemetryDto.cs @@ -1,44 +1,43 @@ using AsbCloudApp.Data.SAUB; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO телеметрии панели +/// +public class TelemetryBaseDto : IId +{ + /// + public int Id { get; set; } + + /// + /// уникальный идентификатор телеметрии по которому панель оператора присылает данные + /// + public string RemoteUid { get; set; } = null!; + + /// + /// информация о бурении, панели оператора и контроллерах + /// + public TelemetryInfoDto? Info { get; set; } + + /// + /// Смещение часового пояса от UTC + /// + public SimpleTimezoneDto? TimeZone { get; set; } +} + +/// +/// DTO телеметрии панели с скважиной +/// +public class TelemetryDto : TelemetryBaseDto { /// - /// DTO телеметрии панели + /// ИД скважины /// - public class TelemetryBaseDto : IId - { - /// - public int Id { get; set; } - - /// - /// уникальный идентификатор телеметрии по которому панель оператора присылает данные - /// - public string RemoteUid { get; set; } = null!; - - /// - /// информация о бурении, панели оператора и контроллерах - /// - public TelemetryInfoDto? Info { get; set; } - - /// - /// Смещение часового пояса от UTC - /// - public SimpleTimezoneDto? TimeZone { get; set; } - } + public int? IdWell { get; set; } /// - /// DTO телеметрии панели с скважиной + /// DTO скважины /// - public class TelemetryDto : TelemetryBaseDto - { - /// - /// ИД скважины - /// - public int? IdWell { get; set; } - - /// - /// DTO скважины - /// - public WellInfoDto? Well { get; set; } - } + public WellInfoDto? Well { get; set; } } diff --git a/AsbCloudApp/Data/TimeDto.cs b/AsbCloudApp/Data/TimeDto.cs index 34bcba3e..2cb40a6d 100644 --- a/AsbCloudApp/Data/TimeDto.cs +++ b/AsbCloudApp/Data/TimeDto.cs @@ -1,159 +1,158 @@ using System; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO времени +/// +public class TimeDto : IComparable { + private int hour = 0; + private int minute = 0; + private int second = 0; + /// - /// DTO времени + /// час /// - public class TimeDto : IComparable + public int Hour { - private int hour = 0; - private int minute = 0; - private int second = 0; - - /// - /// час - /// - public int Hour + get => hour; + set { - get => hour; - set - { - if (value > 23 || value < 0) - throw new ArgumentOutOfRangeException(nameof(Hour), "hour should be in [0; 23]"); - hour = value; - } + if (value > 23 || value < 0) + throw new ArgumentOutOfRangeException(nameof(Hour), "hour should be in [0; 23]"); + hour = value; + } + } + + /// + /// минута + /// + public int Minute + { + get => minute; + set + { + if (value > 59 || value < 0) + throw new ArgumentOutOfRangeException(nameof(minute), "minute should be in [0; 59]"); + minute = value; + } + } + + /// + /// секунда + /// + public int Second + { + get => second; + set + { + if (value > 59 || value < 0) + throw new ArgumentOutOfRangeException(nameof(second), "second should be in [0; 59]"); + second = value; + } + } + + /// + /// Кол-во секунд с начала суток + /// + public int TotalSeconds => (Hour * 60 + minute) * 60 + second; + + /// + public TimeDto() + { } + + /// + public TimeDto(int hour = 0, int minute = 0, int second = 0) + { + this.hour = hour; + this.minute = minute; + this.second = second; + } + + /// + public TimeDto(TimeOnly time) + { + hour = time.Hour; + minute = time.Minute; + second = time.Second; + } + + /// + public TimeDto(DateTime fullDate) + { + hour = fullDate.Hour; + minute = fullDate.Minute; + second = fullDate.Second; + } + + /// + public TimeDto(DateTimeOffset fullDate) + { + hour = fullDate.Hour; + minute = fullDate.Minute; + second = fullDate.Second; + } + + /// + /// Makes System.TimeOnly + /// + /// System.TimeOnly + public TimeOnly MakeTimeOnly() => new(Hour, Minute, Second); + + /// + public override string ToString() + { + var str = $"{Hour:00}:{Minute:00}:{Second:00}"; + return str; + } + + /// + public static bool operator ==(TimeDto a, TimeDto b) => a?.TotalSeconds == b?.TotalSeconds; + + /// + public static bool operator !=(TimeDto a, TimeDto b) => !(a == b); + + /// + public static bool operator <=(TimeDto a, TimeDto b) => a.TotalSeconds <= b.TotalSeconds; + + /// + public static bool operator >=(TimeDto a, TimeDto b) => a.TotalSeconds >= b.TotalSeconds; + + /// + public static bool operator <(TimeDto a, TimeDto b) => a.TotalSeconds < b.TotalSeconds; + + /// + public static bool operator >(TimeDto a, TimeDto b) => a.TotalSeconds > b.TotalSeconds; + + /// + public int CompareTo(TimeDto? other) + => TotalSeconds - other?.TotalSeconds??0; + + /// + public override bool Equals(object? obj) + { + if (ReferenceEquals(this, obj)) + { + return true; } - /// - /// минута - /// - public int Minute + if (obj is null) { - get => minute; - set - { - if (value > 59 || value < 0) - throw new ArgumentOutOfRangeException(nameof(minute), "minute should be in [0; 59]"); - minute = value; - } - } - - /// - /// секунда - /// - public int Second - { - get => second; - set - { - if (value > 59 || value < 0) - throw new ArgumentOutOfRangeException(nameof(second), "second should be in [0; 59]"); - second = value; - } - } - - /// - /// Кол-во секунд с начала суток - /// - public int TotalSeconds => (Hour * 60 + minute) * 60 + second; - - /// - public TimeDto() - { } - - /// - public TimeDto(int hour = 0, int minute = 0, int second = 0) - { - this.hour = hour; - this.minute = minute; - this.second = second; - } - - /// - public TimeDto(TimeOnly time) - { - hour = time.Hour; - minute = time.Minute; - second = time.Second; - } - - /// - public TimeDto(DateTime fullDate) - { - hour = fullDate.Hour; - minute = fullDate.Minute; - second = fullDate.Second; - } - - /// - public TimeDto(DateTimeOffset fullDate) - { - hour = fullDate.Hour; - minute = fullDate.Minute; - second = fullDate.Second; - } - - /// - /// Makes System.TimeOnly - /// - /// System.TimeOnly - public TimeOnly MakeTimeOnly() => new(Hour, Minute, Second); - - /// - public override string ToString() - { - var str = $"{Hour:00}:{Minute:00}:{Second:00}"; - return str; - } - - /// - public static bool operator ==(TimeDto a, TimeDto b) => a?.TotalSeconds == b?.TotalSeconds; - - /// - public static bool operator !=(TimeDto a, TimeDto b) => !(a == b); - - /// - public static bool operator <=(TimeDto a, TimeDto b) => a.TotalSeconds <= b.TotalSeconds; - - /// - public static bool operator >=(TimeDto a, TimeDto b) => a.TotalSeconds >= b.TotalSeconds; - - /// - public static bool operator <(TimeDto a, TimeDto b) => a.TotalSeconds < b.TotalSeconds; - - /// - public static bool operator >(TimeDto a, TimeDto b) => a.TotalSeconds > b.TotalSeconds; - - /// - public int CompareTo(TimeDto? other) - => TotalSeconds - other?.TotalSeconds??0; - - /// - public override bool Equals(object? obj) - { - if (ReferenceEquals(this, obj)) - { - return true; - } - - if (obj is null) - { - return false; - } - - if (obj is TimeDto objTime) - { - return objTime == this; - } - return false; } - /// - public override int GetHashCode() + if (obj is TimeDto objTime) { - return base.GetHashCode(); + return objTime == this; } + + return false; + } + + /// + public override int GetHashCode() + { + return base.GetHashCode(); } } diff --git a/AsbCloudApp/Data/Trajectory/TrajectoryCartesianFactDto.cs b/AsbCloudApp/Data/Trajectory/TrajectoryCartesianFactDto.cs index 218462db..bff00570 100644 --- a/AsbCloudApp/Data/Trajectory/TrajectoryCartesianFactDto.cs +++ b/AsbCloudApp/Data/Trajectory/TrajectoryCartesianFactDto.cs @@ -1,30 +1,29 @@ -namespace AsbCloudApp.Data.Trajectory +namespace AsbCloudApp.Data.Trajectory; + + + +/// +/// Визуализация траектории 3D +/// +public class TrajectoryCartesianDto { - + /// + /// Координаты по оси X, в сторону востока (м) + /// + public double X { get; set; } /// - /// Визуализация траектории 3D + /// Координаты по оси Y, в высоту (м) /// - public class TrajectoryCartesianDto - { - /// - /// Координаты по оси X, в сторону востока (м) - /// - public double X { get; set; } - - /// - /// Координаты по оси Y, в высоту (м) - /// - public double Y { get; set; } - - /// - /// Координаты по оси Z, в сторону юга (м) - /// - public double Z { get; set; } - } + public double Y { get; set; } /// - /// Визуализация фактической траектории 3D + /// Координаты по оси Z, в сторону юга (м) /// - public class TrajectoryCartesianFactDto : TrajectoryCartesianDto { } + public double Z { get; set; } } + +/// +/// Визуализация фактической траектории 3D +/// +public class TrajectoryCartesianFactDto : TrajectoryCartesianDto { } diff --git a/AsbCloudApp/Data/Trajectory/TrajectoryCartesianPlanDto.cs b/AsbCloudApp/Data/Trajectory/TrajectoryCartesianPlanDto.cs index 91096ad6..fc31e9d3 100644 --- a/AsbCloudApp/Data/Trajectory/TrajectoryCartesianPlanDto.cs +++ b/AsbCloudApp/Data/Trajectory/TrajectoryCartesianPlanDto.cs @@ -1,18 +1,17 @@ -namespace AsbCloudApp.Data.Trajectory +namespace AsbCloudApp.Data.Trajectory; + +/// +/// Визуализация траектории 3D для построения радиуса цели +/// +public class TrajectoryCartesianPlanDto : TrajectoryCartesianFactDto { /// - /// Визуализация траектории 3D для построения радиуса цели + /// радиус цели /// - public class TrajectoryCartesianPlanDto : TrajectoryCartesianFactDto - { - /// - /// радиус цели - /// - public double? Radius { get; set; } + public double? Radius { get; set; } - /// - /// комментарий - /// - public string? Comment { get; set; } - } + /// + /// комментарий + /// + public string? Comment { get; set; } } diff --git a/AsbCloudApp/Data/Trajectory/TrajectoryGeoDto.cs b/AsbCloudApp/Data/Trajectory/TrajectoryGeoDto.cs index 2c940043..987fa6ce 100644 --- a/AsbCloudApp/Data/Trajectory/TrajectoryGeoDto.cs +++ b/AsbCloudApp/Data/Trajectory/TrajectoryGeoDto.cs @@ -3,60 +3,59 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -namespace AsbCloudApp.Data.Trajectory +namespace AsbCloudApp.Data.Trajectory; + +/// +/// Базовая географическая траектория +/// +public abstract class TrajectoryGeoDto : IId, IValidatableObject { /// - /// Базовая географическая траектория + /// ИД строки с координатами + /// + public int Id { get; set; } + /// + /// Id скважины /// - public abstract class TrajectoryGeoDto : IId, IValidatableObject + public int IdWell { get; set; } + + /// + /// Глубина по стволу + /// + public double WellboreDepth { get; set; } + /// + /// Угол зенитный + /// + public double ZenithAngle { get; set; } + + /// + /// Азимут Географ. + /// + public double AzimuthGeo { get; set; } + + /// + /// Азимут Магнитный + /// + public double? AzimuthMagnetic { get; set; } + + /// + /// Глубина вертикальная + /// + public double? VerticalDepth { get; set; } + + /// + /// Дата загрузки + /// + public DateTimeOffset UpdateDate { get; set; } + + /// + /// ИД пользователя + /// + public int IdUser { get; set; } + + /// + public IEnumerable Validate(ValidationContext validationContext) { - /// - /// ИД строки с координатами - /// - public int Id { get; set; } - /// - /// Id скважины - /// - public int IdWell { get; set; } - - /// - /// Глубина по стволу - /// - public double WellboreDepth { get; set; } - /// - /// Угол зенитный - /// - public double ZenithAngle { get; set; } - - /// - /// Азимут Географ. - /// - public double AzimuthGeo { get; set; } - - /// - /// Азимут Магнитный - /// - public double? AzimuthMagnetic { get; set; } - - /// - /// Глубина вертикальная - /// - public double? VerticalDepth { get; set; } - - /// - /// Дата загрузки - /// - public DateTimeOffset UpdateDate { get; set; } - - /// - /// ИД пользователя - /// - public int IdUser { get; set; } - - /// - public IEnumerable Validate(ValidationContext validationContext) - { - return Enumerable.Empty(); - } + return Enumerable.Empty(); } } diff --git a/AsbCloudApp/Data/Trajectory/TrajectoryGeoPlanDto.cs b/AsbCloudApp/Data/Trajectory/TrajectoryGeoPlanDto.cs index 6730e6db..e13cb2e2 100644 --- a/AsbCloudApp/Data/Trajectory/TrajectoryGeoPlanDto.cs +++ b/AsbCloudApp/Data/Trajectory/TrajectoryGeoPlanDto.cs @@ -1,21 +1,20 @@ using System; -namespace AsbCloudApp.Data.Trajectory +namespace AsbCloudApp.Data.Trajectory; + +/// +/// Формирование данных по плановой географической траектории +/// +public class TrajectoryGeoPlanDto : TrajectoryGeoDto { /// - /// Формирование данных по плановой географической траектории + /// Радиус цели /// - public class TrajectoryGeoPlanDto : TrajectoryGeoDto - { - /// - /// Радиус цели - /// - public double? Radius { get; set; } + public double? Radius { get; set; } - /// - /// Комментарии - /// - public string? Comment { get; set; } - } + /// + /// Комментарии + /// + public string? Comment { get; set; } } diff --git a/AsbCloudApp/Data/Trajectory/TrajectoryPlanFactDto.cs b/AsbCloudApp/Data/Trajectory/TrajectoryPlanFactDto.cs index f691fb76..6fc18c7b 100644 --- a/AsbCloudApp/Data/Trajectory/TrajectoryPlanFactDto.cs +++ b/AsbCloudApp/Data/Trajectory/TrajectoryPlanFactDto.cs @@ -1,25 +1,24 @@ -namespace AsbCloudApp.Data.Trajectory +namespace AsbCloudApp.Data.Trajectory; + +/// +/// DTO объединяющее плановые и фактические значения траекторий +/// +/// +/// +public class TrajectoryPlanFactDto { /// - /// DTO объединяющее плановые и фактические значения траекторий + /// Плановое значение /// - /// - /// - public class TrajectoryPlanFactDto - { - /// - /// Плановое значение - /// - public T? Plan { get; set; } + public T? Plan { get; set; } - /// - /// Фактическое значение - /// - public V? FactManual { get; set; } + /// + /// Фактическое значение + /// + public V? FactManual { get; set; } - /// - /// Фактическое ннб-значение - /// - public V? FactNnb { get; set; } - } + /// + /// Фактическое ннб-значение + /// + public V? FactNnb { get; set; } } diff --git a/AsbCloudApp/Data/User/UserDto.cs b/AsbCloudApp/Data/User/UserDto.cs index ce1d6f4a..4ad8934a 100644 --- a/AsbCloudApp/Data/User/UserDto.cs +++ b/AsbCloudApp/Data/User/UserDto.cs @@ -1,96 +1,95 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data.User +namespace AsbCloudApp.Data.User; + +/// +/// DTO пользователя платформы +/// +public class UserDto : IId { + /// + public int Id { get; set; } + /// - /// DTO пользователя платформы + /// логин /// - public class UserDto : IId + [Required(ErrorMessage = "Логин не должен быть пустым")] + [StringLength(50, MinimumLength = 3, ErrorMessage = "Допустимая длина логина от 3 до 50 символов")] + public string Login { get; set; } = null!; + + /// + /// Имя + /// + [StringLength(50, MinimumLength = 0, ErrorMessage = "Допустимая длина имени от 1 до 50 символов")] + public string? Name { get; set; } + + /// + /// Фамилия + /// + [StringLength(50, MinimumLength = 0, ErrorMessage = "Допустимая длина фамилии от 1 до 50 символов")] + public string? Surname { get; set; } + + /// + /// Отчество + /// + [StringLength(50, MinimumLength = 0, ErrorMessage = "Допустимая длина отчества от 1 до 50 символов")] + public string? Patronymic { get; set; } + + /// + /// Email + /// + [Required] + [StringLength(260, MinimumLength = 3, ErrorMessage = "Допустимая длина email от 3 до 260 символов")] + public string Email { get; set; } = null!; + + /// + /// Phone + /// + [StringLength(50, MinimumLength = 1, ErrorMessage = "Допустимая длина телефона от 1 до 50 символов")] + public string? Phone { get; set; } + + /// + /// Должность + /// + [StringLength(100, MinimumLength = 1, ErrorMessage = "Допустимая длина должности от 1 до 100 символов")] + public string? Position { get; set; } + + /// + /// Id компании + /// + [Required] + public int IdCompany { get; set; } + + /// + /// Id состояния пользователя + /// 0 - не активен, + /// 1 - активен, + /// 2 - заблокирован + /// + public short IdState { get; set; } + + /// + /// DTO компании + /// + public CompanyDto? Company { get; set; } + + /// + /// Получение отображаемого имени + /// + /// + public string MakeDisplayName() { - /// - public int Id { get; set; } + if (string.IsNullOrEmpty(Surname)) + return Login; - /// - /// логин - /// - [Required(ErrorMessage = "Логин не должен быть пустым")] - [StringLength(50, MinimumLength = 3, ErrorMessage = "Допустимая длина логина от 3 до 50 символов")] - public string Login { get; set; } = null!; - - /// - /// Имя - /// - [StringLength(50, MinimumLength = 0, ErrorMessage = "Допустимая длина имени от 1 до 50 символов")] - public string? Name { get; set; } - - /// - /// Фамилия - /// - [StringLength(50, MinimumLength = 0, ErrorMessage = "Допустимая длина фамилии от 1 до 50 символов")] - public string? Surname { get; set; } - - /// - /// Отчество - /// - [StringLength(50, MinimumLength = 0, ErrorMessage = "Допустимая длина отчества от 1 до 50 символов")] - public string? Patronymic { get; set; } - - /// - /// Email - /// - [Required] - [StringLength(260, MinimumLength = 3, ErrorMessage = "Допустимая длина email от 3 до 260 символов")] - public string Email { get; set; } = null!; - - /// - /// Phone - /// - [StringLength(50, MinimumLength = 1, ErrorMessage = "Допустимая длина телефона от 1 до 50 символов")] - public string? Phone { get; set; } - - /// - /// Должность - /// - [StringLength(100, MinimumLength = 1, ErrorMessage = "Допустимая длина должности от 1 до 100 символов")] - public string? Position { get; set; } - - /// - /// Id компании - /// - [Required] - public int IdCompany { get; set; } - - /// - /// Id состояния пользователя - /// 0 - не активен, - /// 1 - активен, - /// 2 - заблокирован - /// - public short IdState { get; set; } - - /// - /// DTO компании - /// - public CompanyDto? Company { get; set; } - - /// - /// Получение отображаемого имени - /// - /// - public string MakeDisplayName() + var s = Surname; + if (!string.IsNullOrEmpty(Name)) { - if (string.IsNullOrEmpty(Surname)) - return Login; - - var s = Surname; - if (!string.IsNullOrEmpty(Name)) - { - s += $"{Name[0]}."; - if (!string.IsNullOrEmpty(Patronymic)) - s += $" {Patronymic[0]}."; - } - - return s; + s += $"{Name[0]}."; + if (!string.IsNullOrEmpty(Patronymic)) + s += $" {Patronymic[0]}."; } + + return s; } } diff --git a/AsbCloudApp/Data/User/UserExtendedDto.cs b/AsbCloudApp/Data/User/UserExtendedDto.cs index 9cec40a6..2ac5e498 100644 --- a/AsbCloudApp/Data/User/UserExtendedDto.cs +++ b/AsbCloudApp/Data/User/UserExtendedDto.cs @@ -1,14 +1,13 @@ using System.Collections.Generic; using System.Linq; -namespace AsbCloudApp.Data.User +namespace AsbCloudApp.Data.User; + +/// +public class UserExtendedDto : UserDto { - /// - public class UserExtendedDto : UserDto - { - /// - /// Роли пользователя - /// - public IEnumerable RoleNames { get; set; } = Enumerable.Empty(); - } + /// + /// Роли пользователя + /// + public IEnumerable RoleNames { get; set; } = Enumerable.Empty(); } diff --git a/AsbCloudApp/Data/User/UserRegistrationDto.cs b/AsbCloudApp/Data/User/UserRegistrationDto.cs index 26530fa4..403de12f 100644 --- a/AsbCloudApp/Data/User/UserRegistrationDto.cs +++ b/AsbCloudApp/Data/User/UserRegistrationDto.cs @@ -1,15 +1,14 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data.User +namespace AsbCloudApp.Data.User; + +/// +public class UserRegistrationDto : UserDto { - /// - public class UserRegistrationDto : UserDto - { - /// - /// пароль, используется только при регистрации. - /// - [Required(ErrorMessage = "Пароль не должен быть пустым")] - [StringLength(50, MinimumLength = 3, ErrorMessage = "Допустимая длина пароля от 3 до 50 символов")] - public string Password { get; set; } = null!; - } + /// + /// пароль, используется только при регистрации. + /// + [Required(ErrorMessage = "Пароль не должен быть пустым")] + [StringLength(50, MinimumLength = 3, ErrorMessage = "Допустимая длина пароля от 3 до 50 символов")] + public string Password { get; set; } = null!; } diff --git a/AsbCloudApp/Data/User/UserRoleDto.cs b/AsbCloudApp/Data/User/UserRoleDto.cs index 68f54434..d78a2d4c 100644 --- a/AsbCloudApp/Data/User/UserRoleDto.cs +++ b/AsbCloudApp/Data/User/UserRoleDto.cs @@ -2,36 +2,35 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -namespace AsbCloudApp.Data.User +namespace AsbCloudApp.Data.User; + +/// +/// Роль пользователя платформы +/// +public class UserRoleDto : IId { + /// + public int Id { get; set; } + /// - /// Роль пользователя платформы + /// название /// - public class UserRoleDto : IId - { - /// - public int Id { get; set; } + [Required] + [StringLength(50, MinimumLength = 1, ErrorMessage = "Допустимая длина названия роли от 1 до 50 символов")] + public string Caption { get; set; } = null!; - /// - /// название - /// - [Required] - [StringLength(50, MinimumLength = 1, ErrorMessage = "Допустимая длина названия роли от 1 до 50 символов")] - public string Caption { get; set; } = null!; + /// + /// id типа роли + /// + public int IdType { get; set; } - /// - /// id типа роли - /// - public int IdType { get; set; } + /// + /// список разрешений + /// + public IEnumerable Permissions { get; set; } = Enumerable.Empty(); - /// - /// список разрешений - /// - public IEnumerable Permissions { get; set; } = Enumerable.Empty(); - - /// - /// Включенные роли - /// - public virtual IEnumerable Roles { get; set; } = Enumerable.Empty(); - } + /// + /// Включенные роли + /// + public virtual IEnumerable Roles { get; set; } = Enumerable.Empty(); } diff --git a/AsbCloudApp/Data/User/UserTokenDto.cs b/AsbCloudApp/Data/User/UserTokenDto.cs index e11a1f8f..ca91f3a6 100644 --- a/AsbCloudApp/Data/User/UserTokenDto.cs +++ b/AsbCloudApp/Data/User/UserTokenDto.cs @@ -1,19 +1,18 @@ using System.Collections.Generic; using System.Linq; -namespace AsbCloudApp.Data.User -{ - /// - public class UserTokenDto : UserExtendedDto - { - /// - /// все разрешения пользователя - /// - public IEnumerable Permissions { get; set; } = Enumerable.Empty(); +namespace AsbCloudApp.Data.User; - /// - /// bearer token (для работы с web-api) - /// - public string Token { get; set; } = null!; - } +/// +public class UserTokenDto : UserExtendedDto +{ + /// + /// все разрешения пользователя + /// + public IEnumerable Permissions { get; set; } = Enumerable.Empty(); + + /// + /// bearer token (для работы с web-api) + /// + public string Token { get; set; } = null!; } diff --git a/AsbCloudApp/Data/WITS/Record1Dto.cs b/AsbCloudApp/Data/WITS/Record1Dto.cs index 28a0aaa2..0d0fa162 100644 --- a/AsbCloudApp/Data/WITS/Record1Dto.cs +++ b/AsbCloudApp/Data/WITS/Record1Dto.cs @@ -1,582 +1,581 @@ -namespace AsbCloudApp.Data.WITS +namespace AsbCloudApp.Data.WITS; + +/// +/// Record name: General Time-Based +/// Description: Drilling data gathered at regular time intervals +/// + +public class Record1Dto : RecordBaseDto { + /// - /// Record name: General Time-Based - /// Description: Drilling data gathered at regular time intervals + /// RecordId = 1, + /// ItemId = 8, + /// LongMnemonic = "DEPTBITM", + /// ShortMnemonic = "DBTM", + /// Description = "Depth Bit (meas)", + /// Description2 = "Code indicating what activity is currently being performed on the rig. IT IS ESSENTIAL that this information be as accurate and current as possible. Acceptable codes are shown here", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" /// - public class Record1Dto : RecordBaseDto - { - - /// - /// RecordId = 1, - /// ItemId = 8, - /// LongMnemonic = "DEPTBITM", - /// ShortMnemonic = "DBTM", - /// Description = "Depth Bit (meas)", - /// Description2 = "Code indicating what activity is currently being performed on the rig. IT IS ESSENTIAL that this information be as accurate and current as possible. Acceptable codes are shown here", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptbitm { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 9, - /// LongMnemonic = "DEPTBITV", - /// ShortMnemonic = "DBTV", - /// Description = "Depth Bit (vert)", - /// Description2 = "Measured depth of the bit at the time the record is generated. This is the measured depth of the shoe when running casing or liner.", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptbitv { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 10, - /// LongMnemonic = "DEPTMEAS", - /// ShortMnemonic = "DMEA", - /// Description = "Depth Hole (meas)", - /// Description2 = "Vertical depth of the bit at the time the record is generated. This is the vertical depth of the shoe when running casing or liner.", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptmeas { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 11, - /// LongMnemonic = "DEPTVERT", - /// ShortMnemonic = "DVER", - /// Description = "Depth Hole (vet)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptvert { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 12, - /// LongMnemonic = "BLKPOS", - /// ShortMnemonic = "BPOS", - /// Description = "Block Position", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Blkpos { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 13, - /// LongMnemonic = "ROPA", - /// ShortMnemonic = "ROPA", - /// Description = "Rate of Penetration (avg)", - /// Description2 = "", - /// FPSUnits = "F/HR", - /// MetricUnits = "M/HR", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Ropa { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 14, - /// LongMnemonic = "HKLA", - /// ShortMnemonic = "HKLA", - /// Description = "Hook-load (avg)", - /// Description2 = "", - /// FPSUnits = "KLB", - /// MetricUnits = "KDN", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Hkla { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 15, - /// LongMnemonic = "HKLX", - /// ShortMnemonic = "HKLX", - /// Description = "Hook-load (max)", - /// Description2 = "", - /// FPSUnits = "KLB", - /// MetricUnits = "KDN", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Hklx { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 16, - /// LongMnemonic = "WOBA", - /// ShortMnemonic = "WOBA", - /// Description = "Weight-on-Bit (surf,avg)", - /// Description2 = "", - /// FPSUnits = "KLB", - /// MetricUnits = "KDN", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Woba { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 17, - /// LongMnemonic = "WOBX", - /// ShortMnemonic = "WOBX", - /// Description = "Weight-on-Bit (surf,max)", - /// Description2 = "", - /// FPSUnits = "KLB", - /// MetricUnits = "KDN", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Wobx { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 18, - /// LongMnemonic = "TORQA", - /// ShortMnemonic = "TQA", - /// Description = "Rotary Torque (surf,avg)", - /// Description2 = "", - /// FPSUnits = "KFLB", - /// MetricUnits = "KNM", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Torqa { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 19, - /// LongMnemonic = "TORQX", - /// ShortMnemonic = "TQX", - /// Description = "Rotary Torque (surf,max)", - /// Description2 = "", - /// FPSUnits = "KFLB", - /// MetricUnits = "KNM", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Torqx { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 20, - /// LongMnemonic = "RPMA", - /// ShortMnemonic = "RPMA", - /// Description = "Rotary Speed (surf,avg)", - /// Description2 = "", - /// FPSUnits = "RPM", - /// MetricUnits = "RPM", - /// Length = 2, - /// ValueType = "S" - /// - - public short? Rpma { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 21, - /// LongMnemonic = "SPPA", - /// ShortMnemonic = "SPPA", - /// Description = "Standpipe Pressure (avg)", - /// Description2 = "", - /// FPSUnits = "PSI", - /// MetricUnits = "KPA", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Sppa { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 22, - /// LongMnemonic = "CHKP", - /// ShortMnemonic = "CHKP", - /// Description = "Casing (Choke) Pressure", - /// Description2 = "", - /// FPSUnits = "PSI", - /// MetricUnits = "KPA", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Chkp { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 23, - /// LongMnemonic = "SPM1", - /// ShortMnemonic = "SPM1", - /// Description = "Pump Stroke Rate #1", - /// Description2 = "", - /// FPSUnits = "SPM", - /// MetricUnits = "SPM", - /// Length = 2, - /// ValueType = "S" - /// - - public short? Spm1 { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 24, - /// LongMnemonic = "SPM2", - /// ShortMnemonic = "SPM2", - /// Description = "Pump Stroke Rate #2", - /// Description2 = "", - /// FPSUnits = "SPM", - /// MetricUnits = "SPM", - /// Length = 2, - /// ValueType = "S" - /// - - public short? Spm2 { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 25, - /// LongMnemonic = "SPM3", - /// ShortMnemonic = "SPM3", - /// Description = "Pump Stroke Rate #3", - /// Description2 = "", - /// FPSUnits = "SPM", - /// MetricUnits = "SPM", - /// Length = 2, - /// ValueType = "S" - /// - - public short? Spm3 { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 26, - /// LongMnemonic = "TVOLACT", - /// ShortMnemonic = "TVA", - /// Description = "Tank Volume (active)", - /// Description2 = "", - /// FPSUnits = "BBL", - /// MetricUnits = "M3", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Tvolact { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 27, - /// LongMnemonic = "TVOLCACT", - /// ShortMnemonic = "TVCA", - /// Description = "Tank Volume Change (act)", - /// Description2 = "", - /// FPSUnits = "BBL", - /// MetricUnits = "M3", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Tvolcact { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 28, - /// LongMnemonic = "MFOP", - /// ShortMnemonic = "MFOP", - /// Description = "Mud Flow Out %", - /// Description2 = "", - /// FPSUnits = "%", - /// MetricUnits = "%", - /// Length = 2, - /// ValueType = "S" - /// - - public short? Mfop { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 29, - /// LongMnemonic = "MFOA", - /// ShortMnemonic = "MFOA", - /// Description = "Mud Flow Out (avg)", - /// Description2 = "", - /// FPSUnits = "GPM", - /// MetricUnits = "L/M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mfoa { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 30, - /// LongMnemonic = "MFIA", - /// ShortMnemonic = "MFIA", - /// Description = "Mud Flow In (avg)", - /// Description2 = "", - /// FPSUnits = "GPM", - /// MetricUnits = "L/M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mfia { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 31, - /// LongMnemonic = "MDOA", - /// ShortMnemonic = "MDOA", - /// Description = "Mud Density Out (avg)", - /// Description2 = "", - /// FPSUnits = "PPG", - /// MetricUnits = "KGM3", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mdoa { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 32, - /// LongMnemonic = "MDIA", - /// ShortMnemonic = "MDIA", - /// Description = "Mud Density In (avg)", - /// Description2 = "", - /// FPSUnits = "PPG", - /// MetricUnits = "KGM3", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mdia { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 33, - /// LongMnemonic = "MTOA", - /// ShortMnemonic = "MTOA", - /// Description = "Mud Temperature Out (avg)", - /// Description2 = "", - /// FPSUnits = "DEGF", - /// MetricUnits = "DEGC", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mtoa { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 34, - /// LongMnemonic = "MTIA", - /// ShortMnemonic = "MTIA", - /// Description = "Mud Temperature In (avg)", - /// Description2 = "", - /// FPSUnits = "DEGF", - /// MetricUnits = "DEGC", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mtia { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 35, - /// LongMnemonic = "MCOA", - /// ShortMnemonic = "MCOA", - /// Description = "Mud Conductivity Out (avg)", - /// Description2 = "", - /// FPSUnits = "MMHO", - /// MetricUnits = "MMHO", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mcoa { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 36, - /// LongMnemonic = "MCIA", - /// ShortMnemonic = "MCIA", - /// Description = "Mud Conductivity In (avg)", - /// Description2 = "", - /// FPSUnits = "MMHO", - /// MetricUnits = "MMHO", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mcia { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 37, - /// LongMnemonic = "STKC", - /// ShortMnemonic = "STKC", - /// Description = "Pump Stroke Count (cum)", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "L" - /// - - public int? Stkc { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 38, - /// LongMnemonic = "LAGSTKS", - /// ShortMnemonic = "LSTK", - /// Description = "Lag Strokes", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 2, - /// ValueType = "S" - /// - - public short? Lagstks { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 39, - /// LongMnemonic = "DEPTRETM", - /// ShortMnemonic = "DRTM", - /// Description = "Depth Returns (meas)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptretm { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 40, - /// LongMnemonic = "GASA", - /// ShortMnemonic = "GASA", - /// Description = "Gas (avg)", - /// Description2 = "", - /// FPSUnits = "%", - /// MetricUnits = "%", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Gasa { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 41, - /// LongMnemonic = "SPARE1", - /// ShortMnemonic = "SPR1", - /// Description = "SPARE 1", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Spare1 { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 42, - /// LongMnemonic = "SPARE2", - /// ShortMnemonic = "SPR2", - /// Description = "SPARE 2", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Spare2 { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 43, - /// LongMnemonic = "SPARE3", - /// ShortMnemonic = "SPR3", - /// Description = "SPARE 3", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Spare3 { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 44, - /// LongMnemonic = "SPARE4", - /// ShortMnemonic = "SPR4", - /// Description = "SPARE 4", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Spare4 { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 45, - /// LongMnemonic = "SPARE5", - /// ShortMnemonic = "SPR5", - /// Description = "SPARE 5", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Spare5 { get; set; } - - } + public float? Deptbitm { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 9, + /// LongMnemonic = "DEPTBITV", + /// ShortMnemonic = "DBTV", + /// Description = "Depth Bit (vert)", + /// Description2 = "Measured depth of the bit at the time the record is generated. This is the measured depth of the shoe when running casing or liner.", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptbitv { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 10, + /// LongMnemonic = "DEPTMEAS", + /// ShortMnemonic = "DMEA", + /// Description = "Depth Hole (meas)", + /// Description2 = "Vertical depth of the bit at the time the record is generated. This is the vertical depth of the shoe when running casing or liner.", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptmeas { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 11, + /// LongMnemonic = "DEPTVERT", + /// ShortMnemonic = "DVER", + /// Description = "Depth Hole (vet)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptvert { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 12, + /// LongMnemonic = "BLKPOS", + /// ShortMnemonic = "BPOS", + /// Description = "Block Position", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Blkpos { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 13, + /// LongMnemonic = "ROPA", + /// ShortMnemonic = "ROPA", + /// Description = "Rate of Penetration (avg)", + /// Description2 = "", + /// FPSUnits = "F/HR", + /// MetricUnits = "M/HR", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Ropa { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 14, + /// LongMnemonic = "HKLA", + /// ShortMnemonic = "HKLA", + /// Description = "Hook-load (avg)", + /// Description2 = "", + /// FPSUnits = "KLB", + /// MetricUnits = "KDN", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Hkla { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 15, + /// LongMnemonic = "HKLX", + /// ShortMnemonic = "HKLX", + /// Description = "Hook-load (max)", + /// Description2 = "", + /// FPSUnits = "KLB", + /// MetricUnits = "KDN", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Hklx { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 16, + /// LongMnemonic = "WOBA", + /// ShortMnemonic = "WOBA", + /// Description = "Weight-on-Bit (surf,avg)", + /// Description2 = "", + /// FPSUnits = "KLB", + /// MetricUnits = "KDN", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Woba { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 17, + /// LongMnemonic = "WOBX", + /// ShortMnemonic = "WOBX", + /// Description = "Weight-on-Bit (surf,max)", + /// Description2 = "", + /// FPSUnits = "KLB", + /// MetricUnits = "KDN", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Wobx { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 18, + /// LongMnemonic = "TORQA", + /// ShortMnemonic = "TQA", + /// Description = "Rotary Torque (surf,avg)", + /// Description2 = "", + /// FPSUnits = "KFLB", + /// MetricUnits = "KNM", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Torqa { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 19, + /// LongMnemonic = "TORQX", + /// ShortMnemonic = "TQX", + /// Description = "Rotary Torque (surf,max)", + /// Description2 = "", + /// FPSUnits = "KFLB", + /// MetricUnits = "KNM", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Torqx { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 20, + /// LongMnemonic = "RPMA", + /// ShortMnemonic = "RPMA", + /// Description = "Rotary Speed (surf,avg)", + /// Description2 = "", + /// FPSUnits = "RPM", + /// MetricUnits = "RPM", + /// Length = 2, + /// ValueType = "S" + /// + + public short? Rpma { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 21, + /// LongMnemonic = "SPPA", + /// ShortMnemonic = "SPPA", + /// Description = "Standpipe Pressure (avg)", + /// Description2 = "", + /// FPSUnits = "PSI", + /// MetricUnits = "KPA", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Sppa { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 22, + /// LongMnemonic = "CHKP", + /// ShortMnemonic = "CHKP", + /// Description = "Casing (Choke) Pressure", + /// Description2 = "", + /// FPSUnits = "PSI", + /// MetricUnits = "KPA", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Chkp { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 23, + /// LongMnemonic = "SPM1", + /// ShortMnemonic = "SPM1", + /// Description = "Pump Stroke Rate #1", + /// Description2 = "", + /// FPSUnits = "SPM", + /// MetricUnits = "SPM", + /// Length = 2, + /// ValueType = "S" + /// + + public short? Spm1 { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 24, + /// LongMnemonic = "SPM2", + /// ShortMnemonic = "SPM2", + /// Description = "Pump Stroke Rate #2", + /// Description2 = "", + /// FPSUnits = "SPM", + /// MetricUnits = "SPM", + /// Length = 2, + /// ValueType = "S" + /// + + public short? Spm2 { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 25, + /// LongMnemonic = "SPM3", + /// ShortMnemonic = "SPM3", + /// Description = "Pump Stroke Rate #3", + /// Description2 = "", + /// FPSUnits = "SPM", + /// MetricUnits = "SPM", + /// Length = 2, + /// ValueType = "S" + /// + + public short? Spm3 { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 26, + /// LongMnemonic = "TVOLACT", + /// ShortMnemonic = "TVA", + /// Description = "Tank Volume (active)", + /// Description2 = "", + /// FPSUnits = "BBL", + /// MetricUnits = "M3", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Tvolact { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 27, + /// LongMnemonic = "TVOLCACT", + /// ShortMnemonic = "TVCA", + /// Description = "Tank Volume Change (act)", + /// Description2 = "", + /// FPSUnits = "BBL", + /// MetricUnits = "M3", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Tvolcact { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 28, + /// LongMnemonic = "MFOP", + /// ShortMnemonic = "MFOP", + /// Description = "Mud Flow Out %", + /// Description2 = "", + /// FPSUnits = "%", + /// MetricUnits = "%", + /// Length = 2, + /// ValueType = "S" + /// + + public short? Mfop { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 29, + /// LongMnemonic = "MFOA", + /// ShortMnemonic = "MFOA", + /// Description = "Mud Flow Out (avg)", + /// Description2 = "", + /// FPSUnits = "GPM", + /// MetricUnits = "L/M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mfoa { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 30, + /// LongMnemonic = "MFIA", + /// ShortMnemonic = "MFIA", + /// Description = "Mud Flow In (avg)", + /// Description2 = "", + /// FPSUnits = "GPM", + /// MetricUnits = "L/M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mfia { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 31, + /// LongMnemonic = "MDOA", + /// ShortMnemonic = "MDOA", + /// Description = "Mud Density Out (avg)", + /// Description2 = "", + /// FPSUnits = "PPG", + /// MetricUnits = "KGM3", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mdoa { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 32, + /// LongMnemonic = "MDIA", + /// ShortMnemonic = "MDIA", + /// Description = "Mud Density In (avg)", + /// Description2 = "", + /// FPSUnits = "PPG", + /// MetricUnits = "KGM3", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mdia { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 33, + /// LongMnemonic = "MTOA", + /// ShortMnemonic = "MTOA", + /// Description = "Mud Temperature Out (avg)", + /// Description2 = "", + /// FPSUnits = "DEGF", + /// MetricUnits = "DEGC", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mtoa { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 34, + /// LongMnemonic = "MTIA", + /// ShortMnemonic = "MTIA", + /// Description = "Mud Temperature In (avg)", + /// Description2 = "", + /// FPSUnits = "DEGF", + /// MetricUnits = "DEGC", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mtia { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 35, + /// LongMnemonic = "MCOA", + /// ShortMnemonic = "MCOA", + /// Description = "Mud Conductivity Out (avg)", + /// Description2 = "", + /// FPSUnits = "MMHO", + /// MetricUnits = "MMHO", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mcoa { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 36, + /// LongMnemonic = "MCIA", + /// ShortMnemonic = "MCIA", + /// Description = "Mud Conductivity In (avg)", + /// Description2 = "", + /// FPSUnits = "MMHO", + /// MetricUnits = "MMHO", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mcia { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 37, + /// LongMnemonic = "STKC", + /// ShortMnemonic = "STKC", + /// Description = "Pump Stroke Count (cum)", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "L" + /// + + public int? Stkc { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 38, + /// LongMnemonic = "LAGSTKS", + /// ShortMnemonic = "LSTK", + /// Description = "Lag Strokes", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 2, + /// ValueType = "S" + /// + + public short? Lagstks { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 39, + /// LongMnemonic = "DEPTRETM", + /// ShortMnemonic = "DRTM", + /// Description = "Depth Returns (meas)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptretm { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 40, + /// LongMnemonic = "GASA", + /// ShortMnemonic = "GASA", + /// Description = "Gas (avg)", + /// Description2 = "", + /// FPSUnits = "%", + /// MetricUnits = "%", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Gasa { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 41, + /// LongMnemonic = "SPARE1", + /// ShortMnemonic = "SPR1", + /// Description = "SPARE 1", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Spare1 { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 42, + /// LongMnemonic = "SPARE2", + /// ShortMnemonic = "SPR2", + /// Description = "SPARE 2", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Spare2 { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 43, + /// LongMnemonic = "SPARE3", + /// ShortMnemonic = "SPR3", + /// Description = "SPARE 3", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Spare3 { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 44, + /// LongMnemonic = "SPARE4", + /// ShortMnemonic = "SPR4", + /// Description = "SPARE 4", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Spare4 { get; set; } + + /// + /// RecordId = 1, + /// ItemId = 45, + /// LongMnemonic = "SPARE5", + /// ShortMnemonic = "SPR5", + /// Description = "SPARE 5", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Spare5 { get; set; } + } diff --git a/AsbCloudApp/Data/WITS/Record50Dto.cs b/AsbCloudApp/Data/WITS/Record50Dto.cs index c72fa154..a7d848d5 100644 --- a/AsbCloudApp/Data/WITS/Record50Dto.cs +++ b/AsbCloudApp/Data/WITS/Record50Dto.cs @@ -1,298 +1,297 @@ -namespace AsbCloudApp.Data.WITS +namespace AsbCloudApp.Data.WITS; + +/// +/// Record name: Резистивиметр MCR +/// Description: SibReciver. Резистивиметр MCR +/// Description2: +/// + +public class Record50Dto : RecordBaseDto { + /// - /// Record name: Резистивиметр MCR - /// Description: SibReciver. Резистивиметр MCR - /// Description2: + /// RecordId = 50, + /// ItemId = 8, + /// LongMnemonic = "DEPTBITM", + /// ShortMnemonic = "DBTM", + /// Description = "SibReceiver custom. Положение долота", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" /// - public class Record50Dto : RecordBaseDto - { + public float? Deptbitm { get; set; } - /// - /// RecordId = 50, - /// ItemId = 8, - /// LongMnemonic = "DEPTBITM", - /// ShortMnemonic = "DBTM", - /// Description = "SibReceiver custom. Положение долота", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 50, + /// ItemId = 10, + /// LongMnemonic = "DEPTMEAS_MCRSTAT", + /// ShortMnemonic = "DEPTMEAS_MCRSTAT", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Deptbitm { get; set; } + public float? DeptmeasMcrstat { get; set; } - /// - /// RecordId = 50, - /// ItemId = 10, - /// LongMnemonic = "DEPTMEAS_MCRSTAT", - /// ShortMnemonic = "DEPTMEAS_MCRSTAT", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 50, + /// ItemId = 11, + /// LongMnemonic = "MCRSTAT", + /// ShortMnemonic = "MCRSTAT", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? DeptmeasMcrstat { get; set; } + public float? Mcrstat { get; set; } - /// - /// RecordId = 50, - /// ItemId = 11, - /// LongMnemonic = "MCRSTAT", - /// ShortMnemonic = "MCRSTAT", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 50, + /// ItemId = 12, + /// LongMnemonic = "DEPTMEAS_SLVL_mc", + /// ShortMnemonic = "DEPTMEAS_SLVL_mc", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Mcrstat { get; set; } + public float? DeptmeasSlvlMc { get; set; } - /// - /// RecordId = 50, - /// ItemId = 12, - /// LongMnemonic = "DEPTMEAS_SLVL_mc", - /// ShortMnemonic = "DEPTMEAS_SLVL_mc", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 50, + /// ItemId = 13, + /// LongMnemonic = "SLVL_mc", + /// ShortMnemonic = "SLVL_mc", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? DeptmeasSlvlMc { get; set; } + public float? SlvlMc { get; set; } - /// - /// RecordId = 50, - /// ItemId = 13, - /// LongMnemonic = "SLVL_mc", - /// ShortMnemonic = "SLVL_mc", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 50, + /// ItemId = 14, + /// LongMnemonic = "DEPTMEAS_GDP_mc", + /// ShortMnemonic = "DEPTMEAS_GDP_mc", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? SlvlMc { get; set; } + public float? DeptmeasGdpMc { get; set; } - /// - /// RecordId = 50, - /// ItemId = 14, - /// LongMnemonic = "DEPTMEAS_GDP_mc", - /// ShortMnemonic = "DEPTMEAS_GDP_mc", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 50, + /// ItemId = 15, + /// LongMnemonic = "GDP_mc", + /// ShortMnemonic = "GDP_mc", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? DeptmeasGdpMc { get; set; } + public float? GdpMc { get; set; } - /// - /// RecordId = 50, - /// ItemId = 15, - /// LongMnemonic = "GDP_mc", - /// ShortMnemonic = "GDP_mc", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 50, + /// ItemId = 16, + /// LongMnemonic = "DEPTMEAS_RA33F2_mc", + /// ShortMnemonic = "DEPTMEAS_RA33F2_mc", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? GdpMc { get; set; } + public float? DeptmeasRa33f2Mc { get; set; } - /// - /// RecordId = 50, - /// ItemId = 16, - /// LongMnemonic = "DEPTMEAS_RA33F2_mc", - /// ShortMnemonic = "DEPTMEAS_RA33F2_mc", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 50, + /// ItemId = 17, + /// LongMnemonic = "RA33F2_mc", + /// ShortMnemonic = "RA33F2_mc", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? DeptmeasRa33f2Mc { get; set; } + public float? Ra33f2Mc { get; set; } - /// - /// RecordId = 50, - /// ItemId = 17, - /// LongMnemonic = "RA33F2_mc", - /// ShortMnemonic = "RA33F2_mc", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 50, + /// ItemId = 18, + /// LongMnemonic = "DEPTMEAS_RP33F2_mc", + /// ShortMnemonic = "DEPTMEAS_RP33F2_mc", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Ra33f2Mc { get; set; } + public float? DeptmeasRp33f2Mc { get; set; } - /// - /// RecordId = 50, - /// ItemId = 18, - /// LongMnemonic = "DEPTMEAS_RP33F2_mc", - /// ShortMnemonic = "DEPTMEAS_RP33F2_mc", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 50, + /// ItemId = 19, + /// LongMnemonic = "RP33F2_mc", + /// ShortMnemonic = "RP33F2_mc", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? DeptmeasRp33f2Mc { get; set; } + public float? Rp33f2Mc { get; set; } - /// - /// RecordId = 50, - /// ItemId = 19, - /// LongMnemonic = "RP33F2_mc", - /// ShortMnemonic = "RP33F2_mc", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 50, + /// ItemId = 20, + /// LongMnemonic = "DEPTMEAS_RA33F4_mc", + /// ShortMnemonic = "DEPTMEAS_RA33F4_mc", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Rp33f2Mc { get; set; } + public float? DeptmeasRa33f4Mc { get; set; } - /// - /// RecordId = 50, - /// ItemId = 20, - /// LongMnemonic = "DEPTMEAS_RA33F4_mc", - /// ShortMnemonic = "DEPTMEAS_RA33F4_mc", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 50, + /// ItemId = 21, + /// LongMnemonic = "RA33F4_mc", + /// ShortMnemonic = "RA33F4_mc", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? DeptmeasRa33f4Mc { get; set; } + public float? Ra33f4Mc { get; set; } - /// - /// RecordId = 50, - /// ItemId = 21, - /// LongMnemonic = "RA33F4_mc", - /// ShortMnemonic = "RA33F4_mc", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 50, + /// ItemId = 22, + /// LongMnemonic = "DEPTMEAS_RP33F4_mc", + /// ShortMnemonic = "DEPTMEAS_RP33F4_mc", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Ra33f4Mc { get; set; } + public float? DeptmeasRp33f4Mc { get; set; } - /// - /// RecordId = 50, - /// ItemId = 22, - /// LongMnemonic = "DEPTMEAS_RP33F4_mc", - /// ShortMnemonic = "DEPTMEAS_RP33F4_mc", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 50, + /// ItemId = 23, + /// LongMnemonic = "RP33F4_mc", + /// ShortMnemonic = "RP33F4_mc", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? DeptmeasRp33f4Mc { get; set; } + public float? Rp33f4Mc { get; set; } - /// - /// RecordId = 50, - /// ItemId = 23, - /// LongMnemonic = "RP33F4_mc", - /// ShortMnemonic = "RP33F4_mc", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 50, + /// ItemId = 46, + /// LongMnemonic = "DEPTMEAS_RA33_mc", + /// ShortMnemonic = "DEPTMEAS_RA33_mc", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Rp33f4Mc { get; set; } + public float? DeptmeasRa33Mc { get; set; } - /// - /// RecordId = 50, - /// ItemId = 46, - /// LongMnemonic = "DEPTMEAS_RA33_mc", - /// ShortMnemonic = "DEPTMEAS_RA33_mc", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 50, + /// ItemId = 47, + /// LongMnemonic = "RA33_mc", + /// ShortMnemonic = "RA33_mc", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? DeptmeasRa33Mc { get; set; } + public float? Ra33Mc { get; set; } - /// - /// RecordId = 50, - /// ItemId = 47, - /// LongMnemonic = "RA33_mc", - /// ShortMnemonic = "RA33_mc", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 50, + /// ItemId = 28, + /// LongMnemonic = "DEPTMEAS_RP33_mc", + /// ShortMnemonic = "DEPTMEAS_RP33_mc", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Ra33Mc { get; set; } + public float? DeptmeasRp33Mc { get; set; } - /// - /// RecordId = 50, - /// ItemId = 28, - /// LongMnemonic = "DEPTMEAS_RP33_mc", - /// ShortMnemonic = "DEPTMEAS_RP33_mc", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 50, + /// ItemId = 29, + /// LongMnemonic = "RP33_mc", + /// ShortMnemonic = "RP33_mc", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? DeptmeasRp33Mc { get; set; } + public float? Rp33Mc { get; set; } - /// - /// RecordId = 50, - /// ItemId = 29, - /// LongMnemonic = "RP33_mc", - /// ShortMnemonic = "RP33_mc", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Rp33Mc { get; set; } - - } } diff --git a/AsbCloudApp/Data/WITS/Record60Dto.cs b/AsbCloudApp/Data/WITS/Record60Dto.cs index 19dc5338..0387cbeb 100644 --- a/AsbCloudApp/Data/WITS/Record60Dto.cs +++ b/AsbCloudApp/Data/WITS/Record60Dto.cs @@ -1,163 +1,162 @@ -namespace AsbCloudApp.Data.WITS +namespace AsbCloudApp.Data.WITS; + +/// +/// Record name: Передача полных +/// Description: SibReciver. Передача полных +/// Description2: +/// + +public class Record60Dto : RecordBaseDto { + /// - /// Record name: Передача полных - /// Description: SibReciver. Передача полных - /// Description2: + /// RecordId = 60, + /// ItemId = 99, + /// LongMnemonic = "DEPTBITM", + /// ShortMnemonic = "DBTM", + /// Description = "SibReceiver custom. Положение долота", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" /// - public class Record60Dto : RecordBaseDto - { + public float? Deptbitm { get; set; } - /// - /// RecordId = 60, - /// ItemId = 99, - /// LongMnemonic = "DEPTBITM", - /// ShortMnemonic = "DBTM", - /// Description = "SibReceiver custom. Положение долота", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 60, + /// ItemId = 10, + /// LongMnemonic = "DEPTMEAS", + /// ShortMnemonic = "DMEA", + /// Description = "SibReceiver custom. Точка Замера", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Deptbitm { get; set; } + public float? Deptmeas { get; set; } - /// - /// RecordId = 60, - /// ItemId = 10, - /// LongMnemonic = "DEPTMEAS", - /// ShortMnemonic = "DMEA", - /// Description = "SibReceiver custom. Точка Замера", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 60, + /// ItemId = 11, + /// LongMnemonic = "Gtot", + /// ShortMnemonic = "Gtot", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Deptmeas { get; set; } + public float? Gtot { get; set; } - /// - /// RecordId = 60, - /// ItemId = 11, - /// LongMnemonic = "Gtot", - /// ShortMnemonic = "Gtot", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 60, + /// ItemId = 12, + /// LongMnemonic = "Gx", + /// ShortMnemonic = "Gx", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Gtot { get; set; } + public float? Gx { get; set; } - /// - /// RecordId = 60, - /// ItemId = 12, - /// LongMnemonic = "Gx", - /// ShortMnemonic = "Gx", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 60, + /// ItemId = 13, + /// LongMnemonic = "Gy", + /// ShortMnemonic = "Gy", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Gx { get; set; } + public float? Gy { get; set; } - /// - /// RecordId = 60, - /// ItemId = 13, - /// LongMnemonic = "Gy", - /// ShortMnemonic = "Gy", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 60, + /// ItemId = 14, + /// LongMnemonic = "Gz", + /// ShortMnemonic = "Gz", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Gy { get; set; } + public float? Gz { get; set; } - /// - /// RecordId = 60, - /// ItemId = 14, - /// LongMnemonic = "Gz", - /// ShortMnemonic = "Gz", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 60, + /// ItemId = 15, + /// LongMnemonic = "Btot", + /// ShortMnemonic = "Btot", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Gz { get; set; } + public float? Btot { get; set; } - /// - /// RecordId = 60, - /// ItemId = 15, - /// LongMnemonic = "Btot", - /// ShortMnemonic = "Btot", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 60, + /// ItemId = 16, + /// LongMnemonic = "Bx", + /// ShortMnemonic = "Bx", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Btot { get; set; } + public float? Bx { get; set; } - /// - /// RecordId = 60, - /// ItemId = 16, - /// LongMnemonic = "Bx", - /// ShortMnemonic = "Bx", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 60, + /// ItemId = 17, + /// LongMnemonic = "By", + /// ShortMnemonic = "By", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Bx { get; set; } + public float? By { get; set; } - /// - /// RecordId = 60, - /// ItemId = 17, - /// LongMnemonic = "By", - /// ShortMnemonic = "By", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 60, + /// ItemId = 18, + /// LongMnemonic = "Bz", + /// ShortMnemonic = "Bz", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? By { get; set; } + public float? Bz { get; set; } - /// - /// RecordId = 60, - /// ItemId = 18, - /// LongMnemonic = "Bz", - /// ShortMnemonic = "Bz", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Bz { get; set; } - - } } diff --git a/AsbCloudApp/Data/WITS/Record61Dto.cs b/AsbCloudApp/Data/WITS/Record61Dto.cs index 12d59663..18f0e202 100644 --- a/AsbCloudApp/Data/WITS/Record61Dto.cs +++ b/AsbCloudApp/Data/WITS/Record61Dto.cs @@ -1,178 +1,177 @@ -namespace AsbCloudApp.Data.WITS +namespace AsbCloudApp.Data.WITS; + +/// +/// Record name: Резистивиметр Corvet +/// Description: SibReciver. Резистивиметр Corvet +/// Description2: +/// + +public class Record61Dto : RecordBaseDto { + /// - /// Record name: Резистивиметр Corvet - /// Description: SibReciver. Резистивиметр Corvet - /// Description2: + /// RecordId = 61, + /// ItemId = 99, + /// LongMnemonic = "DEPTBITM", + /// ShortMnemonic = "DBTM", + /// Description = "SibReceiver custom. Положение долота", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" /// - public class Record61Dto : RecordBaseDto - { + public float? Deptbitm { get; set; } - /// - /// RecordId = 61, - /// ItemId = 99, - /// LongMnemonic = "DEPTBITM", - /// ShortMnemonic = "DBTM", - /// Description = "SibReceiver custom. Положение долота", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 61, + /// ItemId = 10, + /// LongMnemonic = "DEPTMEAS", + /// ShortMnemonic = "DMEA", + /// Description = "SibReceiver custom. Точка Замера", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Deptbitm { get; set; } + public float? Deptmeas { get; set; } - /// - /// RecordId = 61, - /// ItemId = 10, - /// LongMnemonic = "DEPTMEAS", - /// ShortMnemonic = "DMEA", - /// Description = "SibReceiver custom. Точка Замера", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 61, + /// ItemId = 11, + /// LongMnemonic = "PHL1F1", + /// ShortMnemonic = "PHL1F1", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Deptmeas { get; set; } + public float? Phl1f1 { get; set; } - /// - /// RecordId = 61, - /// ItemId = 11, - /// LongMnemonic = "PHL1F1", - /// ShortMnemonic = "PHL1F1", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 61, + /// ItemId = 12, + /// LongMnemonic = "PHL1F2", + /// ShortMnemonic = "PHL1F2", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Phl1f1 { get; set; } + public float? Phl1f2 { get; set; } - /// - /// RecordId = 61, - /// ItemId = 12, - /// LongMnemonic = "PHL1F2", - /// ShortMnemonic = "PHL1F2", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 61, + /// ItemId = 13, + /// LongMnemonic = "PHL2F1", + /// ShortMnemonic = "PHL2F1", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Phl1f2 { get; set; } + public float? Phl2f1 { get; set; } - /// - /// RecordId = 61, - /// ItemId = 13, - /// LongMnemonic = "PHL2F1", - /// ShortMnemonic = "PHL2F1", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 61, + /// ItemId = 14, + /// LongMnemonic = "PHL2F2", + /// ShortMnemonic = "PHL2F2", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Phl2f1 { get; set; } + public float? Phl2f2 { get; set; } - /// - /// RecordId = 61, - /// ItemId = 14, - /// LongMnemonic = "PHL2F2", - /// ShortMnemonic = "PHL2F2", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 61, + /// ItemId = 15, + /// LongMnemonic = "ATT06H", + /// ShortMnemonic = "ATT06H", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Phl2f2 { get; set; } + public float? Att06h { get; set; } - /// - /// RecordId = 61, - /// ItemId = 15, - /// LongMnemonic = "ATT06H", - /// ShortMnemonic = "ATT06H", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 61, + /// ItemId = 16, + /// LongMnemonic = "ATT06L", + /// ShortMnemonic = "ATT06L", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Att06h { get; set; } + public float? Att06l { get; set; } - /// - /// RecordId = 61, - /// ItemId = 16, - /// LongMnemonic = "ATT06L", - /// ShortMnemonic = "ATT06L", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 61, + /// ItemId = 17, + /// LongMnemonic = "ATT10H", + /// ShortMnemonic = "ATT10H", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Att06l { get; set; } + public float? Att10h { get; set; } - /// - /// RecordId = 61, - /// ItemId = 17, - /// LongMnemonic = "ATT10H", - /// ShortMnemonic = "ATT10H", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 61, + /// ItemId = 18, + /// LongMnemonic = "ATT10L", + /// ShortMnemonic = "ATT10L", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Att10h { get; set; } + public float? Att10l { get; set; } - /// - /// RecordId = 61, - /// ItemId = 18, - /// LongMnemonic = "ATT10L", - /// ShortMnemonic = "ATT10L", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 61, + /// ItemId = 19, + /// LongMnemonic = "Status", + /// ShortMnemonic = "Status", + /// Description = "SibReceiver custom", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Att10l { get; set; } + public float? Status { get; set; } - /// - /// RecordId = 61, - /// ItemId = 19, - /// LongMnemonic = "Status", - /// ShortMnemonic = "Status", - /// Description = "SibReceiver custom", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Status { get; set; } - - } } diff --git a/AsbCloudApp/Data/WITS/Record7Dto.cs b/AsbCloudApp/Data/WITS/Record7Dto.cs index 0e7664ff..54c05501 100644 --- a/AsbCloudApp/Data/WITS/Record7Dto.cs +++ b/AsbCloudApp/Data/WITS/Record7Dto.cs @@ -1,298 +1,297 @@ -namespace AsbCloudApp.Data.WITS +namespace AsbCloudApp.Data.WITS; + +/// +/// Record name: Survey/Directional +/// Description: Directional/Survey data +/// Description2: +/// + +public class Record7Dto : RecordBaseDto { + /// - /// Record name: Survey/Directional - /// Description: Directional/Survey data - /// Description2: + /// RecordId = 7, + /// ItemId = 8, + /// LongMnemonic = "DEPTSVYM", + /// ShortMnemonic = "DSVM", + /// Description = "Depth Svy/reading (meas)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" /// - public class Record7Dto : RecordBaseDto - { + public float? Deptsvym { get; set; } - /// - /// RecordId = 7, - /// ItemId = 8, - /// LongMnemonic = "DEPTSVYM", - /// ShortMnemonic = "DSVM", - /// Description = "Depth Svy/reading (meas)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 7, + /// ItemId = 9, + /// LongMnemonic = "DEPTSVYV", + /// ShortMnemonic = "DSVV", + /// Description = "Depth Svy/reading (vert)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// - public float? Deptsvym { get; set; } + public float? Deptsvyv { get; set; } - /// - /// RecordId = 7, - /// ItemId = 9, - /// LongMnemonic = "DEPTSVYV", - /// ShortMnemonic = "DSVV", - /// Description = "Depth Svy/reading (vert)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 7, + /// ItemId = 10, + /// LongMnemonic = "PASSNUM", + /// ShortMnemonic = "PASS", + /// Description = "Pass Number", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 2, + /// ValueType = "S" + /// - public float? Deptsvyv { get; set; } + public short? Passnum { get; set; } - /// - /// RecordId = 7, - /// ItemId = 10, - /// LongMnemonic = "PASSNUM", - /// ShortMnemonic = "PASS", - /// Description = "Pass Number", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 2, - /// ValueType = "S" - /// + /// + /// RecordId = 7, + /// ItemId = 11, + /// LongMnemonic = "DEPTMEAS", + /// ShortMnemonic = "DMEA", + /// Description = "Depth Hole (meas)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// - public short? Passnum { get; set; } + public float? Deptmeas { get; set; } - /// - /// RecordId = 7, - /// ItemId = 11, - /// LongMnemonic = "DEPTMEAS", - /// ShortMnemonic = "DMEA", - /// Description = "Depth Hole (meas)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 7, + /// ItemId = 12, + /// LongMnemonic = "SVYTYPE", + /// ShortMnemonic = "STYP", + /// Description = "Svy Type", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 8, + /// ValueType = "A" + /// - public float? Deptmeas { get; set; } + public string Svytype { get; set; } = string.Empty; - /// - /// RecordId = 7, - /// ItemId = 12, - /// LongMnemonic = "SVYTYPE", - /// ShortMnemonic = "STYP", - /// Description = "Svy Type", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 8, - /// ValueType = "A" - /// + /// + /// RecordId = 7, + /// ItemId = 13, + /// LongMnemonic = "SVYINC", + /// ShortMnemonic = "SINC", + /// Description = "Svy Inclination", + /// Description2 = "", + /// FPSUnits = "DEG", + /// MetricUnits = "DEG", + /// Length = 4, + /// ValueType = "F" + /// - public string Svytype { get; set; } = string.Empty; + public float? Svyinc { get; set; } - /// - /// RecordId = 7, - /// ItemId = 13, - /// LongMnemonic = "SVYINC", - /// ShortMnemonic = "SINC", - /// Description = "Svy Inclination", - /// Description2 = "", - /// FPSUnits = "DEG", - /// MetricUnits = "DEG", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 7, + /// ItemId = 14, + /// LongMnemonic = "SVYAZU", + /// ShortMnemonic = "SAZU", + /// Description = "Svy Azimuth (uncorrected)", + /// Description2 = "", + /// FPSUnits = "DEG", + /// MetricUnits = "DEG", + /// Length = 4, + /// ValueType = "F" + /// - public float? Svyinc { get; set; } + public float? Svyazu { get; set; } - /// - /// RecordId = 7, - /// ItemId = 14, - /// LongMnemonic = "SVYAZU", - /// ShortMnemonic = "SAZU", - /// Description = "Svy Azimuth (uncorrected)", - /// Description2 = "", - /// FPSUnits = "DEG", - /// MetricUnits = "DEG", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 7, + /// ItemId = 15, + /// LongMnemonic = "SVYAZC", + /// ShortMnemonic = "SAZC", + /// Description = "Svy Azimuth (corrected)", + /// Description2 = "", + /// FPSUnits = "DEG", + /// MetricUnits = "DEG", + /// Length = 4, + /// ValueType = "F" + /// - public float? Svyazu { get; set; } + public float? Svyazc { get; set; } - /// - /// RecordId = 7, - /// ItemId = 15, - /// LongMnemonic = "SVYAZC", - /// ShortMnemonic = "SAZC", - /// Description = "Svy Azimuth (corrected)", - /// Description2 = "", - /// FPSUnits = "DEG", - /// MetricUnits = "DEG", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 7, + /// ItemId = 16, + /// LongMnemonic = "SVYMTF", + /// ShortMnemonic = "SMTF", + /// Description = "Svy Magnetic Toolface", + /// Description2 = "", + /// FPSUnits = "DEG", + /// MetricUnits = "DEG", + /// Length = 4, + /// ValueType = "F" + /// - public float? Svyazc { get; set; } + public float? Svymtf { get; set; } - /// - /// RecordId = 7, - /// ItemId = 16, - /// LongMnemonic = "SVYMTF", - /// ShortMnemonic = "SMTF", - /// Description = "Svy Magnetic Toolface", - /// Description2 = "", - /// FPSUnits = "DEG", - /// MetricUnits = "DEG", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 7, + /// ItemId = 17, + /// LongMnemonic = "SVYGTF", + /// ShortMnemonic = "SGTF", + /// Description = "Svy Gravity Toolface", + /// Description2 = "", + /// FPSUnits = "DEG", + /// MetricUnits = "DEG", + /// Length = 4, + /// ValueType = "F" + /// - public float? Svymtf { get; set; } + public float? Svygtf { get; set; } - /// - /// RecordId = 7, - /// ItemId = 17, - /// LongMnemonic = "SVYGTF", - /// ShortMnemonic = "SGTF", - /// Description = "Svy Gravity Toolface", - /// Description2 = "", - /// FPSUnits = "DEG", - /// MetricUnits = "DEG", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 7, + /// ItemId = 18, + /// LongMnemonic = "SVYNS", + /// ShortMnemonic = "SNS", + /// Description = "Svy North-South Position", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// - public float? Svygtf { get; set; } + public float? Svyns { get; set; } - /// - /// RecordId = 7, - /// ItemId = 18, - /// LongMnemonic = "SVYNS", - /// ShortMnemonic = "SNS", - /// Description = "Svy North-South Position", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 7, + /// ItemId = 19, + /// LongMnemonic = "SVYEW", + /// ShortMnemonic = "SEW", + /// Description = "Svy East-West Position", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// - public float? Svyns { get; set; } + public float? Svyew { get; set; } - /// - /// RecordId = 7, - /// ItemId = 19, - /// LongMnemonic = "SVYEW", - /// ShortMnemonic = "SEW", - /// Description = "Svy East-West Position", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 7, + /// ItemId = 20, + /// LongMnemonic = "SVYDLS", + /// ShortMnemonic = "SDLS", + /// Description = "Svy Dog Leg Severity", + /// Description2 = "", + /// FPSUnits = "DGHF", + /// MetricUnits = "DGHM", + /// Length = 4, + /// ValueType = "F" + /// - public float? Svyew { get; set; } + public float? Svydls { get; set; } - /// - /// RecordId = 7, - /// ItemId = 20, - /// LongMnemonic = "SVYDLS", - /// ShortMnemonic = "SDLS", - /// Description = "Svy Dog Leg Severity", - /// Description2 = "", - /// FPSUnits = "DGHF", - /// MetricUnits = "DGHM", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 7, + /// ItemId = 21, + /// LongMnemonic = "SVYWALK", + /// ShortMnemonic = "SWLK", + /// Description = "Svy Rate of Walk", + /// Description2 = "", + /// FPSUnits = "DGHF", + /// MetricUnits = "DGHM", + /// Length = 4, + /// ValueType = "F" + /// - public float? Svydls { get; set; } + public float? Svywalk { get; set; } - /// - /// RecordId = 7, - /// ItemId = 21, - /// LongMnemonic = "SVYWALK", - /// ShortMnemonic = "SWLK", - /// Description = "Svy Rate of Walk", - /// Description2 = "", - /// FPSUnits = "DGHF", - /// MetricUnits = "DGHM", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 7, + /// ItemId = 22, + /// LongMnemonic = "SPARE1", + /// ShortMnemonic = "SPR1", + /// Description = "SPARE 1", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "F" + /// - public float? Svywalk { get; set; } + public float? Spare1 { get; set; } - /// - /// RecordId = 7, - /// ItemId = 22, - /// LongMnemonic = "SPARE1", - /// ShortMnemonic = "SPR1", - /// Description = "SPARE 1", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 7, + /// ItemId = 23, + /// LongMnemonic = "SPARE2", + /// ShortMnemonic = "SPR2", + /// Description = "SPARE 2", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "F" + /// - public float? Spare1 { get; set; } + public float? Spare2 { get; set; } - /// - /// RecordId = 7, - /// ItemId = 23, - /// LongMnemonic = "SPARE2", - /// ShortMnemonic = "SPR2", - /// Description = "SPARE 2", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 7, + /// ItemId = 24, + /// LongMnemonic = "SPARE3", + /// ShortMnemonic = "SPR3", + /// Description = "SPARE 3", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "F" + /// - public float? Spare2 { get; set; } + public float? Spare3 { get; set; } - /// - /// RecordId = 7, - /// ItemId = 24, - /// LongMnemonic = "SPARE3", - /// ShortMnemonic = "SPR3", - /// Description = "SPARE 3", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 7, + /// ItemId = 25, + /// LongMnemonic = "SPARE4", + /// ShortMnemonic = "SPR4", + /// Description = "SPARE 4", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "F" + /// - public float? Spare3 { get; set; } + public float? Spare4 { get; set; } - /// - /// RecordId = 7, - /// ItemId = 25, - /// LongMnemonic = "SPARE4", - /// ShortMnemonic = "SPR4", - /// Description = "SPARE 4", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "F" - /// + /// + /// RecordId = 7, + /// ItemId = 26, + /// LongMnemonic = "SPARE5", + /// ShortMnemonic = "SPR5", + /// Description = "SPARE 5", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// - public float? Spare4 { get; set; } + public float? Spare5 { get; set; } - /// - /// RecordId = 7, - /// ItemId = 26, - /// LongMnemonic = "SPARE5", - /// ShortMnemonic = "SPR5", - /// Description = "SPARE 5", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Spare5 { get; set; } - - } } diff --git a/AsbCloudApp/Data/WITS/Record8Dto.cs b/AsbCloudApp/Data/WITS/Record8Dto.cs index 7a8d7331..ee196058 100644 --- a/AsbCloudApp/Data/WITS/Record8Dto.cs +++ b/AsbCloudApp/Data/WITS/Record8Dto.cs @@ -1,733 +1,732 @@ -namespace AsbCloudApp.Data.WITS +namespace AsbCloudApp.Data.WITS; + +/// +/// Record name: MWD Formation Evaluation +/// Description: MWD Formation Evaluation data +/// Description2: +/// + +public class Record8Dto : RecordBaseDto { + /// - /// Record name: MWD Formation Evaluation - /// Description: MWD Formation Evaluation data - /// Description2: + /// RecordId = 8, + /// ItemId = 8, + /// LongMnemonic = "DEPTMEAS", + /// ShortMnemonic = "DMEA", + /// Description = "Depth Hole (meas)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" /// - public class Record8Dto : RecordBaseDto - { - - /// - /// RecordId = 8, - /// ItemId = 8, - /// LongMnemonic = "DEPTMEAS", - /// ShortMnemonic = "DMEA", - /// Description = "Depth Hole (meas)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptmeas { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 9, - /// LongMnemonic = "DEPTVERT", - /// ShortMnemonic = "DVER", - /// Description = "Depth Hole (vert)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptvert { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 10, - /// LongMnemonic = "DEPTBITM", - /// ShortMnemonic = "DBTM", - /// Description = "Depth Bit (meas)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptbitm { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 11, - /// LongMnemonic = "DEPTBITV", - /// ShortMnemonic = "DBTV", - /// Description = "Depth Bit (vert)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptbitv { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 12, - /// LongMnemonic = "PASSNUM", - /// ShortMnemonic = "PASS", - /// Description = "Pass Number", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 2, - /// ValueType = "S" - /// - - public short? Passnum { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 13, - /// LongMnemonic = "DEPTRS1M", - /// ShortMnemonic = "DR1M", - /// Description = "Depth Resis 1 sensor (meas)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptrs1m { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 14, - /// LongMnemonic = "DEPTRS1V", - /// ShortMnemonic = "DR1V", - /// Description = "Depth Resis 1 sensor (vert)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptrs1v { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 15, - /// LongMnemonic = "MR1", - /// ShortMnemonic = "MR1", - /// Description = "Resis 1 reading", - /// Description2 = "", - /// FPSUnits = "OHMM", - /// MetricUnits = "OHMM", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mr1 { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 16, - /// LongMnemonic = "MR1C", - /// ShortMnemonic = "MR1C", - /// Description = "Resis 1 (borehole corr)", - /// Description2 = "", - /// FPSUnits = "OHMM", - /// MetricUnits = "OHMM", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mr1c { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 17, - /// LongMnemonic = "DEPTRS2M", - /// ShortMnemonic = "DR2M", - /// Description = "Depth Resis 2 sensor (meas)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptrs2m { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 18, - /// LongMnemonic = "DEPTRS2V", - /// ShortMnemonic = "DR2V", - /// Description = "Depth Resis 2 sensor (vert)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptrs2v { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 19, - /// LongMnemonic = "MR2", - /// ShortMnemonic = "MR2", - /// Description = "Resis 2 reading", - /// Description2 = "", - /// FPSUnits = "OHMM", - /// MetricUnits = "OHMM", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mr2 { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 20, - /// LongMnemonic = "MR2C", - /// ShortMnemonic = "MR2C", - /// Description = "Resis 2 (borehole corr)", - /// Description2 = "", - /// FPSUnits = "OHMM", - /// MetricUnits = "OHMM", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mr2c { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 21, - /// LongMnemonic = "DEPTGR1M", - /// ShortMnemonic = "DG1M", - /// Description = "Depth G.Ray 1 sensor(meas)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptgr1m { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 22, - /// LongMnemonic = "DEPTGR1V", - /// ShortMnemonic = "DG1V", - /// Description = "Depth G.Ray 1 sensor(vert)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptgr1v { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 23, - /// LongMnemonic = "MG1", - /// ShortMnemonic = "MG1", - /// Description = "Gamma Ray 1 reading", - /// Description2 = "", - /// FPSUnits = "API", - /// MetricUnits = "API", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mg1 { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 24, - /// LongMnemonic = "MG1C", - /// ShortMnemonic = "MG1C", - /// Description = "Gamma Ray 1(borehole corr)", - /// Description2 = "", - /// FPSUnits = "API", - /// MetricUnits = "API", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mg1c { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 25, - /// LongMnemonic = "DEPTGR2M", - /// ShortMnemonic = "DG2M", - /// Description = "Depth G.Ray 2 sensor(meas)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptgr2m { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 26, - /// LongMnemonic = "DEPTGR2V", - /// ShortMnemonic = "DG2V", - /// Description = "Depth G.Ray 2 sensor(vert)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptgr2v { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 27, - /// LongMnemonic = "MG2", - /// ShortMnemonic = "MG2", - /// Description = "Gamma Ray 2 reading", - /// Description2 = "", - /// FPSUnits = "API", - /// MetricUnits = "API", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mg2 { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 28, - /// LongMnemonic = "MG2C", - /// ShortMnemonic = "MG2C", - /// Description = "Gamma Ray 2(borehole corr)", - /// Description2 = "", - /// FPSUnits = "API", - /// MetricUnits = "API", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mg2c { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 29, - /// LongMnemonic = "DEPTP1M", - /// ShortMnemonic = "DP1M", - /// Description = "Depth Por 1 sensor (meas)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptp1m { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 30, - /// LongMnemonic = "DEPTP1V", - /// ShortMnemonic = "DP1V", - /// Description = "Depth Por 1 sensor (vert)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptp1v { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 31, - /// LongMnemonic = "MPO1", - /// ShortMnemonic = "MPO1", - /// Description = "Porosity Tool 1 reading", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mpo1 { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 32, - /// LongMnemonic = "DEPTP2M", - /// ShortMnemonic = "DP2M", - /// Description = "Depth Por 2 sensor (meas)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptp2m { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 33, - /// LongMnemonic = "DEPTP2V", - /// ShortMnemonic = "DP2V", - /// Description = "Depth Por 2 sensor (vert)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptp2v { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 34, - /// LongMnemonic = "MPO2", - /// ShortMnemonic = "MPO2", - /// Description = "Porosity Tool 2 reading", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mpo2 { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 35, - /// LongMnemonic = "MFTANN", - /// ShortMnemonic = "MFTA", - /// Description = "Downhole Fluid Temp (ann)", - /// Description2 = "", - /// FPSUnits = "DEGF", - /// MetricUnits = "DEGC", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mftann { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 36, - /// LongMnemonic = "MFTPIPE", - /// ShortMnemonic = "MFTP", - /// Description = "Downhole Fluid Temp (pipe)", - /// Description2 = "", - /// FPSUnits = "DEGF", - /// MetricUnits = "DEGC", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mftpipe { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 37, - /// LongMnemonic = "MFRANN", - /// ShortMnemonic = "MFRA", - /// Description = "Downhole Fluid Resis (ann)", - /// Description2 = "", - /// FPSUnits = "OHMM", - /// MetricUnits = "OHMM", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mfrann { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 38, - /// LongMnemonic = "MFRPIPE", - /// ShortMnemonic = "MFRP", - /// Description = "Downhole Fluid Resis (pipe)", - /// Description2 = "", - /// FPSUnits = "OHMM", - /// MetricUnits = "OHMM", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mfrpipe { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 39, - /// LongMnemonic = "DEPTFDM", - /// ShortMnemonic = "DFDM", - /// Description = "Depth Form Density (meas)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptfdm { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 40, - /// LongMnemonic = "DEPTFDV", - /// ShortMnemonic = "DFDV", - /// Description = "Depth Form Density (vert)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptfdv { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 41, - /// LongMnemonic = "MFD", - /// ShortMnemonic = "MFD", - /// Description = "Formation Density", - /// Description2 = "", - /// FPSUnits = "G/CC", - /// MetricUnits = "G/CC", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mfd { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 42, - /// LongMnemonic = "DEPTCALM", - /// ShortMnemonic = "DCLM", - /// Description = "Depth Caliper (meas)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptcalm { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 43, - /// LongMnemonic = "DEPTCALV", - /// ShortMnemonic = "DCLV", - /// Description = "Depth Caliper (vert)", - /// Description2 = "", - /// FPSUnits = "F", - /// MetricUnits = "M", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Deptcalv { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 44, - /// LongMnemonic = "MCLP", - /// ShortMnemonic = "MCLP", - /// Description = "Caliper", - /// Description2 = "", - /// FPSUnits = "IN", - /// MetricUnits = "MM", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mclp { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 45, - /// LongMnemonic = "MFPP", - /// ShortMnemonic = "MFPP", - /// Description = "Pore Pressure Grad MWD", - /// Description2 = "", - /// FPSUnits = "PPG", - /// MetricUnits = "KGM3", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mfpp { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 46, - /// LongMnemonic = "MFFP", - /// ShortMnemonic = "MFFP", - /// Description = "Frac Pressure Grad MWD", - /// Description2 = "", - /// FPSUnits = "PPG", - /// MetricUnits = "KGM3", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Mffp { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 47, - /// LongMnemonic = "SPARE1", - /// ShortMnemonic = "SPR1", - /// Description = "SPARE 1", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Spare1 { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 48, - /// LongMnemonic = "SPARE2", - /// ShortMnemonic = "SPR2", - /// Description = "SPARE 2", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Spare2 { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 49, - /// LongMnemonic = "SPARE3", - /// ShortMnemonic = "SPR3", - /// Description = "SPARE 3", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Spare3 { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 50, - /// LongMnemonic = "SPARE4", - /// ShortMnemonic = "SPR4", - /// Description = "SPARE 4", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Spare4 { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 51, - /// LongMnemonic = "SPARE5", - /// ShortMnemonic = "SPR5", - /// Description = "SPARE 5", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "---", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Spare5 { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 52, - /// LongMnemonic = "SPARE6", - /// ShortMnemonic = "SPR6", - /// Description = "SPARE 6", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Spare6 { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 53, - /// LongMnemonic = "SPARE7", - /// ShortMnemonic = "SPR7", - /// Description = "SPARE 7", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Spare7 { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 54, - /// LongMnemonic = "SPARE8", - /// ShortMnemonic = "SPR8", - /// Description = "SPARE 8", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Spare8 { get; set; } - - /// - /// RecordId = 8, - /// ItemId = 55, - /// LongMnemonic = "SPARE9", - /// ShortMnemonic = "SPR9", - /// Description = "SPARE 9", - /// Description2 = "", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "F" - /// - - public float? Spare9 { get; set; } - - } + public float? Deptmeas { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 9, + /// LongMnemonic = "DEPTVERT", + /// ShortMnemonic = "DVER", + /// Description = "Depth Hole (vert)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptvert { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 10, + /// LongMnemonic = "DEPTBITM", + /// ShortMnemonic = "DBTM", + /// Description = "Depth Bit (meas)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptbitm { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 11, + /// LongMnemonic = "DEPTBITV", + /// ShortMnemonic = "DBTV", + /// Description = "Depth Bit (vert)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptbitv { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 12, + /// LongMnemonic = "PASSNUM", + /// ShortMnemonic = "PASS", + /// Description = "Pass Number", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 2, + /// ValueType = "S" + /// + + public short? Passnum { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 13, + /// LongMnemonic = "DEPTRS1M", + /// ShortMnemonic = "DR1M", + /// Description = "Depth Resis 1 sensor (meas)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptrs1m { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 14, + /// LongMnemonic = "DEPTRS1V", + /// ShortMnemonic = "DR1V", + /// Description = "Depth Resis 1 sensor (vert)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptrs1v { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 15, + /// LongMnemonic = "MR1", + /// ShortMnemonic = "MR1", + /// Description = "Resis 1 reading", + /// Description2 = "", + /// FPSUnits = "OHMM", + /// MetricUnits = "OHMM", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mr1 { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 16, + /// LongMnemonic = "MR1C", + /// ShortMnemonic = "MR1C", + /// Description = "Resis 1 (borehole corr)", + /// Description2 = "", + /// FPSUnits = "OHMM", + /// MetricUnits = "OHMM", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mr1c { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 17, + /// LongMnemonic = "DEPTRS2M", + /// ShortMnemonic = "DR2M", + /// Description = "Depth Resis 2 sensor (meas)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptrs2m { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 18, + /// LongMnemonic = "DEPTRS2V", + /// ShortMnemonic = "DR2V", + /// Description = "Depth Resis 2 sensor (vert)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptrs2v { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 19, + /// LongMnemonic = "MR2", + /// ShortMnemonic = "MR2", + /// Description = "Resis 2 reading", + /// Description2 = "", + /// FPSUnits = "OHMM", + /// MetricUnits = "OHMM", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mr2 { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 20, + /// LongMnemonic = "MR2C", + /// ShortMnemonic = "MR2C", + /// Description = "Resis 2 (borehole corr)", + /// Description2 = "", + /// FPSUnits = "OHMM", + /// MetricUnits = "OHMM", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mr2c { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 21, + /// LongMnemonic = "DEPTGR1M", + /// ShortMnemonic = "DG1M", + /// Description = "Depth G.Ray 1 sensor(meas)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptgr1m { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 22, + /// LongMnemonic = "DEPTGR1V", + /// ShortMnemonic = "DG1V", + /// Description = "Depth G.Ray 1 sensor(vert)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptgr1v { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 23, + /// LongMnemonic = "MG1", + /// ShortMnemonic = "MG1", + /// Description = "Gamma Ray 1 reading", + /// Description2 = "", + /// FPSUnits = "API", + /// MetricUnits = "API", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mg1 { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 24, + /// LongMnemonic = "MG1C", + /// ShortMnemonic = "MG1C", + /// Description = "Gamma Ray 1(borehole corr)", + /// Description2 = "", + /// FPSUnits = "API", + /// MetricUnits = "API", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mg1c { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 25, + /// LongMnemonic = "DEPTGR2M", + /// ShortMnemonic = "DG2M", + /// Description = "Depth G.Ray 2 sensor(meas)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptgr2m { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 26, + /// LongMnemonic = "DEPTGR2V", + /// ShortMnemonic = "DG2V", + /// Description = "Depth G.Ray 2 sensor(vert)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptgr2v { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 27, + /// LongMnemonic = "MG2", + /// ShortMnemonic = "MG2", + /// Description = "Gamma Ray 2 reading", + /// Description2 = "", + /// FPSUnits = "API", + /// MetricUnits = "API", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mg2 { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 28, + /// LongMnemonic = "MG2C", + /// ShortMnemonic = "MG2C", + /// Description = "Gamma Ray 2(borehole corr)", + /// Description2 = "", + /// FPSUnits = "API", + /// MetricUnits = "API", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mg2c { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 29, + /// LongMnemonic = "DEPTP1M", + /// ShortMnemonic = "DP1M", + /// Description = "Depth Por 1 sensor (meas)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptp1m { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 30, + /// LongMnemonic = "DEPTP1V", + /// ShortMnemonic = "DP1V", + /// Description = "Depth Por 1 sensor (vert)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptp1v { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 31, + /// LongMnemonic = "MPO1", + /// ShortMnemonic = "MPO1", + /// Description = "Porosity Tool 1 reading", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mpo1 { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 32, + /// LongMnemonic = "DEPTP2M", + /// ShortMnemonic = "DP2M", + /// Description = "Depth Por 2 sensor (meas)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptp2m { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 33, + /// LongMnemonic = "DEPTP2V", + /// ShortMnemonic = "DP2V", + /// Description = "Depth Por 2 sensor (vert)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptp2v { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 34, + /// LongMnemonic = "MPO2", + /// ShortMnemonic = "MPO2", + /// Description = "Porosity Tool 2 reading", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mpo2 { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 35, + /// LongMnemonic = "MFTANN", + /// ShortMnemonic = "MFTA", + /// Description = "Downhole Fluid Temp (ann)", + /// Description2 = "", + /// FPSUnits = "DEGF", + /// MetricUnits = "DEGC", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mftann { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 36, + /// LongMnemonic = "MFTPIPE", + /// ShortMnemonic = "MFTP", + /// Description = "Downhole Fluid Temp (pipe)", + /// Description2 = "", + /// FPSUnits = "DEGF", + /// MetricUnits = "DEGC", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mftpipe { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 37, + /// LongMnemonic = "MFRANN", + /// ShortMnemonic = "MFRA", + /// Description = "Downhole Fluid Resis (ann)", + /// Description2 = "", + /// FPSUnits = "OHMM", + /// MetricUnits = "OHMM", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mfrann { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 38, + /// LongMnemonic = "MFRPIPE", + /// ShortMnemonic = "MFRP", + /// Description = "Downhole Fluid Resis (pipe)", + /// Description2 = "", + /// FPSUnits = "OHMM", + /// MetricUnits = "OHMM", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mfrpipe { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 39, + /// LongMnemonic = "DEPTFDM", + /// ShortMnemonic = "DFDM", + /// Description = "Depth Form Density (meas)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptfdm { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 40, + /// LongMnemonic = "DEPTFDV", + /// ShortMnemonic = "DFDV", + /// Description = "Depth Form Density (vert)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptfdv { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 41, + /// LongMnemonic = "MFD", + /// ShortMnemonic = "MFD", + /// Description = "Formation Density", + /// Description2 = "", + /// FPSUnits = "G/CC", + /// MetricUnits = "G/CC", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mfd { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 42, + /// LongMnemonic = "DEPTCALM", + /// ShortMnemonic = "DCLM", + /// Description = "Depth Caliper (meas)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptcalm { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 43, + /// LongMnemonic = "DEPTCALV", + /// ShortMnemonic = "DCLV", + /// Description = "Depth Caliper (vert)", + /// Description2 = "", + /// FPSUnits = "F", + /// MetricUnits = "M", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Deptcalv { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 44, + /// LongMnemonic = "MCLP", + /// ShortMnemonic = "MCLP", + /// Description = "Caliper", + /// Description2 = "", + /// FPSUnits = "IN", + /// MetricUnits = "MM", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mclp { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 45, + /// LongMnemonic = "MFPP", + /// ShortMnemonic = "MFPP", + /// Description = "Pore Pressure Grad MWD", + /// Description2 = "", + /// FPSUnits = "PPG", + /// MetricUnits = "KGM3", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mfpp { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 46, + /// LongMnemonic = "MFFP", + /// ShortMnemonic = "MFFP", + /// Description = "Frac Pressure Grad MWD", + /// Description2 = "", + /// FPSUnits = "PPG", + /// MetricUnits = "KGM3", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Mffp { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 47, + /// LongMnemonic = "SPARE1", + /// ShortMnemonic = "SPR1", + /// Description = "SPARE 1", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Spare1 { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 48, + /// LongMnemonic = "SPARE2", + /// ShortMnemonic = "SPR2", + /// Description = "SPARE 2", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Spare2 { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 49, + /// LongMnemonic = "SPARE3", + /// ShortMnemonic = "SPR3", + /// Description = "SPARE 3", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Spare3 { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 50, + /// LongMnemonic = "SPARE4", + /// ShortMnemonic = "SPR4", + /// Description = "SPARE 4", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Spare4 { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 51, + /// LongMnemonic = "SPARE5", + /// ShortMnemonic = "SPR5", + /// Description = "SPARE 5", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "---", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Spare5 { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 52, + /// LongMnemonic = "SPARE6", + /// ShortMnemonic = "SPR6", + /// Description = "SPARE 6", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Spare6 { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 53, + /// LongMnemonic = "SPARE7", + /// ShortMnemonic = "SPR7", + /// Description = "SPARE 7", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Spare7 { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 54, + /// LongMnemonic = "SPARE8", + /// ShortMnemonic = "SPR8", + /// Description = "SPARE 8", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Spare8 { get; set; } + + /// + /// RecordId = 8, + /// ItemId = 55, + /// LongMnemonic = "SPARE9", + /// ShortMnemonic = "SPR9", + /// Description = "SPARE 9", + /// Description2 = "", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "F" + /// + + public float? Spare9 { get; set; } + } diff --git a/AsbCloudApp/Data/WITS/RecordBaseDto.cs b/AsbCloudApp/Data/WITS/RecordBaseDto.cs index 8c874136..4c3f7261 100644 --- a/AsbCloudApp/Data/WITS/RecordBaseDto.cs +++ b/AsbCloudApp/Data/WITS/RecordBaseDto.cs @@ -1,133 +1,132 @@ using System; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data.WITS +namespace AsbCloudApp.Data.WITS; + +/// +/// This is base class for all WITS-0 records +/// +public abstract class RecordBaseDto : IId, ITelemetryData { + /// + [Required] + public int Id { get; set; } + + /// + public int IdTelemetry { get; set; } + + /// + [Required] + public DateTime DateTime { get; set; } + /// - /// This is base class for all WITS-0 records + /// отметка времени /// - public abstract class RecordBaseDto : IId, ITelemetryData - { - /// - [Required] - public int Id { get; set; } + [Required] + public int TimeStamp { get; set; } - /// - public int IdTelemetry { get; set; } + /// + /// RecordId = 1, + /// ItemId = 1, + /// LongMnemonic = "WELLID", + /// ShortMnemonic = "WID", + /// Description = "Well Identifier", + /// Description2 = "Number/name assigned to the well by the operator for identification purposes. This item is common to all records. This includes a four-character code identifying the SENDER.", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 16, + /// ValueType = "A" + /// + [Required] + public string Wellid { get; set; } = string.Empty; - /// - [Required] - public DateTime DateTime { get; set; } + /// + /// RecordId = 1, + /// ItemId = 2, + /// LongMnemonic = "STKNUM", + /// ShortMnemonic = "SKNO", + /// Description = "Sidetrack/Hole Sect No.", + /// Description2 = "Measured depth of the hole at the time the record is generated.", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 2, + /// ValueType = "S" + /// - /// - /// отметка времени - /// - [Required] - public int TimeStamp { get; set; } + public short? Stknum { get; set; } - /// - /// RecordId = 1, - /// ItemId = 1, - /// LongMnemonic = "WELLID", - /// ShortMnemonic = "WID", - /// Description = "Well Identifier", - /// Description2 = "Number/name assigned to the well by the operator for identification purposes. This item is common to all records. This includes a four-character code identifying the SENDER.", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 16, - /// ValueType = "A" - /// - [Required] - public string Wellid { get; set; } = string.Empty; + /// + /// RecordId = 1, + /// ItemId = 3, + /// LongMnemonic = "RECID", + /// ShortMnemonic = "RID", + /// Description = "Record Identifier", + /// Description2 = "Number of the sidetrack being drilled at the time the computer generated the record. Prior to having a sidetrack, this number is always 0. The sidetrack number indexes at the time drilling new formation commences (not while drilling the cement plug). This item is common to all records.", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 2, + /// ValueType = "S" + /// - /// - /// RecordId = 1, - /// ItemId = 2, - /// LongMnemonic = "STKNUM", - /// ShortMnemonic = "SKNO", - /// Description = "Sidetrack/Hole Sect No.", - /// Description2 = "Measured depth of the hole at the time the record is generated.", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 2, - /// ValueType = "S" - /// + public short? Recid { get; set; } - public short? Stknum { get; set; } + /// + /// RecordId = 1, + /// ItemId = 4, + /// LongMnemonic = "SEQID", + /// ShortMnemonic = "SQID", + /// Description = "Sequence Identifier", + /// Description2 = "Logical data record type identifier. This item is common to all records and, for current Pre-Defined Records, contains a value between 1 and 25, according to the record type. Types 26 through 49 inclusive are reserved for future expansion of the Pre-Defined records. Types 50 through 80 inclusive are open for Custom user definition. NOTE that the Logical Record Type for a record is this number plus 150, thus WITS Record 1 is Logical Record Type 151, WITS Record 2 is Logical Record Type 152, etc.", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "L" + /// - /// - /// RecordId = 1, - /// ItemId = 3, - /// LongMnemonic = "RECID", - /// ShortMnemonic = "RID", - /// Description = "Record Identifier", - /// Description2 = "Number of the sidetrack being drilled at the time the computer generated the record. Prior to having a sidetrack, this number is always 0. The sidetrack number indexes at the time drilling new formation commences (not while drilling the cement plug). This item is common to all records.", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 2, - /// ValueType = "S" - /// + public int? Seqid { get; set; } - public short? Recid { get; set; } + /// + /// RecordId = 1, + /// ItemId = 5, + /// LongMnemonic = "DATE", + /// ShortMnemonic = "DATE", + /// Description = "Date", + /// Description2 = "Indicates the number of times this record has been generated (it is not reset to zero for a sidetrack). The computer should automatically increase the number by one each time it creates a new record. This item is common to all records. The sequence identifier in each individual record type keeps track of the count for that particular record only. Thus there is a sequence identifier for each record type used.", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "L" + /// - /// - /// RecordId = 1, - /// ItemId = 4, - /// LongMnemonic = "SEQID", - /// ShortMnemonic = "SQID", - /// Description = "Sequence Identifier", - /// Description2 = "Logical data record type identifier. This item is common to all records and, for current Pre-Defined Records, contains a value between 1 and 25, according to the record type. Types 26 through 49 inclusive are reserved for future expansion of the Pre-Defined records. Types 50 through 80 inclusive are open for Custom user definition. NOTE that the Logical Record Type for a record is this number plus 150, thus WITS Record 1 is Logical Record Type 151, WITS Record 2 is Logical Record Type 152, etc.", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "L" - /// + public int? Date_ { get; set; } - public int? Seqid { get; set; } + /// + /// RecordId = 1, + /// ItemId = 6, + /// LongMnemonic = "TIME", + /// ShortMnemonic = "TIME", + /// Description = "Time", + /// Description2 = "Indicates the date the computer generated this record. The date is reported as a 6 digit integer in a YYMMDD type format. e.g. 910404 would represent April 4, 1991. It is common to all records. Note that, like Time below, Universal Coordinated Time (Greenwich Mean Time) is used as the common reference. Note also that though this number should never decrease, there is no guarantee of this fact.", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 4, + /// ValueType = "L" + /// - /// - /// RecordId = 1, - /// ItemId = 5, - /// LongMnemonic = "DATE", - /// ShortMnemonic = "DATE", - /// Description = "Date", - /// Description2 = "Indicates the number of times this record has been generated (it is not reset to zero for a sidetrack). The computer should automatically increase the number by one each time it creates a new record. This item is common to all records. The sequence identifier in each individual record type keeps track of the count for that particular record only. Thus there is a sequence identifier for each record type used.", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "L" - /// + public int? Time { get; set; } - public int? Date_ { get; set; } + /// + /// RecordId = 1, + /// ItemId = 7, + /// LongMnemonic = "ACTCOD", + /// ShortMnemonic = "ACTC", + /// Description = "Activity Code", + /// Description2 = "Indicates the time of day (24 hour clock), when the computer generated the record, eg. 225015 would represent 10:50:15 pm. This item is common to all records. Note that, like Date above, Universal Coordinated Time (Greenwich Mean Time) is used as the common reference.", + /// FPSUnits = "----", + /// MetricUnits = "----", + /// Length = 2, + /// ValueType = "S" + /// - /// - /// RecordId = 1, - /// ItemId = 6, - /// LongMnemonic = "TIME", - /// ShortMnemonic = "TIME", - /// Description = "Time", - /// Description2 = "Indicates the date the computer generated this record. The date is reported as a 6 digit integer in a YYMMDD type format. e.g. 910404 would represent April 4, 1991. It is common to all records. Note that, like Time below, Universal Coordinated Time (Greenwich Mean Time) is used as the common reference. Note also that though this number should never decrease, there is no guarantee of this fact.", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 4, - /// ValueType = "L" - /// - - public int? Time { get; set; } - - /// - /// RecordId = 1, - /// ItemId = 7, - /// LongMnemonic = "ACTCOD", - /// ShortMnemonic = "ACTC", - /// Description = "Activity Code", - /// Description2 = "Indicates the time of day (24 hour clock), when the computer generated the record, eg. 225015 would represent 10:50:15 pm. This item is common to all records. Note that, like Date above, Universal Coordinated Time (Greenwich Mean Time) is used as the common reference.", - /// FPSUnits = "----", - /// MetricUnits = "----", - /// Length = 2, - /// ValueType = "S" - /// - - public short? Actcod { get; set; } - } + public short? Actcod { get; set; } } diff --git a/AsbCloudApp/Data/WellCaseDto.cs b/AsbCloudApp/Data/WellCaseDto.cs index b3a50693..4984f88d 100644 --- a/AsbCloudApp/Data/WellCaseDto.cs +++ b/AsbCloudApp/Data/WellCaseDto.cs @@ -2,30 +2,28 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Дела скважины +/// +public class WellCaseDto { /// - /// Дела скважины + /// Скважина /// - public class WellCaseDto - { - /// - /// Скважина - /// - [Required] - public int IdWell { get; set; } + [Required] + public int IdWell { get; set; } - /// - /// Разрешение для текущего пользователя добавлять ответственных - /// - [Required] - public bool PermissionToSetPubliher { get; set; } = true; - - /// - /// Документ дела скважины - /// - [Required] - public IEnumerable WellFinalDocuments { get; set; } = Enumerable.Empty(); - } + /// + /// Разрешение для текущего пользователя добавлять ответственных + /// + [Required] + public bool PermissionToSetPubliher { get; set; } = true; + /// + /// Документ дела скважины + /// + [Required] + public IEnumerable WellFinalDocuments { get; set; } = Enumerable.Empty(); } diff --git a/AsbCloudApp/Data/WellCompositeDto.cs b/AsbCloudApp/Data/WellCompositeDto.cs index af9a91a8..f2516cf0 100644 --- a/AsbCloudApp/Data/WellCompositeDto.cs +++ b/AsbCloudApp/Data/WellCompositeDto.cs @@ -1,26 +1,25 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO элемент композитной скважины +/// +public class WellCompositeDto : IWellRelated { + /// + [Required] + public int IdWell { get; set; } + /// - /// DTO элемент композитной скважины + /// id скважины входящей в композитную для этой /// - public class WellCompositeDto : IWellRelated - { - /// - [Required] - public int IdWell { get; set; } + [Required] + public int IdWellSrc { get; set; } - /// - /// id скважины входящей в композитную для этой - /// - [Required] - public int IdWellSrc { get; set; } - - /// - /// id секции скважины входящей в композитную для этой - /// - [Required] - public int IdWellSectionType { get; set; } - } + /// + /// id секции скважины входящей в композитную для этой + /// + [Required] + public int IdWellSectionType { get; set; } } diff --git a/AsbCloudApp/Data/WellCompositeOperationDto.cs b/AsbCloudApp/Data/WellCompositeOperationDto.cs index 97c1ff90..f6f47143 100644 --- a/AsbCloudApp/Data/WellCompositeOperationDto.cs +++ b/AsbCloudApp/Data/WellCompositeOperationDto.cs @@ -5,22 +5,21 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Хранение операций по композитной скважине +/// и по скважинам, на основе которых была рассчитана композитная скважина +/// +public class WellCompositeOperationDto { /// - /// Хранение операций по композитной скважине - /// и по скважинам, на основе которых была рассчитана композитная скважина + /// Список операций композитной скважины /// - public class WellCompositeOperationDto - { - /// - /// Список операций композитной скважины - /// - public IEnumerable WellOperationsComposite { get; set; } = null!; + public IEnumerable WellOperationsComposite { get; set; } = null!; - /// - /// Список операций, на основе которых были рассчитаны операции по композитной скважине - /// - public IEnumerable WellCompositeSourceOperations { get; set; } = null!; - } + /// + /// Список операций, на основе которых были рассчитаны операции по композитной скважине + /// + public IEnumerable WellCompositeSourceOperations { get; set; } = null!; } diff --git a/AsbCloudApp/Data/WellCompositeOperationSourceDto.cs b/AsbCloudApp/Data/WellCompositeOperationSourceDto.cs index e991dd3f..18c54646 100644 --- a/AsbCloudApp/Data/WellCompositeOperationSourceDto.cs +++ b/AsbCloudApp/Data/WellCompositeOperationSourceDto.cs @@ -1,21 +1,20 @@ using AsbCloudApp.Data.WellOperation; using System.Collections.Generic; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Операции по скважине, по которой рассчитывается композитная скважина +/// +public class WellCompositeOperationSourceDto { /// - /// Операции по скважине, по которой рассчитывается композитная скважина + /// Скважина /// - public class WellCompositeOperationSourceDto - { - /// - /// Скважина - /// - public WellDto Well { get; set; } = null!; + public WellDto Well { get; set; } = null!; - /// - /// Операции по скважине - /// - public IEnumerable Operations { get; set; } = null!; - } + /// + /// Операции по скважине + /// + public IEnumerable Operations { get; set; } = null!; } diff --git a/AsbCloudApp/Data/WellDto.cs b/AsbCloudApp/Data/WellDto.cs index 223aad41..a158c5a8 100644 --- a/AsbCloudApp/Data/WellDto.cs +++ b/AsbCloudApp/Data/WellDto.cs @@ -3,90 +3,89 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// базовая информация о скважине +/// +public class WellWithTimezoneDto : WellInfoDto { - /// - /// базовая информация о скважине - /// - public class WellWithTimezoneDto : WellInfoDto - { - /// - [Required] - public SimpleTimezoneDto Timezone { get; set; } = null!; - - /// - /// 0 - неизвестно, - /// 1 - в работе, - /// 2 - завершена - /// - [Required] - public int IdState { get; set; } - } + /// + [Required] + public SimpleTimezoneDto Timezone { get; set; } = null!; /// - /// Скважина + /// 0 - неизвестно, + /// 1 - в работе, + /// 2 - завершена /// - public class WellDto : WellInfoDto, IMapPoint, IId - { - /// - [Range(-90, 90, ErrorMessage = "Допустимые значения широты от -90 до 90")] - public double? Latitude { get; set; } - - /// - [Range(-180, 180, ErrorMessage = "Допустимые значения долготы от -180 до 180")] - public double? Longitude { get; set; } - - /// - [Required] - public SimpleTimezoneDto Timezone { get; set; } = null!; - - /// - /// Название типа скважины - /// - public string? WellType { get; set; } - - /// - /// ID типа скважины - /// - [Range(1, 2, ErrorMessage = "Тип скважины указан неправильно.")] - public int IdWellType { get; set; } - - /// - /// ID куста - /// - public int IdCluster { get; set; } - - /// - /// 0 - неизвестно, - /// 1 - в работе, - /// 2 - завершена - /// - [Range(0, 2, ErrorMessage = "Текущее состояние работы скважины указано неправильно.")] - public int IdState { get; set; } - - /// - /// Дата/время первой операции - /// - public DateTimeOffset? StartDate { get; set; } - - /// - /// Дата/время кода приходили данные последний раз - /// - public DateTimeOffset LastTelemetryDate { get; set; } - - /// - /// ID телеметрии - /// - public int? IdTelemetry { get; set; } - - /// - /// Объект телеметрии (инфо от панели оператора) - /// - public TelemetryBaseDto? Telemetry { get; set; } - - /// - /// Компании участвующие в работах на скважине - /// - public IEnumerable Companies { get; set; } = Enumerable.Empty(); - } + [Required] + public int IdState { get; set; } +} + +/// +/// Скважина +/// +public class WellDto : WellInfoDto, IMapPoint, IId +{ + /// + [Range(-90, 90, ErrorMessage = "Допустимые значения широты от -90 до 90")] + public double? Latitude { get; set; } + + /// + [Range(-180, 180, ErrorMessage = "Допустимые значения долготы от -180 до 180")] + public double? Longitude { get; set; } + + /// + [Required] + public SimpleTimezoneDto Timezone { get; set; } = null!; + + /// + /// Название типа скважины + /// + public string? WellType { get; set; } + + /// + /// ID типа скважины + /// + [Range(1, 2, ErrorMessage = "Тип скважины указан неправильно.")] + public int IdWellType { get; set; } + + /// + /// ID куста + /// + public int IdCluster { get; set; } + + /// + /// 0 - неизвестно, + /// 1 - в работе, + /// 2 - завершена + /// + [Range(0, 2, ErrorMessage = "Текущее состояние работы скважины указано неправильно.")] + public int IdState { get; set; } + + /// + /// Дата/время первой операции + /// + public DateTimeOffset? StartDate { get; set; } + + /// + /// Дата/время кода приходили данные последний раз + /// + public DateTimeOffset LastTelemetryDate { get; set; } + + /// + /// ID телеметрии + /// + public int? IdTelemetry { get; set; } + + /// + /// Объект телеметрии (инфо от панели оператора) + /// + public TelemetryBaseDto? Telemetry { get; set; } + + /// + /// Компании участвующие в работах на скважине + /// + public IEnumerable Companies { get; set; } = Enumerable.Empty(); } diff --git a/AsbCloudApp/Data/WellFinalDocumentDBDto.cs b/AsbCloudApp/Data/WellFinalDocumentDBDto.cs index d69c793e..eae27862 100644 --- a/AsbCloudApp/Data/WellFinalDocumentDBDto.cs +++ b/AsbCloudApp/Data/WellFinalDocumentDBDto.cs @@ -1,23 +1,22 @@ -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO Дело скважины +/// +public class WellFinalDocumentDBDto { /// - /// DTO Дело скважины + /// Идентификатор скважины /// - public class WellFinalDocumentDBDto - { - /// - /// Идентификатор скважины - /// - public int IdWell { get; set; } + public int IdWell { get; set; } - /// - /// Идентификатор ответственного - /// - public int IdUser { get; set; } + /// + /// Идентификатор ответственного + /// + public int IdUser { get; set; } - /// - /// Идентификатор категории файла - /// - public int IdCategory { get; set; } - } + /// + /// Идентификатор категории файла + /// + public int IdCategory { get; set; } } diff --git a/AsbCloudApp/Data/WellFinalDocumentDto.cs b/AsbCloudApp/Data/WellFinalDocumentDto.cs index 7fe90b6a..f507bbf0 100644 --- a/AsbCloudApp/Data/WellFinalDocumentDto.cs +++ b/AsbCloudApp/Data/WellFinalDocumentDto.cs @@ -3,45 +3,44 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using AsbCloudApp.Data.User; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO Документ дела скважины +/// +public class WellFinalDocumentDto { /// - /// DTO Документ дела скважины + /// Идентификатор категории файла /// - public class WellFinalDocumentDto - { - /// - /// Идентификатор категории файла - /// - [Required] - public int IdCategory { get; set; } + [Required] + public int IdCategory { get; set; } - /// - /// Наименование категории файла - /// - public string NameCategory { get; set; } = string.Empty; + /// + /// Наименование категории файла + /// + public string NameCategory { get; set; } = string.Empty; - /// - /// Разрешение для текущего пользователя загружать документ - /// - [Required] - public bool PermissionToUpload { get; set; } = false; + /// + /// Разрешение для текущего пользователя загружать документ + /// + [Required] + public bool PermissionToUpload { get; set; } = false; - /// - /// Список ответственных - /// - [Required] - public IEnumerable Publishers { get; set; } = Enumerable.Empty(); + /// + /// Список ответственных + /// + [Required] + public IEnumerable Publishers { get; set; } = Enumerable.Empty(); - /// - /// Количество файлов этой категории загруженных ранее - /// - [Required] - public int FilesCount { get; set; } + /// + /// Количество файлов этой категории загруженных ранее + /// + [Required] + public int FilesCount { get; set; } - /// - /// Актуальный файл - /// - public FileInfoDto? File { get; set; } - } + /// + /// Актуальный файл + /// + public FileInfoDto? File { get; set; } } diff --git a/AsbCloudApp/Data/WellFinalDocumentInputDto.cs b/AsbCloudApp/Data/WellFinalDocumentInputDto.cs index 82e2072d..1da39906 100644 --- a/AsbCloudApp/Data/WellFinalDocumentInputDto.cs +++ b/AsbCloudApp/Data/WellFinalDocumentInputDto.cs @@ -2,23 +2,22 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO Для сохранения категорий дела скважины +/// +public class WellFinalDocumentInputDto { /// - /// DTO Для сохранения категорий дела скважины + /// Идентификатор категории файла /// - public class WellFinalDocumentInputDto - { - /// - /// Идентификатор категории файла - /// - [Required] - public int IdCategory { get; set; } + [Required] + public int IdCategory { get; set; } - /// - /// Список ответственных - /// - [Required] - public IEnumerable IdsPublishers { get; set; } = Enumerable.Empty(); - } + /// + /// Список ответственных + /// + [Required] + public IEnumerable IdsPublishers { get; set; } = Enumerable.Empty(); } diff --git a/AsbCloudApp/Data/WellFinalDocumentsHistoryDto.cs b/AsbCloudApp/Data/WellFinalDocumentsHistoryDto.cs index b69bb415..0e2239a3 100644 --- a/AsbCloudApp/Data/WellFinalDocumentsHistoryDto.cs +++ b/AsbCloudApp/Data/WellFinalDocumentsHistoryDto.cs @@ -1,29 +1,28 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// DTO Дело скважины, история файлов +/// +public class WellFinalDocumentsHistoryDto { /// - /// DTO Дело скважины, история файлов + /// Вышка /// - public class WellFinalDocumentsHistoryDto - { - /// - /// Вышка - /// - [Required] - public int IdWell { get; set; } + [Required] + public int IdWell { get; set; } - /// - /// Наименование категории файла - /// - [Required] - public int IdCategory { get; set; } + /// + /// Наименование категории файла + /// + [Required] + public int IdCategory { get; set; } - /// - /// Файлы - /// - [Required] - public IEnumerable Files { get; set; } = null!; - } + /// + /// Файлы + /// + [Required] + public IEnumerable Files { get; set; } = null!; } diff --git a/AsbCloudApp/Data/WellInfoDto.cs b/AsbCloudApp/Data/WellInfoDto.cs index 58ce537d..3d85ad48 100644 --- a/AsbCloudApp/Data/WellInfoDto.cs +++ b/AsbCloudApp/Data/WellInfoDto.cs @@ -1,29 +1,28 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// базовая информация о скважине +/// +public class WellInfoDto: IId { + /// + public int Id { get; set; } + /// - /// базовая информация о скважине + /// Название /// - public class WellInfoDto: IId - { - /// - public int Id { get; set; } + [Required] + public string Caption { get; set; } = null!; - /// - /// Название - /// - [Required] - public string Caption { get; set; } = null!; + /// + /// Название куста + /// + public string? Cluster { get; set; } - /// - /// Название куста - /// - public string? Cluster { get; set; } - - /// - /// Название месторождения - /// - public string? Deposit { get; set; } - } + /// + /// Название месторождения + /// + public string? Deposit { get; set; } } \ No newline at end of file diff --git a/AsbCloudApp/Data/WellMapInfoDto.cs b/AsbCloudApp/Data/WellMapInfoDto.cs index 2b49ad3f..49e3d57f 100644 --- a/AsbCloudApp/Data/WellMapInfoDto.cs +++ b/AsbCloudApp/Data/WellMapInfoDto.cs @@ -3,142 +3,141 @@ using System; using System.Collections.Generic; using System.Linq; -namespace AsbCloudApp.Data +namespace AsbCloudApp.Data; + +/// +/// Инфо о скважине для отображения на карте последними данными телеметрии +/// +public class WellMapInfoWithTelemetryStat : WellMapInfoDto { /// - /// Инфо о скважине для отображения на карте последними данными телеметрии + /// Последние полученные данные от АПД /// - public class WellMapInfoWithTelemetryStat : WellMapInfoDto - { - /// - /// Последние полученные данные от АПД - /// - public TelemetryDataSaubDto? LastDataSaub { get; set; } - - /// - /// Последние полученные данные от Осцилляции - /// - public TelemetryDataSpinDto? LastDataSpin { get; set; } - - /// - /// Дата полседнего получения данных от ННБ - /// - public DateTime? LastDataDdsDate { get; set; } - - /// - /// Дата полседнего получения данных от ГТИ - /// - public DateTime? LastDataGtrDate { get; set; } - - /// - /// Дата полседнего получения данных от СКПБ - /// - public DateTime? LastDataDpcsDate { get; set; } - - /// - /// Дата полседнего получения данных от станции контроля параметров цементирования (СКЦ) - /// - public DateTime? LastDataCpmsDate { get; set; } - - /// - /// Компании - /// - public IEnumerable Companies { get; set; } = Enumerable.Empty(); - } + public TelemetryDataSaubDto? LastDataSaub { get; set; } /// - /// Инфо о скважине для отображения на карте + /// Последние полученные данные от Осцилляции /// - public class WellMapInfoDto: MapPointBaseDto - { - /// - /// 0 - неизвестно, - /// 1 - в работе, - /// 2 - завершена - /// - public int IdState { get; set; } - - /// - /// Название текущей секции - /// - public string? Section { get; set; } + public TelemetryDataSpinDto? LastDataSpin { get; set; } - /// - /// Коэф-т использования автоподачи долота (суммарный ротор + слайд) - /// - public double SaubUsage { get; set; } + /// + /// Дата полседнего получения данных от ННБ + /// + public DateTime? LastDataDdsDate { get; set; } - /// - /// Коэф-т использования осциллятора - /// - public double SpinUsage { get; set; } + /// + /// Дата полседнего получения данных от ГТИ + /// + public DateTime? LastDataGtrDate { get; set; } - /// - /// Коэф-т использования демпфера - /// - public double TorqueKUsage { get; set; } + /// + /// Дата полседнего получения данных от СКПБ + /// + public DateTime? LastDataDpcsDate { get; set; } - /// - /// Дата начала первой фактической операции - /// Используется как дата начала бурения - /// - public DateTimeOffset? FirstFactOperationDateStart { get; set; } + /// + /// Дата полседнего получения данных от станции контроля параметров цементирования (СКЦ) + /// + public DateTime? LastDataCpmsDate { get; set; } - /// - /// Дата окончания последней прогнозируемой операции - /// Если скважина завершена, то дата окончания последней фактической операции - /// Используется как прогноз окончания бурения - /// - public DateTimeOffset? LastPredictOperationDateEnd { get; set; } - - /// - /// Рейсовая скорость проходки, последнего рейса - /// - public PlanFactDto RaceSpeed { get; set; } = null!; - - /// - /// Механическая скорость проходки, последней операции бурения - /// - public PlanFactDto ROP { get; set; } = null!; - - /// - /// Нагрузка на долота, Т - /// - public PlanFactDto AxialLoad { get; set; } = null!; - - /// - /// Обороты ротора - /// - public PlanFactDto TopDriveSpeed { get; set; } = null!; - - /// - /// Момент ротора кн/м - /// - public PlanFactDto TopDriveTorque { get; set; } = null!; - - /// - /// Перепад давления - /// - public PlanFactDto Pressure { get; set; } = null!; - - /// - /// Действующее задание давления, атм - /// - public double? PressureSp { get; set; } - - /// - /// Плановая и текущая глубина - /// - public PlanFactDto WellDepth { get; set; } = null!; - - /// - /// Отставание от ГГД, дни - /// - public double? TvdLagDays { get; set; } - - /// - /// Кол-во дней бурения по ГГД - /// - public double? TvdDrillingDays { get; set; } - } + /// + /// Компании + /// + public IEnumerable Companies { get; set; } = Enumerable.Empty(); +} + +/// +/// Инфо о скважине для отображения на карте +/// +public class WellMapInfoDto: MapPointBaseDto +{ + /// + /// 0 - неизвестно, + /// 1 - в работе, + /// 2 - завершена + /// + public int IdState { get; set; } + + /// + /// Название текущей секции + /// + public string? Section { get; set; } + + /// + /// Коэф-т использования автоподачи долота (суммарный ротор + слайд) + /// + public double SaubUsage { get; set; } + + /// + /// Коэф-т использования осциллятора + /// + public double SpinUsage { get; set; } + + /// + /// Коэф-т использования демпфера + /// + public double TorqueKUsage { get; set; } + + /// + /// Дата начала первой фактической операции + /// Используется как дата начала бурения + /// + public DateTimeOffset? FirstFactOperationDateStart { get; set; } + + /// + /// Дата окончания последней прогнозируемой операции + /// Если скважина завершена, то дата окончания последней фактической операции + /// Используется как прогноз окончания бурения + /// + public DateTimeOffset? LastPredictOperationDateEnd { get; set; } + + /// + /// Рейсовая скорость проходки, последнего рейса + /// + public PlanFactDto RaceSpeed { get; set; } = null!; + + /// + /// Механическая скорость проходки, последней операции бурения + /// + public PlanFactDto ROP { get; set; } = null!; + + /// + /// Нагрузка на долота, Т + /// + public PlanFactDto AxialLoad { get; set; } = null!; + + /// + /// Обороты ротора + /// + public PlanFactDto TopDriveSpeed { get; set; } = null!; + + /// + /// Момент ротора кн/м + /// + public PlanFactDto TopDriveTorque { get; set; } = null!; + + /// + /// Перепад давления + /// + public PlanFactDto Pressure { get; set; } = null!; + + /// + /// Действующее задание давления, атм + /// + public double? PressureSp { get; set; } + + /// + /// Плановая и текущая глубина + /// + public PlanFactDto WellDepth { get; set; } = null!; + + /// + /// Отставание от ГГД, дни + /// + public double? TvdLagDays { get; set; } + + /// + /// Кол-во дней бурения по ГГД + /// + public double? TvdDrillingDays { get; set; } } diff --git a/AsbCloudApp/Data/WellOperation/WellOperationCategoryDto.cs b/AsbCloudApp/Data/WellOperation/WellOperationCategoryDto.cs index 46e7dbe5..176d8596 100644 --- a/AsbCloudApp/Data/WellOperation/WellOperationCategoryDto.cs +++ b/AsbCloudApp/Data/WellOperation/WellOperationCategoryDto.cs @@ -1,38 +1,37 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data.WellOperation +namespace AsbCloudApp.Data.WellOperation; + +/// +/// DTO категория операции +/// +public class WellOperationCategoryDto : IId { + /// + [Required] + public int Id { get; set; } + /// - /// DTO категория операции + /// название /// - public class WellOperationCategoryDto : IId - { - /// - [Required] - public int Id { get; set; } + [Required] + [StringLength(512)] + public string Name { get; set; } = null!; - /// - /// название - /// - [Required] - [StringLength(512)] - public string Name { get; set; } = null!; + /// + /// Идентификатор родительской категории + /// + public int? IdParent { get; set; } - /// - /// Идентификатор родительской категории - /// - public int? IdParent { get; set; } + /// + /// Название ключевого показателя операции + /// + [StringLength(32)] + public string? KeyValueName { get; set; } - /// - /// Название ключевого показателя операции - /// - [StringLength(32)] - public string? KeyValueName { get; set; } - - /// - /// Единицы измерения ключевого показателя операции - /// - [StringLength(16)] - public string? KeyValueUnits { get; set; } - } + /// + /// Единицы измерения ключевого показателя операции + /// + [StringLength(16)] + public string? KeyValueUnits { get; set; } } diff --git a/AsbCloudApp/Exceptions/ArgumentInvalidException.cs b/AsbCloudApp/Exceptions/ArgumentInvalidException.cs index 93c37fa7..d0f3a316 100644 --- a/AsbCloudApp/Exceptions/ArgumentInvalidException.cs +++ b/AsbCloudApp/Exceptions/ArgumentInvalidException.cs @@ -2,41 +2,40 @@ using System; using System.Collections.Generic; using System.Linq; -namespace AsbCloudApp.Exceptions +namespace AsbCloudApp.Exceptions; + +/// +/// Argument validation fail Exception +/// +public class ArgumentInvalidException : Exception { /// - /// Argument validation fail Exception + /// словарь с ошибками, где ключ - имя аргумента, а значение - массив из одного сообщения /// - public class ArgumentInvalidException : Exception + public IDictionary ErrorState { get; } = null!; + + // TODO: swap arguments, inherit from ArgumentException + /// + /// конструктор + /// + /// + /// + public ArgumentInvalidException(string paramName, string message) + : base(message) { - /// - /// словарь с ошибками, где ключ - имя аргумента, а значение - массив из одного сообщения - /// - public IDictionary ErrorState { get; } = null!; + ErrorState = new Dictionary() { + { paramName, new[]{ message } } + }; + } - // TODO: swap arguments, inherit from ArgumentException - /// - /// конструктор - /// - /// - /// - public ArgumentInvalidException(string paramName, string message) - : base(message) - { - ErrorState = new Dictionary() { - { paramName, new[]{ message } } - }; - } - - /// - /// конструктор - /// - /// - /// - public ArgumentInvalidException(string[] paramsNames, string message) - : base(message) - { - ErrorState = paramsNames.ToDictionary(paramName => paramName, item => new[] { message }); - } + /// + /// конструктор + /// + /// + /// + public ArgumentInvalidException(string[] paramsNames, string message) + : base(message) + { + ErrorState = paramsNames.ToDictionary(paramName => paramName, item => new[] { message }); } } diff --git a/AsbCloudApp/Exceptions/ForbidException.cs b/AsbCloudApp/Exceptions/ForbidException.cs index daad3d49..79dda311 100644 --- a/AsbCloudApp/Exceptions/ForbidException.cs +++ b/AsbCloudApp/Exceptions/ForbidException.cs @@ -1,23 +1,22 @@ using System; -namespace AsbCloudApp.Exceptions +namespace AsbCloudApp.Exceptions; + +/// +/// Access denied exception +/// +public class ForbidException : Exception { /// /// Access denied exception /// - public class ForbidException : Exception - { - /// - /// Access denied exception - /// - public ForbidException() - : base() { } + public ForbidException() + : base() { } - /// - /// Access denied exception - /// - public ForbidException(string message) - : base(message) { } + /// + /// Access denied exception + /// + public ForbidException(string message) + : base(message) { } - } } diff --git a/AsbCloudApp/Extensions/ChangeLogExtensions.cs b/AsbCloudApp/Extensions/ChangeLogExtensions.cs index 32b636ed..a9a82135 100644 --- a/AsbCloudApp/Extensions/ChangeLogExtensions.cs +++ b/AsbCloudApp/Extensions/ChangeLogExtensions.cs @@ -6,28 +6,27 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace AsbCloudApp.Extensions +namespace AsbCloudApp.Extensions; + +/// +/// Расширения для поиска в истории +/// +public static class ChangeLogExtensions { /// - /// Расширения для поиска в истории + /// Действительные на момент времени значения /// - public static class ChangeLogExtensions + /// + /// + /// + /// + public static IEnumerable> WhereActualAtMoment(this IEnumerable> items, DateTimeOffset moment) + where T : IId { - /// - /// Действительные на момент времени значения - /// - /// - /// - /// - /// - public static IEnumerable> WhereActualAtMoment(this IEnumerable> items, DateTimeOffset moment) - where T : IId - { - var actualItems = items - .Where(item => item.Creation <= moment) - .Where(item => item.Obsolete is null || item.Obsolete >= moment); + var actualItems = items + .Where(item => item.Creation <= moment) + .Where(item => item.Obsolete is null || item.Obsolete >= moment); - return actualItems; - } + return actualItems; } } diff --git a/AsbCloudApp/Repositories/IDataSaubStatRepository.cs b/AsbCloudApp/Repositories/IDataSaubStatRepository.cs index b25675c7..d419ad82 100644 --- a/AsbCloudApp/Repositories/IDataSaubStatRepository.cs +++ b/AsbCloudApp/Repositories/IDataSaubStatRepository.cs @@ -5,37 +5,36 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Repositories +namespace AsbCloudApp.Repositories; + +/// +/// Репозиторий работы с данными из таблицы t_data_daub_stat +/// +public interface IDataSaubStatRepository : ITelemetryDataEditorService { /// - /// Репозиторий работы с данными из таблицы t_data_daub_stat + /// Получение записей по ключу телеметрии /// - public interface IDataSaubStatRepository : ITelemetryDataEditorService - { - /// - /// Получение записей по ключу телеметрии - /// - /// ключ телеметрии - /// начальная дата - /// конечная дата - /// - /// - Task> GetAsync(int idTelemetry, DateTimeOffset geDate, DateTimeOffset leDate, CancellationToken token); + /// ключ телеметрии + /// начальная дата + /// конечная дата + /// + /// + Task> GetAsync(int idTelemetry, DateTimeOffset geDate, DateTimeOffset leDate, CancellationToken token); - /// - /// Получение последних по дате окончания бурения записей в разрезе телеметрий - /// - /// ключи телеметрий - /// - /// - Task> GetLastsAsync(int[] idTelemetries, CancellationToken token); + /// + /// Получение последних по дате окончания бурения записей в разрезе телеметрий + /// + /// ключи телеметрий + /// + /// + Task> GetLastsAsync(int[] idTelemetries, CancellationToken token); - /// - /// Вставка записей статистики - /// - /// - /// - /// - Task InsertRangeAsync(IEnumerable dataSaubStats, CancellationToken token); - } + /// + /// Вставка записей статистики + /// + /// + /// + /// + Task InsertRangeAsync(IEnumerable dataSaubStats, CancellationToken token); } diff --git a/AsbCloudApp/Repositories/IDepositRepository.cs b/AsbCloudApp/Repositories/IDepositRepository.cs index 4185c9e3..dc1f3833 100644 --- a/AsbCloudApp/Repositories/IDepositRepository.cs +++ b/AsbCloudApp/Repositories/IDepositRepository.cs @@ -3,31 +3,30 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Repositories +namespace AsbCloudApp.Repositories; + +/// +/// Сервис информации о кустах +/// +public interface IDepositRepository { /// - /// Сервис информации о кустах + /// список месторождений, доступных для пользователя /// - public interface IDepositRepository - { - /// - /// список месторождений, доступных для пользователя - /// - /// - /// - /// - Task> GetAsync(int idCompany, - CancellationToken token); + /// + /// + /// + Task> GetAsync(int idCompany, + CancellationToken token); - /// - /// Список кустов месторождения доступных компании - /// - /// - /// - /// - /// - Task> GetClustersAsync(int idCompany, - int depositId, CancellationToken token); + /// + /// Список кустов месторождения доступных компании + /// + /// + /// + /// + /// + Task> GetClustersAsync(int idCompany, + int depositId, CancellationToken token); - } } diff --git a/AsbCloudApp/Repositories/IDrillTestRepository.cs b/AsbCloudApp/Repositories/IDrillTestRepository.cs index d7b5d1b7..20fc28b6 100644 --- a/AsbCloudApp/Repositories/IDrillTestRepository.cs +++ b/AsbCloudApp/Repositories/IDrillTestRepository.cs @@ -5,38 +5,37 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Repositories +namespace AsbCloudApp.Repositories; + +/// +/// репозиторий по работе с данными drill_test +/// +public interface IDrillTestRepository : ITelemetryDataEditorService { /// - /// репозиторий по работе с данными drill_test + /// Получить данные drill_test в соответствии с параметрами запроса /// - public interface IDrillTestRepository : ITelemetryDataEditorService - { - /// - /// Получить данные drill_test в соответствии с параметрами запроса - /// - /// ключ телеметрии - /// запрос - /// - /// - Task> GetAllAsync(int idTelemetry, FileReportRequest request, CancellationToken cancellationToken); + /// ключ телеметрии + /// запрос + /// + /// + Task> GetAllAsync(int idTelemetry, FileReportRequest request, CancellationToken cancellationToken); - /// - /// Получить запись drill_test - /// - /// ключ телеметрии - /// ключ записи drill_test - /// - /// - Task GetAsync(int idTelemetry, int id, CancellationToken cancellationToken); + /// + /// Получить запись drill_test + /// + /// ключ телеметрии + /// ключ записи drill_test + /// + /// + Task GetAsync(int idTelemetry, int id, CancellationToken cancellationToken); - /// - /// Сохранить данные drill_test - /// - /// ключ телеметрии - /// записи drill test - /// - /// - Task SaveDataAsync(int idTelemetry, IEnumerable dtos, CancellationToken token); - } + /// + /// Сохранить данные drill_test + /// + /// ключ телеметрии + /// записи drill test + /// + /// + Task SaveDataAsync(int idTelemetry, IEnumerable dtos, CancellationToken token); } diff --git a/AsbCloudApp/Repositories/IFaqRepository.cs b/AsbCloudApp/Repositories/IFaqRepository.cs index f4079159..0df1b1e9 100644 --- a/AsbCloudApp/Repositories/IFaqRepository.cs +++ b/AsbCloudApp/Repositories/IFaqRepository.cs @@ -5,61 +5,60 @@ using System.Threading; using AsbCloudApp.Requests; using AsbCloudApp.Services; -namespace AsbCloudApp.Repositories +namespace AsbCloudApp.Repositories; + +/// +/// репозиторий по работе с faq-вопросами +/// +public interface IFaqRepository { /// - /// репозиторий по работе с faq-вопросами + /// Получить список вопросов /// - public interface IFaqRepository - { - /// - /// Получить список вопросов - /// - /// - /// - /// - Task> GetFilteredAsync(FaqRequest request, CancellationToken token); + /// + /// + /// + Task> GetFilteredAsync(FaqRequest request, CancellationToken token); - /// - /// Добавить вопрос - /// - /// - /// - /// - Task InsertAsync(FaqDto faqDto, CancellationToken token); + /// + /// Добавить вопрос + /// + /// + /// + /// + Task InsertAsync(FaqDto faqDto, CancellationToken token); - /// - /// Обновить существующий вопрос - /// - /// - /// - /// - Task UpdateAsync(FaqDto dto, CancellationToken token); + /// + /// Обновить существующий вопрос + /// + /// + /// + /// + Task UpdateAsync(FaqDto dto, CancellationToken token); - /// - /// Объединить 2 вопроса в 1 - /// - /// ключ первого вопроса, подлежащего объединению - /// ключ второго вопроса, подлежащего объединению - /// Флаг, объединять текст вопросов или нет - /// - /// - Task MergeAsync(int sourceId1, int sourceId2, bool mergeQuestions, CancellationToken token); + /// + /// Объединить 2 вопроса в 1 + /// + /// ключ первого вопроса, подлежащего объединению + /// ключ второго вопроса, подлежащего объединению + /// Флаг, объединять текст вопросов или нет + /// + /// + Task MergeAsync(int sourceId1, int sourceId2, bool mergeQuestions, CancellationToken token); - /// - /// Пометить вопрос по id как удаленный - /// - /// - /// - /// - Task MarkAsDeletedAsync(int id, CancellationToken token); + /// + /// Пометить вопрос по id как удаленный + /// + /// + /// + /// + Task MarkAsDeletedAsync(int id, CancellationToken token); - /// - /// Удалить вопрос по ключу - /// - /// - /// - /// - Task DeleteAsync(int id, CancellationToken token); - } + /// + /// Удалить вопрос по ключу + /// + /// + /// + /// + Task DeleteAsync(int id, CancellationToken token); } diff --git a/AsbCloudApp/Repositories/IFileRepository.cs b/AsbCloudApp/Repositories/IFileRepository.cs index 7ed4d574..c75ad977 100644 --- a/AsbCloudApp/Repositories/IFileRepository.cs +++ b/AsbCloudApp/Repositories/IFileRepository.cs @@ -5,77 +5,76 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Repositories +namespace AsbCloudApp.Repositories; + +/// +/// Сервис доступа к файлам +/// +public interface IFileRepository : ICrudRepository { /// - /// Сервис доступа к файлам + /// Получение файлов по скважине /// - public interface IFileRepository : ICrudRepository - { - /// - /// Получение файлов по скважине - /// - /// - /// - /// - Task> GetInfosAsync(FileRequest request, CancellationToken token); + /// + /// + /// + Task> GetInfosAsync(FileRequest request, CancellationToken token); - /// - /// Получить список файлов в контейнере - /// - /// - /// - /// - Task> GetInfosPaginatedAsync(FileRequest request, CancellationToken token = default); + /// + /// Получить список файлов в контейнере + /// + /// + /// + /// + Task> GetInfosPaginatedAsync(FileRequest request, CancellationToken token = default); - /// - /// Пометить файл как удаленный - /// - /// - /// - /// - Task MarkAsDeletedAsync(int idFile, CancellationToken token = default); + /// + /// Пометить файл как удаленный + /// + /// + /// + /// + Task MarkAsDeletedAsync(int idFile, CancellationToken token = default); - /// - /// удалить файлы - /// - /// - /// - /// - Task> DeleteAsync(IEnumerable ids, CancellationToken token); + /// + /// удалить файлы + /// + /// + /// + /// + Task> DeleteAsync(IEnumerable ids, CancellationToken token); - /// - /// получить инфо о файле по метке - /// - /// - /// - /// - Task GetByMarkId(int idMark, CancellationToken token); + /// + /// получить инфо о файле по метке + /// + /// + /// + /// + Task GetByMarkId(int idMark, CancellationToken token); - /// - /// добавить метку на файл - /// - /// - /// - /// - /// - Task CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token); + /// + /// добавить метку на файл + /// + /// + /// + /// + /// + Task CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token); - /// - /// Инфо о файлах - /// - /// - /// - /// - Task> GetInfoByIdsAsync(IEnumerable idsFile, CancellationToken token); + /// + /// Инфо о файлах + /// + /// + /// + /// + Task> GetInfoByIdsAsync(IEnumerable idsFile, CancellationToken token); - /// - /// пометить метки файлов как удаленные - /// - /// - /// - /// - Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token); + /// + /// пометить метки файлов как удаленные + /// + /// + /// + /// + Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token); - } } diff --git a/AsbCloudApp/Repositories/IFileStorageRepository.cs b/AsbCloudApp/Repositories/IFileStorageRepository.cs index 22635e52..99e0d86a 100644 --- a/AsbCloudApp/Repositories/IFileStorageRepository.cs +++ b/AsbCloudApp/Repositories/IFileStorageRepository.cs @@ -4,107 +4,106 @@ using System.IO; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Repositories +namespace AsbCloudApp.Repositories; + +/// +/// Репозиторий хранения фалов +/// +public interface IFileStorageRepository { + /// - /// Репозиторий хранения фалов + /// Получение длинны фала и проверка его наличия, если отсутствует падает исключение /// - public interface IFileStorageRepository - { + /// + /// + long GetFileLength(string srcFilePath); - /// - /// Получение длинны фала и проверка его наличия, если отсутствует падает исключение - /// - /// - /// - long GetFileLength(string srcFilePath); + /// + /// Перемещение файла + /// + /// + /// + void MoveFile(string srcFilePath, string filePath); - /// - /// Перемещение файла - /// - /// - /// - void MoveFile(string srcFilePath, string filePath); + /// + /// Копирование файла + /// + /// + /// + /// + /// + Task SaveFileAsync(string filePathRec, Stream fileStreamSrc, CancellationToken token); - /// - /// Копирование файла - /// - /// - /// - /// - /// - Task SaveFileAsync(string filePathRec, Stream fileStreamSrc, CancellationToken token); + /// + /// Удаление пачки файлов + /// + /// + void DeleteFiles(IEnumerable filesName); - /// - /// Удаление пачки файлов - /// - /// - void DeleteFiles(IEnumerable filesName); + /// + /// Удаление одного файла + /// + /// + void DeleteFile(string fileName); - /// - /// Удаление одного файла - /// - /// - void DeleteFile(string fileName); + /// + /// Удаление директории + /// + /// + /// + void DeleteDirectory(string path, bool isRecursive); - /// - /// Удаление директории - /// - /// - /// - void DeleteDirectory(string path, bool isRecursive); + /// + /// Удаление всех файлов с диска о которых нет информации в базе + /// + /// + /// + int DeleteFilesNotInList(int idWell, IEnumerable idsFiles); - /// - /// Удаление всех файлов с диска о которых нет информации в базе - /// - /// - /// - int DeleteFilesNotInList(int idWell, IEnumerable idsFiles); + /// + /// Вывод списка всех файлов из базы, для которых нет файла на диске + /// + /// + /// + IEnumerable GetListFilesNotDisc(IEnumerable files); - /// - /// Вывод списка всех файлов из базы, для которых нет файла на диске - /// - /// - /// - IEnumerable GetListFilesNotDisc(IEnumerable files); + /// + /// Создание пути для сохранения файла связанного со скважиной + /// + /// + /// + /// + /// + /// + string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId); + + /// + /// Создание пути для сохранения файла + /// + /// + /// + /// + /// + string MakeFilePath(string path1, string path2, string path3); - /// - /// Создание пути для сохранения файла связанного со скважиной - /// - /// - /// - /// - /// - /// - string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId); - - /// - /// Создание пути для сохранения файла - /// - /// - /// - /// - /// - string MakeFilePath(string path1, string path2, string path3); - - /// - /// Получение пути к файлу связанного со скважиной - /// - /// - /// - /// - /// - /// - string GetFilePath(int idWell, int idCategory, int idFile, string dotExtenstion); - - /// - /// Получение пути файла лежащего на диске - /// - /// - /// - /// - /// - /// - string GetFilePath(string path1, string path2, int idFile, string dotExtenstion); - } + /// + /// Получение пути к файлу связанного со скважиной + /// + /// + /// + /// + /// + /// + string GetFilePath(int idWell, int idCategory, int idFile, string dotExtenstion); + + /// + /// Получение пути файла лежащего на диске + /// + /// + /// + /// + /// + /// + string GetFilePath(string path1, string path2, int idFile, string dotExtenstion); } diff --git a/AsbCloudApp/Repositories/IGtrRepository.cs b/AsbCloudApp/Repositories/IGtrRepository.cs index fcda4be2..64db4bf0 100644 --- a/AsbCloudApp/Repositories/IGtrRepository.cs +++ b/AsbCloudApp/Repositories/IGtrRepository.cs @@ -7,70 +7,69 @@ using AsbCloudApp.Requests; using AsbCloudApp.Data; using AsbCloudApp.Services; -namespace AsbCloudApp.Repositories +namespace AsbCloudApp.Repositories; + +/// +/// данные ГТИ +/// +public interface IGtrRepository : ITelemetryDataEditorService { /// - /// данные ГТИ + /// добавить данные (для панели бурильщика) /// - public interface IGtrRepository : ITelemetryDataEditorService - { - /// - /// добавить данные (для панели бурильщика) - /// - /// - /// - /// - /// - Task SaveDataAsync(int idTelemetry, IEnumerable dtos, CancellationToken token); - - /// - /// получить данные ГТИ - /// - /// - /// - /// - /// - Task> GetAsync(int idWell, GtrRequest request, CancellationToken token); + /// + /// + /// + /// + Task SaveDataAsync(int idTelemetry, IEnumerable dtos, CancellationToken token); + + /// + /// получить данные ГТИ + /// + /// + /// + /// + /// + Task> GetAsync(int idWell, GtrRequest request, CancellationToken token); - /// - /// получить данные для клиента - /// - /// - /// - /// - /// кол-во элементов до которых эти данные прореживаются - /// - /// - [Obsolete] - Task> GetAsync(int idWell, - DateTime? dateBegin, double intervalSec = 600d, - int approxPointsCount = 1024, CancellationToken token = default); + /// + /// получить данные для клиента + /// + /// + /// + /// + /// кол-во элементов до которых эти данные прореживаются + /// + /// + [Obsolete] + Task> GetAsync(int idWell, + DateTime? dateBegin, double intervalSec = 600d, + int approxPointsCount = 1024, CancellationToken token = default); - /// - /// получение последних данных ГТИ по record id - /// - /// - /// - /// - [Obsolete] - IEnumerable GetLastDataByRecordId(int idWell, int idRecord); + /// + /// получение последних данных ГТИ по record id + /// + /// + /// + /// + [Obsolete] + IEnumerable GetLastDataByRecordId(int idWell, int idRecord); - /// - /// Последние полученные параметры - /// - /// - /// - [Obsolete] - IEnumerable GetLastData(int idWell); + /// + /// Последние полученные параметры + /// + /// + /// + [Obsolete] + IEnumerable GetLastData(int idWell); - /// - /// Доступные даты по скважине - /// - /// - /// - /// - /// - /// - Task GetRangeAsync(int idWell, DateTimeOffset? geDate, DateTimeOffset? leDate, CancellationToken token); - } + /// + /// Доступные даты по скважине + /// + /// + /// + /// + /// + /// + Task GetRangeAsync(int idWell, DateTimeOffset? geDate, DateTimeOffset? leDate, CancellationToken token); } diff --git a/AsbCloudApp/Repositories/ILimitingParameterRepository.cs b/AsbCloudApp/Repositories/ILimitingParameterRepository.cs index dcc2725a..c19ff9c1 100644 --- a/AsbCloudApp/Repositories/ILimitingParameterRepository.cs +++ b/AsbCloudApp/Repositories/ILimitingParameterRepository.cs @@ -5,30 +5,29 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Repositories +namespace AsbCloudApp.Repositories; + +/// +/// Репозиторий по ограничивающим параметрам с фильтрацией +/// +public interface ILimitingParameterRepository : ITelemetryDataEditorService { /// - /// Репозиторий по ограничивающим параметрам с фильтрацией + /// Получение списка ограничивающих параметров по идентификатору скважины /// - public interface ILimitingParameterRepository : ITelemetryDataEditorService - { - /// - /// Получение списка ограничивающих параметров по идентификатору скважины - /// - /// - /// - /// - /// - Task> GetLimitingParametersAsync(LimitingParameterRequest request, WellDto wellDto, CancellationToken token); + /// + /// + /// + /// + Task> GetLimitingParametersAsync(LimitingParameterRequest request, WellDto wellDto, CancellationToken token); - /// - /// Получение списка ограничивающих параметров по идентификатору скважины - /// - /// - /// - /// - /// - /// - Task> GetLimitingParametersAsync(LimitingParameterRequest request, int idTelemetry, double timezoneHours, CancellationToken token); - } + /// + /// Получение списка ограничивающих параметров по идентификатору скважины + /// + /// + /// + /// + /// + /// + Task> GetLimitingParametersAsync(LimitingParameterRequest request, int idTelemetry, double timezoneHours, CancellationToken token); } diff --git a/AsbCloudApp/Repositories/ITelemetryDataCache.cs b/AsbCloudApp/Repositories/ITelemetryDataCache.cs index 0e4d83b1..a044c0a3 100644 --- a/AsbCloudApp/Repositories/ITelemetryDataCache.cs +++ b/AsbCloudApp/Repositories/ITelemetryDataCache.cs @@ -4,80 +4,79 @@ using AsbCloudInfrastructure.Services.SAUB; using System; using System.Collections.Generic; -namespace AsbCloudApp.Repositories +namespace AsbCloudApp.Repositories; + +/// +/// Хранилище кеша +/// +/// +public interface ITelemetryDataCache where TDto : ITelemetryData { /// - /// Хранилище кеша + /// добавить в кеш чанк записей по телеметрии /// - /// - public interface ITelemetryDataCache where TDto : ITelemetryData - { - /// - /// добавить в кеш чанк записей по телеметрии - /// - /// - /// - void AddRange(int idTelemetry, IEnumerable range); + /// + /// + void AddRange(int idTelemetry, IEnumerable range); - /// - /// вернуть последнюю запись - /// - /// - /// - TDto? GetLastOrDefault(int idTelemetry); + /// + /// вернуть последнюю запись + /// + /// + /// + TDto? GetLastOrDefault(int idTelemetry); - /// - /// Получить кешированые записи - /// - /// - /// - /// - /// приблизительное кол-во возвращаемых записей после их прореживания - /// - IEnumerable? GetOrDefault(int idTelemetry, DateTime dateBegin, double intervalSec = 600, int approxPointsCount = 1024); + /// + /// Получить кешированые записи + /// + /// + /// + /// + /// приблизительное кол-во возвращаемых записей после их прореживания + /// + IEnumerable? GetOrDefault(int idTelemetry, DateTime dateBegin, double intervalSec = 600, int approxPointsCount = 1024); - /// - /// Получить кешированые записи - /// - /// - /// - /// - IEnumerable? GetOrDefault(int idTelemetry, TelemetryDataRequest request); + /// + /// Получить кешированые записи + /// + /// + /// + /// + IEnumerable? GetOrDefault(int idTelemetry, TelemetryDataRequest request); - /// - /// Диапазон дат находящийся в кеше - /// - /// - /// - DatesRangeDto? GetOrDefaultCachedDataDateRange(int idTelemetry); + /// + /// Диапазон дат находящийся в кеше + /// + /// + /// + DatesRangeDto? GetOrDefaultCachedDataDateRange(int idTelemetry); - /// - /// Получить диапазон дат телеметрии. - /// Дата первой записи телеметрии храниться отдельно и запоняется при инициализации - /// - /// - /// - DatesRangeDto? GetOrDefaultWellDataDateRange(int idTelemetry); + /// + /// Получить диапазон дат телеметрии. + /// Дата первой записи телеметрии храниться отдельно и запоняется при инициализации + /// + /// + /// + DatesRangeDto? GetOrDefaultWellDataDateRange(int idTelemetry); - /// - /// Получение первой и последней записи телеметрии. - /// Первая запись телеметрии храниться отдельно и запоняется при инициализации - /// - /// - /// - (TDto First, TDto Last)? GetOrDefaultFirstLast(int idTelemetry); + /// + /// Получение первой и последней записи телеметрии. + /// Первая запись телеметрии храниться отдельно и запоняется при инициализации + /// + /// + /// + (TDto First, TDto Last)? GetOrDefaultFirstLast(int idTelemetry); - /// - /// статистика хранимой телеметрии по всем кешированым - /// - /// - IEnumerable GetStat(); + /// + /// статистика хранимой телеметрии по всем кешированым + /// + /// + IEnumerable GetStat(); - /// - /// Получить ключи телеметрии по параметрам запроса - /// - /// - /// - IEnumerable GetIds(TelemetryDataRequest request); - } + /// + /// Получить ключи телеметрии по параметрам запроса + /// + /// + /// + IEnumerable GetIds(TelemetryDataRequest request); } \ No newline at end of file diff --git a/AsbCloudApp/Repositories/ITelemetryWirelineRunOutRepository.cs b/AsbCloudApp/Repositories/ITelemetryWirelineRunOutRepository.cs index 3166a301..f038d977 100644 --- a/AsbCloudApp/Repositories/ITelemetryWirelineRunOutRepository.cs +++ b/AsbCloudApp/Repositories/ITelemetryWirelineRunOutRepository.cs @@ -4,36 +4,35 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Repositories +namespace AsbCloudApp.Repositories; + +/// +/// Наработка талевого каната +/// +public interface ITelemetryWirelineRunOutRepository { /// - /// Наработка талевого каната + /// Принимает данные от панели /// - public interface ITelemetryWirelineRunOutRepository - { - /// - /// Принимает данные от панели - /// - /// - /// - /// - /// - Task AddOrUpdateAsync(string uid, TelemetryWirelineRunOutBaseDto dto, CancellationToken token); + /// + /// + /// + /// + Task AddOrUpdateAsync(string uid, TelemetryWirelineRunOutBaseDto dto, CancellationToken token); - /// - /// Выдает данные по скважине - /// - /// - /// - /// - Task GetOrDefaultAsync(int idWell, CancellationToken token); + /// + /// Выдает данные по скважине + /// + /// + /// + /// + Task GetOrDefaultAsync(int idWell, CancellationToken token); - /// - /// Возвращает данные по всем скважинам - /// - /// - /// - /// - Task> GetAllAsync(int idCompany, CancellationToken token); - } + /// + /// Возвращает данные по всем скважинам + /// + /// + /// + /// + Task> GetAllAsync(int idCompany, CancellationToken token); } diff --git a/AsbCloudApp/Repositories/ITrajectoryEditableRepository.cs b/AsbCloudApp/Repositories/ITrajectoryEditableRepository.cs index ff438112..d65b1100 100644 --- a/AsbCloudApp/Repositories/ITrajectoryEditableRepository.cs +++ b/AsbCloudApp/Repositories/ITrajectoryEditableRepository.cs @@ -3,54 +3,53 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Repositories +namespace AsbCloudApp.Repositories; + +/// +/// CRUD-репозиторий для работы с траекторией из клиента (плановой и фактической) +/// +/// +//TrajectoryGeoPlanDto +public interface ITrajectoryEditableRepository : ITrajectoryRepository where T : TrajectoryGeoDto { /// - /// CRUD-репозиторий для работы с траекторией из клиента (плановой и фактической) - /// + /// Добавить строки с координатами по одной скважине. Если в коллекции координаты для разных скважин получаем exception. + /// + /// + /// + /// количество записанных строк или exception с описанием + Task AddRangeAsync(IEnumerable trajectoryRows, CancellationToken token); + + /// + /// Добавить одну строку с координатами + /// + /// + /// /// - //TrajectoryGeoPlanDto - public interface ITrajectoryEditableRepository : ITrajectoryRepository where T : TrajectoryGeoDto - { - /// - /// Добавить строки с координатами по одной скважине. Если в коллекции координаты для разных скважин получаем exception. - /// - /// - /// - /// количество записанных строк или exception с описанием - Task AddRangeAsync(IEnumerable trajectoryRows, CancellationToken token); + Task AddAsync(T trajectoryRow, CancellationToken token); - /// - /// Добавить одну строку с координатами - /// - /// - /// - /// - Task AddAsync(T trajectoryRow, CancellationToken token); + /// + /// Обновить строку с координатами + /// + /// + /// + /// + Task UpdateAsync(T row, + CancellationToken token); - /// - /// Обновить строку с координатами - /// - /// - /// - /// - Task UpdateAsync(T row, - CancellationToken token); + /// + /// Удалить строки с координатами + /// + /// + /// + /// + Task DeleteRangeAsync(IEnumerable ids, CancellationToken token); - /// - /// Удалить строки с координатами - /// - /// - /// - /// - Task DeleteRangeAsync(IEnumerable ids, CancellationToken token); - - /// - /// Удалить всю траекторию по ИД скважины - /// - /// - /// - /// - Task DeleteByIdWellAsync(int idWell, CancellationToken token); - } + /// + /// Удалить всю траекторию по ИД скважины + /// + /// + /// + /// + Task DeleteByIdWellAsync(int idWell, CancellationToken token); } diff --git a/AsbCloudApp/Repositories/ITrajectoryNnbRepository.cs b/AsbCloudApp/Repositories/ITrajectoryNnbRepository.cs index 2d3d89e0..a0abefdc 100644 --- a/AsbCloudApp/Repositories/ITrajectoryNnbRepository.cs +++ b/AsbCloudApp/Repositories/ITrajectoryNnbRepository.cs @@ -4,20 +4,19 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Repositories +namespace AsbCloudApp.Repositories; + +/// +/// репозиторий для работы с траекторией из ннб (фактической) +/// +/// +public interface ITrajectoryNnbRepository : ITrajectoryRepository { /// - /// репозиторий для работы с траекторией из ннб (фактической) + /// получение списка траекторий по параметрам запроса /// + /// параметры запроса + /// /// - public interface ITrajectoryNnbRepository : ITrajectoryRepository - { - /// - /// получение списка траекторий по параметрам запроса - /// - /// параметры запроса - /// - /// - Task> GetByRequestAsync(TrajectoryRequest trajectoryRequest, CancellationToken cancellationToken); - } + Task> GetByRequestAsync(TrajectoryRequest trajectoryRequest, CancellationToken cancellationToken); } diff --git a/AsbCloudApp/Repositories/ITrajectoryRepository.cs b/AsbCloudApp/Repositories/ITrajectoryRepository.cs index 0c51ec85..7e8048a7 100644 --- a/AsbCloudApp/Repositories/ITrajectoryRepository.cs +++ b/AsbCloudApp/Repositories/ITrajectoryRepository.cs @@ -3,20 +3,19 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Repositories +namespace AsbCloudApp.Repositories; + +/// +/// Репозиторий по работе с траекторией +/// +public interface ITrajectoryRepository + where T : TrajectoryGeoDto { /// - /// Репозиторий по работе с траекторией + /// Получить все добавленные по скважине координаты траектории /// - public interface ITrajectoryRepository - where T : TrajectoryGeoDto - { - /// - /// Получить все добавленные по скважине координаты траектории - /// - /// ключ скважины - /// - /// - Task> GetAsync(int idWell, CancellationToken token); - } + /// ключ скважины + /// + /// + Task> GetAsync(int idWell, CancellationToken token); } diff --git a/AsbCloudApp/Repositories/IUserRepository.cs b/AsbCloudApp/Repositories/IUserRepository.cs index db6a32ea..06e91bf8 100644 --- a/AsbCloudApp/Repositories/IUserRepository.cs +++ b/AsbCloudApp/Repositories/IUserRepository.cs @@ -3,34 +3,33 @@ using AsbCloudApp.Data.User; using AsbCloudApp.Services; using System.Collections.Generic; -namespace AsbCloudApp.Repositories +namespace AsbCloudApp.Repositories; + +/// +/// Репозиторий пользователей +/// +public interface IUserRepository : ICrudRepository { /// - /// Репозиторий пользователей + /// Получить список всех прав пользователя (включая наследование групп) /// - public interface IUserRepository : ICrudRepository - { - /// - /// Получить список всех прав пользователя (включая наследование групп) - /// - /// - /// - IEnumerable GetNestedPermissions(int idUser); + /// + /// + IEnumerable GetNestedPermissions(int idUser); - /// - /// Получить список ролей пользователя (включая наследование) - /// - /// - /// - /// - IEnumerable GetRolesByIdUser(int idUser, int nestedLevel = 0); + /// + /// Получить список ролей пользователя (включая наследование) + /// + /// + /// + /// + IEnumerable GetRolesByIdUser(int idUser, int nestedLevel = 0); - /// - /// определяет есть ли у пользователя указанное разрешение - /// - /// - /// - /// - public bool HasPermission(int idUser, string permissionName); - } + /// + /// определяет есть ли у пользователя указанное разрешение + /// + /// + /// + /// + public bool HasPermission(int idUser, string permissionName); } diff --git a/AsbCloudApp/Repositories/IUserRoleRepository.cs b/AsbCloudApp/Repositories/IUserRoleRepository.cs index b2ca7f4f..c1a3be61 100644 --- a/AsbCloudApp/Repositories/IUserRoleRepository.cs +++ b/AsbCloudApp/Repositories/IUserRoleRepository.cs @@ -4,35 +4,34 @@ using System.Threading.Tasks; using System.Threading; using AsbCloudApp.Data.User; -namespace AsbCloudApp.Repositories +namespace AsbCloudApp.Repositories; + +/// +/// Разрешения на доступ к данным +/// +public interface IUserRoleRepository : ICrudRepository { /// - /// Разрешения на доступ к данным + /// получить dto по названиям /// - public interface IUserRoleRepository : ICrudRepository - { - /// - /// получить dto по названиям - /// - /// - /// - /// - Task> GetByNamesAsync(IEnumerable names, CancellationToken token = default); + /// + /// + /// + Task> GetByNamesAsync(IEnumerable names, CancellationToken token = default); - /// - /// получить все вложенные разрешения - /// - /// - /// - /// - IEnumerable GetNestedById(int id, int counter = 10); + /// + /// получить все вложенные разрешения + /// + /// + /// + /// + IEnumerable GetNestedById(int id, int counter = 10); - /// - /// определяет содержится ли разрешение в одной из указанных ролей - /// - /// - /// - /// - bool HasPermission(IEnumerable rolesIds, string permissionName); - } + /// + /// определяет содержится ли разрешение в одной из указанных ролей + /// + /// + /// + /// + bool HasPermission(IEnumerable rolesIds, string permissionName); } diff --git a/AsbCloudApp/Repositories/IWellCompositeRepository.cs b/AsbCloudApp/Repositories/IWellCompositeRepository.cs index 1023ba8d..df78979f 100644 --- a/AsbCloudApp/Repositories/IWellCompositeRepository.cs +++ b/AsbCloudApp/Repositories/IWellCompositeRepository.cs @@ -4,36 +4,35 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Repositories +namespace AsbCloudApp.Repositories; + +/// +/// Репозиторий создания композитной скважины +/// +public interface IWellCompositeRepository { /// - /// Репозиторий создания композитной скважины + /// Получить секции композитной скважины /// - public interface IWellCompositeRepository - { - /// - /// Получить секции композитной скважины - /// - /// - /// - /// - Task> GetAsync(int idWell, CancellationToken token); + /// + /// + /// + Task> GetAsync(int idWell, CancellationToken token); - /// - /// сохранить секции композитной скважины - /// - /// - /// - /// - /// - Task SaveAsync(int idWell, IEnumerable wellComposites, CancellationToken token); + /// + /// сохранить секции композитной скважины + /// + /// + /// + /// + /// + Task SaveAsync(int idWell, IEnumerable wellComposites, CancellationToken token); - /// - /// Получение РТК-план бурение по композитной скважине - /// - /// - /// - /// - Task> GetCompositeProcessMap(int idWell, CancellationToken token); - } + /// + /// Получение РТК-план бурение по композитной скважине + /// + /// + /// + /// + Task> GetCompositeProcessMap(int idWell, CancellationToken token); } diff --git a/AsbCloudApp/Repositories/IWellFinalDocumentsRepository.cs b/AsbCloudApp/Repositories/IWellFinalDocumentsRepository.cs index 252c1e5b..f0e6791e 100644 --- a/AsbCloudApp/Repositories/IWellFinalDocumentsRepository.cs +++ b/AsbCloudApp/Repositories/IWellFinalDocumentsRepository.cs @@ -4,47 +4,46 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Repositories +namespace AsbCloudApp.Repositories; + +/// +/// Репозиторий "Дело скважины" +/// +public interface IWellFinalDocumentsRepository { /// - /// Репозиторий "Дело скважины" + /// Обновление всех записей по скважине /// - public interface IWellFinalDocumentsRepository - { - /// - /// Обновление всех записей по скважине - /// - /// - /// - /// - /// - Task> UpdateRangeAsync(int idWell, IEnumerable dtos, CancellationToken token); + /// + /// + /// + /// + Task> UpdateRangeAsync(int idWell, IEnumerable dtos, CancellationToken token); - /// - /// Получение всех записей - /// - /// - /// - /// - /// - Task GetByWellIdAsync(int idWell, int idUser, CancellationToken token); + /// + /// Получение всех записей + /// + /// + /// + /// + /// + Task GetByWellIdAsync(int idWell, int idUser, CancellationToken token); - /// - /// Получение списка ответственных - /// - /// - /// - /// - Task> GetAvailableUsersAsync(int idWell, CancellationToken token); + /// + /// Получение списка ответственных + /// + /// + /// + /// + Task> GetAvailableUsersAsync(int idWell, CancellationToken token); - /// - /// Возвращаент категорию файла - /// - /// - /// - /// - /// - /// - Task GetCategoryAsync(int idWell, int idCategory, int idUser, CancellationToken token); - } + /// + /// Возвращаент категорию файла + /// + /// + /// + /// + /// + /// + Task GetCategoryAsync(int idWell, int idCategory, int idUser, CancellationToken token); } diff --git a/AsbCloudApp/Repositories/IWellOperationCategoryRepository.cs b/AsbCloudApp/Repositories/IWellOperationCategoryRepository.cs index 12d7995e..e152d5ba 100644 --- a/AsbCloudApp/Repositories/IWellOperationCategoryRepository.cs +++ b/AsbCloudApp/Repositories/IWellOperationCategoryRepository.cs @@ -1,17 +1,16 @@ using System.Collections.Generic; using AsbCloudApp.Data.WellOperation; -namespace AsbCloudApp.Repositories +namespace AsbCloudApp.Repositories; + +/// +/// сервис операций по скважине +/// +public interface IWellOperationCategoryRepository { /// - /// сервис операций по скважине + /// список названий операций /// - public interface IWellOperationCategoryRepository - { - /// - /// список названий операций - /// - /// - IEnumerable Get(bool includeParents, bool includeHidden = true); - } + /// + IEnumerable Get(bool includeParents, bool includeHidden = true); } \ No newline at end of file diff --git a/AsbCloudApp/Repositories/IWellOperationRepository.cs b/AsbCloudApp/Repositories/IWellOperationRepository.cs index b7b433fe..f80ad02d 100644 --- a/AsbCloudApp/Repositories/IWellOperationRepository.cs +++ b/AsbCloudApp/Repositories/IWellOperationRepository.cs @@ -5,91 +5,90 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Repositories +namespace AsbCloudApp.Repositories; + +/// +/// сервис операций по скважине +/// +public interface IWellOperationRepository { /// - /// сервис операций по скважине + /// Список секций /// - public interface IWellOperationRepository - { - /// - /// Список секций - /// - /// - IEnumerable GetSectionTypes(); + /// + IEnumerable GetSectionTypes(); - /// - /// Добавить несколько операций - /// - /// - /// - /// - /// - Task InsertRangeAsync(IEnumerable dtos, bool deleteBeforeInsert, CancellationToken token); + /// + /// Добавить несколько операций + /// + /// + /// + /// + /// + Task InsertRangeAsync(IEnumerable dtos, bool deleteBeforeInsert, CancellationToken token); - /// - /// Обновить существующую операцию - /// - /// - /// - /// - Task UpdateRangeAsync(IEnumerable dtos, CancellationToken token); + /// + /// Обновить существующую операцию + /// + /// + /// + /// + Task UpdateRangeAsync(IEnumerable dtos, CancellationToken token); - /// - /// Удалить операции по id - /// - /// - /// - /// - Task DeleteRangeAsync(IEnumerable ids, CancellationToken token); + /// + /// Удалить операции по id + /// + /// + /// + /// + Task DeleteRangeAsync(IEnumerable ids, CancellationToken token); - /// - /// Получить секции скважин из операций ГГД. Секцие поделены на плановые и фактические. - /// - /// - /// - /// - Task> GetSectionsAsync(IEnumerable idsWells, CancellationToken token); + /// + /// Получить секции скважин из операций ГГД. Секцие поделены на плановые и фактические. + /// + /// + /// + /// + Task> GetSectionsAsync(IEnumerable idsWells, CancellationToken token); - /// - /// Получить диапазон дат выполнения операций - /// - /// - /// - /// - /// - Task GetDatesRangeAsync(int idWell, int idType, CancellationToken cancellationToken); + /// + /// Получить диапазон дат выполнения операций + /// + /// + /// + /// + /// + Task GetDatesRangeAsync(int idWell, int idType, CancellationToken cancellationToken); - /// - /// Возвращает первую и последнюю фактическую операцию - /// - /// - /// - (WellOperationBaseDto First, WellOperationBaseDto Last)? GetFirstAndLastFact(int idWell); + /// + /// Возвращает первую и последнюю фактическую операцию + /// + /// + /// + (WellOperationBaseDto First, WellOperationBaseDto Last)? GetFirstAndLastFact(int idWell); - /// - /// Получить список операций по запросу - /// - /// - /// - /// - Task> GetAll(WellOperationRequest request, CancellationToken token); + /// + /// Получить список операций по запросу + /// + /// + /// + /// + Task> GetAll(WellOperationRequest request, CancellationToken token); - /// - /// Получить список операций по запросу - /// - /// - /// - /// - Task> GetAll(WellOperationRepositoryRequest request, CancellationToken token); + /// + /// Получить список операций по запросу + /// + /// + /// + /// + Task> GetAll(WellOperationRepositoryRequest request, CancellationToken token); - /// - /// Получить список операций по ключу скважины - /// - /// - /// - /// - Task> GetAll(int idWell, CancellationToken token); - } + /// + /// Получить список операций по ключу скважины + /// + /// + /// + /// + Task> GetAll(int idWell, CancellationToken token); } \ No newline at end of file diff --git a/AsbCloudApp/Requests/DataSaubStatRequest.cs b/AsbCloudApp/Requests/DataSaubStatRequest.cs index 1fe186b5..78f314d6 100644 --- a/AsbCloudApp/Requests/DataSaubStatRequest.cs +++ b/AsbCloudApp/Requests/DataSaubStatRequest.cs @@ -1,41 +1,40 @@ using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Requests +namespace AsbCloudApp.Requests; + +/// +/// Параметры запроса для построения отчёта +/// +public class DataSaubStatRequest { /// - /// Параметры запроса для построения отчёта + /// Изменение уставки факт перепада давления от первого значения в начале интервала + /// Не менее 5 атм и не более 50 атм; /// - public class DataSaubStatRequest - { - /// - /// Изменение уставки факт перепада давления от первого значения в начале интервала - /// Не менее 5 атм и не более 50 атм; - /// - [Range(5, 50, ErrorMessage = "Изменение уставки факт перепада давления не может быть меньше 5 и больше 50 атм")] - public double DeltaPressure { get; set; } = 5d; + [Range(5, 50, ErrorMessage = "Изменение уставки факт перепада давления не может быть меньше 5 и больше 50 атм")] + public double DeltaPressure { get; set; } = 5d; - /// - /// Изменение уставки факт осевой нагрузки от первого значения в начале интервала - /// Не менее 1 т и не более 20 т; - /// - [Range(1, 20, ErrorMessage = "Изменение уставки факт осевой нагрузки не может быть меньше 1 и больше 20 т")] - public double DeltaAxialLoad { get; set; } = 1d; + /// + /// Изменение уставки факт осевой нагрузки от первого значения в начале интервала + /// Не менее 1 т и не более 20 т; + /// + [Range(1, 20, ErrorMessage = "Изменение уставки факт осевой нагрузки не может быть меньше 1 и больше 20 т")] + public double DeltaAxialLoad { get; set; } = 1d; - /// - /// Изменение уставки момента от первого значения в начале интервала - /// Не менее 5 кН*м и не более 20 кН*м. - /// - [Range(5, 20, ErrorMessage = "Изменение уставки момента не может быть меньше 5 и больше 20 кН*м")] - public double DeltaRotorTorque { get; set; } = 5d; + /// + /// Изменение уставки момента от первого значения в начале интервала + /// Не менее 5 кН*м и не более 20 кН*м. + /// + [Range(5, 20, ErrorMessage = "Изменение уставки момента не может быть меньше 5 и больше 20 кН*м")] + public double DeltaRotorTorque { get; set; } = 5d; - /// - /// Изменение ограничения нагрузки от первого значения в начале интервала - /// - public double DeltaAxialLoadSp => 1.0; + /// + /// Изменение ограничения нагрузки от первого значения в начале интервала + /// + public double DeltaAxialLoadSp => 1.0; - /// - /// Изменение ограничения момента от первого значения в начале интервала - /// - public double DeltaRotorTorqueSp => 5.0; - } + /// + /// Изменение ограничения момента от первого значения в начале интервала + /// + public double DeltaRotorTorqueSp => 5.0; } diff --git a/AsbCloudApp/Requests/FaqRequest.cs b/AsbCloudApp/Requests/FaqRequest.cs index 3094d12c..18a042f9 100644 --- a/AsbCloudApp/Requests/FaqRequest.cs +++ b/AsbCloudApp/Requests/FaqRequest.cs @@ -5,26 +5,25 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace AsbCloudApp.Requests +namespace AsbCloudApp.Requests; + +/// +/// Параметры запроса для фильтрации faq-вопросов +/// +public class FaqRequest { /// - /// Параметры запроса для фильтрации faq-вопросов + /// Есть ли ответ на вопрос /// - public class FaqRequest - { - /// - /// Есть ли ответ на вопрос - /// - public bool HasAnswer { get; set; } = false; + public bool HasAnswer { get; set; } = false; - /// - /// Частый вопрос - /// - public bool IsFrequently { get; set; } = false; + /// + /// Частый вопрос + /// + public bool IsFrequently { get; set; } = false; - /// - /// Включать ли в выборку удаленные вопросы - /// - public bool IncludeDeleted { get; set; } = false; - } + /// + /// Включать ли в выборку удаленные вопросы + /// + public bool IncludeDeleted { get; set; } = false; } diff --git a/AsbCloudApp/Requests/FileRequest.cs b/AsbCloudApp/Requests/FileRequest.cs index d8b05364..d603ad58 100644 --- a/AsbCloudApp/Requests/FileRequest.cs +++ b/AsbCloudApp/Requests/FileRequest.cs @@ -1,48 +1,47 @@ using System; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Requests +namespace AsbCloudApp.Requests; + +/// +/// Параметры запроса для файлового сервиса +/// +public class FileRequest : RequestBase { /// - /// Параметры запроса для файлового сервиса + /// Идентификатор скважины /// - public class FileRequest : RequestBase - { - /// - /// Идентификатор скважины - /// - [Required] - public int IdWell { get; set; } + [Required] + public int IdWell { get; set; } - /// - /// Идентификатор категории файла - /// - [Required] - public int? IdCategory { get; set; } - - /// - /// Наименование компании - /// - public string? CompanyNamePart { get; set; } - - /// - /// Имя файла - /// - public string? FileNamePart { get; set; } - - /// - /// Дата начала периода - /// - public DateTimeOffset? Begin { get; set; } + /// + /// Идентификатор категории файла + /// + [Required] + public int? IdCategory { get; set; } + + /// + /// Наименование компании + /// + public string? CompanyNamePart { get; set; } + + /// + /// Имя файла + /// + public string? FileNamePart { get; set; } + + /// + /// Дата начала периода + /// + public DateTimeOffset? Begin { get; set; } - /// - /// Дата окончания периода - /// - public DateTimeOffset? End { get; set; } + /// + /// Дата окончания периода + /// + public DateTimeOffset? End { get; set; } - /// - /// Признак удаления - /// - public bool? IsDeleted { get; set; } - } + /// + /// Признак удаления + /// + public bool? IsDeleted { get; set; } } diff --git a/AsbCloudApp/Requests/LimitingParameterRequest.cs b/AsbCloudApp/Requests/LimitingParameterRequest.cs index 6bf0b11d..30e136b8 100644 --- a/AsbCloudApp/Requests/LimitingParameterRequest.cs +++ b/AsbCloudApp/Requests/LimitingParameterRequest.cs @@ -1,37 +1,36 @@ using System; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Requests +namespace AsbCloudApp.Requests; + +/// +/// Класс с фильтрами для запроса по ограничивающим параметрам +/// +public class LimitingParameterRequest { /// - /// Класс с фильтрами для запроса по ограничивающим параметрам + /// идентификатор скважины /// - public class LimitingParameterRequest - { - /// - /// идентификатор скважины - /// - [Required] - public int IdWell { get; set; } + [Required] + public int IdWell { get; set; } - /// - /// Больше или равно дате - /// - public DateTimeOffset? GtDate { get; set; } + /// + /// Больше или равно дате + /// + public DateTimeOffset? GtDate { get; set; } - /// - /// Меньше или равно дате - /// - public DateTimeOffset? LtDate { get; set; } + /// + /// Меньше или равно дате + /// + public DateTimeOffset? LtDate { get; set; } - /// - /// Больше или равно глубины забоя - /// - public double? GtDepth { get; set; } + /// + /// Больше или равно глубины забоя + /// + public double? GtDepth { get; set; } - /// - /// Меньше или равно глубины забоя - /// - public double? LtDepth { get; set; } - } + /// + /// Меньше или равно глубины забоя + /// + public double? LtDepth { get; set; } } diff --git a/AsbCloudApp/Requests/MessageRequest.cs b/AsbCloudApp/Requests/MessageRequest.cs index db814e82..1e755231 100644 --- a/AsbCloudApp/Requests/MessageRequest.cs +++ b/AsbCloudApp/Requests/MessageRequest.cs @@ -1,65 +1,64 @@ using System; using System.Collections.Generic; -namespace AsbCloudApp.Requests +namespace AsbCloudApp.Requests; + +/// +/// параметры для запроса списка сообщений +/// +public class MessageRequestBase : RequestBase { /// - /// параметры для запроса списка сообщений + /// категория /// - public class MessageRequestBase : RequestBase - { - /// - /// категория - /// - public IEnumerable? Categoryids { get; set; } + public IEnumerable? Categoryids { get; set; } - /// - /// начальная дата - /// - public DateTimeOffset? Begin { get; set; } + /// + /// начальная дата + /// + public DateTimeOffset? Begin { get; set; } - /// - /// конечная дата - /// - public DateTimeOffset? End { get; set; } + /// + /// конечная дата + /// + public DateTimeOffset? End { get; set; } - /// - /// строка поиска - /// - public string? SearchString { get; set; } + /// + /// строка поиска + /// + public string? SearchString { get; set; } - } +} + +/// +/// параметры для запроса списка сообщений (с id скважины) +/// +public class MessageRequest : MessageRequestBase +{ + + /// + /// id скважины + /// + public int IdWell { get; set; } /// /// параметры для запроса списка сообщений (с id скважины) /// - public class MessageRequest : MessageRequestBase + /// + /// + public MessageRequest(MessageRequestBase request, int idWell) { + this.IdWell = idWell; - /// - /// id скважины - /// - public int IdWell { get; set; } - - /// - /// параметры для запроса списка сообщений (с id скважины) - /// - /// - /// - public MessageRequest(MessageRequestBase request, int idWell) - { - this.IdWell = idWell; - - this.Categoryids = request.Categoryids; - this.Begin = request.Begin; - this.End = request.End; - this.SearchString = request.SearchString; - - this.Skip = request.Skip; - this.Take = request.Take; - this.SortFields = request.SortFields; - } + this.Categoryids = request.Categoryids; + this.Begin = request.Begin; + this.End = request.End; + this.SearchString = request.SearchString; + this.Skip = request.Skip; + this.Take = request.Take; + this.SortFields = request.SortFields; } + } diff --git a/AsbCloudApp/Requests/OperationStatRequest.cs b/AsbCloudApp/Requests/OperationStatRequest.cs index c9a384e3..dd9d5ed4 100644 --- a/AsbCloudApp/Requests/OperationStatRequest.cs +++ b/AsbCloudApp/Requests/OperationStatRequest.cs @@ -1,34 +1,33 @@ using System; -namespace AsbCloudApp.Requests +namespace AsbCloudApp.Requests; + +/// +/// Параметры фильтра операции +/// +public class OperationStatRequest { + //TODO: использовать DateOnly. Поправить naming /// - /// Параметры фильтра операции + /// Дата начала операции в UTC /// - public class OperationStatRequest - { - //TODO: использовать DateOnly. Поправить naming - /// - /// Дата начала операции в UTC - /// - public DateTime? DateStartUTC { get; set; } + public DateTime? DateStartUTC { get; set; } - //TODO: использовать DateOnly. Поправить naming - /// - /// Дата окончания операции в UTC - /// - public DateTime? DateEndUTC { get; set; } + //TODO: использовать DateOnly. Поправить naming + /// + /// Дата окончания операции в UTC + /// + public DateTime? DateEndUTC { get; set; } - //TODO: поправить naming - /// - /// Минимальная продолжительность операции, мин - /// - public double? DurationMinutesMin { get; set; } + //TODO: поправить naming + /// + /// Минимальная продолжительность операции, мин + /// + public double? DurationMinutesMin { get; set; } - //TODO: поправить naming - /// - /// Максимальная продолжительность операции, мин - /// - public double? DurationMinutesMax { get; set; } - } + //TODO: поправить naming + /// + /// Максимальная продолжительность операции, мин + /// + public double? DurationMinutesMax { get; set; } } diff --git a/AsbCloudApp/Requests/RequestBase.cs b/AsbCloudApp/Requests/RequestBase.cs index 3f045fd5..e187ba8d 100644 --- a/AsbCloudApp/Requests/RequestBase.cs +++ b/AsbCloudApp/Requests/RequestBase.cs @@ -1,45 +1,44 @@ using System.Collections.Generic; -namespace AsbCloudApp.Requests +namespace AsbCloudApp.Requests; + +/// +/// Базовые параметры запроса +/// +public class RequestBase { + /// + /// Параметр пагинации + /// + public int? Skip { get; set; } + + /// + /// Параметр пагинации + /// + public int? Take { get; set; } + + /// + /// Сортировки: + /// Содержат список названий полей сортировки + /// Указать направление сортировки можно через пробел "asc" или "desc" + /// + public IEnumerable? SortFields { get; set; } + /// /// Базовые параметры запроса /// - public class RequestBase + public RequestBase() { - /// - /// Параметр пагинации - /// - public int? Skip { get; set; } + } - /// - /// Параметр пагинации - /// - public int? Take { get; set; } - - /// - /// Сортировки: - /// Содержат список названий полей сортировки - /// Указать направление сортировки можно через пробел "asc" или "desc" - /// - public IEnumerable? SortFields { get; set; } - - /// - /// Базовые параметры запроса - /// - public RequestBase() - { - } - - /// - /// Базовые параметры запроса. Копирующий конструктор - /// - /// - public RequestBase(RequestBase request) - { - Skip = request.Skip; - Take = request.Take; - SortFields = request.SortFields; - } + /// + /// Базовые параметры запроса. Копирующий конструктор + /// + /// + public RequestBase(RequestBase request) + { + Skip = request.Skip; + Take = request.Take; + SortFields = request.SortFields; } } diff --git a/AsbCloudApp/Requests/SubsystemRequest.cs b/AsbCloudApp/Requests/SubsystemRequest.cs index f427dcec..4c5705d6 100644 --- a/AsbCloudApp/Requests/SubsystemRequest.cs +++ b/AsbCloudApp/Requests/SubsystemRequest.cs @@ -2,71 +2,70 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Requests +namespace AsbCloudApp.Requests; + +/// +/// класс с фильтрами для запроса +/// +public class SubsystemRequest: RequestBase, IValidatableObject { + private static readonly DateTimeOffset validationMinDate = new DateTimeOffset(2020,01,01,0,0,0, TimeSpan.Zero); + /// - /// класс с фильтрами для запроса + /// идентификатор скважины /// - public class SubsystemRequest: RequestBase, IValidatableObject + [Required] + public int IdWell { get; set; } + + /// + /// Идентификатор бурильщика + /// + public int? IdDriller { get; set; } + + /// + /// Больше или равно дате + /// + public DateTimeOffset? GeDate { get; set; } + + /// + /// Меньше или равно дате + /// + public DateTimeOffset? LeDate { get; set; } + + /// + /// Больше или равно глубины забоя + /// + public double? GeDepth { get; set; } + + /// + /// Меньше или равно глубины забоя + /// + public double? LeDepth { get; set; } + + /// + public IEnumerable Validate(ValidationContext validationContext) { - private static readonly DateTimeOffset validationMinDate = new DateTimeOffset(2020,01,01,0,0,0, TimeSpan.Zero); + if (GeDate.HasValue && GeDate < validationMinDate) + yield return new ValidationResult( + $"Должно быть больше {validationMinDate:O})", + new[] { nameof(GeDate) }); - /// - /// идентификатор скважины - /// - [Required] - public int IdWell { get; set; } - - /// - /// Идентификатор бурильщика - /// - public int? IdDriller { get; set; } - - /// - /// Больше или равно дате - /// - public DateTimeOffset? GeDate { get; set; } - - /// - /// Меньше или равно дате - /// - public DateTimeOffset? LeDate { get; set; } - - /// - /// Больше или равно глубины забоя - /// - public double? GeDepth { get; set; } - - /// - /// Меньше или равно глубины забоя - /// - public double? LeDepth { get; set; } - - /// - public IEnumerable Validate(ValidationContext validationContext) + if (LeDate.HasValue && GeDate.HasValue) { - if (GeDate.HasValue && GeDate < validationMinDate) + if (LeDate < GeDate) yield return new ValidationResult( - $"Должно быть больше {validationMinDate:O})", - new[] { nameof(GeDate) }); - - if (LeDate.HasValue && GeDate.HasValue) - { - if (LeDate < GeDate) - yield return new ValidationResult( - $"{nameof(LeDate)} должно быть больше {nameof(GeDate)}. ({LeDate:O} < {GeDate:O})", - new[] { nameof(LeDate), nameof(GeDate) }); - } - - if (LeDepth.HasValue && GeDepth.HasValue) - { - if (LeDepth < GeDepth) - yield return new ValidationResult( - $"{nameof(LeDepth)} должно быть больше {nameof(GeDepth)}. ({LeDepth} < {GeDepth})", - new[] { nameof(LeDepth), nameof(GeDepth) }); - } - - yield break; + $"{nameof(LeDate)} должно быть больше {nameof(GeDate)}. ({LeDate:O} < {GeDate:O})", + new[] { nameof(LeDate), nameof(GeDate) }); } + + if (LeDepth.HasValue && GeDepth.HasValue) + { + if (LeDepth < GeDepth) + yield return new ValidationResult( + $"{nameof(LeDepth)} должно быть больше {nameof(GeDepth)}. ({LeDepth} < {GeDepth})", + new[] { nameof(LeDepth), nameof(GeDepth) }); + } + + yield break; } } diff --git a/AsbCloudApp/Requests/WellContactRequest.cs b/AsbCloudApp/Requests/WellContactRequest.cs index 26fd4f1b..e49917bf 100644 --- a/AsbCloudApp/Requests/WellContactRequest.cs +++ b/AsbCloudApp/Requests/WellContactRequest.cs @@ -1,20 +1,19 @@ using System.Collections.Generic; -namespace AsbCloudApp.Requests +namespace AsbCloudApp.Requests; + +/// +/// Запрос на получение контактов +/// +public class WellContactRequest { /// - /// Запрос на получение контактов + /// Идентификаторы скважин /// - public class WellContactRequest - { - /// - /// Идентификаторы скважин - /// - public IEnumerable IdsWells { get; set; } = null!; + public IEnumerable IdsWells { get; set; } = null!; - /// - /// Ключ типа контактов - /// - public int? ContactTypeId { get; set; } - } + /// + /// Ключ типа контактов + /// + public int? ContactTypeId { get; set; } } diff --git a/AsbCloudApp/Requests/WellRequest.cs b/AsbCloudApp/Requests/WellRequest.cs index 8be9dee8..c3edb9b0 100644 --- a/AsbCloudApp/Requests/WellRequest.cs +++ b/AsbCloudApp/Requests/WellRequest.cs @@ -1,25 +1,24 @@ using System.Collections.Generic; -namespace AsbCloudApp.Requests +namespace AsbCloudApp.Requests; + +/// +/// Запрос на получение скважин +/// +public class WellRequest { /// - /// Запрос на получение скважин + /// id компании /// - public class WellRequest - { - /// - /// id компании - /// - public int? IdCompany { get; set; } + public int? IdCompany { get; set; } - /// - /// id состояния - /// - public int? IdState { get; set; } + /// + /// id состояния + /// + public int? IdState { get; set; } - /// - /// Идентификаторы скважин - /// - public IEnumerable? Ids { get; set; } - } + /// + /// Идентификаторы скважин + /// + public IEnumerable? Ids { get; set; } } diff --git a/AsbCloudApp/Services/FileService.cs b/AsbCloudApp/Services/FileService.cs index 6065d310..3e27e92b 100644 --- a/AsbCloudApp/Services/FileService.cs +++ b/AsbCloudApp/Services/FileService.cs @@ -7,295 +7,294 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Сервис доступа к файлам +/// +public class FileService { + private readonly IFileRepository fileRepository; + private readonly IFileStorageRepository fileStorageRepository; + /// /// Сервис доступа к файлам /// - public class FileService + /// + /// + public FileService(IFileRepository fileRepository, IFileStorageRepository fileStorageRepository) { - private readonly IFileRepository fileRepository; - private readonly IFileStorageRepository fileStorageRepository; + this.fileRepository = fileRepository; + this.fileStorageRepository = fileStorageRepository; + } - /// - /// Сервис доступа к файлам - /// - /// - /// - public FileService(IFileRepository fileRepository, IFileStorageRepository fileStorageRepository) + /// + /// переместить файл + /// + /// + /// + /// + /// + /// + /// + /// + public async Task MoveAsync(int idWell, int? idUser, int idCategory, + string destinationFileName, string srcFilePath, CancellationToken token = default) + { + destinationFileName = Path.GetFileName(destinationFileName); + srcFilePath = Path.GetFullPath(srcFilePath); + var fileSize = fileStorageRepository.GetFileLength(srcFilePath); + + //save info to db + var dto = new FileInfoDto { + IdWell = idWell, + IdAuthor = idUser, + IdCategory = idCategory, + Name = destinationFileName, + Size = fileSize + }; + var fileId = await fileRepository.InsertAsync(dto, token) + .ConfigureAwait(false); + + string filePath = fileStorageRepository.MakeFilePath(idWell, idCategory, destinationFileName, fileId); + fileStorageRepository.MoveFile(srcFilePath, filePath); + + return await GetOrDefaultAsync(fileId, token); + } + + /// + /// Сохранить файл + /// + /// + /// + /// + /// + /// + /// + /// + public async Task SaveAsync(int idWell, int? idUser, int idCategory, + string fileFullName, Stream fileStream, CancellationToken token) + { + //save info to db + var dto = new FileInfoDto { - this.fileRepository = fileRepository; - this.fileStorageRepository = fileStorageRepository; - } + IdWell = idWell, + IdAuthor = idUser, + IdCategory = idCategory, + Name = Path.GetFileName(fileFullName), + Size = fileStream.Length + }; - /// - /// переместить файл - /// - /// - /// - /// - /// - /// - /// - /// - public async Task MoveAsync(int idWell, int? idUser, int idCategory, - string destinationFileName, string srcFilePath, CancellationToken token = default) - { - destinationFileName = Path.GetFileName(destinationFileName); - srcFilePath = Path.GetFullPath(srcFilePath); - var fileSize = fileStorageRepository.GetFileLength(srcFilePath); + var fileId = await fileRepository.InsertAsync(dto, token) + .ConfigureAwait(false); - //save info to db - var dto = new FileInfoDto { - IdWell = idWell, - IdAuthor = idUser, - IdCategory = idCategory, - Name = destinationFileName, - Size = fileSize - }; - var fileId = await fileRepository.InsertAsync(dto, token) - .ConfigureAwait(false); - - string filePath = fileStorageRepository.MakeFilePath(idWell, idCategory, destinationFileName, fileId); - fileStorageRepository.MoveFile(srcFilePath, filePath); - - return await GetOrDefaultAsync(fileId, token); - } + //save stream to disk + string filePath = fileStorageRepository.MakeFilePath(idWell, idCategory, fileFullName, fileId); + await fileStorageRepository.SaveFileAsync(filePath, fileStream, token); - /// - /// Сохранить файл - /// - /// - /// - /// - /// - /// - /// - /// - public async Task SaveAsync(int idWell, int? idUser, int idCategory, - string fileFullName, Stream fileStream, CancellationToken token) - { - //save info to db - var dto = new FileInfoDto + return (await GetOrDefaultAsync(fileId, token))!; + } + + /// + /// удалить файл + /// + /// + /// + /// + public Task DeleteAsync(int idFile, CancellationToken token) + => DeleteAsync(new int[] { idFile }, token); + + /// + /// удалить файлы + /// + /// + /// + /// + public async Task DeleteAsync(IEnumerable ids, CancellationToken token) + { + if (ids is null || !ids.Any()) + return 0; + + var files = await fileRepository.DeleteAsync(ids, token).ConfigureAwait(false); + + if (files is null || !files.Any()) + return 0; + + var filesName = files.Select(x => GetUrl(x.IdWell, x.IdCategory, x.Id, Path.GetExtension(x.Name))); + fileStorageRepository.DeleteFiles(filesName); + + return files.Any() ? 1 : 0; + } + + /// + /// получить путь для скачивания + /// + /// + /// + public string GetUrl(FileInfoDto fileInfo) => + GetUrl(fileInfo.IdWell, fileInfo.IdCategory, fileInfo.Id, Path.GetExtension(fileInfo.Name)); + + /// + /// получить путь для скачивания + /// + /// + /// + /// + /// + /// + public string GetUrl(int idWell, int idCategory, int idFile, string dotExtention) => + fileStorageRepository.GetFilePath(idWell, idCategory, idFile, dotExtention); + + /// + /// пометить метку файла как удаленную + /// + /// + /// + /// + public Task MarkFileMarkAsDeletedAsync(int idMark, + CancellationToken token) + => fileRepository.MarkFileMarkAsDeletedAsync(new int[] { idMark }, token); + + /// + /// Инфо о файле + /// + /// + /// + /// + public async Task> GetInfoByIdsAsync(IEnumerable idsFile, CancellationToken token) + { + var result = await fileRepository.GetInfoByIdsAsync(idsFile, token).ConfigureAwait(false); + return result; + } + + /// + /// Получить файлы определенной категории + /// + /// + /// + /// + public Task> GetInfosAsync(FileRequest request, CancellationToken token) + => fileRepository.GetInfosAsync(request, token); + + /// + /// Получить список файлов в контейнере + /// + /// + /// + /// + public Task> GetInfosPaginatedAsync(FileRequest request, CancellationToken token) + => fileRepository.GetInfosPaginatedAsync(request, token); + + /// + /// Пометить файл как удаленный + /// + /// + /// + /// + public Task MarkAsDeletedAsync(int idFile, CancellationToken token = default) + => fileRepository.MarkAsDeletedAsync(idFile, token); + + /// + /// добавить метку на файл + /// + /// + /// + /// + /// + public Task CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token) + => fileRepository.CreateFileMarkAsync(fileMarkDto, idUser, token); + + /// + /// Получить запись по id + /// + /// + /// + /// + public Task GetOrDefaultAsync(int id, CancellationToken token) + => fileRepository.GetOrDefaultAsync(id, token); + + /// + /// получить инфо о файле по метке + /// + /// + /// + /// + public Task GetByMarkId(int idMark, CancellationToken token) + => fileRepository.GetByMarkId(idMark, token); + + /// + /// получить инфо о файле по метке + /// + /// + /// + /// + public Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token) + => fileRepository.MarkFileMarkAsDeletedAsync(idsMarks, token); + + /// + /// Удаление всех файлов по скважине помеченных как удаленные + /// + /// + /// + /// + public async Task DeleteFilesFromDbMarkedDeletionByIdWell(int idWell, CancellationToken token) + { + var files = await fileRepository.GetInfosAsync( + new FileRequest { IdWell = idWell, - IdAuthor = idUser, - IdCategory = idCategory, - Name = Path.GetFileName(fileFullName), - Size = fileStream.Length - }; + IsDeleted = true + }, + token); + var result = await DeleteAsync(files.Select(x => x.Id), token); + return result; + } - var fileId = await fileRepository.InsertAsync(dto, token) - .ConfigureAwait(false); + /// + /// Удаление всех файлов с диска о которых нет информации в базе + /// + /// + /// + public async Task DeleteFilesNotExistStorage(int idWell, CancellationToken token) + { + var files = await fileRepository.GetInfosAsync( + new FileRequest + { + IdWell = idWell + }, + token); + var result = await Task.FromResult(fileStorageRepository.DeleteFilesNotInList(idWell, files.Select(x => x.Id))); + return result; + } - //save stream to disk - string filePath = fileStorageRepository.MakeFilePath(idWell, idCategory, fileFullName, fileId); - await fileStorageRepository.SaveFileAsync(filePath, fileStream, token); + /// + /// Вывод списка всех файлов из базы, для которых нет файла на диске + /// + /// + /// + /// + public async Task> GetListFilesNotDisc(int idWell, CancellationToken token) + { + var files = await fileRepository.GetInfosAsync( + new FileRequest + { + IdWell = idWell + }, + token); + var result = fileStorageRepository.GetListFilesNotDisc(files); + return result; + } - return (await GetOrDefaultAsync(fileId, token))!; - } + /// + /// Получить файловый поток по идентификатору файла + /// + /// + /// + public Stream GetFileStream(FileInfoDto fileInfo) + { + var relativePath = GetUrl(fileInfo); + var fileStream = new FileStream(Path.GetFullPath(relativePath), FileMode.Open); - /// - /// удалить файл - /// - /// - /// - /// - public Task DeleteAsync(int idFile, CancellationToken token) - => DeleteAsync(new int[] { idFile }, token); - - /// - /// удалить файлы - /// - /// - /// - /// - public async Task DeleteAsync(IEnumerable ids, CancellationToken token) - { - if (ids is null || !ids.Any()) - return 0; - - var files = await fileRepository.DeleteAsync(ids, token).ConfigureAwait(false); - - if (files is null || !files.Any()) - return 0; - - var filesName = files.Select(x => GetUrl(x.IdWell, x.IdCategory, x.Id, Path.GetExtension(x.Name))); - fileStorageRepository.DeleteFiles(filesName); - - return files.Any() ? 1 : 0; - } - - /// - /// получить путь для скачивания - /// - /// - /// - public string GetUrl(FileInfoDto fileInfo) => - GetUrl(fileInfo.IdWell, fileInfo.IdCategory, fileInfo.Id, Path.GetExtension(fileInfo.Name)); - - /// - /// получить путь для скачивания - /// - /// - /// - /// - /// - /// - public string GetUrl(int idWell, int idCategory, int idFile, string dotExtention) => - fileStorageRepository.GetFilePath(idWell, idCategory, idFile, dotExtention); - - /// - /// пометить метку файла как удаленную - /// - /// - /// - /// - public Task MarkFileMarkAsDeletedAsync(int idMark, - CancellationToken token) - => fileRepository.MarkFileMarkAsDeletedAsync(new int[] { idMark }, token); - - /// - /// Инфо о файле - /// - /// - /// - /// - public async Task> GetInfoByIdsAsync(IEnumerable idsFile, CancellationToken token) - { - var result = await fileRepository.GetInfoByIdsAsync(idsFile, token).ConfigureAwait(false); - return result; - } - - /// - /// Получить файлы определенной категории - /// - /// - /// - /// - public Task> GetInfosAsync(FileRequest request, CancellationToken token) - => fileRepository.GetInfosAsync(request, token); - - /// - /// Получить список файлов в контейнере - /// - /// - /// - /// - public Task> GetInfosPaginatedAsync(FileRequest request, CancellationToken token) - => fileRepository.GetInfosPaginatedAsync(request, token); - - /// - /// Пометить файл как удаленный - /// - /// - /// - /// - public Task MarkAsDeletedAsync(int idFile, CancellationToken token = default) - => fileRepository.MarkAsDeletedAsync(idFile, token); - - /// - /// добавить метку на файл - /// - /// - /// - /// - /// - public Task CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token) - => fileRepository.CreateFileMarkAsync(fileMarkDto, idUser, token); - - /// - /// Получить запись по id - /// - /// - /// - /// - public Task GetOrDefaultAsync(int id, CancellationToken token) - => fileRepository.GetOrDefaultAsync(id, token); - - /// - /// получить инфо о файле по метке - /// - /// - /// - /// - public Task GetByMarkId(int idMark, CancellationToken token) - => fileRepository.GetByMarkId(idMark, token); - - /// - /// получить инфо о файле по метке - /// - /// - /// - /// - public Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token) - => fileRepository.MarkFileMarkAsDeletedAsync(idsMarks, token); - - /// - /// Удаление всех файлов по скважине помеченных как удаленные - /// - /// - /// - /// - public async Task DeleteFilesFromDbMarkedDeletionByIdWell(int idWell, CancellationToken token) - { - var files = await fileRepository.GetInfosAsync( - new FileRequest - { - IdWell = idWell, - IsDeleted = true - }, - token); - var result = await DeleteAsync(files.Select(x => x.Id), token); - return result; - } - - /// - /// Удаление всех файлов с диска о которых нет информации в базе - /// - /// - /// - public async Task DeleteFilesNotExistStorage(int idWell, CancellationToken token) - { - var files = await fileRepository.GetInfosAsync( - new FileRequest - { - IdWell = idWell - }, - token); - var result = await Task.FromResult(fileStorageRepository.DeleteFilesNotInList(idWell, files.Select(x => x.Id))); - return result; - } - - /// - /// Вывод списка всех файлов из базы, для которых нет файла на диске - /// - /// - /// - /// - public async Task> GetListFilesNotDisc(int idWell, CancellationToken token) - { - var files = await fileRepository.GetInfosAsync( - new FileRequest - { - IdWell = idWell - }, - token); - var result = fileStorageRepository.GetListFilesNotDisc(files); - return result; - } - - /// - /// Получить файловый поток по идентификатору файла - /// - /// - /// - public Stream GetFileStream(FileInfoDto fileInfo) - { - var relativePath = GetUrl(fileInfo); - var fileStream = new FileStream(Path.GetFullPath(relativePath), FileMode.Open); - - return fileStream; - } + return fileStream; } } diff --git a/AsbCloudApp/Services/IAuthService.cs b/AsbCloudApp/Services/IAuthService.cs index ac470f73..9eb9eac6 100644 --- a/AsbCloudApp/Services/IAuthService.cs +++ b/AsbCloudApp/Services/IAuthService.cs @@ -3,53 +3,52 @@ using System.Security.Claims; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Сервис авторизации +/// +public interface IAuthService { /// - /// Сервис авторизации + /// Смена пароля пользователю /// - public interface IAuthService - { - /// - /// Смена пароля пользователю - /// - /// - /// - /// - void ChangePassword(int idUser, string newPassword); + /// + /// + /// + void ChangePassword(int idUser, string newPassword); - /// - /// Смена пароля пользователю - /// - /// - /// - /// - void ChangePassword(string userLogin, string newPassword); + /// + /// Смена пароля пользователю + /// + /// + /// + /// + void ChangePassword(string userLogin, string newPassword); - /// - /// Авторизация - /// - /// - /// - /// токен отмены задачи - /// - Task LoginAsync(string login, - string password, CancellationToken token = default); + /// + /// Авторизация + /// + /// + /// + /// токен отмены задачи + /// + Task LoginAsync(string login, + string password, CancellationToken token = default); - /// - /// Обновление токена авторизации - /// - /// - /// - /// - Task RefreshAsync(ClaimsPrincipal identity, - CancellationToken token); + /// + /// Обновление токена авторизации + /// + /// + /// + /// + Task RefreshAsync(ClaimsPrincipal identity, + CancellationToken token); - /// - /// Регистрация нового пользователя - /// - /// - /// - void Register(UserRegistrationDto userDto); - } + /// + /// Регистрация нового пользователя + /// + /// + /// + void Register(UserRegistrationDto userDto); } \ No newline at end of file diff --git a/AsbCloudApp/Services/ICrudRepository.cs b/AsbCloudApp/Services/ICrudRepository.cs index b4ab2459..df581326 100644 --- a/AsbCloudApp/Services/ICrudRepository.cs +++ b/AsbCloudApp/Services/ICrudRepository.cs @@ -2,73 +2,72 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Сервис получения, добавления, изменения, удаления данных +/// +/// +public interface ICrudRepository + where TDto : Data.IId { /// - /// Сервис получения, добавления, изменения, удаления данных + /// Код возврата ошибки: Id не найден в БД. /// - /// - public interface ICrudRepository - where TDto : Data.IId - { - /// - /// Код возврата ошибки: Id не найден в БД. - /// - public const int ErrorIdNotFound = -1; + public const int ErrorIdNotFound = -1; - /// - /// Получение всех записей - /// - /// - /// emptyList if nothing found - Task> GetAllAsync(CancellationToken token); + /// + /// Получение всех записей + /// + /// + /// emptyList if nothing found + Task> GetAllAsync(CancellationToken token); - /// - /// Получить запись по id - /// - /// - /// - /// null if not found - Task GetOrDefaultAsync(int id, CancellationToken token); + /// + /// Получить запись по id + /// + /// + /// + /// null if not found + Task GetOrDefaultAsync(int id, CancellationToken token); - /// - /// Получить запись по id - /// - /// - /// null if not found - TDto? GetOrDefault(int id); + /// + /// Получить запись по id + /// + /// + /// null if not found + TDto? GetOrDefault(int id); - /// - /// Добавление новой записи - /// - /// - /// - /// Id новой записи - Task InsertAsync(TDto newItem, CancellationToken token); + /// + /// Добавление новой записи + /// + /// + /// + /// Id новой записи + Task InsertAsync(TDto newItem, CancellationToken token); - /// - /// Добавление нескольких записей - /// - /// - /// - /// количество добавленных - Task InsertRangeAsync(IEnumerable newItems, CancellationToken token); + /// + /// Добавление нескольких записей + /// + /// + /// + /// количество добавленных + Task InsertRangeAsync(IEnumerable newItems, CancellationToken token); - /// - /// Отредактировать запись - /// - /// - /// - /// если больше 0 - Id записи, если меньше 0 - код ошибки - Task UpdateAsync(TDto item, CancellationToken token); + /// + /// Отредактировать запись + /// + /// + /// + /// если больше 0 - Id записи, если меньше 0 - код ошибки + Task UpdateAsync(TDto item, CancellationToken token); - /// - /// Удалить запись - /// - /// - /// - /// количество добавленных, если меньше 0 - код ошибки - Task DeleteAsync(int id, CancellationToken token); - } + /// + /// Удалить запись + /// + /// + /// + /// количество добавленных, если меньше 0 - код ошибки + Task DeleteAsync(int id, CancellationToken token); } \ No newline at end of file diff --git a/AsbCloudApp/Services/IDataSaubStatService.cs b/AsbCloudApp/Services/IDataSaubStatService.cs index f72d4480..66088d31 100644 --- a/AsbCloudApp/Services/IDataSaubStatService.cs +++ b/AsbCloudApp/Services/IDataSaubStatService.cs @@ -2,23 +2,22 @@ using System; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Сервис записи данных в таблицу DataSaubStat, которая используется для построения РТК-отчета +/// +public interface IDataSaubStatService { /// - /// Сервис записи данных в таблицу DataSaubStat, которая используется для построения РТК-отчета + /// Расчет статистики DataSaubStat /// - public interface IDataSaubStatService - { - /// - /// Расчет статистики DataSaubStat - /// - /// - /// Количество дней за которые должны были приходить данные, чтобы телеметрия попала в обработку. - /// - /// - /// - /// - Task CreateStatAsync(int lastDaysFilter, Action onProgressCallback, CancellationToken token); + /// + /// Количество дней за которые должны были приходить данные, чтобы телеметрия попала в обработку. + /// + /// + /// + /// + Task CreateStatAsync(int lastDaysFilter, Action onProgressCallback, CancellationToken token); - } } diff --git a/AsbCloudApp/Services/IDrillParamsService.cs b/AsbCloudApp/Services/IDrillParamsService.cs index c40ecf59..797f4d66 100644 --- a/AsbCloudApp/Services/IDrillParamsService.cs +++ b/AsbCloudApp/Services/IDrillParamsService.cs @@ -3,80 +3,79 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// The параметры бурения service. +/// +public interface IDrillParamsService : ICrudRepository { /// - /// The параметры бурения service. + /// default параметры бурения /// - public interface IDrillParamsService : ICrudRepository - { - /// - /// default параметры бурения - /// - /// The id well. - /// The start depth. - /// The end depth. - /// The token. - /// A Task. - Task GetDefaultDrillParamsAsync(int idWell, double startDepth, - double endDepth, CancellationToken token = default); + /// The id well. + /// The start depth. + /// The end depth. + /// The token. + /// A Task. + Task GetDefaultDrillParamsAsync(int idWell, double startDepth, + double endDepth, CancellationToken token = default); - /// - /// Все за скважину - /// - /// The id well. - /// The token. - /// A Task. - Task> GetAllAsync(int idWell, - CancellationToken token = default); + /// + /// Все за скважину + /// + /// The id well. + /// The token. + /// A Task. + Task> GetAllAsync(int idWell, + CancellationToken token = default); - /// - /// Все скважину по композитной скважине - /// - /// The id well. - /// The token. - /// A Task. - Task> GetCompositeAllAsync(int idWell, - CancellationToken token = default); + /// + /// Все скважину по композитной скважине + /// + /// The id well. + /// The token. + /// A Task. + Task> GetCompositeAllAsync(int idWell, + CancellationToken token = default); - /// - /// Добавить - /// - /// The id well. - /// The dto. - /// The token. - /// A Task. - Task InsertAsync(int idWell, DrillParamsDto dto, - CancellationToken token = default); + /// + /// Добавить + /// + /// The id well. + /// The dto. + /// The token. + /// A Task. + Task InsertAsync(int idWell, DrillParamsDto dto, + CancellationToken token = default); - /// - /// Добавить несколько - /// - /// The id well. - /// The dtos. - /// The token. - /// A Task. - Task InsertRangeAsync(int idWell, IEnumerable dtos, - CancellationToken token = default); + /// + /// Добавить несколько + /// + /// The id well. + /// The dtos. + /// The token. + /// A Task. + Task InsertRangeAsync(int idWell, IEnumerable dtos, + CancellationToken token = default); - /// - /// Редактировать - /// - /// The id well. - /// The dto id. - /// The dto. - /// The token. - /// A Task. - Task UpdateAsync(int idWell, int dtoId, DrillParamsDto dto, - CancellationToken token = default); + /// + /// Редактировать + /// + /// The id well. + /// The dto id. + /// The dto. + /// The token. + /// A Task. + Task UpdateAsync(int idWell, int dtoId, DrillParamsDto dto, + CancellationToken token = default); - /// - /// Удалить старые и сохранить новые - /// - /// The id well. - /// The dtos. - /// The token. - /// A Task. - Task SaveAsync(int idWell, IEnumerable dtos, CancellationToken token = default); - } + /// + /// Удалить старые и сохранить новые + /// + /// The id well. + /// The dtos. + /// The token. + /// A Task. + Task SaveAsync(int idWell, IEnumerable dtos, CancellationToken token = default); } diff --git a/AsbCloudApp/Services/IDrillTestReportService.cs b/AsbCloudApp/Services/IDrillTestReportService.cs index f13f0aa2..1773beb0 100644 --- a/AsbCloudApp/Services/IDrillTestReportService.cs +++ b/AsbCloudApp/Services/IDrillTestReportService.cs @@ -5,31 +5,30 @@ using System.IO; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// сервис по работе с отчетами drill test +/// +public interface IDrillTestReportService { /// - /// сервис по работе с отчетами drill test + /// Список файлов drill test /// - public interface IDrillTestReportService - { - /// - /// Список файлов drill test - /// - /// ключ скважины - /// параметры запроса - /// - /// - Task> GetListAsync(int idWell, - FileReportRequest request, - CancellationToken cancellationToken); + /// ключ скважины + /// параметры запроса + /// + /// + Task> GetListAsync(int idWell, + FileReportRequest request, + CancellationToken cancellationToken); - /// - /// Генерация файла с отчётом - /// - /// ключ скважины - /// ключ drill test записи - /// - /// - Task<(string fileName, Stream stream)> GenerateAsync(int idWell, int id, CancellationToken cancellationToken); - } + /// + /// Генерация файла с отчётом + /// + /// ключ скважины + /// ключ drill test записи + /// + /// + Task<(string fileName, Stream stream)> GenerateAsync(int idWell, int id, CancellationToken cancellationToken); } diff --git a/AsbCloudApp/Services/IDrillingProgramService.cs b/AsbCloudApp/Services/IDrillingProgramService.cs index f8742ac5..84f58558 100644 --- a/AsbCloudApp/Services/IDrillingProgramService.cs +++ b/AsbCloudApp/Services/IDrillingProgramService.cs @@ -4,111 +4,110 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Программа бурения +/// +public interface IDrillingProgramService { /// - /// Программа бурения + /// Получить пользователей доступных для назначения в публикаторы или акцепторы /// - public interface IDrillingProgramService - { - /// - /// Получить пользователей доступных для назначения в публикаторы или акцепторы - /// - /// - /// - /// - Task> GetAvailableUsers(int idWell, CancellationToken token = default); + /// + /// + /// + Task> GetAvailableUsers(int idWell, CancellationToken token = default); - /// - /// Части программы бурения - /// - /// - /// - Task> GetCategoriesAsync(CancellationToken token = default); + /// + /// Части программы бурения + /// + /// + /// + Task> GetCategoriesAsync(CancellationToken token = default); - /// - /// Состояние программы бурения - /// - /// - /// - /// - /// - Task GetStateAsync(int idWell, int idUser, - CancellationToken token = default); + /// + /// Состояние программы бурения + /// + /// + /// + /// + /// + Task GetStateAsync(int idWell, int idUser, + CancellationToken token = default); - /// - /// Загрузить файл - /// - /// - /// - /// - /// - /// - /// - /// - Task AddFile(int idWell, int idFileCategory, int idUser, string fileFullName, System.IO.Stream fileStream, CancellationToken token = default); - - /// - /// Добавить часть программы бурения - /// - /// - /// - /// - /// - Task AddPartsAsync(int idWell, IEnumerable idFileCategories, CancellationToken token = default); + /// + /// Загрузить файл + /// + /// + /// + /// + /// + /// + /// + /// + Task AddFile(int idWell, int idFileCategory, int idUser, string fileFullName, System.IO.Stream fileStream, CancellationToken token = default); + + /// + /// Добавить часть программы бурения + /// + /// + /// + /// + /// + Task AddPartsAsync(int idWell, IEnumerable idFileCategories, CancellationToken token = default); - /// - /// Удалить часть программы бурения - /// - /// - /// - /// - /// - Task RemovePartsAsync(int idWell, IEnumerable idFileCategories, CancellationToken token = default); - - /// - /// Назначить пользователю роль - /// - /// - /// - /// - /// - /// - /// - Task AddUserAsync(int idWell, int idFileCategory, int idUser, int idUserRole, CancellationToken token = default); + /// + /// Удалить часть программы бурения + /// + /// + /// + /// + /// + Task RemovePartsAsync(int idWell, IEnumerable idFileCategories, CancellationToken token = default); + + /// + /// Назначить пользователю роль + /// + /// + /// + /// + /// + /// + /// + Task AddUserAsync(int idWell, int idFileCategory, int idUser, int idUserRole, CancellationToken token = default); - /// - /// Удалить пользователя - /// - /// - /// - /// - /// - /// - /// - Task RemoveUserAsync(int idWell, int idFileCategory, int idUser, int idUserRole, CancellationToken token = default); + /// + /// Удалить пользователя + /// + /// + /// + /// + /// + /// + /// + Task RemoveUserAsync(int idWell, int idFileCategory, int idUser, int idUserRole, CancellationToken token = default); - /// - /// Добавить или изменить отметку для файла (согласование/отклонение) - /// - /// - /// - /// - /// - Task AddOrReplaceFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token); + /// + /// Добавить или изменить отметку для файла (согласование/отклонение) + /// + /// + /// + /// + /// + Task AddOrReplaceFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token); - /// - /// Удалить отметку с файла - /// - /// - /// - /// - Task MarkAsDeletedFileMarkAsync(int idFileMark, CancellationToken token); + /// + /// Удалить отметку с файла + /// + /// + /// + /// + Task MarkAsDeletedFileMarkAsync(int idFileMark, CancellationToken token); - /// - /// Сбросить ошибку формирования - /// - /// - void ClearError(int idWell); - } + /// + /// Сбросить ошибку формирования + /// + /// + void ClearError(int idWell); } \ No newline at end of file diff --git a/AsbCloudApp/Services/IEventService.cs b/AsbCloudApp/Services/IEventService.cs index 8efb1b2c..a376b649 100644 --- a/AsbCloudApp/Services/IEventService.cs +++ b/AsbCloudApp/Services/IEventService.cs @@ -3,21 +3,20 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Сервис сохранения списка сообщений от панелей +/// +public interface IEventService { /// - /// Сервис сохранения списка сообщений от панелей + /// Сохранить. Добавить или заменить. /// - public interface IEventService - { - /// - /// Сохранить. Добавить или заменить. - /// - /// - /// - /// - /// - Task UpsertAsync(string uid, IEnumerable dtos, - CancellationToken token = default); - } + /// + /// + /// + /// + Task UpsertAsync(string uid, IEnumerable dtos, + CancellationToken token = default); } diff --git a/AsbCloudApp/Services/IFileCategoryService.cs b/AsbCloudApp/Services/IFileCategoryService.cs index bc00acea..66e0aa00 100644 --- a/AsbCloudApp/Services/IFileCategoryService.cs +++ b/AsbCloudApp/Services/IFileCategoryService.cs @@ -3,25 +3,24 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Сервис "Категории документов (файлов)" +/// +public interface IFileCategoryService { /// - /// Сервис "Категории документов (файлов)" + /// Получить категории файлов /// - public interface IFileCategoryService - { - /// - /// Получить категории файлов - /// - /// - /// - /// - Task GetOrDefaultAsync(int id, CancellationToken token); + /// + /// + /// + Task GetOrDefaultAsync(int id, CancellationToken token); - /// - /// Получение справочника категорий файлов - /// - /// - Task> GetWellCaseCategoriesAsync(CancellationToken token); - } + /// + /// Получение справочника категорий файлов + /// + /// + Task> GetWellCaseCategoriesAsync(CancellationToken token); } diff --git a/AsbCloudApp/Services/ILimitingParameterService.cs b/AsbCloudApp/Services/ILimitingParameterService.cs index 1424e392..df32e532 100644 --- a/AsbCloudApp/Services/ILimitingParameterService.cs +++ b/AsbCloudApp/Services/ILimitingParameterService.cs @@ -4,25 +4,24 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Сервис по ограничивающим параметрам с фильтрацией +/// +public interface ILimitingParameterService { /// - /// Сервис по ограничивающим параметрам с фильтрацией + /// Получение статистики по ограничивающим параметрам /// - public interface ILimitingParameterService - { - /// - /// Получение статистики по ограничивающим параметрам - /// - /// - /// - /// - Task> GetStatAsync(LimitingParameterRequest request, CancellationToken token); + /// + /// + /// + Task> GetStatAsync(LimitingParameterRequest request, CancellationToken token); - /// - /// Получение списка ограничений - /// - /// - Dictionary GetLimitingParameteraNames(); - } + /// + /// Получение списка ограничений + /// + /// + Dictionary GetLimitingParameteraNames(); } diff --git a/AsbCloudApp/Services/IMeasureService.cs b/AsbCloudApp/Services/IMeasureService.cs index e3b89111..70c91dbf 100644 --- a/AsbCloudApp/Services/IMeasureService.cs +++ b/AsbCloudApp/Services/IMeasureService.cs @@ -3,72 +3,71 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Сервис хранения результатов лабораторных анализов и измерений +/// +public interface IMeasureService { /// - /// Сервис хранения результатов лабораторных анализов и измерений + /// Категории измерений /// - public interface IMeasureService - { - /// - /// Категории измерений - /// - /// - /// - Task> GetCategoriesAsync(CancellationToken token); + /// + /// + Task> GetCategoriesAsync(CancellationToken token); - /// - /// Последние измерения по категории - /// - /// - /// - /// - /// - Task GetLastOrDefaultAsync(int idWell, int idCategory, CancellationToken token); + /// + /// Последние измерения по категории + /// + /// + /// + /// + /// + Task GetLastOrDefaultAsync(int idWell, int idCategory, CancellationToken token); - /// - /// История измерений по категории - /// - /// - /// - /// - /// - Task> GetHisoryAsync(int idWell, int? idCategory, CancellationToken token); - - /// - /// Добавить измерение - /// - /// - /// - /// - /// - Task InsertAsync(int idWell, MeasureDto data, CancellationToken token); + /// + /// История измерений по категории + /// + /// + /// + /// + /// + Task> GetHisoryAsync(int idWell, int? idCategory, CancellationToken token); + + /// + /// Добавить измерение + /// + /// + /// + /// + /// + Task InsertAsync(int idWell, MeasureDto data, CancellationToken token); - /// - /// Редактировать - /// - /// - /// - /// - /// - Task UpdateAsync(int idWell, MeasureDto data, CancellationToken token); + /// + /// Редактировать + /// + /// + /// + /// + /// + Task UpdateAsync(int idWell, MeasureDto data, CancellationToken token); - /// - /// Пометить удаленным - /// - /// - /// - /// - /// - Task MarkAsDeleteAsync(int idWell, int idData, CancellationToken token); + /// + /// Пометить удаленным + /// + /// + /// + /// + /// + Task MarkAsDeleteAsync(int idWell, int idData, CancellationToken token); - /// - /// Удалить - /// - /// - /// - /// - /// - Task DeleteAsync(int idWell, int idData, CancellationToken token); - } + /// + /// Удалить + /// + /// + /// + /// + /// + Task DeleteAsync(int idWell, int idData, CancellationToken token); } diff --git a/AsbCloudApp/Services/IMessageService.cs b/AsbCloudApp/Services/IMessageService.cs index 0a6557ba..5a5f4d17 100644 --- a/AsbCloudApp/Services/IMessageService.cs +++ b/AsbCloudApp/Services/IMessageService.cs @@ -5,29 +5,28 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Сервис сообщений панели оператора +/// +public interface IMessageService : ITelemetryDataEditorService { /// - /// Сервис сообщений панели оператора + /// Получить сообщения по параметрам /// - public interface IMessageService : ITelemetryDataEditorService - { - /// - /// Получить сообщения по параметрам - /// - /// - /// - /// - Task> GetMessagesAsync(MessageRequest request, CancellationToken token); + /// + /// + /// + Task> GetMessagesAsync(MessageRequest request, CancellationToken token); - /// - /// Метод для сохранения сообщения от панели - /// - /// - /// - /// - /// - Task InsertAsync(string uid, IEnumerable dtos, - CancellationToken token); - } + /// + /// Метод для сохранения сообщения от панели + /// + /// + /// + /// + /// + Task InsertAsync(string uid, IEnumerable dtos, + CancellationToken token); } \ No newline at end of file diff --git a/AsbCloudApp/Services/IOperationsStatService.cs b/AsbCloudApp/Services/IOperationsStatService.cs index 0861d8b1..d437bf52 100644 --- a/AsbCloudApp/Services/IOperationsStatService.cs +++ b/AsbCloudApp/Services/IOperationsStatService.cs @@ -4,44 +4,43 @@ using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data.WellOperation; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Сервис расчета статистики по операциям вводимым вручную +/// +public interface IOperationsStatService { /// - /// Сервис расчета статистики по операциям вводимым вручную + /// Получить статистику МСП по кусту в котором находится скважина с IdWell /// - public interface IOperationsStatService - { - /// - /// Получить статистику МСП по кусту в котором находится скважина с IdWell - /// - /// - /// - /// - Task GetOrDefaultRopStatAsync(int idWell, CancellationToken token); + /// + /// + /// + Task GetOrDefaultRopStatAsync(int idWell, CancellationToken token); - /// - /// Получить статистику по скважинам куста, которые доступны компании - /// - /// - /// - /// - /// - Task GetOrDefaultStatClusterAsync(int idCluster, int idCompany, CancellationToken token); + /// + /// Получить статистику по скважинам куста, которые доступны компании + /// + /// + /// + /// + /// + Task GetOrDefaultStatClusterAsync(int idCluster, int idCompany, CancellationToken token); - /// - /// получить статистику по скважине - /// - /// - /// - /// - Task GetOrDefaultWellStatAsync(int idWell, CancellationToken token); + /// + /// получить статистику по скважине + /// + /// + /// + /// + Task GetOrDefaultWellStatAsync(int idWell, CancellationToken token); - /// - /// Получить статистику по набору скважин - /// - /// - /// - /// - Task> GetWellsStatAsync(IEnumerable idWells, CancellationToken token); - } + /// + /// Получить статистику по набору скважин + /// + /// + /// + /// + Task> GetWellsStatAsync(IEnumerable idWells, CancellationToken token); } diff --git a/AsbCloudApp/Services/IReduceSamplingService.cs b/AsbCloudApp/Services/IReduceSamplingService.cs index eb7dacf5..e63072fe 100644 --- a/AsbCloudApp/Services/IReduceSamplingService.cs +++ b/AsbCloudApp/Services/IReduceSamplingService.cs @@ -1,41 +1,40 @@ using AsbCloudApp.Data; using System.Collections.Generic; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Делегат обновления состояния задачи +/// +/// +public delegate void OnJobProgressDelagate(JobDto job); + +/// +/// Сервис прореживания архива БД. +/// Удаляет часть телеметрии. +/// Понижает частоту записей в БД с 1 запись за 1 сек до 1 запись за N сек. +/// +public interface IReduceSamplingService { /// - /// Делегат обновления состояния задачи + /// Получить все задания. Задания удаляются минимум через 10 сек после выполнения, возможно позднее. /// - /// - public delegate void OnJobProgressDelagate(JobDto job); + /// Enumerable of JobDto or empty + IEnumerable GetJobs(); /// - /// Сервис прореживания архива БД. - /// Удаляет часть телеметрии. - /// Понижает частоту записей в БД с 1 запись за 1 сек до 1 запись за N сек. + /// Получить состояние определенной задачи /// - public interface IReduceSamplingService - { - /// - /// Получить все задания. Задания удаляются минимум через 10 сек после выполнения, возможно позднее. - /// - /// Enumerable of JobDto or empty - IEnumerable GetJobs(); + /// + /// + JobDto? GetOrDefaultState(int idTelemetry); - /// - /// Получить состояние определенной задачи - /// - /// - /// - JobDto? GetOrDefaultState(int idTelemetry); - - /// - /// Создать задачу прореживанию архива и добавить её в очередь на выполнение - /// - /// телеметрия для прореживания - /// колбек процесса выполнения - /// созданная задача или задача из очереди - /// задача добавлена == true - bool TryEnqueueRediceSamplingJob(int idTelemetry, OnJobProgressDelagate onProgress, out JobDto jobDto); - } + /// + /// Создать задачу прореживанию архива и добавить её в очередь на выполнение + /// + /// телеметрия для прореживания + /// колбек процесса выполнения + /// созданная задача или задача из очереди + /// задача добавлена == true + bool TryEnqueueRediceSamplingJob(int idTelemetry, OnJobProgressDelagate onProgress, out JobDto jobDto); } \ No newline at end of file diff --git a/AsbCloudApp/Services/IReportService.cs b/AsbCloudApp/Services/IReportService.cs index 19c0d70b..2e287a91 100644 --- a/AsbCloudApp/Services/IReportService.cs +++ b/AsbCloudApp/Services/IReportService.cs @@ -6,70 +6,69 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Сервис рапортов +/// +public interface IReportService { + /// - /// Сервис рапортов + /// Поставить рапорт в очередь на формирование /// - public interface IReportService - { + /// + /// + /// + /// + /// + string EnqueueCreateReportWork(int idWell, int idUser, ReportParametersRequest request, + Action handleReportProgress); - /// - /// Поставить рапорт в очередь на формирование - /// - /// - /// - /// - /// - /// - string EnqueueCreateReportWork(int idWell, int idUser, ReportParametersRequest request, - Action handleReportProgress); + /// + /// Создание отчета + /// + /// + /// + /// + /// + /// + /// + /// + Task CreateReportAsync(string workId, int idWell, int idUser, ReportParametersRequest request, Action progressHandler, CancellationToken token); - /// - /// Создание отчета - /// - /// - /// - /// - /// - /// - /// - /// - Task CreateReportAsync(string workId, int idWell, int idUser, ReportParametersRequest request, Action progressHandler, CancellationToken token); + /// + /// Получить предполагаемый список страниц рапорта + /// + /// + /// + /// + /// + /// + /// + int GetReportPagesCount(int idWell, DateTimeOffset begin, DateTimeOffset end, + int stepSeconds, int format); - /// - /// Получить предполагаемый список страниц рапорта - /// - /// - /// - /// - /// - /// - /// - int GetReportPagesCount(int idWell, DateTimeOffset begin, DateTimeOffset end, - int stepSeconds, int format); + /// + /// получить диапазон дат за которые есть данные + /// + /// + /// + DatesRangeDto? GetDatesRangeOrDefault(int idWell); - /// - /// получить диапазон дат за которые есть данные - /// - /// - /// - DatesRangeDto? GetDatesRangeOrDefault(int idWell); + /// + /// Список готовых рапортов + /// + /// + /// + /// + Task> GetAllReportsByWellAsync(int idWell, CancellationToken token); - /// - /// Список готовых рапортов - /// - /// - /// - /// - Task> GetAllReportsByWellAsync(int idWell, CancellationToken token); - - /// - /// Удаление отчетов, если превышен их период хранения - /// - /// период хранения отчетов - /// - /// - Task DeleteAllOldReportsAsync(TimeSpan lifetime, CancellationToken token); - } + /// + /// Удаление отчетов, если превышен их период хранения + /// + /// период хранения отчетов + /// + /// + Task DeleteAllOldReportsAsync(TimeSpan lifetime, CancellationToken token); } diff --git a/AsbCloudApp/Services/IRepositoryWellRelated.cs b/AsbCloudApp/Services/IRepositoryWellRelated.cs index ac98cfd1..829a8db4 100644 --- a/AsbCloudApp/Services/IRepositoryWellRelated.cs +++ b/AsbCloudApp/Services/IRepositoryWellRelated.cs @@ -3,30 +3,29 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Репозиторий получения, добавления, изменения, удаления данных
+/// Для сущностей относящихся к скважине +///
+/// +public interface IRepositoryWellRelated : ICrudRepository + where Tdto : IId, IWellRelated { /// - /// Репозиторий получения, добавления, изменения, удаления данных
- /// Для сущностей относящихся к скважине + /// Получение всех записей по скважине ///
- /// - public interface IRepositoryWellRelated : ICrudRepository - where Tdto : IId, IWellRelated - { - /// - /// Получение всех записей по скважине - /// - /// id скважины - /// - /// emptyList if nothing found - Task> GetByIdWellAsync(int idWell, CancellationToken token); + /// id скважины + /// + /// emptyList if nothing found + Task> GetByIdWellAsync(int idWell, CancellationToken token); - /// - /// Получение всех записей по нескольким скважинам - /// - /// id скважин - /// - /// emptyList if nothing found - Task> GetByIdWellAsync(IEnumerable idsWells, CancellationToken token); - } + /// + /// Получение всех записей по нескольким скважинам + /// + /// id скважин + /// + /// emptyList if nothing found + Task> GetByIdWellAsync(IEnumerable idsWells, CancellationToken token); } \ No newline at end of file diff --git a/AsbCloudApp/Services/IRequestTracker.cs b/AsbCloudApp/Services/IRequestTracker.cs index efaf6048..3be30f4d 100644 --- a/AsbCloudApp/Services/IRequestTracker.cs +++ b/AsbCloudApp/Services/IRequestTracker.cs @@ -2,59 +2,58 @@ using AsbCloudApp.Data; using System; using System.Collections.Generic; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Отслеживание и сбор статистики по запросам +/// +public interface IRequerstTrackerService { /// - /// Отслеживание и сбор статистики по запросам + /// Регистрирует новый запрос /// - public interface IRequerstTrackerService - { - /// - /// Регистрирует новый запрос - /// - /// - void RegisterRequest(RequestLogDto requestLog); + /// + void RegisterRequest(RequestLogDto requestLog); - /// - /// Регистрирует новый запрос, вызвавший ошибку на сервере - /// - /// - /// - void RegisterRequestError(RequestLogDto requestLog, Exception ex); + /// + /// Регистрирует новый запрос, вызвавший ошибку на сервере + /// + /// + /// + void RegisterRequestError(RequestLogDto requestLog, Exception ex); - /// - /// все зарегистрированные запросы - /// - /// - /// - IEnumerable GetAll(int? take); + /// + /// все зарегистрированные запросы + /// + /// + /// + IEnumerable GetAll(int? take); - /// - /// запросы которые выполнялись быстро - /// - /// - /// - IEnumerable GetFast(int? take); + /// + /// запросы которые выполнялись быстро + /// + /// + /// + IEnumerable GetFast(int? take); - /// - /// запросы, которые выполнялись медленно - /// - /// - /// - IEnumerable GetSlow(int? take); + /// + /// запросы, которые выполнялись медленно + /// + /// + /// + IEnumerable GetSlow(int? take); - /// - /// запросы, которые завершились ошибкой - /// - /// - /// - IEnumerable GetError(int? take); + /// + /// запросы, которые завершились ошибкой + /// + /// + /// + IEnumerable GetError(int? take); - /// - /// Статистика посещений пользователей - /// - /// - /// - IEnumerable GetUsersStat(int? take); - } + /// + /// Статистика посещений пользователей + /// + /// + /// + IEnumerable GetUsersStat(int? take); } diff --git a/AsbCloudApp/Services/IScheduleReportService.cs b/AsbCloudApp/Services/IScheduleReportService.cs index 5c7e535f..b26b2b85 100644 --- a/AsbCloudApp/Services/IScheduleReportService.cs +++ b/AsbCloudApp/Services/IScheduleReportService.cs @@ -2,19 +2,18 @@ using System.IO; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Сервис формирования Сетевого графика. +/// +public interface IScheduleReportService { /// - /// Сервис формирования Сетевого графика. + /// Сформировать. /// - public interface IScheduleReportService - { - /// - /// Сформировать. - /// - /// - /// - /// - Task MakeReportAsync(int idWell, CancellationToken token = default); - } + /// + /// + /// + Task MakeReportAsync(int idWell, CancellationToken token = default); } \ No newline at end of file diff --git a/AsbCloudApp/Services/IScheduleService.cs b/AsbCloudApp/Services/IScheduleService.cs index 8181ba59..6eafa089 100644 --- a/AsbCloudApp/Services/IScheduleService.cs +++ b/AsbCloudApp/Services/IScheduleService.cs @@ -5,37 +5,36 @@ using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Requests; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Репозиторий расписания смен бурильщика +/// +public interface IScheduleRepository : IRepositoryWellRelated { /// - /// Репозиторий расписания смен бурильщика + /// Получить расписание смен /// - public interface IScheduleRepository : IRepositoryWellRelated - { - /// - /// Получить расписание смен - /// - /// - /// - /// - /// - Task> GetAsync(int idWell, DateTimeOffset workTime, CancellationToken token); - - /// - /// получить бурильщика по idWell и времени - /// - /// - /// - /// - /// - Task GetOrDefaultDrillerAsync(int idWell, DateTimeOffset workTime, CancellationToken token); + /// + /// + /// + /// + Task> GetAsync(int idWell, DateTimeOffset workTime, CancellationToken token); + + /// + /// получить бурильщика по idWell и времени + /// + /// + /// + /// + /// + Task GetOrDefaultDrillerAsync(int idWell, DateTimeOffset workTime, CancellationToken token); - /// - /// Получить расписание смен - /// - /// - /// - /// - Task> GetPageAsync(GetStatRequest request, CancellationToken token); - } + /// + /// Получить расписание смен + /// + /// + /// + /// + Task> GetPageAsync(GetStatRequest request, CancellationToken token); } diff --git a/AsbCloudApp/Services/ISetpointsService.cs b/AsbCloudApp/Services/ISetpointsService.cs index 59936e85..a5db8620 100644 --- a/AsbCloudApp/Services/ISetpointsService.cs +++ b/AsbCloudApp/Services/ISetpointsService.cs @@ -3,57 +3,56 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Сервис рекомендаций новых уставок для панели оператора САУБ +/// +public interface ISetpointsService { /// - /// Сервис рекомендаций новых уставок для панели оператора САУБ + /// Добавить новый набор рекомендаций /// - public interface ISetpointsService - { - /// - /// Добавить новый набор рекомендаций - /// - /// - /// - /// - Task InsertAsync(SetpointsRequestDto setpoints, CancellationToken token); - - /// - /// Получить наборы уставок на скважине - /// - /// - /// - /// - Task> GetAsync(int idWell, CancellationToken token); + /// + /// + /// + Task InsertAsync(SetpointsRequestDto setpoints, CancellationToken token); + + /// + /// Получить наборы уставок на скважине + /// + /// + /// + /// + Task> GetAsync(int idWell, CancellationToken token); - /// - /// Скачать новые рекомендации (скачивает панель оператора) - /// - /// - /// - /// - Task> GetForPanelAsync(string uid, CancellationToken token); + /// + /// Скачать новые рекомендации (скачивает панель оператора) + /// + /// + /// + /// + Task> GetForPanelAsync(string uid, CancellationToken token); - /// - /// Попробовать удалить (успешно, если панель еще не забрала уставки) - /// - /// - /// - /// - Task TryDelete(int id, CancellationToken token); + /// + /// Попробовать удалить (успешно, если панель еще не забрала уставки) + /// + /// + /// + /// + Task TryDelete(int id, CancellationToken token); - /// - /// отредактировать состояние набора рекомендаций - /// - /// - /// - /// - Task UpdateStateAsync(SetpointsRequestDto setpointsRequestDto, CancellationToken token); + /// + /// отредактировать состояние набора рекомендаций + /// + /// + /// + /// + Task UpdateStateAsync(SetpointsRequestDto setpointsRequestDto, CancellationToken token); - /// - /// Список уставок для рекомендаций - /// - /// - IEnumerable GetSetpointsNames(); - } + /// + /// Список уставок для рекомендаций + /// + /// + IEnumerable GetSetpointsNames(); } diff --git a/AsbCloudApp/Services/ISlipsStatService.cs b/AsbCloudApp/Services/ISlipsStatService.cs index c2b2aa98..873c44d1 100644 --- a/AsbCloudApp/Services/ISlipsStatService.cs +++ b/AsbCloudApp/Services/ISlipsStatService.cs @@ -5,19 +5,18 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Сервис для получения аналитики удержания в клиньях +/// +public interface ISlipsStatService { /// - /// Сервис для получения аналитики удержания в клиньях + /// Получение записей для построения аналитики удержания в клиньях /// - public interface ISlipsStatService - { - /// - /// Получение записей для построения аналитики удержания в клиньях - /// - /// параметры запроса - /// - /// - Task> GetAllAsync(OperationStatRequest request, CancellationToken token); - } + /// параметры запроса + /// + /// + Task> GetAllAsync(OperationStatRequest request, CancellationToken token); } diff --git a/AsbCloudApp/Services/ITelemetryDataService.cs b/AsbCloudApp/Services/ITelemetryDataService.cs index f9e3c4d7..96ea6e98 100644 --- a/AsbCloudApp/Services/ITelemetryDataService.cs +++ b/AsbCloudApp/Services/ITelemetryDataService.cs @@ -5,70 +5,69 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// сервис данных тех. процесса +/// +/// +public interface ITelemetryDataService : ITelemetryDataEditorService where TDto : ITelemetryData { + /// - /// сервис данных тех. процесса + /// получить данные тех. процесса /// - /// - public interface ITelemetryDataService : ITelemetryDataEditorService where TDto : ITelemetryData - { + /// + /// + /// + /// кол-во элементов до которых эти данные прореживаются + /// + /// + Task> GetByWellAsync(int idWell, + DateTime dateBegin = default, double intervalSec = 600d, + int approxPointsCount = 1024, CancellationToken token = default); - /// - /// получить данные тех. процесса - /// - /// - /// - /// - /// кол-во элементов до которых эти данные прореживаются - /// - /// - Task> GetByWellAsync(int idWell, - DateTime dateBegin = default, double intervalSec = 600d, - int approxPointsCount = 1024, CancellationToken token = default); + /// + /// Получить данные тех. процесса по скважине + /// + /// + /// + /// + /// + Task> GetByWellAsync(int idWell, TelemetryDataRequest request, CancellationToken token); - /// - /// Получить данные тех. процесса по скважине - /// - /// - /// - /// - /// - Task> GetByWellAsync(int idWell, TelemetryDataRequest request, CancellationToken token); + /// + /// Получение данных тех. процесса по телеметрии + /// + /// + /// + /// + /// + Task> GetByTelemetryAsync(int idTelemetry, TelemetryDataRequest request, CancellationToken token); - /// - /// Получение данных тех. процесса по телеметрии - /// - /// - /// - /// - /// - Task> GetByTelemetryAsync(int idTelemetry, TelemetryDataRequest request, CancellationToken token); + /// + /// Период за который есть данные по скважине в рамках временного интервала + /// + /// + /// + /// + /// + /// + Task GetRangeAsync(int idWell, DateTimeOffset geDate, DateTimeOffset? leDate, CancellationToken token); - /// - /// Период за который есть данные по скважине в рамках временного интервала - /// - /// - /// - /// - /// - /// - Task GetRangeAsync(int idWell, DateTimeOffset geDate, DateTimeOffset? leDate, CancellationToken token); + /// + /// Период за который есть данные по скважине + /// + /// + /// + DatesRangeDto? GetRange(int idWell); - /// - /// Период за который есть данные по скважине - /// - /// - /// - DatesRangeDto? GetRange(int idWell); - - /// - /// добавить/изменить данные тех. процесса (используется панелью) - /// - /// - /// - /// - /// - Task UpdateDataAsync(string uid, IEnumerable dtos, CancellationToken token); - } + /// + /// добавить/изменить данные тех. процесса (используется панелью) + /// + /// + /// + /// + /// + Task UpdateDataAsync(string uid, IEnumerable dtos, CancellationToken token); } \ No newline at end of file diff --git a/AsbCloudApp/Services/ITelemetryService.cs b/AsbCloudApp/Services/ITelemetryService.cs index 49b28388..3c434700 100644 --- a/AsbCloudApp/Services/ITelemetryService.cs +++ b/AsbCloudApp/Services/ITelemetryService.cs @@ -6,77 +6,76 @@ using System.IO; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Сервис телеметрии +/// +public interface ITelemetryService { /// - /// Сервис телеметрии + /// сервис временных зон /// - public interface ITelemetryService - { - /// - /// сервис временных зон - /// - ITimezoneService TimeZoneService { get; } + ITimezoneService TimeZoneService { get; } - /// - /// получить idWell по uid телеметрии - /// - /// - /// - int? GetIdWellByTelemetryUid(string uid); + /// + /// получить idWell по uid телеметрии + /// + /// + /// + int? GetIdWellByTelemetryUid(string uid); - /// - /// Получить id телеметрии. Если её нет в БД, то добавить новую. - /// - /// - /// - TelemetryDto GetOrCreateTelemetryByUid(string uid); + /// + /// Получить id телеметрии. Если её нет в БД, то добавить новую. + /// + /// + /// + TelemetryDto GetOrCreateTelemetryByUid(string uid); - /// - /// получить временную зону скважины по idTelemetry - /// - /// - /// - SimpleTimezoneDto GetTimezone(int idTelemetry); + /// + /// получить временную зону скважины по idTelemetry + /// + /// + /// + SimpleTimezoneDto GetTimezone(int idTelemetry); - /// - /// получить idTelemetry по IdWell - /// - /// - /// - TelemetryBaseDto? GetOrDefaultTelemetryByIdWell(int idWell); + /// + /// получить idTelemetry по IdWell + /// + /// + /// + TelemetryBaseDto? GetOrDefaultTelemetryByIdWell(int idWell); - /// - /// получить диапазон дат за которые есть данные - /// - /// - /// - DatesRangeDto GetDatesRange(int idTelemetry); + /// + /// получить диапазон дат за которые есть данные + /// + /// + /// + DatesRangeDto GetDatesRange(int idTelemetry); - /// - /// обновить данные о телеметрии (используется панелью) - /// - /// - /// - /// - /// - Task UpdateInfoAsync(string uid, TelemetryInfoDto info, CancellationToken token); + /// + /// обновить данные о телеметрии (используется панелью) + /// + /// + /// + /// + /// + Task UpdateInfoAsync(string uid, TelemetryInfoDto info, CancellationToken token); - /// - /// Слить данные телеметрии в одну - /// - /// старая (исходная) - /// новая - /// - /// - Task MergeAsync(int from, int to, CancellationToken token); + /// + /// Слить данные телеметрии в одну + /// + /// старая (исходная) + /// новая + /// + /// + Task MergeAsync(int from, int to, CancellationToken token); - /// - /// Получить телеметрию по последней дате - /// - /// - /// - /// - Task GetTelemetriesInfoByLastData(DateTimeOffset from, CancellationToken token); - } + /// + /// Получить телеметрию по последней дате + /// + /// + /// + /// + Task GetTelemetriesInfoByLastData(DateTimeOffset from, CancellationToken token); } \ No newline at end of file diff --git a/AsbCloudApp/Services/ITelemetryUserService.cs b/AsbCloudApp/Services/ITelemetryUserService.cs index 8635f666..721979c8 100644 --- a/AsbCloudApp/Services/ITelemetryUserService.cs +++ b/AsbCloudApp/Services/ITelemetryUserService.cs @@ -4,36 +4,35 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// сервис пользователей телеметрии +/// +public interface ITelemetryUserService { /// - /// сервис пользователей телеметрии + /// get user by ids /// - public interface ITelemetryUserService - { - /// - /// get user by ids - /// - /// - /// - /// - TelemetryUserDto? GetOrDefault(int idTelemetry, int idUser); + /// + /// + /// + TelemetryUserDto? GetOrDefault(int idTelemetry, int idUser); - /// - /// get users by id telemetry and predicate - /// - /// - /// - /// - IEnumerable GetUsers(int idTelemetry, Func? predicate = default); + /// + /// get users by id telemetry and predicate + /// + /// + /// + /// + IEnumerable GetUsers(int idTelemetry, Func? predicate = default); - /// - /// получает и сохраняет/обновляет список пользователей панели оператора - /// - /// - /// - /// - /// - Task UpsertAsync(string uid, IEnumerable dtos, CancellationToken token = default); - } + /// + /// получает и сохраняет/обновляет список пользователей панели оператора + /// + /// + /// + /// + /// + Task UpsertAsync(string uid, IEnumerable dtos, CancellationToken token = default); } \ No newline at end of file diff --git a/AsbCloudApp/Services/ITimeZoneService.cs b/AsbCloudApp/Services/ITimeZoneService.cs index 06993884..fd44e2fc 100644 --- a/AsbCloudApp/Services/ITimeZoneService.cs +++ b/AsbCloudApp/Services/ITimeZoneService.cs @@ -2,28 +2,27 @@ using AsbCloudApp.Data; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// сервис определения временной зоны +/// +public interface ITimezoneService { /// - /// сервис определения временной зоны + /// по координатам /// - public interface ITimezoneService - { - /// - /// по координатам - /// - /// - /// - /// - SimpleTimezoneDto? GetOrDefaultByCoordinates(double latitude, double longitude); + /// + /// + /// + SimpleTimezoneDto? GetOrDefaultByCoordinates(double latitude, double longitude); - /// - /// по координатам - /// - /// - /// - /// - /// - Task GetOrDefaultByCoordinatesAsync(double latitude, double longitude, CancellationToken token); - } + /// + /// по координатам + /// + /// + /// + /// + /// + Task GetOrDefaultByCoordinatesAsync(double latitude, double longitude, CancellationToken token); } \ No newline at end of file diff --git a/AsbCloudApp/Services/IUserSettingsRepository.cs b/AsbCloudApp/Services/IUserSettingsRepository.cs index 63605d4b..65efa111 100644 --- a/AsbCloudApp/Services/IUserSettingsRepository.cs +++ b/AsbCloudApp/Services/IUserSettingsRepository.cs @@ -1,57 +1,56 @@ using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// репозиторий для личных настроек пользователя +/// +public interface IUserSettingsRepository { /// - /// репозиторий для личных настроек пользователя + /// код ошибки: ключ не найден /// - public interface IUserSettingsRepository - { - /// - /// код ошибки: ключ не найден - /// - public const int ErrorKeyNotFound = -1; - - /// - /// код ошибки: ключ уже занят - /// - public const int ErrorKeyIsUsed = -2; + public const int ErrorKeyNotFound = -1; + + /// + /// код ошибки: ключ уже занят + /// + public const int ErrorKeyIsUsed = -2; - /// - /// Получить настройки по ключу для пользователя - /// - /// - /// - /// - /// - Task GetOrDefaultAsync(int userId, string key, CancellationToken token); + /// + /// Получить настройки по ключу для пользователя + /// + /// + /// + /// + /// + Task GetOrDefaultAsync(int userId, string key, CancellationToken token); - /// - /// Добавить или изменить настройки с ключем для пользователя - /// - /// - /// - /// - /// - /// - Task UpsertAsync(int userId, string key, System.Text.Json.JsonDocument value, CancellationToken token); + /// + /// Добавить или изменить настройки с ключем для пользователя + /// + /// + /// + /// + /// + /// + Task UpsertAsync(int userId, string key, System.Text.Json.JsonDocument value, CancellationToken token); - /// - /// Удалить настройки с ключем для пользователя - /// - /// - /// - /// - /// - Task DeleteAsync(int userId, string key, CancellationToken token); + /// + /// Удалить настройки с ключем для пользователя + /// + /// + /// + /// + /// + Task DeleteAsync(int userId, string key, CancellationToken token); - /// - /// Удалить ВСЕ настройки пользователя - /// - /// - /// - /// - Task DeleteAsync(int userId, CancellationToken token); - } + /// + /// Удалить ВСЕ настройки пользователя + /// + /// + /// + /// + Task DeleteAsync(int userId, CancellationToken token); } \ No newline at end of file diff --git a/AsbCloudApp/Services/IWellCompositeOperationService.cs b/AsbCloudApp/Services/IWellCompositeOperationService.cs index 98be1494..875be603 100644 --- a/AsbCloudApp/Services/IWellCompositeOperationService.cs +++ b/AsbCloudApp/Services/IWellCompositeOperationService.cs @@ -3,19 +3,18 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Интерфейс для вычисления композитной скважины +/// +public interface IWellCompositeOperationService { /// - /// Интерфейс для вычисления композитной скважины + /// Получение данных для построения композитной скважины /// - public interface IWellCompositeOperationService - { - /// - /// Получение данных для построения композитной скважины - /// - /// - /// - /// - Task GetAsync(IEnumerable idsWells, CancellationToken token); - } + /// + /// + /// + Task GetAsync(IEnumerable idsWells, CancellationToken token); } diff --git a/AsbCloudApp/Services/IWellContactService.cs b/AsbCloudApp/Services/IWellContactService.cs index cf7124db..e5738139 100644 --- a/AsbCloudApp/Services/IWellContactService.cs +++ b/AsbCloudApp/Services/IWellContactService.cs @@ -5,70 +5,69 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Сервис по работе с контактной информацией по скважине +/// +public interface IWellContactService { /// - /// Сервис по работе с контактной информацией по скважине + /// Получение контактов по параметрам запроса /// - public interface IWellContactService - { - /// - /// Получение контактов по параметрам запроса - /// - /// ключ скважины - /// - /// - Task> GetAllAsync(WellContactRequest request, CancellationToken token); + /// ключ скважины + /// + /// + Task> GetAllAsync(WellContactRequest request, CancellationToken token); - /// - /// Получение контакта по ключу - /// - /// ключ скважины - /// ключ пользователя - /// - /// - Task GetAsync(int idWell, int id, CancellationToken token); + /// + /// Получение контакта по ключу + /// + /// ключ скважины + /// ключ пользователя + /// + /// + Task GetAsync(int idWell, int id, CancellationToken token); - /// - /// Получение типов контактов - /// - /// - /// - Task> GetTypesAsync(CancellationToken token); + /// + /// Получение типов контактов + /// + /// + /// + Task> GetTypesAsync(CancellationToken token); - /// - /// Добавление контакта - /// - /// - /// - /// - Task InsertAsync(ContactDto contactDto, CancellationToken token); + /// + /// Добавление контакта + /// + /// + /// + /// + Task InsertAsync(ContactDto contactDto, CancellationToken token); - /// - /// Изменение контакта - /// - /// - /// - /// - Task UpdateAsync(ContactDto contactDto, CancellationToken token); + /// + /// Изменение контакта + /// + /// + /// + /// + Task UpdateAsync(ContactDto contactDto, CancellationToken token); - /// - /// Удаление контакта - /// - /// ключ скважины - /// ключ скважины - /// - /// - Task DeleteAsync(int idWell, int id, CancellationToken token); + /// + /// Удаление контакта + /// + /// ключ скважины + /// ключ скважины + /// + /// + Task DeleteAsync(int idWell, int id, CancellationToken token); - /// - /// Скопировать контакты в другую скважину - /// - /// ключ скважины, откуда копировать контакты - /// ключ скважины, куда копировать контакты - /// - /// - /// - Task CopyAsync(int idWell, int idWellTarget, IEnumerable contactIds, CancellationToken token); - } + /// + /// Скопировать контакты в другую скважину + /// + /// ключ скважины, откуда копировать контакты + /// ключ скважины, куда копировать контакты + /// + /// + /// + Task CopyAsync(int idWell, int idWellTarget, IEnumerable contactIds, CancellationToken token); } diff --git a/AsbCloudApp/Services/IWellFinalDocumentsService.cs b/AsbCloudApp/Services/IWellFinalDocumentsService.cs index 06daee1e..c47f18aa 100644 --- a/AsbCloudApp/Services/IWellFinalDocumentsService.cs +++ b/AsbCloudApp/Services/IWellFinalDocumentsService.cs @@ -4,51 +4,50 @@ using System.IO; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Сервис "Дело скважины" +/// +public interface IWellFinalDocumentsService { /// - /// Сервис "Дело скважины" + /// Обновление записей дела скважины /// - public interface IWellFinalDocumentsService - { - /// - /// Обновление записей дела скважины - /// - /// - /// - /// - /// - Task UpdateRangeAsync(int idWell, IEnumerable dtos, CancellationToken token); + /// + /// + /// + /// + Task UpdateRangeAsync(int idWell, IEnumerable dtos, CancellationToken token); - /// - /// Получение истории файлов - /// - /// - /// - /// - /// - Task GetFilesHistoryByIdCategoryAsync(int idWell, int idCategory, CancellationToken token); + /// + /// Получение истории файлов + /// + /// + /// + /// + /// + Task GetFilesHistoryByIdCategoryAsync(int idWell, int idCategory, CancellationToken token); - /// - /// Сохранение файла - /// - /// - /// - /// пользователь, который сохраняет файл - /// - /// - /// - /// - Task SaveCategoryFileAsync(int idWell, int idCategory, int idUser, Stream fileStream, string fileName, CancellationToken token); + /// + /// Сохранение файла + /// + /// + /// + /// пользователь, который сохраняет файл + /// + /// + /// + /// + Task SaveCategoryFileAsync(int idWell, int idCategory, int idUser, Stream fileStream, string fileName, CancellationToken token); - /// - /// Повторно оповестить ответственных за загрузку - /// - /// - /// запрашивающий пользователь, для проверки его прав и текста сообщения - /// - /// - /// count of notified publishers - Task ReNotifyPublishersAsync(int idWell, int idUser, int idCategory, CancellationToken token); - } + /// + /// Повторно оповестить ответственных за загрузку + /// + /// + /// запрашивающий пользователь, для проверки его прав и текста сообщения + /// + /// + /// count of notified publishers + Task ReNotifyPublishersAsync(int idWell, int idUser, int idCategory, CancellationToken token); } \ No newline at end of file diff --git a/AsbCloudApp/Services/IWellOperationService.cs b/AsbCloudApp/Services/IWellOperationService.cs index ea4b466b..4c956606 100644 --- a/AsbCloudApp/Services/IWellOperationService.cs +++ b/AsbCloudApp/Services/IWellOperationService.cs @@ -5,62 +5,59 @@ using System.Threading.Tasks; using AsbCloudApp.Data.WellOperation; using AsbCloudApp.Requests; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// Сервис по представлению данных по операциям +/// +public interface IWellOperationService { /// - /// Сервис по представлению данных по операциям + /// Получить страницу списка операций /// - public interface IWellOperationService - { - /// - /// Получить страницу списка операций - /// - /// - /// - /// - Task> GetAsync(WellOperationRequest request, CancellationToken token); + /// + /// + /// + Task> GetAsync(WellOperationRequest request, CancellationToken token); - /// - /// Получить страницу списка операций - /// - /// - /// - /// - Task> GetPageAsync(WellOperationRequest request, CancellationToken token); + /// + /// Получить страницу списка операций + /// + /// + /// + /// + Task> GetPageAsync(WellOperationRequest request, CancellationToken token); - /// - /// Получить страницу с операцией - /// - /// - /// - /// - /// - /// - /// - /// - Task?> GetPageAsync(int idWell, - int id, - int operationType, - int? take, - IEnumerable? sortFields, - CancellationToken token); - - /// - /// Получить статистику операции по скважине с группировкой по категориям - /// - /// - /// - /// - Task> GetGroupOperationsStatAsync(WellOperationRequest request, CancellationToken token); - - /// - /// Получить данные для графика TVD - /// - /// - /// - /// - Task>> GetTvdAsync(int idWell, CancellationToken token); - } + /// + /// Получить страницу с операцией + /// + /// + /// + /// + /// + /// + /// + /// + Task?> GetPageAsync(int idWell, + int id, + int operationType, + int? take, + IEnumerable? sortFields, + CancellationToken token); + /// + /// Получить статистику операции по скважине с группировкой по категориям + /// + /// + /// + /// + Task> GetGroupOperationsStatAsync(WellOperationRequest request, CancellationToken token); + /// + /// Получить данные для графика TVD + /// + /// + /// + /// + Task>> GetTvdAsync(int idWell, CancellationToken token); } diff --git a/AsbCloudApp/Services/IWellService.cs b/AsbCloudApp/Services/IWellService.cs index 2decf61b..21bc7f7f 100644 --- a/AsbCloudApp/Services/IWellService.cs +++ b/AsbCloudApp/Services/IWellService.cs @@ -5,104 +5,103 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// сервис скважин +/// +public interface IWellService : ICrudRepository { /// - /// сервис скважин + /// сервис телеметрии /// - public interface IWellService : ICrudRepository - { - /// - /// сервис телеметрии - /// - ITelemetryService TelemetryService { get; } + ITelemetryService TelemetryService { get; } - /// - /// Список скважин доступных компании - /// - /// - /// - /// - Task> GetAsync(WellRequest request, CancellationToken token); + /// + /// Список скважин доступных компании + /// + /// + /// + /// + Task> GetAsync(WellRequest request, CancellationToken token); - /// - /// Статистика по скважине - /// - /// - /// - /// - Task GetOrDefaultStatAsync(int idWell, CancellationToken token); + /// + /// Статистика по скважине + /// + /// + /// + /// + Task GetOrDefaultStatAsync(int idWell, CancellationToken token); - /// - /// проверяет доступ к скважине для компании - /// - /// - /// - /// - /// - Task IsCompanyInvolvedInWellAsync(int idCompany, int idWell, CancellationToken token); + /// + /// проверяет доступ к скважине для компании + /// + /// + /// + /// + /// + Task IsCompanyInvolvedInWellAsync(int idCompany, int idWell, CancellationToken token); - //TODO: remove that - /// - /// получить название скважины по id - /// - /// - /// - /// - Task GetWellCaptionByIdAsync(int idWell, CancellationToken token); + //TODO: remove that + /// + /// получить название скважины по id + /// + /// + /// + /// + Task GetWellCaptionByIdAsync(int idWell, CancellationToken token); - /// - /// список компаний участвующих в скважине - /// - /// - /// - /// - Task> GetCompaniesAsync(int idWell, CancellationToken token); + /// + /// список компаний участвующих в скважине + /// + /// + /// + /// + Task> GetCompaniesAsync(int idWell, CancellationToken token); - //TODO: remove that - /// - /// - /// - /// - /// - string GetStateText(int state); + //TODO: remove that + /// + /// + /// + /// + /// + string GetStateText(int state); - /// - /// дата получения последних данных от панели - /// - /// - /// - DateTimeOffset GetLastTelemetryDate(int idWell); + /// + /// дата получения последних данных от панели + /// + /// + /// + DateTimeOffset GetLastTelemetryDate(int idWell); - //TODO: выяснить и удалить отсюда - /// - /// получение списка скважин куста в котором находится указанная скважина - /// - /// - /// - /// - Task> GetClusterWellsIdsAsync(int idWell, CancellationToken token); + //TODO: выяснить и удалить отсюда + /// + /// получение списка скважин куста в котором находится указанная скважина + /// + /// + /// + /// + Task> GetClusterWellsIdsAsync(int idWell, CancellationToken token); - /// - /// часовой пояс скважины - /// - /// - /// - SimpleTimezoneDto GetTimezone(int idWell); + /// + /// часовой пояс скважины + /// + /// + /// + SimpleTimezoneDto GetTimezone(int idWell); - /// - /// диапазон дат с данными телеметрии - /// - /// - /// - DatesRangeDto GetDatesRange(int idWell); + /// + /// диапазон дат с данными телеметрии + /// + /// + /// + DatesRangeDto GetDatesRange(int idWell); - /// - /// ВРЕМЕННЫЙ метод - /// - /// - /// - /// - Task> GetWellTreeAsync(int idCompany, CancellationToken token); - } + /// + /// ВРЕМЕННЫЙ метод + /// + /// + /// + /// + Task> GetWellTreeAsync(int idCompany, CancellationToken token); } diff --git a/AsbCloudApp/Services/IWitsRepository.cs b/AsbCloudApp/Services/IWitsRepository.cs index e6b409c1..ec2f99b3 100644 --- a/AsbCloudApp/Services/IWitsRepository.cs +++ b/AsbCloudApp/Services/IWitsRepository.cs @@ -5,46 +5,45 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Services; + +/// +/// The wits record repository. +/// +public interface IWitsRecordRepository : ITelemetryDataEditorService + where TDto : ITelemetryData { /// - /// The wits record repository. + /// Добавить новые данные /// - public interface IWitsRecordRepository : ITelemetryDataEditorService - where TDto : ITelemetryData - { - /// - /// Добавить новые данные - /// - /// The id telemetry. - /// The dtos. - /// The token. - /// A Task. - Task SaveDataAsync(int idTelemetry, IEnumerable dtos, CancellationToken token); + /// The id telemetry. + /// The dtos. + /// The token. + /// A Task. + Task SaveDataAsync(int idTelemetry, IEnumerable dtos, CancellationToken token); - /// - /// Получить данные по телеметрии за период - /// - /// - /// - /// - /// - /// - Task> GetAsync(int idTelemetry, DateTime begin, DateTime end, CancellationToken token); - - /// - /// получить массив из одной записи самой поздней по дате - /// - /// The id telemetry. - /// A Task. - TDto? GetLastOrDefault(int idTelemetry); - - /// - /// получить статистику по всему архиву: дата самой ранней записи, самой поздней и общее количество - /// - /// The id telemetry. - /// The token. - /// A Task. - Task<(DateTime begin, DateTime end, int count)?> GetStatAsync(int idTelemetry, CancellationToken token); - } + /// + /// Получить данные по телеметрии за период + /// + /// + /// + /// + /// + /// + Task> GetAsync(int idTelemetry, DateTime begin, DateTime end, CancellationToken token); + + /// + /// получить массив из одной записи самой поздней по дате + /// + /// The id telemetry. + /// A Task. + TDto? GetLastOrDefault(int idTelemetry); + + /// + /// получить статистику по всему архиву: дата самой ранней записи, самой поздней и общее количество + /// + /// The id telemetry. + /// The token. + /// A Task. + Task<(DateTime begin, DateTime end, int count)?> GetStatAsync(int idTelemetry, CancellationToken token); } \ No newline at end of file diff --git a/AsbCloudApp/Services/ProcessMaps/WellDrilling/IProcessMapReportDrillingExportService.cs b/AsbCloudApp/Services/ProcessMaps/WellDrilling/IProcessMapReportDrillingExportService.cs index d0d0fc32..b1d3a149 100644 --- a/AsbCloudApp/Services/ProcessMaps/WellDrilling/IProcessMapReportDrillingExportService.cs +++ b/AsbCloudApp/Services/ProcessMaps/WellDrilling/IProcessMapReportDrillingExportService.cs @@ -7,20 +7,19 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services.ProcessMaps.WellDrilling +namespace AsbCloudApp.Services.ProcessMaps.WellDrilling; + +/// +/// Сервис экспорт РТК +/// +public interface IProcessMapReportDrillingExportService { /// - /// Сервис экспорт РТК + /// Сформировать файл с данными /// - public interface IProcessMapReportDrillingExportService - { - /// - /// Сформировать файл с данными - /// - /// - /// параметры запроса - /// - /// - Task<(string Name, Stream File)?> ExportAsync(int idWell, DataSaubStatRequest request, CancellationToken cancellationToken); - } + /// + /// параметры запроса + /// + /// + Task<(string Name, Stream File)?> ExportAsync(int idWell, DataSaubStatRequest request, CancellationToken cancellationToken); } diff --git a/AsbCloudInfrastructure/AssemblyExtensions.cs b/AsbCloudInfrastructure/AssemblyExtensions.cs index 79ff0695..3fbdf43b 100644 --- a/AsbCloudInfrastructure/AssemblyExtensions.cs +++ b/AsbCloudInfrastructure/AssemblyExtensions.cs @@ -3,27 +3,26 @@ using System.IO; using System.Linq; using System.Reflection; -namespace AsbCloudInfrastructure +namespace AsbCloudInfrastructure; + +public static class AssemblyExtensions { - public static class AssemblyExtensions - { - public static Stream GetTemplateCopyStream(this Assembly assembly, string templateName) - { - var resourceName = assembly - .GetManifestResourceNames() - .FirstOrDefault(n => n.EndsWith(templateName)); + public static Stream GetTemplateCopyStream(this Assembly assembly, string templateName) + { + var resourceName = assembly + .GetManifestResourceNames() + .FirstOrDefault(n => n.EndsWith(templateName)); - if (string.IsNullOrWhiteSpace(resourceName)) - throw new ArgumentNullException(nameof(resourceName)); + if (string.IsNullOrWhiteSpace(resourceName)) + throw new ArgumentNullException(nameof(resourceName)); - using var stream = Assembly.GetExecutingAssembly() - .GetManifestResourceStream(resourceName); + using var stream = Assembly.GetExecutingAssembly() + .GetManifestResourceStream(resourceName); - var memoryStream = new MemoryStream(); - stream?.CopyTo(memoryStream); - memoryStream.Position = 0; + var memoryStream = new MemoryStream(); + stream?.CopyTo(memoryStream); + memoryStream.Position = 0; return memoryStream; } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Background/PeriodicWorks/WorkDataSaubStat.cs b/AsbCloudInfrastructure/Background/PeriodicWorks/WorkDataSaubStat.cs index 6a2f92de..444672ad 100644 --- a/AsbCloudInfrastructure/Background/PeriodicWorks/WorkDataSaubStat.cs +++ b/AsbCloudInfrastructure/Background/PeriodicWorks/WorkDataSaubStat.cs @@ -13,27 +13,26 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Background.PeriodicWorks +namespace AsbCloudInfrastructure.Background.PeriodicWorks; + +/// +/// задача по добавлению данных в таблицу DataSaubStat, которая используется для построения РТК-отчета +/// +internal class WorkDataSaubStat : Work { - /// - /// задача по добавлению данных в таблицу DataSaubStat, которая используется для построения РТК-отчета - /// - internal class WorkDataSaubStat : Work + private int Gap = 60; + + public WorkDataSaubStat() : base("Generate DataSaubStat entries and save them into Db") { - private int Gap = 60; - - public WorkDataSaubStat() : base("Generate DataSaubStat entries and save them into Db") - { - Timeout = TimeSpan.FromMinutes(10); - } - - protected override async Task Action(string id, IServiceProvider services, Action onProgressCallback, CancellationToken token) - { - var dataSaubStatService = services.GetRequiredService(); - - if (dataSaubStatService != null ) - await dataSaubStatService.CreateStatAsync(Gap, onProgressCallback, token); - - } + Timeout = TimeSpan.FromMinutes(10); } + + protected override async Task Action(string id, IServiceProvider services, Action onProgressCallback, CancellationToken token) + { + var dataSaubStatService = services.GetRequiredService(); + + if (dataSaubStatService != null ) + await dataSaubStatService.CreateStatAsync(Gap, onProgressCallback, token); + + } } diff --git a/AsbCloudInfrastructure/Background/PeriodicWorks/WorkToDeleteOldReports.cs b/AsbCloudInfrastructure/Background/PeriodicWorks/WorkToDeleteOldReports.cs index 5a91dedd..7a6a6922 100644 --- a/AsbCloudInfrastructure/Background/PeriodicWorks/WorkToDeleteOldReports.cs +++ b/AsbCloudInfrastructure/Background/PeriodicWorks/WorkToDeleteOldReports.cs @@ -4,31 +4,30 @@ using System; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Background.PeriodicWorks -{ - /// - /// Задача по удалению загруженных отчетов - /// - public class WorkToDeleteOldReports : Work - { - public WorkToDeleteOldReports() - : base("work to delete reports older than 30 days") - { - Timeout = TimeSpan.FromMinutes(10); - } +namespace AsbCloudInfrastructure.Background.PeriodicWorks; - /// - /// Удаление отчетов, загруженных ранее 30 дней от текущей даты - /// - /// - /// - /// - /// - /// - protected override async Task Action(string id, IServiceProvider services, Action onProgressCallback, CancellationToken token) - { - var reportService = services.GetRequiredService(); - await reportService.DeleteAllOldReportsAsync(TimeSpan.FromDays(30), token); - } +/// +/// Задача по удалению загруженных отчетов +/// +public class WorkToDeleteOldReports : Work +{ + public WorkToDeleteOldReports() + : base("work to delete reports older than 30 days") + { + Timeout = TimeSpan.FromMinutes(10); + } + + /// + /// Удаление отчетов, загруженных ранее 30 дней от текущей даты + /// + /// + /// + /// + /// + /// + protected override async Task Action(string id, IServiceProvider services, Action onProgressCallback, CancellationToken token) + { + var reportService = services.GetRequiredService(); + await reportService.DeleteAllOldReportsAsync(TimeSpan.FromDays(30), token); } } diff --git a/AsbCloudInfrastructure/Background/WorkToSendEmail.cs b/AsbCloudInfrastructure/Background/WorkToSendEmail.cs index d4b20ceb..7ed51928 100644 --- a/AsbCloudInfrastructure/Background/WorkToSendEmail.cs +++ b/AsbCloudInfrastructure/Background/WorkToSendEmail.cs @@ -6,39 +6,38 @@ using System; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Background +namespace AsbCloudInfrastructure.Background; + +/// +/// Класс для отправки email +/// +internal class WorkToSendEmail : Work { - /// - /// Класс для отправки email - /// - internal class WorkToSendEmail : Work + private NotificationDto notification; + + public WorkToSendEmail(NotificationDto notification) : base(MakeWorkId(notification)) { - private NotificationDto notification; + this.notification = notification; + } - public WorkToSendEmail(NotificationDto notification) : base(MakeWorkId(notification)) - { - this.notification = notification; - } + protected override async Task Action(string id, IServiceProvider services, Action onProgressCallback, CancellationToken token) + { + var notificationService = services.GetRequiredService(); + var notificationRepository = services.GetRequiredService(); - protected override async Task Action(string id, IServiceProvider services, Action onProgressCallback, CancellationToken token) - { - var notificationService = services.GetRequiredService(); - var notificationRepository = services.GetRequiredService(); + await notificationService.SendAsync(notification, token); - await notificationService.SendAsync(notification, token); + notification.SentDate = DateTimeOffset.UtcNow; + await notificationRepository.UpdateAsync(notification, token); - notification.SentDate = DateTimeOffset.UtcNow; - await notificationRepository.UpdateAsync(notification, token); - - } + } - private static string MakeWorkId(NotificationDto notification) - { - var hash = notification.IdUser.GetHashCode(); - hash ^= notification.Title.GetHashCode(); - hash ^= notification.Message.GetHashCode(); - return hash.ToString("x"); - } + private static string MakeWorkId(NotificationDto notification) + { + var hash = notification.IdUser.GetHashCode(); + hash ^= notification.Title.GetHashCode(); + hash ^= notification.Message.GetHashCode(); + return hash.ToString("x"); } } diff --git a/AsbCloudInfrastructure/DateTimeExtensions.cs b/AsbCloudInfrastructure/DateTimeExtensions.cs index 61b1c72c..c9386a55 100644 --- a/AsbCloudInfrastructure/DateTimeExtensions.cs +++ b/AsbCloudInfrastructure/DateTimeExtensions.cs @@ -2,84 +2,80 @@ using System; -namespace AsbCloudInfrastructure +namespace AsbCloudInfrastructure; + +public static class DateTimeExtensions { - public static class DateTimeExtensions + /// + /// Приветсти к UTC из времени куста + /// + /// + /// + /// + public static DateTimeOffset ToUtcDateTimeOffset(this DateTime date, double remoteTimezoneOffsetHours) { - /// - /// Приветсти к UTC из времени куста - /// - /// - /// - /// - public static DateTimeOffset ToUtcDateTimeOffset(this DateTime date, double remoteTimezoneOffsetHours) + if (date == default) + return new DateTimeOffset(); + + var dateUtc = date.Kind switch { - if (date == default) - return new DateTimeOffset(); + DateTimeKind.Local => date.ToUniversalTime(), + DateTimeKind.Unspecified => DateTime.SpecifyKind(date.AddHours(-remoteTimezoneOffsetHours), DateTimeKind.Utc), + _ => date, + }; + return new DateTimeOffset(dateUtc); + } - var dateUtc = date.Kind switch - { - DateTimeKind.Local => date.ToUniversalTime(), - DateTimeKind.Unspecified => DateTime.SpecifyKind(date.AddHours(-remoteTimezoneOffsetHours), DateTimeKind.Utc), - _ => date, - }; - return new DateTimeOffset(dateUtc); - } + /// + /// Привести ко времени куста из utc + /// + /// + /// + /// + public static DateTime ToRemoteDateTime(this DateTimeOffset date, double remoteTimezoneOffsetHours) + { + if (date == default) + return new DateTime(0, DateTimeKind.Unspecified); + var dateTz = date.ToOffset(TimeSpan.FromHours(remoteTimezoneOffsetHours)); + return dateTz.DateTime; + } - /// - /// Привести ко времени куста из utc - /// - /// - /// - /// - public static DateTime ToRemoteDateTime(this DateTimeOffset date, double remoteTimezoneOffsetHours) + /// + /// Поиск индекса близкого к value значения в span. + /// Элементы в span должны быть отсортированы по возрастанию по полю propertyGetter. + /// + /// + /// + /// + /// метод получения свойства из объекта класса T + /// искомое значение + /// максимальное кол-во итераций. Прим.: + /// в span из 4000 записей достаточно 9-ти итераций + /// 8_000 => 10 итераций; + /// 16_000 => 11; + /// ... + /// 256_000 => 15; + /// При недостаточном кол-ве итераций индекс может оказаться близко, но это будет не ближайшее значение + /// + /// + public static int BinarySearch(this Span span, Func propertyGetter, TProp value, int maxIterations = 16) + where TProp : IComparable + { + if (span.Length < 2 || --maxIterations < 0) + return 0; + + var indexOfMiddle = span.Length >> 1; + + var comparison = value.CompareTo(propertyGetter(span[indexOfMiddle])); + + if (comparison > 0) { - if (date == default) - return new DateTime(0, DateTimeKind.Unspecified); - - var dateTz = date.ToOffset(TimeSpan.FromHours(remoteTimezoneOffsetHours)); - - var result = DateTime.SpecifyKind(dateTz.DateTime, DateTimeKind.Unspecified); - return result; - } - - /// - /// Поиск индекса близкого к value значения в span. - /// Элементы в span должны быть отсортированы по возрастанию по полю propertyGetter. - /// - /// - /// - /// - /// метод получения свойства из объекта класса T - /// искомое значение - /// максимальное кол-во итераций. Прим.: - /// в span из 4000 записей достаточно 9-ти итераций - /// 8_000 => 10 итераций; - /// 16_000 => 11; - /// ... - /// 256_000 => 15; - /// При недостаточном кол-ве итераций индекс может оказаться близко, но это будет не ближайшее значение - /// - /// - public static int BinarySearch(this Span span, Func propertyGetter, TProp value, int maxIterations = 16) - where TProp : IComparable - { - if (span.Length < 2 || --maxIterations < 0) - return 0; - - var indexOfMiddle = span.Length >> 1; - - var comparison = value.CompareTo(propertyGetter(span[indexOfMiddle])); - - if (comparison > 0) - { - var index = indexOfMiddle + 1 + BinarySearch(span[(indexOfMiddle + 1)..], propertyGetter, value, maxIterations); - return index < span.Length ? index : span.Length - 1; - } - else if (comparison < 0) - return BinarySearch(span[..(indexOfMiddle)], propertyGetter, value, maxIterations); - else //if (comparison == 0) - return indexOfMiddle; + var index = indexOfMiddle + 1 + BinarySearch(span[(indexOfMiddle + 1)..], propertyGetter, value, maxIterations); + return index < span.Length ? index : span.Length - 1; } + else if (comparison < 0) + return BinarySearch(span[..(indexOfMiddle)], propertyGetter, value, maxIterations); + else //if (comparison == 0) + return indexOfMiddle; } } diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index b3943a6c..a6a89ab5 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -48,516 +48,515 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using System; -namespace AsbCloudInfrastructure +namespace AsbCloudInfrastructure; + +public static class DependencyInjection { - public static class DependencyInjection + public static void MapsterSetup() { - public static void MapsterSetup() - { - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .Ignore(source => source.Author) - .Ignore(source => source.Well); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .Ignore(source => source.Author) + .Ignore(source => source.Well); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .Ignore(source => source.OperationCategory); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .Ignore(source => source.OperationCategory); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .Ignore(source => source.Driller); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .Ignore(source => source.Driller); #pragma warning disable CS8603 // Possible null reference return. - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .Ignore(dst => dst.Author, dst => dst.Editor); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .Ignore(dst => dst.Author, dst => dst.Editor); #pragma warning restore CS8603 // Possible null reference return. - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .MapWith((source) => source.DateTime); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .MapWith((source) => source.DateTime); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .MapWith((source) => source == default ? new DateTime(0, DateTimeKind.Utc) : source); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .MapWith((source) => source == default ? new DateTime(0, DateTimeKind.Utc) : source); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .MapWith((source) => source.MakeTimeOnly()); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .MapWith((source) => source.MakeTimeOnly()); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .MapWith((source) => new(source)); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .MapWith((source) => new(source)); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .MapWith((source) => new(source)); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .MapWith((source) => new(source)); #pragma warning disable CS8603 // Possible null reference return. - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .Ignore(dst => dst.Cluster, - dst => dst.RelationCompaniesWells, - dst => dst.Telemetry, - dst => dst.WellComposites, - dst => dst.WellCompositeSrcs, - dst => dst.WellOperations, - dst => dst.WellType); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .Ignore(dst => dst.Cluster, + dst => dst.RelationCompaniesWells, + dst => dst.Telemetry, + dst => dst.WellComposites, + dst => dst.WellCompositeSrcs, + dst => dst.WellOperations, + dst => dst.WellType); #pragma warning restore CS8603 // Possible null reference return. - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .Ignore(dst => dst.Deposit, - dst => dst.Wells); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .Ignore(dst => dst.Deposit, + dst => dst.Wells); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType(); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType(); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType(); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType(); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .Ignore(dst => dst.NotificationCategory, - dst => dst.User); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .Ignore(dst => dst.NotificationCategory, + dst => dst.User); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .Map(dest => dest.DurationHours, src => new PlanFactDto() - { - Plan = src.DurationHoursPlan, - Fact = src.DurationHoursFact - }); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .Map(dest => dest.DurationHours, src => new PlanFactDto() + { + Plan = src.DurationHoursPlan, + Fact = src.DurationHoursFact + }); - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .Map(dest => dest.WellDepth, src => new PlanFactDto() - { - Plan = src.WellDepthPlan - }); + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .Map(dest => dest.WellDepth, src => new PlanFactDto() + { + Plan = src.WellDepthPlan + }); - TypeAdapterConfig>.NewConfig() - .Include>() - .Map(dest => dest, src => new ChangeLogDto() - { - Item = src.Adapt() - }); + TypeAdapterConfig>.NewConfig() + .Include>() + .Map(dest => dest, src => new ChangeLogDto() + { + Item = src.Adapt() + }); - TypeAdapterConfig>.NewConfig() - .Include>() - .Map(dest => dest, src => new ChangeLogDto() - { - Item = src.Adapt() - }); + TypeAdapterConfig>.NewConfig() + .Include>() + .Map(dest => dest, src => new ChangeLogDto() + { + Item = src.Adapt() + }); - TypeAdapterConfig>.NewConfig() - .Include>() - .Map(dest => dest, src => new ChangeLogDto() - { - Item = src.Adapt() - }); + TypeAdapterConfig>.NewConfig() + .Include>() + .Map(dest => dest, src => new ChangeLogDto() + { + Item = src.Adapt() + }); - TypeAdapterConfig>.NewConfig() - .Include>() - .Map(dest => dest, src => new ChangeLogDto() - { - Item = src.Adapt() - }); + TypeAdapterConfig>.NewConfig() + .Include>() + .Map(dest => dest, src => new ChangeLogDto() + { + Item = src.Adapt() + }); - TypeAdapterConfig>.NewConfig() - .Include>() - .Map(dest => dest, src => new ChangeLogDto() - { - Item = src.Adapt() - }); + TypeAdapterConfig>.NewConfig() + .Include>() + .Map(dest => dest, src => new ChangeLogDto() + { + Item = src.Adapt() + }); - TypeAdapterConfig>.NewConfig() - .Include>() - .Map(dest => dest, src => new ChangeLogDto() - { - Item = src.Adapt() - }); + TypeAdapterConfig>.NewConfig() + .Include>() + .Map(dest => dest, src => new ChangeLogDto() + { + Item = src.Adapt() + }); - TypeAdapterConfig>.NewConfig() - .Include>() - .Map(dest => dest, src => new ChangeLogDto() - { - Item = src.Adapt() - }); + TypeAdapterConfig>.NewConfig() + .Include>() + .Map(dest => dest, src => new ChangeLogDto() + { + Item = src.Adapt() + }); - TypeAdapterConfig>.NewConfig() - .Include>() - .Map(dest => dest, src => new ChangeLogDto() - { - Item = src.Adapt() - }); + TypeAdapterConfig>.NewConfig() + .Include>() + .Map(dest => dest, src => new ChangeLogDto() + { + Item = src.Adapt() + }); - TypeAdapterConfig>.NewConfig() - .Include>() - .Map(dest => dest, src => new ChangeLogDto() - { - Item = src.Adapt() - }); + TypeAdapterConfig>.NewConfig() + .Include>() + .Map(dest => dest, src => new ChangeLogDto() + { + Item = src.Adapt() + }); - TypeAdapterConfig>.NewConfig() - .Include>() - .Map(dest => dest, src => new ChangeLogDto() - { - Item = src.Adapt() - }); + TypeAdapterConfig>.NewConfig() + .Include>() + .Map(dest => dest, src => new ChangeLogDto() + { + Item = src.Adapt() + }); - TypeAdapterConfig>.NewConfig() - .Include>() - .Map(dest => dest, src => new ChangeLogDto() - { - Item = src.Adapt() - }); + TypeAdapterConfig>.NewConfig() + .Include>() + .Map(dest => dest, src => new ChangeLogDto() + { + Item = src.Adapt() + }); - TypeAdapterConfig>.NewConfig() - .Include>() - .Map(dest => dest, src => new ChangeLogDto() - { - Item = src.Adapt() - }); + TypeAdapterConfig>.NewConfig() + .Include>() + .Map(dest => dest, src => new ChangeLogDto() + { + Item = src.Adapt() + }); - TypeAdapterConfig>.NewConfig() - .Include>() - .Map(dest => dest, src => new ChangeLogDto() - { - Item = src.Adapt() - }); + TypeAdapterConfig>.NewConfig() + .Include>() + .Map(dest => dest, src => new ChangeLogDto() + { + Item = src.Adapt() + }); - TypeAdapterConfig>.NewConfig() - .Include>() - .Map(dest => dest, src => new ChangeLogDto() - { - Item = src.Adapt() - }); + TypeAdapterConfig>.NewConfig() + .Include>() + .Map(dest => dest, src => new ChangeLogDto() + { + Item = src.Adapt() + }); - TypeAdapterConfig>.NewConfig() - .Include>() - .Map(dest => dest, src => new ChangeLogDto() - { - Item = src.Adapt() - }); + TypeAdapterConfig>.NewConfig() + .Include>() + .Map(dest => dest, src => new ChangeLogDto() + { + Item = src.Adapt() + }); - TypeAdapterConfig>.NewConfig() - .Include>() - .Map(dest => dest, src => new ChangeLogDto() - { - Item = src.Adapt() - }); + TypeAdapterConfig>.NewConfig() + .Include>() + .Map(dest => dest, src => new ChangeLogDto() + { + Item = src.Adapt() + }); - TypeAdapterConfig>.NewConfig() - .Include>() - .Map(dest => dest, src => new ChangeLogDto() - { - Item = src.Adapt() - }); + TypeAdapterConfig>.NewConfig() + .Include>() + .Map(dest => dest, src => new ChangeLogDto() + { + Item = src.Adapt() + }); - TypeAdapterConfig>.NewConfig() - .Include>() - .Map(dest => dest, src => new ChangeLogDto() - { - Item = src.Adapt() - }); - } + TypeAdapterConfig>.NewConfig() + .Include>() + .Map(dest => dest, src => new ChangeLogDto() + { + Item = src.Adapt() + }); + } - public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration) - { - MapsterSetup(); - string connectionStringName = "DefaultConnection"; + public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration) + { + MapsterSetup(); + string connectionStringName = "DefaultConnection"; #if DEBUG - connectionStringName = "DebugConnection"; + connectionStringName = "DebugConnection"; #endif - services.AddDbContext(options => - options.UseNpgsql(configuration.GetConnectionString(connectionStringName))); + services.AddDbContext(options => + options.UseNpgsql(configuration.GetConnectionString(connectionStringName))); - services.AddMemoryCache(); - services.AddScoped(provider => provider.GetRequiredService()); + services.AddMemoryCache(); + services.AddScoped(provider => provider.GetRequiredService()); - services.AddSingleton(new WitsInfoService()); - services.AddSingleton>(provider => - TelemetryDataCache.GetInstance(provider)); - services.AddSingleton>(provider => - TelemetryDataCache.GetInstance(provider)); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(provider => ReduceSamplingService.GetInstance(configuration)); + services.AddSingleton(new WitsInfoService()); + services.AddSingleton>(provider => + TelemetryDataCache.GetInstance(provider)); + services.AddSingleton>(provider => + TelemetryDataCache.GetInstance(provider)); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(provider => ReduceSamplingService.GetInstance(configuration)); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddScoped(); - services.AddTransient(); - services.AddTransient(); - services.AddScoped(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient, CrudWellRelatedRepositoryBase>(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddScoped(); + services.AddTransient(); + services.AddTransient(); + services.AddScoped(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient, CrudWellRelatedRepositoryBase>(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - services.AddTransient< - IChangeLogRepository, - ProcessMapPlanBaseRepository>(); + services.AddTransient< + IChangeLogRepository, + ProcessMapPlanBaseRepository>(); - services.AddTransient< - IChangeLogRepository, - ProcessMapPlanBaseRepository>(); + services.AddTransient< + IChangeLogRepository, + ProcessMapPlanBaseRepository>(); - services.AddTransient< - IChangeLogRepository, - ProcessMapPlanBaseRepository>(); + services.AddTransient< + IChangeLogRepository, + ProcessMapPlanBaseRepository>(); - services.AddTransient< - IChangeLogRepository, - ProcessMapPlanBaseRepository>(); + services.AddTransient< + IChangeLogRepository, + ProcessMapPlanBaseRepository>(); - services.AddTransient< - IChangeLogRepository, - ProcessMapPlanBaseRepository>(); + services.AddTransient< + IChangeLogRepository, + ProcessMapPlanBaseRepository>(); - services.AddTransient< - IChangeLogRepository, - ProcessMapPlanBaseRepository>(); + services.AddTransient< + IChangeLogRepository, + ProcessMapPlanBaseRepository>(); - services.AddTransient< - IChangeLogRepository, - ProcessMapPlanBaseRepository>(); + services.AddTransient< + IChangeLogRepository, + ProcessMapPlanBaseRepository>(); - services.AddTransient< - IChangeLogRepository, - ProcessMapPlanBaseRepository>(); + services.AddTransient< + IChangeLogRepository, + ProcessMapPlanBaseRepository>(); - services.AddTransient< - IChangeLogRepository, - ProcessMapPlanBaseRepository>(); + services.AddTransient< + IChangeLogRepository, + ProcessMapPlanBaseRepository>(); - services.AddTransient< - IChangeLogRepository, - ProcessMapPlanBaseRepository>(); + services.AddTransient< + IChangeLogRepository, + ProcessMapPlanBaseRepository>(); - services.AddTransient< - IChangeLogRepository, - ProcessMapPlanBaseRepository>(); + services.AddTransient< + IChangeLogRepository, + ProcessMapPlanBaseRepository>(); - services.AddTransient< - IChangeLogRepository, - ProcessMapPlanBaseRepository>(); + services.AddTransient< + IChangeLogRepository, + ProcessMapPlanBaseRepository>(); - services.AddTransient< - IChangeLogRepository, - ProcessMapPlanBaseRepository>(); + services.AddTransient< + IChangeLogRepository, + ProcessMapPlanBaseRepository>(); - services.AddTransient< - IChangeLogRepository, - ProcessMapPlanBaseRepository>(); + services.AddTransient< + IChangeLogRepository, + ProcessMapPlanBaseRepository>(); - services.AddTransient< - IChangeLogRepository, - ProcessMapPlanBaseRepository>(); + services.AddTransient< + IChangeLogRepository, + ProcessMapPlanBaseRepository>(); - services.AddTransient< - IChangeLogRepository, - ProcessMapPlanBaseRepository>(); + services.AddTransient< + IChangeLogRepository, + ProcessMapPlanBaseRepository>(); - services.AddTransient< - IChangeLogRepository, - ProcessMapPlanBaseRepository>(); + services.AddTransient< + IChangeLogRepository, + ProcessMapPlanBaseRepository>(); - services.AddTransient< - IChangeLogRepository, - ProcessMapPlanBaseRepository>(); + services.AddTransient< + IChangeLogRepository, + ProcessMapPlanBaseRepository>(); - services.AddTransient(); + services.AddTransient(); - services.AddTransient(); + services.AddTransient(); - services.AddTransient(); + services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient, CrudCacheRepositoryBase>(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient, CrudCacheRepositoryBase>(); + services.AddTransient(); + services.AddTransient(); - // admin crud services: - services.AddTransient, CrudCacheRepositoryBase>(s => - new CrudCacheRepositoryBase( - s.GetRequiredService(), - s.GetRequiredService(), - dbSet => dbSet.Include(t => t.Well))); // может быть включен в сервис TelemetryService - services.AddTransient, CrudCacheRepositoryBase>(s => - new CrudCacheRepositoryBase( - s.GetRequiredService(), - s.GetRequiredService(), - dbSet => dbSet.Include(d => d.Clusters) - .ThenInclude(c => c.Wells))); - services.AddTransient, CrudCacheRepositoryBase>(s => - new CrudCacheRepositoryBase( - s.GetRequiredService(), - s.GetRequiredService(), - dbSet => dbSet.Include(c => c.CompanyType))); + // admin crud services: + services.AddTransient, CrudCacheRepositoryBase>(s => + new CrudCacheRepositoryBase( + s.GetRequiredService(), + s.GetRequiredService(), + dbSet => dbSet.Include(t => t.Well))); // может быть включен в сервис TelemetryService + services.AddTransient, CrudCacheRepositoryBase>(s => + new CrudCacheRepositoryBase( + s.GetRequiredService(), + s.GetRequiredService(), + dbSet => dbSet.Include(d => d.Clusters) + .ThenInclude(c => c.Wells))); + services.AddTransient, CrudCacheRepositoryBase>(s => + new CrudCacheRepositoryBase( + s.GetRequiredService(), + s.GetRequiredService(), + dbSet => dbSet.Include(c => c.CompanyType))); - services.AddTransient, CrudCacheRepositoryBase>(); - services.AddTransient, CrudCacheRepositoryBase>(s => - new CrudCacheRepositoryBase( - s.GetRequiredService(), - s.GetRequiredService(), - dbSet => dbSet - .Include(c => c.Wells) - .Include(c => c.Deposit))); // может быть включен в сервис ClusterService + services.AddTransient, CrudCacheRepositoryBase>(); + services.AddTransient, CrudCacheRepositoryBase>(s => + new CrudCacheRepositoryBase( + s.GetRequiredService(), + s.GetRequiredService(), + dbSet => dbSet + .Include(c => c.Wells) + .Include(c => c.Deposit))); // может быть включен в сервис ClusterService - services.AddTransient, CrudCacheRepositoryBase>(); + services.AddTransient, CrudCacheRepositoryBase>(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - services.AddTransient>(); - services.AddTransient>(); - services.AddTransient>(); - services.AddTransient>(); - services.AddTransient>(); - services.AddTransient>(); - services.AddTransient>(); - services.AddTransient>(); - services.AddTransient>(); - services.AddTransient>(); - services.AddTransient>(); - services.AddTransient>(); - services.AddTransient>(); - services.AddTransient>(); - services.AddTransient>(); - services.AddTransient>(); - services.AddTransient>(); - services.AddTransient>(); + services.AddTransient>(); + services.AddTransient>(); + services.AddTransient>(); + services.AddTransient>(); + services.AddTransient>(); + services.AddTransient>(); + services.AddTransient>(); + services.AddTransient>(); + services.AddTransient>(); + services.AddTransient>(); + services.AddTransient>(); + services.AddTransient>(); + services.AddTransient>(); + services.AddTransient>(); + services.AddTransient>(); + services.AddTransient>(); + services.AddTransient>(); + services.AddTransient>(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient, TrajectoryEditableRepository>(); - services.AddTransient, TrajectoryEditableRepository>(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient, CrudCacheRepositoryBase>(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient, TrajectoryEditableRepository>(); + services.AddTransient, TrajectoryEditableRepository>(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient, CrudCacheRepositoryBase>(); - services.AddTransient, CrudCacheRepositoryBase>(); + services.AddTransient, CrudCacheRepositoryBase>(); - services.AddTransient, CrudCacheRepositoryBase>(); + services.AddTransient, CrudCacheRepositoryBase>(); - // TelemetryData services - services.AddTransient(); - services.AddTransient, TelemetryDataSpinService>(); + // TelemetryData services + services.AddTransient(); + services.AddTransient, TelemetryDataSpinService>(); - // Wits - services.AddTransient, WitsRecordRepository>(); - services.AddTransient, WitsRecordRepository>(); - services.AddTransient, WitsRecordRepository>(); - services.AddTransient, WitsRecordRepository>(); - services.AddTransient, WitsRecordRepository>(); - services.AddTransient, WitsRecordRepository>(); + // Wits + services.AddTransient, WitsRecordRepository>(); + services.AddTransient, WitsRecordRepository>(); + services.AddTransient, WitsRecordRepository>(); + services.AddTransient, WitsRecordRepository>(); + services.AddTransient, WitsRecordRepository>(); + services.AddTransient, WitsRecordRepository>(); - services.AddTransient(); - services.AddTransient, DrillTestReportMakerService>(); + services.AddTransient(); + services.AddTransient, DrillTestReportMakerService>(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient, CrudRepositoryBase>(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient, CrudRepositoryBase>(); - services.AddTransient(); + services.AddTransient(); - services.AddTransient(); + services.AddTransient(); - services.AddTransient(); + services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - services.AddTransient, CrudWellRelatedRepositoryBase>(); + services.AddTransient, CrudWellRelatedRepositoryBase>(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); - return services; - } + return services; } } diff --git a/AsbCloudInfrastructure/LinqExtensions.cs b/AsbCloudInfrastructure/LinqExtensions.cs index 061cc60a..eb54693e 100644 --- a/AsbCloudInfrastructure/LinqExtensions.cs +++ b/AsbCloudInfrastructure/LinqExtensions.cs @@ -4,36 +4,35 @@ using System; using System.Collections.Generic; using System.Linq; -namespace AsbCloudInfrastructure +namespace AsbCloudInfrastructure; + +public static class LinqExtensions { - public static class LinqExtensions + public static TProp? MaxOrDefault(this IEnumerable enumerable, Func getter) + where TProp : struct { - public static TProp? MaxOrDefault(this IEnumerable enumerable, Func getter) - where TProp : struct - { - var value = MaxByOrDefault(enumerable, getter); - if (value is null) - return null; - return getter(value); - } + var value = MaxByOrDefault(enumerable, getter); + if (value is null) + return null; + return getter(value); + } - public static TObj? MaxByOrDefault(this IEnumerable enumerable, Func getter) - { - return enumerable.OrderByDescending(getter).FirstOrDefault(); - } + public static TObj? MaxByOrDefault(this IEnumerable enumerable, Func getter) + { + return enumerable.OrderByDescending(getter).FirstOrDefault(); + } - public static TProp? MinOrDefault(this IEnumerable enumerable, Func getter) - where TProp : struct - { - var value = MinByOrDefault(enumerable, getter); - if (value is null) - return null; - return getter(value); - } + public static TProp? MinOrDefault(this IEnumerable enumerable, Func getter) + where TProp : struct + { + var value = MinByOrDefault(enumerable, getter); + if (value is null) + return null; + return getter(value); + } - public static TObj? MinByOrDefault(this IEnumerable enumerable, Func getter) - { - return enumerable.OrderBy(getter).FirstOrDefault(); - } + public static TObj? MinByOrDefault(this IEnumerable enumerable, Func getter) + { + return enumerable.OrderBy(getter).FirstOrDefault(); } } diff --git a/AsbCloudInfrastructure/MemoryCacheExtentions.cs b/AsbCloudInfrastructure/MemoryCacheExtentions.cs index a8d89010..1abde63d 100644 --- a/AsbCloudInfrastructure/MemoryCacheExtentions.cs +++ b/AsbCloudInfrastructure/MemoryCacheExtentions.cs @@ -6,106 +6,105 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure +namespace AsbCloudInfrastructure; + + +public static class MemoryCacheExtentions { + private static readonly TimeSpan CacheOlescence = TimeSpan.FromMinutes(5); - public static class MemoryCacheExtentions + /// + /// Создать кеш на основе асинхронного запроса к БД. + /// Ключ кеша - полное имя типа T. + /// + /// + /// + /// + /// + /// + public static Task> GetOrCreateBasicAsync(this IMemoryCache memoryCache, IQueryable query, CancellationToken token) + where T : class { - private static readonly TimeSpan CacheOlescence = TimeSpan.FromMinutes(5); - - /// - /// Создать кеш на основе асинхронного запроса к БД. - /// Ключ кеша - полное имя типа T. - /// - /// - /// - /// - /// - /// - public static Task> GetOrCreateBasicAsync(this IMemoryCache memoryCache, IQueryable query, CancellationToken token) - where T : class + var getter = async (CancellationToken token) => { - var getter = async (CancellationToken token) => - { - var entities = await query - .AsNoTracking() - .ToArrayAsync(token); - return entities.AsEnumerable(); - }; - return memoryCache.GetOrCreateBasicAsync(getter, token); - } - - /// - /// Создать кеш на основе результата выполнения произвольной асинхронной функции. - /// Ключ кеша - полное имя типа T. - /// - /// - /// - /// - /// - /// - public static Task> GetOrCreateBasicAsync(this IMemoryCache memoryCache, Func>> getterAsync, CancellationToken token) - { - var key = typeof(T).FullName!; - var cache = memoryCache.GetOrCreateAsync(key, async (cacheEntry) => - { - cacheEntry.AbsoluteExpirationRelativeToNow = CacheOlescence; - cacheEntry.SlidingExpiration = CacheOlescence; - var entities = await getterAsync(token); - return entities; - }); - return cache!; - } - - /// - /// Создать кеш на основе запроса к БД. - /// Ключ кеша - полное имя типа T. - /// - /// - /// - /// - /// - public static IEnumerable GetOrCreateBasic(this IMemoryCache memoryCache, IQueryable query) - where T : class - { - var getter = () => query + var entities = await query .AsNoTracking() - .ToArray(); - return memoryCache.GetOrCreateBasic(getter); - } + .ToArrayAsync(token); + return entities.AsEnumerable(); + }; + return memoryCache.GetOrCreateBasicAsync(getter, token); + } - /// - /// Создать кеш на основе результата выполнения произвольной функции. - /// Ключ кеша - полное имя типа T. - /// - /// - /// - /// - /// - public static IEnumerable GetOrCreateBasic(this IMemoryCache memoryCache, Func> getter) + /// + /// Создать кеш на основе результата выполнения произвольной асинхронной функции. + /// Ключ кеша - полное имя типа T. + /// + /// + /// + /// + /// + /// + public static Task> GetOrCreateBasicAsync(this IMemoryCache memoryCache, Func>> getterAsync, CancellationToken token) + { + var key = typeof(T).FullName!; + var cache = memoryCache.GetOrCreateAsync(key, async (cacheEntry) => { - var key = typeof(T).FullName!; - var cache = memoryCache.GetOrCreate(key, cacheEntry => - { - cacheEntry.AbsoluteExpirationRelativeToNow = CacheOlescence; - cacheEntry.SlidingExpiration = CacheOlescence; - return getter(); - }); - return cache!; - } + cacheEntry.AbsoluteExpirationRelativeToNow = CacheOlescence; + cacheEntry.SlidingExpiration = CacheOlescence; + var entities = await getterAsync(token); + return entities; + }); + return cache!; + } - /// - /// Сбросить кеш. - /// Ключ кеша - полное имя типа T. - /// - /// - /// - public static void DropBasic(this IMemoryCache memoryCache) - where T : class + /// + /// Создать кеш на основе запроса к БД. + /// Ключ кеша - полное имя типа T. + /// + /// + /// + /// + /// + public static IEnumerable GetOrCreateBasic(this IMemoryCache memoryCache, IQueryable query) + where T : class + { + var getter = () => query + .AsNoTracking() + .ToArray(); + return memoryCache.GetOrCreateBasic(getter); + } + + /// + /// Создать кеш на основе результата выполнения произвольной функции. + /// Ключ кеша - полное имя типа T. + /// + /// + /// + /// + /// + public static IEnumerable GetOrCreateBasic(this IMemoryCache memoryCache, Func> getter) + { + var key = typeof(T).FullName!; + var cache = memoryCache.GetOrCreate(key, cacheEntry => { - var key = typeof(T).FullName!; + cacheEntry.AbsoluteExpirationRelativeToNow = CacheOlescence; + cacheEntry.SlidingExpiration = CacheOlescence; + return getter(); + }); + return cache!; + } - memoryCache.Remove(key); - } + /// + /// Сбросить кеш. + /// Ключ кеша - полное имя типа T. + /// + /// + /// + public static void DropBasic(this IMemoryCache memoryCache) + where T : class + { + var key = typeof(T).FullName!; + + memoryCache.Remove(key); } } diff --git a/AsbCloudInfrastructure/PredicateBuilder.cs b/AsbCloudInfrastructure/PredicateBuilder.cs index 423dec6f..a658e973 100644 --- a/AsbCloudInfrastructure/PredicateBuilder.cs +++ b/AsbCloudInfrastructure/PredicateBuilder.cs @@ -3,77 +3,76 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -namespace AsbCloudInfrastructure +namespace AsbCloudInfrastructure; + + +/// +/// stolen from https://github.com/lotosbin/BinbinPredicateBuilder +/// +public static class PredicateBuilder { + /// + /// Combines the first predicate with the second using the logical "and". + /// + public static Expression> And(this Expression> first, Expression> second) + { + return first.Compose(second, Expression.AndAlso); + } /// - /// stolen from https://github.com/lotosbin/BinbinPredicateBuilder + /// Combines the first predicate with the second using the logical "or". /// - public static class PredicateBuilder + public static Expression> Or(this Expression> first, Expression> second) { - /// - /// Combines the first predicate with the second using the logical "and". - /// - public static Expression> And(this Expression> first, Expression> second) + return first.Compose(second, Expression.OrElse); + } + + /// + /// Negates the predicate. + /// + public static Expression> Not(this Expression> expression) + { + var negated = Expression.Not(expression.Body); + return Expression.Lambda>(negated, expression.Parameters); + } + + private static Expression Compose(this Expression first, Expression second, Func merge) + { + var map = first.Parameters + .Select((f, i) => new { f, s = second.Parameters[i] }) + .ToDictionary(p => p.s, p => p.f); + + var tryReplaceParametr = (Expression node) => { - return first.Compose(second, Expression.AndAlso); + if (node is ParameterExpression parameter) + if (map.TryGetValue(parameter, out ParameterExpression? replacement)) + return replacement; + return node; + }; + + var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body); + return Expression.Lambda(merge(first.Body, secondBody), first.Parameters); + } + + class ParameterRebinder : ExpressionVisitor + { + private readonly Dictionary map; + + private ParameterRebinder(Dictionary map) + { + this.map = map; } - /// - /// Combines the first predicate with the second using the logical "or". - /// - public static Expression> Or(this Expression> first, Expression> second) + public static Expression ReplaceParameters(Dictionary map, Expression exp) { - return first.Compose(second, Expression.OrElse); + return new ParameterRebinder(map).Visit(exp); } - /// - /// Negates the predicate. - /// - public static Expression> Not(this Expression> expression) + protected override Expression VisitParameter(ParameterExpression parametr) { - var negated = Expression.Not(expression.Body); - return Expression.Lambda>(negated, expression.Parameters); - } - - private static Expression Compose(this Expression first, Expression second, Func merge) - { - var map = first.Parameters - .Select((f, i) => new { f, s = second.Parameters[i] }) - .ToDictionary(p => p.s, p => p.f); - - var tryReplaceParametr = (Expression node) => - { - if (node is ParameterExpression parameter) - if (map.TryGetValue(parameter, out ParameterExpression? replacement)) - return replacement; - return node; - }; - - var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body); - return Expression.Lambda(merge(first.Body, secondBody), first.Parameters); - } - - class ParameterRebinder : ExpressionVisitor - { - private readonly Dictionary map; - - private ParameterRebinder(Dictionary map) - { - this.map = map; - } - - public static Expression ReplaceParameters(Dictionary map, Expression exp) - { - return new ParameterRebinder(map).Visit(exp); - } - - protected override Expression VisitParameter(ParameterExpression parametr) - { - if (map.TryGetValue(parametr, out ParameterExpression? replacement)) - parametr = replacement; - return parametr; - } + if (map.TryGetValue(parametr, out ParameterExpression? replacement)) + parametr = replacement; + return parametr; } } } diff --git a/AsbCloudInfrastructure/ReportDataSourcePgCloud.cs b/AsbCloudInfrastructure/ReportDataSourcePgCloud.cs index 8c4333a6..eadb5093 100644 --- a/AsbCloudInfrastructure/ReportDataSourcePgCloud.cs +++ b/AsbCloudInfrastructure/ReportDataSourcePgCloud.cs @@ -6,180 +6,178 @@ using System; using System.Collections.Generic; using System.Linq; -namespace AsbCloudInfrastructure +namespace AsbCloudInfrastructure; + +public class ReportDataSourcePgCloud : IReportDataSource { - public class ReportDataSourcePgCloud : IReportDataSource + private const string DefaultTimezoneId = "Asia/Yekaterinburg"; + private readonly IAsbCloudDbContext context; + + private readonly int? idTelemetry; + private readonly WellInfoReport info; + + private readonly Dictionary events; + private readonly Dictionary users; + private readonly double timezoneOffset; + private readonly Dictionary categories = new Dictionary { - private const string DefaultTimezoneId = "Asia/Yekaterinburg"; - private readonly IAsbCloudDbContext context; + {1, "Авария"}, + {2, "Предупреждение"}, + {3, "Информация"}, + }; - private readonly int? idTelemetry; - private readonly WellInfoReport info; + public ReportDataSourcePgCloud(IAsbCloudDbContext context, int idWell) + { + this.context = context; - private readonly Dictionary events; - private readonly Dictionary users; - private readonly double timezoneOffset; - private readonly Dictionary categories = new Dictionary + var well = context.Wells + .Include(w => w.Cluster) + .ThenInclude(c => c.Deposit) + .Include(w => w.RelationCompaniesWells) + .ThenInclude(r => r.Company) + .Include(w => w.Telemetry) + .FirstOrDefault(w => w.Id == idWell) + ?? throw new ArgumentInvalidException(nameof(idWell), "idWell doesn`t exist"); + + idTelemetry = well?.IdTelemetry + ?? throw new ArgumentInvalidException(nameof(idWell), $"Well {idWell} doesn't contain telemetry"); + + events = context.TelemetryEvents + .Where(e => e.IdTelemetry == idTelemetry) + .ToDictionary(e => e.IdEvent, e => e); + + users = context.TelemetryUsers + .Where(u => u.IdTelemetry == idTelemetry) + .ToDictionary(u => u.IdUser, u => u); + + timezoneOffset = well!.Telemetry?.Info?.TimeZoneOffsetTotalHours ?? well.Timezone?.Hours ?? 5.0; + + info = new WellInfoReport { - {1, "Авария"}, - {2, "Предупреждение"}, - {3, "Информация"}, + Deposit = well.Cluster?.Deposit?.Caption, + Cluster = well.Cluster?.Caption, + Well = well.Caption, + Customer = well.RelationCompaniesWells.FirstOrDefault(c => c.Company.IdCompanyType == 1)?.Company.Caption, + DrillingStartDate = well.Telemetry?.Info?.DrillingStartDate.ToRemoteDateTime(timezoneOffset) ?? default, + TimeZoneId = well.Telemetry?.Info?.TimeZoneId ?? well.Timezone?.TimezoneId ?? DefaultTimezoneId, + TimeZoneOffsetTotalHours = timezoneOffset, }; + } - public ReportDataSourcePgCloud(IAsbCloudDbContext context, int idWell) - { - this.context = context; - - var well = context.Wells - .Include(w => w.Cluster) - .ThenInclude(c => c.Deposit) - .Include(w => w.RelationCompaniesWells) - .ThenInclude(r => r.Company) - .Include(w => w.Telemetry) - .FirstOrDefault(w => w.Id == idWell) - ?? throw new ArgumentInvalidException(nameof(idWell), "idWell doesn`t exist"); - - idTelemetry = well?.IdTelemetry - ?? throw new ArgumentInvalidException(nameof(idWell), $"Well {idWell} doesn't contain telemetry"); - - events = context.TelemetryEvents - .Where(e => e.IdTelemetry == idTelemetry) - .ToDictionary(e => e.IdEvent, e => e); - - users = context.TelemetryUsers - .Where(u => u.IdTelemetry == idTelemetry) - .ToDictionary(u => u.IdUser, u => u); - - timezoneOffset = well!.Telemetry?.Info?.TimeZoneOffsetTotalHours ?? well.Timezone?.Hours ?? 5.0; - - info = new WellInfoReport - { - Deposit = well.Cluster?.Deposit?.Caption, - Cluster = well.Cluster?.Caption, - Well = well.Caption, - Customer = well.RelationCompaniesWells.FirstOrDefault(c => c.Company.IdCompanyType == 1)?.Company.Caption, - DrillingStartDate = well.Telemetry?.Info?.DrillingStartDate.ToRemoteDateTime(timezoneOffset) ?? default, - TimeZoneId = well.Telemetry?.Info?.TimeZoneId ?? well.Timezone?.TimezoneId ?? DefaultTimezoneId, - TimeZoneOffsetTotalHours = timezoneOffset, - }; - } - - public AnalyzeResult Analyze() - { - // TODO: Replace by linq methods. - var messagesStat = (from item in context.TelemetryMessages - where item.IdTelemetry == idTelemetry - group item.DateTime by item.IdTelemetry into g - select new { min = g.Min(), max = g.Max(), count = g.Count() }) - .FirstOrDefault(); - - var dataStat = (from item in context.TelemetryDataSaub + public AnalyzeResult Analyze() + { + // TODO: Replace by linq methods. + var messagesStat = (from item in context.TelemetryMessages where item.IdTelemetry == idTelemetry group item.DateTime by item.IdTelemetry into g select new { min = g.Min(), max = g.Max(), count = g.Count() }) - .FirstOrDefault(); + .FirstOrDefault(); - var result = new AnalyzeResult - { - MinDate = dataStat?.min.UtcDateTime ?? messagesStat?.min.UtcDateTime ?? default, - MaxDate = dataStat?.max.UtcDateTime ?? messagesStat?.max.UtcDateTime ?? default, - MessagesCount = messagesStat?.count ?? 0, - }; - - return result; - } - - public IQueryable GetDataSaubItems(DateTime begin, DateTime end) - { - var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset); - var endUtc = end.ToUtcDateTimeOffset(timezoneOffset); - - var query = context.TelemetryDataSaub - .Where(d => d.IdTelemetry == idTelemetry - && d.DateTime >= beginUtc - && d.DateTime <= endUtc) - .OrderBy(d => d.DateTime) - .Select(d => new DataSaubReport - { - Date = d.DateTime.DateTime.AddHours(timezoneOffset), - Mode = d.Mode, - WellDepth = d.WellDepth, - BitDepth = d.BitDepth, - BlockPosition = d.BlockPosition, - BlockSpeed = d.BlockSpeed, - BlockSpeedSp = d.BlockSpeedSp, - BlockSpeedSpDevelop = d.BlockSpeedSpDevelop, - Pressure = d.Pressure, - PressureSp = d.PressureSp, - AxialLoad = d.AxialLoad, - AxialLoadSp = d.AxialLoadSp, - AxialLoadLimitMax = d.AxialLoadLimitMax, - HookWeight = d.HookWeight, - RotorTorque = d.RotorTorque, - RotorTorqueSp = d.RotorTorqueSp, - RotorSpeed = d.RotorSpeed, - Flow = d.Flow, - PressureSpDevelop = d.PressureSpDevelop, - IdFeedRegulator = d.IdFeedRegulator, - Pump0Flow = d.Pump0Flow, - Pump1Flow = d.Pump1Flow, - Pump2Flow = d.Pump2Flow, - - }); - return query; - } - - public IQueryable GetDataSpinItems(DateTime begin, DateTime end) - { - var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset); - var endUtc = end.ToUtcDateTimeOffset(timezoneOffset); - - var query = context.TelemetryDataSpin - .Where(d => d.IdTelemetry == idTelemetry - && d.DateTime >= beginUtc - && d.DateTime <= endUtc) - .OrderBy(d => d.DateTime) - .Select(d => new DataSpinReport - { - Date = d.DateTime.DateTime.AddHours(timezoneOffset), - Mode = d.Mode, - IsWorkingSpinMaster = (d.State != 0 && d.State != 5 && d.State != 6 && d.State != 7), - IsWorkingTorqueMaster = (d.State == 7 && (d.Mode & 2) > 0), - }); - return query; - } - - public IQueryable GetMessages(DateTime begin, DateTime end) - { - var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset); - var endUtc = end.ToUtcDateTimeOffset(timezoneOffset); - - var query = from item in context.TelemetryMessages + var dataStat = (from item in context.TelemetryDataSaub where item.IdTelemetry == idTelemetry - && item.DateTime >= beginUtc - && item.DateTime <= endUtc - orderby item.DateTime - select new MessageReport - { - Id = item.Id, - Date = item.DateTime.DateTime, - Category = events.GetValueOrDefault(item.IdEvent) == null - ? $"" - : categories[events[item.IdEvent].IdCategory], - User = item.IdTelemetryUser == null - ? "" - : users.GetValueOrDefault((int)item.IdTelemetryUser) == null - ? $"User id{item.IdTelemetryUser}" - : users[(int)item.IdTelemetryUser].MakeDisplayName(), - Text = events.GetValueOrDefault(item.IdEvent) == null - ? $"Событие {item.IdEvent} {item.Arg0} {item.Arg1} {item.Arg2} {item.Arg3}" - : events[item.IdEvent].MakeMessageText(item) - }; - return query; - } + group item.DateTime by item.IdTelemetry into g + select new { min = g.Min(), max = g.Max(), count = g.Count() }) + .FirstOrDefault(); - public WellInfoReport GetWellInfo() - => info; + var result = new AnalyzeResult + { + MinDate = dataStat?.min.UtcDateTime ?? messagesStat?.min.UtcDateTime ?? default, + MaxDate = dataStat?.max.UtcDateTime ?? messagesStat?.max.UtcDateTime ?? default, + MessagesCount = messagesStat?.count ?? 0, + }; + + return result; } + public IQueryable GetDataSaubItems(DateTime begin, DateTime end) + { + var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset); + var endUtc = end.ToUtcDateTimeOffset(timezoneOffset); + + var query = context.TelemetryDataSaub + .Where(d => d.IdTelemetry == idTelemetry + && d.DateTime >= beginUtc + && d.DateTime <= endUtc) + .OrderBy(d => d.DateTime) + .Select(d => new DataSaubReport + { + Date = d.DateTime.DateTime.AddHours(timezoneOffset), + Mode = d.Mode, + WellDepth = d.WellDepth, + BitDepth = d.BitDepth, + BlockPosition = d.BlockPosition, + BlockSpeed = d.BlockSpeed, + BlockSpeedSp = d.BlockSpeedSp, + BlockSpeedSpDevelop = d.BlockSpeedSpDevelop, + Pressure = d.Pressure, + PressureSp = d.PressureSp, + AxialLoad = d.AxialLoad, + AxialLoadSp = d.AxialLoadSp, + AxialLoadLimitMax = d.AxialLoadLimitMax, + HookWeight = d.HookWeight, + RotorTorque = d.RotorTorque, + RotorTorqueSp = d.RotorTorqueSp, + RotorSpeed = d.RotorSpeed, + Flow = d.Flow, + PressureSpDevelop = d.PressureSpDevelop, + IdFeedRegulator = d.IdFeedRegulator, + Pump0Flow = d.Pump0Flow, + Pump1Flow = d.Pump1Flow, + Pump2Flow = d.Pump2Flow, + + }); + return query; + } + + public IQueryable GetDataSpinItems(DateTime begin, DateTime end) + { + var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset); + var endUtc = end.ToUtcDateTimeOffset(timezoneOffset); + + var query = context.TelemetryDataSpin + .Where(d => d.IdTelemetry == idTelemetry + && d.DateTime >= beginUtc + && d.DateTime <= endUtc) + .OrderBy(d => d.DateTime) + .Select(d => new DataSpinReport + { + Date = d.DateTime.DateTime.AddHours(timezoneOffset), + Mode = d.Mode, + IsWorkingSpinMaster = (d.State != 0 && d.State != 5 && d.State != 6 && d.State != 7), + IsWorkingTorqueMaster = (d.State == 7 && (d.Mode & 2) > 0), + }); + return query; + } + + public IQueryable GetMessages(DateTime begin, DateTime end) + { + var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset); + var endUtc = end.ToUtcDateTimeOffset(timezoneOffset); + + var query = from item in context.TelemetryMessages + where item.IdTelemetry == idTelemetry + && item.DateTime >= beginUtc + && item.DateTime <= endUtc + orderby item.DateTime + select new MessageReport + { + Id = item.Id, + Date = item.DateTime.DateTime, + Category = events.GetValueOrDefault(item.IdEvent) == null + ? $"" + : categories[events[item.IdEvent].IdCategory], + User = item.IdTelemetryUser == null + ? "" + : users.GetValueOrDefault((int)item.IdTelemetryUser) == null + ? $"User id{item.IdTelemetryUser}" + : users[(int)item.IdTelemetryUser].MakeDisplayName(), + Text = events.GetValueOrDefault(item.IdEvent) == null + ? $"Событие {item.IdEvent} {item.Arg0} {item.Arg1} {item.Arg2} {item.Arg3}" + : events[item.IdEvent].MakeMessageText(item) + }; + return query; + } + + public WellInfoReport GetWellInfo() + => info; } diff --git a/AsbCloudInfrastructure/Repository/CacheBase.cs b/AsbCloudInfrastructure/Repository/CacheBase.cs index 46670658..61948bc2 100644 --- a/AsbCloudInfrastructure/Repository/CacheBase.cs +++ b/AsbCloudInfrastructure/Repository/CacheBase.cs @@ -7,58 +7,56 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + + +public class CacheBase : QueryContainer + where TEntity : class, AsbCloudDb.Model.IId { + protected readonly IMemoryCache memoryCache; + protected string CacheTag = typeof(TEntity).Name; + protected TimeSpan CacheObsolescence = TimeSpan.FromMinutes(5); - public class CacheBase : QueryContainer - where TEntity : class, AsbCloudDb.Model.IId + public CacheBase(IAsbCloudDbContext context, IMemoryCache memoryCache) + : base(context) { - protected readonly IMemoryCache memoryCache; - protected string CacheTag = typeof(TEntity).Name; - protected TimeSpan CacheObsolescence = TimeSpan.FromMinutes(5); - - public CacheBase(IAsbCloudDbContext context, IMemoryCache memoryCache) - : base(context) - { - this.memoryCache = memoryCache; - } - - public CacheBase(IAsbCloudDbContext context, IMemoryCache memoryCache, Func, IQueryable> makeQuery) - : base(context, makeQuery) - { - this.memoryCache = memoryCache; - } - - protected virtual void DropCache() - => memoryCache.Remove(CacheTag); - - protected virtual IEnumerable GetCache() - { - var cache = memoryCache.GetOrCreate(CacheTag, cacheEntry => - { - cacheEntry.AbsoluteExpirationRelativeToNow = CacheObsolescence; - cacheEntry.SlidingExpiration = CacheObsolescence; - - var entities = this.GetQuery().ToArray(); - cacheEntry.Value = entities; - return entities; - }); - return cache!; - } - - protected virtual async Task> GetCacheAsync(CancellationToken token) - { - var cache = await memoryCache.GetOrCreateAsync(CacheTag, async (cacheEntry) => - { - cacheEntry.AbsoluteExpirationRelativeToNow = CacheObsolescence; - cacheEntry.SlidingExpiration = CacheObsolescence; - - var entities = await GetQuery().AsNoTracking().ToArrayAsync(token); - cacheEntry.Value = entities; - return entities.AsEnumerable(); - }); - return cache!; - } + this.memoryCache = memoryCache; } + public CacheBase(IAsbCloudDbContext context, IMemoryCache memoryCache, Func, IQueryable> makeQuery) + : base(context, makeQuery) + { + this.memoryCache = memoryCache; + } + + protected virtual void DropCache() + => memoryCache.Remove(CacheTag); + + protected virtual IEnumerable GetCache() + { + var cache = memoryCache.GetOrCreate(CacheTag, cacheEntry => + { + cacheEntry.AbsoluteExpirationRelativeToNow = CacheObsolescence; + cacheEntry.SlidingExpiration = CacheObsolescence; + + var entities = this.GetQuery().ToArray(); + cacheEntry.Value = entities; + return entities; + }); + return cache!; + } + + protected virtual async Task> GetCacheAsync(CancellationToken token) + { + var cache = await memoryCache.GetOrCreateAsync(CacheTag, async (cacheEntry) => + { + cacheEntry.AbsoluteExpirationRelativeToNow = CacheObsolescence; + cacheEntry.SlidingExpiration = CacheObsolescence; + + var entities = await GetQuery().AsNoTracking().ToArrayAsync(token); + cacheEntry.Value = entities; + return entities.AsEnumerable(); + }); + return cache!; + } } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Repository/CrudCacheRepositoryBase.cs b/AsbCloudInfrastructure/Repository/CrudCacheRepositoryBase.cs index bfa1c410..698ac306 100644 --- a/AsbCloudInfrastructure/Repository/CrudCacheRepositoryBase.cs +++ b/AsbCloudInfrastructure/Repository/CrudCacheRepositoryBase.cs @@ -9,106 +9,104 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + + +/// +/// CRUD сервис с кешем в оперативке +/// +/// +/// +public class CrudCacheRepositoryBase : CacheBase, ICrudRepository + where TDto : AsbCloudApp.Data.IId + where TEntity : class, IId { + protected int KeySelector(TEntity entity) => entity.Id; + protected readonly ICrudRepository crudServiceBase; - /// - /// CRUD сервис с кешем в оперативке - /// - /// - /// - public class CrudCacheRepositoryBase : CacheBase, ICrudRepository - where TDto : AsbCloudApp.Data.IId - where TEntity : class, IId + public CrudCacheRepositoryBase(IAsbCloudDbContext dbContext, IMemoryCache memoryCache) + : base(dbContext, memoryCache) { - protected int KeySelector(TEntity entity) => entity.Id; - protected readonly ICrudRepository crudServiceBase; - - public CrudCacheRepositoryBase(IAsbCloudDbContext dbContext, IMemoryCache memoryCache) - : base(dbContext, memoryCache) - { - crudServiceBase = new CrudRepositoryBase(dbContext); - } - - public CrudCacheRepositoryBase(IAsbCloudDbContext dbContext, IMemoryCache memoryCache, Func, IQueryable> makeQuery) - : base(dbContext, memoryCache, makeQuery) - { - crudServiceBase = new CrudRepositoryBase(dbContext, makeQuery); - } - - /// - public virtual async Task InsertAsync(TDto newItem, CancellationToken token) - { - var result = await crudServiceBase.InsertAsync(newItem, token); - if (result > 0) - DropCache(); - return result; - } - - /// - public virtual async Task InsertRangeAsync(IEnumerable dtos, CancellationToken token) - { - var result = await crudServiceBase.InsertRangeAsync(dtos, token); - if (result > 0) - DropCache(); - return result; - } - - /// - public virtual async Task UpdateAsync(TDto dto, CancellationToken token) - { - var result = await crudServiceBase.UpdateAsync(dto, token); - if (result > 0) - DropCache(); - return result; - } - - /// - public async Task> GetAllAsync(CancellationToken token) - { - var cache = await GetCacheAsync(token); - var dtos = cache.Select(Convert); - return dtos; - } - - /// - /// Синхронно получить запись по ИД - /// - /// - /// - public TDto? GetOrDefault(int id) - { - var cache = GetCache(); - var cacheItem = cache.FirstOrDefault(d => d.Id == id); - if (cacheItem is null) - return default; - var dto = Convert(cacheItem); - return dto; - } - - /// - public async Task GetOrDefaultAsync(int id, CancellationToken token) - { - var cache = await GetCacheAsync(token); - var cacheItem = cache.FirstOrDefault(d => d.Id == id); - if (cacheItem is null) - return default; - var dto = Convert(cacheItem); - return dto; - } - - /// - public virtual async Task DeleteAsync(int id, CancellationToken token) - { - var result = await crudServiceBase.DeleteAsync(id, token); - if (result > 0) - DropCache(); - return result; - } - - protected virtual TDto Convert(TEntity src) => src.Adapt(); - - protected virtual TEntity Convert(TDto src) => src.Adapt(); + crudServiceBase = new CrudRepositoryBase(dbContext); } + public CrudCacheRepositoryBase(IAsbCloudDbContext dbContext, IMemoryCache memoryCache, Func, IQueryable> makeQuery) + : base(dbContext, memoryCache, makeQuery) + { + crudServiceBase = new CrudRepositoryBase(dbContext, makeQuery); + } + + /// + public virtual async Task InsertAsync(TDto newItem, CancellationToken token) + { + var result = await crudServiceBase.InsertAsync(newItem, token); + if (result > 0) + DropCache(); + return result; + } + + /// + public virtual async Task InsertRangeAsync(IEnumerable dtos, CancellationToken token) + { + var result = await crudServiceBase.InsertRangeAsync(dtos, token); + if (result > 0) + DropCache(); + return result; + } + + /// + public virtual async Task UpdateAsync(TDto dto, CancellationToken token) + { + var result = await crudServiceBase.UpdateAsync(dto, token); + if (result > 0) + DropCache(); + return result; + } + + /// + public async Task> GetAllAsync(CancellationToken token) + { + var cache = await GetCacheAsync(token); + var dtos = cache.Select(Convert); + return dtos; + } + + /// + /// Синхронно получить запись по ИД + /// + /// + /// + public TDto? GetOrDefault(int id) + { + var cache = GetCache(); + var cacheItem = cache.FirstOrDefault(d => d.Id == id); + if (cacheItem is null) + return default; + var dto = Convert(cacheItem); + return dto; + } + + /// + public async Task GetOrDefaultAsync(int id, CancellationToken token) + { + var cache = await GetCacheAsync(token); + var cacheItem = cache.FirstOrDefault(d => d.Id == id); + if (cacheItem is null) + return default; + var dto = Convert(cacheItem); + return dto; + } + + /// + public virtual async Task DeleteAsync(int id, CancellationToken token) + { + var result = await crudServiceBase.DeleteAsync(id, token); + if (result > 0) + DropCache(); + return result; + } + + protected virtual TDto Convert(TEntity src) => src.Adapt(); + + protected virtual TEntity Convert(TDto src) => src.Adapt(); } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Repository/CrudRepositoryBase.cs b/AsbCloudInfrastructure/Repository/CrudRepositoryBase.cs index 48fe4c8b..e00e830f 100644 --- a/AsbCloudInfrastructure/Repository/CrudRepositoryBase.cs +++ b/AsbCloudInfrastructure/Repository/CrudRepositoryBase.cs @@ -10,180 +10,178 @@ using System.Threading.Tasks; using AsbCloudApp.Exceptions; using Microsoft.EntityFrameworkCore.ChangeTracking; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + + +/// +/// CRUD сервис для работы с БД +/// +/// +/// +public class CrudRepositoryBase : QueryContainer, ICrudRepository + where TDto : AsbCloudApp.Data.IId + where TEntity : class, IId { + public CrudRepositoryBase(IAsbCloudDbContext context) + : base(context) + { } - /// - /// CRUD сервис для работы с БД - /// - /// - /// - public class CrudRepositoryBase : QueryContainer, ICrudRepository - where TDto : AsbCloudApp.Data.IId - where TEntity : class, IId + public CrudRepositoryBase(IAsbCloudDbContext context, Func, IQueryable> makeQuery) + : base(context, makeQuery) + { } + + /// + public virtual async Task> GetAllAsync(CancellationToken token) { - public CrudRepositoryBase(IAsbCloudDbContext context) - : base(context) - { } - - public CrudRepositoryBase(IAsbCloudDbContext context, Func, IQueryable> makeQuery) - : base(context, makeQuery) - { } - - /// - public virtual async Task> GetAllAsync(CancellationToken token) - { - var entities = await GetQuery() - .AsNoTracking() - .ToListAsync(token) - .ConfigureAwait(false); - var dtos = entities.Select(Convert).ToList(); - return dtos; - } - - /// - public virtual async Task GetOrDefaultAsync(int id, CancellationToken token) - { - var entity = await GetQuery() - .AsNoTracking() - .FirstOrDefaultAsync(e => e.Id == id, token) - .ConfigureAwait(false); - if (entity == default) - return default; - var dto = Convert(entity); - return dto; - } - - /// - public virtual TDto? GetOrDefault(int id) - { - var entity = GetQuery() - .AsNoTracking() - .FirstOrDefault(e => e.Id == id); - if (entity == default) - return default; - var dto = Convert(entity); - return dto; - } - - /// - public virtual async Task InsertAsync(TDto item, CancellationToken token) - { - var entity = Convert(item); - entity.Id = 0; - var entry = dbSet.Add(entity); - await dbContext.SaveChangesAsync(token); - entry.State = EntityState.Detached; - return entity.Id; - } - - /// - public virtual async Task InsertRangeAsync(IEnumerable items, CancellationToken token) - { - if (!items.Any()) - return 0; - var entities = items.Select(i => - { - var entity = Convert(i); - entity.Id = 0; - return entity; - }); - var entries = new List(items.Count()); - foreach (var entity in entities) - { - var entry = dbSet.Add(entity); - entries.Add(entry); - } - var affected = await dbContext.SaveChangesAsync(token); - entries.ForEach(e => e.State = EntityState.Detached); - return affected; - } - - /// - public virtual async Task UpdateAsync(TDto item, CancellationToken token) - { - var existingEntity = await dbSet - .AsNoTracking() - .FirstOrDefaultAsync(e => e.Id == item.Id, token) - .ConfigureAwait(false); - - if (existingEntity is null) - return ICrudRepository.ErrorIdNotFound; - - var entity = Convert(item); - var entry = dbSet.Update(entity); - await dbContext.SaveChangesAsync(token); - entry.State = EntityState.Detached; - return entry.Entity.Id; - } - - public virtual async Task UpdateRangeAsync(IEnumerable dtos, CancellationToken token) - { - if (!dtos.Any()) - return 0; - - var ids = dtos - .Select(o => o.Id) - .Distinct() - .ToArray(); - - if (ids.Any(id => id == default)) - throw new ArgumentInvalidException(nameof(dtos), "Все записи должны иметь Id"); - - if (ids.Length != dtos.Count()) - throw new ArgumentInvalidException(nameof(dtos), "Все записи должны иметь уникальные Id"); - - var existingEntitiesCount = await dbContext.Set() - .Where(o => ids.Contains(o.Id)) - .CountAsync(token); - - if (ids.Length != existingEntitiesCount) - throw new ArgumentInvalidException(nameof(dtos), "Все записи должны существовать в БД"); - - var entities = dtos.Select(Convert); - - var entries = entities.Select(entity => dbContext.Set().Update(entity)).ToList(); - - var affected = await dbContext.SaveChangesAsync(token); - - entries.ForEach(entry => entry.State = EntityState.Detached); - - return affected; - } - - /// - public virtual Task DeleteAsync(int id, CancellationToken token) - { - var entity = dbSet - .AsNoTracking() - .FirstOrDefault(e => e.Id == id); - if (entity == default) - return Task.FromResult(ICrudRepository.ErrorIdNotFound); - dbSet.Remove(entity); - var affected = dbContext.SaveChangesAsync(token); - return affected; - } - - public virtual async Task DeleteRangeAsync(IEnumerable 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.ErrorIdNotFound; - - var entities = dbContext.Set().Where(e => ids.Contains(e.Id)); - dbContext.Set().RemoveRange(entities); - return await dbContext.SaveChangesAsync(token); - } - - protected virtual TDto Convert(TEntity src) => src.Adapt(); - - protected virtual TEntity Convert(TDto src) => src.Adapt(); + var entities = await GetQuery() + .AsNoTracking() + .ToListAsync(token) + .ConfigureAwait(false); + var dtos = entities.Select(Convert).ToList(); + return dtos; } + /// + public virtual async Task GetOrDefaultAsync(int id, CancellationToken token) + { + var entity = await GetQuery() + .AsNoTracking() + .FirstOrDefaultAsync(e => e.Id == id, token) + .ConfigureAwait(false); + if (entity == default) + return default; + var dto = Convert(entity); + return dto; + } + + /// + public virtual TDto? GetOrDefault(int id) + { + var entity = GetQuery() + .AsNoTracking() + .FirstOrDefault(e => e.Id == id); + if (entity == default) + return default; + var dto = Convert(entity); + return dto; + } + + /// + public virtual async Task InsertAsync(TDto item, CancellationToken token) + { + var entity = Convert(item); + entity.Id = 0; + var entry = dbSet.Add(entity); + await dbContext.SaveChangesAsync(token); + entry.State = EntityState.Detached; + return entity.Id; + } + + /// + public virtual async Task InsertRangeAsync(IEnumerable items, CancellationToken token) + { + if (!items.Any()) + return 0; + var entities = items.Select(i => + { + var entity = Convert(i); + entity.Id = 0; + return entity; + }); + var entries = new List(items.Count()); + foreach (var entity in entities) + { + var entry = dbSet.Add(entity); + entries.Add(entry); + } + var affected = await dbContext.SaveChangesAsync(token); + entries.ForEach(e => e.State = EntityState.Detached); + return affected; + } + + /// + public virtual async Task UpdateAsync(TDto item, CancellationToken token) + { + var existingEntity = await dbSet + .AsNoTracking() + .FirstOrDefaultAsync(e => e.Id == item.Id, token) + .ConfigureAwait(false); + + if (existingEntity is null) + return ICrudRepository.ErrorIdNotFound; + + var entity = Convert(item); + var entry = dbSet.Update(entity); + await dbContext.SaveChangesAsync(token); + entry.State = EntityState.Detached; + return entry.Entity.Id; + } + + public virtual async Task UpdateRangeAsync(IEnumerable dtos, CancellationToken token) + { + if (!dtos.Any()) + return 0; + + var ids = dtos + .Select(o => o.Id) + .Distinct() + .ToArray(); + + if (ids.Any(id => id == default)) + throw new ArgumentInvalidException(nameof(dtos), "Все записи должны иметь Id"); + + if (ids.Length != dtos.Count()) + throw new ArgumentInvalidException(nameof(dtos), "Все записи должны иметь уникальные Id"); + + var existingEntitiesCount = await dbContext.Set() + .Where(o => ids.Contains(o.Id)) + .CountAsync(token); + + if (ids.Length != existingEntitiesCount) + throw new ArgumentInvalidException(nameof(dtos), "Все записи должны существовать в БД"); + + var entities = dtos.Select(Convert); + + var entries = entities.Select(entity => dbContext.Set().Update(entity)).ToList(); + + var affected = await dbContext.SaveChangesAsync(token); + + entries.ForEach(entry => entry.State = EntityState.Detached); + + return affected; + } + + /// + public virtual Task DeleteAsync(int id, CancellationToken token) + { + var entity = dbSet + .AsNoTracking() + .FirstOrDefault(e => e.Id == id); + if (entity == default) + return Task.FromResult(ICrudRepository.ErrorIdNotFound); + dbSet.Remove(entity); + var affected = dbContext.SaveChangesAsync(token); + return affected; + } + + public virtual async Task DeleteRangeAsync(IEnumerable 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.ErrorIdNotFound; + + var entities = dbContext.Set().Where(e => ids.Contains(e.Id)); + dbContext.Set().RemoveRange(entities); + return await dbContext.SaveChangesAsync(token); + } + + protected virtual TDto Convert(TEntity src) => src.Adapt(); + + protected virtual TEntity Convert(TDto src) => src.Adapt(); } diff --git a/AsbCloudInfrastructure/Repository/CrudWellRelatedCacheRepositoryBase.cs b/AsbCloudInfrastructure/Repository/CrudWellRelatedCacheRepositoryBase.cs index 601ab274..73f3ead3 100644 --- a/AsbCloudInfrastructure/Repository/CrudWellRelatedCacheRepositoryBase.cs +++ b/AsbCloudInfrastructure/Repository/CrudWellRelatedCacheRepositoryBase.cs @@ -8,43 +8,41 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + + +public class CrudWellRelatedCacheRepositoryBase : CrudCacheRepositoryBase, IRepositoryWellRelated + where TDto : AsbCloudApp.Data.IId, AsbCloudApp.Data.IWellRelated + where TEntity : class, IId, IWellRelated { + public CrudWellRelatedCacheRepositoryBase(IAsbCloudDbContext context, IMemoryCache memoryCache) + : base(context, memoryCache) { } - public class CrudWellRelatedCacheRepositoryBase : CrudCacheRepositoryBase, IRepositoryWellRelated - where TDto : AsbCloudApp.Data.IId, AsbCloudApp.Data.IWellRelated - where TEntity : class, IId, IWellRelated + public CrudWellRelatedCacheRepositoryBase(IAsbCloudDbContext context, IMemoryCache memoryCache, Func, IQueryable> makeQuery) + : base(context, memoryCache, makeQuery) { } + + public async Task> GetByIdWellAsync(int idWell, CancellationToken token) { - public CrudWellRelatedCacheRepositoryBase(IAsbCloudDbContext context, IMemoryCache memoryCache) - : base(context, memoryCache) { } + var cache = await GetCacheAsync(token); - public CrudWellRelatedCacheRepositoryBase(IAsbCloudDbContext context, IMemoryCache memoryCache, Func, IQueryable> makeQuery) - : base(context, memoryCache, makeQuery) { } + var dtos = cache + .Where(e => e.IdWell == idWell) + .Select(Convert); - public async Task> GetByIdWellAsync(int idWell, CancellationToken token) - { - var cache = await GetCacheAsync(token); - - var dtos = cache - .Where(e => e.IdWell == idWell) - .Select(Convert); - - return dtos; - } - - public async Task> GetByIdWellAsync(IEnumerable idsWells, CancellationToken token) - { - if (!idsWells.Any()) - return Enumerable.Empty(); - - var cache = await GetCacheAsync(token); - - var dtos = cache - .Where(e => idsWells.Contains(e.IdWell)) - .Select(Convert); - - return dtos; - } + return dtos; } + public async Task> GetByIdWellAsync(IEnumerable idsWells, CancellationToken token) + { + if (!idsWells.Any()) + return Enumerable.Empty(); + + var cache = await GetCacheAsync(token); + + var dtos = cache + .Where(e => idsWells.Contains(e.IdWell)) + .Select(Convert); + + return dtos; + } } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Repository/CrudWellRelatedRepositoryBase.cs b/AsbCloudInfrastructure/Repository/CrudWellRelatedRepositoryBase.cs index bafb2944..4cdb237b 100644 --- a/AsbCloudInfrastructure/Repository/CrudWellRelatedRepositoryBase.cs +++ b/AsbCloudInfrastructure/Repository/CrudWellRelatedRepositoryBase.cs @@ -7,40 +7,39 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + + +public class CrudWellRelatedRepositoryBase : CrudRepositoryBase, IRepositoryWellRelated + where TDto : AsbCloudApp.Data.IId, AsbCloudApp.Data.IWellRelated + where TEntity : class, IId, IWellRelated { + public CrudWellRelatedRepositoryBase(IAsbCloudDbContext context) + : base(context) { } - public class CrudWellRelatedRepositoryBase : CrudRepositoryBase, IRepositoryWellRelated - where TDto : AsbCloudApp.Data.IId, AsbCloudApp.Data.IWellRelated - where TEntity : class, IId, IWellRelated + public CrudWellRelatedRepositoryBase(IAsbCloudDbContext context, Func, IQueryable> makeQuery) + : base(context, makeQuery) { } + + public async Task> GetByIdWellAsync(int idWell, CancellationToken token) { - public CrudWellRelatedRepositoryBase(IAsbCloudDbContext context) - : base(context) { } + var entities = await GetQuery() + .Where(e => e.IdWell == idWell) + .AsNoTracking() + .ToArrayAsync(token); + var dtos = entities.Select(Convert).ToList(); + return dtos; + } - public CrudWellRelatedRepositoryBase(IAsbCloudDbContext context, Func, IQueryable> makeQuery) - : base(context, makeQuery) { } + public async Task> GetByIdWellAsync(IEnumerable idsWells, CancellationToken token) + { + if (!idsWells.Any()) + return Enumerable.Empty(); - public async Task> GetByIdWellAsync(int idWell, CancellationToken token) - { - var entities = await GetQuery() - .Where(e => e.IdWell == idWell) - .AsNoTracking() - .ToArrayAsync(token); - var dtos = entities.Select(Convert).ToList(); - return dtos; - } - - public async Task> GetByIdWellAsync(IEnumerable idsWells, CancellationToken token) - { - if (!idsWells.Any()) - return Enumerable.Empty(); - - var entities = await GetQuery() - .Where(e => idsWells.Contains(e.IdWell)) - .AsNoTracking() - .ToArrayAsync(token); - var dtos = entities.Select(Convert).ToList(); - return dtos; - } + var entities = await GetQuery() + .Where(e => idsWells.Contains(e.IdWell)) + .AsNoTracking() + .ToArrayAsync(token); + var dtos = entities.Select(Convert).ToList(); + return dtos; } } diff --git a/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs b/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs index d5159bf6..d8932b28 100644 --- a/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs +++ b/AsbCloudInfrastructure/Repository/DataSaubStatRepository.cs @@ -11,103 +11,102 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + +public class DataSaubStatRepository : IDataSaubStatRepository { - public class DataSaubStatRepository : IDataSaubStatRepository + private readonly IAsbCloudDbContext db; + private readonly ITelemetryService telemetryService; + + public DataSaubStatRepository(IAsbCloudDbContext dbContext, ITelemetryService telemetryService) { - private readonly IAsbCloudDbContext db; - private readonly ITelemetryService telemetryService; + db = dbContext; + this.telemetryService = telemetryService; - public DataSaubStatRepository(IAsbCloudDbContext dbContext, ITelemetryService telemetryService) + } + + public async Task> GetLastsAsync(int[] idTelemetries, CancellationToken token) + { + var timeZoneOffsets = idTelemetries + .Distinct() + .ToDictionary(idTelemetry => idTelemetry, idTelemetry => TimeSpan.FromHours(telemetryService.GetTimezone(idTelemetry).Hours)); + + var stats = await db.Set() + .Where(s => idTelemetries.Contains(s.IdTelemetry)) + .GroupBy(s => s.IdTelemetry, (key, group) => group.OrderByDescending(el => el.DateEnd).First()) + .ToArrayAsync(token); + + var result = stats.Select(s => ConvertToDto(s, timeZoneOffsets[s.IdTelemetry])); + + return result; + } + + public async Task> GetAsync(int idTelemetry, DateTimeOffset geDate, DateTimeOffset leDate, CancellationToken token) + { + var timeSpan = TimeSpan.FromHours(telemetryService.GetTimezone(idTelemetry).Hours); + var geDateUtc = geDate.ToUniversalTime(); + var leDateUtc = leDate.ToUniversalTime(); + + var stats = await db.Set() + .Where(s => s.IdTelemetry == idTelemetry) + .Where(s => s.DateStart >= geDateUtc) + .Where(s => s.DateEnd <= leDateUtc) + .ToArrayAsync(token); + + var result = stats.Select(s => ConvertToDto(s, timeSpan)); + + return result; + } + + public async Task InsertRangeAsync(IEnumerable dataSaubStats, CancellationToken token) + { + var entities = dataSaubStats.Select(data => ConvertToEntity(data)); + db.Set().AddRange(entities); + return await db.SaveChangesAsync(token); + } + + private static DataSaubStatDto ConvertToDto(DataSaubStat entity, TimeSpan timeSpan) + { + var dto = entity.Adapt(); + dto.DateStart = dto.DateStart.ToOffset(timeSpan); + dto.DateEnd = dto.DateEnd.ToOffset(timeSpan); + + return dto; + } + + private static DataSaubStat ConvertToEntity(DataSaubStatDto dto) + { + var entity = dto.Adapt(); + entity.DateStart = dto.DateStart.ToUniversalTime(); + entity.DateEnd = dto.DateEnd.ToUniversalTime(); + + return entity; + } + + private IQueryable BuildQuery(TelemetryPartDeleteRequest request) + { + var query = db.Set() + .Where(o => o.IdTelemetry == request.IdTelemetry); + + if (request.LeDate is not null) { - db = dbContext; - this.telemetryService = telemetryService; - + var leDate = request.LeDate.Value.ToUniversalTime(); + query = query.Where(o => o.DateStart <= leDate); } - public async Task> GetLastsAsync(int[] idTelemetries, CancellationToken token) + if (request.GeDate is not null) { - var timeZoneOffsets = idTelemetries - .Distinct() - .ToDictionary(idTelemetry => idTelemetry, idTelemetry => TimeSpan.FromHours(telemetryService.GetTimezone(idTelemetry).Hours)); - - var stats = await db.Set() - .Where(s => idTelemetries.Contains(s.IdTelemetry)) - .GroupBy(s => s.IdTelemetry, (key, group) => group.OrderByDescending(el => el.DateEnd).First()) - .ToArrayAsync(token); - - var result = stats.Select(s => ConvertToDto(s, timeZoneOffsets[s.IdTelemetry])); - - return result; + var geDate = request.GeDate.Value.ToUniversalTime(); + query = query.Where(o => o.DateEnd >= geDate); } - public async Task> GetAsync(int idTelemetry, DateTimeOffset geDate, DateTimeOffset leDate, CancellationToken token) - { - var timeSpan = TimeSpan.FromHours(telemetryService.GetTimezone(idTelemetry).Hours); - var geDateUtc = geDate.ToUniversalTime(); - var leDateUtc = leDate.ToUniversalTime(); + return query; + } - var stats = await db.Set() - .Where(s => s.IdTelemetry == idTelemetry) - .Where(s => s.DateStart >= geDateUtc) - .Where(s => s.DateEnd <= leDateUtc) - .ToArrayAsync(token); - - var result = stats.Select(s => ConvertToDto(s, timeSpan)); - - return result; - } - - public async Task InsertRangeAsync(IEnumerable dataSaubStats, CancellationToken token) - { - var entities = dataSaubStats.Select(data => ConvertToEntity(data)); - db.Set().AddRange(entities); - return await db.SaveChangesAsync(token); - } - - private static DataSaubStatDto ConvertToDto(DataSaubStat entity, TimeSpan timeSpan) - { - var dto = entity.Adapt(); - dto.DateStart = dto.DateStart.ToOffset(timeSpan); - dto.DateEnd = dto.DateEnd.ToOffset(timeSpan); - - return dto; - } - - private static DataSaubStat ConvertToEntity(DataSaubStatDto dto) - { - var entity = dto.Adapt(); - entity.DateStart = dto.DateStart.ToUniversalTime(); - entity.DateEnd = dto.DateEnd.ToUniversalTime(); - - return entity; - } - - private IQueryable BuildQuery(TelemetryPartDeleteRequest request) - { - var query = db.Set() - .Where(o => o.IdTelemetry == request.IdTelemetry); - - if (request.LeDate is not null) - { - var leDate = request.LeDate.Value.ToUniversalTime(); - query = query.Where(o => o.DateStart <= leDate); - } - - if (request.GeDate is not null) - { - var geDate = request.GeDate.Value.ToUniversalTime(); - query = query.Where(o => o.DateEnd >= geDate); - } - - return query; - } - - public async Task DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token) - { - var query = BuildQuery(request); - db.Set().RemoveRange(query); - return await db.SaveChangesAsync(token); - } + public async Task DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token) + { + var query = BuildQuery(request); + db.Set().RemoveRange(query); + return await db.SaveChangesAsync(token); } } diff --git a/AsbCloudInfrastructure/Repository/DrillTestRepository.cs b/AsbCloudInfrastructure/Repository/DrillTestRepository.cs index a7bc82a0..d9d3931d 100644 --- a/AsbCloudInfrastructure/Repository/DrillTestRepository.cs +++ b/AsbCloudInfrastructure/Repository/DrillTestRepository.cs @@ -12,105 +12,104 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + +public class DrillTestRepository : IDrillTestRepository { - public class DrillTestRepository : IDrillTestRepository + private readonly IAsbCloudDbContext db; + + public DrillTestRepository(IAsbCloudDbContext db) { - private readonly IAsbCloudDbContext db; + this.db = db; + } - public DrillTestRepository(IAsbCloudDbContext db) + public async Task> GetAllAsync(int idTelemetry, FileReportRequest request, CancellationToken cancellationToken) + { + var query = db.DrillTests + .Where(d => d.IdTelemetry == idTelemetry) + .Include(d => d.Telemetry) + .AsNoTracking(); + + if (request.GeDate.HasValue) { - this.db = db; + var startDateUTC = new DateTimeOffset(request.GeDate.Value.Year, request.GeDate.Value.Month, request.GeDate.Value.Day, 0, 0, 0, TimeSpan.Zero); + query = query.Where(q => q.TimeStampStart >= startDateUTC); + } + if (request.LeDate.HasValue) + { + var finishDateUTC = new DateTimeOffset(request.LeDate.Value.Year, request.LeDate.Value.Month, request.LeDate.Value.Day, 0, 0, 0, TimeSpan.Zero); + query = query.Where(q => q.TimeStampStart <= finishDateUTC); } - public async Task> GetAllAsync(int idTelemetry, FileReportRequest request, CancellationToken cancellationToken) + var entities = await query.ToListAsync(cancellationToken); + var dtos = entities.Select(e => Convert(e)); + + return dtos; + } + + + public async Task GetAsync(int idTelemetry, int id, CancellationToken cancellationToken) + { + var drillTest = await db.DrillTests + .Where(d => d.Id == id) + .Include(d => d.Telemetry) + .Where(d => d.Telemetry.Id == idTelemetry) + .FirstOrDefaultAsync(cancellationToken); + + if (drillTest is null) + throw new ArgumentInvalidException(new string[] { nameof(id), nameof(idTelemetry) }, $"Drill test with id: {id} and idTelemetry: {idTelemetry} does not exist."); + + var dto = Convert(drillTest); + + return dto; + } + + public async Task SaveDataAsync(int idTelemetry, IEnumerable dtos, CancellationToken token) + { + var entities = dtos.Select(dto => { - var query = db.DrillTests - .Where(d => d.IdTelemetry == idTelemetry) - .Include(d => d.Telemetry) - .AsNoTracking(); + var entity = dto.Adapt(); + entity.TimeStampStart = dto.TimeStampStart.ToUniversalTime(); + entity.IdTelemetry = idTelemetry; + return entity; + }); - if (request.GeDate.HasValue) - { - var startDateUTC = new DateTimeOffset(request.GeDate.Value.Year, request.GeDate.Value.Month, request.GeDate.Value.Day, 0, 0, 0, TimeSpan.Zero); - query = query.Where(q => q.TimeStampStart >= startDateUTC); - } - if (request.LeDate.HasValue) - { - var finishDateUTC = new DateTimeOffset(request.LeDate.Value.Year, request.LeDate.Value.Month, request.LeDate.Value.Day, 0, 0, 0, TimeSpan.Zero); - query = query.Where(q => q.TimeStampStart <= finishDateUTC); - } + var result = await db.Database.ExecInsertOrUpdateAsync(db.Set(), entities, token); + return result; + } - var entities = await query.ToListAsync(cancellationToken); - var dtos = entities.Select(e => Convert(e)); + private static DrillTestDto Convert(DrillTest entity) + { + var dto = entity.Adapt(); + dto.TimeStampStart = dto.TimeStampStart.ToRemoteDateTime(dto.Telemetry?.TimeZone?.Hours ?? 0); + return dto; + } - return dtos; + //TODO: Унифицировать модели данных телеметрии.Чтобы в будущем унифицировать репозитории данных телеметрии. + private IQueryable BuildQuery(TelemetryPartDeleteRequest request) + { + var query = db.Set() + .Where(o => o.IdTelemetry == request.IdTelemetry); + + if (request.LeDate is not null) + { + var leDate = request.LeDate.Value.ToUniversalTime(); + query = query.Where(o => o.TimeStampStart <= leDate); } - - public async Task GetAsync(int idTelemetry, int id, CancellationToken cancellationToken) + if (request.GeDate is not null) { - var drillTest = await db.DrillTests - .Where(d => d.Id == id) - .Include(d => d.Telemetry) - .Where(d => d.Telemetry.Id == idTelemetry) - .FirstOrDefaultAsync(cancellationToken); - - if (drillTest is null) - throw new ArgumentInvalidException(new string[] { nameof(id), nameof(idTelemetry) }, $"Drill test with id: {id} and idTelemetry: {idTelemetry} does not exist."); - - var dto = Convert(drillTest); - - return dto; + var geDate = request.GeDate.Value.ToUniversalTime(); + query = query.Where(o => o.TimeStampStart >= geDate); } - public async Task SaveDataAsync(int idTelemetry, IEnumerable dtos, CancellationToken token) - { - var entities = dtos.Select(dto => - { - var entity = dto.Adapt(); - entity.TimeStampStart = dto.TimeStampStart.ToUniversalTime(); - entity.IdTelemetry = idTelemetry; - return entity; - }); + return query; + } - var result = await db.Database.ExecInsertOrUpdateAsync(db.Set(), entities, token); - return result; - } - - private static DrillTestDto Convert(DrillTest entity) - { - var dto = entity.Adapt(); - dto.TimeStampStart = dto.TimeStampStart.ToRemoteDateTime(dto.Telemetry?.TimeZone?.Hours ?? 0); - return dto; - } - - //TODO: Унифицировать модели данных телеметрии.Чтобы в будущем унифицировать репозитории данных телеметрии. - private IQueryable BuildQuery(TelemetryPartDeleteRequest request) - { - var query = db.Set() - .Where(o => o.IdTelemetry == request.IdTelemetry); - - if (request.LeDate is not null) - { - var leDate = request.LeDate.Value.ToUniversalTime(); - query = query.Where(o => o.TimeStampStart <= leDate); - } - - if (request.GeDate is not null) - { - var geDate = request.GeDate.Value.ToUniversalTime(); - query = query.Where(o => o.TimeStampStart >= geDate); - } - - return query; - } - - public async Task DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token) - { - var query = BuildQuery(request); - db.Set().RemoveRange(query); - return await db.SaveChangesAsync(token); - } + public async Task DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token) + { + var query = BuildQuery(request); + db.Set().RemoveRange(query); + return await db.SaveChangesAsync(token); } } diff --git a/AsbCloudInfrastructure/Repository/FaqRepository.cs b/AsbCloudInfrastructure/Repository/FaqRepository.cs index 378a540a..ccea4385 100644 --- a/AsbCloudInfrastructure/Repository/FaqRepository.cs +++ b/AsbCloudInfrastructure/Repository/FaqRepository.cs @@ -13,148 +13,147 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + +/// +/// сервис по работе с faq-вопросами +/// +public class FaqRepository : IFaqRepository { - /// - /// сервис по работе с faq-вопросами - /// - public class FaqRepository : IFaqRepository + private readonly IAsbCloudDbContext db; + private readonly IWellService wellService; + + public FaqRepository(IAsbCloudDbContext db, IWellService wellService) { - private readonly IAsbCloudDbContext db; - private readonly IWellService wellService; + this.db = db; + this.wellService = wellService; + } - public FaqRepository(IAsbCloudDbContext db, IWellService wellService) + public async Task> GetFilteredAsync(FaqRequest request, CancellationToken token) + { + var query = db.Faqs.AsNoTracking(); + + if (request.IsFrequently) { - this.db = db; - this.wellService = wellService; + query = query.Where(o => o.IsFrequently); + } + if (request.HasAnswer) + { + query = query.Where(o => !string.IsNullOrEmpty(o.Answer)); + } + if (!request.IncludeDeleted) + { + query = query.Where(o => o.State != Faq.StateDeleted); } - public async Task> GetFilteredAsync(FaqRequest request, CancellationToken token) - { - var query = db.Faqs.AsNoTracking(); - - if (request.IsFrequently) + var entities = query + .OrderByDescending(e => e.DateCreatedQuestion) + .Select(o => new FaqDto() { - query = query.Where(o => o.IsFrequently); - } - if (request.HasAnswer) - { - query = query.Where(o => !string.IsNullOrEmpty(o.Answer)); - } - if (!request.IncludeDeleted) - { - query = query.Where(o => o.State != Faq.StateDeleted); - } - - var entities = query - .OrderByDescending(e => e.DateCreatedQuestion) - .Select(o => new FaqDto() - { - Id = o.Id, - Question = o.Question, - Answer = o.Answer, - CounterQuestion = o.CounterQuestion, - IsFrequently = o.IsFrequently, - State = o.State, - DateCreatedQuestion = o.DateCreatedQuestion, - IdAuthorQuestion = o.IdAuthorQuestion, - AurhorQuestionName = o.AuthorQuestion.MakeDisplayName(), - AurhorAnswerName = (o.AuthorAnswer != null) - ? o.AuthorAnswer.MakeDisplayName() - : string.Empty, - }); + Id = o.Id, + Question = o.Question, + Answer = o.Answer, + CounterQuestion = o.CounterQuestion, + IsFrequently = o.IsFrequently, + State = o.State, + DateCreatedQuestion = o.DateCreatedQuestion, + IdAuthorQuestion = o.IdAuthorQuestion, + AurhorQuestionName = o.AuthorQuestion.MakeDisplayName(), + AurhorAnswerName = (o.AuthorAnswer != null) + ? o.AuthorAnswer.MakeDisplayName() + : string.Empty, + }); - var result = await entities.AsNoTracking() - .ToArrayAsync(token) - .ConfigureAwait(false); + var result = await entities.AsNoTracking() + .ToArrayAsync(token) + .ConfigureAwait(false); - return result; + return result; - } + } - public async Task InsertAsync(FaqDto faqDto, CancellationToken token) + public async Task InsertAsync(FaqDto faqDto, CancellationToken token) + { + var entity = faqDto.Adapt(); + entity.DateCreatedQuestion = entity.DateLastEditedQuestion = DateTimeOffset.UtcNow; + entity.CounterQuestion = 1; + entity.State = Faq.StateOpened; + if (!string.IsNullOrEmpty(entity.Answer)) + entity.IdAuthorAnswer = entity.IdAuthorQuestion; + + + db.Faqs.Add(entity); + + await db.SaveChangesAsync(token).ConfigureAwait(false); + return entity.Id; + } + + public async Task MergeAsync(int sourceId1, int sourceId2, bool mergeQuestions, CancellationToken token) + { + var sourceFaqs = db.Faqs.Where(e => e.Id == sourceId1 || e.Id == sourceId2).ToArray(); + if (sourceFaqs.Count() < 2) + throw new ArgumentInvalidException(nameof(sourceFaqs), "Questions with target ids don't exist"); + + var newFaq = new Faq() { - var entity = faqDto.Adapt(); - entity.DateCreatedQuestion = entity.DateLastEditedQuestion = DateTimeOffset.UtcNow; - entity.CounterQuestion = 1; - entity.State = Faq.StateOpened; - if (!string.IsNullOrEmpty(entity.Answer)) - entity.IdAuthorAnswer = entity.IdAuthorQuestion; + CounterQuestion = sourceFaqs.Sum(e => e.CounterQuestion), + State = 0, + IsFrequently = sourceFaqs.Any(e => e.IsFrequently), + IdAuthorQuestion = sourceFaqs.Last().IdAuthorQuestion, + DateCreatedQuestion = DateTimeOffset.UtcNow, + DateLastEditedQuestion = DateTimeOffset.UtcNow, + Answer = mergeQuestions == true + ? string.Join(Environment.NewLine, sourceFaqs.Select(e => e.Answer)) + : sourceFaqs.Last().Answer, + Question = mergeQuestions == true + ? string.Join(Environment.NewLine, sourceFaqs.Select(e => e.Question)) + : sourceFaqs.Last().Question, + }; + db.Faqs.Add(newFaq); + await db.SaveChangesAsync(token).ConfigureAwait(false); - db.Faqs.Add(entity); + if (newFaq.Id == 0) + throw new ArgumentInvalidException(nameof(sourceId1), "Error creating new question"); - await db.SaveChangesAsync(token).ConfigureAwait(false); - return entity.Id; - } - - public async Task MergeAsync(int sourceId1, int sourceId2, bool mergeQuestions, CancellationToken token) + foreach (var sourceFaq in sourceFaqs) { - var sourceFaqs = db.Faqs.Where(e => e.Id == sourceId1 || e.Id == sourceId2).ToArray(); - if (sourceFaqs.Count() < 2) - throw new ArgumentInvalidException(nameof(sourceFaqs), "Questions with target ids don't exist"); - - var newFaq = new Faq() - { - CounterQuestion = sourceFaqs.Sum(e => e.CounterQuestion), - State = 0, - IsFrequently = sourceFaqs.Any(e => e.IsFrequently), - IdAuthorQuestion = sourceFaqs.Last().IdAuthorQuestion, - DateCreatedQuestion = DateTimeOffset.UtcNow, - DateLastEditedQuestion = DateTimeOffset.UtcNow, - Answer = mergeQuestions == true - ? string.Join(Environment.NewLine, sourceFaqs.Select(e => e.Answer)) - : sourceFaqs.Last().Answer, - Question = mergeQuestions == true - ? string.Join(Environment.NewLine, sourceFaqs.Select(e => e.Question)) - : sourceFaqs.Last().Question, - }; - - db.Faqs.Add(newFaq); - await db.SaveChangesAsync(token).ConfigureAwait(false); - - if (newFaq.Id == 0) - throw new ArgumentInvalidException(nameof(sourceId1), "Error creating new question"); - - foreach (var sourceFaq in sourceFaqs) - { - sourceFaq.IdReplacementQuestion = newFaq.Id; - sourceFaq.State = Faq.StateDeleted; - } - await db.SaveChangesAsync(token).ConfigureAwait(false); - - return newFaq.Id; + sourceFaq.IdReplacementQuestion = newFaq.Id; + sourceFaq.State = Faq.StateDeleted; } + await db.SaveChangesAsync(token).ConfigureAwait(false); - public async Task UpdateAsync(FaqDto dto, CancellationToken token) - { - var entity = dto.Adapt(); - entity.DateLastEditedQuestion = DateTimeOffset.UtcNow; - db.Faqs.Update(entity); - return await db.SaveChangesAsync(token) - .ConfigureAwait(false); - } + return newFaq.Id; + } - public async Task MarkAsDeletedAsync(int id, CancellationToken token) - { - var entity = db.Faqs.FirstOrDefault(e => e.Id == id) - ?? throw new ArgumentInvalidException(nameof(id), "Question doesn't exist"); + public async Task UpdateAsync(FaqDto dto, CancellationToken token) + { + var entity = dto.Adapt(); + entity.DateLastEditedQuestion = DateTimeOffset.UtcNow; + db.Faqs.Update(entity); + return await db.SaveChangesAsync(token) + .ConfigureAwait(false); + } - entity.State = Faq.StateDeleted; - entity.DateLastEditedQuestion = DateTimeOffset.UtcNow; + public async Task MarkAsDeletedAsync(int id, CancellationToken token) + { + var entity = db.Faqs.FirstOrDefault(e => e.Id == id) + ?? throw new ArgumentInvalidException(nameof(id), "Question doesn't exist"); - return await db.SaveChangesAsync(token) - .ConfigureAwait(false); - } + entity.State = Faq.StateDeleted; + entity.DateLastEditedQuestion = DateTimeOffset.UtcNow; - public async Task DeleteAsync(int id, CancellationToken token) - { - var faq = db.Faqs.FirstOrDefault(f => f.Id == id) - ?? throw new ArgumentInvalidException(nameof(id), "Question doesn't exist"); + return await db.SaveChangesAsync(token) + .ConfigureAwait(false); + } - db.Faqs.Remove(faq); - return await db.SaveChangesAsync(token); - } + public async Task DeleteAsync(int id, CancellationToken token) + { + var faq = db.Faqs.FirstOrDefault(f => f.Id == id) + ?? throw new ArgumentInvalidException(nameof(id), "Question doesn't exist"); + + db.Faqs.Remove(faq); + return await db.SaveChangesAsync(token); } } diff --git a/AsbCloudInfrastructure/Repository/FileRepository.cs b/AsbCloudInfrastructure/Repository/FileRepository.cs index a01f121b..8dd865ee 100644 --- a/AsbCloudInfrastructure/Repository/FileRepository.cs +++ b/AsbCloudInfrastructure/Repository/FileRepository.cs @@ -11,279 +11,277 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + + +public class FileRepository : IFileRepository { + private readonly IQueryable dbSetConfigured; + private readonly IAsbCloudDbContext db; - public class FileRepository : IFileRepository + public FileRepository(IAsbCloudDbContext db) { - private readonly IQueryable dbSetConfigured; - private readonly IAsbCloudDbContext db; - - public FileRepository(IAsbCloudDbContext db) - { - this.db = db; - this.dbSetConfigured = db.Files - .Include(f => f.Author) - .ThenInclude(u => u!.Company) - .ThenInclude(c => c.CompanyType) - .Include(f => f.FileMarks) - .ThenInclude(m => m.User) - .Include(f => f.Well); - } - - private IQueryable BuildQuery(FileRequest request) - { - var query = dbSetConfigured - .Where(e => e.IdWell == request.IdWell); - - if (request.IdCategory is not null) - query = query.Where(x => x.IdCategory == request.IdCategory); - - if (request.IsDeleted is not null) - query = query.Where(x => x.IsDeleted == request.IsDeleted); - - if (request.CompanyNamePart is not null) - query = query.Where(e => e.Author != null && e.Author.Company.Caption.ToLower().Contains(request.CompanyNamePart.ToLower())); - - if (request.FileNamePart is not null) - query = query.Where(e => e.Name.ToLower().Contains(request.FileNamePart.ToLower())); - - if (request.Begin is not null) - { - var beginUtc = request.Begin.Value.ToUniversalTime(); - query = query.Where(e => e.UploadDate >= beginUtc); - } - - if (request.End is not null) - { - var endUtc = request.End.Value.ToUniversalTime(); - query = query.Where(e => e.UploadDate <= endUtc); - } - - if (request?.SortFields?.Any() == true) - { - query = query.SortBy(request.SortFields); - } - else - query = query - .OrderBy(o => o.UploadDate); - - return query; - } - - public async Task> GetInfosAsync(FileRequest request, CancellationToken token) - { - var query = BuildQuery(request); - - var entities = await query - .SkipTake(request.Skip, request.Take) - .AsNoTracking() - .ToListAsync(token) - .ConfigureAwait(false); - - var dtos = entities.Select(e => Convert(e)); - return dtos; - } - - public async Task> GetInfosPaginatedAsync(FileRequest request, CancellationToken token = default) - { - var skip = request.Skip ?? 0; - var take = request.Take ?? 32; - - var query = BuildQuery(request); - - var result = new PaginationContainer() - { - Skip = skip, - Take = take, - Count = await query.CountAsync(token), - }; - - if (result.Count == 0) - return result; - - var entities = await query - .SkipTake(skip, take) - .AsNoTracking() - .ToListAsync(token) - .ConfigureAwait(false); - - result.Items = entities.Select(e => Convert(e)); - - return result; - } - - public async Task> GetInfoByIdsAsync(IEnumerable idsFile, CancellationToken token) - { - var result = Enumerable.Empty(); - - var entities = await dbSetConfigured - .AsNoTracking() - .Where(f => idsFile.Contains(f.Id)) - .ToListAsync(token) - .ConfigureAwait(false); - - if (entities is not null) - result = entities.Select(entity => Convert(entity)); - - return result; - } - - public async Task MarkAsDeletedAsync(int idFile, CancellationToken token = default) - { - var fileInfo = await db.Files.FirstOrDefaultAsync(f => f.Id == idFile, token).ConfigureAwait(false); - - if (fileInfo is null) - return 0; - - fileInfo.IsDeleted = true; - - return await db.SaveChangesAsync(token).ConfigureAwait(false); - } - - public async Task> DeleteAsync(IEnumerable ids, CancellationToken token) - { - var query = dbSetConfigured - .Where(f => ids.Contains(f.Id)); - - var files = await query.ToListAsync(token); - - var filesDtos = files.Select(x => Convert(x)); - - db.Files.RemoveRange(query); - await db.SaveChangesAsync(token).ConfigureAwait(false); - - return filesDtos; - } - - public async Task GetByMarkId(int idMark, CancellationToken token) - { - var entity = await dbSetConfigured - .FirstOrDefaultAsync(f => f.FileMarks.Any(m => m.Id == idMark), token) - .ConfigureAwait(false); - - FileInfoDto dto = Convert(entity!); - return dto; - } - - public async Task CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token) - { - var fileMark = await db.FileMarks - .FirstOrDefaultAsync(m => m.IdFile == fileMarkDto.IdFile && - m.IdMarkType == fileMarkDto.IdMarkType && - m.IdUser == idUser && - m.IsDeleted == false, - token) - .ConfigureAwait(false); - - if (fileMark is not null) - return 0; - - var newFileMark = fileMarkDto.Adapt(); - newFileMark.Id = default; - newFileMark.DateCreated = DateTimeOffset.UtcNow; - newFileMark.IdUser = idUser; - newFileMark.User = null!; - - db.FileMarks.Add(newFileMark); - return await db.SaveChangesAsync(token); - } - - public async Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token) - { - var fileMarkQuery = db.FileMarks - .Where(m => idsMarks.Contains(m.Id)); - - foreach (var fileMark in fileMarkQuery) - fileMark.IsDeleted = true; - - return await db.SaveChangesAsync(token); - } - - public async Task> GetAllAsync(CancellationToken token) - => await dbSetConfigured.AsNoTracking() - .Select(x => Convert(x)) - .ToListAsync(token) - .ConfigureAwait(false); - - public async Task GetOrDefaultAsync(int id, CancellationToken token) - { - var entity = await dbSetConfigured - .AsNoTracking() - .FirstOrDefaultAsync(f => f.Id == id, token) - .ConfigureAwait(false); - - if (entity is null) - return null; - - var dto = Convert(entity); - return dto; - } - - public FileInfoDto? GetOrDefault(int id) - { - var entity = dbSetConfigured - .AsNoTracking() - .FirstOrDefault(f => f.Id == id); - - if (entity is null) - return null; - - var dto = Convert(entity); - return dto; - } - - public async Task InsertAsync(FileInfoDto newItem, CancellationToken token) - { - var fileInfo = new FileInfo() - { - IdWell = newItem.IdWell, - IdAuthor = newItem.IdAuthor, - IdCategory = newItem.IdCategory, - Name = newItem.Name, - UploadDate = DateTimeOffset.UtcNow, - IsDeleted = false, - Size = newItem.Size, - }; - - var entry = db.Files.Add(fileInfo); - await db.SaveChangesAsync(token).ConfigureAwait(false); - return entry.Entity.Id; - } - - public Task InsertRangeAsync(IEnumerable newItems, CancellationToken token) - { - throw new NotImplementedException(); - } - - public Task UpdateAsync(FileInfoDto item, CancellationToken token) - { - throw new NotImplementedException(); - } - - public Task DeleteAsync(int id, CancellationToken token) - { - throw new NotImplementedException(); - } - - private static FileInfoDto Convert(FileInfo entity) - { - var timezoneOffset = entity.Well.Timezone?.Hours ?? 5; - return Convert(entity, timezoneOffset); - } - - private static FileInfoDto Convert(FileInfo entity, double timezoneOffset) - { - var dto = entity.Adapt(); - dto.UploadDate = entity.UploadDate.ToOffset(TimeSpan.FromHours(timezoneOffset)); - dto.FileMarks = entity.FileMarks.Select(m => - { - var mark = m.Adapt(); - mark.DateCreated = m.DateCreated.ToOffset(TimeSpan.FromHours(timezoneOffset)); - return mark; - }); - return dto; - } + this.db = db; + this.dbSetConfigured = db.Files + .Include(f => f.Author) + .ThenInclude(u => u!.Company) + .ThenInclude(c => c.CompanyType) + .Include(f => f.FileMarks) + .ThenInclude(m => m.User) + .Include(f => f.Well); } + private IQueryable BuildQuery(FileRequest request) + { + var query = dbSetConfigured + .Where(e => e.IdWell == request.IdWell); + + if (request.IdCategory is not null) + query = query.Where(x => x.IdCategory == request.IdCategory); + + if (request.IsDeleted is not null) + query = query.Where(x => x.IsDeleted == request.IsDeleted); + + if (request.CompanyNamePart is not null) + query = query.Where(e => e.Author != null && e.Author.Company.Caption.ToLower().Contains(request.CompanyNamePart.ToLower())); + + if (request.FileNamePart is not null) + query = query.Where(e => e.Name.ToLower().Contains(request.FileNamePart.ToLower())); + + if (request.Begin is not null) + { + var beginUtc = request.Begin.Value.ToUniversalTime(); + query = query.Where(e => e.UploadDate >= beginUtc); + } + + if (request.End is not null) + { + var endUtc = request.End.Value.ToUniversalTime(); + query = query.Where(e => e.UploadDate <= endUtc); + } + + if (request?.SortFields?.Any() == true) + { + query = query.SortBy(request.SortFields); + } + else + query = query + .OrderBy(o => o.UploadDate); + + return query; + } + + public async Task> GetInfosAsync(FileRequest request, CancellationToken token) + { + var query = BuildQuery(request); + + var entities = await query + .SkipTake(request.Skip, request.Take) + .AsNoTracking() + .ToListAsync(token) + .ConfigureAwait(false); + + var dtos = entities.Select(e => Convert(e)); + return dtos; + } + + public async Task> GetInfosPaginatedAsync(FileRequest request, CancellationToken token = default) + { + var skip = request.Skip ?? 0; + var take = request.Take ?? 32; + + var query = BuildQuery(request); + + var result = new PaginationContainer() + { + Skip = skip, + Take = take, + Count = await query.CountAsync(token), + }; + + if (result.Count == 0) + return result; + + var entities = await query + .SkipTake(skip, take) + .AsNoTracking() + .ToListAsync(token) + .ConfigureAwait(false); + + result.Items = entities.Select(e => Convert(e)); + + return result; + } + + public async Task> GetInfoByIdsAsync(IEnumerable idsFile, CancellationToken token) + { + var result = Enumerable.Empty(); + + var entities = await dbSetConfigured + .AsNoTracking() + .Where(f => idsFile.Contains(f.Id)) + .ToListAsync(token) + .ConfigureAwait(false); + + if (entities is not null) + result = entities.Select(entity => Convert(entity)); + + return result; + } + + public async Task MarkAsDeletedAsync(int idFile, CancellationToken token = default) + { + var fileInfo = await db.Files.FirstOrDefaultAsync(f => f.Id == idFile, token).ConfigureAwait(false); + + if (fileInfo is null) + return 0; + + fileInfo.IsDeleted = true; + + return await db.SaveChangesAsync(token).ConfigureAwait(false); + } + + public async Task> DeleteAsync(IEnumerable ids, CancellationToken token) + { + var query = dbSetConfigured + .Where(f => ids.Contains(f.Id)); + + var files = await query.ToListAsync(token); + + var filesDtos = files.Select(x => Convert(x)); + + db.Files.RemoveRange(query); + await db.SaveChangesAsync(token).ConfigureAwait(false); + + return filesDtos; + } + + public async Task GetByMarkId(int idMark, CancellationToken token) + { + var entity = await dbSetConfigured + .FirstOrDefaultAsync(f => f.FileMarks.Any(m => m.Id == idMark), token) + .ConfigureAwait(false); + + FileInfoDto dto = Convert(entity!); + return dto; + } + + public async Task CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token) + { + var fileMark = await db.FileMarks + .FirstOrDefaultAsync(m => m.IdFile == fileMarkDto.IdFile && + m.IdMarkType == fileMarkDto.IdMarkType && + m.IdUser == idUser && + m.IsDeleted == false, + token) + .ConfigureAwait(false); + + if (fileMark is not null) + return 0; + + var newFileMark = fileMarkDto.Adapt(); + newFileMark.Id = default; + newFileMark.DateCreated = DateTimeOffset.UtcNow; + newFileMark.IdUser = idUser; + newFileMark.User = null!; + + db.FileMarks.Add(newFileMark); + return await db.SaveChangesAsync(token); + } + + public async Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token) + { + var fileMarkQuery = db.FileMarks + .Where(m => idsMarks.Contains(m.Id)); + + foreach (var fileMark in fileMarkQuery) + fileMark.IsDeleted = true; + + return await db.SaveChangesAsync(token); + } + + public async Task> GetAllAsync(CancellationToken token) + => await dbSetConfigured.AsNoTracking() + .Select(x => Convert(x)) + .ToListAsync(token) + .ConfigureAwait(false); + + public async Task GetOrDefaultAsync(int id, CancellationToken token) + { + var entity = await dbSetConfigured + .AsNoTracking() + .FirstOrDefaultAsync(f => f.Id == id, token) + .ConfigureAwait(false); + + if (entity is null) + return null; + + var dto = Convert(entity); + return dto; + } + + public FileInfoDto? GetOrDefault(int id) + { + var entity = dbSetConfigured + .AsNoTracking() + .FirstOrDefault(f => f.Id == id); + + if (entity is null) + return null; + + var dto = Convert(entity); + return dto; + } + + public async Task InsertAsync(FileInfoDto newItem, CancellationToken token) + { + var fileInfo = new FileInfo() + { + IdWell = newItem.IdWell, + IdAuthor = newItem.IdAuthor, + IdCategory = newItem.IdCategory, + Name = newItem.Name, + UploadDate = DateTimeOffset.UtcNow, + IsDeleted = false, + Size = newItem.Size, + }; + + var entry = db.Files.Add(fileInfo); + await db.SaveChangesAsync(token).ConfigureAwait(false); + return entry.Entity.Id; + } + + public Task InsertRangeAsync(IEnumerable newItems, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task UpdateAsync(FileInfoDto item, CancellationToken token) + { + throw new NotImplementedException(); + } + + public Task DeleteAsync(int id, CancellationToken token) + { + throw new NotImplementedException(); + } + + private static FileInfoDto Convert(FileInfo entity) + { + var timezoneOffset = entity.Well.Timezone?.Hours ?? 5; + return Convert(entity, timezoneOffset); + } + + private static FileInfoDto Convert(FileInfo entity, double timezoneOffset) + { + var dto = entity.Adapt(); + dto.UploadDate = entity.UploadDate.ToOffset(TimeSpan.FromHours(timezoneOffset)); + dto.FileMarks = entity.FileMarks.Select(m => + { + var mark = m.Adapt(); + mark.DateCreated = m.DateCreated.ToOffset(TimeSpan.FromHours(timezoneOffset)); + return mark; + }); + return dto; + } } diff --git a/AsbCloudInfrastructure/Repository/GtrWitsRepository.cs b/AsbCloudInfrastructure/Repository/GtrWitsRepository.cs index 54b19e6b..22707146 100644 --- a/AsbCloudInfrastructure/Repository/GtrWitsRepository.cs +++ b/AsbCloudInfrastructure/Repository/GtrWitsRepository.cs @@ -17,478 +17,477 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + +public class GtrWitsRepository : IGtrRepository { - public class GtrWitsRepository : IGtrRepository + private static IDictionary<(int IdRecord, int IdItem), string> WitsParameters = new Dictionary<(int, int), string> { - private static IDictionary<(int IdRecord, int IdItem), string> WitsParameters = new Dictionary<(int, int), string> + { (1, 8), nameof(GtrWitsDto.DEPTBITM) }, + { (1, 10), nameof(GtrWitsDto.DEPTMEAS) }, + { (1, 14), nameof(GtrWitsDto.HKLA) }, + { (1, 12), nameof(GtrWitsDto.BLKPOS) }, + { (1, 16), nameof(GtrWitsDto.WOBA) }, + { (1, 18), nameof(GtrWitsDto.TORQA) }, + { (1, 21), nameof(GtrWitsDto.SPPA) }, + { (2, 15), nameof(GtrWitsDto.RPMA) }, + { (1, 13), nameof(GtrWitsDto.ROPA) }, + { (3, 16), nameof(GtrWitsDto.RSUX) }, + { (3, 17), nameof(GtrWitsDto.RSDX) }, + { (1, 30), nameof(GtrWitsDto.MFIA) }, + { (1, 29), nameof(GtrWitsDto.MFOA)}, + { (1, 34), nameof(GtrWitsDto.MTIA) }, + { (1, 33), nameof(GtrWitsDto.MTOA) }, + { (1, 23), nameof(GtrWitsDto.SPM1) }, + { (1, 24), nameof(GtrWitsDto.SPM2) }, + { (1, 25), nameof(GtrWitsDto.SPM3) }, + { (1, 26), nameof(GtrWitsDto.TVOLACT) }, + { (11, 29), nameof(GtrWitsDto.TTVOL1) }, + { (11, 30), nameof(GtrWitsDto.TTVOL2) }, + { (11, 15), nameof(GtrWitsDto.TVOL01) }, + { (11, 16), nameof(GtrWitsDto.TVOL02) }, + { (11, 17), nameof(GtrWitsDto.TVOL03) }, + { (11, 18), nameof(GtrWitsDto.TVOL04) }, + { (11, 19), nameof(GtrWitsDto.TVOL05) }, + { (11, 20), nameof(GtrWitsDto.TVOL06) }, + { (11, 21), nameof(GtrWitsDto.TVOL07) }, + { (11, 22), nameof(GtrWitsDto.TVOL08) }, + { (11, 23), nameof(GtrWitsDto.TVOL09) }, + { (11, 24), nameof(GtrWitsDto.TVOL10) }, + { (11, 25), nameof(GtrWitsDto.TVOL11) }, + { (11, 26), nameof(GtrWitsDto.TVOL12) }, + { (11, 27), nameof(GtrWitsDto.TVOL13) }, + { (11, 28), nameof(GtrWitsDto.TVOL14) }, + { (1, 31), nameof(GtrWitsDto.MDOA) }, + { (1, 32), nameof(GtrWitsDto.MDIA) }, + { (12, 12), nameof(GtrWitsDto.METHANE) }, + { (12, 13), nameof(GtrWitsDto.ETHANE) }, + { (12, 14), nameof(GtrWitsDto.PROPANE) }, + { (12, 15), nameof(GtrWitsDto.IBUTANE) }, + { (12, 16), nameof(GtrWitsDto.NBUTANE) }, + { (1, 40), nameof(GtrWitsDto.GASA) }, + }; + + private readonly IAsbCloudDbContext db; + private readonly ITelemetryService telemetryService; + private static ConcurrentDictionary> cache = new(); + + public GtrWitsRepository( + IAsbCloudDbContext db, + ITelemetryService telemetryService) + { + this.db = db; + this.telemetryService = telemetryService; + } + + public async Task> GetAsync(int idWell, GtrRequest request, CancellationToken token) => + await GetAsync(idWell, request, token); + + public async Task GetRangeAsync(int idWell, DateTimeOffset? geDate, DateTimeOffset? leDate, CancellationToken token) + { + var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); + + if (telemetry is null) + return null; + + var rangeQuery = db + .Set() + .Where(e => e.IdTelemetry == telemetry.Id); + + if (geDate is not null) + rangeQuery = rangeQuery.Where(e => e.DateTime >= geDate); + + if (leDate is not null) + rangeQuery = rangeQuery.Where(e => e.DateTime <= leDate); + + var groupedQuery = rangeQuery.GroupBy(e => e.IdTelemetry) + .Select(group => new + { + Min = group.Min(e => e.DateTime), + Max = group.Max(e => e.DateTime) + }); + var range = await groupedQuery.FirstOrDefaultAsync(token); + + if (range is null) + return null; + + var result = new DatesRangeDto { - { (1, 8), nameof(GtrWitsDto.DEPTBITM) }, - { (1, 10), nameof(GtrWitsDto.DEPTMEAS) }, - { (1, 14), nameof(GtrWitsDto.HKLA) }, - { (1, 12), nameof(GtrWitsDto.BLKPOS) }, - { (1, 16), nameof(GtrWitsDto.WOBA) }, - { (1, 18), nameof(GtrWitsDto.TORQA) }, - { (1, 21), nameof(GtrWitsDto.SPPA) }, - { (2, 15), nameof(GtrWitsDto.RPMA) }, - { (1, 13), nameof(GtrWitsDto.ROPA) }, - { (3, 16), nameof(GtrWitsDto.RSUX) }, - { (3, 17), nameof(GtrWitsDto.RSDX) }, - { (1, 30), nameof(GtrWitsDto.MFIA) }, - { (1, 29), nameof(GtrWitsDto.MFOA)}, - { (1, 34), nameof(GtrWitsDto.MTIA) }, - { (1, 33), nameof(GtrWitsDto.MTOA) }, - { (1, 23), nameof(GtrWitsDto.SPM1) }, - { (1, 24), nameof(GtrWitsDto.SPM2) }, - { (1, 25), nameof(GtrWitsDto.SPM3) }, - { (1, 26), nameof(GtrWitsDto.TVOLACT) }, - { (11, 29), nameof(GtrWitsDto.TTVOL1) }, - { (11, 30), nameof(GtrWitsDto.TTVOL2) }, - { (11, 15), nameof(GtrWitsDto.TVOL01) }, - { (11, 16), nameof(GtrWitsDto.TVOL02) }, - { (11, 17), nameof(GtrWitsDto.TVOL03) }, - { (11, 18), nameof(GtrWitsDto.TVOL04) }, - { (11, 19), nameof(GtrWitsDto.TVOL05) }, - { (11, 20), nameof(GtrWitsDto.TVOL06) }, - { (11, 21), nameof(GtrWitsDto.TVOL07) }, - { (11, 22), nameof(GtrWitsDto.TVOL08) }, - { (11, 23), nameof(GtrWitsDto.TVOL09) }, - { (11, 24), nameof(GtrWitsDto.TVOL10) }, - { (11, 25), nameof(GtrWitsDto.TVOL11) }, - { (11, 26), nameof(GtrWitsDto.TVOL12) }, - { (11, 27), nameof(GtrWitsDto.TVOL13) }, - { (11, 28), nameof(GtrWitsDto.TVOL14) }, - { (1, 31), nameof(GtrWitsDto.MDOA) }, - { (1, 32), nameof(GtrWitsDto.MDIA) }, - { (12, 12), nameof(GtrWitsDto.METHANE) }, - { (12, 13), nameof(GtrWitsDto.ETHANE) }, - { (12, 14), nameof(GtrWitsDto.PROPANE) }, - { (12, 15), nameof(GtrWitsDto.IBUTANE) }, - { (12, 16), nameof(GtrWitsDto.NBUTANE) }, - { (1, 40), nameof(GtrWitsDto.GASA) }, + From = range.Min.ToOffset(telemetry.TimeZone!.Offset), + To = range.Max.ToOffset(telemetry.TimeZone!.Offset), + }; + return result; + } + + private async Task> GetAsync(int idWell, GtrRequest request, CancellationToken token) + where TEntity : WitsItemBase + where TType : notnull + { + var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); + + if (telemetry is null) + return Enumerable.Empty(); + + if (telemetry.TimeZone is null) + throw new ArgumentInvalidException(nameof(idWell), $"Telemetry id: {telemetry.Id} can't find timezone"); + + var query = BuildQuery(telemetry.Id, request); + + var idsRecord = WitsParameters.Select(p => p.Key.IdRecord); + + var entities = await query + .Where(e => idsRecord.Contains(e.IdRecord)) + .OrderBy(e => e.DateTime) + .AsNoTracking() + .ToArrayAsync(token); + + if (!entities.Any()) + return Enumerable.Empty(); + + var interval = TimeSpan.FromSeconds(10); + var timezoneOffset = TimeSpan.FromHours(telemetry.TimeZone.Hours); + + var dtos = entities + .GroupBy(e => e.DateTime.Ticks / interval.Ticks) + .Select(groupByInterval => + { + var items = groupByInterval.Select(e => e); + var values = items.GroupBy(e => (e.IdRecord, e.IdItem)) + .Where(group => WitsParameters.ContainsKey(group.Key)) + .ToDictionary(group => WitsParameters[group.Key], g => (object)g.Last().Value); + + var dto = values.Adapt(); + dto.DateTime = items.Last().DateTime.ToOffset(timezoneOffset); + return dto; + }); + + return dtos; + } + + private IQueryable BuildQuery(int idTelemetry, GtrRequest request) + where TEntity : WitsItemBase + where TType : notnull + { + var query = db.Set() + .Where(e => e.IdTelemetry == idTelemetry); + + if (request.Begin.HasValue) + { + var dateBegin = request.Begin.Value.ToUniversalTime(); + var dateEnd = dateBegin.AddSeconds(request.IntervalSec); + query = query + .Where(e => e.DateTime >= dateBegin) + .Where(e => e.DateTime <= dateEnd); + } + else + { + var lastDate = query + .OrderBy(e => e.DateTime) + .LastOrDefault() + ?.DateTime + ?? DateTimeOffset.UtcNow; + var dateBegin = lastDate.AddSeconds(-request.IntervalSec); + var dateEnd = lastDate; + query = query + .Where(e => e.DateTime >= dateBegin) + .Where(e => e.DateTime <= dateEnd); + } + + return query; + } + + [Obsolete] + public async Task> GetAsync(int idWell, DateTime? dateBegin, double intervalSec = 600, int approxPointsCount = 1024, CancellationToken token = default) + { + var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); + if (telemetry is null) + return Enumerable.Empty(); + + var timezone = telemetryService.GetTimezone(telemetry.Id); + + DateTimeOffset? dateBeginUtc = dateBegin?.ToUtcDateTimeOffset(timezone.Hours); + var dateEnd = dateBeginUtc?.AddSeconds(intervalSec); + + var witsRequest = new WitsRequest() + { + IdTelemetry = telemetry.Id, + DateBeginUtc = dateBeginUtc, + DateEnd = dateEnd, + ApproxPointsCount = approxPointsCount, + TimezoneHours = timezone.Hours }; - private readonly IAsbCloudDbContext db; - private readonly ITelemetryService telemetryService; - private static ConcurrentDictionary> cache = new(); + var recordAllInt = await GetItemsOrDefaultAsync(witsRequest, token); + var recordAllFloat = await GetItemsOrDefaultAsync(witsRequest, token); + var recordAllString = await GetItemsOrDefaultAsync(witsRequest, token); - public GtrWitsRepository( - IAsbCloudDbContext db, - ITelemetryService telemetryService) - { - this.db = db; - this.telemetryService = telemetryService; - } - - public async Task> GetAsync(int idWell, GtrRequest request, CancellationToken token) => - await GetAsync(idWell, request, token); - - public async Task GetRangeAsync(int idWell, DateTimeOffset? geDate, DateTimeOffset? leDate, CancellationToken token) - { - var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); - - if (telemetry is null) - return null; - - var rangeQuery = db - .Set() - .Where(e => e.IdTelemetry == telemetry.Id); - - if (geDate is not null) - rangeQuery = rangeQuery.Where(e => e.DateTime >= geDate); - - if (leDate is not null) - rangeQuery = rangeQuery.Where(e => e.DateTime <= leDate); - - var groupedQuery = rangeQuery.GroupBy(e => e.IdTelemetry) - .Select(group => new + var dtos = (recordAllFloat.Union(recordAllInt)).Union(recordAllString) + .GroupBy(g => new + { + g.IdRecord, + g.Date + }) + .Select(g => new WitsRecordDto + { + Id = g.Key.IdRecord, + Date = g.Key.Date, + Items = g.Select(r => new { - Min = group.Min(e => e.DateTime), - Max = group.Max(e => e.DateTime) - }); - var range = await groupedQuery.FirstOrDefaultAsync(token); - - if (range is null) - return null; - - var result = new DatesRangeDto - { - From = range.Min.ToOffset(telemetry.TimeZone!.Offset), - To = range.Max.ToOffset(telemetry.TimeZone!.Offset), - }; - return result; - } - - private async Task> GetAsync(int idWell, GtrRequest request, CancellationToken token) - where TEntity : WitsItemBase - where TType : notnull - { - var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); - - if (telemetry is null) - return Enumerable.Empty(); - - if (telemetry.TimeZone is null) - throw new ArgumentInvalidException(nameof(idWell), $"Telemetry id: {telemetry.Id} can't find timezone"); - - var query = BuildQuery(telemetry.Id, request); - - var idsRecord = WitsParameters.Select(p => p.Key.IdRecord); - - var entities = await query - .Where(e => idsRecord.Contains(e.IdRecord)) - .OrderBy(e => e.DateTime) - .AsNoTracking() - .ToArrayAsync(token); - - if (!entities.Any()) - return Enumerable.Empty(); - - var interval = TimeSpan.FromSeconds(10); - var timezoneOffset = TimeSpan.FromHours(telemetry.TimeZone.Hours); - - var dtos = entities - .GroupBy(e => e.DateTime.Ticks / interval.Ticks) - .Select(groupByInterval => - { - var items = groupByInterval.Select(e => e); - var values = items.GroupBy(e => (e.IdRecord, e.IdItem)) - .Where(group => WitsParameters.ContainsKey(group.Key)) - .ToDictionary(group => WitsParameters[group.Key], g => (object)g.Last().Value); - - var dto = values.Adapt(); - dto.DateTime = items.Last().DateTime.ToOffset(timezoneOffset); - return dto; - }); - - return dtos; - } - - private IQueryable BuildQuery(int idTelemetry, GtrRequest request) - where TEntity : WitsItemBase - where TType : notnull - { - var query = db.Set() - .Where(e => e.IdTelemetry == idTelemetry); - - if (request.Begin.HasValue) - { - var dateBegin = request.Begin.Value.ToUniversalTime(); - var dateEnd = dateBegin.AddSeconds(request.IntervalSec); - query = query - .Where(e => e.DateTime >= dateBegin) - .Where(e => e.DateTime <= dateEnd); - } - else - { - var lastDate = query - .OrderBy(e => e.DateTime) - .LastOrDefault() - ?.DateTime - ?? DateTimeOffset.UtcNow; - var dateBegin = lastDate.AddSeconds(-request.IntervalSec); - var dateEnd = lastDate; - query = query - .Where(e => e.DateTime >= dateBegin) - .Where(e => e.DateTime <= dateEnd); - } - - return query; - } - - [Obsolete] - public async Task> GetAsync(int idWell, DateTime? dateBegin, double intervalSec = 600, int approxPointsCount = 1024, CancellationToken token = default) - { - var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); - if (telemetry is null) - return Enumerable.Empty(); - - var timezone = telemetryService.GetTimezone(telemetry.Id); - - DateTimeOffset? dateBeginUtc = dateBegin?.ToUtcDateTimeOffset(timezone.Hours); - var dateEnd = dateBeginUtc?.AddSeconds(intervalSec); - - var witsRequest = new WitsRequest() - { - IdTelemetry = telemetry.Id, - DateBeginUtc = dateBeginUtc, - DateEnd = dateEnd, - ApproxPointsCount = approxPointsCount, - TimezoneHours = timezone.Hours - }; - - var recordAllInt = await GetItemsOrDefaultAsync(witsRequest, token); - var recordAllFloat = await GetItemsOrDefaultAsync(witsRequest, token); - var recordAllString = await GetItemsOrDefaultAsync(witsRequest, token); - - var dtos = (recordAllFloat.Union(recordAllInt)).Union(recordAllString) - .GroupBy(g => new - { - g.IdRecord, - g.Date - }) - .Select(g => new WitsRecordDto - { - Id = g.Key.IdRecord, - Date = g.Key.Date, - Items = g.Select(r => new - { - Key = r.IdItem, - r.Value - }).ToDictionary(x => x.Key, x => x.Value) - }); - return dtos; - } - - public IEnumerable GetLastDataByRecordId(int idWell, int idRecord) - { - var result = GetLastData(idWell) - .Where(item => item.IdRecord == idRecord); - return result; - } - - public IEnumerable GetLastData(int idWell) - { - var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); - if (telemetry is null) - return Enumerable.Empty(); - - var lastData = cache.GetValueOrDefault(telemetry.Id); - return lastData?.Values ?? Enumerable.Empty(); - } - - private async Task> GetItemsOrDefaultAsync( - WitsRequest request, - CancellationToken token) - where TEntity : WitsItemBase - where TValue : notnull - { - var query = BuildQuery(request); - - var fullDataCount = await query.CountAsync(token); - if (fullDataCount == 0) - return Enumerable.Empty(); - - if (request.ApproxPointsCount is not null && fullDataCount > 1.75 * request.ApproxPointsCount) - { - var m = (int)Math.Round(1d * fullDataCount / request.ApproxPointsCount!.Value); - if (m > 1) - query = query.Where((d) => (((d.DateTime.DayOfYear * 24 + d.DateTime.Hour) * 60 + d.DateTime.Minute) * 60 + d.DateTime.Second) % m == 0); - } - - var entities = await query - .OrderBy(d => d.DateTime) - .AsNoTracking() - .ToListAsync(token) - .ConfigureAwait(false); - - var items = entities.Select(e => new WitsItemRecordDto - { - IdRecord = e.IdRecord, - Date = e.DateTime.ToRemoteDateTime(request.TimezoneHours), - IdItem = e.IdItem, - Value = new JsonValue(e.Value) + Key = r.IdItem, + r.Value + }).ToDictionary(x => x.Key, x => x.Value) }); - return items; + return dtos; + } + + public IEnumerable GetLastDataByRecordId(int idWell, int idRecord) + { + var result = GetLastData(idWell) + .Where(item => item.IdRecord == idRecord); + return result; + } + + public IEnumerable GetLastData(int idWell) + { + var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); + if (telemetry is null) + return Enumerable.Empty(); + + var lastData = cache.GetValueOrDefault(telemetry.Id); + return lastData?.Values ?? Enumerable.Empty(); + } + + private async Task> GetItemsOrDefaultAsync( + WitsRequest request, + CancellationToken token) + where TEntity : WitsItemBase + where TValue : notnull + { + var query = BuildQuery(request); + + var fullDataCount = await query.CountAsync(token); + if (fullDataCount == 0) + return Enumerable.Empty(); + + if (request.ApproxPointsCount is not null && fullDataCount > 1.75 * request.ApproxPointsCount) + { + var m = (int)Math.Round(1d * fullDataCount / request.ApproxPointsCount!.Value); + if (m > 1) + query = query.Where((d) => (((d.DateTime.DayOfYear * 24 + d.DateTime.Hour) * 60 + d.DateTime.Minute) * 60 + d.DateTime.Second) % m == 0); } - private IQueryable BuildQuery(WitsRequest request) - where TEntity : WitsItemBase - where TValue : notnull + var entities = await query + .OrderBy(d => d.DateTime) + .AsNoTracking() + .ToListAsync(token) + .ConfigureAwait(false); + + var items = entities.Select(e => new WitsItemRecordDto { - var query = db.Set().Where(i => i.IdTelemetry == request.IdTelemetry); + IdRecord = e.IdRecord, + Date = e.DateTime.ToRemoteDateTime(request.TimezoneHours), + IdItem = e.IdItem, + Value = new JsonValue(e.Value) + }); + return items; + } - if (request.IdRecord is not null) - query = query - .Where(d => d.IdRecord == request.IdRecord); + private IQueryable BuildQuery(WitsRequest request) + where TEntity : WitsItemBase + where TValue : notnull + { + var query = db.Set().Where(i => i.IdTelemetry == request.IdTelemetry); - if (request.DateBeginUtc is not null) - query = query - .Where(d => d.DateTime >= request.DateBeginUtc); + if (request.IdRecord is not null) + query = query + .Where(d => d.IdRecord == request.IdRecord); - if (request.DateEnd is not null) - query = query - .Where(d => d.DateTime <= request.DateEnd); + if (request.DateBeginUtc is not null) + query = query + .Where(d => d.DateTime >= request.DateBeginUtc); - return query; - } + if (request.DateEnd is not null) + query = query + .Where(d => d.DateTime <= request.DateEnd); - public async Task SaveDataAsync(int idTelemetry, IEnumerable dtos, CancellationToken token) + return query; + } + + public async Task SaveDataAsync(int idTelemetry, IEnumerable dtos, CancellationToken token) + { + var timezoneHours = telemetryService.GetTimezone(idTelemetry).Hours; + + var cacheTelemetryItems = cache.GetValueOrDefault(idTelemetry); + + var strings = new List(4); + var floats = new List(4); + var ints = new List(4); + + foreach (var record in dtos) { - var timezoneHours = telemetryService.GetTimezone(idTelemetry).Hours; - - var cacheTelemetryItems = cache.GetValueOrDefault(idTelemetry); - - var strings = new List(4); - var floats = new List(4); - var ints = new List(4); - - foreach (var record in dtos) + var dateTime = record.Date.ToUtcDateTimeOffset(timezoneHours); + foreach (var item in record.Items) { - var dateTime = record.Date.ToUtcDateTimeOffset(timezoneHours); - foreach (var item in record.Items) - { - if (cacheTelemetryItems?.TryGetValue((record.Id, item.Key), out var cacheItem) == true) - if (Math.Abs((dateTime - cacheItem.Date).TotalSeconds) < 1) - continue; + if (cacheTelemetryItems?.TryGetValue((record.Id, item.Key), out var cacheItem) == true) + if (Math.Abs((dateTime - cacheItem.Date).TotalSeconds) < 1) + continue; - if (item.Value.Value is string valueString) - { - var entity = MakeEntity(record.Id, item.Key, idTelemetry, dateTime, valueString); - strings.Add(entity); - } - if (item.Value.Value is float valueFloat) - { - var entity = MakeEntity(record.Id, item.Key, idTelemetry, dateTime, valueFloat); - floats.Add(entity); - } - if (item.Value.Value is int valueInt) - { - var entity = MakeEntity(record.Id, item.Key, idTelemetry, dateTime, valueInt); - ints.Add(entity); - } + if (item.Value.Value is string valueString) + { + var entity = MakeEntity(record.Id, item.Key, idTelemetry, dateTime, valueString); + strings.Add(entity); + } + if (item.Value.Value is float valueFloat) + { + var entity = MakeEntity(record.Id, item.Key, idTelemetry, dateTime, valueFloat); + floats.Add(entity); + } + if (item.Value.Value is int valueInt) + { + var entity = MakeEntity(record.Id, item.Key, idTelemetry, dateTime, valueInt); + ints.Add(entity); } } - - try - { - if (strings.Any()) - await db.Database.ExecInsertOrIgnoreAsync(db.Set(), strings, token); - - if (floats.Any()) - await db.Database.ExecInsertOrIgnoreAsync(db.Set(), floats, token); - - if (ints.Any()) - await db.Database.ExecInsertOrIgnoreAsync(db.Set(), ints, token); - } - catch (Exception ex) - { - Trace.TraceError("Exception while saving GTR Wits data", ex); - } - - cache.AddOrUpdate(idTelemetry, - (_) => MakeNewCache(dtos), - (_, oldItemsDictionary) => - { - foreach (var record in dtos) - foreach (var item in record.Items) - { - oldItemsDictionary.AddOrUpdate( - (record.Id, item.Key), - (_) => new WitsItemRecordDto - { - IdRecord = record.Id, - IdItem = item.Key, - Date = record.Date, - Value = item.Value - }, - (_, _) => new WitsItemRecordDto - { - IdRecord = record.Id, - IdItem = item.Key, - Date = record.Date, - Value = item.Value - }); - } - return oldItemsDictionary; - }); } - private static ConcurrentDictionary<(int, int), WitsItemRecordDto> MakeNewCache(IEnumerable dtos) + try { - var items = dtos.SelectMany(record => - record.Items.Select( - item => new WitsItemRecordDto + if (strings.Any()) + await db.Database.ExecInsertOrIgnoreAsync(db.Set(), strings, token); + + if (floats.Any()) + await db.Database.ExecInsertOrIgnoreAsync(db.Set(), floats, token); + + if (ints.Any()) + await db.Database.ExecInsertOrIgnoreAsync(db.Set(), ints, token); + } + catch (Exception ex) + { + Trace.TraceError("Exception while saving GTR Wits data", ex); + } + + cache.AddOrUpdate(idTelemetry, + (_) => MakeNewCache(dtos), + (_, oldItemsDictionary) => + { + foreach (var record in dtos) + foreach (var item in record.Items) { - IdItem = item.Key, - IdRecord = record.Id, - Date = record.Date, - Value = item.Value, - })); + oldItemsDictionary.AddOrUpdate( + (record.Id, item.Key), + (_) => new WitsItemRecordDto + { + IdRecord = record.Id, + IdItem = item.Key, + Date = record.Date, + Value = item.Value + }, + (_, _) => new WitsItemRecordDto + { + IdRecord = record.Id, + IdItem = item.Key, + Date = record.Date, + Value = item.Value + }); + } + return oldItemsDictionary; + }); + } - var groups = items - .GroupBy(item => (item.IdRecord, item.IdItem)); + private static ConcurrentDictionary<(int, int), WitsItemRecordDto> MakeNewCache(IEnumerable dtos) + { + var items = dtos.SelectMany(record => + record.Items.Select( + item => new WitsItemRecordDto + { + IdItem = item.Key, + IdRecord = record.Id, + Date = record.Date, + Value = item.Value, + })); - var pairs = groups.Select(group => new KeyValuePair<(int, int), WitsItemRecordDto>( - group.Key, - group.OrderByDescending(item => item.Date).First())); + var groups = items + .GroupBy(item => (item.IdRecord, item.IdItem)); - return new ConcurrentDictionary<(int, int), WitsItemRecordDto>(pairs); + var pairs = groups.Select(group => new KeyValuePair<(int, int), WitsItemRecordDto>( + group.Key, + group.OrderByDescending(item => item.Date).First())); + + return new ConcurrentDictionary<(int, int), WitsItemRecordDto>(pairs); + } + + private static TEntity MakeEntity(int idRecord, int idItem, int idTelemetry, DateTimeOffset dateTime, TValue value) + where TEntity : WitsItemBase, new() + where TValue : notnull + => new TEntity() + { + IdRecord = idRecord, + IdItem = idItem, + IdTelemetry = idTelemetry, + DateTime = dateTime, + Value = value, + }; + + private static TEntity MakeEntity(WitsItemRecordDto dto, int idTelemetry, DateTimeOffset dateTime) + where TEntity : WitsItemBase, new() + where TValue : notnull + => new TEntity() + { + IdRecord = dto.IdRecord, + IdItem = dto.IdItem, + IdTelemetry = idTelemetry, + DateTime = dateTime, + Value = (TValue)dto.Value.Value, + }; + + private IQueryable BuildQuery(TelemetryPartDeleteRequest request) + where TEntity : WitsItemBase + where TValue : notnull + { + var query = db.Set().Where(i => i.IdTelemetry == request.IdTelemetry); + + if (request.LeDate is not null) + { + var leDate = request.LeDate.Value.ToUniversalTime(); + query = query.Where(o => o.DateTime <= leDate); } - private static TEntity MakeEntity(int idRecord, int idItem, int idTelemetry, DateTimeOffset dateTime, TValue value) - where TEntity : WitsItemBase, new() - where TValue : notnull - => new TEntity() + if (request.GeDate is not null) { - IdRecord = idRecord, - IdItem = idItem, - IdTelemetry = idTelemetry, - DateTime = dateTime, - Value = value, - }; - - private static TEntity MakeEntity(WitsItemRecordDto dto, int idTelemetry, DateTimeOffset dateTime) - where TEntity : WitsItemBase, new() - where TValue : notnull - => new TEntity() - { - IdRecord = dto.IdRecord, - IdItem = dto.IdItem, - IdTelemetry = idTelemetry, - DateTime = dateTime, - Value = (TValue)dto.Value.Value, - }; - - private IQueryable BuildQuery(TelemetryPartDeleteRequest request) - where TEntity : WitsItemBase - where TValue : notnull - { - var query = db.Set().Where(i => i.IdTelemetry == request.IdTelemetry); - - if (request.LeDate is not null) - { - var leDate = request.LeDate.Value.ToUniversalTime(); - query = query.Where(o => o.DateTime <= leDate); - } - - if (request.GeDate is not null) - { - var geDate = request.GeDate.Value.ToUniversalTime(); - query = query.Where(o => o.DateTime >= geDate); - } - - return query; + var geDate = request.GeDate.Value.ToUniversalTime(); + query = query.Where(o => o.DateTime >= geDate); } - public async Task DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token) - { - var result = 0; - result += await DeleteAsync(request, token); - result += await DeleteAsync(request, token); - result += await DeleteAsync(request, token); + return query; + } - return result; - } + public async Task DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token) + { + var result = 0; + result += await DeleteAsync(request, token); + result += await DeleteAsync(request, token); + result += await DeleteAsync(request, token); - private async Task DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token) - where TEntity : WitsItemBase - where TType : notnull - { - var query = BuildQuery(request); - db.Set().RemoveRange(query); - return await db.SaveChangesAsync(token); - } + return result; + } + + private async Task DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token) + where TEntity : WitsItemBase + where TType : notnull + { + var query = BuildQuery(request); + db.Set().RemoveRange(query); + return await db.SaveChangesAsync(token); + } - private class WitsRequest - { - public int IdTelemetry { get; set; } - public DateTimeOffset? DateBeginUtc { get; set; } - public DateTimeOffset? DateEnd { get; set; } - public int? ApproxPointsCount { get; set; } - public double TimezoneHours { get; set; } - public int? IdRecord { get; set; } - } + private class WitsRequest + { + public int IdTelemetry { get; set; } + public DateTimeOffset? DateBeginUtc { get; set; } + public DateTimeOffset? DateEnd { get; set; } + public int? ApproxPointsCount { get; set; } + public double TimezoneHours { get; set; } + public int? IdRecord { get; set; } } } diff --git a/AsbCloudInfrastructure/Repository/LimitingParameterRepository.cs b/AsbCloudInfrastructure/Repository/LimitingParameterRepository.cs index 858558df..dd24e573 100644 --- a/AsbCloudInfrastructure/Repository/LimitingParameterRepository.cs +++ b/AsbCloudInfrastructure/Repository/LimitingParameterRepository.cs @@ -9,98 +9,96 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + + +public class LimitingParameterRepository : ILimitingParameterRepository { + private readonly IAsbCloudDbContext context; - public class LimitingParameterRepository : ILimitingParameterRepository + public LimitingParameterRepository(IAsbCloudDbContext context) { - private readonly IAsbCloudDbContext context; - - public LimitingParameterRepository(IAsbCloudDbContext context) - { - this.context = context; - } - - public async Task DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token) - { - var query = BuildQuery(request); - context.Set().RemoveRange(query); - return await context.SaveChangesAsync(token); - } - - public async Task> GetLimitingParametersAsync(LimitingParameterRequest request, WellDto wellDto, CancellationToken token) - { - var timezoneOffset = wellDto.Timezone.Hours; - var IdTelemetry = wellDto.IdTelemetry!.Value; - return await GetLimitingParametersAsync(request, IdTelemetry, timezoneOffset, token); - } - - public async Task> GetLimitingParametersAsync(LimitingParameterRequest request, int idTelemetry, double timezoneHours, CancellationToken token) - { - var timezoneSpan = TimeSpan.FromHours(timezoneHours); - var query = BuildQuery(request, idTelemetry, timezoneHours); - - var data = (await query.ToListAsync(token)) - .Select(x => new LimitingParameterDataDto - { - IdWell = request.IdWell, - IdTelemetry = x.IdTelemetry, - IdFeedRegulator = x.IdFeedRegulator, - DateStart = x.DateStart.ToOffset(timezoneSpan), - DateEnd = x.DateEnd.ToOffset(timezoneSpan), - DepthStart = x.DepthStart, - DepthEnd = x.DepthEnd - }); - return data; - } - - private IQueryable BuildQuery(LimitingParameterRequest request, int idTelemetry, double timezoneHours) - { - var query = context.LimitingParameter - .OrderBy(x => x.Id) - .Where(x => x.IdTelemetry == idTelemetry) - .AsNoTracking(); - - if (request.GtDate.HasValue) - { - var gtDate = request.GtDate.Value.ToUniversalTime(); - query = query.Where(x => x.DateEnd >= gtDate); - } - - if (request.LtDate.HasValue) - { - var ltDate = request.LtDate.Value.ToUniversalTime(); - query = query.Where(x => x.DateStart <= ltDate); - } - - if (request.GtDepth.HasValue) - query = query.Where(x => x.DepthEnd >= request.GtDepth.Value); - - if (request.LtDepth.HasValue) - query = query.Where(x => x.DepthStart <= request.LtDepth.Value); - - return query; - } - - private IQueryable BuildQuery(TelemetryPartDeleteRequest request) - { - var query = context.Set() - .Where(o => o.IdTelemetry == request.IdTelemetry); - - if (request.LeDate is not null) - { - var leDate = request.LeDate.Value.ToUniversalTime(); - query = query.Where(o => o.DateStart <= leDate); - } - - if (request.GeDate is not null) - { - var geDate = request.GeDate.Value.ToUniversalTime(); - query = query.Where(o => o.DateEnd >= geDate); - } - - return query; - } + this.context = context; } + public async Task DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token) + { + var query = BuildQuery(request); + context.Set().RemoveRange(query); + return await context.SaveChangesAsync(token); + } + + public async Task> GetLimitingParametersAsync(LimitingParameterRequest request, WellDto wellDto, CancellationToken token) + { + var timezoneOffset = wellDto.Timezone.Hours; + var IdTelemetry = wellDto.IdTelemetry!.Value; + return await GetLimitingParametersAsync(request, IdTelemetry, timezoneOffset, token); + } + + public async Task> GetLimitingParametersAsync(LimitingParameterRequest request, int idTelemetry, double timezoneHours, CancellationToken token) + { + var timezoneSpan = TimeSpan.FromHours(timezoneHours); + var query = BuildQuery(request, idTelemetry, timezoneHours); + + var data = (await query.ToListAsync(token)) + .Select(x => new LimitingParameterDataDto + { + IdWell = request.IdWell, + IdTelemetry = x.IdTelemetry, + IdFeedRegulator = x.IdFeedRegulator, + DateStart = x.DateStart.ToOffset(timezoneSpan), + DateEnd = x.DateEnd.ToOffset(timezoneSpan), + DepthStart = x.DepthStart, + DepthEnd = x.DepthEnd + }); + return data; + } + + private IQueryable BuildQuery(LimitingParameterRequest request, int idTelemetry, double timezoneHours) + { + var query = context.LimitingParameter + .OrderBy(x => x.Id) + .Where(x => x.IdTelemetry == idTelemetry) + .AsNoTracking(); + + if (request.GtDate.HasValue) + { + var gtDate = request.GtDate.Value.ToUniversalTime(); + query = query.Where(x => x.DateEnd >= gtDate); + } + + if (request.LtDate.HasValue) + { + var ltDate = request.LtDate.Value.ToUniversalTime(); + query = query.Where(x => x.DateStart <= ltDate); + } + + if (request.GtDepth.HasValue) + query = query.Where(x => x.DepthEnd >= request.GtDepth.Value); + + if (request.LtDepth.HasValue) + query = query.Where(x => x.DepthStart <= request.LtDepth.Value); + + return query; + } + + private IQueryable BuildQuery(TelemetryPartDeleteRequest request) + { + var query = context.Set() + .Where(o => o.IdTelemetry == request.IdTelemetry); + + if (request.LeDate is not null) + { + var leDate = request.LeDate.Value.ToUniversalTime(); + query = query.Where(o => o.DateStart <= leDate); + } + + if (request.GeDate is not null) + { + var geDate = request.GeDate.Value.ToUniversalTime(); + query = query.Where(o => o.DateEnd >= geDate); + } + + return query; + } } diff --git a/AsbCloudInfrastructure/Repository/QueryContainer.cs b/AsbCloudInfrastructure/Repository/QueryContainer.cs index a2179e8b..1ade79d5 100644 --- a/AsbCloudInfrastructure/Repository/QueryContainer.cs +++ b/AsbCloudInfrastructure/Repository/QueryContainer.cs @@ -3,28 +3,26 @@ using Microsoft.EntityFrameworkCore; using System; using System.Linq; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + + +public class QueryContainer where TEntity : class, IId { + protected readonly IAsbCloudDbContext dbContext; + protected readonly DbSet dbSet; + protected readonly Func> GetQuery; - public class QueryContainer where TEntity : class, IId + public QueryContainer(IAsbCloudDbContext context) { - protected readonly IAsbCloudDbContext dbContext; - protected readonly DbSet dbSet; - protected readonly Func> GetQuery; - - public QueryContainer(IAsbCloudDbContext context) - { - dbContext = context; - dbSet = context.Set(); - GetQuery = () => dbSet; - } - - public QueryContainer(IAsbCloudDbContext context, Func, IQueryable> makeQuery) - { - dbContext = context; - dbSet = context.Set(); - GetQuery = () => makeQuery(dbSet); - } + dbContext = context; + dbSet = context.Set(); + GetQuery = () => dbSet; } + public QueryContainer(IAsbCloudDbContext context, Func, IQueryable> makeQuery) + { + dbContext = context; + dbSet = context.Set(); + GetQuery = () => makeQuery(dbSet); + } } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Repository/ScheduleRepository.cs b/AsbCloudInfrastructure/Repository/ScheduleRepository.cs index cbafa45a..d4e5001a 100644 --- a/AsbCloudInfrastructure/Repository/ScheduleRepository.cs +++ b/AsbCloudInfrastructure/Repository/ScheduleRepository.cs @@ -10,93 +10,91 @@ using System.Threading.Tasks; using AsbCloudApp.Requests; using Mapster; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + + +public class ScheduleRepository : CrudWellRelatedRepositoryBase, + IScheduleRepository { + private readonly IWellService wellService; - public class ScheduleRepository : CrudWellRelatedRepositoryBase, - IScheduleRepository + public ScheduleRepository(IAsbCloudDbContext context, IWellService wellService) + : base(context, dbSet => dbSet.Include(s => s.Driller)) { - private readonly IWellService wellService; - - public ScheduleRepository(IAsbCloudDbContext context, IWellService wellService) - : base(context, dbSet => dbSet.Include(s => s.Driller)) - { - this.wellService = wellService; - } - - public async Task> GetAsync(int idWell, DateTimeOffset workTime, CancellationToken token) - { - var entities = await BuildQuery(idWell, workTime) - .AsNoTracking() - .ToArrayAsync(token); - - return entities.Select(Convert); - } - - public async Task GetOrDefaultDrillerAsync(int idWell, DateTimeOffset workTime, CancellationToken token) - { - var entities = await BuildQuery(idWell, workTime) - .AsNoTracking() - .ToArrayAsync(token); - - if (!entities.Any()) - return null; - - var hoursOffset = wellService.GetTimezone(idWell).Hours; - var time = new TimeOnly(workTime.Hour, workTime.Minute, workTime.Second); - - var entity = entities.FirstOrDefault(s => - s.ShiftStart > s.ShiftEnd ^ - (time >= s.ShiftStart && time < s.ShiftEnd) - ); - - return entity?.Driller.Adapt(); - } - - public async Task> GetPageAsync(GetStatRequest request, CancellationToken token) - { - var idWell = request.IdsWells; - var idsDrillers = request.IdsDrillers; - var query = GetQuery().Where(s => request.IdsWells.Contains(s.IdWell)); - if (idsDrillers.Any()) - { - query = query.Where(s => idsDrillers.Contains(s.IdDriller)); - } - - var result = await query.ToArrayAsync(token); - return result.Select(Convert); - - } - - private IQueryable BuildQuery(int idWell, DateTimeOffset workTime) - { - var hoursOffset = wellService.GetTimezone(idWell).Hours; - - var workTimeDateTime = workTime.ToUniversalTime(); - - return GetQuery().Where(s => s.IdWell == idWell - && s.DrillStart <= workTimeDateTime - && s.DrillEnd >= workTimeDateTime); - } - - protected override Schedule Convert(ScheduleDto dto) - { - var entity = base.Convert(dto); - 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.ToOffset(timeSpan); - dto.DrillEnd = entity.DrillEnd.ToOffset(timeSpan); - return dto; - } + this.wellService = wellService; } + public async Task> GetAsync(int idWell, DateTimeOffset workTime, CancellationToken token) + { + var entities = await BuildQuery(idWell, workTime) + .AsNoTracking() + .ToArrayAsync(token); + + return entities.Select(Convert); + } + + public async Task GetOrDefaultDrillerAsync(int idWell, DateTimeOffset workTime, CancellationToken token) + { + var entities = await BuildQuery(idWell, workTime) + .AsNoTracking() + .ToArrayAsync(token); + + if (!entities.Any()) + return null; + + var hoursOffset = wellService.GetTimezone(idWell).Hours; + var time = new TimeOnly(workTime.Hour, workTime.Minute, workTime.Second); + + var entity = entities.FirstOrDefault(s => + s.ShiftStart > s.ShiftEnd ^ + (time >= s.ShiftStart && time < s.ShiftEnd) + ); + + return entity?.Driller.Adapt(); + } + + public async Task> GetPageAsync(GetStatRequest request, CancellationToken token) + { + var idWell = request.IdsWells; + var idsDrillers = request.IdsDrillers; + var query = GetQuery().Where(s => request.IdsWells.Contains(s.IdWell)); + if (idsDrillers.Any()) + { + query = query.Where(s => idsDrillers.Contains(s.IdDriller)); + } + + var result = await query.ToArrayAsync(token); + return result.Select(Convert); + + } + + private IQueryable BuildQuery(int idWell, DateTimeOffset workTime) + { + var hoursOffset = wellService.GetTimezone(idWell).Hours; + + var workTimeDateTime = workTime.ToUniversalTime(); + + return GetQuery().Where(s => s.IdWell == idWell + && s.DrillStart <= workTimeDateTime + && s.DrillEnd >= workTimeDateTime); + } + + protected override Schedule Convert(ScheduleDto dto) + { + var entity = base.Convert(dto); + 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.ToOffset(timeSpan); + dto.DrillEnd = entity.DrillEnd.ToOffset(timeSpan); + return dto; + } } diff --git a/AsbCloudInfrastructure/Repository/SetpointsRequestRepository.cs b/AsbCloudInfrastructure/Repository/SetpointsRequestRepository.cs index 027b2565..02608bd8 100644 --- a/AsbCloudInfrastructure/Repository/SetpointsRequestRepository.cs +++ b/AsbCloudInfrastructure/Repository/SetpointsRequestRepository.cs @@ -10,71 +10,69 @@ using System.Threading; using System.Linq; using AsbCloudApp.Exceptions; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + + +public class SetpointsRequestRepository : CrudWellRelatedCacheRepositoryBase { + private readonly IWellService wellService; - public class SetpointsRequestRepository : CrudWellRelatedCacheRepositoryBase + public SetpointsRequestRepository(IAsbCloudDbContext dbContext, IMemoryCache memoryCache, IWellService wellService) + : base(dbContext, memoryCache, q => q.Include(s => s.Author) + .Include(s => s.Well)) { - private readonly IWellService wellService; - - public SetpointsRequestRepository(IAsbCloudDbContext dbContext, IMemoryCache memoryCache, IWellService wellService) - : base(dbContext, memoryCache, q => q.Include(s => s.Author) - .Include(s => s.Well)) - { - this.wellService = wellService; - } - - //TODO: заметка для рефакторинга. Использовать метод из базового репозитория - public virtual async Task UpdateRangeAsync(IEnumerable dtos, CancellationToken token) - { - if (!dtos.Any()) - return 0; - - var ids = dtos - .Select(o => o.Id) - .Distinct() - .ToArray(); - - if (ids.Any(id => id == default)) - throw new ArgumentInvalidException(nameof(dtos), "Все записи должны иметь Id"); - - if (ids.Length != dtos.Count()) - throw new ArgumentInvalidException(nameof(dtos), "Все записи должны иметь уникальные Id"); - - var existingEntitiesCount = await dbContext.Set() - .Where(o => ids.Contains(o.Id)) - .CountAsync(token); - - if (ids.Length != existingEntitiesCount) - throw new ArgumentInvalidException(nameof(dtos), "Все записи должны существовать в БД"); - - var entities = dtos.Select(Convert); - var entries = entities.Select(entity => dbContext.Set().Update(entity)).ToList(); - - var affected = await dbContext.SaveChangesAsync(token); - - entries.ForEach(entry => entry.State = EntityState.Detached); - - if(affected > 0) - DropCache(); - - return affected; - } - - protected override SetpointsRequestDto Convert(SetpointsRequest src) - { - var result = base.Convert(src); - var timezoneOffsetHours = wellService.GetTimezone(src.IdWell).Hours; - result.UploadDate = src.UploadDate.ToOffset(TimeSpan.FromHours(timezoneOffsetHours)); - return result; - } - - protected override SetpointsRequest Convert(SetpointsRequestDto src) - { - var result = base.Convert(src); - result.UploadDate = src.UploadDate.ToUniversalTime(); - return result; - } + this.wellService = wellService; } + //TODO: заметка для рефакторинга. Использовать метод из базового репозитория + public virtual async Task UpdateRangeAsync(IEnumerable dtos, CancellationToken token) + { + if (!dtos.Any()) + return 0; + + var ids = dtos + .Select(o => o.Id) + .Distinct() + .ToArray(); + + if (ids.Any(id => id == default)) + throw new ArgumentInvalidException(nameof(dtos), "Все записи должны иметь Id"); + + if (ids.Length != dtos.Count()) + throw new ArgumentInvalidException(nameof(dtos), "Все записи должны иметь уникальные Id"); + + var existingEntitiesCount = await dbContext.Set() + .Where(o => ids.Contains(o.Id)) + .CountAsync(token); + + if (ids.Length != existingEntitiesCount) + throw new ArgumentInvalidException(nameof(dtos), "Все записи должны существовать в БД"); + + var entities = dtos.Select(Convert); + var entries = entities.Select(entity => dbContext.Set().Update(entity)).ToList(); + + var affected = await dbContext.SaveChangesAsync(token); + + entries.ForEach(entry => entry.State = EntityState.Detached); + + if(affected > 0) + DropCache(); + + return affected; + } + + protected override SetpointsRequestDto Convert(SetpointsRequest src) + { + var result = base.Convert(src); + var timezoneOffsetHours = wellService.GetTimezone(src.IdWell).Hours; + result.UploadDate = src.UploadDate.ToOffset(TimeSpan.FromHours(timezoneOffsetHours)); + return result; + } + + protected override SetpointsRequest Convert(SetpointsRequestDto src) + { + var result = base.Convert(src); + result.UploadDate = src.UploadDate.ToUniversalTime(); + return result; + } } diff --git a/AsbCloudInfrastructure/Repository/TelemetryWirelineRunOutRepository.cs b/AsbCloudInfrastructure/Repository/TelemetryWirelineRunOutRepository.cs index c57fc57c..032dfc65 100644 --- a/AsbCloudInfrastructure/Repository/TelemetryWirelineRunOutRepository.cs +++ b/AsbCloudInfrastructure/Repository/TelemetryWirelineRunOutRepository.cs @@ -11,100 +11,98 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + + +public class TelemetryWirelineRunOutRepository : ITelemetryWirelineRunOutRepository { + private readonly IAsbCloudDbContext context; + private readonly ITelemetryService telemetryService; + private readonly IWellService wellService; - public class TelemetryWirelineRunOutRepository : ITelemetryWirelineRunOutRepository + public TelemetryWirelineRunOutRepository(IAsbCloudDbContext context, + ITelemetryService telemetryService, + IWellService wellService) { - private readonly IAsbCloudDbContext context; - private readonly ITelemetryService telemetryService; - private readonly IWellService wellService; - - public TelemetryWirelineRunOutRepository(IAsbCloudDbContext context, - ITelemetryService telemetryService, - IWellService wellService) - { - this.context = context; - this.telemetryService = telemetryService; - this.wellService = wellService; - } - - /// - public async Task AddOrUpdateAsync(string uid, TelemetryWirelineRunOutBaseDto dto, CancellationToken token) - { - var idTelemetry = telemetryService.GetOrCreateTelemetryByUid(uid).Id; - var timezoneOffset = telemetryService.GetTimezone(idTelemetry).Hours; - var entity = Convert(idTelemetry, dto, timezoneOffset); - - if (await context.TelemetryWirelineRunOut.AnyAsync(w => w.IdTelemetry == idTelemetry, token)) - context.TelemetryWirelineRunOut.Update(entity); - else - context.TelemetryWirelineRunOut.Add(entity); - - return await context.SaveChangesAsync(token); - } - - /// - public async Task GetOrDefaultAsync(int idWell, CancellationToken token) - { - var well = await wellService.GetOrDefaultAsync(idWell, token).ConfigureAwait(false); - if (well is null) - return null; - - return await GetOrDefaultAsync(well, token); - } - - private async Task GetOrDefaultAsync(WellDto well, CancellationToken token) - { - var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(well.Id); - if (telemetry is null) - return null; - - var entity = await context.TelemetryWirelineRunOut - .Where(x => x.IdTelemetry == telemetry.Id) - .AsNoTracking() - .FirstOrDefaultAsync(token) - .ConfigureAwait(false); - - if (entity is null) - return null; - - var timezoneHours = well.Timezone.Hours; - return Convert(entity, well, timezoneHours); - } - - /// - public async Task> GetAllAsync(int idCompany, CancellationToken token) - { - var wells = await wellService.GetAsync(new() { IdCompany = idCompany }, token) - .ConfigureAwait(false); - - var result = new List(wells.Count()); - foreach (var well in wells) - { - var dto = await GetOrDefaultAsync(well, token); - if (dto is not null) - result.Add(dto); - } - - return result; - } - - private static TelemetryWirelineRunOut Convert(int idTelemetry, TelemetryWirelineRunOutBaseDto dto, double timezoneOffset) - { - var entity = dto.Adapt(); - entity.IdTelemetry = idTelemetry; - entity.DateTime = dto.DateTime.ToUniversalTime(); - return entity; - } - - private static TelemetryWirelineRunOutDto Convert(TelemetryWirelineRunOut entity, WellDto well, double timezoneOffset) - { - var dto = entity.Adapt(); - dto.DateTime = entity.DateTime.ToOffset(TimeSpan.FromHours(timezoneOffset)); - dto.WellInfo = well; - return dto; - } + this.context = context; + this.telemetryService = telemetryService; + this.wellService = wellService; } + /// + public async Task AddOrUpdateAsync(string uid, TelemetryWirelineRunOutBaseDto dto, CancellationToken token) + { + var idTelemetry = telemetryService.GetOrCreateTelemetryByUid(uid).Id; + var timezoneOffset = telemetryService.GetTimezone(idTelemetry).Hours; + var entity = Convert(idTelemetry, dto, timezoneOffset); + + if (await context.TelemetryWirelineRunOut.AnyAsync(w => w.IdTelemetry == idTelemetry, token)) + context.TelemetryWirelineRunOut.Update(entity); + else + context.TelemetryWirelineRunOut.Add(entity); + + return await context.SaveChangesAsync(token); + } + + /// + public async Task GetOrDefaultAsync(int idWell, CancellationToken token) + { + var well = await wellService.GetOrDefaultAsync(idWell, token).ConfigureAwait(false); + if (well is null) + return null; + + return await GetOrDefaultAsync(well, token); + } + + private async Task GetOrDefaultAsync(WellDto well, CancellationToken token) + { + var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(well.Id); + if (telemetry is null) + return null; + + var entity = await context.TelemetryWirelineRunOut + .Where(x => x.IdTelemetry == telemetry.Id) + .AsNoTracking() + .FirstOrDefaultAsync(token) + .ConfigureAwait(false); + + if (entity is null) + return null; + + var timezoneHours = well.Timezone.Hours; + return Convert(entity, well, timezoneHours); + } + + /// + public async Task> GetAllAsync(int idCompany, CancellationToken token) + { + var wells = await wellService.GetAsync(new() { IdCompany = idCompany }, token) + .ConfigureAwait(false); + + var result = new List(wells.Count()); + foreach (var well in wells) + { + var dto = await GetOrDefaultAsync(well, token); + if (dto is not null) + result.Add(dto); + } + + return result; + } + + private static TelemetryWirelineRunOut Convert(int idTelemetry, TelemetryWirelineRunOutBaseDto dto, double timezoneOffset) + { + var entity = dto.Adapt(); + entity.IdTelemetry = idTelemetry; + entity.DateTime = dto.DateTime.ToUniversalTime(); + return entity; + } + + private static TelemetryWirelineRunOutDto Convert(TelemetryWirelineRunOut entity, WellDto well, double timezoneOffset) + { + var dto = entity.Adapt(); + 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 6233dfc3..4b45a9ea 100644 --- a/AsbCloudInfrastructure/Repository/TrajectoryEditableRepository.cs +++ b/AsbCloudInfrastructure/Repository/TrajectoryEditableRepository.cs @@ -12,108 +12,107 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + +/// +/// CRUD-репозиторий для работы с траекториями (плановыми и фактическими) +/// +/// +/// +public class TrajectoryEditableRepository : ITrajectoryEditableRepository + where TEntity : Trajectory + where Tdto : TrajectoryGeoDto { - /// - /// CRUD-репозиторий для работы с траекториями (плановыми и фактическими) - /// - /// - /// - public class TrajectoryEditableRepository : ITrajectoryEditableRepository - where TEntity : Trajectory - where Tdto : TrajectoryGeoDto + private readonly IAsbCloudDbContext db; + private readonly IWellService wellService; + public TrajectoryEditableRepository(IAsbCloudDbContext db, IWellService wellService) { - private readonly IAsbCloudDbContext db; - private readonly IWellService wellService; - public TrajectoryEditableRepository(IAsbCloudDbContext db, IWellService wellService) - { - this.db = db; - this.wellService = wellService; - } + this.db = db; + this.wellService = wellService; + } - public async Task AddRangeAsync(IEnumerable trajectoryRows, CancellationToken token) - { - var idWell = trajectoryRows.First().IdWell; - if (!trajectoryRows.All(r => r.IdWell == idWell)) - throw new ArgumentInvalidException(nameof(trajectoryRows), "Все строки должны относиться к одной скважине"); + public async Task AddRangeAsync(IEnumerable trajectoryRows, CancellationToken token) + { + var idWell = trajectoryRows.First().IdWell; + if (!trajectoryRows.All(r => r.IdWell == idWell)) + throw new ArgumentInvalidException(nameof(trajectoryRows), "Все строки должны относиться к одной скважине"); - var entities = trajectoryRows - .Select(e => - { - var entity = Convert(e); - entity.Id = 0; - return entity; - }); + var entities = trajectoryRows + .Select(e => + { + var entity = Convert(e); + entity.Id = 0; + return entity; + }); - db.Set().AddRange(entities); - return await db.SaveChangesAsync(token); - } + db.Set().AddRange(entities); + return await db.SaveChangesAsync(token); + } - public async Task AddAsync(Tdto trajectoryRow, CancellationToken token) - { - var entity = Convert(trajectoryRow); - entity.Id = 0; - db.Set().Add(entity); - return await db.SaveChangesAsync(token) - .ConfigureAwait(false); - } + public async Task AddAsync(Tdto trajectoryRow, CancellationToken token) + { + var entity = Convert(trajectoryRow); + entity.Id = 0; + db.Set().Add(entity); + return await db.SaveChangesAsync(token) + .ConfigureAwait(false); + } - public async Task DeleteRangeAsync(IEnumerable ids, CancellationToken token) - { - var query = db.Set() - .Where(e => ids.Contains(e.Id)); - db.Set().RemoveRange(query); - return await db.SaveChangesAsync(token) - .ConfigureAwait(false); - } + public async Task DeleteRangeAsync(IEnumerable ids, CancellationToken token) + { + var query = db.Set() + .Where(e => ids.Contains(e.Id)); + db.Set().RemoveRange(query); + return await db.SaveChangesAsync(token) + .ConfigureAwait(false); + } - public async Task DeleteByIdWellAsync(int idWell, CancellationToken token) - { - var query = db.Set() - .Where(e => e.IdWell == idWell); - db.Set().RemoveRange(query); - return await db.SaveChangesAsync(token) - .ConfigureAwait(false); - } + public async Task DeleteByIdWellAsync(int idWell, CancellationToken token) + { + var query = db.Set() + .Where(e => e.IdWell == idWell); + db.Set().RemoveRange(query); + return await db.SaveChangesAsync(token) + .ConfigureAwait(false); + } - public async Task> GetAsync(int idWell, CancellationToken token) - { - var well = wellService.GetOrDefault(idWell) - ?? throw new ArgumentInvalidException(nameof(idWell), "idWell doesn`t exist"); + public async Task> GetAsync(int idWell, CancellationToken token) + { + var well = wellService.GetOrDefault(idWell) + ?? throw new ArgumentInvalidException(nameof(idWell), "idWell doesn`t exist"); - var offsetHours = well.Timezone.Hours; - var query = db.Set() - .AsNoTracking() - .Where(x => x.IdWell == well.Id); - var entities = await query - .OrderBy(e => e.WellboreDepth) - .ToArrayAsync(token); + var offsetHours = well.Timezone.Hours; + var query = db.Set() + .AsNoTracking() + .Where(x => x.IdWell == well.Id); + var entities = await query + .OrderBy(e => e.WellboreDepth) + .ToArrayAsync(token); - var result = entities - .Select(r => Convert(r, offsetHours)); - return result; - } + var result = entities + .Select(r => Convert(r, offsetHours)); + return result; + } - public async Task UpdateAsync(Tdto row, CancellationToken token) - { - var entity = Convert(row); - db.Set().Update(entity); - return await db.SaveChangesAsync(token) - .ConfigureAwait(false); - } + public async Task UpdateAsync(Tdto row, CancellationToken token) + { + var entity = Convert(row); + db.Set().Update(entity); + return await db.SaveChangesAsync(token) + .ConfigureAwait(false); + } - private static Tdto Convert(TEntity entity, double offsetHours) - { - var dto = entity.Adapt(); - dto.UpdateDate = entity.UpdateDate.ToOffset(TimeSpan.FromHours(offsetHours)); - return dto; - } + private static Tdto Convert(TEntity entity, double offsetHours) + { + var dto = entity.Adapt(); + dto.UpdateDate = entity.UpdateDate.ToOffset(TimeSpan.FromHours(offsetHours)); + return dto; + } - private static TEntity Convert(Tdto dto) - { - var entity = dto.Adapt(); - entity.UpdateDate = DateTimeOffset.UtcNow; - return entity; - } + private static TEntity Convert(Tdto dto) + { + var entity = dto.Adapt(); + entity.UpdateDate = DateTimeOffset.UtcNow; + return entity; } } diff --git a/AsbCloudInfrastructure/Repository/TrajectoryNnbRepository.cs b/AsbCloudInfrastructure/Repository/TrajectoryNnbRepository.cs index 1bd3ca2a..fe17315d 100644 --- a/AsbCloudInfrastructure/Repository/TrajectoryNnbRepository.cs +++ b/AsbCloudInfrastructure/Repository/TrajectoryNnbRepository.cs @@ -11,78 +11,77 @@ using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Services; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + +public class TrajectoryNnbRepository : ITrajectoryNnbRepository { - public class TrajectoryNnbRepository : ITrajectoryNnbRepository + private readonly IAsbCloudDbContext db; + private readonly IWellService wellService; + + public TrajectoryNnbRepository(IAsbCloudDbContext db, + IWellService wellService) { - private readonly IAsbCloudDbContext db; - private readonly IWellService wellService; - - public TrajectoryNnbRepository(IAsbCloudDbContext db, - IWellService wellService) + this.db = db; + this.wellService = wellService; + } + + private IQueryable BuildQuery(TrajectoryRequest request) + { + var well = db.Wells.SingleOrDefault(w => w.Id == request.IdWell); + var timezone = wellService.GetTimezone(request.IdWell); + + if (well is null) + throw new ArgumentInvalidException($"Скважина с Id: {request.IdWell} не найдена", nameof(request.IdWell)); + + var query = db.Record7.Where(r => r.IdTelemetry == well.IdTelemetry) + .Where(x => x.IdTelemetry == well.IdTelemetry); + + if (request.GeDate.HasValue) { - this.db = db; - this.wellService = wellService; + var geDate = request.GeDate.Value.ToUniversalTime(); + query = query.Where(r => r.DateTime >= geDate); } - private IQueryable BuildQuery(TrajectoryRequest request) + if (request.LeDate.HasValue) { - var well = db.Wells.SingleOrDefault(w => w.Id == request.IdWell); - var timezone = wellService.GetTimezone(request.IdWell); + var leDate = request.LeDate.Value.ToUniversalTime(); + query = query.Where(r => r.DateTime <= leDate); + } - if (well is null) - throw new ArgumentInvalidException($"Скважина с Id: {request.IdWell} не найдена", nameof(request.IdWell)); + return query.OrderBy(e => e.Deptsvym); + } - var query = db.Record7.Where(r => r.IdTelemetry == well.IdTelemetry) - .Where(x => x.IdTelemetry == well.IdTelemetry); + public async Task> GetAsync(int idWell, CancellationToken token) + { + var request = new TrajectoryRequest() + { + IdWell = idWell, + }; + var result = await GetByRequestAsync(request, token); + return result; + } - if (request.GeDate.HasValue) + public async Task> GetByRequestAsync(TrajectoryRequest request, CancellationToken token) + { + var entities = (await BuildQuery(request) + .Where(coord => coord.Deptsvym.HasValue && + coord.Svyinc.HasValue && + coord.Svyazc.HasValue) + .AsNoTracking() + .ToArrayAsync(token)); + + var result = entities + .Select(coord => new TrajectoryGeoFactDto { - var geDate = request.GeDate.Value.ToUniversalTime(); - query = query.Where(r => r.DateTime >= geDate); - } + IdWell = request.IdWell, + AzimuthMagnetic = coord.Svymtf, + VerticalDepth = coord.Deptsvyv, + WellboreDepth = coord.Deptsvym!.Value, + ZenithAngle = coord.Svyinc!.Value, + AzimuthGeo = coord.Svyazc!.Value + }) + .ToArray(); - if (request.LeDate.HasValue) - { - var leDate = request.LeDate.Value.ToUniversalTime(); - query = query.Where(r => r.DateTime <= leDate); - } - - return query.OrderBy(e => e.Deptsvym); - } - - public async Task> GetAsync(int idWell, CancellationToken token) - { - var request = new TrajectoryRequest() - { - IdWell = idWell, - }; - var result = await GetByRequestAsync(request, token); - return result; - } - - public async Task> GetByRequestAsync(TrajectoryRequest request, CancellationToken token) - { - var entities = (await BuildQuery(request) - .Where(coord => coord.Deptsvym.HasValue && - coord.Svyinc.HasValue && - coord.Svyazc.HasValue) - .AsNoTracking() - .ToArrayAsync(token)); - - var result = entities - .Select(coord => new TrajectoryGeoFactDto - { - IdWell = request.IdWell, - AzimuthMagnetic = coord.Svymtf, - VerticalDepth = coord.Deptsvyv, - WellboreDepth = coord.Deptsvym!.Value, - ZenithAngle = coord.Svyinc!.Value, - AzimuthGeo = coord.Svyazc!.Value - }) - .ToArray(); - - return result; - } + return result; } } diff --git a/AsbCloudInfrastructure/Repository/UserRepository.cs b/AsbCloudInfrastructure/Repository/UserRepository.cs index 0f40b933..2f23bf0d 100644 --- a/AsbCloudInfrastructure/Repository/UserRepository.cs +++ b/AsbCloudInfrastructure/Repository/UserRepository.cs @@ -12,274 +12,272 @@ using System.Threading.Tasks; using Microsoft.Extensions.Caching.Memory; using AsbCloudApp.Data.User; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + + +public class UserRepository : IUserRepository { - - public class UserRepository : IUserRepository + private readonly IAsbCloudDbContext dbContext; + private readonly IUserRoleRepository userRoleRepository; + private const string userCacheTag = "User"; + private const string relationUserUserRoleCacheTag = "RelationUserUserRole"; + private static readonly TimeSpan cacheObsolence = TimeSpan.FromMinutes(15); + private static readonly TypeAdapterConfig userTypeAdapterConfig = TypeAdapterConfig + .NewConfig() + .Ignore(dst => dst.Company, + dst => dst.FileMarks, + dst => dst.Files, + dst => dst.RelationUsersUserRoles) + .Config; + private readonly IMemoryCache memoryCache; + public UserRepository(IAsbCloudDbContext dbContext, IUserRoleRepository userRoleRepository, IMemoryCache memoryCache) { - private readonly IAsbCloudDbContext dbContext; - private readonly IUserRoleRepository userRoleRepository; - private const string userCacheTag = "User"; - private const string relationUserUserRoleCacheTag = "RelationUserUserRole"; - private static readonly TimeSpan cacheObsolence = TimeSpan.FromMinutes(15); - private static readonly TypeAdapterConfig userTypeAdapterConfig = TypeAdapterConfig - .NewConfig() - .Ignore(dst => dst.Company, - dst => dst.FileMarks, - dst => dst.Files, - dst => dst.RelationUsersUserRoles) - .Config; - private readonly IMemoryCache memoryCache; - public UserRepository(IAsbCloudDbContext dbContext, IUserRoleRepository userRoleRepository, IMemoryCache memoryCache) - { - this.dbContext = dbContext; - this.userRoleRepository = userRoleRepository; - this.memoryCache = memoryCache; - } - - public async Task InsertAsync(UserExtendedDto dto, CancellationToken token) - { - dto.Id = default; - var entity = Convert(dto); - await AssertLoginIsBusyAsync(dto.Login, token); - var userRoles = await userRoleRepository.GetByNamesAsync(dto.RoleNames, token).ConfigureAwait(false); - var updatedEntity = await dbContext.Users.AddAsync(entity, token).ConfigureAwait(false); - await dbContext.SaveChangesAsync(token); - - if (userRoles?.Any() == true) - await UpdateRolesCacheForUserAsync(updatedEntity.Entity.Id, userRoles, token); - - DropCacheUsers(); - return updatedEntity.Entity.Id; - } - - public Task InsertRangeAsync(IEnumerable newItems, CancellationToken token) - { - throw new NotImplementedException(); - } - - public async Task> GetAllAsync(CancellationToken token) - { - var users = await GetCacheUserAsync(token); - if (users is null) - return Enumerable.Empty(); - var dtos = new List(); - foreach(var user in users) - { - var dto = Convert(user); - dto.RoleNames = GetRolesNamesByIdUser(user.Id); - dtos.Add(dto); - }; - return dtos; - } - - - public UserExtendedDto? GetOrDefault(int id) - { - var user = GetCacheUser().FirstOrDefault(u => u.Id == id); - if (user is null) - return null; - var dto = Convert(user); - dto.RoleNames = GetRolesNamesByIdUser(dto.Id); - return dto; - } - - public async Task GetOrDefaultAsync(int id, CancellationToken token) - { - var user = (await GetCacheUserAsync(token)).FirstOrDefault(u => u.Id == id); - if (user is null) - return null; - var dto = Convert(user); - dto.RoleNames = GetRolesNamesByIdUser(dto.Id); - return dto; - } - - public async Task UpdateAsync(UserExtendedDto dto, CancellationToken token) - { - if (dto.Id <= 1) - throw new ArgumentInvalidException(nameof(dto), $"Invalid id {dto.Id}. You can't edit this user."); - - var oldUser = (await GetCacheUserAsync(token)).FirstOrDefault(u => u.Id == dto.Id) - ?? throw new ArgumentInvalidException(nameof(dto), $"Invalid id {dto.Id}. You can't edit this user."); - - if (oldUser.Login != dto.Login) - await AssertLoginIsBusyAsync(dto.Login, token); - - var userRoles = await userRoleRepository.GetByNamesAsync(dto.RoleNames, token).ConfigureAwait(false); - await UpdateRolesCacheForUserAsync(dto.Id, userRoles, token); - - var entity = dbContext.Users.FirstOrDefault(u => u.Id == dto.Id) - ?? throw new ArgumentInvalidException(nameof(dto), $"Invalid id {dto.Id}. You can't edit this user."); - - entity.Id = dto.Id; - entity.Login = dto.Login; - entity.Name = dto.Name; - entity.Email = dto.Email; - entity.Phone = dto.Phone; - entity.Surname = dto.Surname; - entity.Patronymic = dto.Patronymic; - entity.Position = dto.Position; - entity.IdCompany = dto.IdCompany; - entity.IdState = dto.IdState; - await dbContext.SaveChangesAsync(token); - DropCacheUsers(); - return entity.Id; - } - - public async Task DeleteAsync(int id, CancellationToken token) - { - var user = (await GetCacheUserAsync(token)).FirstOrDefault(u => u.Id == id) - ?? throw new ArgumentInvalidException(nameof(id), $"Invalid id {id}. You can't edit this user."); - - var query = dbContext - .Users - .Where(u => u.Id == id); - if (query.Any()) - { - var result = dbContext.Users.Remove(query.First()); - await dbContext.SaveChangesAsync(token); - DropCacheUsers(); - return result.Entity.Id; - } - throw new ArgumentInvalidException - (nameof(id), $"Invalid id {id}. You can't edit this user."); - } - - public IEnumerable GetRolesByIdUser(int idUser, int nestedLevel = 0) - { - var roles = GetCachRelationUserUserRoleCacheTag().Where(r => r.IdUser == idUser); - return roles.SelectMany(r => userRoleRepository.GetNestedById(r.IdUserRole, nestedLevel)); - } - - public IEnumerable GetNestedPermissions(int idUser) - { - var roles = GetRolesByIdUser(idUser, 7); - if (roles is null) - return Enumerable.Empty(); - - var permissions = roles - .Where(r => r.Permissions is not null) - .SelectMany(r => r.Permissions); - - return permissions; - } - - public bool HasPermission(int idUser, string permissionName) - { - if (idUser == 1) - return true; - - var relationsToRoles = GetCachRelationUserUserRoleCacheTag() - .Where(r => r.IdUser == idUser); - if (relationsToRoles is null) - return false; - - return userRoleRepository.HasPermission(relationsToRoles - .Select(r => r.IdUserRole), permissionName); - } - - private IEnumerable GetRolesNamesByIdUser(int idUser) - { - var userRoles = GetRolesByIdUser(idUser, 7) - .Select(r => r.Caption) - .Distinct(); - if (userRoles.Any()) - return userRoles; - return Enumerable.Empty(); - } - - private async Task AssertLoginIsBusyAsync(string login, CancellationToken token) - { - var existingUserDto = (await GetCacheUserAsync(token)) - .FirstOrDefault(u => u.Login.ToLower() == login.ToLower()); - - if (existingUserDto is not null) - throw new ArgumentInvalidException(nameof(login), $"Login {login} is busy by {existingUserDto.MakeDisplayName()}, id{existingUserDto.Id}"); - } - - private IEnumerable GetCachRelationUserUserRoleCacheTag() - { - var cache = memoryCache.GetOrCreate(relationUserUserRoleCacheTag, cacheEntry => - { - cacheEntry.AbsoluteExpirationRelativeToNow = cacheObsolence; - cacheEntry.SlidingExpiration = cacheObsolence; - var query = dbContext.RelationUserUserRoles - .Include(r => r.UserRole) - .Include(r => r.User); - var entities = query.ToArray(); - return entities; - }); - return cache!; - } - - private void DropCacheRelationUserUserRoleCacheTag() - { - memoryCache.Remove(relationUserUserRoleCacheTag); - } - - private async Task UpdateRolesCacheForUserAsync(int idUser, IEnumerable roleDtos, CancellationToken token) - { - var relations = dbContext.RelationUserUserRoles.Where(r => r.IdUser == idUser); - dbContext.RelationUserUserRoles.RemoveRange(relations); - var entityRoles = roleDtos.Select(role => new RelationUserUserRole - { - IdUser = idUser, - IdUserRole = role.Id - }); - dbContext.RelationUserUserRoles.AddRange(entityRoles); - await dbContext.SaveChangesAsync(token); - DropCacheRelationUserUserRoleCacheTag(); - } - - private void DropCacheUsers() - => memoryCache.Remove(userCacheTag); - - private IEnumerable GetCacheUser() - { - var cache = memoryCache.GetOrCreate(userCacheTag, cacheEntry => - { - cacheEntry.AbsoluteExpirationRelativeToNow = cacheObsolence; - cacheEntry.SlidingExpiration = cacheObsolence; - var query = dbContext.Users - .Include(r => r.Company) - .Include(r => r.RelationUsersUserRoles); - var entities = query.ToArray(); - return entities; - }); - return cache!; - } - - private Task> GetCacheUserAsync(CancellationToken token) - { - var cache = memoryCache.GetOrCreateAsync(userCacheTag, async (cacheEntry) => - { - cacheEntry.AbsoluteExpirationRelativeToNow = cacheObsolence; - cacheEntry.SlidingExpiration = cacheObsolence; - var query = dbContext.Users - .Include(r => r.Company) - .Include(r => r.RelationUsersUserRoles); - var entities = await query.ToArrayAsync(token); - return entities.AsEnumerable(); - }); - return cache!; - } - - protected User Convert(UserExtendedDto dto) - { - var entity = dto.Adapt(userTypeAdapterConfig); - if (string.IsNullOrEmpty(entity.PasswordHash)) - { - var hash = dbContext.Users.FirstOrDefault(u => u.Id == dto.Id)?.PasswordHash; - entity.PasswordHash = hash ?? string.Empty; - } - - return entity; - } - protected virtual UserExtendedDto Convert(User entity) - { - var dto = entity.Adapt(); - return dto; - } + this.dbContext = dbContext; + this.userRoleRepository = userRoleRepository; + this.memoryCache = memoryCache; } + public async Task InsertAsync(UserExtendedDto dto, CancellationToken token) + { + dto.Id = default; + var entity = Convert(dto); + await AssertLoginIsBusyAsync(dto.Login, token); + var userRoles = await userRoleRepository.GetByNamesAsync(dto.RoleNames, token).ConfigureAwait(false); + var updatedEntity = await dbContext.Users.AddAsync(entity, token).ConfigureAwait(false); + await dbContext.SaveChangesAsync(token); + + if (userRoles?.Any() == true) + await UpdateRolesCacheForUserAsync(updatedEntity.Entity.Id, userRoles, token); + + DropCacheUsers(); + return updatedEntity.Entity.Id; + } + + public Task InsertRangeAsync(IEnumerable newItems, CancellationToken token) + { + throw new NotImplementedException(); + } + + public async Task> GetAllAsync(CancellationToken token) + { + var users = await GetCacheUserAsync(token); + if (users is null) + return Enumerable.Empty(); + var dtos = new List(); + foreach(var user in users) + { + var dto = Convert(user); + dto.RoleNames = GetRolesNamesByIdUser(user.Id); + dtos.Add(dto); + }; + return dtos; + } + + + public UserExtendedDto? GetOrDefault(int id) + { + var user = GetCacheUser().FirstOrDefault(u => u.Id == id); + if (user is null) + return null; + var dto = Convert(user); + dto.RoleNames = GetRolesNamesByIdUser(dto.Id); + return dto; + } + + public async Task GetOrDefaultAsync(int id, CancellationToken token) + { + var user = (await GetCacheUserAsync(token)).FirstOrDefault(u => u.Id == id); + if (user is null) + return null; + var dto = Convert(user); + dto.RoleNames = GetRolesNamesByIdUser(dto.Id); + return dto; + } + + public async Task UpdateAsync(UserExtendedDto dto, CancellationToken token) + { + if (dto.Id <= 1) + throw new ArgumentInvalidException(nameof(dto), $"Invalid id {dto.Id}. You can't edit this user."); + + var oldUser = (await GetCacheUserAsync(token)).FirstOrDefault(u => u.Id == dto.Id) + ?? throw new ArgumentInvalidException(nameof(dto), $"Invalid id {dto.Id}. You can't edit this user."); + + if (oldUser.Login != dto.Login) + await AssertLoginIsBusyAsync(dto.Login, token); + + var userRoles = await userRoleRepository.GetByNamesAsync(dto.RoleNames, token).ConfigureAwait(false); + await UpdateRolesCacheForUserAsync(dto.Id, userRoles, token); + + var entity = dbContext.Users.FirstOrDefault(u => u.Id == dto.Id) + ?? throw new ArgumentInvalidException(nameof(dto), $"Invalid id {dto.Id}. You can't edit this user."); + + entity.Id = dto.Id; + entity.Login = dto.Login; + entity.Name = dto.Name; + entity.Email = dto.Email; + entity.Phone = dto.Phone; + entity.Surname = dto.Surname; + entity.Patronymic = dto.Patronymic; + entity.Position = dto.Position; + entity.IdCompany = dto.IdCompany; + entity.IdState = dto.IdState; + await dbContext.SaveChangesAsync(token); + DropCacheUsers(); + return entity.Id; + } + + public async Task DeleteAsync(int id, CancellationToken token) + { + var user = (await GetCacheUserAsync(token)).FirstOrDefault(u => u.Id == id) + ?? throw new ArgumentInvalidException(nameof(id), $"Invalid id {id}. You can't edit this user."); + + var query = dbContext + .Users + .Where(u => u.Id == id); + if (query.Any()) + { + var result = dbContext.Users.Remove(query.First()); + await dbContext.SaveChangesAsync(token); + DropCacheUsers(); + return result.Entity.Id; + } + throw new ArgumentInvalidException + (nameof(id), $"Invalid id {id}. You can't edit this user."); + } + + public IEnumerable GetRolesByIdUser(int idUser, int nestedLevel = 0) + { + var roles = GetCachRelationUserUserRoleCacheTag().Where(r => r.IdUser == idUser); + return roles.SelectMany(r => userRoleRepository.GetNestedById(r.IdUserRole, nestedLevel)); + } + + public IEnumerable GetNestedPermissions(int idUser) + { + var roles = GetRolesByIdUser(idUser, 7); + if (roles is null) + return Enumerable.Empty(); + + var permissions = roles + .Where(r => r.Permissions is not null) + .SelectMany(r => r.Permissions); + + return permissions; + } + + public bool HasPermission(int idUser, string permissionName) + { + if (idUser == 1) + return true; + + var relationsToRoles = GetCachRelationUserUserRoleCacheTag() + .Where(r => r.IdUser == idUser); + if (relationsToRoles is null) + return false; + + return userRoleRepository.HasPermission(relationsToRoles + .Select(r => r.IdUserRole), permissionName); + } + + private IEnumerable GetRolesNamesByIdUser(int idUser) + { + var userRoles = GetRolesByIdUser(idUser, 7) + .Select(r => r.Caption) + .Distinct(); + if (userRoles.Any()) + return userRoles; + return Enumerable.Empty(); + } + + private async Task AssertLoginIsBusyAsync(string login, CancellationToken token) + { + var existingUserDto = (await GetCacheUserAsync(token)) + .FirstOrDefault(u => u.Login.ToLower() == login.ToLower()); + + if (existingUserDto is not null) + throw new ArgumentInvalidException(nameof(login), $"Login {login} is busy by {existingUserDto.MakeDisplayName()}, id{existingUserDto.Id}"); + } + + private IEnumerable GetCachRelationUserUserRoleCacheTag() + { + var cache = memoryCache.GetOrCreate(relationUserUserRoleCacheTag, cacheEntry => + { + cacheEntry.AbsoluteExpirationRelativeToNow = cacheObsolence; + cacheEntry.SlidingExpiration = cacheObsolence; + var query = dbContext.RelationUserUserRoles + .Include(r => r.UserRole) + .Include(r => r.User); + var entities = query.ToArray(); + return entities; + }); + return cache!; + } + + private void DropCacheRelationUserUserRoleCacheTag() + { + memoryCache.Remove(relationUserUserRoleCacheTag); + } + + private async Task UpdateRolesCacheForUserAsync(int idUser, IEnumerable roleDtos, CancellationToken token) + { + var relations = dbContext.RelationUserUserRoles.Where(r => r.IdUser == idUser); + dbContext.RelationUserUserRoles.RemoveRange(relations); + var entityRoles = roleDtos.Select(role => new RelationUserUserRole + { + IdUser = idUser, + IdUserRole = role.Id + }); + dbContext.RelationUserUserRoles.AddRange(entityRoles); + await dbContext.SaveChangesAsync(token); + DropCacheRelationUserUserRoleCacheTag(); + } + + private void DropCacheUsers() + => memoryCache.Remove(userCacheTag); + + private IEnumerable GetCacheUser() + { + var cache = memoryCache.GetOrCreate(userCacheTag, cacheEntry => + { + cacheEntry.AbsoluteExpirationRelativeToNow = cacheObsolence; + cacheEntry.SlidingExpiration = cacheObsolence; + var query = dbContext.Users + .Include(r => r.Company) + .Include(r => r.RelationUsersUserRoles); + var entities = query.ToArray(); + return entities; + }); + return cache!; + } + + private Task> GetCacheUserAsync(CancellationToken token) + { + var cache = memoryCache.GetOrCreateAsync(userCacheTag, async (cacheEntry) => + { + cacheEntry.AbsoluteExpirationRelativeToNow = cacheObsolence; + cacheEntry.SlidingExpiration = cacheObsolence; + var query = dbContext.Users + .Include(r => r.Company) + .Include(r => r.RelationUsersUserRoles); + var entities = await query.ToArrayAsync(token); + return entities.AsEnumerable(); + }); + return cache!; + } + + protected User Convert(UserExtendedDto dto) + { + var entity = dto.Adapt(userTypeAdapterConfig); + if (string.IsNullOrEmpty(entity.PasswordHash)) + { + var hash = dbContext.Users.FirstOrDefault(u => u.Id == dto.Id)?.PasswordHash; + entity.PasswordHash = hash ?? string.Empty; + } + + return entity; + } + protected virtual UserExtendedDto Convert(User entity) + { + var dto = entity.Adapt(); + return dto; + } } diff --git a/AsbCloudInfrastructure/Repository/UserRoleRepository.cs b/AsbCloudInfrastructure/Repository/UserRoleRepository.cs index 799fe857..5301a7d5 100644 --- a/AsbCloudInfrastructure/Repository/UserRoleRepository.cs +++ b/AsbCloudInfrastructure/Repository/UserRoleRepository.cs @@ -14,287 +14,285 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + + +public class UserRoleRepository : IUserRoleRepository { + private readonly IAsbCloudDbContext dbContext; + private readonly IMemoryCache memoryCache; - public class UserRoleRepository : IUserRoleRepository + public UserRoleRepository(IAsbCloudDbContext dbContext, IMemoryCache memoryCache) { - private readonly IAsbCloudDbContext dbContext; - private readonly IMemoryCache memoryCache; + this.dbContext = dbContext; + this.memoryCache = memoryCache; + } - public UserRoleRepository(IAsbCloudDbContext dbContext, IMemoryCache memoryCache) - { - this.dbContext = dbContext; - this.memoryCache = memoryCache; - } - - public async Task InsertAsync(UserRoleDto dto, CancellationToken token) - { - var entity = dto.Adapt(); - var updatedEntity = dbContext.UserRoles.Add(entity); - await dbContext.SaveChangesAsync(token); - - if (updatedEntity.IsKeySet) - { - dto.Id = updatedEntity.Entity.Id; - await UpdatePermissionsAsync(dto, token); - await UpdateIncludedRolesAsync(dto, token); - - DropCacheUserRole(); - return updatedEntity.Entity.Id; - } - return 0; - } - - public Task InsertRangeAsync(IEnumerable newItems, CancellationToken token) - { - throw new NotImplementedException(); - } - - public async Task> GetAllAsync(CancellationToken token) - { - var entities = await GetCacheUserRoleAsync(token) - .ConfigureAwait(false); - - return entities.Select(Convert); - } - - public UserRoleDto? GetOrDefault(int id) - { - var entity = GetCacheUserRole().FirstOrDefault(x => x.Id == id); - if (entity is null) - return null; - return Convert(entity); - } - - public async Task GetOrDefaultAsync(int id, CancellationToken token) - { - var entity = (await GetCacheUserRoleAsync(token) - .ConfigureAwait(false)).FirstOrDefault(r => r.Id == id); - if (entity is null) - return null; - return Convert(entity); - } - - public async Task> GetByNamesAsync(IEnumerable names, CancellationToken token) - { - if (names?.Any() != true) - return Enumerable.Empty(); - - var entities = (await GetCacheUserRoleAsync(token)) - .Where(r => names.Contains(r.Caption)); - - if (entities?.Count() != names.Count()) - throw new ArgumentInvalidException(nameof(names), "Invalid role names"); - - return entities.Select(Convert); - } - - public async Task UpdateAsync(UserRoleDto dto, CancellationToken token) + public async Task InsertAsync(UserRoleDto dto, CancellationToken token) + { + var entity = dto.Adapt(); + var updatedEntity = dbContext.UserRoles.Add(entity); + await dbContext.SaveChangesAsync(token); + + if (updatedEntity.IsKeySet) { + dto.Id = updatedEntity.Entity.Id; await UpdatePermissionsAsync(dto, token); await UpdateIncludedRolesAsync(dto, token); - var entity = Convert(dto); - var result = dbContext.UserRoles.Upsert(entity); - await dbContext.SaveChangesAsync(token); DropCacheUserRole(); - return result.Entity.Id; - } - - public IEnumerable GetNestedById(int id, int recursionLevel = 7) - { - var role = GetCacheUserRole() - .FirstOrDefault(r => r.Id == id); - if (role is null) - return Enumerable.Empty(); - - var roles = new SortedSet(ComparerIId.GetInstance()) { Convert(role) }; - - if (recursionLevel <= 0 || role.RelationUserRoleUserRoles?.Any() != true) - return roles; - - foreach (var relation in role.RelationUserRoleUserRoles) - { - var nestedRoles = GetNestedById(relation.IdInclude, --recursionLevel); - if (nestedRoles?.Any() != true) - continue; - foreach (var nestedRole in nestedRoles) - roles.Add(nestedRole); - } - return roles; - } - - public async Task DeleteAsync(int id, CancellationToken token) - { - var entity = (await GetCacheUserRoleAsync(token)).FirstOrDefault(r => r.Id == id); - - if (entity is not null) - { - var removeEntity = dbContext.UserRoles.Remove(entity); - await dbContext.SaveChangesAsync(token); - DropCacheUserRole(); - return removeEntity.Entity.Id; - } - else return 0; - } - - public bool HasPermission(IEnumerable rolesIds, string permissionName) - { - var permissionInfo = GetCacheRelationUserRolePermissions() - .FirstOrDefault(p => p. Permission?.Name.ToLower() == permissionName.ToLower()) - ?.Permission; - - if (permissionInfo is null) - return false; - - if (rolesIds.Contains(1)) - return true; - - var idPermissionInfo = permissionInfo.Id; - var entities = GetCacheUserRole() - .Where(r => rolesIds.Contains(r.Id)); - - foreach (var role in entities) - if (HasPermission(role, idPermissionInfo)) - return true; - return false; - } - - private bool HasPermission(UserRole userRole, int idPermission, int recursionLevel = 7) - { - if (userRole.RelationUserRolePermissions.Any(p => p.IdPermission == idPermission)) - return true; - - if (recursionLevel <= 0 || userRole.RelationUserRoleUserRoles?.Any() != true) - return false; - - foreach (var relation in userRole.RelationUserRoleUserRoles) - { - var entity = GetCacheUserRole() - .First(p => p.Id == relation.IdInclude); - if (HasPermission(entity, idPermission, --recursionLevel)) - return true; - } - return false; - } - - private IEnumerable GetNestedByIds(IEnumerable ids, int recursionLevel = 7) - { - var roles = new List(); - foreach (var id in ids) - roles.AddRange(GetNestedById(id, recursionLevel)); - - return roles; - } - - private async Task UpdateIncludedRolesAsync(UserRoleDto dto, CancellationToken token) - { - if (!dto.Roles.Any()) - return; - - var idsIncludeRole = GetNestedByIds(dto.Roles.Select(x => x.Id)).Select(x => x.Id); - - if (idsIncludeRole.Any(x => x == dto.Id)) - throw new ArgumentInvalidException(nameof(dto), "Invalid include role (self reference)"); - - var removeRelationsQuery = dbContext.RelationUserRoleUserRoles - .Where(r => r.Id == dto.Id); - - dbContext.RelationUserRoleUserRoles.RemoveRange(removeRelationsQuery); - var newRelations = dto.Roles.Select(r => new RelationUserRoleUserRole - { - Id = dto.Id, - IdInclude = r.Id, - }); - dbContext.RelationUserRoleUserRoles.AddRange(newRelations); - await dbContext.SaveChangesAsync(token); - DropCacheRelationUserRoleUserRole(); - } - - private async Task UpdatePermissionsAsync(UserRoleDto dto, CancellationToken token) - { - if (dto?.Permissions is null) - return; - - var relations = await dbContext.RelationUserRolePermissions - .Where(r => r.IdUserRole == dto.Id) - .ToListAsync(token) - .ConfigureAwait(false); - dbContext.RelationUserRolePermissions.RemoveRange(relations); - - if (dto.Permissions.Any()) - { - var newRelations = dto.Permissions.Select(p => new RelationUserRolePermission - { - IdPermission = p.Id, - IdUserRole = dto.Id, - }); - - await dbContext.RelationUserRolePermissions.AddRangeAsync(newRelations, token); - await dbContext.SaveChangesAsync(token); - } - DropCacheRelationUserRolePermissions(); - } - - private Task> GetCacheUserRoleAsync(CancellationToken token) - => memoryCache.GetOrCreateBasicAsync(dbContext.Set() - .Include(r => r.RelationUserRolePermissions) - .Include(r => r.RelationUserRoleUserRoles) - .Include(r => r.RelationUsersUserRoles), token); - - private IEnumerable GetCacheUserRole() - => memoryCache.GetOrCreateBasic(dbContext.Set() - .Include(r => r.RelationUserRolePermissions) - .Include(r => r.RelationUserRoleUserRoles) - .Include(r => r.RelationUsersUserRoles)); - - private void DropCacheUserRole() - => memoryCache.DropBasic(); - - private void DropCacheRelationUserRoleUserRole() - => memoryCache.DropBasic(); - - private IEnumerable GetCacheRelationUserRolePermissions() - => memoryCache.GetOrCreateBasic(dbContext.Set() - .Include(r => r.UserRole) - .Include(r => r.Permission)); - - private void DropCacheRelationUserRolePermissions() - => memoryCache.DropBasic(); - - private UserRoleDto Convert(UserRole entity) - { - var dto = entity.Adapt(); - if (entity.RelationUserRolePermissions?.Any() == true) - { - dto.Permissions = GetCacheRelationUserRolePermissions() - .Where(r => entity.Id == r.IdUserRole) - .Select(r => Convert(r.Permission)); - } - - if (entity.RelationUserRoleUserRoles?.Any() == true) - { - var rolesCache = GetCacheUserRole(); - dto.Roles = entity.RelationUserRoleUserRoles - .Select(rel => Convert(rolesCache - .First(r => r.Id == rel.IdInclude))) - .ToArray(); - } - return dto; - } - - private static PermissionDto Convert(Permission entity) - { - var dto = entity.Adapt(); - return dto; - } - - private static UserRole Convert(UserRoleDto dto) - { - var entity = dto.Adapt(); - return entity; + return updatedEntity.Entity.Id; } + return 0; } + public Task InsertRangeAsync(IEnumerable newItems, CancellationToken token) + { + throw new NotImplementedException(); + } + + public async Task> GetAllAsync(CancellationToken token) + { + var entities = await GetCacheUserRoleAsync(token) + .ConfigureAwait(false); + + return entities.Select(Convert); + } + + public UserRoleDto? GetOrDefault(int id) + { + var entity = GetCacheUserRole().FirstOrDefault(x => x.Id == id); + if (entity is null) + return null; + return Convert(entity); + } + + public async Task GetOrDefaultAsync(int id, CancellationToken token) + { + var entity = (await GetCacheUserRoleAsync(token) + .ConfigureAwait(false)).FirstOrDefault(r => r.Id == id); + if (entity is null) + return null; + return Convert(entity); + } + + public async Task> GetByNamesAsync(IEnumerable names, CancellationToken token) + { + if (names?.Any() != true) + return Enumerable.Empty(); + + var entities = (await GetCacheUserRoleAsync(token)) + .Where(r => names.Contains(r.Caption)); + + if (entities?.Count() != names.Count()) + throw new ArgumentInvalidException(nameof(names), "Invalid role names"); + + return entities.Select(Convert); + } + + public async Task UpdateAsync(UserRoleDto dto, CancellationToken token) + { + await UpdatePermissionsAsync(dto, token); + await UpdateIncludedRolesAsync(dto, token); + + var entity = Convert(dto); + var result = dbContext.UserRoles.Upsert(entity); + await dbContext.SaveChangesAsync(token); + DropCacheUserRole(); + return result.Entity.Id; + } + + public IEnumerable GetNestedById(int id, int recursionLevel = 7) + { + var role = GetCacheUserRole() + .FirstOrDefault(r => r.Id == id); + if (role is null) + return Enumerable.Empty(); + + var roles = new SortedSet(ComparerIId.GetInstance()) { Convert(role) }; + + if (recursionLevel <= 0 || role.RelationUserRoleUserRoles?.Any() != true) + return roles; + + foreach (var relation in role.RelationUserRoleUserRoles) + { + var nestedRoles = GetNestedById(relation.IdInclude, --recursionLevel); + if (nestedRoles?.Any() != true) + continue; + foreach (var nestedRole in nestedRoles) + roles.Add(nestedRole); + } + return roles; + } + + public async Task DeleteAsync(int id, CancellationToken token) + { + var entity = (await GetCacheUserRoleAsync(token)).FirstOrDefault(r => r.Id == id); + + if (entity is not null) + { + var removeEntity = dbContext.UserRoles.Remove(entity); + await dbContext.SaveChangesAsync(token); + DropCacheUserRole(); + return removeEntity.Entity.Id; + } + else return 0; + } + + public bool HasPermission(IEnumerable rolesIds, string permissionName) + { + var permissionInfo = GetCacheRelationUserRolePermissions() + .FirstOrDefault(p => p. Permission?.Name.ToLower() == permissionName.ToLower()) + ?.Permission; + + if (permissionInfo is null) + return false; + + if (rolesIds.Contains(1)) + return true; + + var idPermissionInfo = permissionInfo.Id; + var entities = GetCacheUserRole() + .Where(r => rolesIds.Contains(r.Id)); + + foreach (var role in entities) + if (HasPermission(role, idPermissionInfo)) + return true; + return false; + } + + private bool HasPermission(UserRole userRole, int idPermission, int recursionLevel = 7) + { + if (userRole.RelationUserRolePermissions.Any(p => p.IdPermission == idPermission)) + return true; + + if (recursionLevel <= 0 || userRole.RelationUserRoleUserRoles?.Any() != true) + return false; + + foreach (var relation in userRole.RelationUserRoleUserRoles) + { + var entity = GetCacheUserRole() + .First(p => p.Id == relation.IdInclude); + if (HasPermission(entity, idPermission, --recursionLevel)) + return true; + } + return false; + } + + private IEnumerable GetNestedByIds(IEnumerable ids, int recursionLevel = 7) + { + var roles = new List(); + foreach (var id in ids) + roles.AddRange(GetNestedById(id, recursionLevel)); + + return roles; + } + + private async Task UpdateIncludedRolesAsync(UserRoleDto dto, CancellationToken token) + { + if (!dto.Roles.Any()) + return; + + var idsIncludeRole = GetNestedByIds(dto.Roles.Select(x => x.Id)).Select(x => x.Id); + + if (idsIncludeRole.Any(x => x == dto.Id)) + throw new ArgumentInvalidException(nameof(dto), "Invalid include role (self reference)"); + + var removeRelationsQuery = dbContext.RelationUserRoleUserRoles + .Where(r => r.Id == dto.Id); + + dbContext.RelationUserRoleUserRoles.RemoveRange(removeRelationsQuery); + var newRelations = dto.Roles.Select(r => new RelationUserRoleUserRole + { + Id = dto.Id, + IdInclude = r.Id, + }); + dbContext.RelationUserRoleUserRoles.AddRange(newRelations); + await dbContext.SaveChangesAsync(token); + DropCacheRelationUserRoleUserRole(); + } + + private async Task UpdatePermissionsAsync(UserRoleDto dto, CancellationToken token) + { + if (dto?.Permissions is null) + return; + + var relations = await dbContext.RelationUserRolePermissions + .Where(r => r.IdUserRole == dto.Id) + .ToListAsync(token) + .ConfigureAwait(false); + dbContext.RelationUserRolePermissions.RemoveRange(relations); + + if (dto.Permissions.Any()) + { + var newRelations = dto.Permissions.Select(p => new RelationUserRolePermission + { + IdPermission = p.Id, + IdUserRole = dto.Id, + }); + + await dbContext.RelationUserRolePermissions.AddRangeAsync(newRelations, token); + await dbContext.SaveChangesAsync(token); + } + DropCacheRelationUserRolePermissions(); + } + + private Task> GetCacheUserRoleAsync(CancellationToken token) + => memoryCache.GetOrCreateBasicAsync(dbContext.Set() + .Include(r => r.RelationUserRolePermissions) + .Include(r => r.RelationUserRoleUserRoles) + .Include(r => r.RelationUsersUserRoles), token); + + private IEnumerable GetCacheUserRole() + => memoryCache.GetOrCreateBasic(dbContext.Set() + .Include(r => r.RelationUserRolePermissions) + .Include(r => r.RelationUserRoleUserRoles) + .Include(r => r.RelationUsersUserRoles)); + + private void DropCacheUserRole() + => memoryCache.DropBasic(); + + private void DropCacheRelationUserRoleUserRole() + => memoryCache.DropBasic(); + + private IEnumerable GetCacheRelationUserRolePermissions() + => memoryCache.GetOrCreateBasic(dbContext.Set() + .Include(r => r.UserRole) + .Include(r => r.Permission)); + + private void DropCacheRelationUserRolePermissions() + => memoryCache.DropBasic(); + + private UserRoleDto Convert(UserRole entity) + { + var dto = entity.Adapt(); + if (entity.RelationUserRolePermissions?.Any() == true) + { + dto.Permissions = GetCacheRelationUserRolePermissions() + .Where(r => entity.Id == r.IdUserRole) + .Select(r => Convert(r.Permission)); + } + + if (entity.RelationUserRoleUserRoles?.Any() == true) + { + var rolesCache = GetCacheUserRole(); + dto.Roles = entity.RelationUserRoleUserRoles + .Select(rel => Convert(rolesCache + .First(r => r.Id == rel.IdInclude))) + .ToArray(); + } + return dto; + } + + private static PermissionDto Convert(Permission entity) + { + var dto = entity.Adapt(); + return dto; + } + + private static UserRole Convert(UserRoleDto dto) + { + var entity = dto.Adapt(); + return entity; + } } diff --git a/AsbCloudInfrastructure/Repository/UserSettingsRepository.cs b/AsbCloudInfrastructure/Repository/UserSettingsRepository.cs index 56b797ca..b0ec32c6 100644 --- a/AsbCloudInfrastructure/Repository/UserSettingsRepository.cs +++ b/AsbCloudInfrastructure/Repository/UserSettingsRepository.cs @@ -5,69 +5,68 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + +public class UserSettingsRepository : IUserSettingsRepository { - public class UserSettingsRepository : IUserSettingsRepository + private readonly IAsbCloudDbContext context; + + public UserSettingsRepository(IAsbCloudDbContext context) { - private readonly IAsbCloudDbContext context; + this.context = context; + } - public UserSettingsRepository(IAsbCloudDbContext context) + public Task GetOrDefaultAsync(int userId, string key, CancellationToken token) + => context.Set() + .Where(s => s.IdUser == userId && s.Key == key) + .Select(s => s.Value) + .FirstOrDefaultAsync(token); + + public async Task UpsertAsync(int userId, string key, System.Text.Json.JsonDocument value, CancellationToken token) + { + var set = context.Set(); + var updatingItem = await set + .FirstOrDefaultAsync(s => s.IdUser == userId && s.Key == key, token); + + if (updatingItem is null) { - this.context = context; - } - - public Task GetOrDefaultAsync(int userId, string key, CancellationToken token) - => context.Set() - .Where(s => s.IdUser == userId && s.Key == key) - .Select(s => s.Value) - .FirstOrDefaultAsync(token); - - public async Task UpsertAsync(int userId, string key, System.Text.Json.JsonDocument value, CancellationToken token) - { - var set = context.Set(); - var updatingItem = await set - .FirstOrDefaultAsync(s => s.IdUser == userId && s.Key == key, token); - - if (updatingItem is null) + var settings = new UserSetting { - var settings = new UserSetting - { - IdUser = userId, - Key = key, - Value = value, - }; - set.Add(settings); - } - else - { - updatingItem.Value = value; - set.Update(updatingItem); - } - - return await context.SaveChangesAsync(token); + IdUser = userId, + Key = key, + Value = value, + }; + set.Add(settings); } - - public async Task DeleteAsync(int userId, string key, CancellationToken token) + else { - var set = context.Set(); - var removingItem = await set - .FirstOrDefaultAsync(s => s.IdUser == userId && s.Key == key, token); - - if (removingItem is null) - return IUserSettingsRepository.ErrorKeyNotFound; - - set.Remove(removingItem); - return await context.SaveChangesAsync(token); + updatingItem.Value = value; + set.Update(updatingItem); } - - public async Task DeleteAsync(int userId, CancellationToken token) - { - var set = context.Set(); - var removingItems = set - .Where(s => s.IdUser == userId); - set.RemoveRange(removingItems); - return await context.SaveChangesAsync(token); - } + return await context.SaveChangesAsync(token); + } + + public async Task DeleteAsync(int userId, string key, CancellationToken token) + { + var set = context.Set(); + var removingItem = await set + .FirstOrDefaultAsync(s => s.IdUser == userId && s.Key == key, token); + + if (removingItem is null) + return IUserSettingsRepository.ErrorKeyNotFound; + + set.Remove(removingItem); + return await context.SaveChangesAsync(token); + } + + public async Task DeleteAsync(int userId, CancellationToken token) + { + var set = context.Set(); + var removingItems = set + .Where(s => s.IdUser == userId); + + set.RemoveRange(removingItems); + return await context.SaveChangesAsync(token); } } diff --git a/AsbCloudInfrastructure/Repository/WellFinalDocumentsRepository.cs b/AsbCloudInfrastructure/Repository/WellFinalDocumentsRepository.cs index 7729242a..2b14f5f7 100644 --- a/AsbCloudInfrastructure/Repository/WellFinalDocumentsRepository.cs +++ b/AsbCloudInfrastructure/Repository/WellFinalDocumentsRepository.cs @@ -13,129 +13,127 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + + +public class WellFinalDocumentsRepository : IWellFinalDocumentsRepository { + private readonly IAsbCloudDbContext context; + private readonly FileService fileService; + private readonly IUserRepository userRepository; - public class WellFinalDocumentsRepository : IWellFinalDocumentsRepository + public WellFinalDocumentsRepository(IAsbCloudDbContext context, + FileService fileService, + IUserRepository userRepository) { - private readonly IAsbCloudDbContext context; - private readonly FileService fileService; - private readonly IUserRepository userRepository; - - public WellFinalDocumentsRepository(IAsbCloudDbContext context, - FileService fileService, - IUserRepository userRepository) - { - this.context = context; - this.fileService = fileService; - this.userRepository = userRepository; - } - - /// - public async Task> UpdateRangeAsync(int idWell, IEnumerable dtos, CancellationToken token) - { - if (!dtos.Any()) - throw new ArgumentInvalidException(nameof(dtos), "Данные по категориям отсутствуют."); - - var entities = dtos - .Where(dto => dto.IdsPublishers?.Any() == true) - .SelectMany(dto => dto.IdsPublishers - .Select(idUser => new WellFinalDocument - { - IdCategory = dto.IdCategory, - IdWell = idWell, - IdUser = idUser - })); - - var itemsToDelete = context.WellFinalDocuments.Where(d => d.IdWell == idWell); - context.WellFinalDocuments.RemoveRange(itemsToDelete); - - context.WellFinalDocuments.AddRange(entities); - await context.SaveChangesAsync(token).ConfigureAwait(false); - - return entities.Adapt>(); - } - - /// - public async Task GetByWellIdAsync(int idWell, int idUser, CancellationToken token) - { - var entities = await context.WellFinalDocuments - .Include(d => d.Category) - .Include(d => d.User) - .Where(d => d.IdWell == idWell) - .AsNoTracking() - .ToArrayAsync(token) - .ConfigureAwait(false); - - var entitiesGroups = entities - .GroupBy(d => d.IdCategory); - - var categoriesIds = entitiesGroups - .Select(g => g.Key); - - var files = (await fileService - .GetInfosAsync(new FileRequest { IdWell = idWell }, token) - .ConfigureAwait(false)) - .Where(f => categoriesIds.Contains(f.IdCategory)) - .ToArray(); - - var docs = entitiesGroups.Select((g) => new WellFinalDocumentDto - { - IdCategory = g.Key, - FilesCount = files - .Where(f => f.IdCategory == g.Key) - .Count(), - File = files - .Where(f => f.IdCategory == g.Key) - .OrderBy(f => f.UploadDate) - .LastOrDefault(), - NameCategory = g.First().Category.Name, - Publishers = g.Select(i => i.User.Adapt()), - PermissionToUpload = g.Any(i => i.IdUser == idUser), - }); - - var result = new WellCaseDto - { - IdWell = idWell, - PermissionToSetPubliher = userRepository.HasPermission(idUser, "WellFinalDocuments.editPublisher"), - WellFinalDocuments = docs, - }; - - return result; - } - - /// - public async Task> GetAvailableUsersAsync(int idWell, CancellationToken token) - { - var companyIds = await context.RelationCompaniesWells - .AsNoTracking() - .Where(x => x.IdWell == idWell).Select(x => x.IdCompany) - .ToListAsync(token) - .ConfigureAwait(false); - - var allUsers = await userRepository - .GetAllAsync(token) - .ConfigureAwait(false); - - return allUsers.Where(x => companyIds.Contains(x.IdCompany)) - .OrderBy(x => x.Surname) - .Select(u => u as UserDto) - .ToArray(); - } - - /// - public async Task GetCategoryAsync(int idWell, int idCategory, int idUser, CancellationToken token) - { - var entity = await context.WellFinalDocuments - .AsNoTracking() - .FirstOrDefaultAsync(x => x.IdWell == idWell && x.IdCategory == idCategory && x.IdUser == idUser, token) - ?? throw new ArgumentInvalidException(nameof(idUser), "Пользователь не является ответственным за загрузку файла для данной категории."); - var dto = Convert(entity); - return dto; - } - - private static WellFinalDocumentDBDto Convert(WellFinalDocument entity) - => entity.Adapt(); + this.context = context; + this.fileService = fileService; + this.userRepository = userRepository; } + /// + public async Task> UpdateRangeAsync(int idWell, IEnumerable dtos, CancellationToken token) + { + if (!dtos.Any()) + throw new ArgumentInvalidException(nameof(dtos), "Данные по категориям отсутствуют."); + + var entities = dtos + .Where(dto => dto.IdsPublishers?.Any() == true) + .SelectMany(dto => dto.IdsPublishers + .Select(idUser => new WellFinalDocument + { + IdCategory = dto.IdCategory, + IdWell = idWell, + IdUser = idUser + })); + + var itemsToDelete = context.WellFinalDocuments.Where(d => d.IdWell == idWell); + context.WellFinalDocuments.RemoveRange(itemsToDelete); + + context.WellFinalDocuments.AddRange(entities); + await context.SaveChangesAsync(token).ConfigureAwait(false); + + return entities.Adapt>(); + } + + /// + public async Task GetByWellIdAsync(int idWell, int idUser, CancellationToken token) + { + var entities = await context.WellFinalDocuments + .Include(d => d.Category) + .Include(d => d.User) + .Where(d => d.IdWell == idWell) + .AsNoTracking() + .ToArrayAsync(token) + .ConfigureAwait(false); + + var entitiesGroups = entities + .GroupBy(d => d.IdCategory); + + var categoriesIds = entitiesGroups + .Select(g => g.Key); + + var files = (await fileService + .GetInfosAsync(new FileRequest { IdWell = idWell }, token) + .ConfigureAwait(false)) + .Where(f => categoriesIds.Contains(f.IdCategory)) + .ToArray(); + + var docs = entitiesGroups.Select((g) => new WellFinalDocumentDto + { + IdCategory = g.Key, + FilesCount = files + .Where(f => f.IdCategory == g.Key) + .Count(), + File = files + .Where(f => f.IdCategory == g.Key) + .OrderBy(f => f.UploadDate) + .LastOrDefault(), + NameCategory = g.First().Category.Name, + Publishers = g.Select(i => i.User.Adapt()), + PermissionToUpload = g.Any(i => i.IdUser == idUser), + }); + + var result = new WellCaseDto + { + IdWell = idWell, + PermissionToSetPubliher = userRepository.HasPermission(idUser, "WellFinalDocuments.editPublisher"), + WellFinalDocuments = docs, + }; + + return result; + } + + /// + public async Task> GetAvailableUsersAsync(int idWell, CancellationToken token) + { + var companyIds = await context.RelationCompaniesWells + .AsNoTracking() + .Where(x => x.IdWell == idWell).Select(x => x.IdCompany) + .ToListAsync(token) + .ConfigureAwait(false); + + var allUsers = await userRepository + .GetAllAsync(token) + .ConfigureAwait(false); + + return allUsers.Where(x => companyIds.Contains(x.IdCompany)) + .OrderBy(x => x.Surname) + .Select(u => u as UserDto) + .ToArray(); + } + + /// + public async Task GetCategoryAsync(int idWell, int idCategory, int idUser, CancellationToken token) + { + var entity = await context.WellFinalDocuments + .AsNoTracking() + .FirstOrDefaultAsync(x => x.IdWell == idWell && x.IdCategory == idCategory && x.IdUser == idUser, token) + ?? throw new ArgumentInvalidException(nameof(idUser), "Пользователь не является ответственным за загрузку файла для данной категории."); + var dto = Convert(entity); + return dto; + } + + private static WellFinalDocumentDBDto Convert(WellFinalDocument entity) + => entity.Adapt(); } diff --git a/AsbCloudInfrastructure/Repository/WitsRecordRepository.cs b/AsbCloudInfrastructure/Repository/WitsRecordRepository.cs index 46ea461a..94045173 100644 --- a/AsbCloudInfrastructure/Repository/WitsRecordRepository.cs +++ b/AsbCloudInfrastructure/Repository/WitsRecordRepository.cs @@ -10,160 +10,159 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Repository +namespace AsbCloudInfrastructure.Repository; + +public class WitsRecordRepository : IWitsRecordRepository + where TEntity : AsbCloudDb.Model.WITS.RecordBase, ITelemetryData + where TDto : AsbCloudApp.Data.ITelemetryData { - public class WitsRecordRepository : IWitsRecordRepository - where TEntity : AsbCloudDb.Model.WITS.RecordBase, ITelemetryData - where TDto : AsbCloudApp.Data.ITelemetryData + private static readonly Random random = new Random((int)(DateTime.Now.Ticks % 0xFFFFFFFF)); + private readonly DbSet dbset; + private readonly IAsbCloudDbContext db; + private readonly ITelemetryService telemetryService; + + private static readonly ConcurrentDictionary cache = new(); + + public WitsRecordRepository(IAsbCloudDbContext db, ITelemetryService telemetryService) { - private static readonly Random random = new Random((int)(DateTime.Now.Ticks % 0xFFFFFFFF)); - private readonly DbSet dbset; - private readonly IAsbCloudDbContext db; - private readonly ITelemetryService telemetryService; + dbset = db.Set(); + this.db = db; + this.telemetryService = telemetryService; + } - private static readonly ConcurrentDictionary cache = new(); + public async Task<(DateTime begin, DateTime end, int count)?> GetStatAsync(int idTelemetry, CancellationToken token) + { + var timezoneHours = telemetryService.GetTimezone(idTelemetry).Hours; + var stat = await dbset.Where(d => d.IdTelemetry == idTelemetry) + .GroupBy(d => d.IdTelemetry) + .Select(g => new Tuple(g.Min(d => d.DateTime), g.Max(d => d.DateTime), g.Count())) + .FirstOrDefaultAsync(token); - public WitsRecordRepository(IAsbCloudDbContext db, ITelemetryService telemetryService) + if (stat is null || stat.Item3 == 0) + return null; + + return ( + stat.Item1.ToRemoteDateTime(timezoneHours), + stat.Item2.ToRemoteDateTime(timezoneHours), + stat.Item3); + } + + public async Task> GetAsync(int idTelemetry, DateTime begin, DateTime end, CancellationToken token) + { + var timezoneHours = telemetryService.GetTimezone(idTelemetry).Hours; + var query = dbset + .Where(d => d.IdTelemetry == idTelemetry) + .Where(d => d.DateTime >= begin) + .Where(d => d.DateTime <= end) + .AsNoTracking(); + var data = await query.ToListAsync(token); + return data.Select(d => Convert(d, timezoneHours)); + } + + private IQueryable BuildQuery(TelemetryPartDeleteRequest request) + { + var query = db.Set() + .Where(o => o.IdTelemetry == request.IdTelemetry); + + if (request.LeDate is not null) { - dbset = db.Set(); - this.db = db; - this.telemetryService = telemetryService; + var leDate = request.LeDate.Value.ToUniversalTime(); + query = query.Where(o => o.DateTime <= leDate); } - public async Task<(DateTime begin, DateTime end, int count)?> GetStatAsync(int idTelemetry, CancellationToken token) + if (request.GeDate is not null) { - var timezoneHours = telemetryService.GetTimezone(idTelemetry).Hours; - var stat = await dbset.Where(d => d.IdTelemetry == idTelemetry) - .GroupBy(d => d.IdTelemetry) - .Select(g => new Tuple(g.Min(d => d.DateTime), g.Max(d => d.DateTime), g.Count())) - .FirstOrDefaultAsync(token); - - if (stat is null || stat.Item3 == 0) - return null; - - return ( - stat.Item1.ToRemoteDateTime(timezoneHours), - stat.Item2.ToRemoteDateTime(timezoneHours), - stat.Item3); + var geDate = request.GeDate.Value.ToUniversalTime(); + query = query.Where(o => o.DateTime >= geDate); } - public async Task> GetAsync(int idTelemetry, DateTime begin, DateTime end, CancellationToken token) - { - var timezoneHours = telemetryService.GetTimezone(idTelemetry).Hours; - var query = dbset - .Where(d => d.IdTelemetry == idTelemetry) - .Where(d => d.DateTime >= begin) - .Where(d => d.DateTime <= end) - .AsNoTracking(); - var data = await query.ToListAsync(token); - return data.Select(d => Convert(d, timezoneHours)); - } + return query; + } - private IQueryable BuildQuery(TelemetryPartDeleteRequest request) - { - var query = db.Set() - .Where(o => o.IdTelemetry == request.IdTelemetry); + public async Task DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token) + { + var query = BuildQuery(request); + dbset.RemoveRange(query); + return await db.SaveChangesAsync(token); + } - if (request.LeDate is not null) + public TDto? GetLastOrDefault(int idTelemetry) + => cache.GetValueOrDefault(idTelemetry); + + public async Task SaveDataAsync(int idTelemetry, IEnumerable dtos, CancellationToken token) + { + if (!dtos.Any()) + return; + + cache.AddOrUpdate(idTelemetry, dtos.Last(), (_, _) => dtos.OrderBy(r => r.DateTime).Last()); + + var timezoneHours = telemetryService.GetTimezone(idTelemetry).Hours; + var entities = dtos + .DistinctBy(d => d.DateTime) + .Select(dto => Convert(dto, idTelemetry, timezoneHours)); + + var dateMin = entities.Min(e => e.DateTime); + var dateMax = entities.Max(e => e.DateTime); + var existingEntities = await db.Set() + .Where(e => e.IdTelemetry == idTelemetry) + .Where(e => e.DateTime >= dateMin && e.DateTime <= dateMax) + .Select(e => e.DateTime) + .OrderBy(d => d) + .ToArrayAsync(token); + + foreach (var entity in entities) + { + if (!existingEntities.Any(e => e == entity.DateTime)) { - var leDate = request.LeDate.Value.ToUniversalTime(); - query = query.Where(o => o.DateTime <= leDate); + dbset.Add(entity); } - - if (request.GeDate is not null) + else { - var geDate = request.GeDate.Value.ToUniversalTime(); - query = query.Where(o => o.DateTime >= geDate); + var dt = entity.DateTime; + entity.DateTime = new DateTimeOffset( + dt.Year, + dt.Month, + dt.Day, + dt.Hour, + dt.Minute, + dt.Second, + (dt.Millisecond + random.Next(1, 283)) % 1000, + dt.Offset); + dbset.Add(entity); } - - return query; } - public async Task DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token) + await db.SaveChangesAsync(token); + } + + private static short GetRecId(TDto dto) + { + var recid = dto switch { - var query = BuildQuery(request); - dbset.RemoveRange(query); - return await db.SaveChangesAsync(token); - } + AsbCloudApp.Data.WITS.Record1Dto _ => 1, + AsbCloudApp.Data.WITS.Record7Dto _ => 7, + AsbCloudApp.Data.WITS.Record8Dto _ => 8, + AsbCloudApp.Data.WITS.Record50Dto _ => 50, + AsbCloudApp.Data.WITS.Record60Dto _ => 60, + AsbCloudApp.Data.WITS.Record61Dto _ => 61, + _ => 0, + }; + return (short)recid; + } - public TDto? GetLastOrDefault(int idTelemetry) - => cache.GetValueOrDefault(idTelemetry); + private static TEntity Convert(TDto dto, int idTelemetry, double timezoneHours) + { + var entity = dto.Adapt(); + entity.Recid = GetRecId(dto); + entity.IdTelemetry = idTelemetry; + entity.DateTime = dto.DateTime.ToUtcDateTimeOffset(timezoneHours); + return entity; + } - public async Task SaveDataAsync(int idTelemetry, IEnumerable dtos, CancellationToken token) - { - if (!dtos.Any()) - return; - - cache.AddOrUpdate(idTelemetry, dtos.Last(), (_, _) => dtos.OrderBy(r => r.DateTime).Last()); - - var timezoneHours = telemetryService.GetTimezone(idTelemetry).Hours; - var entities = dtos - .DistinctBy(d => d.DateTime) - .Select(dto => Convert(dto, idTelemetry, timezoneHours)); - - var dateMin = entities.Min(e => e.DateTime); - var dateMax = entities.Max(e => e.DateTime); - var existingEntities = await db.Set() - .Where(e => e.IdTelemetry == idTelemetry) - .Where(e => e.DateTime >= dateMin && e.DateTime <= dateMax) - .Select(e => e.DateTime) - .OrderBy(d => d) - .ToArrayAsync(token); - - foreach (var entity in entities) - { - if (!existingEntities.Any(e => e == entity.DateTime)) - { - dbset.Add(entity); - } - else - { - var dt = entity.DateTime; - entity.DateTime = new DateTimeOffset( - dt.Year, - dt.Month, - dt.Day, - dt.Hour, - dt.Minute, - dt.Second, - (dt.Millisecond + random.Next(1, 283)) % 1000, - dt.Offset); - dbset.Add(entity); - } - } - - await db.SaveChangesAsync(token); - } - - private static short GetRecId(TDto dto) - { - var recid = dto switch - { - AsbCloudApp.Data.WITS.Record1Dto _ => 1, - AsbCloudApp.Data.WITS.Record7Dto _ => 7, - AsbCloudApp.Data.WITS.Record8Dto _ => 8, - AsbCloudApp.Data.WITS.Record50Dto _ => 50, - AsbCloudApp.Data.WITS.Record60Dto _ => 60, - AsbCloudApp.Data.WITS.Record61Dto _ => 61, - _ => 0, - }; - return (short)recid; - } - - private static TEntity Convert(TDto dto, int idTelemetry, double timezoneHours) - { - var entity = dto.Adapt(); - entity.Recid = GetRecId(dto); - entity.IdTelemetry = idTelemetry; - entity.DateTime = dto.DateTime.ToUtcDateTimeOffset(timezoneHours); - return entity; - } - - private static TDto Convert(TEntity entity, double timezoneHours) - { - var data = entity.Adapt(); - data.DateTime = entity.DateTime.ToRemoteDateTime(timezoneHours); - return data; - } + private static TDto Convert(TEntity entity, double timezoneHours) + { + var data = entity.Adapt(); + data.DateTime = entity.DateTime.ToRemoteDateTime(timezoneHours); + return data; } } diff --git a/AsbCloudInfrastructure/Services/AuthService.cs b/AsbCloudInfrastructure/Services/AuthService.cs index 91b6f22b..3d17f5fd 100644 --- a/AsbCloudInfrastructure/Services/AuthService.cs +++ b/AsbCloudInfrastructure/Services/AuthService.cs @@ -17,212 +17,211 @@ using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services +namespace AsbCloudInfrastructure.Services; + +/// +public class AuthService : IAuthService { - /// - public class AuthService : IAuthService + private readonly IAsbCloudDbContext db; + private readonly IUserRepository userRepository; + + public const string issuer = "a"; + public const string audience = "a"; + public static readonly SymmetricSecurityKey securityKey = new(Encoding.ASCII.GetBytes("супер секретный ключ для шифрования")); + private const string algorithms = SecurityAlgorithms.HmacSha256; + + private static readonly TimeSpan expiresTimespan = TimeSpan.FromDays(365.25); + private static readonly Encoding encoding = Encoding.UTF8; + private const int PasswordSaltLength = 5; + private const string claimIdUser = "id"; + private const string claimNameIdCompany = "idCompany"; + private readonly HashAlgorithm hashAlgorithm; + private readonly Random rnd; + + public AuthService(IAsbCloudDbContext db, IUserRepository userRepository) { - private readonly IAsbCloudDbContext db; - private readonly IUserRepository userRepository; + this.db = db; + this.userRepository = userRepository; + hashAlgorithm = SHA384.Create(); + rnd = new Random((int)(DateTime.Now.Ticks % 2147480161)); + } - public const string issuer = "a"; - public const string audience = "a"; - public static readonly SymmetricSecurityKey securityKey = new(Encoding.ASCII.GetBytes("супер секретный ключ для шифрования")); - private const string algorithms = SecurityAlgorithms.HmacSha256; + /// + public async Task LoginAsync(string login, string password, + CancellationToken token) + { + var user = await GetUserByLoginAsync(login, token); + if (user is null) + return null; - private static readonly TimeSpan expiresTimespan = TimeSpan.FromDays(365.25); - private static readonly Encoding encoding = Encoding.UTF8; - private const int PasswordSaltLength = 5; - private const string claimIdUser = "id"; - private const string claimNameIdCompany = "idCompany"; - private readonly HashAlgorithm hashAlgorithm; - private readonly Random rnd; + if (!CheckPassword(user.PasswordHash, password)) + return null; - public AuthService(IAsbCloudDbContext db, IUserRepository userRepository) + return await MakeUserTokenDto(user, token); + } + + /// + public async Task RefreshAsync(ClaimsPrincipal identity, + CancellationToken token) + { + var login = identity.FindFirst(ClaimsIdentity.DefaultNameClaimType)?.Value; + if (string.IsNullOrEmpty(login)) + return null; + + var user = await GetUserByLoginAsync(login, token); + if (user is null) + return null; + + var dto = await MakeUserTokenDto(user, token); + return dto; + } + + /// + public void Register(UserRegistrationDto userDto) + { + var user = db.Users.FirstOrDefault(u => u.Login == userDto.Login) + ?? throw new ArgumentInvalidException(nameof(userDto.Login), "Логин уже занят"); + + var salt = GenerateSalt(); + + var newUser = new User { - this.db = db; - this.userRepository = userRepository; - hashAlgorithm = SHA384.Create(); - rnd = new Random((int)(DateTime.Now.Ticks % 2147480161)); - } + IdCompany = userDto.IdCompany, + IdState = 0, + Name = userDto.Name, + Surname = userDto.Surname, + Patronymic = userDto.Patronymic, + Email = userDto.Email, + Phone = userDto.Phone, + Position = userDto.Position, + Login = userDto.Login, + PasswordHash = salt + ComputeHash(salt, userDto.Password), + }; - /// - public async Task LoginAsync(string login, string password, - CancellationToken token) + db.Users.Add(newUser); + db.SaveChanges(); + db.RelationUserUserRoles.Add(new RelationUserUserRole { - var user = await GetUserByLoginAsync(login, token); - if (user is null) - return null; + IdUser = newUser.Id, + IdUserRole = 2 + }); + db.SaveChanges(); + } - if (!CheckPassword(user.PasswordHash, password)) - return null; + /// + public void ChangePassword(string userLogin, string newPassword) + { + var user = db.Users.FirstOrDefault(u => u.Login == userLogin) + ?? throw new ArgumentInvalidException(nameof(userLogin), "Логин не зарегистрирован"); - return await MakeUserTokenDto(user, token); - } + var salt = GenerateSalt(); + user.PasswordHash = salt + ComputeHash(salt, newPassword); + db.SaveChanges(); + } - /// - public async Task RefreshAsync(ClaimsPrincipal identity, - CancellationToken token) - { - var login = identity.FindFirst(ClaimsIdentity.DefaultNameClaimType)?.Value; - if (string.IsNullOrEmpty(login)) - return null; + /// + public void ChangePassword(int idUser, string newPassword) + { + var user = db.Users.FirstOrDefault(u => u.Id == idUser) + ?? throw new ArgumentInvalidException(nameof(idUser), $"Пользователь с idUser:{idUser} не зарегистрирован"); - var user = await GetUserByLoginAsync(login, token); - if (user is null) - return null; + var salt = GenerateSalt(); + user.PasswordHash = salt + ComputeHash(salt, newPassword); + db.SaveChanges(); + } - var dto = await MakeUserTokenDto(user, token); - return dto; - } + private async Task MakeUserTokenDto(User user, CancellationToken token) + { + var identity = MakeClaims(user); + if (identity is null || user.IdState == 0) + return null; - /// - public void Register(UserRegistrationDto userDto) - { - var user = db.Users.FirstOrDefault(u => u.Login == userDto.Login) - ?? throw new ArgumentInvalidException(nameof(userDto.Login), "Логин уже занят"); + var userDto = await userRepository.GetOrDefaultAsync(user.Id, token); + if (userDto is null) + return null; - var salt = GenerateSalt(); + var dto = userDto.Adapt(); + dto.Permissions = userRepository.GetNestedPermissions(userDto.Id); + dto.Token = MakeToken(identity.Claims); + return dto; + } - var newUser = new User + private static string MakeToken(IEnumerable claims) + { + var now = DateTime.Now; + + var jwt = new JwtSecurityToken( + issuer, + audience, + notBefore: now, + claims: claims, + expires: now.Add(expiresTimespan), + signingCredentials: new SigningCredentials(securityKey, algorithms)); + + return new JwtSecurityTokenHandler().WriteToken(jwt); + } + + private async Task GetUserByLoginAsync(string login, CancellationToken token = default) + { + var user = await db.Users + .Include(e => e.Company) + .Where(e => e.Login == login) + .AsNoTracking() + .FirstOrDefaultAsync(token) + .ConfigureAwait(false); + return user; + } + + private ClaimsIdentity MakeClaims(User user) + { + var claims = new List { - IdCompany = userDto.IdCompany, - IdState = 0, - Name = userDto.Name, - Surname = userDto.Surname, - Patronymic = userDto.Patronymic, - Email = userDto.Email, - Phone = userDto.Phone, - Position = userDto.Position, - Login = userDto.Login, - PasswordHash = salt + ComputeHash(salt, userDto.Password), + new (claimIdUser, user.Id.ToString()), + new (ClaimsIdentity.DefaultNameClaimType, user.Login), + new (claimNameIdCompany, user.IdCompany.ToString()), }; + var roles = userRepository.GetRolesByIdUser(user.Id); + if (roles is not null) + foreach (var role in roles) + claims.Add(new Claim(ClaimsIdentity.DefaultRoleClaimType, role.Caption)); - db.Users.Add(newUser); - db.SaveChanges(); - db.RelationUserUserRoles.Add(new RelationUserUserRole - { - IdUser = newUser.Id, - IdUserRole = 2 - }); - db.SaveChanges(); - } + var claimsIdentity = new ClaimsIdentity(claims, "Token", ClaimsIdentity.DefaultNameClaimType, ClaimsIdentity.DefaultRoleClaimType); + return claimsIdentity; + } - /// - public void ChangePassword(string userLogin, string newPassword) - { - var user = db.Users.FirstOrDefault(u => u.Login == userLogin) - ?? throw new ArgumentInvalidException(nameof(userLogin), "Логин не зарегистрирован"); + private bool CheckPassword(string passwordHash, string password) + { + if (passwordHash?.Length == 0 && password.Length == 0) + return true; - var salt = GenerateSalt(); - user.PasswordHash = salt + ComputeHash(salt, newPassword); - db.SaveChanges(); - } + if (passwordHash?.Length < PasswordSaltLength) + return false; - /// - public void ChangePassword(int idUser, string newPassword) - { - var user = db.Users.FirstOrDefault(u => u.Id == idUser) - ?? throw new ArgumentInvalidException(nameof(idUser), $"Пользователь с idUser:{idUser} не зарегистрирован"); + if (passwordHash is null) + return false; - var salt = GenerateSalt(); - user.PasswordHash = salt + ComputeHash(salt, newPassword); - db.SaveChanges(); - } + var salt = passwordHash[0..PasswordSaltLength]; + var hashDb = passwordHash[PasswordSaltLength..]; - private async Task MakeUserTokenDto(User user, CancellationToken token) - { - var identity = MakeClaims(user); - if (identity is null || user.IdState == 0) - return null; + return hashDb == ComputeHash(salt, password); + } - var userDto = await userRepository.GetOrDefaultAsync(user.Id, token); - if (userDto is null) - return null; + private string ComputeHash(string salt, string password) + { + var hashBytes = hashAlgorithm.ComputeHash(encoding.GetBytes(salt + password)); + var hashString = BitConverter.ToString(hashBytes) + .Replace("-", "") + .ToLower(); + return hashString; + } - var dto = userDto.Adapt(); - dto.Permissions = userRepository.GetNestedPermissions(userDto.Id); - dto.Token = MakeToken(identity.Claims); - return dto; - } - - private static string MakeToken(IEnumerable claims) - { - var now = DateTime.Now; - - var jwt = new JwtSecurityToken( - issuer, - audience, - notBefore: now, - claims: claims, - expires: now.Add(expiresTimespan), - signingCredentials: new SigningCredentials(securityKey, algorithms)); - - return new JwtSecurityTokenHandler().WriteToken(jwt); - } - - private async Task GetUserByLoginAsync(string login, CancellationToken token = default) - { - var user = await db.Users - .Include(e => e.Company) - .Where(e => e.Login == login) - .AsNoTracking() - .FirstOrDefaultAsync(token) - .ConfigureAwait(false); - return user; - } - - private ClaimsIdentity MakeClaims(User user) - { - var claims = new List - { - new (claimIdUser, user.Id.ToString()), - new (ClaimsIdentity.DefaultNameClaimType, user.Login), - new (claimNameIdCompany, user.IdCompany.ToString()), - }; - var roles = userRepository.GetRolesByIdUser(user.Id); - if (roles is not null) - foreach (var role in roles) - claims.Add(new Claim(ClaimsIdentity.DefaultRoleClaimType, role.Caption)); - - var claimsIdentity = new ClaimsIdentity(claims, "Token", ClaimsIdentity.DefaultNameClaimType, ClaimsIdentity.DefaultRoleClaimType); - return claimsIdentity; - } - - private bool CheckPassword(string passwordHash, string password) - { - if (passwordHash?.Length == 0 && password.Length == 0) - return true; - - if (passwordHash?.Length < PasswordSaltLength) - return false; - - if (passwordHash is null) - return false; - - var salt = passwordHash[0..PasswordSaltLength]; - var hashDb = passwordHash[PasswordSaltLength..]; - - return hashDb == ComputeHash(salt, password); - } - - private string ComputeHash(string salt, string password) - { - var hashBytes = hashAlgorithm.ComputeHash(encoding.GetBytes(salt + password)); - var hashString = BitConverter.ToString(hashBytes) - .Replace("-", "") - .ToLower(); - return hashString; - } - - private string GenerateSalt() - { - const string saltChars = "sHwiaX7kZT1QRp0cPILGUuK2Sz=9q8lmejDNfoYCE3B_WtgyVv6M5OxAJ4Frbhnd"; - var salt = ""; - for (var i = 0; i < PasswordSaltLength - 1; i++) - salt += saltChars[rnd.Next(0, saltChars.Length)]; - salt += "|"; - return salt; - } + private string GenerateSalt() + { + const string saltChars = "sHwiaX7kZT1QRp0cPILGUuK2Sz=9q8lmejDNfoYCE3B_WtgyVv6M5OxAJ4Frbhnd"; + var salt = ""; + for (var i = 0; i < PasswordSaltLength - 1; i++) + salt += saltChars[rnd.Next(0, saltChars.Length)]; + salt += "|"; + return salt; } } diff --git a/AsbCloudInfrastructure/Services/DataSaubStatService.cs b/AsbCloudInfrastructure/Services/DataSaubStatService.cs index e54a380d..bdeaf6eb 100644 --- a/AsbCloudInfrastructure/Services/DataSaubStatService.cs +++ b/AsbCloudInfrastructure/Services/DataSaubStatService.cs @@ -11,227 +11,225 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services +namespace AsbCloudInfrastructure.Services; + + +public class DataSaubStatService : IDataSaubStatService { + private IDataSaubStatRepository dataSaubStatRepository; + private ITelemetryDataCache telemetryDataCache; + private ITelemetryDataSaubService dataSaubService; + private IDetectedOperationRepository detectedOperationRepository; - public class DataSaubStatService : IDataSaubStatService + public DataSaubStatService( + IDataSaubStatRepository dataSaubStatRepository, + ITelemetryDataCache telemetryDataCache, + ITelemetryDataSaubService dataSaubService, + IDetectedOperationRepository detectedOperationRepository) { - private IDataSaubStatRepository dataSaubStatRepository; - private ITelemetryDataCache telemetryDataCache; - private ITelemetryDataSaubService dataSaubService; - private IDetectedOperationRepository detectedOperationRepository; + this.dataSaubStatRepository = dataSaubStatRepository; + this.telemetryDataCache = telemetryDataCache; + this.dataSaubService = dataSaubService; + this.detectedOperationRepository = detectedOperationRepository; + } - public DataSaubStatService( - IDataSaubStatRepository dataSaubStatRepository, - ITelemetryDataCache telemetryDataCache, - ITelemetryDataSaubService dataSaubService, - IDetectedOperationRepository detectedOperationRepository) + public async Task CreateStatAsync(int lastDaysFilter, Action onProgressCallback, CancellationToken token) + { + var cacheRequest = new TelemetryDataRequest() { - this.dataSaubStatRepository = dataSaubStatRepository; - this.telemetryDataCache = telemetryDataCache; - this.dataSaubService = dataSaubService; - this.detectedOperationRepository = detectedOperationRepository; - } + GeDate = DateTime.UtcNow.AddDays(-lastDaysFilter) + }; + var idTelemetries = telemetryDataCache.GetIds(cacheRequest).ToArray(); - public async Task CreateStatAsync(int lastDaysFilter, Action onProgressCallback, CancellationToken token) + if (!idTelemetries.Any()) + return; + + var stats = await dataSaubStatRepository.GetLastsAsync(idTelemetries, token); + + for (var i = 0; i < idTelemetries.Length; i++) { - var cacheRequest = new TelemetryDataRequest() - { - GeDate = DateTime.UtcNow.AddDays(-lastDaysFilter) - }; - var idTelemetries = telemetryDataCache.GetIds(cacheRequest).ToArray(); - - if (!idTelemetries.Any()) - return; - - var stats = await dataSaubStatRepository.GetLastsAsync(idTelemetries, token); - - for (var i = 0; i < idTelemetries.Length; i++) - { - var idTelemetry = idTelemetries[i]; - var lastDate = stats.FirstOrDefault(s => s.IdTelemetry == idTelemetry)?.DateEnd.ToUniversalTime() ?? DateTimeOffset.UnixEpoch; - var statsCount = await CreateStatForTelemetryFromDate(idTelemetry, lastDate, token); - if(onProgressCallback != null) - onProgressCallback($"Calculate stat for telemetry: {idTelemetry}; from {lastDate}; results count: {statsCount};", 1d * i / idTelemetries.Length); - } - } - - private async Task CreateStatForTelemetryFromDate( - int idTelemetry, - DateTimeOffset begin, - CancellationToken token) - { - var detectedOperationRequest = new DetectedOperationByTelemetryRequest - { - GeDateStart = begin, - IdTelemetry = idTelemetry, - IdsCategories = WellOperationCategory.MechanicalDrillingSubIds, - SortFields = new[] { nameof(DetectedOperation.DateStart) }, - Take = 250, - }; - - var detectedOperations = await detectedOperationRepository.Get(detectedOperationRequest, token); - - if (!detectedOperations.Any()) - return 0; - - var geDate = detectedOperations.First().DateStart; - var leDate = detectedOperations.OrderByDescending(d => d.DateEnd).First().DateEnd; - - var dataSaub = await dataSaubService.Get(idTelemetry, true, geDate, leDate, 100_000, token); - - if (!dataSaub.Any()) - return 0; - - if (dataSaub is not TelemetryDataSaubDto[] dataSaubArray) - dataSaubArray = dataSaub.ToArray(); - - var dataSaubStats = CreateDataSaubStat(detectedOperations, dataSaubArray); - - return await dataSaubStatRepository.InsertRangeAsync(dataSaubStats, token); - } - - private static IEnumerable CreateDataSaubStat(IEnumerable detectedOperations, TelemetryDataSaubDto[] dataSaub) - { - var indexStart = 0; - var indexEnd = 0; - var result = new List(); - - if (!dataSaub.Any()) - return result; - - foreach (var operation in detectedOperations) - { - indexStart = Array.FindIndex(dataSaub, indexEnd, t => t.DateTime >= operation.DateStart); - if (indexStart < 0) - break; - - indexEnd = Array.FindIndex(dataSaub, indexStart, t => t.DateTime > operation.DateEnd); - - if (indexEnd < 0) - indexEnd = dataSaub.Length - 1; - - if (indexEnd == indexStart) - continue; - - var length = indexEnd - indexStart + 1; - - var subset = dataSaub.AsSpan(indexStart, length); - var stats = CalcStats(operation, subset); - result.AddRange(stats); - } - return result; - } - - private static IEnumerable CalcStats(DetectedOperationDto operation, Span dataSaub) - { - var result = new List(); - - var indexStart = 0; - for (var i = 1; i < dataSaub.Length; i++) - { - var previous = dataSaub[i - 1]; - var current = dataSaub[i]; - - if (IsNewCacheItem(previous, current) || i == dataSaub.Length - 1) - { - var length = i - indexStart + 1; - var span = dataSaub.Slice(indexStart, length); - indexStart = i; - if (length <= 2 || (span[^1].WellDepth - span[0].WellDepth) < 0.001) - continue; // мелкие выборки не учитываем. - var stat = CalcStat(operation, span); - result.Add(stat); - } - } - - return result; - } - - private static DataSaubStatDto CalcStat(DetectedOperationDto operation, Span span) - { - var aggregatedValues = CalcAggregate(span); - var dateStart = span[0].DateTime; - var dateEnd = span[^1].DateTime; - var depthStart = span[0].WellDepth; - var depthEnd = span[^1].WellDepth; - var speed = ((depthEnd - depthStart) / (dateEnd - dateStart).TotalHours); - - var processMapDrillingCacheItem = new DataSaubStatDto - { - DateStart = dateStart, - DateEnd = dateEnd, - DepthStart = depthStart, - DepthEnd = depthEnd, - Speed = speed, - BlockSpeedSp = span[0].BlockSpeedSp, - Pressure = aggregatedValues.Pressure, - PressureIdle = span[0].PressureIdle, - PressureSp = span[0].PressureSp, - AxialLoad = aggregatedValues.AxialLoad, - AxialLoadSp = span[0].AxialLoadSp, - AxialLoadLimitMax = span[0].AxialLoadLimitMax, - RotorTorque = aggregatedValues.RotorTorque, - RotorTorqueSp = span[0].RotorTorqueSp, - RotorTorqueLimitMax = span[0].RotorTorqueLimitMax, - IdFeedRegulator = span[0].IdFeedRegulator, - RotorSpeed = aggregatedValues.RotorSpeed, - IdCategory = operation.IdCategory, - EnabledSubsystems = operation.EnabledSubsystems, - HasOscillation = operation.EnabledSubsystems.IsAutoOscillation, - IdTelemetry = operation.IdTelemetry, - Flow = aggregatedValues.Flow - }; - return processMapDrillingCacheItem; - } - - private static ( - double Pressure, - double AxialLoad, - double RotorTorque, - double RotorSpeed, - double Flow - ) CalcAggregate(Span span) - { - var sumPressure = 0.0; - var sumAxialLoad = 0.0; - var sumRotorTorque = 0.0; - var sumRotorSpeed = 0.0; - var flow = span[0].Flow ?? 0.0; - var diffDepthTotal = span[^1].WellDepth - span[0].WellDepth; - for (var i = 0; i < span.Length - 1; i++) - { - var diffDepth = span[i + 1].WellDepth - span[i].WellDepth; - sumPressure += diffDepth * span[i].Pressure; - sumAxialLoad += diffDepth * span[i].AxialLoad; - sumRotorTorque += diffDepth * span[i].RotorTorque; - sumRotorSpeed += diffDepth * span[i].RotorSpeed; - flow = span[i + 1].Flow > flow ? span[i + 1].Flow ?? 0.0 : flow; - } - return ( - Pressure: sumPressure / diffDepthTotal, - AxialLoad: sumAxialLoad / diffDepthTotal, - RotorTorque: sumRotorTorque / diffDepthTotal, - RotorSpeed: sumRotorSpeed / diffDepthTotal, - Flow: flow - ); - } - - private static bool IsNewCacheItem(TelemetryDataSaubDto previous, TelemetryDataSaubDto current) - { - return !(current.Mode == previous.Mode) - || !(current.WellDepth >= previous.WellDepth) - || !(current.BlockSpeedSp == previous.BlockSpeedSp) - || !(current.PressureIdle == previous.PressureIdle) - || !(current.PressureSp == previous.PressureSp) - || !(current.AxialLoadSp == previous.AxialLoadSp) - || !(current.AxialLoadLimitMax == previous.AxialLoadLimitMax) - || !(current.HookWeightIdle == previous.HookWeightIdle) - || !(current.RotorTorqueIdle == previous.RotorTorqueIdle) - || !(current.RotorTorqueSp == previous.RotorTorqueSp) - || !(current.RotorTorqueLimitMax == previous.RotorTorqueLimitMax) - || !(current.IdFeedRegulator == previous.IdFeedRegulator); + var idTelemetry = idTelemetries[i]; + var lastDate = stats.FirstOrDefault(s => s.IdTelemetry == idTelemetry)?.DateEnd.ToUniversalTime() ?? DateTimeOffset.UnixEpoch; + var statsCount = await CreateStatForTelemetryFromDate(idTelemetry, lastDate, token); + if(onProgressCallback != null) + onProgressCallback($"Calculate stat for telemetry: {idTelemetry}; from {lastDate}; results count: {statsCount};", 1d * i / idTelemetries.Length); } } + private async Task CreateStatForTelemetryFromDate( + int idTelemetry, + DateTimeOffset begin, + CancellationToken token) + { + var detectedOperationRequest = new DetectedOperationByTelemetryRequest + { + GeDateStart = begin, + IdTelemetry = idTelemetry, + IdsCategories = WellOperationCategory.MechanicalDrillingSubIds, + SortFields = new[] { nameof(DetectedOperation.DateStart) }, + Take = 250, + }; + + var detectedOperations = await detectedOperationRepository.Get(detectedOperationRequest, token); + + if (!detectedOperations.Any()) + return 0; + + var geDate = detectedOperations.First().DateStart; + var leDate = detectedOperations.OrderByDescending(d => d.DateEnd).First().DateEnd; + + var dataSaub = await dataSaubService.Get(idTelemetry, true, geDate, leDate, 100_000, token); + + if (!dataSaub.Any()) + return 0; + + if (dataSaub is not TelemetryDataSaubDto[] dataSaubArray) + dataSaubArray = dataSaub.ToArray(); + + var dataSaubStats = CreateDataSaubStat(detectedOperations, dataSaubArray); + + return await dataSaubStatRepository.InsertRangeAsync(dataSaubStats, token); + } + + private static IEnumerable CreateDataSaubStat(IEnumerable detectedOperations, TelemetryDataSaubDto[] dataSaub) + { + var indexStart = 0; + var indexEnd = 0; + var result = new List(); + + if (!dataSaub.Any()) + return result; + + foreach (var operation in detectedOperations) + { + indexStart = Array.FindIndex(dataSaub, indexEnd, t => t.DateTime >= operation.DateStart); + if (indexStart < 0) + break; + + indexEnd = Array.FindIndex(dataSaub, indexStart, t => t.DateTime > operation.DateEnd); + + if (indexEnd < 0) + indexEnd = dataSaub.Length - 1; + + if (indexEnd == indexStart) + continue; + + var length = indexEnd - indexStart + 1; + + var subset = dataSaub.AsSpan(indexStart, length); + var stats = CalcStats(operation, subset); + result.AddRange(stats); + } + return result; + } + + private static IEnumerable CalcStats(DetectedOperationDto operation, Span dataSaub) + { + var result = new List(); + + var indexStart = 0; + for (var i = 1; i < dataSaub.Length; i++) + { + var previous = dataSaub[i - 1]; + var current = dataSaub[i]; + + if (IsNewCacheItem(previous, current) || i == dataSaub.Length - 1) + { + var length = i - indexStart + 1; + var span = dataSaub.Slice(indexStart, length); + indexStart = i; + if (length <= 2 || (span[^1].WellDepth - span[0].WellDepth) < 0.001) + continue; // мелкие выборки не учитываем. + var stat = CalcStat(operation, span); + result.Add(stat); + } + } + + return result; + } + + private static DataSaubStatDto CalcStat(DetectedOperationDto operation, Span span) + { + var aggregatedValues = CalcAggregate(span); + var dateStart = span[0].DateTime; + var dateEnd = span[^1].DateTime; + var depthStart = span[0].WellDepth; + var depthEnd = span[^1].WellDepth; + var speed = ((depthEnd - depthStart) / (dateEnd - dateStart).TotalHours); + + var processMapDrillingCacheItem = new DataSaubStatDto + { + DateStart = dateStart, + DateEnd = dateEnd, + DepthStart = depthStart, + DepthEnd = depthEnd, + Speed = speed, + BlockSpeedSp = span[0].BlockSpeedSp, + Pressure = aggregatedValues.Pressure, + PressureIdle = span[0].PressureIdle, + PressureSp = span[0].PressureSp, + AxialLoad = aggregatedValues.AxialLoad, + AxialLoadSp = span[0].AxialLoadSp, + AxialLoadLimitMax = span[0].AxialLoadLimitMax, + RotorTorque = aggregatedValues.RotorTorque, + RotorTorqueSp = span[0].RotorTorqueSp, + RotorTorqueLimitMax = span[0].RotorTorqueLimitMax, + IdFeedRegulator = span[0].IdFeedRegulator, + RotorSpeed = aggregatedValues.RotorSpeed, + IdCategory = operation.IdCategory, + EnabledSubsystems = operation.EnabledSubsystems, + HasOscillation = operation.EnabledSubsystems.IsAutoOscillation, + IdTelemetry = operation.IdTelemetry, + Flow = aggregatedValues.Flow + }; + return processMapDrillingCacheItem; + } + + private static ( + double Pressure, + double AxialLoad, + double RotorTorque, + double RotorSpeed, + double Flow + ) CalcAggregate(Span span) + { + var sumPressure = 0.0; + var sumAxialLoad = 0.0; + var sumRotorTorque = 0.0; + var sumRotorSpeed = 0.0; + var flow = span[0].Flow ?? 0.0; + var diffDepthTotal = span[^1].WellDepth - span[0].WellDepth; + for (var i = 0; i < span.Length - 1; i++) + { + var diffDepth = span[i + 1].WellDepth - span[i].WellDepth; + sumPressure += diffDepth * span[i].Pressure; + sumAxialLoad += diffDepth * span[i].AxialLoad; + sumRotorTorque += diffDepth * span[i].RotorTorque; + sumRotorSpeed += diffDepth * span[i].RotorSpeed; + flow = span[i + 1].Flow > flow ? span[i + 1].Flow ?? 0.0 : flow; + } + return ( + Pressure: sumPressure / diffDepthTotal, + AxialLoad: sumAxialLoad / diffDepthTotal, + RotorTorque: sumRotorTorque / diffDepthTotal, + RotorSpeed: sumRotorSpeed / diffDepthTotal, + Flow: flow + ); + } + + private static bool IsNewCacheItem(TelemetryDataSaubDto previous, TelemetryDataSaubDto current) + { + return !(current.Mode == previous.Mode) + || !(current.WellDepth >= previous.WellDepth) + || !(current.BlockSpeedSp == previous.BlockSpeedSp) + || !(current.PressureIdle == previous.PressureIdle) + || !(current.PressureSp == previous.PressureSp) + || !(current.AxialLoadSp == previous.AxialLoadSp) + || !(current.AxialLoadLimitMax == previous.AxialLoadLimitMax) + || !(current.HookWeightIdle == previous.HookWeightIdle) + || !(current.RotorTorqueIdle == previous.RotorTorqueIdle) + || !(current.RotorTorqueSp == previous.RotorTorqueSp) + || !(current.RotorTorqueLimitMax == previous.RotorTorqueLimitMax) + || !(current.IdFeedRegulator == previous.IdFeedRegulator); + } } diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorConditioning.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorConditioning.cs index 6ef413ef..b33eda75 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorConditioning.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorConditioning.cs @@ -6,50 +6,49 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors +namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors; + +public class DetectorConditioning : DetectorAbstract { - 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) { - protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end) => - CalcDeltaMinutes(telemetry, begin, end); + var currentPoint = telemetry[position]; + if (currentPoint.Pressure < 10) + return false; - 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; - if (currentPoint.RotorSpeed <= 8) - return false; + var delta = currentPoint.WellDepth - currentPoint.BitDepth; + if (delta < 0.03d) + return false; - var delta = currentPoint.WellDepth - currentPoint.BitDepth; - if (delta < 0.03d) - return false; + if (currentPoint.BitDepth < 150) + return false; - if (currentPoint.BitDepth < 150) - return false; + return true; + } - return true; - } + protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation) + { + var currentPoint = telemetry[position]; - 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_DeltaWellDepthAndBitDepthIsLo; + if (currentPoint.BitDepth < 150) + return IdReasonOfEnd_BitDepthIsLo; + return IdReasonOfEnd_NotDetected; + } - if (currentPoint.Pressure < 10) - return IdReasonOfEnd_PressureIsLo; - if (currentPoint.RotorSpeed <=8) - return IdReasonOfEnd_RotorSpeedIsHi; - if ((currentPoint.WellDepth - currentPoint.BitDepth) < 0.03d) - return IdReasonOfEnd_DeltaWellDepthAndBitDepthIsLo; - if (currentPoint.BitDepth < 150) - return IdReasonOfEnd_BitDepthIsLo; - return IdReasonOfEnd_NotDetected; - } - - protected override (int IdCategory, IDictionary ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry, int begin, int end) - { - return (WellOperationCategory.IdConditioning, new Dictionary()); - } + protected override (int IdCategory, IDictionary ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry, int begin, int end) + { + return (WellOperationCategory.IdConditioning, new Dictionary()); } } diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorFlashing.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorFlashing.cs index f300f1c5..f30403a9 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorFlashing.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorFlashing.cs @@ -3,65 +3,64 @@ using AsbCloudDb.Model; using System; using System.Collections.Generic; -namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors +namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors; + + +/// +/// Промывка +/// +public class DetectorFlashing : DetectorAbstract { - /// - /// Промывка - /// - public class DetectorFlashing : 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) { - protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end) - => CalcDeltaMinutes(telemetry, begin, end); + var currentPoint = telemetry[position]; + if (currentPoint.Pressure < 10) + return false; - protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation) - { + var delta = currentPoint.WellDepth - currentPoint.BitDepth; + if (delta < 0.01d) + return false; - 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.01d) - return false; + var nextIndexPoint = telemetry.Length <= position ? position : position + 1; + var nextPoint = telemetry[nextIndexPoint]; + if (Math.Abs(currentPoint.WellDepth - nextPoint.WellDepth) > 0) + return false; - if (currentPoint.RotorSpeed > 8) - return false; + if (currentPoint.BitDepth < 150) + return false; - var nextIndexPoint = telemetry.Length <= position ? position : position + 1; - var nextPoint = telemetry[nextIndexPoint]; - if (Math.Abs(currentPoint.WellDepth - nextPoint.WellDepth) > 0) - return false; + return true; - 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.WellDepth - currentPoint.BitDepth) < 0.01d) + return IdReasonOfEnd_DeltaWellDepthAndBitDepthIsLo; + if (currentPoint.RotorSpeed > 8) + return IdReasonOfEnd_RotorSpeedIsHi; + if (currentPoint.BitDepth < 150) + return IdReasonOfEnd_BitDepthIsLo; + return IdReasonOfEnd_NotDetected; + } - protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation) - { - var currentPoint = telemetry[position]; - - if (currentPoint.Pressure < 10) - return IdReasonOfEnd_PressureIsLo; - if ((currentPoint.WellDepth - currentPoint.BitDepth) < 0.01d) - return IdReasonOfEnd_DeltaWellDepthAndBitDepthIsLo; - if (currentPoint.RotorSpeed > 8) - return IdReasonOfEnd_RotorSpeedIsHi; - if (currentPoint.BitDepth < 150) - return IdReasonOfEnd_BitDepthIsLo; - return IdReasonOfEnd_NotDetected; - } - - protected override (int IdCategory, IDictionary ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry, - int begin, - int end) - { - return (WellOperationCategory.IdFlashing, new Dictionary()); - } + protected override (int IdCategory, IDictionary ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry, + int begin, + int end) + { + return (WellOperationCategory.IdFlashing, new Dictionary()); } } diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDetectorResult.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDetectorResult.cs index 453a7fab..f29b8f32 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDetectorResult.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDetectorResult.cs @@ -1,12 +1,11 @@ using AsbCloudApp.Data.DetectedOperation; -namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors -{ +namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors; - public class OperationDetectorResult - { - public int TelemetryBegin { get; set; } - public int TelemetryEnd { get; set; } - public DetectedOperationDto Operation { get; set; } = null!; - } + +public class OperationDetectorResult +{ + public int TelemetryBegin { get; set; } + public int TelemetryEnd { get; set; } + public DetectedOperationDto Operation { get; set; } = null!; } diff --git a/AsbCloudInfrastructure/Services/DetectOperations/InterpolationLine.cs b/AsbCloudInfrastructure/Services/DetectOperations/InterpolationLine.cs index a6880881..094f7235 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/InterpolationLine.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/InterpolationLine.cs @@ -1,57 +1,55 @@ using System.Collections.Generic; -namespace AsbCloudInfrastructure.Services.DetectOperations +namespace AsbCloudInfrastructure.Services.DetectOperations; + + +public class InterpolationLine { + private readonly double xSum; + private readonly double ySum; + private readonly double xySum; + private readonly double x2Sum; + private readonly int count; - public class InterpolationLine + public InterpolationLine(IEnumerable<(double Y, double X)> rawData) { - private readonly double xSum; - private readonly double ySum; - private readonly double xySum; - private readonly double x2Sum; - private readonly int count; - - public InterpolationLine(IEnumerable<(double Y, double X)> rawData) + var iterator = rawData.GetEnumerator(); + while (iterator.MoveNext()) { - var iterator = rawData.GetEnumerator(); - while (iterator.MoveNext()) - { - xSum += iterator.Current.X; - ySum += iterator.Current.Y; - xySum += iterator.Current.X * iterator.Current.Y; - x2Sum += iterator.Current.X * iterator.Current.X; - count++; - } + xSum += iterator.Current.X; + ySum += iterator.Current.Y; + xySum += iterator.Current.X * iterator.Current.Y; + x2Sum += iterator.Current.X * iterator.Current.X; + count++; } - - /// - /// tan(alpha) - /// - public double A => - (xSum * ySum - count * xySum) / - (xSum * xSum - count * x2Sum); - - /// - /// y offset - /// - public double B => - (xSum * xySum - x2Sum * ySum) / - (xSum * xSum - count * x2Sum); - - public bool IsYNotChanges(double upperBound = 0d, double lowerBound = 0d) => - A < upperBound && A > lowerBound; - - public bool IsYIncreases(double bound = 0d) => - A > bound; - - public bool IsYDecreases(double bound = 0d) => - A < bound; - - public bool IsAverageYLessThan(double bound) => - (ySum / count) < bound; - - public bool IsAverageYGreaterThan(double bound) => - (ySum / count) >= bound; } + /// + /// tan(alpha) + /// + public double A => + (xSum * ySum - count * xySum) / + (xSum * xSum - count * x2Sum); + + /// + /// y offset + /// + public double B => + (xSum * xySum - x2Sum * ySum) / + (xSum * xSum - count * x2Sum); + + public bool IsYNotChanges(double upperBound = 0d, double lowerBound = 0d) => + A < upperBound && A > lowerBound; + + public bool IsYIncreases(double bound = 0d) => + A > bound; + + public bool IsYDecreases(double bound = 0d) => + A < bound; + + public bool IsAverageYLessThan(double bound) => + (ySum / count) < bound; + + public bool IsAverageYGreaterThan(double bound) => + (ySum / count) >= bound; } diff --git a/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportMakerService.cs b/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportMakerService.cs index f110a2e2..a42e32b5 100644 --- a/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportMakerService.cs +++ b/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportMakerService.cs @@ -8,72 +8,71 @@ using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Services; -namespace AsbCloudInfrastructure.Services.DrillTestReport +namespace AsbCloudInfrastructure.Services.DrillTestReport; + +public class DrillTestReportMakerService : IReportMakerService { - public class DrillTestReportMakerService : IReportMakerService + private readonly string templateName = "DrillTestReportTemplate.xlsx"; + private readonly string sheetName = "Лист1"; + private readonly int startRowNumber = 8; + + public Stream MakeReport(DrillTestReportDataDto report) { - private readonly string templateName = "DrillTestReportTemplate.xlsx"; - private readonly string sheetName = "Лист1"; - private readonly int startRowNumber = 8; + using var excelTemplateStream = Assembly.GetExecutingAssembly().GetTemplateCopyStream(templateName); - public Stream MakeReport(DrillTestReportDataDto report) - { - using var excelTemplateStream = Assembly.GetExecutingAssembly().GetTemplateCopyStream(templateName); + using var workbook = new XLWorkbook(excelTemplateStream); - using var workbook = new XLWorkbook(excelTemplateStream); + AddToWorkbook(workbook, report); - AddToWorkbook(workbook, report); + MemoryStream memoryStream = new MemoryStream(); + workbook.SaveAs(memoryStream, new SaveOptions { }); + memoryStream.Seek(0, SeekOrigin.Begin); - MemoryStream memoryStream = new MemoryStream(); - workbook.SaveAs(memoryStream, new SaveOptions { }); - memoryStream.Seek(0, SeekOrigin.Begin); - - return memoryStream; - } + return memoryStream; + } + + private void AddToWorkbook(XLWorkbook workbook, DrillTestReportDataDto report) + { + var drillTests = report.Data.Params; - private void AddToWorkbook(XLWorkbook workbook, DrillTestReportDataDto report) + if (!drillTests.Any()) + return; + + var sheet = workbook.GetWorksheet(sheetName); + + sheet.Cell(4, 2).SetCellValue(report.Caption); + sheet.Cell(5, 2).SetCellValue(report.Date); + + var stepWithMaxDepthSpeed = drillTests.MaxBy(p => p.DepthSpeed)!.Step; + var startDepth = report.Data.DepthStart; + var startDate = report.Data.TimeStampStart; + + var rowNumber = startRowNumber; + + foreach (var drillTestEntity in drillTests) { - var drillTests = report.Data.Params; + var endDepth = startDepth + (drillTestEntity.DepthDrillStep ?? 0); + var endDateTime = startDate.AddSeconds(drillTestEntity.TimeDrillStep ?? 0); - if (!drillTests.Any()) - return; + sheet.Cell(rowNumber, 2).SetCellValue(startDepth); + sheet.Cell(rowNumber, 3).SetCellValue(endDepth); + sheet.Cell(rowNumber, 4).SetCellValue(drillTestEntity.DepthDrillStep); + sheet.Cell(rowNumber, 5).SetCellValue(drillTestEntity.Workload); + sheet.Cell(rowNumber, 6).SetCellValue(drillTestEntity.Speed); + sheet.Cell(rowNumber, 7).SetCellValue(startDate.DateTime); + sheet.Cell(rowNumber, 8).SetCellValue(endDateTime.DateTime); + sheet.Cell(rowNumber, 9).SetCellValue(Math.Round((drillTestEntity.TimeDrillStep ?? 0) / (60 * 60), 2)); + sheet.Cell(rowNumber, 10).SetCellValue(drillTestEntity.DepthSpeed); - var sheet = workbook.GetWorksheet(sheetName); - - sheet.Cell(4, 2).SetCellValue(report.Caption); - sheet.Cell(5, 2).SetCellValue(report.Date); - - var stepWithMaxDepthSpeed = drillTests.MaxBy(p => p.DepthSpeed)!.Step; - var startDepth = report.Data.DepthStart; - var startDate = report.Data.TimeStampStart; - - var rowNumber = startRowNumber; - - foreach (var drillTestEntity in drillTests) + if (drillTestEntity.Step == stepWithMaxDepthSpeed) { - var endDepth = startDepth + (drillTestEntity.DepthDrillStep ?? 0); - var endDateTime = startDate.AddSeconds(drillTestEntity.TimeDrillStep ?? 0); - - sheet.Cell(rowNumber, 2).SetCellValue(startDepth); - sheet.Cell(rowNumber, 3).SetCellValue(endDepth); - sheet.Cell(rowNumber, 4).SetCellValue(drillTestEntity.DepthDrillStep); - sheet.Cell(rowNumber, 5).SetCellValue(drillTestEntity.Workload); - sheet.Cell(rowNumber, 6).SetCellValue(drillTestEntity.Speed); - sheet.Cell(rowNumber, 7).SetCellValue(startDate.DateTime); - sheet.Cell(rowNumber, 8).SetCellValue(endDateTime.DateTime); - sheet.Cell(rowNumber, 9).SetCellValue(Math.Round((drillTestEntity.TimeDrillStep ?? 0) / (60 * 60), 2)); - sheet.Cell(rowNumber, 10).SetCellValue(drillTestEntity.DepthSpeed); - - if (drillTestEntity.Step == stepWithMaxDepthSpeed) - { - var currentCells = sheet.Row(rowNumber).Cells(1, 10); - currentCells.Style.Fill.BackgroundColor = XLColor.Yellow; - } - - startDepth = endDepth; - startDate = endDateTime; - rowNumber++; + var currentCells = sheet.Row(rowNumber).Cells(1, 10); + currentCells.Style.Fill.BackgroundColor = XLColor.Yellow; } + + startDepth = endDepth; + startDate = endDateTime; + rowNumber++; } } } diff --git a/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportService.cs b/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportService.cs index c5f43855..e74f0b1f 100644 --- a/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportService.cs +++ b/AsbCloudInfrastructure/Services/DrillTestReport/DrillTestReportService.cs @@ -11,89 +11,88 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services.DrillTestReport +namespace AsbCloudInfrastructure.Services.DrillTestReport; + +public class DrillTestReportService : IDrillTestReportService { - public class DrillTestReportService : IDrillTestReportService + private readonly IWellService wellService; + private readonly IDrillTestRepository drillTestRepository; + private readonly ITelemetryService telemetryService; + private readonly IReportMakerService drillTestReportMakerService; + + public DrillTestReportService( + IWellService wellService, + IDrillTestRepository drillTestRepository, + ITelemetryService telemetryService, + IReportMakerService drillTestReportMakerService) { - private readonly IWellService wellService; - private readonly IDrillTestRepository drillTestRepository; - private readonly ITelemetryService telemetryService; - private readonly IReportMakerService drillTestReportMakerService; + this.wellService = wellService; + this.drillTestRepository = drillTestRepository; + this.telemetryService = telemetryService; + this.drillTestReportMakerService = drillTestReportMakerService; + } - public DrillTestReportService( - IWellService wellService, - IDrillTestRepository drillTestRepository, - ITelemetryService telemetryService, - IReportMakerService drillTestReportMakerService) + public async Task<(string fileName, Stream stream)> GenerateAsync(int idWell, int id, CancellationToken cancellationToken) + { + var well = wellService.GetOrDefault(idWell); + if (well is null) + throw new ArgumentInvalidException(nameof(idWell), $"Well with id: {idWell} does not exist."); + if (well.IdTelemetry is null) + throw new ArgumentInvalidException(nameof(well.IdTelemetry), $"Well with id: {idWell} does not have telemetry."); + + var dto = await drillTestRepository.GetAsync(well.IdTelemetry.Value, id, cancellationToken); + + var report = new DrillTestReportDataDto() { - this.wellService = wellService; - this.drillTestRepository = drillTestRepository; - this.telemetryService = telemetryService; - this.drillTestReportMakerService = drillTestReportMakerService; + Data = dto, + Caption = string.Format("Месторождение: {0}, куст: {1}, скважина: {2}", + well.Deposit ?? "-", + well.Cluster ?? "-", + well.Caption ?? "-"), + Date = DateTimeOffset.Now, + }; + + var fileName = string.Format("Drill_test_{0}.xlsx", dto.TimeStampStart.ToString("dd.mm.yyyy_HH_MM_ss")); + var stream = drillTestReportMakerService.MakeReport(report); + + return (fileName, stream); + } + + + public async Task> GetListAsync(int idWell, FileReportRequest request, CancellationToken cancellationToken) + { + var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); + if (telemetry is null) + throw new Exception($"Telemetry with idWell: {idWell} does not exist."); + + var result = new PaginationContainer + { + Skip = request.Skip ?? 0, + Take = request.Take ?? 10, + Items = Enumerable.Empty() + }; + + var reports = new List(); + var timezone = telemetryService.GetTimezone(telemetry.Id); + + var dtos = await drillTestRepository.GetAllAsync(telemetry.Id, request, cancellationToken); + foreach (var dto in dtos) + { + var remoteDateTime = dto.TimeStampStart.ToOffset(TimeSpan.FromHours(timezone.Hours)); + + reports.Add(new DrillTestReportInfoDto + { + FileName = string.Format("Drill_test_{0}", remoteDateTime), + DrillDepth = (dto.Params + .Where(p => p.DepthDrillStep.HasValue) + .Sum(x => x.DepthDrillStep) ?? 0) + dto.DepthStart, + DateTime = remoteDateTime, + Id = dto.Id, + }); } - public async Task<(string fileName, Stream stream)> GenerateAsync(int idWell, int id, CancellationToken cancellationToken) - { - var well = wellService.GetOrDefault(idWell); - if (well is null) - throw new ArgumentInvalidException(nameof(idWell), $"Well with id: {idWell} does not exist."); - if (well.IdTelemetry is null) - throw new ArgumentInvalidException(nameof(well.IdTelemetry), $"Well with id: {idWell} does not have telemetry."); + result.Items = reports; - var dto = await drillTestRepository.GetAsync(well.IdTelemetry.Value, id, cancellationToken); - - var report = new DrillTestReportDataDto() - { - Data = dto, - Caption = string.Format("Месторождение: {0}, куст: {1}, скважина: {2}", - well.Deposit ?? "-", - well.Cluster ?? "-", - well.Caption ?? "-"), - Date = DateTimeOffset.Now, - }; - - var fileName = string.Format("Drill_test_{0}.xlsx", dto.TimeStampStart.ToString("dd.mm.yyyy_HH_MM_ss")); - var stream = drillTestReportMakerService.MakeReport(report); - - return (fileName, stream); - } - - - public async Task> GetListAsync(int idWell, FileReportRequest request, CancellationToken cancellationToken) - { - var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); - if (telemetry is null) - throw new Exception($"Telemetry with idWell: {idWell} does not exist."); - - var result = new PaginationContainer - { - Skip = request.Skip ?? 0, - Take = request.Take ?? 10, - Items = Enumerable.Empty() - }; - - var reports = new List(); - var timezone = telemetryService.GetTimezone(telemetry.Id); - - var dtos = await drillTestRepository.GetAllAsync(telemetry.Id, request, cancellationToken); - foreach (var dto in dtos) - { - var remoteDateTime = dto.TimeStampStart.ToOffset(TimeSpan.FromHours(timezone.Hours)); - - reports.Add(new DrillTestReportInfoDto - { - FileName = string.Format("Drill_test_{0}", remoteDateTime), - DrillDepth = (dto.Params - .Where(p => p.DepthDrillStep.HasValue) - .Sum(x => x.DepthDrillStep) ?? 0) + dto.DepthStart, - DateTime = remoteDateTime, - Id = dto.Id, - }); - } - - result.Items = reports; - - return result; - } + return result; } } diff --git a/AsbCloudInfrastructure/Services/DrillingProgram/ContentListSheet.cs b/AsbCloudInfrastructure/Services/DrillingProgram/ContentListSheet.cs index 627cec0c..971f524b 100644 --- a/AsbCloudInfrastructure/Services/DrillingProgram/ContentListSheet.cs +++ b/AsbCloudInfrastructure/Services/DrillingProgram/ContentListSheet.cs @@ -4,38 +4,36 @@ using System; using System.Collections.Generic; using System.Linq; -namespace AsbCloudInfrastructure.Services.DrillingProgram +namespace AsbCloudInfrastructure.Services.DrillingProgram; + + +public class ContentListSheet { + private readonly List parts; - public class ContentListSheet + public ContentListSheet(IEnumerable parts) { - private readonly List parts; - - public ContentListSheet(IEnumerable parts) - { - this.parts = parts.ToList(); - } - - public void Draw(IXLWorksheet sheet) - { - sheet.Style.Font.FontName = "Calibri"; - sheet.Style.Font.FontSize = 12; - - sheet.Cell(2, 2) - .SetValue("Содержание") - .Style - .Font.SetBold(true) - .Font.SetFontSize(14); - - for (int i = 0; i < parts.Count; i++) - { - sheet.Cell(4 + i, 1) - .SetValue(i + 1); - - sheet.Cell(4 + i, 2) - .SetValue(parts[i].Name); - } - } + this.parts = parts.ToList(); } + public void Draw(IXLWorksheet sheet) + { + sheet.Style.Font.FontName = "Calibri"; + sheet.Style.Font.FontSize = 12; + + sheet.Cell(2, 2) + .SetValue("Содержание") + .Style + .Font.SetBold(true) + .Font.SetFontSize(14); + + for (int i = 0; i < parts.Count; i++) + { + sheet.Cell(4 + i, 1) + .SetValue(i + 1); + + sheet.Cell(4 + i, 2) + .SetValue(parts[i].Name); + } + } } diff --git a/AsbCloudInfrastructure/Services/DrillingProgram/Convert/ConvertToPdf.cs b/AsbCloudInfrastructure/Services/DrillingProgram/Convert/ConvertToPdf.cs index 4c789698..a2720657 100644 --- a/AsbCloudInfrastructure/Services/DrillingProgram/Convert/ConvertToPdf.cs +++ b/AsbCloudInfrastructure/Services/DrillingProgram/Convert/ConvertToPdf.cs @@ -8,82 +8,80 @@ using System; using iText.Kernel.Pdf; using iText.Kernel.Utils; -namespace AsbCloudInfrastructure.Services.DrillingProgram.Convert +namespace AsbCloudInfrastructure.Services.DrillingProgram.Convert; + + +sealed internal class ConvertToPdf { + internal static readonly string[] filesExtensions = { ".xlsx", ".xls", ".ods", ".odt", ".doc", ".docx", ".pdf" }; - sealed internal class ConvertToPdf + private static void MergeFiles(IEnumerable inputFiles, string outFile) { - internal static readonly string[] filesExtensions = { ".xlsx", ".xls", ".ods", ".odt", ".doc", ".docx", ".pdf" }; - - private static void MergeFiles(IEnumerable inputFiles, string outFile) + using var docResult = new PdfDocument(new PdfWriter(outFile)); + var merger = new PdfMerger(docResult); + + foreach (var fileName in inputFiles) { - using var docResult = new PdfDocument(new PdfWriter(outFile)); - var merger = new PdfMerger(docResult); - - foreach (var fileName in inputFiles) - { - using var doc = new PdfDocument(new PdfReader(fileName)); - merger.Merge(doc, 1, doc.GetNumberOfPages()); - doc.Close(); - }; - - docResult.Close(); - } - - private static (string programFile, string programArg) GetOptionsStartupProcess (string inputFileName, string resultFileDir) - { - (string programFile, string programArg) startupOptions; - if (OperatingSystem.IsWindows()) - { - startupOptions.programFile = "C:\\Program Files\\LibreOffice\\program\\soffice.exe"; - startupOptions.programArg = $"-headless -convert-to pdf {inputFileName} --outdir {resultFileDir}"; - return startupOptions; - } - if(OperatingSystem.IsLinux()) - { - startupOptions.programFile = "/usr/bin/soffice"; - startupOptions.programArg = $"--headless --convert-to pdf {inputFileName} --outdir {resultFileDir}"; - return (startupOptions); - } - - throw new NotSupportedException ("Вызов процесса в текущей операционной системе не возможен"); - } - - private static async Task StartConvertProcessAsync(string inputFileName, string resultFileDir, CancellationToken token) - { - var (programFile, programArg) = GetOptionsStartupProcess(inputFileName, resultFileDir); - var command = Cli.Wrap(programFile) - .WithArguments(programArg); - await command.ExecuteAsync(token); - } - - public static async Task GetConverteAndMergedFileAsync(IEnumerable files, string resultPath, string convertedFilesDir, CancellationToken token) - { - var badFiles = files.Where(f => !filesExtensions.Contains(Path.GetExtension(f))); - if (badFiles.Any()) - { - throw new FileFormatException($"Файлы: {string.Join(", ", badFiles)} - неподдерживаемого формата. " + - $"Они не могут быть добавлены в список файлов для конвертации и слияния в общий файл программы бурения."); - } - var listFiles = files - .Distinct() - .Select(f => new - { - inputFile = f, - convertedFile = Path.Combine(convertedFilesDir, "pdf", Path.ChangeExtension(Path.GetFileName(f), ".pdf")) - }) - .ToList(); - foreach (var file in listFiles) - { - var fileExt = Path.GetExtension(file.inputFile).ToLower(); - if (fileExt != ".pdf") - { - await StartConvertProcessAsync(file.inputFile, Path.GetDirectoryName(file.convertedFile)!, token); - } - } - MergeFiles(listFiles.Select(c => c.convertedFile), resultPath); - Directory.Delete(Path.Combine(convertedFilesDir, "pdf"), true); - } + using var doc = new PdfDocument(new PdfReader(fileName)); + merger.Merge(doc, 1, doc.GetNumberOfPages()); + doc.Close(); + }; + + docResult.Close(); } + private static (string programFile, string programArg) GetOptionsStartupProcess (string inputFileName, string resultFileDir) + { + (string programFile, string programArg) startupOptions; + if (OperatingSystem.IsWindows()) + { + startupOptions.programFile = "C:\\Program Files\\LibreOffice\\program\\soffice.exe"; + startupOptions.programArg = $"-headless -convert-to pdf {inputFileName} --outdir {resultFileDir}"; + return startupOptions; + } + if(OperatingSystem.IsLinux()) + { + startupOptions.programFile = "/usr/bin/soffice"; + startupOptions.programArg = $"--headless --convert-to pdf {inputFileName} --outdir {resultFileDir}"; + return (startupOptions); + } + + throw new NotSupportedException ("Вызов процесса в текущей операционной системе не возможен"); + } + + private static async Task StartConvertProcessAsync(string inputFileName, string resultFileDir, CancellationToken token) + { + var (programFile, programArg) = GetOptionsStartupProcess(inputFileName, resultFileDir); + var command = Cli.Wrap(programFile) + .WithArguments(programArg); + await command.ExecuteAsync(token); + } + + public static async Task GetConverteAndMergedFileAsync(IEnumerable files, string resultPath, string convertedFilesDir, CancellationToken token) + { + var badFiles = files.Where(f => !filesExtensions.Contains(Path.GetExtension(f))); + if (badFiles.Any()) + { + throw new FileFormatException($"Файлы: {string.Join(", ", badFiles)} - неподдерживаемого формата. " + + $"Они не могут быть добавлены в список файлов для конвертации и слияния в общий файл программы бурения."); + } + var listFiles = files + .Distinct() + .Select(f => new + { + inputFile = f, + convertedFile = Path.Combine(convertedFilesDir, "pdf", Path.ChangeExtension(Path.GetFileName(f), ".pdf")) + }) + .ToList(); + foreach (var file in listFiles) + { + var fileExt = Path.GetExtension(file.inputFile).ToLower(); + if (fileExt != ".pdf") + { + await StartConvertProcessAsync(file.inputFile, Path.GetDirectoryName(file.convertedFile)!, token); + } + } + MergeFiles(listFiles.Select(c => c.convertedFile), resultPath); + Directory.Delete(Path.Combine(convertedFilesDir, "pdf"), true); + } } diff --git a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs index 06058d4d..5130a50a 100644 --- a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs +++ b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs @@ -20,556 +20,554 @@ using AsbCloudApp.Requests; using AsbCloudApp.Services.Notifications; using AsbCloudInfrastructure.Services.Email; -namespace AsbCloudInfrastructure.Services.DrillingProgram -{ +namespace AsbCloudInfrastructure.Services.DrillingProgram; + # nullable enable - public class DrillingProgramService : IDrillingProgramService +public class DrillingProgramService : IDrillingProgramService +{ + private static readonly Dictionary drillingProgramCreateErrors = new Dictionary(); + + private readonly IAsbCloudDbContext context; + private readonly FileService fileService; + private readonly IUserRepository userRepository; + private readonly IWellService wellService; + private readonly IConfiguration configuration; + private readonly BackgroundWorker backgroundWorker; + private readonly NotificationService notificationService; + + private const int idTransportType = 1; + + private const int idFileCategoryDrillingProgram = 1000; + private const int idFileCategoryDrillingProgramPartsStart = 1001; + private const int idFileCategoryDrillingProgramPartsEnd = 1100; + + private const int idPartStateNoFile = 0; + private const int idPartStateApproving = 1; + private const int idPartStateApproved = 2; + + private const int idMarkTypeReject = 0; + private const int idMarkTypeApprove = 1; + + private const int idUserRolePublisher = 1; + private const int idUserRoleApprover = 2; + + private const int idStateNotInitialized = 0; + private const int idStateApproving = 1; + private const int idStateCreating = 2; + private const int idStateReady = 3; + private const int idStateError = 4; + + private static readonly string[] validFileExtensions = ConvertToPdf.filesExtensions; + + public DrillingProgramService( + IAsbCloudDbContext context, + FileService fileService, + IUserRepository userRepository, + IWellService wellService, + IConfiguration configuration, + BackgroundWorker backgroundWorker, + NotificationService notificationService) { - private static readonly Dictionary drillingProgramCreateErrors = new Dictionary(); - - private readonly IAsbCloudDbContext context; - private readonly FileService fileService; - private readonly IUserRepository userRepository; - private readonly IWellService wellService; - private readonly IConfiguration configuration; - private readonly BackgroundWorker backgroundWorker; - private readonly NotificationService notificationService; - - private const int idTransportType = 1; - - private const int idFileCategoryDrillingProgram = 1000; - private const int idFileCategoryDrillingProgramPartsStart = 1001; - private const int idFileCategoryDrillingProgramPartsEnd = 1100; - - private const int idPartStateNoFile = 0; - private const int idPartStateApproving = 1; - private const int idPartStateApproved = 2; - - private const int idMarkTypeReject = 0; - private const int idMarkTypeApprove = 1; - - private const int idUserRolePublisher = 1; - private const int idUserRoleApprover = 2; - - private const int idStateNotInitialized = 0; - private const int idStateApproving = 1; - private const int idStateCreating = 2; - private const int idStateReady = 3; - private const int idStateError = 4; - - private static readonly string[] validFileExtensions = ConvertToPdf.filesExtensions; - - public DrillingProgramService( - IAsbCloudDbContext context, - FileService fileService, - IUserRepository userRepository, - IWellService wellService, - IConfiguration configuration, - BackgroundWorker backgroundWorker, - NotificationService notificationService) - { - this.context = context; - this.fileService = fileService; - this.userRepository = userRepository; - this.wellService = wellService; - this.configuration = configuration; - this.backgroundWorker = backgroundWorker; - this.notificationService = notificationService; - } - - public async Task> GetAvailableUsers(int idWell, CancellationToken token = default) - { - var users = await context.RelationCompaniesWells - .Include(r => r.Company) - .ThenInclude(c => c.Users) - .Where(r => r.IdWell == idWell) - .SelectMany(r => r.Company.Users) - .Where(u => u != null && !string.IsNullOrEmpty(u.Email)) - .ToListAsync(token); - var usersDto = users.Adapt>(); - return usersDto; - } - - public async Task> GetCategoriesAsync(CancellationToken token = default) - { - var result = await context.FileCategories - .Where(c => c.Id > idFileCategoryDrillingProgramPartsStart && c.Id < idFileCategoryDrillingProgramPartsEnd) - .ToListAsync(token); - return result.Select(c => c.Adapt()); - } - - public async Task GetStateAsync(int idWell, int idUser, CancellationToken token = default) - { - var fileCategories = await context.FileCategories - .Where(c => c.Id >= idFileCategoryDrillingProgramPartsStart && - c.Id < idFileCategoryDrillingProgramPartsEnd) - .ToListAsync(token); - - var files = await context.Files - .Include(f => f.FileMarks) - .ThenInclude(m => m.User) - .Include(f => f.Author) - .Include(f => f.FileCategory) - .Where(f => f.IdWell == idWell && - f.IdCategory >= idFileCategoryDrillingProgram && - f.IdCategory < idFileCategoryDrillingProgramPartsEnd && - f.IsDeleted == false) - .OrderBy(f => f.UploadDate) - .ToListAsync(token); - - var partEntities = await context.DrillingProgramParts - .Include(p => p.RelatedUsers) - .ThenInclude(r => r.User) - .ThenInclude(u => u.Company) - .Where(p => p.IdWell == idWell) - .ToListAsync(token); - - var parts = new List(partEntities.Count); - var timezoneOffset = wellService.GetTimezone(idWell)?.Hours ?? 5; - foreach (var partEntity in partEntities) - { - var part = ConvertPart(idUser, fileCategories, files, partEntity, timezoneOffset); - parts.Add(part); - } - - var state = new DrillingProgramStateDto - { - Parts = parts, - Program = files.FirstOrDefault(f => f.IdCategory == idFileCategoryDrillingProgram) - ?.Adapt(), - PermissionToEdit = userRepository.HasPermission(idUser, "DrillingProgram.edit"), - }; - - if (parts.Any()) - { - if (parts.All(p => p.IdState == idPartStateApproved)) - { - if (state.Program is not null) - { - state.IdState = idStateReady; - } - else - { - var workId = MakeWorkId(idWell); - if (drillingProgramCreateErrors.ContainsKey(workId)) - { - state.IdState = idStateError; - state.Error = drillingProgramCreateErrors[workId]; - } - else - state.IdState = idStateCreating; - } - } - else - state.IdState = idStateApproving; - } - else - state.IdState = idStateNotInitialized; - - await EnqueueMakeProgramWorkAsync(idWell, state, token); - return state; - } - - private static bool IsFileExtensionValid(string file) - { - var fileExt = Path.GetExtension(file).ToLower(); - return validFileExtensions.Contains(fileExt); - } - - public async Task AddFile(int idWell, int idFileCategory, int idUser, string fileFullName, Stream fileStream, CancellationToken token = default) - { - if (!IsFileExtensionValid(fileFullName)) - throw new FileFormatException($"Файл {fileFullName} - не поддерживаемого формата. Файл не может быть загружен."); - - var part = await context.DrillingProgramParts - .Include(p => p.RelatedUsers) - .ThenInclude(r => r.User) - .FirstOrDefaultAsync(p => p.IdWell == idWell && p.IdFileCategory == idFileCategory, token) - ?? throw new ArgumentInvalidException(nameof(idFileCategory), $"DrillingProgramPart id == {idFileCategory} does not exist"); - - if (!part.RelatedUsers.Any(r => r.IdUser == idUser && r.IdUserRole == idUserRolePublisher)) - throw new ForbidException($"User {idUser} is not in the publisher list."); - - var result = await fileService.SaveAsync( - part.IdWell, - idUser, - part.IdFileCategory, - fileFullName, - fileStream, - token); - - await RemoveDrillingProgramAsync(part.IdWell, token); - - await NotifyApproversAsync(part, result.Id, fileFullName, token); - - return result.Id; - } - - public async Task AddPartsAsync(int idWell, IEnumerable idFileCategories, CancellationToken token = default) - { - if (!idFileCategories.Any()) - return 0; - - var existingCategories = await context.DrillingProgramParts - .Where(p => p.IdWell == idWell) - .Select(p => p.IdFileCategory) - .ToListAsync(token); - - var newParts = idFileCategories - .Where(c => !existingCategories.Any(e => e == c)) - .Select(c => new DrillingProgramPart - { - IdWell = idWell, - IdFileCategory = c, - }); - - context.DrillingProgramParts.AddRange(newParts); - var affected = await context.SaveChangesAsync(token); - - await RemoveDrillingProgramAsync(idWell, token); - return affected; - } - - public async Task RemovePartsAsync(int idWell, IEnumerable idFileCategories, CancellationToken token = default) - { - var whereQuery = context.DrillingProgramParts - .Where(p => p.IdWell == idWell && idFileCategories.Contains(p.IdFileCategory)); - - context.DrillingProgramParts.RemoveRange(whereQuery); - - await RemoveDrillingProgramAsync(idWell, token); - return await context.SaveChangesAsync(token); - } - - public async Task AddUserAsync(int idWell, int idFileCategory, int idUser, int idUserRole, CancellationToken token = default) - { - var user = await userRepository.GetOrDefaultAsync(idUser, token) - ?? throw new ArgumentInvalidException(nameof(idUser), $"User id: {idUser} does not exist"); - - var part = await context.DrillingProgramParts - .Include(p => p.FileCategory) - .FirstOrDefaultAsync(p => p.IdWell == idWell && p.IdFileCategory == idFileCategory, token) - ?? throw new ArgumentInvalidException(nameof(idFileCategory), $"DrillingProgramPart idFileCategory: {idFileCategory} does not exist"); - - if (idUserRole != idUserRoleApprover && idUserRole != idUserRolePublisher) - throw new ArgumentInvalidException(nameof(idUserRole), $"idUserRole ({idUserRole}), should be approver ({idUserRoleApprover}) or publisher ({idUserRolePublisher})"); - - var oldRelation = await context.RelationDrillingProgramPartUsers - .FirstOrDefaultAsync(r => r.IdUser == idUser && r.IdDrillingProgramPart == part.Id, token); - - if (oldRelation is not null) - context.RelationDrillingProgramPartUsers.Remove(oldRelation); - - var newRelation = new RelationUserDrillingProgramPart - { - IdUser = idUser, - IdDrillingProgramPart = part.Id, - IdUserRole = idUserRole, - }; - context.RelationDrillingProgramPartUsers.Add(newRelation); - if (idUserRole == idUserRoleApprover) - await RemoveDrillingProgramAsync(part.IdWell, token); - - if (idUserRole == idUserRolePublisher) - await NotifyNewPublisherAsync(idWell, user, part.FileCategory.Name, token); - - return await context.SaveChangesAsync(token); - } - - public async Task RemoveUserAsync(int idWell, int idFileCategory, int idUser, int idUserRole, CancellationToken token = default) - { - var whereQuery = context.RelationDrillingProgramPartUsers - .Include(r => r.DrillingProgramPart) - .Where(r => r.IdUser == idUser && - r.IdUserRole == idUserRole && - r.DrillingProgramPart.IdWell == idWell && - r.DrillingProgramPart.IdFileCategory == idFileCategory); - - context.RelationDrillingProgramPartUsers.RemoveRange(whereQuery); - - return await context.SaveChangesAsync(token); - } - - public async Task AddOrReplaceFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token) - { - if (fileMarkDto.IdMarkType != idMarkTypeApprove && - fileMarkDto.IdMarkType != idMarkTypeReject) - throw new ArgumentInvalidException(nameof(fileMarkDto), $"В этом методе допустимы только отметки о принятии или отклонении."); - - var fileInfo = await fileService.GetOrDefaultAsync(fileMarkDto.IdFile, token) - ?? throw new ArgumentInvalidException(nameof(fileMarkDto), $"Файла для такой отметки не существует."); - - if (fileInfo.IdCategory < idFileCategoryDrillingProgramPartsStart || - fileInfo.IdCategory > idFileCategoryDrillingProgramPartsEnd) - throw new ArgumentInvalidException(nameof(fileMarkDto), $"Этот метод допустим только для файлов-частей программы бурения."); - - var part = await context.DrillingProgramParts - .Include(p => p.RelatedUsers) - .ThenInclude(r => r.User) - .AsNoTracking() - .FirstOrDefaultAsync(p => p.IdWell == fileInfo.IdWell && p.IdFileCategory == fileInfo.IdCategory, token); - - var user = part?.RelatedUsers.FirstOrDefault(r => r.IdUser == idUser && r.IdUserRole == idUserRoleApprover)?.User - ?? throw new ForbidException($"User {idUser} is not in the approvers list."); - - fileMarkDto.User = user.Adapt(); - - var oldMarksIds = fileInfo.FileMarks - .Where(m => m.User?.Id == idUser) - .Select(m => m.Id); - - if (oldMarksIds?.Any() == true) - await fileService.MarkFileMarkAsDeletedAsync(oldMarksIds, token); - - var result = await fileService.CreateFileMarkAsync(fileMarkDto, idUser, token) - .ConfigureAwait(false); - - if (fileMarkDto.IdMarkType == idMarkTypeReject) - { - await RemoveDrillingProgramAsync(fileInfo.IdWell, token); - await NotifyPublisherOnRejectAsync(fileMarkDto, token); - } - else - { - // если все согласованты согласовали - оповещаем публикатора - var approvers = part!.RelatedUsers - .Where(u => u.IdUserRole == idUserRoleApprover); - if (approvers - .All(user => fileInfo.FileMarks - ?.Any(mark => (mark.IdMarkType == idMarkTypeApprove && mark.User?.Id == user.IdUser && !mark.IsDeleted)) == true || - (fileMarkDto.IdMarkType == idMarkTypeApprove && user.IdUser == idUser))) - { - await NotifyPublisherOnFullAccepAsync(fileMarkDto, token); - } - } - return result; - } - - public async Task MarkAsDeletedFileMarkAsync(int idMark, - CancellationToken token) - { - var fileInfo = await fileService.GetByMarkId(idMark, token) - .ConfigureAwait(false); - - if (fileInfo.IdCategory < idFileCategoryDrillingProgramPartsStart || - fileInfo.IdCategory > idFileCategoryDrillingProgramPartsEnd) - throw new ArgumentInvalidException(nameof(idMark), $"Этот метод допустим только для файлов-частей программы бурения."); - - var result = await fileService.MarkFileMarkAsDeletedAsync(idMark, token) - .ConfigureAwait(false); - - await RemoveDrillingProgramAsync(fileInfo.IdWell, token); - return result; - } - - private async Task NotifyPublisherOnFullAccepAsync(FileMarkDto fileMark, CancellationToken token) - { - var file = await fileService.GetOrDefaultAsync(fileMark.IdFile, token); - var well = await wellService.GetOrDefaultAsync(file!.IdWell, token) - ?? throw new ArgumentInvalidException(nameof(file.IdWell), "idWell doesn`t exist"); - - var user = file.Author!; - var factory = new DrillingMailBodyFactory(configuration); - var subject = factory.MakeSubject(well, "Загруженный вами документ полностью согласован"); - var body = factory.MakeMailBodyForPublisherOnFullAccept(well, user.Name ?? string.Empty, file.Id, file.Name); - - await notificationService.NotifyAsync(new NotifyRequest - { - IdUser = user.Id, - IdNotificationCategory = NotificationCategory.IdSystemNotificationCategory, - Title = subject, - Message = body, - IdTransportType = idTransportType - }, token); - } - - private async Task NotifyPublisherOnRejectAsync(FileMarkDto fileMark, CancellationToken token) - { - var file = await fileService.GetOrDefaultAsync(fileMark.IdFile, token); - var well = await wellService.GetOrDefaultAsync(file!.IdWell, token) - ?? throw new ArgumentInvalidException(nameof(file.IdWell), "idWell doesn`t exist"); - - var user = file.Author!; - var factory = new DrillingMailBodyFactory(configuration); - var subject = factory.MakeSubject(well, "Загруженный вами документ отклонен"); - var body = factory.MakeMailBodyForPublisherOnReject(well, user.Name ?? string.Empty, file.Id, file.Name, fileMark); - - await notificationService.NotifyAsync(new NotifyRequest - { - IdUser = user.Id, - IdNotificationCategory = NotificationCategory.IdSystemNotificationCategory, - Title = subject, - Message = body, - IdTransportType = idTransportType - }, token); - } - - private async Task NotifyApproversAsync(DrillingProgramPart part, int idFile, string fileName, CancellationToken token) - { - var well = await wellService.GetOrDefaultAsync(part.IdWell, token) - ?? throw new ArgumentInvalidException(nameof(part.IdWell), "idWell doesn`t exist"); - - var factory = new DrillingMailBodyFactory(configuration); - var subject = factory.MakeSubject(well, "Загружен новый документ для согласования."); - var users = part.RelatedUsers - .Where(r => r.IdUserRole == idUserRoleApprover) - .Select(r => r.User); - - foreach (var user in users) - { - var body = factory.MakeMailBodyForApproverNewFile(well, user.Name ?? string.Empty, idFile, fileName); - await notificationService.NotifyAsync(new NotifyRequest - { - IdUser = user.Id, - IdNotificationCategory = NotificationCategory.IdSystemNotificationCategory, - Title = subject, - Message = body, - IdTransportType = idTransportType - }, token); - } - } - - private async Task NotifyNewPublisherAsync(int idWell, UserDto user, string documentCategory, CancellationToken token) - { - var well = await wellService.GetOrDefaultAsync(idWell, token) - ?? throw new ArgumentInvalidException(nameof(idWell), "idWell doesn`t exist"); - - var factory = new DrillingMailBodyFactory(configuration); - var subject = factory.MakeSubject(well, $"От вас ожидается загрузка на портал документа «{documentCategory}»"); - var body = factory.MakeMailBodyForNewPublisher(well, user.Name ?? string.Empty, documentCategory); - - await notificationService.NotifyAsync(new NotifyRequest - { - IdUser = user.Id, - IdNotificationCategory = NotificationCategory.IdSystemNotificationCategory, - Title = subject, - Message = body, - IdTransportType = idTransportType - }, token); - } - - private static DrillingProgramPartDto ConvertPart(int idUser, List fileCategories, List files, DrillingProgramPart partEntity, double timezoneOffset) - { - var part = new DrillingProgramPartDto - { - IdFileCategory = partEntity.IdFileCategory, - Name = fileCategories.FirstOrDefault(c => c.Id == partEntity.IdFileCategory)!.Name, - Approvers = partEntity.RelatedUsers - .Where(r => r.IdUserRole == idUserRoleApprover) - .Select(r => r.User.Adapt()), - Publishers = partEntity.RelatedUsers - .Where(r => r.IdUserRole == idUserRolePublisher) - .Select(r => r.User.Adapt()), - PermissionToApprove = partEntity.RelatedUsers - .Any(r => r.IdUserRole == idUserRoleApprover && r.IdUser == idUser), - PermissionToUpload = partEntity.RelatedUsers - .Any(r => r.IdUserRole == idUserRolePublisher && r.IdUser == idUser), - }; - - var fileEntity = files.LastOrDefault(f => f.IdCategory == partEntity.IdFileCategory); - - if (fileEntity is not null) - { - part.IdState = idPartStateApproving; - part.File = new FileInfoDto - { - Id = fileEntity.Id, - Author = fileEntity.Author?.Adapt(), - IdAuthor = fileEntity.Author?.Id, - IdCategory = fileEntity.IdCategory, - IdWell = fileEntity.IdWell, - Name = fileEntity.Name, - Size = fileEntity.Size, - UploadDate = fileEntity.UploadDate.ToOffset(TimeSpan.FromHours(timezoneOffset)), - }; - - var marks = fileEntity.FileMarks?.Where(m => !m.IsDeleted); - if (marks?.Any() == true) - { - part.File.FileMarks = marks.Select(m => - { - var mark = m.Adapt(); - mark.DateCreated = m.DateCreated.ToOffset(TimeSpan.FromHours(timezoneOffset)); - return mark; - }); - var hasReject = marks.Any(m => m.IdMarkType == idMarkTypeReject); - if (!hasReject) - { - var allAproved = part.Approvers.All(a => marks.Any(m => m.IdUser == a.Id && m.IdMarkType == idMarkTypeApprove)); - if (allAproved) - part.IdState = idPartStateApproved; - } - } - } - else - part.IdState = idPartStateNoFile; - - return part; - } - - private async Task EnqueueMakeProgramWorkAsync(int idWell, DrillingProgramStateDto state, CancellationToken token) - { - if (state.IdState == idStateCreating) - { - var workId = MakeWorkId(idWell); - if (!backgroundWorker.Works.Any(w => w.Id == workId)) - { - var well = (await wellService.GetOrDefaultAsync(idWell, token))!; - var resultFileName = $"Программа бурения {well.Cluster} {well.Caption}.pdf"; - var convertedFilesDir = Path.Combine(Path.GetTempPath(), "drillingProgram", $"{well.Cluster}_{well.Caption}"); - var tempResultFilePath = Path.Combine(convertedFilesDir, resultFileName); - var workAction = async (string workId, IServiceProvider serviceProvider, Action onProgress, CancellationToken token) => - { - var context = serviceProvider.GetRequiredService(); - var fileService = serviceProvider.GetRequiredService(); - var files = state.Parts.Select(p => fileService.GetUrl(p.File!)); - onProgress($"Start converting {files.Count()} files to PDF.", null); - await ConvertToPdf.GetConverteAndMergedFileAsync(files, tempResultFilePath, convertedFilesDir, token); - await fileService.MoveAsync(idWell, null, idFileCategoryDrillingProgram, resultFileName, tempResultFilePath, token); - }; - - var onErrorAction = (string workId, Exception exception, CancellationToken token) => - { - var message = $"Не удалось сформировать программу бурения по скважине {well?.Caption}"; - drillingProgramCreateErrors[workId] = new() - { - Message = message, - Exception = exception.Message, - }; - return Task.CompletedTask; - }; - - var work = Work.CreateByDelegate(workId, workAction); - work.OnErrorAsync = onErrorAction; - backgroundWorker.Enqueue(work); - } - } - } - - public void ClearError(int idWell) - { - var workId = MakeWorkId(idWell); - drillingProgramCreateErrors.Remove(workId); - } - - private async Task RemoveDrillingProgramAsync(int idWell, CancellationToken token) - { - var workId = MakeWorkId(idWell); - backgroundWorker.TryRemoveFromQueue(workId); - - var filesIds = await context.Files - .Where(f => f.IdWell == idWell && - f.IdCategory == idFileCategoryDrillingProgram) - .Select(f => f.Id) - .ToListAsync(token); - if (filesIds.Any()) - return await fileService.DeleteAsync(filesIds, token); - else - return 0; - } - - private static string MakeWorkId(int idWell) - => $"Make drilling program for wellId {idWell}"; + this.context = context; + this.fileService = fileService; + this.userRepository = userRepository; + this.wellService = wellService; + this.configuration = configuration; + this.backgroundWorker = backgroundWorker; + this.notificationService = notificationService; } + public async Task> GetAvailableUsers(int idWell, CancellationToken token = default) + { + var users = await context.RelationCompaniesWells + .Include(r => r.Company) + .ThenInclude(c => c.Users) + .Where(r => r.IdWell == idWell) + .SelectMany(r => r.Company.Users) + .Where(u => u != null && !string.IsNullOrEmpty(u.Email)) + .ToListAsync(token); + var usersDto = users.Adapt>(); + return usersDto; + } + + public async Task> GetCategoriesAsync(CancellationToken token = default) + { + var result = await context.FileCategories + .Where(c => c.Id > idFileCategoryDrillingProgramPartsStart && c.Id < idFileCategoryDrillingProgramPartsEnd) + .ToListAsync(token); + return result.Select(c => c.Adapt()); + } + + public async Task GetStateAsync(int idWell, int idUser, CancellationToken token = default) + { + var fileCategories = await context.FileCategories + .Where(c => c.Id >= idFileCategoryDrillingProgramPartsStart && + c.Id < idFileCategoryDrillingProgramPartsEnd) + .ToListAsync(token); + + var files = await context.Files + .Include(f => f.FileMarks) + .ThenInclude(m => m.User) + .Include(f => f.Author) + .Include(f => f.FileCategory) + .Where(f => f.IdWell == idWell && + f.IdCategory >= idFileCategoryDrillingProgram && + f.IdCategory < idFileCategoryDrillingProgramPartsEnd && + f.IsDeleted == false) + .OrderBy(f => f.UploadDate) + .ToListAsync(token); + + var partEntities = await context.DrillingProgramParts + .Include(p => p.RelatedUsers) + .ThenInclude(r => r.User) + .ThenInclude(u => u.Company) + .Where(p => p.IdWell == idWell) + .ToListAsync(token); + + var parts = new List(partEntities.Count); + var timezoneOffset = wellService.GetTimezone(idWell)?.Hours ?? 5; + foreach (var partEntity in partEntities) + { + var part = ConvertPart(idUser, fileCategories, files, partEntity, timezoneOffset); + parts.Add(part); + } + + var state = new DrillingProgramStateDto + { + Parts = parts, + Program = files.FirstOrDefault(f => f.IdCategory == idFileCategoryDrillingProgram) + ?.Adapt(), + PermissionToEdit = userRepository.HasPermission(idUser, "DrillingProgram.edit"), + }; + + if (parts.Any()) + { + if (parts.All(p => p.IdState == idPartStateApproved)) + { + if (state.Program is not null) + { + state.IdState = idStateReady; + } + else + { + var workId = MakeWorkId(idWell); + if (drillingProgramCreateErrors.ContainsKey(workId)) + { + state.IdState = idStateError; + state.Error = drillingProgramCreateErrors[workId]; + } + else + state.IdState = idStateCreating; + } + } + else + state.IdState = idStateApproving; + } + else + state.IdState = idStateNotInitialized; + + await EnqueueMakeProgramWorkAsync(idWell, state, token); + return state; + } + + private static bool IsFileExtensionValid(string file) + { + var fileExt = Path.GetExtension(file).ToLower(); + return validFileExtensions.Contains(fileExt); + } + + public async Task AddFile(int idWell, int idFileCategory, int idUser, string fileFullName, Stream fileStream, CancellationToken token = default) + { + if (!IsFileExtensionValid(fileFullName)) + throw new FileFormatException($"Файл {fileFullName} - не поддерживаемого формата. Файл не может быть загружен."); + + var part = await context.DrillingProgramParts + .Include(p => p.RelatedUsers) + .ThenInclude(r => r.User) + .FirstOrDefaultAsync(p => p.IdWell == idWell && p.IdFileCategory == idFileCategory, token) + ?? throw new ArgumentInvalidException(nameof(idFileCategory), $"DrillingProgramPart id == {idFileCategory} does not exist"); + + if (!part.RelatedUsers.Any(r => r.IdUser == idUser && r.IdUserRole == idUserRolePublisher)) + throw new ForbidException($"User {idUser} is not in the publisher list."); + + var result = await fileService.SaveAsync( + part.IdWell, + idUser, + part.IdFileCategory, + fileFullName, + fileStream, + token); + + await RemoveDrillingProgramAsync(part.IdWell, token); + + await NotifyApproversAsync(part, result.Id, fileFullName, token); + + return result.Id; + } + + public async Task AddPartsAsync(int idWell, IEnumerable idFileCategories, CancellationToken token = default) + { + if (!idFileCategories.Any()) + return 0; + + var existingCategories = await context.DrillingProgramParts + .Where(p => p.IdWell == idWell) + .Select(p => p.IdFileCategory) + .ToListAsync(token); + + var newParts = idFileCategories + .Where(c => !existingCategories.Any(e => e == c)) + .Select(c => new DrillingProgramPart + { + IdWell = idWell, + IdFileCategory = c, + }); + + context.DrillingProgramParts.AddRange(newParts); + var affected = await context.SaveChangesAsync(token); + + await RemoveDrillingProgramAsync(idWell, token); + return affected; + } + + public async Task RemovePartsAsync(int idWell, IEnumerable idFileCategories, CancellationToken token = default) + { + var whereQuery = context.DrillingProgramParts + .Where(p => p.IdWell == idWell && idFileCategories.Contains(p.IdFileCategory)); + + context.DrillingProgramParts.RemoveRange(whereQuery); + + await RemoveDrillingProgramAsync(idWell, token); + return await context.SaveChangesAsync(token); + } + + public async Task AddUserAsync(int idWell, int idFileCategory, int idUser, int idUserRole, CancellationToken token = default) + { + var user = await userRepository.GetOrDefaultAsync(idUser, token) + ?? throw new ArgumentInvalidException(nameof(idUser), $"User id: {idUser} does not exist"); + + var part = await context.DrillingProgramParts + .Include(p => p.FileCategory) + .FirstOrDefaultAsync(p => p.IdWell == idWell && p.IdFileCategory == idFileCategory, token) + ?? throw new ArgumentInvalidException(nameof(idFileCategory), $"DrillingProgramPart idFileCategory: {idFileCategory} does not exist"); + + if (idUserRole != idUserRoleApprover && idUserRole != idUserRolePublisher) + throw new ArgumentInvalidException(nameof(idUserRole), $"idUserRole ({idUserRole}), should be approver ({idUserRoleApprover}) or publisher ({idUserRolePublisher})"); + + var oldRelation = await context.RelationDrillingProgramPartUsers + .FirstOrDefaultAsync(r => r.IdUser == idUser && r.IdDrillingProgramPart == part.Id, token); + + if (oldRelation is not null) + context.RelationDrillingProgramPartUsers.Remove(oldRelation); + + var newRelation = new RelationUserDrillingProgramPart + { + IdUser = idUser, + IdDrillingProgramPart = part.Id, + IdUserRole = idUserRole, + }; + context.RelationDrillingProgramPartUsers.Add(newRelation); + if (idUserRole == idUserRoleApprover) + await RemoveDrillingProgramAsync(part.IdWell, token); + + if (idUserRole == idUserRolePublisher) + await NotifyNewPublisherAsync(idWell, user, part.FileCategory.Name, token); + + return await context.SaveChangesAsync(token); + } + + public async Task RemoveUserAsync(int idWell, int idFileCategory, int idUser, int idUserRole, CancellationToken token = default) + { + var whereQuery = context.RelationDrillingProgramPartUsers + .Include(r => r.DrillingProgramPart) + .Where(r => r.IdUser == idUser && + r.IdUserRole == idUserRole && + r.DrillingProgramPart.IdWell == idWell && + r.DrillingProgramPart.IdFileCategory == idFileCategory); + + context.RelationDrillingProgramPartUsers.RemoveRange(whereQuery); + + return await context.SaveChangesAsync(token); + } + + public async Task AddOrReplaceFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token) + { + if (fileMarkDto.IdMarkType != idMarkTypeApprove && + fileMarkDto.IdMarkType != idMarkTypeReject) + throw new ArgumentInvalidException(nameof(fileMarkDto), $"В этом методе допустимы только отметки о принятии или отклонении."); + + var fileInfo = await fileService.GetOrDefaultAsync(fileMarkDto.IdFile, token) + ?? throw new ArgumentInvalidException(nameof(fileMarkDto), $"Файла для такой отметки не существует."); + + if (fileInfo.IdCategory < idFileCategoryDrillingProgramPartsStart || + fileInfo.IdCategory > idFileCategoryDrillingProgramPartsEnd) + throw new ArgumentInvalidException(nameof(fileMarkDto), $"Этот метод допустим только для файлов-частей программы бурения."); + + var part = await context.DrillingProgramParts + .Include(p => p.RelatedUsers) + .ThenInclude(r => r.User) + .AsNoTracking() + .FirstOrDefaultAsync(p => p.IdWell == fileInfo.IdWell && p.IdFileCategory == fileInfo.IdCategory, token); + + var user = part?.RelatedUsers.FirstOrDefault(r => r.IdUser == idUser && r.IdUserRole == idUserRoleApprover)?.User + ?? throw new ForbidException($"User {idUser} is not in the approvers list."); + + fileMarkDto.User = user.Adapt(); + + var oldMarksIds = fileInfo.FileMarks + .Where(m => m.User?.Id == idUser) + .Select(m => m.Id); + + if (oldMarksIds?.Any() == true) + await fileService.MarkFileMarkAsDeletedAsync(oldMarksIds, token); + + var result = await fileService.CreateFileMarkAsync(fileMarkDto, idUser, token) + .ConfigureAwait(false); + + if (fileMarkDto.IdMarkType == idMarkTypeReject) + { + await RemoveDrillingProgramAsync(fileInfo.IdWell, token); + await NotifyPublisherOnRejectAsync(fileMarkDto, token); + } + else + { + // если все согласованты согласовали - оповещаем публикатора + var approvers = part!.RelatedUsers + .Where(u => u.IdUserRole == idUserRoleApprover); + if (approvers + .All(user => fileInfo.FileMarks + ?.Any(mark => (mark.IdMarkType == idMarkTypeApprove && mark.User?.Id == user.IdUser && !mark.IsDeleted)) == true || + (fileMarkDto.IdMarkType == idMarkTypeApprove && user.IdUser == idUser))) + { + await NotifyPublisherOnFullAccepAsync(fileMarkDto, token); + } + } + return result; + } + + public async Task MarkAsDeletedFileMarkAsync(int idMark, + CancellationToken token) + { + var fileInfo = await fileService.GetByMarkId(idMark, token) + .ConfigureAwait(false); + + if (fileInfo.IdCategory < idFileCategoryDrillingProgramPartsStart || + fileInfo.IdCategory > idFileCategoryDrillingProgramPartsEnd) + throw new ArgumentInvalidException(nameof(idMark), $"Этот метод допустим только для файлов-частей программы бурения."); + + var result = await fileService.MarkFileMarkAsDeletedAsync(idMark, token) + .ConfigureAwait(false); + + await RemoveDrillingProgramAsync(fileInfo.IdWell, token); + return result; + } + + private async Task NotifyPublisherOnFullAccepAsync(FileMarkDto fileMark, CancellationToken token) + { + var file = await fileService.GetOrDefaultAsync(fileMark.IdFile, token); + var well = await wellService.GetOrDefaultAsync(file!.IdWell, token) + ?? throw new ArgumentInvalidException(nameof(file.IdWell), "idWell doesn`t exist"); + + var user = file.Author!; + var factory = new DrillingMailBodyFactory(configuration); + var subject = factory.MakeSubject(well, "Загруженный вами документ полностью согласован"); + var body = factory.MakeMailBodyForPublisherOnFullAccept(well, user.Name ?? string.Empty, file.Id, file.Name); + + await notificationService.NotifyAsync(new NotifyRequest + { + IdUser = user.Id, + IdNotificationCategory = NotificationCategory.IdSystemNotificationCategory, + Title = subject, + Message = body, + IdTransportType = idTransportType + }, token); + } + + private async Task NotifyPublisherOnRejectAsync(FileMarkDto fileMark, CancellationToken token) + { + var file = await fileService.GetOrDefaultAsync(fileMark.IdFile, token); + var well = await wellService.GetOrDefaultAsync(file!.IdWell, token) + ?? throw new ArgumentInvalidException(nameof(file.IdWell), "idWell doesn`t exist"); + + var user = file.Author!; + var factory = new DrillingMailBodyFactory(configuration); + var subject = factory.MakeSubject(well, "Загруженный вами документ отклонен"); + var body = factory.MakeMailBodyForPublisherOnReject(well, user.Name ?? string.Empty, file.Id, file.Name, fileMark); + + await notificationService.NotifyAsync(new NotifyRequest + { + IdUser = user.Id, + IdNotificationCategory = NotificationCategory.IdSystemNotificationCategory, + Title = subject, + Message = body, + IdTransportType = idTransportType + }, token); + } + + private async Task NotifyApproversAsync(DrillingProgramPart part, int idFile, string fileName, CancellationToken token) + { + var well = await wellService.GetOrDefaultAsync(part.IdWell, token) + ?? throw new ArgumentInvalidException(nameof(part.IdWell), "idWell doesn`t exist"); + + var factory = new DrillingMailBodyFactory(configuration); + var subject = factory.MakeSubject(well, "Загружен новый документ для согласования."); + var users = part.RelatedUsers + .Where(r => r.IdUserRole == idUserRoleApprover) + .Select(r => r.User); + + foreach (var user in users) + { + var body = factory.MakeMailBodyForApproverNewFile(well, user.Name ?? string.Empty, idFile, fileName); + await notificationService.NotifyAsync(new NotifyRequest + { + IdUser = user.Id, + IdNotificationCategory = NotificationCategory.IdSystemNotificationCategory, + Title = subject, + Message = body, + IdTransportType = idTransportType + }, token); + } + } + + private async Task NotifyNewPublisherAsync(int idWell, UserDto user, string documentCategory, CancellationToken token) + { + var well = await wellService.GetOrDefaultAsync(idWell, token) + ?? throw new ArgumentInvalidException(nameof(idWell), "idWell doesn`t exist"); + + var factory = new DrillingMailBodyFactory(configuration); + var subject = factory.MakeSubject(well, $"От вас ожидается загрузка на портал документа «{documentCategory}»"); + var body = factory.MakeMailBodyForNewPublisher(well, user.Name ?? string.Empty, documentCategory); + + await notificationService.NotifyAsync(new NotifyRequest + { + IdUser = user.Id, + IdNotificationCategory = NotificationCategory.IdSystemNotificationCategory, + Title = subject, + Message = body, + IdTransportType = idTransportType + }, token); + } + + private static DrillingProgramPartDto ConvertPart(int idUser, List fileCategories, List files, DrillingProgramPart partEntity, double timezoneOffset) + { + var part = new DrillingProgramPartDto + { + IdFileCategory = partEntity.IdFileCategory, + Name = fileCategories.FirstOrDefault(c => c.Id == partEntity.IdFileCategory)!.Name, + Approvers = partEntity.RelatedUsers + .Where(r => r.IdUserRole == idUserRoleApprover) + .Select(r => r.User.Adapt()), + Publishers = partEntity.RelatedUsers + .Where(r => r.IdUserRole == idUserRolePublisher) + .Select(r => r.User.Adapt()), + PermissionToApprove = partEntity.RelatedUsers + .Any(r => r.IdUserRole == idUserRoleApprover && r.IdUser == idUser), + PermissionToUpload = partEntity.RelatedUsers + .Any(r => r.IdUserRole == idUserRolePublisher && r.IdUser == idUser), + }; + + var fileEntity = files.LastOrDefault(f => f.IdCategory == partEntity.IdFileCategory); + + if (fileEntity is not null) + { + part.IdState = idPartStateApproving; + part.File = new FileInfoDto + { + Id = fileEntity.Id, + Author = fileEntity.Author?.Adapt(), + IdAuthor = fileEntity.Author?.Id, + IdCategory = fileEntity.IdCategory, + IdWell = fileEntity.IdWell, + Name = fileEntity.Name, + Size = fileEntity.Size, + UploadDate = fileEntity.UploadDate.ToOffset(TimeSpan.FromHours(timezoneOffset)), + }; + + var marks = fileEntity.FileMarks?.Where(m => !m.IsDeleted); + if (marks?.Any() == true) + { + part.File.FileMarks = marks.Select(m => + { + var mark = m.Adapt(); + mark.DateCreated = m.DateCreated.ToOffset(TimeSpan.FromHours(timezoneOffset)); + return mark; + }); + var hasReject = marks.Any(m => m.IdMarkType == idMarkTypeReject); + if (!hasReject) + { + var allAproved = part.Approvers.All(a => marks.Any(m => m.IdUser == a.Id && m.IdMarkType == idMarkTypeApprove)); + if (allAproved) + part.IdState = idPartStateApproved; + } + } + } + else + part.IdState = idPartStateNoFile; + + return part; + } + + private async Task EnqueueMakeProgramWorkAsync(int idWell, DrillingProgramStateDto state, CancellationToken token) + { + if (state.IdState == idStateCreating) + { + var workId = MakeWorkId(idWell); + if (!backgroundWorker.Works.Any(w => w.Id == workId)) + { + var well = (await wellService.GetOrDefaultAsync(idWell, token))!; + var resultFileName = $"Программа бурения {well.Cluster} {well.Caption}.pdf"; + var convertedFilesDir = Path.Combine(Path.GetTempPath(), "drillingProgram", $"{well.Cluster}_{well.Caption}"); + var tempResultFilePath = Path.Combine(convertedFilesDir, resultFileName); + var workAction = async (string workId, IServiceProvider serviceProvider, Action onProgress, CancellationToken token) => + { + var context = serviceProvider.GetRequiredService(); + var fileService = serviceProvider.GetRequiredService(); + var files = state.Parts.Select(p => fileService.GetUrl(p.File!)); + onProgress($"Start converting {files.Count()} files to PDF.", null); + await ConvertToPdf.GetConverteAndMergedFileAsync(files, tempResultFilePath, convertedFilesDir, token); + await fileService.MoveAsync(idWell, null, idFileCategoryDrillingProgram, resultFileName, tempResultFilePath, token); + }; + + var onErrorAction = (string workId, Exception exception, CancellationToken token) => + { + var message = $"Не удалось сформировать программу бурения по скважине {well?.Caption}"; + drillingProgramCreateErrors[workId] = new() + { + Message = message, + Exception = exception.Message, + }; + return Task.CompletedTask; + }; + + var work = Work.CreateByDelegate(workId, workAction); + work.OnErrorAsync = onErrorAction; + backgroundWorker.Enqueue(work); + } + } + } + + public void ClearError(int idWell) + { + var workId = MakeWorkId(idWell); + drillingProgramCreateErrors.Remove(workId); + } + + private async Task RemoveDrillingProgramAsync(int idWell, CancellationToken token) + { + var workId = MakeWorkId(idWell); + backgroundWorker.TryRemoveFromQueue(workId); + + var filesIds = await context.Files + .Where(f => f.IdWell == idWell && + f.IdCategory == idFileCategoryDrillingProgram) + .Select(f => f.Id) + .ToListAsync(token); + if (filesIds.Any()) + return await fileService.DeleteAsync(filesIds, token); + else + return 0; + } + + private static string MakeWorkId(int idWell) + => $"Make drilling program for wellId {idWell}"; } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/DrillingProgram/ImageInfo.cs b/AsbCloudInfrastructure/Services/DrillingProgram/ImageInfo.cs index bbeaa71b..2203f6da 100644 --- a/AsbCloudInfrastructure/Services/DrillingProgram/ImageInfo.cs +++ b/AsbCloudInfrastructure/Services/DrillingProgram/ImageInfo.cs @@ -1,17 +1,15 @@ using ClosedXML.Excel; -namespace AsbCloudInfrastructure.Services.DrillingProgram +namespace AsbCloudInfrastructure.Services.DrillingProgram; + + +class ImageInfo { - - class ImageInfo - { - public int Id { get; set; } - public byte[] Data { get; set; } = null!; - public int Height { get; set; } - public int Width { get; set; } - public IXLAddress TopLeftCellAddress { get; set; } = null!; - public int Left { get; set; } - public int Top { get; set; } - } - + public int Id { get; set; } + public byte[] Data { get; set; } = null!; + public int Height { get; set; } + public int Width { get; set; } + public IXLAddress TopLeftCellAddress { get; set; } = null!; + public int Left { get; set; } + public int Top { get; set; } } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/DrillingProgram/TitleListSheet.cs b/AsbCloudInfrastructure/Services/DrillingProgram/TitleListSheet.cs index 57e37111..41308f74 100644 --- a/AsbCloudInfrastructure/Services/DrillingProgram/TitleListSheet.cs +++ b/AsbCloudInfrastructure/Services/DrillingProgram/TitleListSheet.cs @@ -4,161 +4,159 @@ using System; using System.Collections.Generic; using System.Linq; -namespace AsbCloudInfrastructure.Services.DrillingProgram +namespace AsbCloudInfrastructure.Services.DrillingProgram; + + +public class TitleListSheet { + private const string directionDirectorPositionName = "Руководитель направления по ТСБ"; - public class TitleListSheet + private readonly DateTimeOffset totalDate; + private readonly FileMarkDto? acceptDirectionDirector; + private readonly List acceptsOthers; + private readonly WellDto well; + + public TitleListSheet(IEnumerable fileMarks, WellDto well) { - private const string directionDirectorPositionName = "Руководитель направления по ТСБ"; - - private readonly DateTimeOffset totalDate; - private readonly FileMarkDto? acceptDirectionDirector; - private readonly List acceptsOthers; - private readonly WellDto well; - - public TitleListSheet(IEnumerable fileMarks, WellDto well) - { - totalDate = fileMarks.Max(f => f.DateCreated); - acceptDirectionDirector = fileMarks - .OrderByDescending(f => f.DateCreated) - .FirstOrDefault(f => f.User?.Position == directionDirectorPositionName); - acceptsOthers = fileMarks - .Where(f => f.Id != acceptDirectionDirector?.Id) - .OrderBy(f => f.DateCreated) - .ToList(); - this.well = well; - } - - public void Draw(IXLWorksheet sheet) - { - const double santimetr = 0.393701; - sheet.Style.Font.FontName = "Calibri"; - sheet.Style.Font.FontSize = 12; - sheet.PageSetup.PaperSize = XLPaperSize.A4Paper; - sheet.PageSetup.Margins - .SetTop(santimetr) - .SetLeft(2 * santimetr) - .SetBottom(santimetr) - .SetRight(santimetr); - - DrawTopRightSign(sheet); - DrawMainTilte(sheet); - DrawOtherAcceptors(sheet); - - sheet.Range(51, 1, 51, 5) - .Merge() - .SetValue($"{totalDate.Year:00}") - .Style.Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center); - - var k = 4.95867768595041; - sheet.Column(1).Width = k*2.3; - sheet.Column(2).Width = k*6; - sheet.Column(3).Width = k*0.53; - sheet.Column(4).Width = k*2.3; - sheet.Column(5).Width = k*6; - } - - private void DrawTopRightSign(IXLWorksheet sheet) - { - if (acceptDirectionDirector?.User is null) - return; - - var user = acceptDirectionDirector.User; - - sheet.Cell(1, 5) - .SetValue("Согласовано:"); - - sheet.Cell(2, 5) - .SetValue(user.Position); - - sheet.Cell(3, 5) - .SetValue(user.Company?.Caption); - - sheet.Cell(4, 5) - .SetValue($"{user.Surname} {user.Name} {user.Patronymic}"); - - sheet.Cell(5, 5) - .SetValue(FormatDate(acceptDirectionDirector.DateCreated)); - - sheet.Range(1,5, 5,5).Style.Alignment - .SetHorizontal(XLAlignmentHorizontalValues.Right); - } - - private void DrawMainTilte(IXLWorksheet sheet) - { - sheet.Range(11, 1, 11, 5) - .Merge() - .SetValue($"Программа на бурение скважины №{well.Caption}, куст №{well.Cluster}"); - - sheet.Range(12, 1, 12, 5) - .Merge() - .SetValue($"{well.Deposit} месторождения"); - - sheet.Range(11, 1, 12, 5).Style - .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center) - .Font.SetFontSize(14) - .Font.SetBold(true); - } - - private void DrawOtherAcceptors(IXLWorksheet sheet) - { - const int baseRow = 16; - const int deltaRow = 7; - (int row, int col)[] addresses = - { - (baseRow + 4 * deltaRow, 4), (baseRow + 4 * deltaRow, 1), - (baseRow + 3 * deltaRow, 4), (baseRow + 3 * deltaRow, 1), - (baseRow + 2 * deltaRow, 4), (baseRow + 2 * deltaRow, 1), - (baseRow + 1 * deltaRow, 4), (baseRow + 1 * deltaRow, 1), - (baseRow + 0 * deltaRow, 4), (baseRow + 0 * deltaRow, 1), - }; - var i = 0; - for (; i < acceptsOthers.Count && i < 10; i++) - DrawAccept(sheet, acceptsOthers[i], addresses[i]); - - sheet.Cell(addresses[i-1].row - 2, 1) - .SetValue("Утверждаю:"); - } - - private static void DrawAccept(IXLWorksheet sheet, FileMarkDto mark, (int row, int col) startAddress) - { - var user = mark.User; - if(user is null) - return; - - int startRow = startAddress.row; - int startCol = startAddress.col; - - sheet.Cell(startRow, startCol) - .SetValue("Должность"); - - sheet.Range(startRow, startCol + 1, startRow + 1, startCol + 1) - .Merge() - .SetValue(user.Position); - - sheet.Cell(startRow + 2, startCol) - .SetValue("Компания"); - - sheet.Range(startRow + 2, startCol + 1, startRow + 3, startCol + 1) - .Merge() - .SetValue(user.Company?.Caption); - - sheet.Range(startRow + 4, startCol, startRow + 4, startCol + 1) - .Merge() - .SetValue($"{user.Surname} {user.Name} {user.Patronymic}"); - - sheet.Range(startRow + 5, startCol, startRow + 5, startCol + 1) - .Merge() - .SetValue(FormatDate(mark.DateCreated)); - - sheet.Range(startRow, startCol, startRow + 5, startCol + 1) - .Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin) - .Alignment.SetVertical(XLAlignmentVerticalValues.Top) - .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Left); - } - - private static string FormatDate(DateTimeOffset dateTime) - => $"{dateTime.Day:00}.{dateTime.Month:00}.{dateTime.Year:00}"; + totalDate = fileMarks.Max(f => f.DateCreated); + acceptDirectionDirector = fileMarks + .OrderByDescending(f => f.DateCreated) + .FirstOrDefault(f => f.User?.Position == directionDirectorPositionName); + acceptsOthers = fileMarks + .Where(f => f.Id != acceptDirectionDirector?.Id) + .OrderBy(f => f.DateCreated) + .ToList(); + this.well = well; } + public void Draw(IXLWorksheet sheet) + { + const double santimetr = 0.393701; + sheet.Style.Font.FontName = "Calibri"; + sheet.Style.Font.FontSize = 12; + sheet.PageSetup.PaperSize = XLPaperSize.A4Paper; + sheet.PageSetup.Margins + .SetTop(santimetr) + .SetLeft(2 * santimetr) + .SetBottom(santimetr) + .SetRight(santimetr); + + DrawTopRightSign(sheet); + DrawMainTilte(sheet); + DrawOtherAcceptors(sheet); + + sheet.Range(51, 1, 51, 5) + .Merge() + .SetValue($"{totalDate.Year:00}") + .Style.Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center); + + var k = 4.95867768595041; + sheet.Column(1).Width = k*2.3; + sheet.Column(2).Width = k*6; + sheet.Column(3).Width = k*0.53; + sheet.Column(4).Width = k*2.3; + sheet.Column(5).Width = k*6; + } + + private void DrawTopRightSign(IXLWorksheet sheet) + { + if (acceptDirectionDirector?.User is null) + return; + + var user = acceptDirectionDirector.User; + + sheet.Cell(1, 5) + .SetValue("Согласовано:"); + + sheet.Cell(2, 5) + .SetValue(user.Position); + + sheet.Cell(3, 5) + .SetValue(user.Company?.Caption); + + sheet.Cell(4, 5) + .SetValue($"{user.Surname} {user.Name} {user.Patronymic}"); + + sheet.Cell(5, 5) + .SetValue(FormatDate(acceptDirectionDirector.DateCreated)); + + sheet.Range(1,5, 5,5).Style.Alignment + .SetHorizontal(XLAlignmentHorizontalValues.Right); + } + + private void DrawMainTilte(IXLWorksheet sheet) + { + sheet.Range(11, 1, 11, 5) + .Merge() + .SetValue($"Программа на бурение скважины №{well.Caption}, куст №{well.Cluster}"); + + sheet.Range(12, 1, 12, 5) + .Merge() + .SetValue($"{well.Deposit} месторождения"); + + sheet.Range(11, 1, 12, 5).Style + .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center) + .Font.SetFontSize(14) + .Font.SetBold(true); + } + + private void DrawOtherAcceptors(IXLWorksheet sheet) + { + const int baseRow = 16; + const int deltaRow = 7; + (int row, int col)[] addresses = + { + (baseRow + 4 * deltaRow, 4), (baseRow + 4 * deltaRow, 1), + (baseRow + 3 * deltaRow, 4), (baseRow + 3 * deltaRow, 1), + (baseRow + 2 * deltaRow, 4), (baseRow + 2 * deltaRow, 1), + (baseRow + 1 * deltaRow, 4), (baseRow + 1 * deltaRow, 1), + (baseRow + 0 * deltaRow, 4), (baseRow + 0 * deltaRow, 1), + }; + var i = 0; + for (; i < acceptsOthers.Count && i < 10; i++) + DrawAccept(sheet, acceptsOthers[i], addresses[i]); + + sheet.Cell(addresses[i-1].row - 2, 1) + .SetValue("Утверждаю:"); + } + + private static void DrawAccept(IXLWorksheet sheet, FileMarkDto mark, (int row, int col) startAddress) + { + var user = mark.User; + if(user is null) + return; + + int startRow = startAddress.row; + int startCol = startAddress.col; + + sheet.Cell(startRow, startCol) + .SetValue("Должность"); + + sheet.Range(startRow, startCol + 1, startRow + 1, startCol + 1) + .Merge() + .SetValue(user.Position); + + sheet.Cell(startRow + 2, startCol) + .SetValue("Компания"); + + sheet.Range(startRow + 2, startCol + 1, startRow + 3, startCol + 1) + .Merge() + .SetValue(user.Company?.Caption); + + sheet.Range(startRow + 4, startCol, startRow + 4, startCol + 1) + .Merge() + .SetValue($"{user.Surname} {user.Name} {user.Patronymic}"); + + sheet.Range(startRow + 5, startCol, startRow + 5, startCol + 1) + .Merge() + .SetValue(FormatDate(mark.DateCreated)); + + sheet.Range(startRow, startCol, startRow + 5, startCol + 1) + .Style.Border.SetOutsideBorder(XLBorderStyleValues.Thin) + .Alignment.SetVertical(XLAlignmentVerticalValues.Top) + .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Left); + } + + private static string FormatDate(DateTimeOffset dateTime) + => $"{dateTime.Day:00}.{dateTime.Month:00}.{dateTime.Year:00}"; } diff --git a/AsbCloudInfrastructure/Services/Email/BaseFactory.cs b/AsbCloudInfrastructure/Services/Email/BaseFactory.cs index 50570467..a138270c 100644 --- a/AsbCloudInfrastructure/Services/Email/BaseFactory.cs +++ b/AsbCloudInfrastructure/Services/Email/BaseFactory.cs @@ -5,69 +5,67 @@ using System; using System.Configuration; using System.IO; -namespace AsbCloudInfrastructure.Services.Email +namespace AsbCloudInfrastructure.Services.Email; + + +public class BaseFactory { + protected readonly string platformName; + protected readonly string platformUrl; + protected readonly string companyName; + protected readonly string supportMail; - public class BaseFactory + public BaseFactory(IConfiguration configuration) { - protected readonly string platformName; - protected readonly string platformUrl; - protected readonly string companyName; - protected readonly string supportMail; + platformName = configuration.GetValue("email:platformName") + ?? throw new ConfigurationErrorsException("email:platformName не определен"); - public BaseFactory(IConfiguration configuration) - { - platformName = configuration.GetValue("email:platformName") - ?? throw new ConfigurationErrorsException("email:platformName не определен"); + platformUrl = configuration.GetValue("email:platformUrl") + ?? throw new ConfigurationErrorsException("email:platformUrl не определен"); - platformUrl = configuration.GetValue("email:platformUrl") - ?? throw new ConfigurationErrorsException("email:platformUrl не определен"); + companyName = configuration.GetValue("email:companyName") + ?? throw new ConfigurationErrorsException("email:companyName не определен"); - companyName = configuration.GetValue("email:companyName") - ?? throw new ConfigurationErrorsException("email:companyName не определен"); - - supportMail = configuration.GetValue("email:supportMail") - ?? throw new ConfigurationErrorsException("email:supportMail не определен"); - } - - public static string GetOrEmptyImageBase64(string resourceFileName) - { - if (string.IsNullOrEmpty(resourceFileName)) - throw new ArgumentInvalidException(nameof(resourceFileName), "ResourceFileName doesn`t exist"); - - var baseDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) - ?? string.Empty; - var resourcesDir = "Res"; - - var logoFilePath = Path.Combine(baseDir, resourcesDir, resourceFileName); - - if (!File.Exists(logoFilePath)) - { - System.Diagnostics.Trace.TraceWarning($"GetOrEmptyImageBase64(). File {logoFilePath} not found."); - return string.Empty; - } - - var imageBytes = File.ReadAllBytes(logoFilePath); - var format = Path.GetExtension(resourceFileName).Trim('.'); - return "data:image/" + format + ";base64," + Convert.ToBase64String(imageBytes); - } - - public static string MakeHref(string url, string text) - => $"{text}"; - - public string MakeSignatue() - { - var logo = GetOrEmptyImageBase64("logo_32.png"); - var sign = $"

---

" + - $"{companyName}
" + - $"Это письмо сформировано автоматически.
" + - $"Для получения помощи по работе на портале {platformName}" + - $"обращайтесь по адресу {supportMail}"; - return sign; - } - - public virtual string MakeSubject(WellDto well, string action) - => $"{well.Deposit}, {well.Cluster}, {well.Caption}. {action}"; + supportMail = configuration.GetValue("email:supportMail") + ?? throw new ConfigurationErrorsException("email:supportMail не определен"); } + public static string GetOrEmptyImageBase64(string resourceFileName) + { + if (string.IsNullOrEmpty(resourceFileName)) + throw new ArgumentInvalidException(nameof(resourceFileName), "ResourceFileName doesn`t exist"); + + var baseDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + ?? string.Empty; + var resourcesDir = "Res"; + + var logoFilePath = Path.Combine(baseDir, resourcesDir, resourceFileName); + + if (!File.Exists(logoFilePath)) + { + System.Diagnostics.Trace.TraceWarning($"GetOrEmptyImageBase64(). File {logoFilePath} not found."); + return string.Empty; + } + + var imageBytes = File.ReadAllBytes(logoFilePath); + var format = Path.GetExtension(resourceFileName).Trim('.'); + return "data:image/" + format + ";base64," + Convert.ToBase64String(imageBytes); + } + + public static string MakeHref(string url, string text) + => $"{text}"; + + public string MakeSignatue() + { + var logo = GetOrEmptyImageBase64("logo_32.png"); + var sign = $"

---

" + + $"{companyName}
" + + $"Это письмо сформировано автоматически.
" + + $"Для получения помощи по работе на портале {platformName}" + + $"обращайтесь по адресу {supportMail}"; + return sign; + } + + public virtual string MakeSubject(WellDto well, string action) + => $"{well.Deposit}, {well.Cluster}, {well.Caption}. {action}"; } diff --git a/AsbCloudInfrastructure/Services/Email/DrillingMailBodyFactory.cs b/AsbCloudInfrastructure/Services/Email/DrillingMailBodyFactory.cs index 1501811a..45005057 100644 --- a/AsbCloudInfrastructure/Services/Email/DrillingMailBodyFactory.cs +++ b/AsbCloudInfrastructure/Services/Email/DrillingMailBodyFactory.cs @@ -1,82 +1,80 @@ using AsbCloudApp.Data; using Microsoft.Extensions.Configuration; -namespace AsbCloudInfrastructure.Services.Email +namespace AsbCloudInfrastructure.Services.Email; + + +class DrillingMailBodyFactory : BaseFactory { - class DrillingMailBodyFactory : BaseFactory + public DrillingMailBodyFactory(IConfiguration configuration) + : base(configuration) { - - public DrillingMailBodyFactory(IConfiguration configuration) - : base(configuration) - { - } - - public override string MakeSubject(WellDto well, string action) - { - var subj = $"{well.Deposit}, {well.Cluster}, {well.Caption}. Программа бурения. {action}"; - return subj; - } - - public string MakeMailBodyForNewPublisher(WellDto well, string publisherName, string documentCategory) - { - var drillingProgramHref = MakeDrillingProgramHref(well); - - var body = $"

Здравствуйте, {publisherName}.

" + - $"На портале {platformName} началось создание программы бурения скважины {drillingProgramHref}," + - $" куст {well.Cluster}, месторождение {well.Deposit}." + - $"

От вас ожидается загрузка на портал документа «{documentCategory}» в формате excel (*.xlsx)." + - MakeSignatue() + - $""; - return body; - } - - public string MakeMailBodyForApproverNewFile(WellDto well, string approverName, int idFile, string fileName) - { - var drillingProgramHref = MakeDrillingProgramHref(well); - - var body = $"

Здравствуйте, {approverName}.

" + - $"На портал {platformName} загружен документ {fileName}" + - $" для согласования при создании программы бурения скважины {drillingProgramHref}, куст ({well.Cluster})" + - $", месторождение ({well.Deposit}).
" + - MakeSignatue() + - $""; - return body; - } - - public string MakeMailBodyForPublisherOnReject(WellDto well, string publisherName, int idFile, string fileName, FileMarkDto fileMark) - { - var drillingProgramHref = MakeDrillingProgramHref(well); - - var body = $"

Здравствуйте, {publisherName}.

" + - $"На портале {platformName} отклонен загруженный вами документ {fileName} " + - $" по программе бурения скважины {drillingProgramHref}," + - $" куст {well.Cluster}, месторождение {well.Deposit}." + - $" Комментарий согласующего ({fileMark.User?.Name} {fileMark.User?.Surname}):
{fileMark.Comment}" + - MakeSignatue() + - $""; - return body; - } - - public string MakeMailBodyForPublisherOnFullAccept(WellDto well, string publisherName, int idFile, string fileName) - { - var drillingProgramHref = MakeDrillingProgramHref(well); - - var body = $"

Здравствуйте, {publisherName}.

" + - $"На портале {platformName} полностью согласован документ {fileName} " + - $" по программе бурения скважины {drillingProgramHref}," + - $" куст {well.Cluster}, месторождение {well.Deposit}." + - MakeSignatue() + - $""; - return body; - } - - private string MakeDrillingProgramHref(WellDto well) - { - var drillingProgramUrl = $"{platformUrl}/well/{well.Id}/drillingProgram"; - var drillingProgramHref = MakeHref(drillingProgramUrl, well.Caption); - return drillingProgramHref; - } } + public override string MakeSubject(WellDto well, string action) + { + var subj = $"{well.Deposit}, {well.Cluster}, {well.Caption}. Программа бурения. {action}"; + return subj; + } + + public string MakeMailBodyForNewPublisher(WellDto well, string publisherName, string documentCategory) + { + var drillingProgramHref = MakeDrillingProgramHref(well); + + var body = $"

Здравствуйте, {publisherName}.

" + + $"На портале {platformName} началось создание программы бурения скважины {drillingProgramHref}," + + $" куст {well.Cluster}, месторождение {well.Deposit}." + + $"

От вас ожидается загрузка на портал документа «{documentCategory}» в формате excel (*.xlsx)." + + MakeSignatue() + + $""; + return body; + } + + public string MakeMailBodyForApproverNewFile(WellDto well, string approverName, int idFile, string fileName) + { + var drillingProgramHref = MakeDrillingProgramHref(well); + + var body = $"

Здравствуйте, {approverName}.

" + + $"На портал {platformName} загружен документ {fileName}" + + $" для согласования при создании программы бурения скважины {drillingProgramHref}, куст ({well.Cluster})" + + $", месторождение ({well.Deposit}).
" + + MakeSignatue() + + $""; + return body; + } + + public string MakeMailBodyForPublisherOnReject(WellDto well, string publisherName, int idFile, string fileName, FileMarkDto fileMark) + { + var drillingProgramHref = MakeDrillingProgramHref(well); + + var body = $"

Здравствуйте, {publisherName}.

" + + $"На портале {platformName} отклонен загруженный вами документ {fileName} " + + $" по программе бурения скважины {drillingProgramHref}," + + $" куст {well.Cluster}, месторождение {well.Deposit}." + + $" Комментарий согласующего ({fileMark.User?.Name} {fileMark.User?.Surname}):
{fileMark.Comment}" + + MakeSignatue() + + $""; + return body; + } + + public string MakeMailBodyForPublisherOnFullAccept(WellDto well, string publisherName, int idFile, string fileName) + { + var drillingProgramHref = MakeDrillingProgramHref(well); + + var body = $"

Здравствуйте, {publisherName}.

" + + $"На портале {platformName} полностью согласован документ {fileName} " + + $" по программе бурения скважины {drillingProgramHref}," + + $" куст {well.Cluster}, месторождение {well.Deposit}." + + MakeSignatue() + + $""; + return body; + } + + private string MakeDrillingProgramHref(WellDto well) + { + var drillingProgramUrl = $"{platformUrl}/well/{well.Id}/drillingProgram"; + var drillingProgramHref = MakeHref(drillingProgramUrl, well.Caption); + return drillingProgramHref; + } } diff --git a/AsbCloudInfrastructure/Services/Email/EmailNotificationTransportService.cs b/AsbCloudInfrastructure/Services/Email/EmailNotificationTransportService.cs index a52cd0b1..72d3b6a5 100644 --- a/AsbCloudInfrastructure/Services/Email/EmailNotificationTransportService.cs +++ b/AsbCloudInfrastructure/Services/Email/EmailNotificationTransportService.cs @@ -11,86 +11,85 @@ using System.Net.Mail; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services.Email +namespace AsbCloudInfrastructure.Services.Email; + + +public class EmailNotificationTransportService : INotificationTransportService { + private readonly IUserRepository userRepository; + private readonly string sender; + private readonly string smtpPassword; + private readonly string smtpServer; - public class EmailNotificationTransportService : INotificationTransportService + public int IdTransportType => 1; + public bool IsConfigured { get; } + + public EmailNotificationTransportService( + IConfiguration configuration, + IUserRepository userRepository) { - private readonly IUserRepository userRepository; - private readonly string sender; - private readonly string smtpPassword; - private readonly string smtpServer; + this.userRepository = userRepository; - public int IdTransportType => 1; - public bool IsConfigured { get; } + this.sender = configuration.GetValue("email:sender") + ?? throw new ConfigurationErrorsException("email:sender не определен"); - public EmailNotificationTransportService( - IConfiguration configuration, - IUserRepository userRepository) + this.smtpPassword = configuration.GetValue("email:password") + ?? throw new ConfigurationErrorsException("email:password не определен"); + + this.smtpServer = configuration.GetValue("email:smtpServer") + ?? throw new ConfigurationErrorsException("email:smtpServer не определен"); + + var configError = string.IsNullOrEmpty(this.sender) || + string.IsNullOrEmpty(this.smtpPassword) || + string.IsNullOrEmpty(this.smtpServer); + + this.IsConfigured = !configError; + } + + public async Task SendAsync(NotificationDto notification, CancellationToken token) + { + if (!IsConfigured) { - this.userRepository = userRepository; - - this.sender = configuration.GetValue("email:sender") - ?? throw new ConfigurationErrorsException("email:sender не определен"); - - this.smtpPassword = configuration.GetValue("email:password") - ?? throw new ConfigurationErrorsException("email:password не определен"); - - this.smtpServer = configuration.GetValue("email:smtpServer") - ?? throw new ConfigurationErrorsException("email:smtpServer не определен"); - - var configError = string.IsNullOrEmpty(this.sender) || - string.IsNullOrEmpty(this.smtpPassword) || - string.IsNullOrEmpty(this.smtpServer); - - this.IsConfigured = !configError; + Trace.TraceWarning("smtp is not configured"); + return; } - public async Task SendAsync(NotificationDto notification, CancellationToken token) + var user = await userRepository.GetOrDefaultAsync(notification.IdUser, token) + ?? throw new ArgumentInvalidException(nameof(notification.IdUser), "Пользователь не найден"); + + if (!MailAddress.TryCreate(user.Email, out var mailAddress)) { - if (!IsConfigured) - { - Trace.TraceWarning("smtp is not configured"); - return; - } - - var user = await userRepository.GetOrDefaultAsync(notification.IdUser, token) - ?? throw new ArgumentInvalidException(nameof(notification.IdUser), "Пользователь не найден"); - - if (!MailAddress.TryCreate(user.Email, out var mailAddress)) - { - Trace.TraceWarning($"Mail {user.Email} is not correct."); - throw new ArgumentInvalidException(nameof(user.Email), $"Mail {user.Email} is not null."); - } - - var from = new MailAddress(sender); - var message = new MailMessage - { - From = from - }; - - message.To.Add(mailAddress.Address); - message.BodyEncoding = System.Text.Encoding.UTF8; - message.Body = notification.Message; - message.Subject = notification.Title; - message.IsBodyHtml = true; - - using var client = new SmtpClient(smtpServer); - client.EnableSsl = true; - client.UseDefaultCredentials = false; - client.Credentials = new System.Net.NetworkCredential(sender, smtpPassword); - - await client.SendMailAsync(message, token); - - Trace.TraceInformation($"Send email to {user.Email} subj:{notification.Title} html body count {notification.Message.Length}"); + Trace.TraceWarning($"Mail {user.Email} is not correct."); + throw new ArgumentInvalidException(nameof(user.Email), $"Mail {user.Email} is not null."); } - public Task SendRangeAsync(IEnumerable notifications, CancellationToken cancellationToken) + var from = new MailAddress(sender); + var message = new MailMessage { - var tasks = notifications - .Select(notification => SendAsync(notification, cancellationToken)); + From = from + }; - return Task.WhenAll(tasks); - } + message.To.Add(mailAddress.Address); + message.BodyEncoding = System.Text.Encoding.UTF8; + message.Body = notification.Message; + message.Subject = notification.Title; + message.IsBodyHtml = true; + + using var client = new SmtpClient(smtpServer); + client.EnableSsl = true; + client.UseDefaultCredentials = false; + client.Credentials = new System.Net.NetworkCredential(sender, smtpPassword); + + await client.SendMailAsync(message, token); + + Trace.TraceInformation($"Send email to {user.Email} subj:{notification.Title} html body count {notification.Message.Length}"); + } + + public Task SendRangeAsync(IEnumerable notifications, CancellationToken cancellationToken) + { + var tasks = notifications + .Select(notification => SendAsync(notification, cancellationToken)); + + return Task.WhenAll(tasks); } } diff --git a/AsbCloudInfrastructure/Services/Email/WellFinalDocumentMailBodyFactory .cs b/AsbCloudInfrastructure/Services/Email/WellFinalDocumentMailBodyFactory .cs index f9a49329..c96312c8 100644 --- a/AsbCloudInfrastructure/Services/Email/WellFinalDocumentMailBodyFactory .cs +++ b/AsbCloudInfrastructure/Services/Email/WellFinalDocumentMailBodyFactory .cs @@ -4,30 +4,28 @@ using Microsoft.Extensions.Configuration; using System; using System.IO; -namespace AsbCloudInfrastructure +namespace AsbCloudInfrastructure; + + +class WellFinalDocumentMailBodyFactory : BaseFactory { - class WellFinalDocumentMailBodyFactory : BaseFactory + public WellFinalDocumentMailBodyFactory(IConfiguration configuration) + : base(configuration) { + + } - public WellFinalDocumentMailBodyFactory(IConfiguration configuration) - : base(configuration) - { - - } - - public override string MakeSubject(WellDto well, string action) - => $"{well.Deposit}, {well.Cluster}, {well.Caption}. Дело скважины. {action}"; - - public string MakeMailBodyForWellFinalDocument(WellDto well, string publisherName, string message) - { - var body = $"

Здравствуйте, {publisherName}.

" + - $"На портале {platformName} {message}," + - $" куст {well.Cluster}, месторождение {well.Deposit}." + - MakeSignatue() + - $""; - return body; - } - } + public override string MakeSubject(WellDto well, string action) + => $"{well.Deposit}, {well.Cluster}, {well.Caption}. Дело скважины. {action}"; + public string MakeMailBodyForWellFinalDocument(WellDto well, string publisherName, string message) + { + var body = $"

Здравствуйте, {publisherName}.

" + + $"На портале {platformName} {message}," + + $" куст {well.Cluster}, месторождение {well.Deposit}." + + MakeSignatue() + + $""; + return body; + } } diff --git a/AsbCloudInfrastructure/Services/FileCategoryService.cs b/AsbCloudInfrastructure/Services/FileCategoryService.cs index 02d8be83..ef747a1d 100644 --- a/AsbCloudInfrastructure/Services/FileCategoryService.cs +++ b/AsbCloudInfrastructure/Services/FileCategoryService.cs @@ -8,26 +8,24 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services +namespace AsbCloudInfrastructure.Services; + + +public class FileCategoryService : CrudCacheRepositoryBase, IFileCategoryService { + public FileCategoryService(IAsbCloudDbContext context, IMemoryCache memoryCache) + : base(context, memoryCache) { } - public class FileCategoryService : CrudCacheRepositoryBase, IFileCategoryService + //TODO: Перенести в сервис "дело скважины" + public async Task> GetWellCaseCategoriesAsync(CancellationToken token) { - public FileCategoryService(IAsbCloudDbContext context, IMemoryCache memoryCache) - : base(context, memoryCache) { } + var cache = await GetCacheAsync(token) + .ConfigureAwait(false); + var dtos = cache + .Where(f => f.Id >= 10000) + .Where(f => f.Id <= 20000) + .Select(Convert); - //TODO: Перенести в сервис "дело скважины" - public async Task> GetWellCaseCategoriesAsync(CancellationToken token) - { - var cache = await GetCacheAsync(token) - .ConfigureAwait(false); - var dtos = cache - .Where(f => f.Id >= 10000) - .Where(f => f.Id <= 20000) - .Select(Convert); - - return dtos; - } + return dtos; } - } diff --git a/AsbCloudInfrastructure/Services/LimitingParameterService.cs b/AsbCloudInfrastructure/Services/LimitingParameterService.cs index da86efd9..5a0a61a3 100644 --- a/AsbCloudInfrastructure/Services/LimitingParameterService.cs +++ b/AsbCloudInfrastructure/Services/LimitingParameterService.cs @@ -8,112 +8,110 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services +namespace AsbCloudInfrastructure.Services; + + +public class LimitingParameterService : ILimitingParameterService { - - public class LimitingParameterService : ILimitingParameterService + private readonly ILimitingParameterRepository limitingParameterRepository; + private readonly IWellService wellService; + private readonly Dictionary feedRegulatorData = new () { - private readonly ILimitingParameterRepository limitingParameterRepository; - private readonly IWellService wellService; - private readonly Dictionary feedRegulatorData = new () - { - { LimitingParameterDto.NoLimit, "Нет ограничения" }, - { LimitingParameterDto.RopPlan, "Скорость блока" }, - { LimitingParameterDto.Pressure, "Давление" }, - { LimitingParameterDto.AxialLoad, "Осевая нагрузка" }, - { LimitingParameterDto.RotorTorque, "Момент на роторе" } - }; + { LimitingParameterDto.NoLimit, "Нет ограничения" }, + { LimitingParameterDto.RopPlan, "Скорость блока" }, + { LimitingParameterDto.Pressure, "Давление" }, + { LimitingParameterDto.AxialLoad, "Осевая нагрузка" }, + { LimitingParameterDto.RotorTorque, "Момент на роторе" } + }; - public LimitingParameterService(ILimitingParameterRepository limitingParameterRepository, - IWellService wellService) - { - this.limitingParameterRepository = limitingParameterRepository; - this.wellService = wellService; - } - - public async Task> GetStatAsync(LimitingParameterRequest request, CancellationToken token) - { - var well = await wellService.GetOrDefaultAsync(request.IdWell, token); - if (well?.IdTelemetry is null || well.Timezone is null) - return Enumerable.Empty(); - - var data = (await limitingParameterRepository.GetLimitingParametersAsync(request, well, token)) - .GroupBy(x => x.IdFeedRegulator); - - List result = new List(data.Count()); - foreach (var item in data) - { - var trimData = TrimLimitingParameters(item, request).ToArray(); - - var allItemDepths = trimData.Sum(x => x.DepthEnd - x.DepthStart); - var allItemDates = trimData.Sum(x => (x.DateEnd - x.DateStart).TotalMinutes); - - result.Add(new LimitingParameterDto - { - IdWell = well.Id, - IdFeedRegulator = item.Key, - Depth = allItemDepths, - TotalMinutes = (float)allItemDates, - NumberInclusions = item.Count(), - NameFeedRegulator = feedRegulatorData.GetValueOrDefault(item.Key) ?? $"Id: {item.Key}" - }); - } - - return result; - } - - public Dictionary GetLimitingParameteraNames() //TODO: Перенести получение ограничений в репозиторий - { - return feedRegulatorData; - } - - private IEnumerable TrimLimitingParameters(IEnumerable data, LimitingParameterRequest request) - { - var result = data.Select((x) => - { - if (request.GtDate.HasValue && x.DateStart < request.GtDate.Value) - { - x.DepthStart = GetDepth(request.GtDate.Value, x); - x.DateStart = request.GtDate.Value; - } - if (request.LtDate.HasValue && x.DateEnd > request.LtDate.Value) - { - x.DepthEnd = GetDepth(request.LtDate.Value, x); - x.DateEnd = request.LtDate.Value; - } - - if (request.GtDepth.HasValue && x.DepthStart < request.GtDepth.Value) - { - x.DateStart = GetDate(request.GtDepth.Value, x); - x.DepthStart = (float)request.GtDepth.Value; - } - if (request.LtDepth.HasValue && x.DepthEnd > request.LtDepth.Value) - { - x.DateEnd = GetDate(request.LtDepth.Value, x); - x.DepthEnd = (float)request.LtDepth.Value; - } - return x; - }); - return result; - } - - private float GetDepth(DateTimeOffset date, LimitingParameterDataDto dto) - { - var a = (date - dto.DateStart).TotalSeconds; - var b = (dto.DateEnd - dto.DateStart).TotalSeconds; - var c = dto.DepthEnd - dto.DepthStart; - var result = dto.DepthStart + (a / b) * c; - return (float)result; - } - - private DateTimeOffset GetDate(double depth, LimitingParameterDataDto dto) - { - var a = depth - dto.DepthStart; - var b = dto.DepthEnd - dto.DepthStart; - var c = (dto.DateEnd - dto.DateStart); - var result = dto.DateStart + (a / b) * c; - return result; - } + public LimitingParameterService(ILimitingParameterRepository limitingParameterRepository, + IWellService wellService) + { + this.limitingParameterRepository = limitingParameterRepository; + this.wellService = wellService; } + public async Task> GetStatAsync(LimitingParameterRequest request, CancellationToken token) + { + var well = await wellService.GetOrDefaultAsync(request.IdWell, token); + if (well?.IdTelemetry is null || well.Timezone is null) + return Enumerable.Empty(); + + var data = (await limitingParameterRepository.GetLimitingParametersAsync(request, well, token)) + .GroupBy(x => x.IdFeedRegulator); + + List result = new List(data.Count()); + foreach (var item in data) + { + var trimData = TrimLimitingParameters(item, request).ToArray(); + + var allItemDepths = trimData.Sum(x => x.DepthEnd - x.DepthStart); + var allItemDates = trimData.Sum(x => (x.DateEnd - x.DateStart).TotalMinutes); + + result.Add(new LimitingParameterDto + { + IdWell = well.Id, + IdFeedRegulator = item.Key, + Depth = allItemDepths, + TotalMinutes = (float)allItemDates, + NumberInclusions = item.Count(), + NameFeedRegulator = feedRegulatorData.GetValueOrDefault(item.Key) ?? $"Id: {item.Key}" + }); + } + + return result; + } + + public Dictionary GetLimitingParameteraNames() //TODO: Перенести получение ограничений в репозиторий + { + return feedRegulatorData; + } + + private IEnumerable TrimLimitingParameters(IEnumerable data, LimitingParameterRequest request) + { + var result = data.Select((x) => + { + if (request.GtDate.HasValue && x.DateStart < request.GtDate.Value) + { + x.DepthStart = GetDepth(request.GtDate.Value, x); + x.DateStart = request.GtDate.Value; + } + if (request.LtDate.HasValue && x.DateEnd > request.LtDate.Value) + { + x.DepthEnd = GetDepth(request.LtDate.Value, x); + x.DateEnd = request.LtDate.Value; + } + + if (request.GtDepth.HasValue && x.DepthStart < request.GtDepth.Value) + { + x.DateStart = GetDate(request.GtDepth.Value, x); + x.DepthStart = (float)request.GtDepth.Value; + } + if (request.LtDepth.HasValue && x.DepthEnd > request.LtDepth.Value) + { + x.DateEnd = GetDate(request.LtDepth.Value, x); + x.DepthEnd = (float)request.LtDepth.Value; + } + return x; + }); + return result; + } + + private float GetDepth(DateTimeOffset date, LimitingParameterDataDto dto) + { + var a = (date - dto.DateStart).TotalSeconds; + var b = (dto.DateEnd - dto.DateStart).TotalSeconds; + var c = dto.DepthEnd - dto.DepthStart; + var result = dto.DepthStart + (a / b) * c; + return (float)result; + } + + private DateTimeOffset GetDate(double depth, LimitingParameterDataDto dto) + { + var a = depth - dto.DepthStart; + var b = dto.DepthEnd - dto.DepthStart; + var c = (dto.DateEnd - dto.DateStart); + var result = dto.DateStart + (a / b) * c; + return result; + } } diff --git a/AsbCloudInfrastructure/Services/MeasureService.cs b/AsbCloudInfrastructure/Services/MeasureService.cs index 5413390d..063b51ea 100644 --- a/AsbCloudInfrastructure/Services/MeasureService.cs +++ b/AsbCloudInfrastructure/Services/MeasureService.cs @@ -11,145 +11,143 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services +namespace AsbCloudInfrastructure.Services; + + +public class MeasureService : IMeasureService { + private readonly IAsbCloudDbContext db; + private readonly IMemoryCache memoryCache; + private readonly IWellService wellService; + private static readonly TimeSpan CacheOlescence = TimeSpan.FromMinutes(20); - public class MeasureService : IMeasureService + public MeasureService(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService) { - private readonly IAsbCloudDbContext db; - private readonly IMemoryCache memoryCache; - private readonly IWellService wellService; - private static readonly TimeSpan CacheOlescence = TimeSpan.FromMinutes(20); - - public MeasureService(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService) - { - this.db = db; - this.memoryCache = memoryCache; - this.wellService = wellService; - } - - public async Task> GetCategoriesAsync(CancellationToken token) - { - var key = typeof(MeasureCategory).FullName; - var cache = await memoryCache.GetOrCreateAsync(key, async (cacheEntry) => { - cacheEntry.AbsoluteExpirationRelativeToNow = CacheOlescence; - cacheEntry.SlidingExpiration = CacheOlescence; - var entities = await db.Set() - .ToDictionaryAsync(e => e.Id, e => e.Name, token); - return entities; - }); - return cache!; - } - - public async Task GetLastOrDefaultAsync(int idWell, int idCategory, CancellationToken token) - { - var query = db.Measures - .Include(m => m.Category) - .Where(m => m.IdWell == idWell && m.IdCategory == idCategory && !m.IsDeleted) - .OrderByDescending(m => m.Timestamp) - .Take(1); - - var entity = await query - .AsNoTracking() - .FirstOrDefaultAsync(token) - .ConfigureAwait(false); - - var timezone = wellService.GetTimezone(idWell); - - if (entity is null) - return null; - - return Convert(entity, timezone.Hours); - } - - public async Task> GetHisoryAsync(int idWell, int? idCategory = null, CancellationToken token = default) - { - var query = db.Measures.Include(m => m.Category) - .Where(m => m.IdWell == idWell && !m.IsDeleted); - - if (idCategory is not null) - query = query.Where(m => m.IdCategory == idCategory); - - var entities = await query - .OrderBy(m => m.Timestamp) - .AsNoTracking() - .ToListAsync(token) - .ConfigureAwait(false); - - var timezone = wellService.GetTimezone(idWell); - var dtos = entities.Select(e => Convert(e, timezone.Hours)); - return dtos; - } - - public Task InsertAsync(int idWell, MeasureDto dto, CancellationToken token) - { - if (dto.IdCategory < 1) - throw new ArgumentInvalidException(nameof(dto), "wrong idCategory"); - if (!dto.Data.Any()) - throw new ArgumentInvalidException(nameof(dto), "data.data is not optional"); - var entity = Convert(dto); - entity.IdWell = idWell; - db.Measures.Add(entity); - return db.SaveChangesAsync(token); - } - - public async Task UpdateAsync(int idWell, MeasureDto dto, CancellationToken token) - { - if (dto.Id < 1) - throw new ArgumentInvalidException(nameof(dto), "wrong id"); - if (dto.IdCategory < 1) - throw new ArgumentInvalidException(nameof(dto), "wrong idCategory"); - if (!dto.Data.Any()) - throw new ArgumentInvalidException(nameof(dto), "data.data is not optional"); - - var entity = await db.Measures - .Where(m => m.Id == dto.Id && !m.IsDeleted) - .FirstOrDefaultAsync(token) - ?? throw new ArgumentInvalidException(nameof(dto), "id doesn't exist"); - - var timezone = wellService.GetTimezone(idWell); - entity.IdWell = idWell; - entity.Timestamp = dto.Timestamp.ToOffset(TimeSpan.FromHours(timezone.Hours)); - entity.Data = dto.Data.Adapt(); - - return await db.SaveChangesAsync(token).ConfigureAwait(false); - } - - public async Task MarkAsDeleteAsync(int idWell, int idData, CancellationToken token) - { - if (idData < 1) - throw new ArgumentInvalidException(nameof(idData), "wrong id"); - - var entity = await db.Measures.Where(m => m.IdWell == idWell && m.Id == idData) - .FirstOrDefaultAsync(token) - ?? throw new ArgumentInvalidException(nameof(idWell), $"Measure doesn't exist"); - - entity.IsDeleted = true; - - return await db.SaveChangesAsync(token).ConfigureAwait(false); - } - - public Task DeleteAsync(int idWell, int idData, CancellationToken token) - { - if (idData < 1) - throw new ArgumentInvalidException(nameof(idData), "wrong id"); - db.Measures.RemoveRange(db.Measures.Where(m => m.IdWell == idWell && m.Id == idData)); - return db.SaveChangesAsync(token); - } - - private MeasureDto Convert(Measure entity, double hours) - { - var dto = entity.Adapt(); - dto.CategoryName = entity.Category?.Name ?? String.Empty; - dto.Timestamp = entity.Timestamp.ToOffset(TimeSpan.FromHours(hours)); - return dto; - } - private Measure Convert(MeasureDto dto) - { - var entity = dto.Adapt(); - entity.Timestamp = dto.Timestamp.ToUniversalTime(); - return entity; - } + this.db = db; + this.memoryCache = memoryCache; + this.wellService = wellService; } + public async Task> GetCategoriesAsync(CancellationToken token) + { + var key = typeof(MeasureCategory).FullName; + var cache = await memoryCache.GetOrCreateAsync(key, async (cacheEntry) => { + cacheEntry.AbsoluteExpirationRelativeToNow = CacheOlescence; + cacheEntry.SlidingExpiration = CacheOlescence; + var entities = await db.Set() + .ToDictionaryAsync(e => e.Id, e => e.Name, token); + return entities; + }); + return cache!; + } + + public async Task GetLastOrDefaultAsync(int idWell, int idCategory, CancellationToken token) + { + var query = db.Measures + .Include(m => m.Category) + .Where(m => m.IdWell == idWell && m.IdCategory == idCategory && !m.IsDeleted) + .OrderByDescending(m => m.Timestamp) + .Take(1); + + var entity = await query + .AsNoTracking() + .FirstOrDefaultAsync(token) + .ConfigureAwait(false); + + var timezone = wellService.GetTimezone(idWell); + + if (entity is null) + return null; + + return Convert(entity, timezone.Hours); + } + + public async Task> GetHisoryAsync(int idWell, int? idCategory = null, CancellationToken token = default) + { + var query = db.Measures.Include(m => m.Category) + .Where(m => m.IdWell == idWell && !m.IsDeleted); + + if (idCategory is not null) + query = query.Where(m => m.IdCategory == idCategory); + + var entities = await query + .OrderBy(m => m.Timestamp) + .AsNoTracking() + .ToListAsync(token) + .ConfigureAwait(false); + + var timezone = wellService.GetTimezone(idWell); + var dtos = entities.Select(e => Convert(e, timezone.Hours)); + return dtos; + } + + public Task InsertAsync(int idWell, MeasureDto dto, CancellationToken token) + { + if (dto.IdCategory < 1) + throw new ArgumentInvalidException(nameof(dto), "wrong idCategory"); + if (!dto.Data.Any()) + throw new ArgumentInvalidException(nameof(dto), "data.data is not optional"); + var entity = Convert(dto); + entity.IdWell = idWell; + db.Measures.Add(entity); + return db.SaveChangesAsync(token); + } + + public async Task UpdateAsync(int idWell, MeasureDto dto, CancellationToken token) + { + if (dto.Id < 1) + throw new ArgumentInvalidException(nameof(dto), "wrong id"); + if (dto.IdCategory < 1) + throw new ArgumentInvalidException(nameof(dto), "wrong idCategory"); + if (!dto.Data.Any()) + throw new ArgumentInvalidException(nameof(dto), "data.data is not optional"); + + var entity = await db.Measures + .Where(m => m.Id == dto.Id && !m.IsDeleted) + .FirstOrDefaultAsync(token) + ?? throw new ArgumentInvalidException(nameof(dto), "id doesn't exist"); + + var timezone = wellService.GetTimezone(idWell); + entity.IdWell = idWell; + entity.Timestamp = dto.Timestamp.ToOffset(TimeSpan.FromHours(timezone.Hours)); + entity.Data = dto.Data.Adapt(); + + return await db.SaveChangesAsync(token).ConfigureAwait(false); + } + + public async Task MarkAsDeleteAsync(int idWell, int idData, CancellationToken token) + { + if (idData < 1) + throw new ArgumentInvalidException(nameof(idData), "wrong id"); + + var entity = await db.Measures.Where(m => m.IdWell == idWell && m.Id == idData) + .FirstOrDefaultAsync(token) + ?? throw new ArgumentInvalidException(nameof(idWell), $"Measure doesn't exist"); + + entity.IsDeleted = true; + + return await db.SaveChangesAsync(token).ConfigureAwait(false); + } + + public Task DeleteAsync(int idWell, int idData, CancellationToken token) + { + if (idData < 1) + throw new ArgumentInvalidException(nameof(idData), "wrong id"); + db.Measures.RemoveRange(db.Measures.Where(m => m.IdWell == idWell && m.Id == idData)); + return db.SaveChangesAsync(token); + } + + private MeasureDto Convert(Measure entity, double hours) + { + var dto = entity.Adapt(); + dto.CategoryName = entity.Category?.Name ?? String.Empty; + dto.Timestamp = entity.Timestamp.ToOffset(TimeSpan.FromHours(hours)); + return dto; + } + private Measure Convert(MeasureDto dto) + { + var entity = dto.Adapt(); + entity.Timestamp = dto.Timestamp.ToUniversalTime(); + return entity; + } } diff --git a/AsbCloudInfrastructure/Services/ReduceSamplingService.cs b/AsbCloudInfrastructure/Services/ReduceSamplingService.cs index 6db845a5..60de2d26 100644 --- a/AsbCloudInfrastructure/Services/ReduceSamplingService.cs +++ b/AsbCloudInfrastructure/Services/ReduceSamplingService.cs @@ -12,326 +12,324 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services -{ +namespace AsbCloudInfrastructure.Services; - class JobHandle + +class JobHandle +{ + public int Id => Job.Id; + public JobDto Job { get; set; } = null!; + public DateTime DateCreate { get; set; } = DateTime.Now; + public OnJobProgressDelagate? OnProgress { get; set; } +} + +public class ReduceSamplingService : IReduceSamplingService +{ + private const string jobResultKeyDeleted = "deleted"; + private const string jobResultKeyTotal = "total"; + private static ReduceSamplingService? instance; + private readonly string connectionString; + private const int ratio = 5; + private readonly List jobHandlers = new(5); + private bool isHandling; + private CancellationTokenSource? cancellationTokenSource; + private Task? task; + + private ReduceSamplingService(IConfiguration configuration) { - public int Id => Job.Id; - public JobDto Job { get; set; } = null!; - public DateTime DateCreate { get; set; } = DateTime.Now; - public OnJobProgressDelagate? OnProgress { get; set; } + connectionString = configuration.GetConnectionString("DefaultConnection") + ?? throw new ConfigurationErrorsException("DefaultConnection не определен"); } - public class ReduceSamplingService : IReduceSamplingService + ~ReduceSamplingService() { - private const string jobResultKeyDeleted = "deleted"; - private const string jobResultKeyTotal = "total"; - private static ReduceSamplingService? instance; - private readonly string connectionString; - private const int ratio = 5; - private readonly List jobHandlers = new(5); - private bool isHandling; - private CancellationTokenSource? cancellationTokenSource; - private Task? task; + Stop(); + } - private ReduceSamplingService(IConfiguration configuration) - { - connectionString = configuration.GetConnectionString("DefaultConnection") - ?? throw new ConfigurationErrorsException("DefaultConnection не определен"); - } + /// + /// Get singleton Instance + /// + /// + /// + public static ReduceSamplingService GetInstance(IConfiguration configuration) + { + instance ??= new(configuration); + return instance; + } - ~ReduceSamplingService() + /// + public bool TryEnqueueRediceSamplingJob(int idTelemetry, OnJobProgressDelagate? onProgress, out JobDto jobDto) + { + lock (jobHandlers) { - Stop(); - } - - /// - /// Get singleton Instance - /// - /// - /// - public static ReduceSamplingService GetInstance(IConfiguration configuration) - { - instance ??= new(configuration); - return instance; - } - - /// - public bool TryEnqueueRediceSamplingJob(int idTelemetry, OnJobProgressDelagate? onProgress, out JobDto jobDto) - { - lock (jobHandlers) + var oldJob = jobHandlers.FirstOrDefault(j => j.Id == idTelemetry); + if (oldJob is not null) { - var oldJob = jobHandlers.FirstOrDefault(j => j.Id == idTelemetry); - if (oldJob is not null) + jobDto = oldJob.Job; + return false; + } + + jobDto = new JobDto + { + Id = idTelemetry, + State = JobState.Waiting, + Results = new(), + }; + var jobHandler = new JobHandle + { + Job = jobDto, + OnProgress = onProgress, + }; + + jobHandlers.Add(jobHandler); + } + EnsureHandleQueueStarted(); + return true; + } + + /// + public JobDto? GetOrDefaultState(int idTelemetry) + { + JobHandle? jobHandler; + lock (jobHandlers) + { + jobHandler = jobHandlers.FirstOrDefault(j => j.Id == idTelemetry); + } + return jobHandler?.Job; + } + + /// + public IEnumerable GetJobs() => jobHandlers.Select(j=>j.Job); + + private bool TryTakeWaitingJob(out JobHandle? job) + { + lock (jobHandlers) + { + job = jobHandlers.FirstOrDefault(j => j.Job.State == JobState.Waiting); + } + return job is not null; + } + + private void EnsureHandleQueueStarted() + { + if (isHandling) + return; + isHandling = true; + cancellationTokenSource = new CancellationTokenSource(); + var token = cancellationTokenSource.Token; + task = Task.Run(async () => await HandleJobs(token)) + .ContinueWith(_ => isHandling = false); + } + + private async Task HandleJobs(CancellationToken token) + { + while (TryTakeWaitingJob(out JobHandle? jobHandler)) + { + jobHandler!.Job.State = JobState.Working; + try + { + await RediceSamplingSaubAsync(jobHandler, token); + await RediceSamplingSpinAsync(jobHandler, token); + jobHandler.Job.State = JobState.Done; + } + catch (Exception exception) + { + jobHandler.Job.State = JobState.Fail; + jobHandler.Job.Results = null; + jobHandler.Job.Error = exception.Message; + jobHandler.OnProgress?.Invoke(jobHandler.Job); + } + + if (!jobHandlers.Any(j => j.Job.State == JobState.Waiting)) + { + var sw = Stopwatch.StartNew(); + await VacuumAsync(token); + sw.Stop(); + if (sw.ElapsedMilliseconds < 10_000) { - jobDto = oldJob.Job; - return false; - } - - jobDto = new JobDto - { - Id = idTelemetry, - State = JobState.Waiting, - Results = new(), - }; - var jobHandler = new JobHandle - { - Job = jobDto, - OnProgress = onProgress, - }; - - jobHandlers.Add(jobHandler); - } - EnsureHandleQueueStarted(); - return true; - } - - /// - public JobDto? GetOrDefaultState(int idTelemetry) - { - JobHandle? jobHandler; - lock (jobHandlers) - { - jobHandler = jobHandlers.FirstOrDefault(j => j.Id == idTelemetry); - } - return jobHandler?.Job; - } - - /// - public IEnumerable GetJobs() => jobHandlers.Select(j=>j.Job); - - private bool TryTakeWaitingJob(out JobHandle? job) - { - lock (jobHandlers) - { - job = jobHandlers.FirstOrDefault(j => j.Job.State == JobState.Waiting); - } - return job is not null; - } - - private void EnsureHandleQueueStarted() - { - if (isHandling) - return; - isHandling = true; - cancellationTokenSource = new CancellationTokenSource(); - var token = cancellationTokenSource.Token; - task = Task.Run(async () => await HandleJobs(token)) - .ContinueWith(_ => isHandling = false); - } - - private async Task HandleJobs(CancellationToken token) - { - while (TryTakeWaitingJob(out JobHandle? jobHandler)) - { - jobHandler!.Job.State = JobState.Working; - try - { - await RediceSamplingSaubAsync(jobHandler, token); - await RediceSamplingSpinAsync(jobHandler, token); - jobHandler.Job.State = JobState.Done; - } - catch (Exception exception) - { - jobHandler.Job.State = JobState.Fail; - jobHandler.Job.Results = null; - jobHandler.Job.Error = exception.Message; - jobHandler.OnProgress?.Invoke(jobHandler.Job); - } - - if (!jobHandlers.Any(j => j.Job.State == JobState.Waiting)) - { - var sw = Stopwatch.StartNew(); - await VacuumAsync(token); - sw.Stop(); - if (sw.ElapsedMilliseconds < 10_000) - { - var delayMs = 10_000 - (int)sw.ElapsedMilliseconds; - await Task.Delay(delayMs, token); - } - CleanJobs(); + var delayMs = 10_000 - (int)sw.ElapsedMilliseconds; + await Task.Delay(delayMs, token); } + CleanJobs(); } } + } - private void CleanJobs() + private void CleanJobs() + { + lock (jobHandlers) { - lock (jobHandlers) - { - jobHandlers.RemoveAll(j => j.Job.State == JobState.Done || j.Job.State == JobState.Fail); - } + jobHandlers.RemoveAll(j => j.Job.State == JobState.Done || j.Job.State == JobState.Fail); } + } - private async Task VacuumAsync(CancellationToken token) + private async Task VacuumAsync(CancellationToken token) + { + using var db = MakeContext(); + var sqlVacuum = "vacuum (SKIP_LOCKED);"; + await db.Database.ExecuteSqlRawAsync(sqlVacuum, token); + } + + private void Stop() + { + cancellationTokenSource?.Cancel(); + task?.Wait(1_000); + task = null; + cancellationTokenSource?.Dispose(); + cancellationTokenSource = null; + } + + private Task RediceSamplingSaubAsync(JobHandle job, CancellationToken token) + { + const int ramLimit = 10 * 1024 * 1024; + const int dataItemSize = 345; // by profiler + const int chankSize = ramLimit / dataItemSize; // ~ 90_000 + const double maxWellDepthGap = 0.1; + + var maxDateGapSec = ratio; + + var sqlSelectTemplate = + "select " + + " * " + + "from " + + " (select " + + " *, " + + " rank() over win1 as row_num, " + + " lag(\"date\", 1) over win1 as lag_date, " + + " lag(\"mode\", 1) over win1 as lag_mode, " + + " lag(mse_state, 1) over win1 as lag_mse_state, " + + " lag(well_depth, 1) over win1 as lag_well_depth, " + + " lag(id_feed_regulator, 1) over win1 as lag_id_feed_regulator " + + " from t_telemetry_data_saub " + + $" where id_telemetry = {job.Id} and \"date\" > {{0}}" + + " window win1 as (order by \"date\") " + + " ) as t_1 " + + "where " + + $" (row_num % {ratio}) = 0 " + + " or \"mode\" != lag_mode " + + $" or(\"date\" - lag_date) >= interval '{maxDateGapSec} second' " + + $" or well_depth - lag_well_depth > {maxWellDepthGap:#0,0#} " + + " or mse_state != lag_mse_state " + + " or id_feed_regulator != lag_id_feed_regulator " + + "order by \"date\" "; + + var sqlDeleteTemplate = "delete " + + "from t_telemetry_data_saub " + + $"where id_telemetry = {job.Id} and \"date\" between {{0}} and {{1}};"; + + return RediceSamplingAsync( + job, + chankSize, + sqlSelectTemplate, + sqlDeleteTemplate, + token); + } + + private Task RediceSamplingSpinAsync(JobHandle job, CancellationToken token) + { + const int ramLimit = 10 * 1024 * 1024; + const int dataItemSize = 345; // by profiler + const int chankSize = ramLimit / dataItemSize; // ~ 90_000 + var maxDateGapSec = ratio; + + var sqlSelectTemplate = + "select " + + " * " + + "from " + + " (select " + + " *, " + + " rank() over win1 as row_num, " + + " lag(\"date\", 1) over win1 as lag_date, " + + " lag(\"mode\", 1) over win1 as lag_mode, " + + " lag(state, 1) over win1 as lag_state " + + " from t_telemetry_data_spin " + + $" where id_telemetry = {job.Id} and \"date\" > {{0}}" + + " window win1 as (order by \"date\") " + + " ) as t_1 " + + "where " + + $" (row_num % {ratio}) = 0 " + + " or \"mode\" != lag_mode " + + $" or(\"date\" - lag_date) >= interval '{maxDateGapSec} second' " + + " or state != lag_state " + + "order by \"date\" "; + + var sqlDeleteTemplate = "delete " + + "from t_telemetry_data_spin " + + $"where id_telemetry = {job.Id} and \"date\" between {{0}} and {{1}};"; + + return RediceSamplingAsync( + job, + chankSize, + sqlSelectTemplate, + sqlDeleteTemplate, + token); + } + + private async Task RediceSamplingAsync( + JobHandle jobHandle, + int chankSize, + string sqlSelectTemplate, + string sqlDeleteTemplate, + CancellationToken token) + where TEntity : class, AsbCloudDb.Model.ITelemetryData + { + using var db = MakeContext(); + var dbset = db.Set(); + + var deleted = 0; + var totalCount = await dbset.Where(t => t.IdTelemetry == jobHandle.Id).CountAsync(token); + + var result = jobHandle.Job.Results!; + if (result[jobResultKeyDeleted] is int previousDeleted) + deleted += previousDeleted; + + if (result[jobResultKeyTotal] is int previousCount) + totalCount += previousCount; + + result[jobResultKeyDeleted] = deleted; + result[jobResultKeyTotal] = totalCount; + + jobHandle.OnProgress?.Invoke(jobHandle.Job); + var startDate = DateTimeOffset.MinValue; + + do { - using var db = MakeContext(); - var sqlVacuum = "vacuum (SKIP_LOCKED);"; - await db.Database.ExecuteSqlRawAsync(sqlVacuum, token); - } + var query = dbset + .FromSqlRaw(sqlSelectTemplate, startDate) + .AsNoTracking(); - private void Stop() - { - cancellationTokenSource?.Cancel(); - task?.Wait(1_000); - task = null; - cancellationTokenSource?.Dispose(); - cancellationTokenSource = null; - } + var data = await query + .Take(chankSize) + .ToArrayAsync(token); - private Task RediceSamplingSaubAsync(JobHandle job, CancellationToken token) - { - const int ramLimit = 10 * 1024 * 1024; - const int dataItemSize = 345; // by profiler - const int chankSize = ramLimit / dataItemSize; // ~ 90_000 - const double maxWellDepthGap = 0.1; + var currentDataCount = data.Length; + if (currentDataCount == 0) + break; - var maxDateGapSec = ratio; + var lastDate = data.Last().DateTime; - var sqlSelectTemplate = - "select " + - " * " + - "from " + - " (select " + - " *, " + - " rank() over win1 as row_num, " + - " lag(\"date\", 1) over win1 as lag_date, " + - " lag(\"mode\", 1) over win1 as lag_mode, " + - " lag(mse_state, 1) over win1 as lag_mse_state, " + - " lag(well_depth, 1) over win1 as lag_well_depth, " + - " lag(id_feed_regulator, 1) over win1 as lag_id_feed_regulator " + - " from t_telemetry_data_saub " + - $" where id_telemetry = {job.Id} and \"date\" > {{0}}" + - " window win1 as (order by \"date\") " + - " ) as t_1 " + - "where " + - $" (row_num % {ratio}) = 0 " + - " or \"mode\" != lag_mode " + - $" or(\"date\" - lag_date) >= interval '{maxDateGapSec} second' " + - $" or well_depth - lag_well_depth > {maxWellDepthGap:#0,0#} " + - " or mse_state != lag_mse_state " + - " or id_feed_regulator != lag_id_feed_regulator " + - "order by \"date\" "; + var currentDeleted = await db.Database.ExecuteSqlRawAsync(sqlDeleteTemplate, new object[] { startDate, lastDate }.AsEnumerable(), token); + if (currentDeleted == 0) + break; - var sqlDeleteTemplate = "delete " + - "from t_telemetry_data_saub " + - $"where id_telemetry = {job.Id} and \"date\" between {{0}} and {{1}};"; - - return RediceSamplingAsync( - job, - chankSize, - sqlSelectTemplate, - sqlDeleteTemplate, - token); - } - - private Task RediceSamplingSpinAsync(JobHandle job, CancellationToken token) - { - const int ramLimit = 10 * 1024 * 1024; - const int dataItemSize = 345; // by profiler - const int chankSize = ramLimit / dataItemSize; // ~ 90_000 - var maxDateGapSec = ratio; - - var sqlSelectTemplate = - "select " + - " * " + - "from " + - " (select " + - " *, " + - " rank() over win1 as row_num, " + - " lag(\"date\", 1) over win1 as lag_date, " + - " lag(\"mode\", 1) over win1 as lag_mode, " + - " lag(state, 1) over win1 as lag_state " + - " from t_telemetry_data_spin " + - $" where id_telemetry = {job.Id} and \"date\" > {{0}}" + - " window win1 as (order by \"date\") " + - " ) as t_1 " + - "where " + - $" (row_num % {ratio}) = 0 " + - " or \"mode\" != lag_mode " + - $" or(\"date\" - lag_date) >= interval '{maxDateGapSec} second' " + - " or state != lag_state " + - "order by \"date\" "; - - var sqlDeleteTemplate = "delete " + - "from t_telemetry_data_spin " + - $"where id_telemetry = {job.Id} and \"date\" between {{0}} and {{1}};"; - - return RediceSamplingAsync( - job, - chankSize, - sqlSelectTemplate, - sqlDeleteTemplate, - token); - } - - private async Task RediceSamplingAsync( - JobHandle jobHandle, - int chankSize, - string sqlSelectTemplate, - string sqlDeleteTemplate, - CancellationToken token) - where TEntity : class, AsbCloudDb.Model.ITelemetryData - { - using var db = MakeContext(); - var dbset = db.Set(); - - var deleted = 0; - var totalCount = await dbset.Where(t => t.IdTelemetry == jobHandle.Id).CountAsync(token); - - var result = jobHandle.Job.Results!; - if (result[jobResultKeyDeleted] is int previousDeleted) - deleted += previousDeleted; - - if (result[jobResultKeyTotal] is int previousCount) - totalCount += previousCount; + await db.Database.ExecInsertAsync(dbset, data, token); + startDate = lastDate; + deleted += currentDeleted; result[jobResultKeyDeleted] = deleted; result[jobResultKeyTotal] = totalCount; - jobHandle.OnProgress?.Invoke(jobHandle.Job); - var startDate = DateTimeOffset.MinValue; + } while (true); - do - { - var query = dbset - .FromSqlRaw(sqlSelectTemplate, startDate) - .AsNoTracking(); - - var data = await query - .Take(chankSize) - .ToArrayAsync(token); - - var currentDataCount = data.Length; - if (currentDataCount == 0) - break; - - var lastDate = data.Last().DateTime; - - var currentDeleted = await db.Database.ExecuteSqlRawAsync(sqlDeleteTemplate, new object[] { startDate, lastDate }.AsEnumerable(), token); - if (currentDeleted == 0) - break; - - await db.Database.ExecInsertAsync(dbset, data, token); - - startDate = lastDate; - deleted += currentDeleted; - result[jobResultKeyDeleted] = deleted; - result[jobResultKeyTotal] = totalCount; - jobHandle.OnProgress?.Invoke(jobHandle.Job); - } while (true); - - return; - } - - private AsbCloudDbContext MakeContext() - { - var options = new DbContextOptionsBuilder() - .UseNpgsql(connectionString) - .Options; - - return new AsbCloudDbContext(options); - } + return; } + private AsbCloudDbContext MakeContext() + { + var options = new DbContextOptionsBuilder() + .UseNpgsql(connectionString) + .Options; + + return new AsbCloudDbContext(options); + } } diff --git a/AsbCloudInfrastructure/Services/RequestTrackerService.cs b/AsbCloudInfrastructure/Services/RequestTrackerService.cs index 2a9ad660..783ac259 100644 --- a/AsbCloudInfrastructure/Services/RequestTrackerService.cs +++ b/AsbCloudInfrastructure/Services/RequestTrackerService.cs @@ -5,128 +5,126 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; -namespace AsbCloudInfrastructure.Services +namespace AsbCloudInfrastructure.Services; + + +public class RequestTrackerService : IRequerstTrackerService { + const int fastRequestsCount = 1000; + const int slowRequestsCount = 1000; + const int errorRequestsCount = 1000; + const int span = 100; - public class RequestTrackerService : IRequerstTrackerService + const int fastLimitMs = 500; + static readonly char[] stackTraceSeparators = "\r\n".ToCharArray(); + private readonly ConcurrentQueue fastRequests = new (); + private readonly ConcurrentQueue slowRequests = new (); + private readonly ConcurrentQueue errorRequests = new (); + private readonly ConcurrentDictionary users = new ConcurrentDictionary(); + + private static IEnumerable Get(IEnumerable list, int? take) { - const int fastRequestsCount = 1000; - const int slowRequestsCount = 1000; - const int errorRequestsCount = 1000; - const int span = 100; + IEnumerable orderedlist = list.OrderByDescending(r => r.Date); + if (take > 0) + orderedlist = orderedlist.Take(take.Value); + return orderedlist; + } - const int fastLimitMs = 500; - static readonly char[] stackTraceSeparators = "\r\n".ToCharArray(); - private readonly ConcurrentQueue fastRequests = new (); - private readonly ConcurrentQueue slowRequests = new (); - private readonly ConcurrentQueue errorRequests = new (); - private readonly ConcurrentDictionary users = new ConcurrentDictionary(); + public IEnumerable GetUsersStat(int? take) + { + IEnumerable result = users.Values.OrderByDescending(u => u.LastDate); + if (take > 0) + result = result.Take(take.Value); + return result; + } - private static IEnumerable Get(IEnumerable list, int? take) + public IEnumerable GetAll(int? take) + { + var result = fastRequests + .Union(slowRequests) + .Union(errorRequests); + + return Get(result, take); + } + + public IEnumerable GetFast(int? take) + => Get(fastRequests, take); + + public IEnumerable GetSlow(int? take) + => Get(slowRequests, take); + + public IEnumerable GetError(int? take) + => Get(errorRequests, take); + + public void RegisterRequest(RequestLogDto requestLog) + { + if (requestLog.Status < 200) + return; + requestLog.Date = DateTime.Now; + if (requestLog.ElapsedMilliseconds > fastLimitMs) + RegisterSlowRequest(requestLog); + else + RegisterFastRequest(requestLog); + + UpdateUserStat(requestLog); + } + + private void RegisterFastRequest(RequestLogDto requestLog) + { + fastRequests.Enqueue(requestLog); + if (fastRequests.Count > fastRequestsCount + span) + while (fastRequests.Count > fastRequestsCount) + fastRequests.TryDequeue(out _); + } + + private void RegisterSlowRequest(RequestLogDto requestLog) + { + slowRequests.Enqueue(requestLog); + if (slowRequests.Count > slowRequestsCount + span) + while (slowRequests.Count > slowRequestsCount) + slowRequests.TryDequeue(out _); + } + + public void RegisterRequestError(RequestLogDto requestLog, Exception ex) + { + requestLog.Date = DateTime.Now; + requestLog.ExceptionMessage = ex.InnerException?.InnerException?.Message + ?? ex.InnerException?.Message + ?? ex.Message; + requestLog.ExceptionStack = ex.StackTrace?.Split(stackTraceSeparators)[0]; + errorRequests.Enqueue(requestLog); + if (errorRequests.Count > errorRequestsCount + span) + while (errorRequests.Count > errorRequestsCount) + errorRequests.TryDequeue(out _); + + UpdateUserStat(requestLog); + } + + private void UpdateUserStat(RequestLogDto requestLog) + { + if (!string.IsNullOrEmpty(requestLog.UserLogin)) { - IEnumerable orderedlist = list.OrderByDescending(r => r.Date); - if (take > 0) - orderedlist = orderedlist.Take(take.Value); - return orderedlist; - } - - public IEnumerable GetUsersStat(int? take) - { - IEnumerable result = users.Values.OrderByDescending(u => u.LastDate); - if (take > 0) - result = result.Take(take.Value); - return result; - } - - public IEnumerable GetAll(int? take) - { - var result = fastRequests - .Union(slowRequests) - .Union(errorRequests); - - return Get(result, take); - } - - public IEnumerable GetFast(int? take) - => Get(fastRequests, take); - - public IEnumerable GetSlow(int? take) - => Get(slowRequests, take); - - public IEnumerable GetError(int? take) - => Get(errorRequests, take); - - public void RegisterRequest(RequestLogDto requestLog) - { - if (requestLog.Status < 200) - return; - requestLog.Date = DateTime.Now; - if (requestLog.ElapsedMilliseconds > fastLimitMs) - RegisterSlowRequest(requestLog); - else - RegisterFastRequest(requestLog); - - UpdateUserStat(requestLog); - } - - private void RegisterFastRequest(RequestLogDto requestLog) - { - fastRequests.Enqueue(requestLog); - if (fastRequests.Count > fastRequestsCount + span) - while (fastRequests.Count > fastRequestsCount) - fastRequests.TryDequeue(out _); - } - - private void RegisterSlowRequest(RequestLogDto requestLog) - { - slowRequests.Enqueue(requestLog); - if (slowRequests.Count > slowRequestsCount + span) - while (slowRequests.Count > slowRequestsCount) - slowRequests.TryDequeue(out _); - } - - public void RegisterRequestError(RequestLogDto requestLog, Exception ex) - { - requestLog.Date = DateTime.Now; - requestLog.ExceptionMessage = ex.InnerException?.InnerException?.Message - ?? ex.InnerException?.Message - ?? ex.Message; - requestLog.ExceptionStack = ex.StackTrace?.Split(stackTraceSeparators)[0]; - errorRequests.Enqueue(requestLog); - if (errorRequests.Count > errorRequestsCount + span) - while (errorRequests.Count > errorRequestsCount) - errorRequests.TryDequeue(out _); - - UpdateUserStat(requestLog); - } - - private void UpdateUserStat(RequestLogDto requestLog) - { - if (!string.IsNullOrEmpty(requestLog.UserLogin)) - { - var key = $"{requestLog.UserId}>{requestLog.UserIp}"; - if (!users.ContainsKey(key)) - users[key] = new RequestLogUserDto - { - UserId = requestLog.UserId, - Ip = requestLog.UserIp, - Login = requestLog.UserLogin, - }; - users[key].ElapsedMs += requestLog.ElapsedMilliseconds; - users[key].LastDate = requestLog.Date; - users[key].Requests++; - if (!string.IsNullOrEmpty(requestLog.ExceptionMessage)) - users[key].Errors++; - - if (users.Count > 1000) + var key = $"{requestLog.UserId}>{requestLog.UserIp}"; + if (!users.ContainsKey(key)) + users[key] = new RequestLogUserDto { - var count = 900 - users.Count; - var toRemove = users.OrderBy(kv => kv.Value.LastDate).Take(count); - foreach (var kv in toRemove) - users.TryRemove(kv); - } + UserId = requestLog.UserId, + Ip = requestLog.UserIp, + Login = requestLog.UserLogin, + }; + users[key].ElapsedMs += requestLog.ElapsedMilliseconds; + users[key].LastDate = requestLog.Date; + users[key].Requests++; + if (!string.IsNullOrEmpty(requestLog.ExceptionMessage)) + users[key].Errors++; + + if (users.Count > 1000) + { + var count = 900 - users.Count; + var toRemove = users.OrderBy(kv => kv.Value.LastDate).Take(count); + foreach (var kv in toRemove) + users.TryRemove(kv); } } } - } diff --git a/AsbCloudInfrastructure/Services/SAUB/CsvSerializer.cs b/AsbCloudInfrastructure/Services/SAUB/CsvSerializer.cs index 71091099..cc92f6bc 100644 --- a/AsbCloudInfrastructure/Services/SAUB/CsvSerializer.cs +++ b/AsbCloudInfrastructure/Services/SAUB/CsvSerializer.cs @@ -4,81 +4,79 @@ using System.Linq; using System.Reflection; using System.Text.RegularExpressions; -namespace System.Text.Csv +namespace System.Text.Csv; + + +public class CsvSerializer { + private readonly PropertyInfo[] props; + private readonly static Regex numbers = new Regex(@"^[0-9\-\+\.]+$"); - public class CsvSerializer + public string Separator { get; set; } = ";"; + public string NewLine { get; set; } = "\r\n"; + public string Quot { get; set; } = "\""; + public Encoding Encoding { get; set; } = Encoding.UTF8; + public string FloatingPointFormat { get; set; } = "#0.000#"; + public string DateTimeFormat { get; set; } = "yyyy-MM-dd HH:mm:ss"; + public string objDateTimeOffsetFormat { get; set; } = "yyyy-MM-dd HH:mm:ss zzz"; + public string TimeOnlyFormat { get; set; } = "HH:mm:ss"; + public string DateOnlyFormat { get; set; } = "yyyy-MM-dd"; + + public CsvSerializer() { - private readonly PropertyInfo[] props; - private readonly static Regex numbers = new Regex(@"^[0-9\-\+\.]+$"); - - public string Separator { get; set; } = ";"; - public string NewLine { get; set; } = "\r\n"; - public string Quot { get; set; } = "\""; - public Encoding Encoding { get; set; } = Encoding.UTF8; - public string FloatingPointFormat { get; set; } = "#0.000#"; - public string DateTimeFormat { get; set; } = "yyyy-MM-dd HH:mm:ss"; - public string objDateTimeOffsetFormat { get; set; } = "yyyy-MM-dd HH:mm:ss zzz"; - public string TimeOnlyFormat { get; set; } = "HH:mm:ss"; - public string DateOnlyFormat { get; set; } = "yyyy-MM-dd"; - - public CsvSerializer() - { - props = typeof(T).GetProperties(); - } - - public void Serialize(IEnumerable data, Stream toStream) - { - if (!data.Any()) - return; - - if(!props.Any()) - return; - - void HandleRow(IEnumerable rowData) - { - var row = string.Join(Separator, rowData); - var bytes = Encoding.GetBytes(row + NewLine); - toStream.Write(bytes); - } - - - HandleRow(props.Select(p => p.Name)); - - foreach ( var item in data) - HandleRow(props.Select(p => CsvSerializer.Escape(Fromat(p.GetValue(item))))); - } - - private string Fromat(object? obj) - { - if (obj is double objDouble) - return objDouble.ToString(FloatingPointFormat); - - if (obj is float objfloat) - return objfloat.ToString(FloatingPointFormat); - - if (obj is DateTime objDateTime) - return objDateTime.ToString(DateTimeFormat); - - if (obj is DateTimeOffset objDateTimeOffset) - return objDateTimeOffset.ToString(objDateTimeOffsetFormat); - - if (obj is DateOnly objDateOnly) - return objDateOnly.ToString(DateOnlyFormat); - - if (obj is TimeOnly objTimeOnly) - return objTimeOnly.ToString(TimeOnlyFormat); - - return obj?.ToString() ?? string.Empty; - } - - private static string Escape(string inString) - { - if (numbers.IsMatch(inString)) - return inString; - - return $"\"{inString}\""; - } + props = typeof(T).GetProperties(); } + public void Serialize(IEnumerable data, Stream toStream) + { + if (!data.Any()) + return; + + if(!props.Any()) + return; + + void HandleRow(IEnumerable rowData) + { + var row = string.Join(Separator, rowData); + var bytes = Encoding.GetBytes(row + NewLine); + toStream.Write(bytes); + } + + + HandleRow(props.Select(p => p.Name)); + + foreach ( var item in data) + HandleRow(props.Select(p => CsvSerializer.Escape(Fromat(p.GetValue(item))))); + } + + private string Fromat(object? obj) + { + if (obj is double objDouble) + return objDouble.ToString(FloatingPointFormat); + + if (obj is float objfloat) + return objfloat.ToString(FloatingPointFormat); + + if (obj is DateTime objDateTime) + return objDateTime.ToString(DateTimeFormat); + + if (obj is DateTimeOffset objDateTimeOffset) + return objDateTimeOffset.ToString(objDateTimeOffsetFormat); + + if (obj is DateOnly objDateOnly) + return objDateOnly.ToString(DateOnlyFormat); + + if (obj is TimeOnly objTimeOnly) + return objTimeOnly.ToString(TimeOnlyFormat); + + return obj?.ToString() ?? string.Empty; + } + + private static string Escape(string inString) + { + if (numbers.IsMatch(inString)) + return inString; + + return $"\"{inString}\""; + } } diff --git a/AsbCloudInfrastructure/Services/SAUB/EventService.cs b/AsbCloudInfrastructure/Services/SAUB/EventService.cs index c01b92c9..d33dc502 100644 --- a/AsbCloudInfrastructure/Services/SAUB/EventService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/EventService.cs @@ -8,39 +8,38 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services.SAUB +namespace AsbCloudInfrastructure.Services.SAUB; + + +public class EventService : IEventService { + private readonly IAsbCloudDbContext db; + private readonly IMemoryCache memoryCache; + private readonly ITelemetryService telemetryService; - public class EventService : IEventService + public EventService(IAsbCloudDbContext db, IMemoryCache memoryCache, ITelemetryService telemetryService) { - private readonly IAsbCloudDbContext db; - private readonly IMemoryCache memoryCache; - private readonly ITelemetryService telemetryService; + this.db = db; + this.memoryCache = memoryCache; + this.telemetryService = telemetryService; + } - public EventService(IAsbCloudDbContext db, IMemoryCache memoryCache, ITelemetryService telemetryService) + public async Task UpsertAsync(string uid, IEnumerable dtos, + CancellationToken token = default) + { + if (!dtos.Any()) + return; + + var telemetry = telemetryService.GetOrCreateTelemetryByUid(uid); + + var entities = dtos.Select(dto => new TelemetryEvent { - this.db = db; - this.memoryCache = memoryCache; - this.telemetryService = telemetryService; - } - - public async Task UpsertAsync(string uid, IEnumerable dtos, - CancellationToken token = default) - { - if (!dtos.Any()) - return; - - var telemetry = telemetryService.GetOrCreateTelemetryByUid(uid); - - var entities = dtos.Select(dto => new TelemetryEvent - { - IdEvent = dto.Id, - IdTelemetry = telemetry.Id, - IdCategory = dto.IdCategory, - MessageTemplate = dto.Message - }); - var result = await db.Database.ExecInsertOrUpdateAsync(db.TelemetryEvents, entities, token); - memoryCache.DropBasic(); - } + IdEvent = dto.Id, + IdTelemetry = telemetry.Id, + IdCategory = dto.IdCategory, + MessageTemplate = dto.Message + }); + var result = await db.Database.ExecInsertOrUpdateAsync(db.TelemetryEvents, entities, token); + memoryCache.DropBasic(); } } diff --git a/AsbCloudInfrastructure/Services/SAUB/MessageService.cs b/AsbCloudInfrastructure/Services/SAUB/MessageService.cs index e19e6a54..5d6555bc 100644 --- a/AsbCloudInfrastructure/Services/SAUB/MessageService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/MessageService.cs @@ -14,173 +14,172 @@ using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services.SAUB -{ - public class MessageService : IMessageService - { - private readonly IAsbCloudDbContext db; - private readonly IMemoryCache memoryCache; - private readonly ITelemetryService telemetryService; +namespace AsbCloudInfrastructure.Services.SAUB; - public MessageService(IAsbCloudDbContext db, IMemoryCache memoryCache, ITelemetryService telemetryService) +public class MessageService : IMessageService +{ + private readonly IAsbCloudDbContext db; + private readonly IMemoryCache memoryCache; + private readonly ITelemetryService telemetryService; + + public MessageService(IAsbCloudDbContext db, IMemoryCache memoryCache, ITelemetryService telemetryService) + { + this.db = db; + this.memoryCache = memoryCache; + this.telemetryService = telemetryService; + } + + public async Task> GetMessagesAsync(MessageRequest request, CancellationToken token) + { + var result = new PaginationContainer { - this.db = db; - this.memoryCache = memoryCache; - this.telemetryService = telemetryService; + Skip = request.Skip ?? 0, + Take = request.Take ?? 32, + }; + + var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(request.IdWell); + if (telemetry is null) + return result; + + var allEvents = await memoryCache.GetOrCreateBasicAsync(db.Set(), token); + var events = allEvents.Where(e => e.IdTelemetry == telemetry.Id); + + if (!events.Any()) + return result; + + var query = db.TelemetryMessages.Where(m => m.IdTelemetry == telemetry.Id) + .OrderBy(m => m.DateTime).AsNoTracking(); + + if (request.Categoryids?.Any() == true || !string.IsNullOrEmpty(request.SearchString)) + { + if (!string.IsNullOrEmpty(request.SearchString)) + events = events.Where(e => e.MessageTemplate.Contains(request.SearchString, StringComparison.OrdinalIgnoreCase)); + + if (request.Categoryids?.Any() == true) + events = events.Where(e => request.Categoryids.ToList().Contains(e.IdCategory)); + + var eventIds = events.Select(e => e.IdEvent); + + if (!eventIds.Any()) + return result; + + query = query.Where(m => eventIds.Contains(m.IdEvent)); } - public async Task> GetMessagesAsync(MessageRequest request, CancellationToken token) + query = query.OrderByDescending(m => m.DateTime); + + if (request.Begin is not null) { - var result = new PaginationContainer + var beginUtc = request.Begin.Value.ToUniversalTime(); + query = query.Where(m => m.DateTime >= beginUtc); + } + + if (request.End is not null) + { + var endUtc = request.End.Value.ToUniversalTime(); + query = query.Where(m => m.DateTime <= endUtc); + } + + result.Count = query.Count(); + + if (request.SortFields?.Any() == true) + { + query = query.SortBy(request.SortFields); + } + var messagesList = await query.Skip(result.Skip) + .Take(result.Take).AsNoTracking() + .ToListAsync(token).ConfigureAwait(false); + + if (messagesList.Count == 0) + return result; + + var allUsers = await memoryCache.GetOrCreateBasicAsync(db.Set(), token); + var users = allUsers.Where(u => u.IdTelemetry == telemetry.Id); + + var eventsDict = events.ToDictionary(x => x.IdEvent, x => x); + var usersDict = users.ToDictionary(x => x.IdUser, x => x); + + var messagesDtoList = new List(); + var timezone = telemetryService.GetTimezone(telemetry.Id); + + foreach (var message in messagesList) + { + var messageDto = new MessageDto { - Skip = request.Skip ?? 0, - Take = request.Take ?? 32, + Id = message.Id, + WellDepth = message.WellDepth }; - var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(request.IdWell); - if (telemetry is null) - return result; + messageDto.DateTime = message.DateTime.ToOffset(TimeSpan.FromHours(timezone.Hours)); - var allEvents = await memoryCache.GetOrCreateBasicAsync(db.Set(), token); - var events = allEvents.Where(e => e.IdTelemetry == telemetry.Id); - - if (!events.Any()) - return result; - - var query = db.TelemetryMessages.Where(m => m.IdTelemetry == telemetry.Id) - .OrderBy(m => m.DateTime).AsNoTracking(); - - if (request.Categoryids?.Any() == true || !string.IsNullOrEmpty(request.SearchString)) + if (message.IdTelemetryUser is not null) { - if (!string.IsNullOrEmpty(request.SearchString)) - events = events.Where(e => e.MessageTemplate.Contains(request.SearchString, StringComparison.OrdinalIgnoreCase)); - - if (request.Categoryids?.Any() == true) - events = events.Where(e => request.Categoryids.ToList().Contains(e.IdCategory)); - - var eventIds = events.Select(e => e.IdEvent); - - if (!eventIds.Any()) - return result; - - query = query.Where(m => eventIds.Contains(m.IdEvent)); - } - - query = query.OrderByDescending(m => m.DateTime); - - if (request.Begin is not null) - { - var beginUtc = request.Begin.Value.ToUniversalTime(); - query = query.Where(m => m.DateTime >= beginUtc); - } - - if (request.End is not null) - { - var endUtc = request.End.Value.ToUniversalTime(); - query = query.Where(m => m.DateTime <= endUtc); - } - - result.Count = query.Count(); - - if (request.SortFields?.Any() == true) - { - query = query.SortBy(request.SortFields); - } - var messagesList = await query.Skip(result.Skip) - .Take(result.Take).AsNoTracking() - .ToListAsync(token).ConfigureAwait(false); - - if (messagesList.Count == 0) - return result; - - var allUsers = await memoryCache.GetOrCreateBasicAsync(db.Set(), token); - var users = allUsers.Where(u => u.IdTelemetry == telemetry.Id); - - var eventsDict = events.ToDictionary(x => x.IdEvent, x => x); - var usersDict = users.ToDictionary(x => x.IdUser, x => x); - - var messagesDtoList = new List(); - var timezone = telemetryService.GetTimezone(telemetry.Id); - - foreach (var message in messagesList) - { - var messageDto = new MessageDto + if (usersDict.TryGetValue((int)message.IdTelemetryUser, out TelemetryUser? user)) { - Id = message.Id, - WellDepth = message.WellDepth - }; - - messageDto.DateTime = message.DateTime.ToOffset(TimeSpan.FromHours(timezone.Hours)); - - if (message.IdTelemetryUser is not null) - { - if (usersDict.TryGetValue((int)message.IdTelemetryUser, out TelemetryUser? user)) - { - messageDto.User = user.MakeDisplayName(); - } - else - messageDto.User = message.IdTelemetryUser.ToString(); + messageDto.User = user.MakeDisplayName(); } - - if (eventsDict.TryGetValue(message.IdEvent, out TelemetryEvent? e)) - { - messageDto.CategoryId = e.IdCategory; - messageDto.Message = e.MakeMessageText(message); - } - messagesDtoList.Add(messageDto); + else + messageDto.User = message.IdTelemetryUser.ToString(); } - result.Items = result.Items.Concat(messagesDtoList); - - return result; - } - - public Task InsertAsync(string uid, IEnumerable dtos, - CancellationToken token = default) - { - if (!dtos.Any()) - return Task.CompletedTask; - - var telemetry = telemetryService.GetOrCreateTelemetryByUid(uid); - - foreach (var dto in dtos) + if (eventsDict.TryGetValue(message.IdEvent, out TelemetryEvent? e)) { - var entity = dto.Adapt(); - entity.Id = 0; - entity.IdTelemetry = telemetry.Id; - entity.DateTime = dto.Date.ToUniversalTime(); - db.TelemetryMessages.Add(entity); + messageDto.CategoryId = e.IdCategory; + messageDto.Message = e.MakeMessageText(message); } - - return db.SaveChangesAsync(token); + messagesDtoList.Add(messageDto); } - private IQueryable BuildQuery(TelemetryPartDeleteRequest request) + result.Items = result.Items.Concat(messagesDtoList); + + return result; + } + + public Task InsertAsync(string uid, IEnumerable dtos, + CancellationToken token = default) + { + if (!dtos.Any()) + return Task.CompletedTask; + + var telemetry = telemetryService.GetOrCreateTelemetryByUid(uid); + + foreach (var dto in dtos) { - var query = db.Set() - .Where(o => o.IdTelemetry == request.IdTelemetry); - - if (request.GeDate is not null) - { - var geDate = request.GeDate.Value.ToUniversalTime(); - query = query.Where(o => o.DateTime <= geDate); - } - - if (request.LeDate is not null) - { - var leDate = request.LeDate.Value.ToUniversalTime(); - query = query.Where(o => o.DateTime >= leDate); - } - - return query; + var entity = dto.Adapt(); + entity.Id = 0; + entity.IdTelemetry = telemetry.Id; + entity.DateTime = dto.Date.ToUniversalTime(); + db.TelemetryMessages.Add(entity); } - public async Task DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token) + return db.SaveChangesAsync(token); + } + + private IQueryable BuildQuery(TelemetryPartDeleteRequest request) + { + var query = db.Set() + .Where(o => o.IdTelemetry == request.IdTelemetry); + + if (request.GeDate is not null) { - var query = BuildQuery(request); - db.Set().RemoveRange(query); - return await db.SaveChangesAsync(token); + var geDate = request.GeDate.Value.ToUniversalTime(); + query = query.Where(o => o.DateTime <= geDate); } + + if (request.LeDate is not null) + { + var leDate = request.LeDate.Value.ToUniversalTime(); + query = query.Where(o => o.DateTime >= leDate); + } + + return query; + } + + public async Task DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token) + { + var query = BuildQuery(request); + db.Set().RemoveRange(query); + return await db.SaveChangesAsync(token); } } diff --git a/AsbCloudInfrastructure/Services/SAUB/SetpointsService.cs b/AsbCloudInfrastructure/Services/SAUB/SetpointsService.cs index 2584554c..3dbaa1b8 100644 --- a/AsbCloudInfrastructure/Services/SAUB/SetpointsService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/SetpointsService.cs @@ -9,105 +9,103 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services.SAUB +namespace AsbCloudInfrastructure.Services.SAUB; + + +public class SetpointsService : ISetpointsService { - - public class SetpointsService : ISetpointsService + // ## Инфо от АПГ от 26.11.2021, дополнения ШОВ от 26.11.2021 + private static readonly Dictionary SetpointInfos = new() { - // ## Инфо от АПГ от 26.11.2021, дополнения ШОВ от 26.11.2021 - private static readonly Dictionary SetpointInfos = new() - { - { "bitLoad", new SetpointInfoDto { Name = "bitLoad", DisplayName = "Осевая нагрузка, т" } }, - { "dPressureMaxRotorSP", new SetpointInfoDto { Name = "dPressureMaxRotorSP", DisplayName = "Дифференциальное рабочее давление в роторе, атм" } }, - { "dPressureMaxSlideSP", new SetpointInfoDto { Name = "dPressureMaxSlideSP", DisplayName = "Дифференциальное рабочее давление в слайде, атм" } }, - { "torque", new SetpointInfoDto { Name = "torque", DisplayName = "Крутящий момент, кН*м" } }, - { "speedRotorSp", new SetpointInfoDto { Name = "speedRotorSp", DisplayName = "Скорость бурения в роторе, м/ч" } }, - { "speedSlideSp", new SetpointInfoDto { Name = "speedSlideSp", DisplayName = "Скорость бурения в слайде, м/ч" } }, - { "speedDevelopSp", new SetpointInfoDto { Name = "speedDevelopSp", DisplayName = "Скорость проработки, м/ч" } }, - { "torque_pid_out_limit", new SetpointInfoDto { Name = "torque_pid_out_limit", DisplayName = "Торк мастер. Допустимый процент отклонения от заданной скорости вращения" } }, // Такая же что и прямой - //{ "", new SetpointInfoDto { Name = "", DisplayName = "Обороты ВСП, об/мин" } }, // Оно в ПЛК спинмастера, пока сделать нельзя, позднее можно. - //{ "", new SetpointInfoDto { Name = "", DisplayName = "Расход промывочной жидкости, л/с" } }, // Нет в контроллере - }; - private readonly SetpointsRequestRepository setpointsRepository; - private readonly ITelemetryService telemetryService; + { "bitLoad", new SetpointInfoDto { Name = "bitLoad", DisplayName = "Осевая нагрузка, т" } }, + { "dPressureMaxRotorSP", new SetpointInfoDto { Name = "dPressureMaxRotorSP", DisplayName = "Дифференциальное рабочее давление в роторе, атм" } }, + { "dPressureMaxSlideSP", new SetpointInfoDto { Name = "dPressureMaxSlideSP", DisplayName = "Дифференциальное рабочее давление в слайде, атм" } }, + { "torque", new SetpointInfoDto { Name = "torque", DisplayName = "Крутящий момент, кН*м" } }, + { "speedRotorSp", new SetpointInfoDto { Name = "speedRotorSp", DisplayName = "Скорость бурения в роторе, м/ч" } }, + { "speedSlideSp", new SetpointInfoDto { Name = "speedSlideSp", DisplayName = "Скорость бурения в слайде, м/ч" } }, + { "speedDevelopSp", new SetpointInfoDto { Name = "speedDevelopSp", DisplayName = "Скорость проработки, м/ч" } }, + { "torque_pid_out_limit", new SetpointInfoDto { Name = "torque_pid_out_limit", DisplayName = "Торк мастер. Допустимый процент отклонения от заданной скорости вращения" } }, // Такая же что и прямой + //{ "", new SetpointInfoDto { Name = "", DisplayName = "Обороты ВСП, об/мин" } }, // Оно в ПЛК спинмастера, пока сделать нельзя, позднее можно. + //{ "", new SetpointInfoDto { Name = "", DisplayName = "Расход промывочной жидкости, л/с" } }, // Нет в контроллере + }; + private readonly SetpointsRequestRepository setpointsRepository; + private readonly ITelemetryService telemetryService; - public SetpointsService(IAsbCloudDbContext db, IMemoryCache memoryCache, ITelemetryService telemetryService, IWellService wellService) - { - setpointsRepository = new SetpointsRequestRepository(db, memoryCache, wellService); - this.telemetryService = telemetryService; - } - - public async Task InsertAsync(SetpointsRequestDto setpointsRequest, CancellationToken token) - { - setpointsRequest.IdState = 1; - setpointsRequest.UploadDate = DateTimeOffset.UtcNow; - var result = await setpointsRepository.InsertAsync(setpointsRequest, token); - return result; - } - - public async Task> GetAsync(int idWell, CancellationToken token) - { - var all = await setpointsRepository.GetAllAsync(token); - var dtos = all.Where(s => s.IdWell == idWell); - return dtos; - } - - public async Task> GetForPanelAsync(string uid, CancellationToken token) - { - var idWell = telemetryService.GetIdWellByTelemetryUid(uid) ?? -1; - - if (idWell < 0) - return Enumerable.Empty(); - var all = await setpointsRepository.GetAllAsync(token); - var filtered = all.Where(s => - s.IdWell == idWell && - s.IdState == 1 && - s.UploadDate.AddSeconds(s.ObsolescenceSec).UtcDateTime > DateTime.UtcNow) - .ToArray(); - - if (!filtered.Any()) - return Enumerable.Empty(); - - foreach (var item in filtered) - item.IdState = 2; - - await setpointsRepository.UpdateRangeAsync(filtered, token); - - return filtered; - } - - public async Task UpdateStateAsync(SetpointsRequestDto setpointsRequestDto, CancellationToken token) - { - if (setpointsRequestDto.IdState != 3 && setpointsRequestDto.IdState != 4) - throw new ArgumentOutOfRangeException(nameof(setpointsRequestDto), $"{nameof(setpointsRequestDto.IdState)} = {setpointsRequestDto.IdState}. Mast be 3 or 4."); - - if (setpointsRequestDto.Id <= 0) - throw new ArgumentOutOfRangeException(nameof(setpointsRequestDto), $"{nameof(setpointsRequestDto.Id)} = {setpointsRequestDto.Id}. Mast be > 0"); - - if (setpointsRequestDto.IdWell <= 0) - throw new ArgumentOutOfRangeException(nameof(setpointsRequestDto), $"{nameof(setpointsRequestDto.IdWell)} = {setpointsRequestDto.IdWell}. Mast be > 0"); - - var entity = await setpointsRepository.GetOrDefaultAsync(setpointsRequestDto.Id, token); - - if (entity?.IdWell != setpointsRequestDto.IdWell) - return 0; - - if (entity is null) - return 0; - - entity.IdState = setpointsRequestDto.IdState; - var affected = await setpointsRepository.UpdateRangeAsync(new[] { entity }, token); - return affected; - } - - public async Task TryDelete(int id, CancellationToken token) - { - var affected = await setpointsRepository.DeleteAsync(id, token); - return affected; - } - - public IEnumerable GetSetpointsNames() - => SetpointInfos.Values; + public SetpointsService(IAsbCloudDbContext db, IMemoryCache memoryCache, ITelemetryService telemetryService, IWellService wellService) + { + setpointsRepository = new SetpointsRequestRepository(db, memoryCache, wellService); + this.telemetryService = telemetryService; } + public async Task InsertAsync(SetpointsRequestDto setpointsRequest, CancellationToken token) + { + setpointsRequest.IdState = 1; + setpointsRequest.UploadDate = DateTimeOffset.UtcNow; + var result = await setpointsRepository.InsertAsync(setpointsRequest, token); + return result; + } + + public async Task> GetAsync(int idWell, CancellationToken token) + { + var all = await setpointsRepository.GetAllAsync(token); + var dtos = all.Where(s => s.IdWell == idWell); + return dtos; + } + + public async Task> GetForPanelAsync(string uid, CancellationToken token) + { + var idWell = telemetryService.GetIdWellByTelemetryUid(uid) ?? -1; + + if (idWell < 0) + return Enumerable.Empty(); + var all = await setpointsRepository.GetAllAsync(token); + var filtered = all.Where(s => + s.IdWell == idWell && + s.IdState == 1 && + s.UploadDate.AddSeconds(s.ObsolescenceSec).UtcDateTime > DateTime.UtcNow) + .ToArray(); + + if (!filtered.Any()) + return Enumerable.Empty(); + + foreach (var item in filtered) + item.IdState = 2; + + await setpointsRepository.UpdateRangeAsync(filtered, token); + + return filtered; + } + + public async Task UpdateStateAsync(SetpointsRequestDto setpointsRequestDto, CancellationToken token) + { + if (setpointsRequestDto.IdState != 3 && setpointsRequestDto.IdState != 4) + throw new ArgumentOutOfRangeException(nameof(setpointsRequestDto), $"{nameof(setpointsRequestDto.IdState)} = {setpointsRequestDto.IdState}. Mast be 3 or 4."); + + if (setpointsRequestDto.Id <= 0) + throw new ArgumentOutOfRangeException(nameof(setpointsRequestDto), $"{nameof(setpointsRequestDto.Id)} = {setpointsRequestDto.Id}. Mast be > 0"); + + if (setpointsRequestDto.IdWell <= 0) + throw new ArgumentOutOfRangeException(nameof(setpointsRequestDto), $"{nameof(setpointsRequestDto.IdWell)} = {setpointsRequestDto.IdWell}. Mast be > 0"); + + var entity = await setpointsRepository.GetOrDefaultAsync(setpointsRequestDto.Id, token); + + if (entity?.IdWell != setpointsRequestDto.IdWell) + return 0; + + if (entity is null) + return 0; + + entity.IdState = setpointsRequestDto.IdState; + var affected = await setpointsRepository.UpdateRangeAsync(new[] { entity }, token); + return affected; + } + + public async Task TryDelete(int id, CancellationToken token) + { + var affected = await setpointsRepository.DeleteAsync(id, token); + return affected; + } + + public IEnumerable GetSetpointsNames() + => SetpointInfos.Values; } diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataEditorService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataEditorService.cs index bcbf4c67..207dc744 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataEditorService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataEditorService.cs @@ -6,77 +6,76 @@ using AsbCloudApp.Services; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services.SAUB +namespace AsbCloudInfrastructure.Services.SAUB; + +/// +/// Сервис по работе с данными телеметрии +/// +public class TelemetryDataEditorService : ITelemetryDataEditorService { + private readonly ITelemetryDataEditorService[] repositories; + /// - /// Сервис по работе с данными телеметрии + /// /// - public class TelemetryDataEditorService : ITelemetryDataEditorService + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public TelemetryDataEditorService( + ITelemetryDataSaubService dataSaubService, + ITelemetryDataService dataSpinService, + IDataSaubStatRepository dataSaubStatRepository, + IMessageService messageService, + IDrillTestRepository drillTestRepository, + ILimitingParameterRepository limitingParameterRepository, + IDetectedOperationRepository detectedOperationRepository, + IWitsRecordRepository witsRecord1Repository, + IWitsRecordRepository witsRecord7Repository, + IWitsRecordRepository witsRecord8Repository, + IWitsRecordRepository witsRecord50Repository, + IWitsRecordRepository witsRecord60Repository, + IWitsRecordRepository witsRecord61Repository, + IGtrRepository gtrRepository + ) { - private readonly ITelemetryDataEditorService[] repositories; + repositories = + [ + dataSaubService, + dataSpinService, + dataSaubStatRepository, + messageService, + drillTestRepository, + limitingParameterRepository, + detectedOperationRepository, + witsRecord1Repository, + witsRecord7Repository, + witsRecord8Repository, + witsRecord50Repository, + witsRecord60Repository, + witsRecord61Repository, + gtrRepository, + ]; + } - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public TelemetryDataEditorService( - ITelemetryDataSaubService dataSaubService, - ITelemetryDataService dataSpinService, - IDataSaubStatRepository dataSaubStatRepository, - IMessageService messageService, - IDrillTestRepository drillTestRepository, - ILimitingParameterRepository limitingParameterRepository, - IDetectedOperationRepository detectedOperationRepository, - IWitsRecordRepository witsRecord1Repository, - IWitsRecordRepository witsRecord7Repository, - IWitsRecordRepository witsRecord8Repository, - IWitsRecordRepository witsRecord50Repository, - IWitsRecordRepository witsRecord60Repository, - IWitsRecordRepository witsRecord61Repository, - IGtrRepository gtrRepository - ) + public async Task DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token) + { + var result = 0; + foreach (var repository in repositories) { - repositories = - [ - dataSaubService, - dataSpinService, - dataSaubStatRepository, - messageService, - drillTestRepository, - limitingParameterRepository, - detectedOperationRepository, - witsRecord1Repository, - witsRecord7Repository, - witsRecord8Repository, - witsRecord50Repository, - witsRecord60Repository, - witsRecord61Repository, - gtrRepository, - ]; + result += await repository.DeleteAsync(request, token); } - public async Task DeleteAsync(TelemetryPartDeleteRequest request, CancellationToken token) - { - var result = 0; - foreach (var repository in repositories) - { - result += await repository.DeleteAsync(request, token); - } - - return result; - } + return result; } } diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSpinService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSpinService.cs index f629c69c..b081026b 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSpinService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSpinService.cs @@ -4,31 +4,29 @@ using AsbCloudApp.Services; using AsbCloudDb.Model; using Mapster; -namespace AsbCloudInfrastructure.Services.SAUB +namespace AsbCloudInfrastructure.Services.SAUB; + + +public class TelemetryDataSpinService : TelemetryDataBaseService { + public TelemetryDataSpinService( + IAsbCloudDbContext db, + ITelemetryService telemetryService, + ITelemetryDataCache telemetryDataCache) + : base(db, telemetryService, telemetryDataCache) + { } - public class TelemetryDataSpinService : TelemetryDataBaseService + protected override TelemetryDataSpin Convert(TelemetryDataSpinDto src, double timezoneOffset) { - public TelemetryDataSpinService( - IAsbCloudDbContext db, - ITelemetryService telemetryService, - ITelemetryDataCache telemetryDataCache) - : base(db, telemetryService, telemetryDataCache) - { } - - protected override TelemetryDataSpin Convert(TelemetryDataSpinDto src, double timezoneOffset) - { - var entity = src.Adapt(); - entity.DateTime = src.DateTime.ToUtcDateTimeOffset(timezoneOffset); - return entity; - } - - protected override TelemetryDataSpinDto Convert(TelemetryDataSpin src, double timezoneOffset) - { - var dto = src.Adapt(); - dto.DateTime = src.DateTime.ToRemoteDateTime(timezoneOffset); - return dto; - } + var entity = src.Adapt(); + entity.DateTime = src.DateTime.ToUtcDateTimeOffset(timezoneOffset); + return entity; } + protected override TelemetryDataSpinDto Convert(TelemetryDataSpin src, double timezoneOffset) + { + var dto = src.Adapt(); + dto.DateTime = src.DateTime.ToRemoteDateTime(timezoneOffset); + return dto; + } } diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs index 4200595e..49d6d821 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryService.cs @@ -15,342 +15,341 @@ using System.Text.Csv; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services.SAUB +namespace AsbCloudInfrastructure.Services.SAUB; + +public class TelemetryService : ITelemetryService { - public class TelemetryService : ITelemetryService + private readonly IAsbCloudDbContext db; + private readonly IMemoryCache memoryCache; + //TODO: методы использующие ITelemetryDataCache, скорее всего, тут не нужны + private readonly ITelemetryDataCache dataSaubCache; + private readonly ITimezoneService timezoneService; + + public ITimezoneService TimeZoneService => timezoneService; + + public TelemetryService( + IAsbCloudDbContext db, + IMemoryCache memoryCache, + ITelemetryDataCache dataSaubCache, + ITimezoneService timezoneService) { - private readonly IAsbCloudDbContext db; - private readonly IMemoryCache memoryCache; - //TODO: методы использующие ITelemetryDataCache, скорее всего, тут не нужны - private readonly ITelemetryDataCache dataSaubCache; - private readonly ITimezoneService timezoneService; + this.db = db; + this.memoryCache = memoryCache; + this.dataSaubCache = dataSaubCache; + this.timezoneService = timezoneService; + } - public ITimezoneService TimeZoneService => timezoneService; + private IEnumerable GetTelemetryCache() + => memoryCache.GetOrCreateBasic( + db.Set() + .Include(t => t.Well)); + + private void DropTelemetryCache() + { + memoryCache.DropBasic(); + } - public TelemetryService( - IAsbCloudDbContext db, - IMemoryCache memoryCache, - ITelemetryDataCache dataSaubCache, - ITimezoneService timezoneService) - { - this.db = db; - this.memoryCache = memoryCache; - this.dataSaubCache = dataSaubCache; - this.timezoneService = timezoneService; - } + public DatesRangeDto GetDatesRange(int idTelemetry) + { + var cacheDataRange = dataSaubCache.GetOrDefaultWellDataDateRange(idTelemetry) + ?? new (); + return cacheDataRange; + } - private IEnumerable GetTelemetryCache() - => memoryCache.GetOrCreateBasic( - db.Set() - .Include(t => t.Well)); + public int? GetIdWellByTelemetryUid(string uid) + => GetWellByTelemetryUid(uid)?.Id; + + public async Task UpdateInfoAsync(string uid, TelemetryInfoDto info, + CancellationToken token) + { + var telemetry = GetOrCreateTelemetry(uid); + telemetry.Info = info.Adapt(); + + if (!string.IsNullOrEmpty(info.TimeZoneId) && + telemetry.TimeZone?.IsOverride != true) + telemetry.TimeZone = new SimpleTimezone() + { + Hours = info.TimeZoneOffsetTotalHours, + TimezoneId = info.TimeZoneId + }; + + db.Telemetries.Upsert(telemetry); + await db.SaveChangesAsync(token); + DropTelemetryCache(); + } + + [Obsolete("This method will be private. Use TelemetryDto.TimeZone prop.")] + public SimpleTimezoneDto GetTimezone(int idTelemetry) + { + var telemetry = GetTelemetryCache().FirstOrDefault(t => t.Id == idTelemetry); + + if (telemetry is null) + throw new Exception($"Telemetry id: {idTelemetry} does not exist."); + + if (telemetry.Well?.Timezone is not null) + return telemetry.Well.Timezone.Adapt(); - private void DropTelemetryCache() + if (telemetry.TimeZone is not null) + return telemetry.TimeZone.Adapt(); + + throw new Exception($"Telemetry id: {idTelemetry} can't find timezone."); + } + + public TelemetryBaseDto? GetOrDefaultTelemetryByIdWell(int idWell) + { + var entity = GetTelemetryCache() + .FirstOrDefault(t => t.Well?.Id == idWell); + + if (entity?.Well?.Timezone is not null && entity.TimeZone.Hours != entity.Well.Timezone.Hours) { - memoryCache.DropBasic(); + entity.TimeZone = entity.Well.Timezone; + //TODO: выдаем предупреждение! } + return entity?.Adapt(); + } - public DatesRangeDto GetDatesRange(int idTelemetry) + public TelemetryDto GetOrCreateTelemetryByUid(string uid) + { + var entity = GetOrCreateTelemetry(uid); + if(entity.Well?.Timezone is not null && entity.TimeZone.Hours != entity.Well.Timezone.Hours) { - var cacheDataRange = dataSaubCache.GetOrDefaultWellDataDateRange(idTelemetry) - ?? new (); - return cacheDataRange; + entity.TimeZone = entity.Well.Timezone; + //TODO: выдаем предупреждение! } + var dto = entity.Adapt(); + return dto; + } - public int? GetIdWellByTelemetryUid(string uid) - => GetWellByTelemetryUid(uid)?.Id; + private Well? GetWellByTelemetryUid(string uid) + { + var telemetry = GetOrDefaultTelemetryByUid(uid); + return telemetry?.Well; + } - public async Task UpdateInfoAsync(string uid, TelemetryInfoDto info, - CancellationToken token) + private Telemetry? GetOrDefaultTelemetryByUid(string uid) + { + var telemetry = GetTelemetryCache().FirstOrDefault(t => t.RemoteUid == uid); + return telemetry; + } + + private Telemetry GetOrCreateTelemetry(string uid) + { + var telemetry = GetOrDefaultTelemetryByUid(uid); + if (telemetry is null) { - var telemetry = GetOrCreateTelemetry(uid); - telemetry.Info = info.Adapt(); - - if (!string.IsNullOrEmpty(info.TimeZoneId) && - telemetry.TimeZone?.IsOverride != true) - telemetry.TimeZone = new SimpleTimezone() + var newTelemetry = new Telemetry + { + RemoteUid = uid, + TimeZone = new SimpleTimezone { - Hours = info.TimeZoneOffsetTotalHours, - TimezoneId = info.TimeZoneId - }; - - db.Telemetries.Upsert(telemetry); - await db.SaveChangesAsync(token); + Hours = 5, + IsOverride = false, + TimezoneId = "default", + } + }; + var entry = db.Telemetries.Add(newTelemetry); + db.SaveChanges(); DropTelemetryCache(); - } + return entry.Entity; + } + return telemetry; + } - [Obsolete("This method will be private. Use TelemetryDto.TimeZone prop.")] - public SimpleTimezoneDto GetTimezone(int idTelemetry) - { - var telemetry = GetTelemetryCache().FirstOrDefault(t => t.Id == idTelemetry); - - if (telemetry is null) - throw new Exception($"Telemetry id: {idTelemetry} does not exist."); - - if (telemetry.Well?.Timezone is not null) - return telemetry.Well.Timezone.Adapt(); - - if (telemetry.TimeZone is not null) - return telemetry.TimeZone.Adapt(); - - throw new Exception($"Telemetry id: {idTelemetry} can't find timezone."); - } - - public TelemetryBaseDto? GetOrDefaultTelemetryByIdWell(int idWell) - { - var entity = GetTelemetryCache() - .FirstOrDefault(t => t.Well?.Id == idWell); - - if (entity?.Well?.Timezone is not null && entity.TimeZone.Hours != entity.Well.Timezone.Hours) + public async Task GetTelemetriesInfoByLastData(DateTimeOffset from, CancellationToken token) + { + var fromUtc = from.UtcDateTime; + var query = db.TelemetryDataSaub + .Where(i => i.DateTime >= fromUtc) + .GroupBy(i => i.IdTelemetry) + .Select(i => new { - entity.TimeZone = entity.Well.Timezone; - //TODO: выдаем предупреждение! - } - return entity?.Adapt(); - } + i.First().Telemetry, + LastDate = i.Max(i => i.DateTime) + }); - public TelemetryDto GetOrCreateTelemetryByUid(string uid) - { - var entity = GetOrCreateTelemetry(uid); - if(entity.Well?.Timezone is not null && entity.TimeZone.Hours != entity.Well.Timezone.Hours) - { - entity.TimeZone = entity.Well.Timezone; - //TODO: выдаем предупреждение! - } - var dto = entity.Adapt(); - return dto; - } + var data = await query.ToArrayAsync(token); - private Well? GetWellByTelemetryUid(string uid) - { - var telemetry = GetOrDefaultTelemetryByUid(uid); - return telemetry?.Well; - } - - private Telemetry? GetOrDefaultTelemetryByUid(string uid) - { - var telemetry = GetTelemetryCache().FirstOrDefault(t => t.RemoteUid == uid); - return telemetry; - } - - private Telemetry GetOrCreateTelemetry(string uid) - { - var telemetry = GetOrDefaultTelemetryByUid(uid); - if (telemetry is null) - { - var newTelemetry = new Telemetry - { - RemoteUid = uid, - TimeZone = new SimpleTimezone - { - Hours = 5, - IsOverride = false, - TimezoneId = "default", - } - }; - var entry = db.Telemetries.Add(newTelemetry); - db.SaveChanges(); - DropTelemetryCache(); - return entry.Entity; - } - return telemetry; - } - - public async Task GetTelemetriesInfoByLastData(DateTimeOffset from, CancellationToken token) - { - var fromUtc = from.UtcDateTime; - var query = db.TelemetryDataSaub - .Where(i => i.DateTime >= fromUtc) - .GroupBy(i => i.IdTelemetry) - .Select(i => new - { - i.First().Telemetry, - LastDate = i.Max(i => i.DateTime) - }); - - var data = await query.ToArrayAsync(token); - - var infos = data.Select(i => new TelemetryWithSoftwareVersionsDto( - i.Telemetry.Id, - i.Telemetry.RemoteUid, - i.LastDate, - i.Telemetry.Info.Deposit, - i.Telemetry.Info.Cluster, - i.Telemetry.Info.Well, - i.Telemetry.Info.HmiVersion, - i.Telemetry.Info.SaubPlcVersion, - i.Telemetry.Info.SpinPlcVersion) - ); - var stream = new MemoryStream(); - if (!data.Any()) - return stream; - - var serializer = new CsvSerializer(); - serializer.Serialize(infos, stream); - stream.Seek(0, SeekOrigin.Begin); + var infos = data.Select(i => new TelemetryWithSoftwareVersionsDto( + i.Telemetry.Id, + i.Telemetry.RemoteUid, + i.LastDate, + i.Telemetry.Info.Deposit, + i.Telemetry.Info.Cluster, + i.Telemetry.Info.Well, + i.Telemetry.Info.HmiVersion, + i.Telemetry.Info.SaubPlcVersion, + i.Telemetry.Info.SpinPlcVersion) + ); + var stream = new MemoryStream(); + if (!data.Any()) return stream; - } - public async Task MergeAsync(int from, int to, CancellationToken token) + var serializer = new CsvSerializer(); + serializer.Serialize(infos, stream); + stream.Seek(0, SeekOrigin.Begin); + return stream; + } + + public async Task MergeAsync(int from, int to, CancellationToken token) + { + if (from == to) + return -2; + + var stopwath = new System.Diagnostics.Stopwatch(); + stopwath.Start(); + + var transaction = await db.Database.BeginTransactionAsync(token).ConfigureAwait(false); + try { - if (from == to) + var affected = 0; + + var wellFrom = await db.Wells.FirstOrDefaultAsync(w => w.IdTelemetry == from, token) + .ConfigureAwait(false); + var wellTo = await db.Wells.FirstOrDefaultAsync(w => w.IdTelemetry == to, token) + .ConfigureAwait(false); + + if (wellTo is not null && wellFrom is not null) return -2; - var stopwath = new System.Diagnostics.Stopwatch(); - stopwath.Start(); - - var transaction = await db.Database.BeginTransactionAsync(token).ConfigureAwait(false); - try + if (wellTo is null && wellFrom is not null) { - var affected = 0; - - var wellFrom = await db.Wells.FirstOrDefaultAsync(w => w.IdTelemetry == from, token) - .ConfigureAwait(false); - var wellTo = await db.Wells.FirstOrDefaultAsync(w => w.IdTelemetry == to, token) - .ConfigureAwait(false); - - if (wellTo is not null && wellFrom is not null) - return -2; - - if (wellTo is null && wellFrom is not null) - { - wellFrom.IdTelemetry = to; - affected += await db.SaveChangesAsync(token); - } - - affected += await MergeEventsAndMessagesAndUsersAsync(from, to, token); - affected += await MergeDataAsync(from, to, token); - affected += await MergeDataAsync(from, to, token); - - affected += await db.Database.ExecuteSqlRawAsync($"DELETE FROM t_telemetry_analysis WHERE id_telemetry = {from} OR id_telemetry = {to};", token) - .ConfigureAwait(false); - affected += await db.Database.ExecuteSqlRawAsync($"DELETE FROM t_telemetry WHERE id = {from};", token) - .ConfigureAwait(false); - await transaction.CommitAsync(token).ConfigureAwait(false); - - stopwath.Stop(); - Console.WriteLine($"Successfully committed in {1d * stopwath.ElapsedMilliseconds / 1000d: #0.00} sec. Affected {affected} rows."); - DropTelemetryCache(); - return affected; - } - catch (Exception ex) - { - System.Diagnostics.Trace.WriteLine($"Merge() Fail. Rollback. Reason is:{ex.Message}"); - await transaction.RollbackAsync(CancellationToken.None); - return -1; - } - } - - private async Task MergeEventsAndMessagesAndUsersAsync(int from, int to, CancellationToken token) - { - var messagesFrom = await db.TelemetryMessages - .Where(d => d.IdTelemetry == from) - .ToListAsync(token) - .ConfigureAwait(false); - - var usersFromQuery = db.TelemetryUsers - .Where(d => d.IdTelemetry == from); - var usersFrom = await usersFromQuery - .ToListAsync(token) - .ConfigureAwait(false); - - var usersTo = await db.TelemetryUsers - .Where(d => d.IdTelemetry == to) - .AsNoTracking() - .ToListAsync(token) - .ConfigureAwait(false); - - var usersToNextId = usersTo.Max(u => u.IdUser) + 100; - - messagesFrom.ForEach(m => m.IdTelemetry = to); - - foreach (var userFrom in usersFrom) - { - var userTo = usersTo - .FirstOrDefault(u => u.IdUser == userFrom.IdUser); - - if (userTo is null || - userTo.Name != userFrom.Name || - userTo.Surname != userFrom.Surname || - userTo.Patronymic != userFrom.Patronymic) - { - messagesFrom - .Where(m => m.IdTelemetryUser == userFrom.IdUser) - .ToList() - .ForEach(m => m.IdTelemetryUser = usersToNextId); - userFrom.IdUser = usersToNextId; - userFrom.IdTelemetry = to; - usersToNextId++; - } + wellFrom.IdTelemetry = to; + affected += await db.SaveChangesAsync(token); } - var eventsFromQuery = db.TelemetryEvents - .Where(d => d.IdTelemetry == from); - var eventsFrom = await eventsFromQuery - .ToListAsync(token) + affected += await MergeEventsAndMessagesAndUsersAsync(from, to, token); + affected += await MergeDataAsync(from, to, token); + affected += await MergeDataAsync(from, to, token); + + affected += await db.Database.ExecuteSqlRawAsync($"DELETE FROM t_telemetry_analysis WHERE id_telemetry = {from} OR id_telemetry = {to};", token) .ConfigureAwait(false); - - var eventsTo = await db.TelemetryEvents - .Where(d => d.IdTelemetry == to) - .AsNoTracking() - .ToListAsync(token) + affected += await db.Database.ExecuteSqlRawAsync($"DELETE FROM t_telemetry WHERE id = {from};", token) .ConfigureAwait(false); + await transaction.CommitAsync(token).ConfigureAwait(false); - var eventsToNextId = eventsTo.Max(e => e.IdEvent) + 1; - - foreach (var eventFrom in eventsFrom) - { - var eventTo = eventsTo - .FirstOrDefault(e => e.IdEvent == eventFrom.IdEvent); - - if (eventTo is null || - eventTo.IdCategory != eventFrom.IdCategory || - eventTo.MessageTemplate != eventFrom.MessageTemplate) - { - messagesFrom - .Where(m => m.IdEvent == eventFrom.IdEvent) - .ToList() - .ForEach(m => m.IdEvent = eventsToNextId); - eventFrom.IdEvent = eventsToNextId; - eventFrom.IdTelemetry = to; - eventsToNextId++; - } - } - - await db.Database.ExecuteSqlRawAsync($"ALTER TABLE t_telemetry_user DISABLE TRIGGER ALL;", token).ConfigureAwait(false); - await db.Database.ExecuteSqlRawAsync($"ALTER TABLE t_telemetry_event DISABLE TRIGGER ALL;", token).ConfigureAwait(false); - await db.Database.ExecuteSqlRawAsync($"ALTER TABLE t_telemetry_message DISABLE TRIGGER ALL;", token).ConfigureAwait(false); - var affected = await db.SaveChangesAsync(token).ConfigureAwait(false); - await db.Database.ExecuteSqlRawAsync($"ALTER TABLE t_telemetry_user ENABLE TRIGGER ALL;", token).ConfigureAwait(false); - await db.Database.ExecuteSqlRawAsync($"ALTER TABLE t_telemetry_event ENABLE TRIGGER ALL;", token).ConfigureAwait(false); - await db.Database.ExecuteSqlRawAsync($"ALTER TABLE t_telemetry_message ENABLE TRIGGER ALL;", token).ConfigureAwait(false); - db.TelemetryUsers.RemoveRange(usersFromQuery); - db.TelemetryEvents.RemoveRange(eventsFromQuery); - affected += await db.SaveChangesAsync(token).ConfigureAwait(false); + stopwath.Stop(); + Console.WriteLine($"Successfully committed in {1d * stopwath.ElapsedMilliseconds / 1000d: #0.00} sec. Affected {affected} rows."); + DropTelemetryCache(); return affected; } - - private async Task MergeDataAsync(int from, int to, CancellationToken token) - where TEntity : class, AsbCloudDb.Model.ITelemetryData + catch (Exception ex) { - const string IdTelemetryColumnName = "\"id_telemetry\""; - var dbSet = db.Set(); - var tableName = dbSet.GetTableName(); - var columns = dbSet.GetColumnsNames().ToList(); - var index = columns.FindIndex(c => c.ToLower() == IdTelemetryColumnName.ToLower()); - if (index < 0) - return -5; - columns[index] = $"{to} as {IdTelemetryColumnName}"; - var columnsString = string.Join(',', columns); - var sql = $"INSERT INTO {tableName} " + - $"select {columnsString} " + - $"from {tableName} " + - $"where {IdTelemetryColumnName} = {from};" + - $"delete from {tableName} where {IdTelemetryColumnName} = {from};"; - - var affected = await db.Database.ExecuteSqlRawAsync(sql, token) - .ConfigureAwait(false); - - return affected; + System.Diagnostics.Trace.WriteLine($"Merge() Fail. Rollback. Reason is:{ex.Message}"); + await transaction.RollbackAsync(CancellationToken.None); + return -1; } } + + private async Task MergeEventsAndMessagesAndUsersAsync(int from, int to, CancellationToken token) + { + var messagesFrom = await db.TelemetryMessages + .Where(d => d.IdTelemetry == from) + .ToListAsync(token) + .ConfigureAwait(false); + + var usersFromQuery = db.TelemetryUsers + .Where(d => d.IdTelemetry == from); + var usersFrom = await usersFromQuery + .ToListAsync(token) + .ConfigureAwait(false); + + var usersTo = await db.TelemetryUsers + .Where(d => d.IdTelemetry == to) + .AsNoTracking() + .ToListAsync(token) + .ConfigureAwait(false); + + var usersToNextId = usersTo.Max(u => u.IdUser) + 100; + + messagesFrom.ForEach(m => m.IdTelemetry = to); + + foreach (var userFrom in usersFrom) + { + var userTo = usersTo + .FirstOrDefault(u => u.IdUser == userFrom.IdUser); + + if (userTo is null || + userTo.Name != userFrom.Name || + userTo.Surname != userFrom.Surname || + userTo.Patronymic != userFrom.Patronymic) + { + messagesFrom + .Where(m => m.IdTelemetryUser == userFrom.IdUser) + .ToList() + .ForEach(m => m.IdTelemetryUser = usersToNextId); + userFrom.IdUser = usersToNextId; + userFrom.IdTelemetry = to; + usersToNextId++; + } + } + + var eventsFromQuery = db.TelemetryEvents + .Where(d => d.IdTelemetry == from); + var eventsFrom = await eventsFromQuery + .ToListAsync(token) + .ConfigureAwait(false); + + var eventsTo = await db.TelemetryEvents + .Where(d => d.IdTelemetry == to) + .AsNoTracking() + .ToListAsync(token) + .ConfigureAwait(false); + + var eventsToNextId = eventsTo.Max(e => e.IdEvent) + 1; + + foreach (var eventFrom in eventsFrom) + { + var eventTo = eventsTo + .FirstOrDefault(e => e.IdEvent == eventFrom.IdEvent); + + if (eventTo is null || + eventTo.IdCategory != eventFrom.IdCategory || + eventTo.MessageTemplate != eventFrom.MessageTemplate) + { + messagesFrom + .Where(m => m.IdEvent == eventFrom.IdEvent) + .ToList() + .ForEach(m => m.IdEvent = eventsToNextId); + eventFrom.IdEvent = eventsToNextId; + eventFrom.IdTelemetry = to; + eventsToNextId++; + } + } + + await db.Database.ExecuteSqlRawAsync($"ALTER TABLE t_telemetry_user DISABLE TRIGGER ALL;", token).ConfigureAwait(false); + await db.Database.ExecuteSqlRawAsync($"ALTER TABLE t_telemetry_event DISABLE TRIGGER ALL;", token).ConfigureAwait(false); + await db.Database.ExecuteSqlRawAsync($"ALTER TABLE t_telemetry_message DISABLE TRIGGER ALL;", token).ConfigureAwait(false); + var affected = await db.SaveChangesAsync(token).ConfigureAwait(false); + await db.Database.ExecuteSqlRawAsync($"ALTER TABLE t_telemetry_user ENABLE TRIGGER ALL;", token).ConfigureAwait(false); + await db.Database.ExecuteSqlRawAsync($"ALTER TABLE t_telemetry_event ENABLE TRIGGER ALL;", token).ConfigureAwait(false); + await db.Database.ExecuteSqlRawAsync($"ALTER TABLE t_telemetry_message ENABLE TRIGGER ALL;", token).ConfigureAwait(false); + db.TelemetryUsers.RemoveRange(usersFromQuery); + db.TelemetryEvents.RemoveRange(eventsFromQuery); + affected += await db.SaveChangesAsync(token).ConfigureAwait(false); + return affected; + } + + private async Task MergeDataAsync(int from, int to, CancellationToken token) + where TEntity : class, AsbCloudDb.Model.ITelemetryData + { + const string IdTelemetryColumnName = "\"id_telemetry\""; + var dbSet = db.Set(); + var tableName = dbSet.GetTableName(); + var columns = dbSet.GetColumnsNames().ToList(); + var index = columns.FindIndex(c => c.ToLower() == IdTelemetryColumnName.ToLower()); + if (index < 0) + return -5; + columns[index] = $"{to} as {IdTelemetryColumnName}"; + var columnsString = string.Join(',', columns); + var sql = $"INSERT INTO {tableName} " + + $"select {columnsString} " + + $"from {tableName} " + + $"where {IdTelemetryColumnName} = {from};" + + $"delete from {tableName} where {IdTelemetryColumnName} = {from};"; + + var affected = await db.Database.ExecuteSqlRawAsync(sql, token) + .ConfigureAwait(false); + + return affected; + } } diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryUserService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryUserService.cs index d3975602..abd17dc4 100644 --- a/AsbCloudInfrastructure/Services/SAUB/TelemetryUserService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryUserService.cs @@ -11,91 +11,89 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services.SAUB +namespace AsbCloudInfrastructure.Services.SAUB; + + +public class TelemetryUserService : ITelemetryUserService { + private const string CacheTag = "TelemetryUserCacheTag"; + private readonly TimeSpan CacheOlescence = TimeSpan.FromMinutes(5); - public class TelemetryUserService : ITelemetryUserService + private readonly IAsbCloudDbContext db; + private readonly ITelemetryService telemetryService; + private readonly IMemoryCache memoryCache; + + public TelemetryUserService(IAsbCloudDbContext db, + ITelemetryService telemetryService, + IMemoryCache memoryCache) { - private const string CacheTag = "TelemetryUserCacheTag"; - private readonly TimeSpan CacheOlescence = TimeSpan.FromMinutes(5); - - private readonly IAsbCloudDbContext db; - private readonly ITelemetryService telemetryService; - private readonly IMemoryCache memoryCache; - - public TelemetryUserService(IAsbCloudDbContext db, - ITelemetryService telemetryService, - IMemoryCache memoryCache) - { - this.db = db; - this.telemetryService = telemetryService; - this.memoryCache = memoryCache; - } - - public TelemetryUserDto? GetOrDefault(int idTelemetry, int idUser) - { - var entity = GetCache() - .FirstOrDefault(u => u.IdTelemetry == idTelemetry && u.IdUser == idUser); - - if(entity is null) - return null; - - return Convert(entity); - } - - public IEnumerable GetUsers(int idTelemetry, Func? predicate = null) - { - var entities = GetCache() - .Where(u => u.IdTelemetry == idTelemetry); - - foreach (var entity in entities) - { - var dto = Convert(entity); - if(predicate?.Invoke(dto)??true) - yield return dto; - } - - yield break; - } - - public async Task UpsertAsync(string uid, IEnumerable dtos, CancellationToken token = default) - { - if (!dtos.Any()) - return; - - var telemetry = telemetryService.GetOrCreateTelemetryByUid(uid); - - var entities = dtos.Distinct(new TelemetryUserDtoComparer()).Select(dto => { - var entity = dto.Adapt(); - entity.IdUser = dto.Id; - entity.IdTelemetry = telemetry.Id; - return entity; - }); - var result = await db.Database.ExecInsertOrUpdateAsync(db.TelemetryUsers, entities, token); - DropCache(); - } - - private IEnumerable GetCache() - { - var cache = memoryCache.GetOrCreate(CacheTag, cacheEntry => { - cacheEntry.AbsoluteExpirationRelativeToNow = CacheOlescence; - cacheEntry.SlidingExpiration = CacheOlescence; - - var entities = db.Set().ToArray(); - return entities; - }); - return cache!; - } - - private void DropCache() - => memoryCache.Remove(CacheTag); - - private static TelemetryUserDto Convert(TelemetryUser entity) - { - var dto = entity.Adapt(); - dto.Id = entity.IdUser; - return dto; - } + this.db = db; + this.telemetryService = telemetryService; + this.memoryCache = memoryCache; } + public TelemetryUserDto? GetOrDefault(int idTelemetry, int idUser) + { + var entity = GetCache() + .FirstOrDefault(u => u.IdTelemetry == idTelemetry && u.IdUser == idUser); + + if(entity is null) + return null; + + return Convert(entity); + } + + public IEnumerable GetUsers(int idTelemetry, Func? predicate = null) + { + var entities = GetCache() + .Where(u => u.IdTelemetry == idTelemetry); + + foreach (var entity in entities) + { + var dto = Convert(entity); + if(predicate?.Invoke(dto)??true) + yield return dto; + } + + yield break; + } + + public async Task UpsertAsync(string uid, IEnumerable dtos, CancellationToken token = default) + { + if (!dtos.Any()) + return; + + var telemetry = telemetryService.GetOrCreateTelemetryByUid(uid); + + var entities = dtos.Distinct(new TelemetryUserDtoComparer()).Select(dto => { + var entity = dto.Adapt(); + entity.IdUser = dto.Id; + entity.IdTelemetry = telemetry.Id; + return entity; + }); + var result = await db.Database.ExecInsertOrUpdateAsync(db.TelemetryUsers, entities, token); + DropCache(); + } + + private IEnumerable GetCache() + { + var cache = memoryCache.GetOrCreate(CacheTag, cacheEntry => { + cacheEntry.AbsoluteExpirationRelativeToNow = CacheOlescence; + cacheEntry.SlidingExpiration = CacheOlescence; + + var entities = db.Set().ToArray(); + return entities; + }); + return cache!; + } + + private void DropCache() + => memoryCache.Remove(CacheTag); + + private static TelemetryUserDto Convert(TelemetryUser entity) + { + var dto = entity.Adapt(); + dto.Id = entity.IdUser; + return dto; + } } diff --git a/AsbCloudInfrastructure/Services/Subsystems/DepthInterpolation.cs b/AsbCloudInfrastructure/Services/Subsystems/DepthInterpolation.cs index 532377ef..8376e06d 100644 --- a/AsbCloudInfrastructure/Services/Subsystems/DepthInterpolation.cs +++ b/AsbCloudInfrastructure/Services/Subsystems/DepthInterpolation.cs @@ -1,62 +1,60 @@ using System; using System.Collections.Generic; -namespace AsbCloudInfrastructure.Services.Subsystems.Utils +namespace AsbCloudInfrastructure.Services.Subsystems.Utils; + + +internal class DepthInterpolation { + private readonly TimeSpan maxDeltaDate = TimeSpan.FromHours(12); + private readonly IEnumerator<(DateTimeOffset x, float y)> enumerator; + private (DateTimeOffset x, float y) p0; + private bool canMoveNext; - internal class DepthInterpolation + public DepthInterpolation(IEnumerable<(DateTimeOffset x, float y)> collection) { - private readonly TimeSpan maxDeltaDate = TimeSpan.FromHours(12); - private readonly IEnumerator<(DateTimeOffset x, float y)> enumerator; - private (DateTimeOffset x, float y) p0; - private bool canMoveNext; - - public DepthInterpolation(IEnumerable<(DateTimeOffset x, float y)> collection) - { - enumerator = collection.GetEnumerator(); - canMoveNext = enumerator.MoveNext(); - p0 = enumerator.Current; - } - - ~DepthInterpolation() - { - enumerator.Dispose(); - } - - public float GetDepth(DateTimeOffset date) - { - // ошибка в телеметрии см. прим.: idTelemetry = 93 && date between '2021-11-16 17:18:40.000 +0500' and '2021-11-16 17:19:37.000 +0500' - while (canMoveNext && enumerator.Current.x < date) - { - p0 = enumerator.Current; - canMoveNext = enumerator.MoveNext(); - } - return CalcValue(date); - } - - private float CalcValue(DateTimeOffset date) - { - var p1 = enumerator.Current; - if (canMoveNext || p1 == default || p0.y == p1.y || p0.x > date) - return p0.y; - - if (p1.x < date) - return p1.y; - - if (p1.x - p0.x > maxDeltaDate && Math.Abs(p1.y - p0.y) > 0.2d) - { - if (date - p0.x < p1.x - date) - return p0.y; - else - return p1.y; - } - - var a = (p1.y - p0.y) / (p1.x - p0.x).TotalSeconds; - var b = p0.y; - var x = (date - p0.x).TotalSeconds; - var y = a * x + b; - return (float)y; - } + enumerator = collection.GetEnumerator(); + canMoveNext = enumerator.MoveNext(); + p0 = enumerator.Current; } + ~DepthInterpolation() + { + enumerator.Dispose(); + } + + public float GetDepth(DateTimeOffset date) + { + // ошибка в телеметрии см. прим.: idTelemetry = 93 && date between '2021-11-16 17:18:40.000 +0500' and '2021-11-16 17:19:37.000 +0500' + while (canMoveNext && enumerator.Current.x < date) + { + p0 = enumerator.Current; + canMoveNext = enumerator.MoveNext(); + } + return CalcValue(date); + } + + private float CalcValue(DateTimeOffset date) + { + var p1 = enumerator.Current; + if (canMoveNext || p1 == default || p0.y == p1.y || p0.x > date) + return p0.y; + + if (p1.x < date) + return p1.y; + + if (p1.x - p0.x > maxDeltaDate && Math.Abs(p1.y - p0.y) > 0.2d) + { + if (date - p0.x < p1.x - date) + return p0.y; + else + return p1.y; + } + + var a = (p1.y - p0.y) / (p1.x - p0.x).TotalSeconds; + var b = p0.y; + var x = (date - p0.x).TotalSeconds; + var y = a * x + b; + return (float)y; + } } diff --git a/AsbCloudInfrastructure/Services/TimeZoneService.cs b/AsbCloudInfrastructure/Services/TimeZoneService.cs index b22edfc0..f0552777 100644 --- a/AsbCloudInfrastructure/Services/TimeZoneService.cs +++ b/AsbCloudInfrastructure/Services/TimeZoneService.cs @@ -5,67 +5,66 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services +namespace AsbCloudInfrastructure.Services; + +public class TimezoneService : ITimezoneService { - public class TimezoneService : ITimezoneService + private class TimeZoneInfo { - private class TimeZoneInfo - { - public string? Sunrise { get; set; } - public double Lng { get; set; } - public double Lat { get; set; } - public string? CountryCode { get; set; } - public double GmtOffset { get; set; } - public double RawOffset { get; set; } - public string? Sunset { get; set; } - public string? TimezoneId { get; set; } - public double DstOffset { get; set; } - public string? CountryName { get; set; } - public string? Time { get; set; } - } - - private const string timezoneApiUrl = "http://api.geonames.org/timezoneJSON"; - private const string timezoneApiUserName = "asbautodrilling"; - - public SimpleTimezoneDto? GetOrDefaultByCoordinates(double latitude, double longitude) - => GetOrDefaultByCoordinatesAsync(latitude, longitude, default).Result; - - public async Task GetOrDefaultByCoordinatesAsync(double latitude, double longitude, CancellationToken token) - { - var lat = latitude.ToString(System.Globalization.CultureInfo.InvariantCulture); - var lng = longitude.ToString(System.Globalization.CultureInfo.InvariantCulture); - - var url = - $"{timezoneApiUrl}?lat={lat}&lng={lng}&username={timezoneApiUserName}"; - - using var client = new HttpClient(); - - var response = await client.GetAsync(url, token) - .ConfigureAwait(false); - - var responseJson = await response.Content.ReadAsStringAsync(token) - .ConfigureAwait(false); - - if (!(responseJson.Contains("timezoneId") && responseJson.Contains("dstOffset"))) - return null; - - var options = new JsonSerializerOptions - { - PropertyNameCaseInsensitive = true - }; - var timezoneInfo = JsonSerializer.Deserialize(responseJson, options); - - if(timezoneInfo is null) - return null; - - return new SimpleTimezoneDto - { - Hours = timezoneInfo.DstOffset, - IsOverride = false, - TimezoneId = timezoneInfo.TimezoneId, - }; - } - - + public string? Sunrise { get; set; } + public double Lng { get; set; } + public double Lat { get; set; } + public string? CountryCode { get; set; } + public double GmtOffset { get; set; } + public double RawOffset { get; set; } + public string? Sunset { get; set; } + public string? TimezoneId { get; set; } + public double DstOffset { get; set; } + public string? CountryName { get; set; } + public string? Time { get; set; } } + + private const string timezoneApiUrl = "http://api.geonames.org/timezoneJSON"; + private const string timezoneApiUserName = "asbautodrilling"; + + public SimpleTimezoneDto? GetOrDefaultByCoordinates(double latitude, double longitude) + => GetOrDefaultByCoordinatesAsync(latitude, longitude, default).Result; + + public async Task GetOrDefaultByCoordinatesAsync(double latitude, double longitude, CancellationToken token) + { + var lat = latitude.ToString(System.Globalization.CultureInfo.InvariantCulture); + var lng = longitude.ToString(System.Globalization.CultureInfo.InvariantCulture); + + var url = + $"{timezoneApiUrl}?lat={lat}&lng={lng}&username={timezoneApiUserName}"; + + using var client = new HttpClient(); + + var response = await client.GetAsync(url, token) + .ConfigureAwait(false); + + var responseJson = await response.Content.ReadAsStringAsync(token) + .ConfigureAwait(false); + + if (!(responseJson.Contains("timezoneId") && responseJson.Contains("dstOffset"))) + return null; + + var options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }; + var timezoneInfo = JsonSerializer.Deserialize(responseJson, options); + + if(timezoneInfo is null) + return null; + + return new SimpleTimezoneDto + { + Hours = timezoneInfo.DstOffset, + IsOverride = false, + TimezoneId = timezoneInfo.TimezoneId, + }; + } + + } diff --git a/AsbCloudInfrastructure/Services/WellContactService.cs b/AsbCloudInfrastructure/Services/WellContactService.cs index 770375f3..3e5bf0af 100644 --- a/AsbCloudInfrastructure/Services/WellContactService.cs +++ b/AsbCloudInfrastructure/Services/WellContactService.cs @@ -11,131 +11,130 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services +namespace AsbCloudInfrastructure.Services; + +public class WellContactService : IWellContactService { - public class WellContactService : IWellContactService + private readonly IAsbCloudDbContext db; + + public WellContactService(IAsbCloudDbContext db) { - private readonly IAsbCloudDbContext db; + this.db = db; + } - public WellContactService(IAsbCloudDbContext db) + public async Task> GetAllAsync(WellContactRequest request, CancellationToken token) + { + var query = db.Contacts + .Where(c => request.IdsWells.Contains(c.IdWell)); + + if (request.ContactTypeId.HasValue) { - this.db = db; - } + query = query.Where(c => c.IdCompanyType == request.ContactTypeId); + }; - public async Task> GetAllAsync(WellContactRequest request, CancellationToken token) + var entities = await query.AsNoTracking() + .ToArrayAsync(token); + + var dtos = entities.Select(c => c.Adapt()); + + return dtos; + } + + public async Task GetAsync(int idWell, int id, CancellationToken token) + { + var dbContact = await GetContact(idWell, id, token); + + var result = dbContact?.Adapt(); + + return result; + } + + public async Task> GetTypesAsync(CancellationToken token) + { + var query = db.CompaniesTypes + .Where(t => t.IsContact) + .OrderBy(t => t.Order); + + var entities = await query.AsNoTracking() + .ToArrayAsync(token); + + var dtos = entities.Adapt>(); + + return dtos; + } + + public async Task InsertAsync(ContactDto contactDto, CancellationToken token) + { + var entity = contactDto.Adapt(); + + db.Contacts.Add(entity); + + await db.SaveChangesAsync(token).ConfigureAwait(false); + return entity.Id; + } + + + public async Task UpdateAsync(ContactDto contactDto, CancellationToken token) + { + var dbContact = await GetContact(contactDto.IdWell, contactDto.Id, token); + if (dbContact is null) + throw new ForbidException("Contact doesn't exist"); + + var entity = contactDto.Adapt(); + db.Contacts.Update(entity); + + return await db.SaveChangesAsync(token); + } + + public async Task DeleteAsync(int idWell, int id, CancellationToken token) + { + var dbContact = await GetContact(idWell, id, token); + if (dbContact is null) + throw new ForbidException("Contact doesn't exist"); + + db.Contacts.Remove(dbContact); + return await db.SaveChangesAsync(token); + } + + public async Task CopyAsync(int idWell, int idWellTarget, IEnumerable contactIds, CancellationToken token) + { + var contacts = await GetContacts(idWell, contactIds, token); + if (!contacts.Any()) + return 0; + + var newContacts = contacts.Select(contact => { - var query = db.Contacts - .Where(c => request.IdsWells.Contains(c.IdWell)); + var newContact = contact.Adapt(); + newContact.IdWell = idWellTarget; + newContact.Id = default; - if (request.ContactTypeId.HasValue) - { - query = query.Where(c => c.IdCompanyType == request.ContactTypeId); - }; + return newContact; + }); - var entities = await query.AsNoTracking() - .ToArrayAsync(token); + db.Contacts.AddRange(newContacts); - var dtos = entities.Select(c => c.Adapt()); + return await db.SaveChangesAsync(token); + } - return dtos; - } + private async Task GetContact(int idWell, int idContact, CancellationToken token) + { + var contact = await db.Contacts + .Where(c => c.IdWell == idWell) + .Where(c => c.Id == idContact) + .AsNoTracking() + .FirstOrDefaultAsync(token); - public async Task GetAsync(int idWell, int id, CancellationToken token) - { - var dbContact = await GetContact(idWell, id, token); + return contact; + } - var result = dbContact?.Adapt(); + private async Task GetContacts(int idWell, IEnumerable contactIds, CancellationToken token) + { + var contacts = await db.Contacts + .Where(c => c.IdWell == idWell) + .Where(c => contactIds.Contains(c.Id)) + .AsNoTracking() + .ToArrayAsync(token); - return result; - } - - public async Task> GetTypesAsync(CancellationToken token) - { - var query = db.CompaniesTypes - .Where(t => t.IsContact) - .OrderBy(t => t.Order); - - var entities = await query.AsNoTracking() - .ToArrayAsync(token); - - var dtos = entities.Adapt>(); - - return dtos; - } - - public async Task InsertAsync(ContactDto contactDto, CancellationToken token) - { - var entity = contactDto.Adapt(); - - db.Contacts.Add(entity); - - await db.SaveChangesAsync(token).ConfigureAwait(false); - return entity.Id; - } - - - public async Task UpdateAsync(ContactDto contactDto, CancellationToken token) - { - var dbContact = await GetContact(contactDto.IdWell, contactDto.Id, token); - if (dbContact is null) - throw new ForbidException("Contact doesn't exist"); - - var entity = contactDto.Adapt(); - db.Contacts.Update(entity); - - return await db.SaveChangesAsync(token); - } - - public async Task DeleteAsync(int idWell, int id, CancellationToken token) - { - var dbContact = await GetContact(idWell, id, token); - if (dbContact is null) - throw new ForbidException("Contact doesn't exist"); - - db.Contacts.Remove(dbContact); - return await db.SaveChangesAsync(token); - } - - public async Task CopyAsync(int idWell, int idWellTarget, IEnumerable contactIds, CancellationToken token) - { - var contacts = await GetContacts(idWell, contactIds, token); - if (!contacts.Any()) - return 0; - - var newContacts = contacts.Select(contact => - { - var newContact = contact.Adapt(); - newContact.IdWell = idWellTarget; - newContact.Id = default; - - return newContact; - }); - - db.Contacts.AddRange(newContacts); - - return await db.SaveChangesAsync(token); - } - - private async Task GetContact(int idWell, int idContact, CancellationToken token) - { - var contact = await db.Contacts - .Where(c => c.IdWell == idWell) - .Where(c => c.Id == idContact) - .AsNoTracking() - .FirstOrDefaultAsync(token); - - return contact; - } - - private async Task GetContacts(int idWell, IEnumerable contactIds, CancellationToken token) - { - var contacts = await db.Contacts - .Where(c => c.IdWell == idWell) - .Where(c => contactIds.Contains(c.Id)) - .AsNoTracking() - .ToArrayAsync(token); - - return contacts; - } + return contacts; } } diff --git a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs index 6e9a9e41..c141e8a6 100644 --- a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs +++ b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs @@ -13,150 +13,148 @@ using System.Threading.Tasks; using AsbCloudApp.Services.Notifications; using AsbCloudDb.Model; -namespace AsbCloudInfrastructure.Services +namespace AsbCloudInfrastructure.Services; + + +/// +/// Сервис "Дело скважины" +/// +public class WellFinalDocumentsService : IWellFinalDocumentsService { + private readonly FileService fileService; + private readonly IUserRepository userRepository; + private readonly IWellService wellService; + private readonly IConfiguration configuration; + private readonly IFileCategoryService fileCategoryService; + private readonly IWellFinalDocumentsRepository wellFinalDocumentsRepository; + private readonly NotificationService notificationService; - /// - /// Сервис "Дело скважины" - /// - public class WellFinalDocumentsService : IWellFinalDocumentsService + public WellFinalDocumentsService(FileService fileService, + IUserRepository userRepository, + IWellService wellService, + IConfiguration configuration, + IFileCategoryService fileCategoryService, + IWellFinalDocumentsRepository wellFinalDocumentsRepository, + NotificationService notificationService) { - private readonly FileService fileService; - private readonly IUserRepository userRepository; - private readonly IWellService wellService; - private readonly IConfiguration configuration; - private readonly IFileCategoryService fileCategoryService; - private readonly IWellFinalDocumentsRepository wellFinalDocumentsRepository; - private readonly NotificationService notificationService; + this.fileService = fileService; + this.userRepository = userRepository; + this.wellService = wellService; + this.configuration = configuration; + this.fileCategoryService = fileCategoryService; + this.wellFinalDocumentsRepository = wellFinalDocumentsRepository; + this.notificationService = notificationService; + } - public WellFinalDocumentsService(FileService fileService, - IUserRepository userRepository, - IWellService wellService, - IConfiguration configuration, - IFileCategoryService fileCategoryService, - IWellFinalDocumentsRepository wellFinalDocumentsRepository, - NotificationService notificationService) + /// + public async Task UpdateRangeAsync(int idWell, IEnumerable dtos, CancellationToken token) + { + var data = await wellFinalDocumentsRepository.UpdateRangeAsync(idWell, dtos, token); + + var message = "от Вас ожидается загрузка на портал документа «{0}»"; + await NotifyUsersAsync(data, message, token); + + return data.Count(); + } + + /// + public async Task SaveCategoryFileAsync(int idWell, int idCategory, int idUser, Stream fileStream, string fileName, CancellationToken token) + { + var dto = await wellFinalDocumentsRepository.GetCategoryAsync(idWell, idCategory, idUser, token) + .ConfigureAwait(false); + + var file = await fileService.SaveAsync(dto.IdWell, dto.IdUser, dto.IdCategory, fileName, + fileStream, token).ConfigureAwait(false); + + return file.Id; + } + + /// + public async Task GetFilesHistoryByIdCategoryAsync(int idWell, int idCategory, CancellationToken token) + { + var request = new FileRequest { - this.fileService = fileService; - this.userRepository = userRepository; - this.wellService = wellService; - this.configuration = configuration; - this.fileCategoryService = fileCategoryService; - this.wellFinalDocumentsRepository = wellFinalDocumentsRepository; - this.notificationService = notificationService; - } + IdWell = idWell, + IdCategory = idCategory, + }; + var files = await fileService.GetInfosAsync(request, token).ConfigureAwait(false); - /// - public async Task UpdateRangeAsync(int idWell, IEnumerable dtos, CancellationToken token) + return new WellFinalDocumentsHistoryDto { + IdWell = idWell, + IdCategory = idCategory, + Files = files + }; + } + + /// + public async Task ReNotifyPublishersAsync(int idWell, int idUser, int idCategory, CancellationToken token) + { + var wellCase = await wellFinalDocumentsRepository.GetByWellIdAsync(idWell, idUser, token); + + if (!wellCase.PermissionToSetPubliher) + throw new ForbidException("Повторная отправка оповещений Вам не разрешена"); + + var requester = await userRepository.GetOrDefaultAsync(idUser, token); + if (requester is null) + throw new ForbidException("Не удается вас опознать"); + + var docs = wellCase.WellFinalDocuments + .Where(doc => doc.IdCategory == idCategory) + .Where(doc => doc.File is null) + .SelectMany(doc => doc.Publishers + .Select(pub => new WellFinalDocumentDBDto { + IdCategory = idCategory, + IdUser = pub.Id, + IdWell = idWell + })); + + if(!docs.Any()) + throw new ArgumentInvalidException(nameof(idCategory), "Нет такой категории, или в нее уже загружен документ"); + + var message = requester.MakeDisplayName() + " ожидает от Вас загрузку на портал документа «{{0}}»"; + await NotifyUsersAsync(docs, message, token); + + return docs.Count(); + } + + private async Task NotifyUsersAsync(IEnumerable dtos, string message, CancellationToken token) + { + foreach (var item in dtos) { - var data = await wellFinalDocumentsRepository.UpdateRangeAsync(idWell, dtos, token); - - var message = "от Вас ожидается загрузка на портал документа «{0}»"; - await NotifyUsersAsync(data, message, token); - - return data.Count(); - } - - /// - public async Task SaveCategoryFileAsync(int idWell, int idCategory, int idUser, Stream fileStream, string fileName, CancellationToken token) - { - var dto = await wellFinalDocumentsRepository.GetCategoryAsync(idWell, idCategory, idUser, token) - .ConfigureAwait(false); - - var file = await fileService.SaveAsync(dto.IdWell, dto.IdUser, dto.IdCategory, fileName, - fileStream, token).ConfigureAwait(false); - - return file.Id; - } - - /// - public async Task GetFilesHistoryByIdCategoryAsync(int idWell, int idCategory, CancellationToken token) - { - var request = new FileRequest + var user = await userRepository.GetOrDefaultAsync(item.IdUser, token); + if (user?.Email is not null) { - IdWell = idWell, - IdCategory = idCategory, - }; - var files = await fileService.GetInfosAsync(request, token).ConfigureAwait(false); + var category = await fileCategoryService.GetOrDefaultAsync(item.IdCategory, token); + var well = await wellService.GetOrDefaultAsync(item.IdWell, token) + ?? throw new ArgumentInvalidException(nameof(item.IdWell), "idWell doesn`t exist"); - return new WellFinalDocumentsHistoryDto { - IdWell = idWell, - IdCategory = idCategory, - Files = files - }; - } - - /// - public async Task ReNotifyPublishersAsync(int idWell, int idUser, int idCategory, CancellationToken token) - { - var wellCase = await wellFinalDocumentsRepository.GetByWellIdAsync(idWell, idUser, token); - - if (!wellCase.PermissionToSetPubliher) - throw new ForbidException("Повторная отправка оповещений Вам не разрешена"); - - var requester = await userRepository.GetOrDefaultAsync(idUser, token); - if (requester is null) - throw new ForbidException("Не удается вас опознать"); - - var docs = wellCase.WellFinalDocuments - .Where(doc => doc.IdCategory == idCategory) - .Where(doc => doc.File is null) - .SelectMany(doc => doc.Publishers - .Select(pub => new WellFinalDocumentDBDto { - IdCategory = idCategory, - IdUser = pub.Id, - IdWell = idWell - })); - - if(!docs.Any()) - throw new ArgumentInvalidException(nameof(idCategory), "Нет такой категории, или в нее уже загружен документ"); - - var message = requester.MakeDisplayName() + " ожидает от Вас загрузку на портал документа «{{0}}»"; - await NotifyUsersAsync(docs, message, token); - - return docs.Count(); - } - - private async Task NotifyUsersAsync(IEnumerable dtos, string message, CancellationToken token) - { - foreach (var item in dtos) - { - var user = await userRepository.GetOrDefaultAsync(item.IdUser, token); - if (user?.Email is not null) - { - var category = await fileCategoryService.GetOrDefaultAsync(item.IdCategory, token); - var well = await wellService.GetOrDefaultAsync(item.IdWell, token) - ?? throw new ArgumentInvalidException(nameof(item.IdWell), "idWell doesn`t exist"); - - await SendMessageAsync(well, user, category?.Name ?? string.Empty, message, - token); - } + await SendMessageAsync(well, user, category?.Name ?? string.Empty, message, + token); } } - - private async Task SendMessageAsync(WellDto well, UserDto user, string documentCategory, string message, - CancellationToken cancellationToken) - { - const int idTransportType = 1; - - var factory = new WellFinalDocumentMailBodyFactory(configuration); - var subject = factory.MakeSubject(well, documentCategory); - - var body = factory.MakeMailBodyForWellFinalDocument( - well, - (user.Name ?? user.Surname ?? string.Empty), - string.Format(message, documentCategory) - ); - - await notificationService.NotifyAsync(new NotifyRequest - { - IdUser = user.Id, - IdNotificationCategory = NotificationCategory.IdSystemNotificationCategory, - Title = subject, - Message = body, - IdTransportType = idTransportType - }, cancellationToken); - } } + private async Task SendMessageAsync(WellDto well, UserDto user, string documentCategory, string message, + CancellationToken cancellationToken) + { + const int idTransportType = 1; + + var factory = new WellFinalDocumentMailBodyFactory(configuration); + var subject = factory.MakeSubject(well, documentCategory); + + var body = factory.MakeMailBodyForWellFinalDocument( + well, + (user.Name ?? user.Surname ?? string.Empty), + string.Format(message, documentCategory) + ); + + await notificationService.NotifyAsync(new NotifyRequest + { + IdUser = user.Id, + IdNotificationCategory = NotificationCategory.IdSystemNotificationCategory, + Title = subject, + Message = body, + IdTransportType = idTransportType + }, cancellationToken); + } } diff --git a/AsbCloudInfrastructure/Services/WellOperationService/Race.cs b/AsbCloudInfrastructure/Services/WellOperationService/Race.cs index e50ef9a9..0de9b26a 100644 --- a/AsbCloudInfrastructure/Services/WellOperationService/Race.cs +++ b/AsbCloudInfrastructure/Services/WellOperationService/Race.cs @@ -3,65 +3,63 @@ using System; using System.Collections.Generic; using System.Linq; -namespace AsbCloudInfrastructure.Services.WellOperationService +namespace AsbCloudInfrastructure.Services.WellOperationService; + + +class Race { + /// + /// Дата начала рейса + /// + public DateTime StartDate { get; set; } - class Race - { - /// - /// Дата начала рейса - /// - public DateTime StartDate { get; set; } + /// + /// Глубина начала рейса, м + /// + public double StartWellDepth { get; set; } - /// - /// Глубина начала рейса, м - /// - public double StartWellDepth { get; set; } + /// + /// Дата окончания рейса + /// + public DateTime EndDate { get; set; } - /// - /// Дата окончания рейса - /// - public DateTime EndDate { get; set; } + /// + /// Глубина окончания рейса, м + /// + public double EndWellDepth { get; set; } - /// - /// Глубина окончания рейса, м - /// - public double EndWellDepth { get; set; } + /// + /// Время рейса, часы + /// + public double DrillingTime { get; set; } - /// - /// Время рейса, часы - /// - public double DrillingTime { get; set; } + /// + /// Время НПВ, часы + /// + public double NonProductiveHours { get; set; } - /// - /// Время НПВ, часы - /// - public double NonProductiveHours { get; set; } + /// + /// Ремонт, часы + /// + public double RepairHours { get; set; } - /// - /// Ремонт, часы - /// - public double RepairHours { get; set; } + /// + /// проходка за рейс, м + /// + public double DeltaDepth => EndWellDepth - StartWellDepth; - /// - /// проходка за рейс, м - /// - public double DeltaDepth => EndWellDepth - StartWellDepth; - - /// - /// Полное время рейса, часы - /// - public double DeltaHours => (EndDate - StartDate).TotalHours; - - /// - /// Скорость за рейс, м/час - /// - public double Speed => DeltaDepth / (DeltaHours - NonProductiveHours - RepairHours + double.Epsilon); - - /// - /// Список операций за рейс - /// - public List Operations { get; internal set; } = new List(); - } + /// + /// Полное время рейса, часы + /// + public double DeltaHours => (EndDate - StartDate).TotalHours; + /// + /// Скорость за рейс, м/час + /// + public double Speed => DeltaDepth / (DeltaHours - NonProductiveHours - RepairHours + double.Epsilon); + + /// + /// Список операций за рейс + /// + public List Operations { get; internal set; } = new List(); } diff --git a/AsbCloudInfrastructure/Services/WellOperationService/ScheduleReportService.cs b/AsbCloudInfrastructure/Services/WellOperationService/ScheduleReportService.cs index aee3c9d1..2b053e03 100644 --- a/AsbCloudInfrastructure/Services/WellOperationService/ScheduleReportService.cs +++ b/AsbCloudInfrastructure/Services/WellOperationService/ScheduleReportService.cs @@ -11,377 +11,375 @@ using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data.WellOperation; -namespace AsbCloudInfrastructure.Services.WellOperationService +namespace AsbCloudInfrastructure.Services.WellOperationService; + +public class ScheduleReportService : IScheduleReportService { - public class ScheduleReportService : IScheduleReportService + private readonly IWellOperationService wellOperationService; + private readonly IWellService wellService; + const string sheetNameSchedule = "Сетевой график"; + const string sheetNameSchedulePlan = "План"; + const string sheetNameScheduleFact = "Факт"; + const string sheetNameSchedulePrediction = "Прогноз"; + const string sheetNameTvd = "ГГД"; + const int maxChartsToWrap = 88; + + public ScheduleReportService(IWellOperationService wellOperationService, IWellService wellService) { - private readonly IWellOperationService wellOperationService; - private readonly IWellService wellService; - const string sheetNameSchedule = "Сетевой график"; - const string sheetNameSchedulePlan = "План"; - const string sheetNameScheduleFact = "Факт"; - const string sheetNameSchedulePrediction = "Прогноз"; - const string sheetNameTvd = "ГГД"; - const int maxChartsToWrap = 88; + this.wellOperationService = wellOperationService; + this.wellService = wellService; + } - public ScheduleReportService(IWellOperationService wellOperationService, IWellService wellService) + public async Task MakeReportAsync(int idWell, CancellationToken token = default) + { + var tvd = await wellOperationService.GetTvdAsync(idWell, token); + + var well = await wellService.GetOrDefaultAsync(idWell, token) + ?? throw new ArgumentInvalidException(nameof(idWell), "idWell doesn`t exist"); + + var ecxelTemplateStream = GetExcelTemplateStream(); + using var workbook = new XLWorkbook(ecxelTemplateStream); + FillScheduleSheetToWorkbook(workbook, tvd, well); + FillTvdSheetToWorkbook(workbook, tvd, well); + MemoryStream memoryStream = new MemoryStream(); + workbook.SaveAs(memoryStream, new SaveOptions { }); + memoryStream.Seek(0, SeekOrigin.Begin); + return memoryStream; + } + + private static void FillScheduleSheetToWorkbook(XLWorkbook workbook, IEnumerable> tvd, WellDto well) + { + FillScheduleSheet(workbook, tvd, well); + + var tvdList = tvd.ToList(); + var plans = tvd + .Where(t => t.Plan is not null) + .Select(t => t.Plan!) + .OrderBy(t => t.DateStart); + FillCurrentScheduleSheet(workbook, plans, sheetNameSchedulePlan); + + var facts = tvd + .Where(t => t.Fact is not null) + .Select(t => t.Fact!) + .OrderBy(t => t.DateStart); + FillCurrentScheduleSheet(workbook, facts, sheetNameScheduleFact); + + var predictions = tvd + .Where(t => t.Predict is not null) + .Select(t => t.Predict!) + .OrderBy(t => t.DateStart); + FillCurrentScheduleSheet(workbook, predictions, sheetNameSchedulePrediction); + } + + private static void FillCurrentScheduleSheet(XLWorkbook workbook, IEnumerable tvdList, string sheetName) + { + var sheet = workbook.GetWorksheet(sheetName); + + const int headerRowsCount = 6; + + const int columnRowNumber = 2; + const int columnCaption = 3; + const int columnWellDepthStart = 4; + const int columnWellDepthEnd = 5; + const int columnDuration = 6; + const int columnDateStart = 7; + const int columnDateEnd = 8; + + int i = 1; + foreach (var tvdItem in tvdList) { - this.wellOperationService = wellOperationService; - this.wellService = wellService; - } - - public async Task MakeReportAsync(int idWell, CancellationToken token = default) - { - var tvd = await wellOperationService.GetTvdAsync(idWell, token); - - var well = await wellService.GetOrDefaultAsync(idWell, token) - ?? throw new ArgumentInvalidException(nameof(idWell), "idWell doesn`t exist"); - - var ecxelTemplateStream = GetExcelTemplateStream(); - using var workbook = new XLWorkbook(ecxelTemplateStream); - FillScheduleSheetToWorkbook(workbook, tvd, well); - FillTvdSheetToWorkbook(workbook, tvd, well); - MemoryStream memoryStream = new MemoryStream(); - workbook.SaveAs(memoryStream, new SaveOptions { }); - memoryStream.Seek(0, SeekOrigin.Begin); - return memoryStream; - } - - private static void FillScheduleSheetToWorkbook(XLWorkbook workbook, IEnumerable> tvd, WellDto well) - { - FillScheduleSheet(workbook, tvd, well); - - var tvdList = tvd.ToList(); - var plans = tvd - .Where(t => t.Plan is not null) - .Select(t => t.Plan!) - .OrderBy(t => t.DateStart); - FillCurrentScheduleSheet(workbook, plans, sheetNameSchedulePlan); - - var facts = tvd - .Where(t => t.Fact is not null) - .Select(t => t.Fact!) - .OrderBy(t => t.DateStart); - FillCurrentScheduleSheet(workbook, facts, sheetNameScheduleFact); - - var predictions = tvd - .Where(t => t.Predict is not null) - .Select(t => t.Predict!) - .OrderBy(t => t.DateStart); - FillCurrentScheduleSheet(workbook, predictions, sheetNameSchedulePrediction); - } - - private static void FillCurrentScheduleSheet(XLWorkbook workbook, IEnumerable tvdList, string sheetName) - { - var sheet = workbook.GetWorksheet(sheetName); - - const int headerRowsCount = 6; - - const int columnRowNumber = 2; - const int columnCaption = 3; - const int columnWellDepthStart = 4; - const int columnWellDepthEnd = 5; - const int columnDuration = 6; - const int columnDateStart = 7; - const int columnDateEnd = 8; - - int i = 1; - foreach (var tvdItem in tvdList) - { - var row = sheet.Row(i + headerRowsCount); - SetCell(row, columnRowNumber, $"{i}"); - SetCell(row, columnCaption, $"{tvdItem.OperationCategoryName} {tvdItem.CategoryInfo}".Trim()); - SetCell(row, columnWellDepthStart, tvdItem.DepthStart); - SetCell(row, columnWellDepthEnd, tvdItem.DepthEnd); - SetCell(row, columnDuration, tvdItem.DurationHours); - SetCell(row, columnDateStart, tvdItem.DateStart); - SetCell(row, columnDateEnd, tvdItem.DateStart.AddHours(tvdItem.DurationHours)); - i++; - } - } - - private static void FillScheduleSheet(XLWorkbook workbook, IEnumerable> tvd, WellDto well) - { - var sheet = workbook.GetWorksheet(sheetNameSchedule); - - const int headerRowsCount = 6; - const int rowTitle = 3; - - const int columnRowNumber = 2; - const int columnCaption = 3; - const int columnWellDepthStartPlan = 4; - const int columnWellDepthStartFact = 5; - const int columnWellDepthStartPredict = 6; - const int columnWellDepthEndPlan = 7; - const int columnWellDepthEndFact = 8; - const int columnWellDepthEndPredict = 9; - const int columnDeltaWellDepthPerDay = 10; - const int columnDurationPlan = 11; - const int columnDurationFact = 12; - const int columnDurationPredict = 13; - const int columnDateStartPlan = 14; - const int columnDateStartFact = 15; - const int columnDateStartPredict = 16; - const int columnDateEndPlan = 17; - const int columnDateEndFact = 18; - const int columnDateEndPredict = 19; - const int columnGuilty = 20; - const int columnNpt = 21; - - var subTitle = $"на строительство скважины №{well.Caption}, куст: {well.Cluster}, м/р: {well.Deposit}"; - sheet.Row(rowTitle).Cell(3).SetCellValue(subTitle); - - var tvdList = tvd.ToList(); - var facts = tvd - .Where(t => t.Fact is not null) - .Select(t => t.Fact!) - .ToList(); - - DateTimeOffset lastFactDate = default; - var lastFactI = 0; - - int i = 0; - for (; i < tvdList.Count; i++) - { - var tvdItem = tvdList[i]; - var operation = tvdItem.Fact ?? tvdItem.Plan; - if (operation is null) - continue; - - var row = sheet.Row(1 + i + headerRowsCount); - - SetCell(row, columnRowNumber, $"{1 + i}"); - SetCell(row, columnCaption, $"{operation.OperationCategoryName} {operation.CategoryInfo}".Trim()); - - SetCell(row, columnWellDepthStartPlan, tvdItem.Plan?.DepthStart); - SetCell(row, columnWellDepthStartFact, tvdItem.Fact?.DepthStart); - SetCell(row, columnWellDepthStartPredict, tvdItem.Predict?.DepthStart); - - SetCell(row, columnWellDepthEndPlan, tvdItem.Plan?.DepthEnd); - SetCell(row, columnWellDepthEndFact, tvdItem.Fact?.DepthEnd); - SetCell(row, columnWellDepthEndPredict, tvdItem.Predict?.DepthEnd); - - SetCell(row, columnDeltaWellDepthPerDay, null); - if (tvdItem.Fact is not null) - { - var fact = tvdItem.Fact; - if (lastFactDate == default) - lastFactDate = fact.DateStart; - - if (i > 0 && fact.DateStart.DayOfYear != lastFactDate.DayOfYear) - { - var daylyOperations = facts - .Where(t => t.DateStart >= lastFactDate && t.DateStart < fact.DateStart); - if (daylyOperations.Any()) - { - var depthDayStart = daylyOperations.Min(o => o.DepthStart); - var depthDayEnd = daylyOperations.Max(o => o.DepthEnd); - var delta = depthDayEnd - depthDayStart; - SetCell(sheet.Row(1 + lastFactI + headerRowsCount), columnDeltaWellDepthPerDay, delta); - lastFactDate = fact.DateStart; - } - } - lastFactI = i; - } - - SetCell(row, columnDurationPlan, tvdItem.Plan?.DurationHours); - SetCell(row, columnDurationFact, tvdItem.Fact?.DurationHours); - SetCell(row, columnDurationPredict, tvdItem.Predict?.DurationHours); - - SetCell(row, columnDateStartPlan, tvdItem.Plan?.DateStart); - SetCell(row, columnDateStartFact, tvdItem.Fact?.DateStart); - SetCell(row, columnDateStartPredict, tvdItem.Predict?.DateStart); - - SetCell(row, columnDateEndPlan, tvdItem.Plan?.DateStart.AddHours(tvdItem.Plan?.DurationHours ?? 0)); - SetCell(row, columnDateEndFact, tvdItem.Fact?.DateStart.AddHours(tvdItem.Fact?.DurationHours ?? 0)); - SetCell(row, columnDateEndPredict, tvdItem.Predict?.DateStart.AddHours(tvdItem.Predict?.DurationHours ?? 0)); - - if (tvdItem.Fact is not null && WellOperationCategory.NonProductiveTimeSubIds.Contains(tvdItem.Fact.IdCategory)) - { - SetCell(row, columnGuilty, tvdItem.Fact.Comment); - SetCell(row, columnNpt, tvdItem.Fact.DurationHours); - row.Row(columnRowNumber, columnNpt).Style.Fill.BackgroundColor = XLColor.Red; - } - else - { - SetCell(row, columnGuilty, null); - SetCell(row, columnNpt, null); - } - } - - var rowNumSummary = 1 + i + headerRowsCount; - var rowNumStart = 1 + headerRowsCount; - var rowNumEnd = i + headerRowsCount; - - string MakeRangeFunction(string funcName, int column) - => $"={funcName}({GetColunmLetter(column)}{rowNumStart}:{GetColunmLetter(column)}{rowNumEnd})"; - - IXLCell AddRangeFormula(IXLRow row, string funcName, int column) - { - var cell = row.Cell(column); - cell.FormulaA1 = MakeRangeFunction(funcName, column); - return cell; - } - - var rowSummary = sheet.Row(rowNumSummary); - rowSummary.Style.Font.Bold = true; - rowSummary.Cell(columnCaption).SetCellValue("Итого:"); - - AddRangeFormula(rowSummary, "sum", columnDeltaWellDepthPerDay); - AddRangeFormula(rowSummary, "sum", columnDurationPlan); - AddRangeFormula(rowSummary, "sum", columnDurationFact); - var cell = AddRangeFormula(rowSummary, "max", columnDateEndPlan); - SetDateTime(cell); - cell = AddRangeFormula(rowSummary, "max", columnDateEndFact); - SetDateTime(cell); - AddRangeFormula(rowSummary, "sum", columnNpt); - SetBorder(rowSummary.Cells(true).Style); - - var rowSummary2 = sheet.Row(rowNumSummary + 1); - rowSummary2.Style.NumberFormat.Format = "0,00"; - rowSummary2.Cell(columnCaption).SetCellValue("в сутках:"); - rowSummary2.Cell(columnDurationPlan).FormulaA1 = $"={GetColunmLetter(columnDurationPlan)}{rowNumSummary}/24"; - SetNumber(rowSummary2.Cell(columnDurationPlan)); - rowSummary2.Cell(columnDurationFact).FormulaA1 = $"={GetColunmLetter(columnDurationFact)}{rowNumSummary}/24"; - SetNumber(rowSummary2.Cell(columnDurationFact)); - rowSummary2.Cell(columnNpt).FormulaA1 = $"={GetColunmLetter(columnNpt)}{rowNumSummary}/24"; - SetNumber(rowSummary2.Cell(columnNpt)); - SetBorder(rowSummary2.Cells(true).Style); - } - - private static void FillTvdSheetToWorkbook(XLWorkbook workbook, IEnumerable> tvd, WellDto well) - { - var sheet = workbook.GetWorksheet(sheetNameTvd); - - const int rowTitle = 2; - const int rowSubtitle = 3; - const int colTitle = 5; - - const int rowTopStatTitle = 2; - const int colTopStatvalue = 10; - - const int colBottomStatvalue = 3; - const int rowStartDateFact = 43; - const int rowEndDatePlan = 44; - const int rowEndDateFact = 45; - - sheet.Row(rowSubtitle).Cell(colTitle).Value - = $"скважины №{well.Caption}, куст: {well.Cluster}, м/р: {well.Deposit}"; - - SetCell(sheet.Row(rowTitle), colTopStatvalue, DateTime.Now); - - var Plan = tvd.Where(t => t.Plan is not null) - .Select(t => t.Plan); - var Fact = tvd.Where(t => t.Fact is not null) - .Select(t => t.Fact); - var Predict = tvd.Where(t => t.Predict is not null) - .Select(t => t.Predict); - - var startDateFact = Fact.FirstOrDefault()?.DateStart; - var planLast = Plan.LastOrDefault(); - var factLast = Fact.LastOrDefault(); - var predictLast = Predict.LastOrDefault(); - - static DateTime GetEndDate(WellOperationDto operation) - => operation is not null - ? operation.DateStart.Date.AddHours(operation.DurationHours) - : default; - - var endDatePlan = planLast is not null ? GetEndDate(planLast) : default; - var endDateFact = factLast is not null ? GetEndDate(factLast) : default; - var endDatePredict = predictLast is not null ? GetEndDate(predictLast) : default; - - var endDate = endDatePredict > endDateFact - ? endDatePredict - : endDateFact; - - if (startDateFact is not null) - { - SetCell(sheet.Row(rowStartDateFact), colBottomStatvalue, startDateFact); - SetCell(sheet.Row(rowEndDatePlan), colBottomStatvalue, endDatePlan); - SetCell(sheet.Row(rowEndDateFact), colBottomStatvalue, endDate); - if (endDate != default) - { - var deltaEndDate = (endDatePlan - endDate).TotalDays; - SetCell(sheet.Row(rowTopStatTitle + 1), colTopStatvalue, Math.Abs(deltaEndDate)); - if (deltaEndDate >= 0) - SetCell(sheet.Row(rowTopStatTitle + 1), colTopStatvalue - 1, "+") - .Style.Font.SetFontColor(XLColor.Green); - else - SetCell(sheet.Row(rowTopStatTitle + 1), colTopStatvalue - 1, "-") - .Style.Font.SetFontColor(XLColor.Red); - } - } - } - - private static string GetColunmLetter(int columnNumber) - { - string letter = ""; - - while (columnNumber > 0) - { - int modulo = (columnNumber - 1) % 26; - letter = Convert.ToChar('A' + modulo) + letter; - columnNumber = (columnNumber - modulo) / 26; - } - - return letter; - } - - private static IXLStyle SetBorder(IXLStyle style) - { - style.Border.RightBorder = XLBorderStyleValues.Thin; - style.Border.LeftBorder = XLBorderStyleValues.Thin; - style.Border.TopBorder = XLBorderStyleValues.Thin; - style.Border.BottomBorder = XLBorderStyleValues.Thin; - style.Border.InsideBorder = XLBorderStyleValues.Thin; - return style; - } - - private static IXLCell SetDateTime(IXLCell cell) - { - cell.Style.DateFormat.Format = "DD.MM.YYYY HH:MM:SS"; - return cell; - } - - private static IXLCell SetNumber(IXLCell cell) - { - cell.Style.NumberFormat.Format = "0.00"; - return cell; - } - - private static IXLCell SetCell(IXLRow row, int colunm, object? value) - { - var cell = row.Cell(colunm); - cell.SetCellValue(value); - - SetBorder(cell.Style); - cell.Style.Alignment.WrapText = true; - - if (value is string valueString && valueString.Length > maxChartsToWrap) - { - var baseHeight = row.Height; - row.Height = 0.82d * baseHeight * Math.Ceiling(1d + valueString.Length / maxChartsToWrap); - } - - if (value is DateTime) - { - SetDateTime(cell); - } - else if (value is IFormattable) - { - SetNumber(cell); - } - - return cell; - } - - private static Stream GetExcelTemplateStream() - { - var stream = System.Reflection.Assembly.GetExecutingAssembly() - .GetManifestResourceStream("AsbCloudInfrastructure.Services.WellOperationService.ScheduleReportTemplate.xlsx")!; - return stream; + var row = sheet.Row(i + headerRowsCount); + SetCell(row, columnRowNumber, $"{i}"); + SetCell(row, columnCaption, $"{tvdItem.OperationCategoryName} {tvdItem.CategoryInfo}".Trim()); + SetCell(row, columnWellDepthStart, tvdItem.DepthStart); + SetCell(row, columnWellDepthEnd, tvdItem.DepthEnd); + SetCell(row, columnDuration, tvdItem.DurationHours); + SetCell(row, columnDateStart, tvdItem.DateStart); + SetCell(row, columnDateEnd, tvdItem.DateStart.AddHours(tvdItem.DurationHours)); + i++; } } + private static void FillScheduleSheet(XLWorkbook workbook, IEnumerable> tvd, WellDto well) + { + var sheet = workbook.GetWorksheet(sheetNameSchedule); + + const int headerRowsCount = 6; + const int rowTitle = 3; + + const int columnRowNumber = 2; + const int columnCaption = 3; + const int columnWellDepthStartPlan = 4; + const int columnWellDepthStartFact = 5; + const int columnWellDepthStartPredict = 6; + const int columnWellDepthEndPlan = 7; + const int columnWellDepthEndFact = 8; + const int columnWellDepthEndPredict = 9; + const int columnDeltaWellDepthPerDay = 10; + const int columnDurationPlan = 11; + const int columnDurationFact = 12; + const int columnDurationPredict = 13; + const int columnDateStartPlan = 14; + const int columnDateStartFact = 15; + const int columnDateStartPredict = 16; + const int columnDateEndPlan = 17; + const int columnDateEndFact = 18; + const int columnDateEndPredict = 19; + const int columnGuilty = 20; + const int columnNpt = 21; + + var subTitle = $"на строительство скважины №{well.Caption}, куст: {well.Cluster}, м/р: {well.Deposit}"; + sheet.Row(rowTitle).Cell(3).SetCellValue(subTitle); + + var tvdList = tvd.ToList(); + var facts = tvd + .Where(t => t.Fact is not null) + .Select(t => t.Fact!) + .ToList(); + + DateTimeOffset lastFactDate = default; + var lastFactI = 0; + + int i = 0; + for (; i < tvdList.Count; i++) + { + var tvdItem = tvdList[i]; + var operation = tvdItem.Fact ?? tvdItem.Plan; + if (operation is null) + continue; + + var row = sheet.Row(1 + i + headerRowsCount); + + SetCell(row, columnRowNumber, $"{1 + i}"); + SetCell(row, columnCaption, $"{operation.OperationCategoryName} {operation.CategoryInfo}".Trim()); + + SetCell(row, columnWellDepthStartPlan, tvdItem.Plan?.DepthStart); + SetCell(row, columnWellDepthStartFact, tvdItem.Fact?.DepthStart); + SetCell(row, columnWellDepthStartPredict, tvdItem.Predict?.DepthStart); + + SetCell(row, columnWellDepthEndPlan, tvdItem.Plan?.DepthEnd); + SetCell(row, columnWellDepthEndFact, tvdItem.Fact?.DepthEnd); + SetCell(row, columnWellDepthEndPredict, tvdItem.Predict?.DepthEnd); + + SetCell(row, columnDeltaWellDepthPerDay, null); + if (tvdItem.Fact is not null) + { + var fact = tvdItem.Fact; + if (lastFactDate == default) + lastFactDate = fact.DateStart; + + if (i > 0 && fact.DateStart.DayOfYear != lastFactDate.DayOfYear) + { + var daylyOperations = facts + .Where(t => t.DateStart >= lastFactDate && t.DateStart < fact.DateStart); + if (daylyOperations.Any()) + { + var depthDayStart = daylyOperations.Min(o => o.DepthStart); + var depthDayEnd = daylyOperations.Max(o => o.DepthEnd); + var delta = depthDayEnd - depthDayStart; + SetCell(sheet.Row(1 + lastFactI + headerRowsCount), columnDeltaWellDepthPerDay, delta); + lastFactDate = fact.DateStart; + } + } + lastFactI = i; + } + + SetCell(row, columnDurationPlan, tvdItem.Plan?.DurationHours); + SetCell(row, columnDurationFact, tvdItem.Fact?.DurationHours); + SetCell(row, columnDurationPredict, tvdItem.Predict?.DurationHours); + + SetCell(row, columnDateStartPlan, tvdItem.Plan?.DateStart); + SetCell(row, columnDateStartFact, tvdItem.Fact?.DateStart); + SetCell(row, columnDateStartPredict, tvdItem.Predict?.DateStart); + + SetCell(row, columnDateEndPlan, tvdItem.Plan?.DateStart.AddHours(tvdItem.Plan?.DurationHours ?? 0)); + SetCell(row, columnDateEndFact, tvdItem.Fact?.DateStart.AddHours(tvdItem.Fact?.DurationHours ?? 0)); + SetCell(row, columnDateEndPredict, tvdItem.Predict?.DateStart.AddHours(tvdItem.Predict?.DurationHours ?? 0)); + + if (tvdItem.Fact is not null && WellOperationCategory.NonProductiveTimeSubIds.Contains(tvdItem.Fact.IdCategory)) + { + SetCell(row, columnGuilty, tvdItem.Fact.Comment); + SetCell(row, columnNpt, tvdItem.Fact.DurationHours); + row.Row(columnRowNumber, columnNpt).Style.Fill.BackgroundColor = XLColor.Red; + } + else + { + SetCell(row, columnGuilty, null); + SetCell(row, columnNpt, null); + } + } + + var rowNumSummary = 1 + i + headerRowsCount; + var rowNumStart = 1 + headerRowsCount; + var rowNumEnd = i + headerRowsCount; + + string MakeRangeFunction(string funcName, int column) + => $"={funcName}({GetColunmLetter(column)}{rowNumStart}:{GetColunmLetter(column)}{rowNumEnd})"; + + IXLCell AddRangeFormula(IXLRow row, string funcName, int column) + { + var cell = row.Cell(column); + cell.FormulaA1 = MakeRangeFunction(funcName, column); + return cell; + } + + var rowSummary = sheet.Row(rowNumSummary); + rowSummary.Style.Font.Bold = true; + rowSummary.Cell(columnCaption).SetCellValue("Итого:"); + + AddRangeFormula(rowSummary, "sum", columnDeltaWellDepthPerDay); + AddRangeFormula(rowSummary, "sum", columnDurationPlan); + AddRangeFormula(rowSummary, "sum", columnDurationFact); + var cell = AddRangeFormula(rowSummary, "max", columnDateEndPlan); + SetDateTime(cell); + cell = AddRangeFormula(rowSummary, "max", columnDateEndFact); + SetDateTime(cell); + AddRangeFormula(rowSummary, "sum", columnNpt); + SetBorder(rowSummary.Cells(true).Style); + + var rowSummary2 = sheet.Row(rowNumSummary + 1); + rowSummary2.Style.NumberFormat.Format = "0,00"; + rowSummary2.Cell(columnCaption).SetCellValue("в сутках:"); + rowSummary2.Cell(columnDurationPlan).FormulaA1 = $"={GetColunmLetter(columnDurationPlan)}{rowNumSummary}/24"; + SetNumber(rowSummary2.Cell(columnDurationPlan)); + rowSummary2.Cell(columnDurationFact).FormulaA1 = $"={GetColunmLetter(columnDurationFact)}{rowNumSummary}/24"; + SetNumber(rowSummary2.Cell(columnDurationFact)); + rowSummary2.Cell(columnNpt).FormulaA1 = $"={GetColunmLetter(columnNpt)}{rowNumSummary}/24"; + SetNumber(rowSummary2.Cell(columnNpt)); + SetBorder(rowSummary2.Cells(true).Style); + } + + private static void FillTvdSheetToWorkbook(XLWorkbook workbook, IEnumerable> tvd, WellDto well) + { + var sheet = workbook.GetWorksheet(sheetNameTvd); + + const int rowTitle = 2; + const int rowSubtitle = 3; + const int colTitle = 5; + + const int rowTopStatTitle = 2; + const int colTopStatvalue = 10; + + const int colBottomStatvalue = 3; + const int rowStartDateFact = 43; + const int rowEndDatePlan = 44; + const int rowEndDateFact = 45; + + sheet.Row(rowSubtitle).Cell(colTitle).Value + = $"скважины №{well.Caption}, куст: {well.Cluster}, м/р: {well.Deposit}"; + + SetCell(sheet.Row(rowTitle), colTopStatvalue, DateTime.Now); + + var Plan = tvd.Where(t => t.Plan is not null) + .Select(t => t.Plan); + var Fact = tvd.Where(t => t.Fact is not null) + .Select(t => t.Fact); + var Predict = tvd.Where(t => t.Predict is not null) + .Select(t => t.Predict); + + var startDateFact = Fact.FirstOrDefault()?.DateStart; + var planLast = Plan.LastOrDefault(); + var factLast = Fact.LastOrDefault(); + var predictLast = Predict.LastOrDefault(); + + static DateTime GetEndDate(WellOperationDto operation) + => operation is not null + ? operation.DateStart.Date.AddHours(operation.DurationHours) + : default; + + var endDatePlan = planLast is not null ? GetEndDate(planLast) : default; + var endDateFact = factLast is not null ? GetEndDate(factLast) : default; + var endDatePredict = predictLast is not null ? GetEndDate(predictLast) : default; + + var endDate = endDatePredict > endDateFact + ? endDatePredict + : endDateFact; + + if (startDateFact is not null) + { + SetCell(sheet.Row(rowStartDateFact), colBottomStatvalue, startDateFact); + SetCell(sheet.Row(rowEndDatePlan), colBottomStatvalue, endDatePlan); + SetCell(sheet.Row(rowEndDateFact), colBottomStatvalue, endDate); + if (endDate != default) + { + var deltaEndDate = (endDatePlan - endDate).TotalDays; + SetCell(sheet.Row(rowTopStatTitle + 1), colTopStatvalue, Math.Abs(deltaEndDate)); + if (deltaEndDate >= 0) + SetCell(sheet.Row(rowTopStatTitle + 1), colTopStatvalue - 1, "+") + .Style.Font.SetFontColor(XLColor.Green); + else + SetCell(sheet.Row(rowTopStatTitle + 1), colTopStatvalue - 1, "-") + .Style.Font.SetFontColor(XLColor.Red); + } + } + } + + private static string GetColunmLetter(int columnNumber) + { + string letter = ""; + + while (columnNumber > 0) + { + int modulo = (columnNumber - 1) % 26; + letter = Convert.ToChar('A' + modulo) + letter; + columnNumber = (columnNumber - modulo) / 26; + } + + return letter; + } + + private static IXLStyle SetBorder(IXLStyle style) + { + style.Border.RightBorder = XLBorderStyleValues.Thin; + style.Border.LeftBorder = XLBorderStyleValues.Thin; + style.Border.TopBorder = XLBorderStyleValues.Thin; + style.Border.BottomBorder = XLBorderStyleValues.Thin; + style.Border.InsideBorder = XLBorderStyleValues.Thin; + return style; + } + + private static IXLCell SetDateTime(IXLCell cell) + { + cell.Style.DateFormat.Format = "DD.MM.YYYY HH:MM:SS"; + return cell; + } + + private static IXLCell SetNumber(IXLCell cell) + { + cell.Style.NumberFormat.Format = "0.00"; + return cell; + } + + private static IXLCell SetCell(IXLRow row, int colunm, object? value) + { + var cell = row.Cell(colunm); + cell.SetCellValue(value); + + SetBorder(cell.Style); + cell.Style.Alignment.WrapText = true; + + if (value is string valueString && valueString.Length > maxChartsToWrap) + { + var baseHeight = row.Height; + row.Height = 0.82d * baseHeight * Math.Ceiling(1d + valueString.Length / maxChartsToWrap); + } + + if (value is DateTime) + { + SetDateTime(cell); + } + else if (value is IFormattable) + { + SetNumber(cell); + } + + return cell; + } + + private static Stream GetExcelTemplateStream() + { + var stream = System.Reflection.Assembly.GetExecutingAssembly() + .GetManifestResourceStream("AsbCloudInfrastructure.Services.WellOperationService.ScheduleReportTemplate.xlsx")!; + return stream; + } } diff --git a/AsbCloudInfrastructure/Services/WellService.cs b/AsbCloudInfrastructure/Services/WellService.cs index baa51b14..ba29dc06 100644 --- a/AsbCloudInfrastructure/Services/WellService.cs +++ b/AsbCloudInfrastructure/Services/WellService.cs @@ -14,344 +14,342 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services +namespace AsbCloudInfrastructure.Services; + +public class WellService : CrudCacheRepositoryBase, IWellService { - public class WellService : CrudCacheRepositoryBase, IWellService + private readonly ITelemetryService telemetryService; + private readonly ICrudRepository companyTypesService; + private readonly ITimezoneService timezoneService; + private readonly WellInfoService wellInfoService; + private readonly IWellOperationRepository wellOperationRepository; + + public ITelemetryService TelemetryService => telemetryService; + + private static IQueryable MakeQueryWell(DbSet dbSet) + => dbSet + .Include(w => w.Cluster) + .ThenInclude(c => c.Deposit) + .Include(w => w.Telemetry) + .Include(w => w.WellType) + .Include(w => w.RelationCompaniesWells) + .ThenInclude(r => r.Company) + .AsNoTracking(); + + public WellService(IAsbCloudDbContext db, + IMemoryCache memoryCache, + ITelemetryService telemetryService, + ITimezoneService timezoneService, + WellInfoService wellInfoService, + IWellOperationCategoryRepository wellOperationCategoryRepository) + : base(db, memoryCache, MakeQueryWell) { - private readonly ITelemetryService telemetryService; - private readonly ICrudRepository companyTypesService; - private readonly ITimezoneService timezoneService; - private readonly WellInfoService wellInfoService; - private readonly IWellOperationRepository wellOperationRepository; - - public ITelemetryService TelemetryService => telemetryService; - - private static IQueryable MakeQueryWell(DbSet dbSet) - => dbSet - .Include(w => w.Cluster) - .ThenInclude(c => c.Deposit) - .Include(w => w.Telemetry) - .Include(w => w.WellType) - .Include(w => w.RelationCompaniesWells) - .ThenInclude(r => r.Company) - .AsNoTracking(); - - public WellService(IAsbCloudDbContext db, - IMemoryCache memoryCache, - ITelemetryService telemetryService, - ITimezoneService timezoneService, - WellInfoService wellInfoService, - IWellOperationCategoryRepository wellOperationCategoryRepository) - : base(db, memoryCache, MakeQueryWell) - { - this.telemetryService = telemetryService; - this.timezoneService = timezoneService; - this.wellInfoService = wellInfoService; - wellOperationRepository = new WellOperationRepository(db, memoryCache, wellOperationCategoryRepository, this); - companyTypesService = new CrudCacheRepositoryBase(dbContext, memoryCache); - } - - private Task> GetCacheRelationCompanyWellAsync(CancellationToken token) - { - return memoryCache.GetOrCreateBasicAsync( - dbContext.Set() - .Include(r => r.Company) - .Include(r => r.Well) - , token); - } - - private void DropCacheRelationCompanyWell() - => memoryCache.DropBasic(); - - public DateTimeOffset GetLastTelemetryDate(int idWell) - { - var well = GetOrDefault(idWell); - - if (well?.IdTelemetry is null) - return DateTimeOffset.MinValue; - - var datesRange = telemetryService.GetDatesRange(well.IdTelemetry.Value); - return datesRange.To; - } - - /// - public async Task> GetWellTreeAsync(int idCompany, CancellationToken token) - { - var wells = await GetEntitiesAsync(new() { IdCompany = idCompany }, token); - - var groupedWells = wells - .GroupBy(w => w.Cluster) - .GroupBy(g => g.Key.Deposit); - - var depositTree = groupedWells.Select( - gDeposit => new DepositBranchDto - { - Id = gDeposit.Key.Id, - Caption = gDeposit.Key.Caption, - Latitude = gDeposit.Key.Latitude, - Longitude = gDeposit.Key.Longitude, - Clusters = gDeposit.Select(gCluster => new ClusterBranchDto - { - Id = gCluster.Key.Id, - Caption = gCluster.Key.Caption, - Latitude = gCluster.Key.Latitude ?? gDeposit.Key.Latitude, - Longitude = gCluster.Key.Longitude ?? gDeposit.Key.Longitude, - Wells = gCluster.Select(well => - { - var dto = wellInfoService.FirstOrDefault(w => w.Id == well.Id && well.IdState == 1); - dto ??= well.Adapt(); - dto.Latitude ??= gCluster.Key.Latitude ?? gDeposit.Key.Latitude; - dto.Longitude ??= gCluster.Key.Longitude ?? gDeposit.Key.Longitude; - dto.Companies = well.RelationCompaniesWells.Select(r => Convert(r.Company)); - return dto; - }), - }), - }); - return depositTree; - } - - public async Task GetOrDefaultStatAsync(int idWell, CancellationToken token) - { - var well = await GetOrDefaultAsync(idWell, token); - - if (well is null) - return null; - - var wellInfo = wellInfoService.FirstOrDefault(well => well.Id == idWell); - - if (wellInfo is null) - return well.Adapt(); - - wellInfo.IdState = well.IdState; - return wellInfo; - } - - public async Task> GetAsync(WellRequest request, CancellationToken token) - { - var wells = await GetEntitiesAsync(request, token); - var wellsDtos = wells.Select(Convert); - return wellsDtos; - } - - private async Task> GetEntitiesAsync(WellRequest request, CancellationToken token) - { - var wells = await GetCacheAsync(token); - - if (request.Ids?.Any() == true) - wells = wells.Where(well => request.Ids.Contains(well.Id)); - - if (request.IdCompany.HasValue) - wells = wells.Where(well => well.RelationCompaniesWells.Any(r => r.IdCompany == request.IdCompany.Value)); - - if (request.IdState.HasValue) - wells = wells.Where(well => well.IdState == request.IdState.Value); - - return wells; - } - - public override async Task InsertAsync(WellDto dto, CancellationToken token) - { - if (IsTelemetryAssignedToDifferentWell(dto)) - throw new ArgumentInvalidException(nameof(dto), "Телеметрия уже была привязана к другой скважине."); - - if (dto.Id != 0 && (await GetCacheAsync(token)).Any(w => w.Id == dto.Id)) - throw new ArgumentInvalidException(nameof(dto), $"Нельзя повторно добавить скважину с id: {dto.Id}"); - - var entity = Convert(dto); - - var result = await base.InsertAsync(dto, token); - - if (dto.Companies.Any()) - { - var newRelations = dto.Companies.Select(c => new RelationCompanyWell { IdWell = result, IdCompany = c.Id }); - dbContext.RelationCompaniesWells.AddRange(newRelations); - await dbContext.SaveChangesAsync(token); - DropCacheRelationCompanyWell(); - } - - return result; - } - - public override Task InsertRangeAsync(IEnumerable dtos, CancellationToken token) - { - throw new NotImplementedException(); - } - - public override async Task UpdateAsync(WellDto dto, - CancellationToken token) - { - if (IsTelemetryAssignedToDifferentWell(dto)) - throw new ArgumentInvalidException(nameof(dto), "Телеметрия уже была привязана к другой скважине."); - - var oldRelations = (await GetCacheRelationCompanyWellAsync(token)) - .Where(r => r.IdWell == dto.Id).ToArray(); - - if (dto.Companies.Count() != oldRelations.Length || - dto.Companies.Any(c => oldRelations.All(oldC => oldC.IdCompany != c.Id))) - { - dbContext.RelationCompaniesWells - .RemoveRange(dbContext.RelationCompaniesWells - .Where(r => r.IdWell == dto.Id)); - - DropCacheRelationCompanyWell(); - - var newRelations = dto.Companies - .Select(c => new RelationCompanyWell - { - IdWell = dto.Id, - IdCompany = c.Id - }); - - dbContext.RelationCompaniesWells.AddRange(newRelations); - } - - var result = await base.UpdateAsync(dto, token); - return result; - } - - public async Task IsCompanyInvolvedInWellAsync(int idCompany, int idWell, CancellationToken token) - => (await GetCacheRelationCompanyWellAsync(token)) - .Any(r => r.IdWell == idWell && r.IdCompany == idCompany); - - public async Task GetWellCaptionByIdAsync(int idWell, CancellationToken token) - { - var entity = await GetOrDefaultAsync(idWell, token).ConfigureAwait(false); - return entity!.Caption; - } - - public async Task> GetCompaniesAsync(int idWell, CancellationToken token) - { - var relations = (await GetCacheRelationCompanyWellAsync(token)) - .Where(r => r.IdWell == idWell); - var dtos = relations.Select(r => Convert(r.Company)); - return dtos; - } - - public string GetStateText(int state) - { - return state switch - { - 1 => "В работе", - 2 => "Завершена", - _ => "Неизвестно", - }; - } - - public async Task> GetClusterWellsIdsAsync(int idWell, CancellationToken token) - { - var well = await GetOrDefaultAsync(idWell, token); - - if (well is null) - return Enumerable.Empty(); - - var cache = await GetCacheAsync(token); - - var clusterWellsIds = cache - .Where((w) => w.IdCluster == well.IdCluster) - .Select(w => w.Id); - - return clusterWellsIds; - } - - protected override Well Convert(WellDto dto) - { - var entity = dto.Adapt(); - - entity.IdTelemetry = entity.IdTelemetry ?? dto.IdTelemetry ?? dto.Telemetry?.Id; - - if (dto.Timezone is null) - entity.Timezone = GetTimezone(dto.Id) - .Adapt(); - - return entity; - } - - protected override WellDto Convert(Well entity) - { - var dto = base.Convert(entity); - - if (entity.Timezone is null) - dto.Timezone = GetTimezone(entity.Id); - - dto.StartDate = wellOperationRepository - .GetFirstAndLastFact(entity.Id)?.First?.DateStart; - 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.ToOffset(dto.Timezone.Offset); - dto.Companies = entity.RelationCompaniesWells - .Select(r => Convert(r.Company)) - .ToList(); - return dto; - } - - private CompanyDto Convert(Company entity) - { - var dto = entity.Adapt(); - dto.CompanyTypeCaption = entity.CompanyType?.Caption - ?? companyTypesService.GetOrDefault(entity.IdCompanyType)?.Caption - ?? string.Empty; - return dto; - } - - public SimpleTimezoneDto GetTimezone(int idWell) - { - var cache = GetCache(); - var cacheItem = cache.FirstOrDefault(d => d.Id == idWell) - ?? throw new ArgumentInvalidException(nameof(idWell), $"idWell: {idWell} does not exist."); - return cacheItem.Timezone.Adapt(); - } - - private bool IsTelemetryAssignedToDifferentWell(WellDto wellDto) - { - if (!wellDto.IdTelemetry.HasValue) - return false; - - var existingWellWithAssignedTelemetry = GetCache() - .FirstOrDefault(x => x.IdTelemetry == wellDto.IdTelemetry); - - if (existingWellWithAssignedTelemetry is null) - return false; - - return existingWellWithAssignedTelemetry.Id != wellDto.Id; - } - - private static AsbCloudDb.Model.IMapPoint GetCoordinates(Well well) - { - if (well is null) - throw new ArgumentNullException(nameof(well)); - - if (well.Latitude is not null & well.Longitude is not null) - return well; - - var cluster = well.Cluster; - - if (cluster.Latitude is not null & cluster.Longitude is not null) - return cluster; - - if (cluster.Deposit is null) - throw new Exception($"Can't find coordinates of well by cluster {cluster.Caption} id: {cluster.Id}"); - - var deposit = cluster.Deposit; - - if (deposit.Latitude is not null & deposit.Longitude is not null) - return deposit; - - throw new Exception($"Can't find coordinates of well by deposit {deposit.Caption} id: {deposit.Id}"); - } - - public DatesRangeDto GetDatesRange(int idWell) - { - var well = GetOrDefault(idWell); - if (well is null) - throw new Exception($"Well id: {idWell} does not exist."); - - if (well.IdTelemetry is null) - throw new KeyNotFoundException($"Well id: {idWell} does not contain telemetry."); - - return telemetryService.GetDatesRange((int)well.IdTelemetry); - } + this.telemetryService = telemetryService; + this.timezoneService = timezoneService; + this.wellInfoService = wellInfoService; + wellOperationRepository = new WellOperationRepository(db, memoryCache, wellOperationCategoryRepository, this); + companyTypesService = new CrudCacheRepositoryBase(dbContext, memoryCache); } + private Task> GetCacheRelationCompanyWellAsync(CancellationToken token) + { + return memoryCache.GetOrCreateBasicAsync( + dbContext.Set() + .Include(r => r.Company) + .Include(r => r.Well) + , token); + } + + private void DropCacheRelationCompanyWell() + => memoryCache.DropBasic(); + + public DateTimeOffset GetLastTelemetryDate(int idWell) + { + var well = GetOrDefault(idWell); + + if (well?.IdTelemetry is null) + return DateTimeOffset.MinValue; + + var datesRange = telemetryService.GetDatesRange(well.IdTelemetry.Value); + return datesRange.To; + } + + /// + public async Task> GetWellTreeAsync(int idCompany, CancellationToken token) + { + var wells = await GetEntitiesAsync(new() { IdCompany = idCompany }, token); + + var groupedWells = wells + .GroupBy(w => w.Cluster) + .GroupBy(g => g.Key.Deposit); + + var depositTree = groupedWells.Select( + gDeposit => new DepositBranchDto + { + Id = gDeposit.Key.Id, + Caption = gDeposit.Key.Caption, + Latitude = gDeposit.Key.Latitude, + Longitude = gDeposit.Key.Longitude, + Clusters = gDeposit.Select(gCluster => new ClusterBranchDto + { + Id = gCluster.Key.Id, + Caption = gCluster.Key.Caption, + Latitude = gCluster.Key.Latitude ?? gDeposit.Key.Latitude, + Longitude = gCluster.Key.Longitude ?? gDeposit.Key.Longitude, + Wells = gCluster.Select(well => + { + var dto = wellInfoService.FirstOrDefault(w => w.Id == well.Id && well.IdState == 1); + dto ??= well.Adapt(); + dto.Latitude ??= gCluster.Key.Latitude ?? gDeposit.Key.Latitude; + dto.Longitude ??= gCluster.Key.Longitude ?? gDeposit.Key.Longitude; + dto.Companies = well.RelationCompaniesWells.Select(r => Convert(r.Company)); + return dto; + }), + }), + }); + return depositTree; + } + + public async Task GetOrDefaultStatAsync(int idWell, CancellationToken token) + { + var well = await GetOrDefaultAsync(idWell, token); + + if (well is null) + return null; + + var wellInfo = wellInfoService.FirstOrDefault(well => well.Id == idWell); + + if (wellInfo is null) + return well.Adapt(); + + wellInfo.IdState = well.IdState; + return wellInfo; + } + + public async Task> GetAsync(WellRequest request, CancellationToken token) + { + var wells = await GetEntitiesAsync(request, token); + var wellsDtos = wells.Select(Convert); + return wellsDtos; + } + + private async Task> GetEntitiesAsync(WellRequest request, CancellationToken token) + { + var wells = await GetCacheAsync(token); + + if (request.Ids?.Any() == true) + wells = wells.Where(well => request.Ids.Contains(well.Id)); + + if (request.IdCompany.HasValue) + wells = wells.Where(well => well.RelationCompaniesWells.Any(r => r.IdCompany == request.IdCompany.Value)); + + if (request.IdState.HasValue) + wells = wells.Where(well => well.IdState == request.IdState.Value); + + return wells; + } + + public override async Task InsertAsync(WellDto dto, CancellationToken token) + { + if (IsTelemetryAssignedToDifferentWell(dto)) + throw new ArgumentInvalidException(nameof(dto), "Телеметрия уже была привязана к другой скважине."); + + if (dto.Id != 0 && (await GetCacheAsync(token)).Any(w => w.Id == dto.Id)) + throw new ArgumentInvalidException(nameof(dto), $"Нельзя повторно добавить скважину с id: {dto.Id}"); + + var entity = Convert(dto); + + var result = await base.InsertAsync(dto, token); + + if (dto.Companies.Any()) + { + var newRelations = dto.Companies.Select(c => new RelationCompanyWell { IdWell = result, IdCompany = c.Id }); + dbContext.RelationCompaniesWells.AddRange(newRelations); + await dbContext.SaveChangesAsync(token); + DropCacheRelationCompanyWell(); + } + + return result; + } + + public override Task InsertRangeAsync(IEnumerable dtos, CancellationToken token) + { + throw new NotImplementedException(); + } + + public override async Task UpdateAsync(WellDto dto, + CancellationToken token) + { + if (IsTelemetryAssignedToDifferentWell(dto)) + throw new ArgumentInvalidException(nameof(dto), "Телеметрия уже была привязана к другой скважине."); + + var oldRelations = (await GetCacheRelationCompanyWellAsync(token)) + .Where(r => r.IdWell == dto.Id).ToArray(); + + if (dto.Companies.Count() != oldRelations.Length || + dto.Companies.Any(c => oldRelations.All(oldC => oldC.IdCompany != c.Id))) + { + dbContext.RelationCompaniesWells + .RemoveRange(dbContext.RelationCompaniesWells + .Where(r => r.IdWell == dto.Id)); + + DropCacheRelationCompanyWell(); + + var newRelations = dto.Companies + .Select(c => new RelationCompanyWell + { + IdWell = dto.Id, + IdCompany = c.Id + }); + + dbContext.RelationCompaniesWells.AddRange(newRelations); + } + + var result = await base.UpdateAsync(dto, token); + return result; + } + + public async Task IsCompanyInvolvedInWellAsync(int idCompany, int idWell, CancellationToken token) + => (await GetCacheRelationCompanyWellAsync(token)) + .Any(r => r.IdWell == idWell && r.IdCompany == idCompany); + + public async Task GetWellCaptionByIdAsync(int idWell, CancellationToken token) + { + var entity = await GetOrDefaultAsync(idWell, token).ConfigureAwait(false); + return entity!.Caption; + } + + public async Task> GetCompaniesAsync(int idWell, CancellationToken token) + { + var relations = (await GetCacheRelationCompanyWellAsync(token)) + .Where(r => r.IdWell == idWell); + var dtos = relations.Select(r => Convert(r.Company)); + return dtos; + } + + public string GetStateText(int state) + { + return state switch + { + 1 => "В работе", + 2 => "Завершена", + _ => "Неизвестно", + }; + } + + public async Task> GetClusterWellsIdsAsync(int idWell, CancellationToken token) + { + var well = await GetOrDefaultAsync(idWell, token); + + if (well is null) + return Enumerable.Empty(); + + var cache = await GetCacheAsync(token); + + var clusterWellsIds = cache + .Where((w) => w.IdCluster == well.IdCluster) + .Select(w => w.Id); + + return clusterWellsIds; + } + + protected override Well Convert(WellDto dto) + { + var entity = dto.Adapt(); + + entity.IdTelemetry = entity.IdTelemetry ?? dto.IdTelemetry ?? dto.Telemetry?.Id; + + if (dto.Timezone is null) + entity.Timezone = GetTimezone(dto.Id) + .Adapt(); + + return entity; + } + + protected override WellDto Convert(Well entity) + { + var dto = base.Convert(entity); + + if (entity.Timezone is null) + dto.Timezone = GetTimezone(entity.Id); + + dto.StartDate = wellOperationRepository + .GetFirstAndLastFact(entity.Id)?.First?.DateStart; + 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.ToOffset(dto.Timezone.Offset); + dto.Companies = entity.RelationCompaniesWells + .Select(r => Convert(r.Company)) + .ToList(); + return dto; + } + + private CompanyDto Convert(Company entity) + { + var dto = entity.Adapt(); + dto.CompanyTypeCaption = entity.CompanyType?.Caption + ?? companyTypesService.GetOrDefault(entity.IdCompanyType)?.Caption + ?? string.Empty; + return dto; + } + + public SimpleTimezoneDto GetTimezone(int idWell) + { + var cache = GetCache(); + var cacheItem = cache.FirstOrDefault(d => d.Id == idWell) + ?? throw new ArgumentInvalidException(nameof(idWell), $"idWell: {idWell} does not exist."); + return cacheItem.Timezone.Adapt(); + } + + private bool IsTelemetryAssignedToDifferentWell(WellDto wellDto) + { + if (!wellDto.IdTelemetry.HasValue) + return false; + + var existingWellWithAssignedTelemetry = GetCache() + .FirstOrDefault(x => x.IdTelemetry == wellDto.IdTelemetry); + + if (existingWellWithAssignedTelemetry is null) + return false; + + return existingWellWithAssignedTelemetry.Id != wellDto.Id; + } + + private static AsbCloudDb.Model.IMapPoint GetCoordinates(Well well) + { + if (well is null) + throw new ArgumentNullException(nameof(well)); + + if (well.Latitude is not null & well.Longitude is not null) + return well; + + var cluster = well.Cluster; + + if (cluster.Latitude is not null & cluster.Longitude is not null) + return cluster; + + if (cluster.Deposit is null) + throw new Exception($"Can't find coordinates of well by cluster {cluster.Caption} id: {cluster.Id}"); + + var deposit = cluster.Deposit; + + if (deposit.Latitude is not null & deposit.Longitude is not null) + return deposit; + + throw new Exception($"Can't find coordinates of well by deposit {deposit.Caption} id: {deposit.Id}"); + } + + public DatesRangeDto GetDatesRange(int idWell) + { + var well = GetOrDefault(idWell); + if (well is null) + throw new Exception($"Well id: {idWell} does not exist."); + + if (well.IdTelemetry is null) + throw new KeyNotFoundException($"Well id: {idWell} does not contain telemetry."); + + return telemetryService.GetDatesRange((int)well.IdTelemetry); + } } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WitsInfoService.cs b/AsbCloudInfrastructure/Services/WitsInfoService.cs index 7e8ac40a..7f78fbac 100644 --- a/AsbCloudInfrastructure/Services/WitsInfoService.cs +++ b/AsbCloudInfrastructure/Services/WitsInfoService.cs @@ -1,35 +1,34 @@ using AsbWitsInfo; using System.Collections.Generic; -namespace AsbCloudInfrastructure.Services +namespace AsbCloudInfrastructure.Services; + + +public class WitsInfoService { - - public class WitsInfoService + private readonly InfoService witsInfoService; + public WitsInfoService(IEnumerable? customItems = null, IEnumerable? customRecords = null) { - private readonly InfoService witsInfoService; - public WitsInfoService(IEnumerable? customItems = null, IEnumerable? customRecords = null) - { - witsInfoService = new InfoService(customItems, customRecords); - } + witsInfoService = new InfoService(customItems, customRecords); + } - public object GetItems(int idRecord = -1) - { - object items; - if (idRecord > 0) - items = witsInfoService.ItemInfoStore.Where(i => i.RecordId == idRecord); - else - items = witsInfoService.ItemInfoStore.Where(i => true); - return items; - } + public object GetItems(int idRecord = -1) + { + object items; + if (idRecord > 0) + items = witsInfoService.ItemInfoStore.Where(i => i.RecordId == idRecord); + else + items = witsInfoService.ItemInfoStore.Where(i => true); + return items; + } - public object GetRecords(int idRecord = -1) - { - object items; - if (idRecord > 0) - items = witsInfoService.RecordInfoStore.Where(i => i.RecordId == idRecord); - else - items = witsInfoService.RecordInfoStore.Where(i => true); - return items; - } + public object GetRecords(int idRecord = -1) + { + object items; + if (idRecord > 0) + items = witsInfoService.RecordInfoStore.Where(i => i.RecordId == idRecord); + else + items = witsInfoService.RecordInfoStore.Where(i => true); + return items; } } diff --git a/AsbCloudInfrastructure/Startup.cs b/AsbCloudInfrastructure/Startup.cs index c6a83d17..83eba346 100644 --- a/AsbCloudInfrastructure/Startup.cs +++ b/AsbCloudInfrastructure/Startup.cs @@ -12,62 +12,60 @@ using AsbCloudDb; using AsbCloudApp.Repositories; using AsbCloudInfrastructure.Background.PeriodicWorks; -namespace AsbCloudInfrastructure +namespace AsbCloudInfrastructure; + +public class Startup { - public class Startup + public static void BeforeRunHandler(IHost host) { - public static void BeforeRunHandler(IHost host) - { - using var scope = host.Services.CreateScope(); - var provider = scope.ServiceProvider; + using var scope = host.Services.CreateScope(); + var provider = scope.ServiceProvider; - var context = provider.GetRequiredService(); - context.Database.EnsureCreatedAndMigrated(); + var context = provider.GetRequiredService(); + context.Database.EnsureCreatedAndMigrated(); - // TODO: Сделать инициализацию кеша телеметрии более явной. - _ = provider.GetRequiredService>(); - _ = provider.GetRequiredService>(); + // TODO: Сделать инициализацию кеша телеметрии более явной. + _ = provider.GetRequiredService>(); + _ = provider.GetRequiredService>(); - var backgroundWorker = provider.GetRequiredService(); - backgroundWorker.Add(TimeSpan.FromDays(1)); - backgroundWorker.Add(TimeSpan.FromMinutes(30)); - backgroundWorker.Add(TimeSpan.FromMinutes(0)); - backgroundWorker.Add(TimeSpan.FromMinutes(0)); - backgroundWorker.Add(TimeSpan.FromMinutes(0)); - backgroundWorker.Add(MakeMemoryMonitoringWork(), TimeSpan.FromMinutes(0)); + var backgroundWorker = provider.GetRequiredService(); + backgroundWorker.Add(TimeSpan.FromDays(1)); + backgroundWorker.Add(TimeSpan.FromMinutes(30)); + backgroundWorker.Add(TimeSpan.FromMinutes(0)); + backgroundWorker.Add(TimeSpan.FromMinutes(0)); + backgroundWorker.Add(TimeSpan.FromMinutes(0)); + backgroundWorker.Add(MakeMemoryMonitoringWork(), TimeSpan.FromMinutes(0)); - var notificationBackgroundWorker = provider.GetRequiredService(); - } - - static Work MakeMemoryMonitoringWork() - { - var workAction = (string _, IServiceProvider _, Action _, CancellationToken _) => { - var bytes = GC.GetTotalMemory(false); - var bytesString = FromatBytes(bytes); - System.Diagnostics.Trace.TraceInformation($"Total memory allocated is {bytesString} bytes. DbContext count is:{AsbCloudDbContext.ReferenceCount}"); - return Task.CompletedTask; - }; - var work = Work.CreateByDelegate("Memory monitoring", workAction); - return work; - } - - static string FromatBytes(long bytes) - { - const double gigaByte = 1024 * 1024 * 1024; - const double megaByte = 1024 * 1024; - const double kiloByte = 1024; - - if (bytes > 10 * gigaByte) - return (bytes / gigaByte).ToString("### ### ###.## Gb"); - - if (bytes > 10 * megaByte) - return (bytes / megaByte).ToString("### ### ###.## Mb"); - - if (bytes > 10 * kiloByte) - return (bytes / megaByte).ToString("### ### ###.## Kb"); - - return bytes.ToString("### ### ###"); - } + var notificationBackgroundWorker = provider.GetRequiredService(); } + static Work MakeMemoryMonitoringWork() + { + var workAction = (string _, IServiceProvider _, Action _, CancellationToken _) => { + var bytes = GC.GetTotalMemory(false); + var bytesString = FromatBytes(bytes); + System.Diagnostics.Trace.TraceInformation($"Total memory allocated is {bytesString} bytes. DbContext count is:{AsbCloudDbContext.ReferenceCount}"); + return Task.CompletedTask; + }; + var work = Work.CreateByDelegate("Memory monitoring", workAction); + return work; + } + + static string FromatBytes(long bytes) + { + const double gigaByte = 1024 * 1024 * 1024; + const double megaByte = 1024 * 1024; + const double kiloByte = 1024; + + if (bytes > 10 * gigaByte) + return (bytes / gigaByte).ToString("### ### ###.## Gb"); + + if (bytes > 10 * megaByte) + return (bytes / megaByte).ToString("### ### ###.## Mb"); + + if (bytes > 10 * kiloByte) + return (bytes / megaByte).ToString("### ### ###.## Kb"); + + return bytes.ToString("### ### ###"); + } } diff --git a/AsbCloudWebApi.IntegrationTests/Data/Defaults.cs b/AsbCloudWebApi.IntegrationTests/Data/Defaults.cs index 1d97e6ec..21e3c531 100644 --- a/AsbCloudWebApi.IntegrationTests/Data/Defaults.cs +++ b/AsbCloudWebApi.IntegrationTests/Data/Defaults.cs @@ -1,58 +1,57 @@ using AsbCloudDb.Model; -namespace AsbCloudWebApi.IntegrationTests.Data +namespace AsbCloudWebApi.IntegrationTests.Data; + +[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2211:Поля, не являющиеся константами, не должны быть видимыми", + Justification = "<Ожидание>")] +public static class Defaults { - [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2211:Поля, не являющиеся константами, не должны быть видимыми", - Justification = "<Ожидание>")] - public static class Defaults - { - public static SimpleTimezone Timezone => new() - { - Hours = 1 - }; + public static SimpleTimezone Timezone => new() + { + Hours = 1 + }; - public const string RemoteUid = "555-555-555"; + public const string RemoteUid = "555-555-555"; - public static Deposit[] Deposits => new Deposit[] - { - new() - { - Caption = "Deposit1", - Latitude = 10, - Longitude = 20, - Timezone = Timezone, - Clusters = new[] - { - new Cluster - { - Caption = "Cluster1", - Latitude = 10, - Longitude = 20, - Timezone = Timezone, - Wells = new[] - { - new Well - { - IdWellType = 1, - IdState = 1, - Caption = "Well1", - Latitude = 10, - Longitude = 20, - Timezone = Timezone, - Telemetry = new Telemetry - { - RemoteUid = RemoteUid, - TimeZone = Timezone - }, - RelationCompaniesWells = new RelationCompanyWell[] - { - new() { IdCompany = 1 }, - }, - } - } - } - } - } - }; - } + public static Deposit[] Deposits => new Deposit[] + { + new() + { + Caption = "Deposit1", + Latitude = 10, + Longitude = 20, + Timezone = Timezone, + Clusters = new[] + { + new Cluster + { + Caption = "Cluster1", + Latitude = 10, + Longitude = 20, + Timezone = Timezone, + Wells = new[] + { + new Well + { + IdWellType = 1, + IdState = 1, + Caption = "Well1", + Latitude = 10, + Longitude = 20, + Timezone = Timezone, + Telemetry = new Telemetry + { + RemoteUid = RemoteUid, + TimeZone = Timezone + }, + RelationCompaniesWells = new RelationCompanyWell[] + { + new() { IdCompany = 1 }, + }, + } + } + } + } + } + }; } \ No newline at end of file diff --git a/AsbCloudWebApi.Tests/AspExtensions.cs b/AsbCloudWebApi.Tests/AspExtensions.cs index a7c1aedd..4ccd8204 100644 --- a/AsbCloudWebApi.Tests/AspExtensions.cs +++ b/AsbCloudWebApi.Tests/AspExtensions.cs @@ -1,19 +1,18 @@ using Microsoft.Extensions.DependencyInjection; using System.Linq; -namespace AsbCloudWebApi.Tests +namespace AsbCloudWebApi.Tests; + +public static class AspExtensions { - public static class AspExtensions + public static IServiceCollection ReplaceService(this IServiceCollection services, T instance) + where T : notnull { - public static IServiceCollection ReplaceService(this IServiceCollection services, T instance) - where T : notnull - { - var typeofT = typeof(T); - var originalDecriptor = services.Last(s => s.ServiceType == typeofT); - var newDecriptor = new ServiceDescriptor(typeofT, instance); - services.Remove(originalDecriptor); - services.Add(newDecriptor); - return services; - } + var typeofT = typeof(T); + var originalDecriptor = services.Last(s => s.ServiceType == typeofT); + var newDecriptor = new ServiceDescriptor(typeofT, instance); + services.Remove(originalDecriptor); + services.Add(newDecriptor); + return services; } } diff --git a/AsbCloudWebApi.Tests/ReflectionExtensions.cs b/AsbCloudWebApi.Tests/ReflectionExtensions.cs index 23019890..86d99a1f 100644 --- a/AsbCloudWebApi.Tests/ReflectionExtensions.cs +++ b/AsbCloudWebApi.Tests/ReflectionExtensions.cs @@ -4,44 +4,43 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace AsbCloudWebApi.Tests +namespace AsbCloudWebApi.Tests; + +public static class ReflectionExtensions { - public static class ReflectionExtensions + private static readonly Dictionary _commonTypeDictionary = new() { - private static readonly Dictionary _commonTypeDictionary = new() - { - { typeof(int), default(int) }, - { typeof(Guid), default(Guid) }, - { typeof(DateOnly), default(DateOnly) }, - { typeof(DateTime), default(DateTime) }, - { typeof(DateTimeOffset), default(DateTimeOffset) }, - { typeof(TimeOnly), default(TimeOnly) }, - { typeof(long), default(long) }, - { typeof(bool), default(bool) }, - { typeof(double), default(double) }, - { typeof(short), default(short) }, - { typeof(float), default(float) }, - { typeof(byte), default(byte) }, - { typeof(char), default(char) }, - { typeof(uint), default(uint) }, - { typeof(ushort), default(ushort) }, - { typeof(ulong), default(ulong) }, - { typeof(sbyte), default(sbyte) } - }; + { typeof(int), default(int) }, + { typeof(Guid), default(Guid) }, + { typeof(DateOnly), default(DateOnly) }, + { typeof(DateTime), default(DateTime) }, + { typeof(DateTimeOffset), default(DateTimeOffset) }, + { typeof(TimeOnly), default(TimeOnly) }, + { typeof(long), default(long) }, + { typeof(bool), default(bool) }, + { typeof(double), default(double) }, + { typeof(short), default(short) }, + { typeof(float), default(float) }, + { typeof(byte), default(byte) }, + { typeof(char), default(char) }, + { typeof(uint), default(uint) }, + { typeof(ushort), default(ushort) }, + { typeof(ulong), default(ulong) }, + { typeof(sbyte), default(sbyte) } + }; - public static object? GetDefaultValue(this Type type) + public static object? GetDefaultValue(this Type type) + { + if (!type.IsValueType) { - if (!type.IsValueType) - { - return null; - } - - return _commonTypeDictionary.TryGetValue(type, out var value) - ? value - : Activator.CreateInstance(type); + return null; } - public static bool IsDefaultValue(this Type type, object? value) - => (value?.Equals(type.GetDefaultValue()) != false); + return _commonTypeDictionary.TryGetValue(type, out var value) + ? value + : Activator.CreateInstance(type); } + + public static bool IsDefaultValue(this Type type, object? value) + => (value?.Equals(type.GetDefaultValue()) != false); } diff --git a/AsbCloudWebApi.Tests/Services/Notification/EmailNotificationTransportServiceTests.cs b/AsbCloudWebApi.Tests/Services/Notification/EmailNotificationTransportServiceTests.cs index 0d2974b9..b2b96735 100644 --- a/AsbCloudWebApi.Tests/Services/Notification/EmailNotificationTransportServiceTests.cs +++ b/AsbCloudWebApi.Tests/Services/Notification/EmailNotificationTransportServiceTests.cs @@ -12,61 +12,60 @@ using System.Threading; using System.Threading.Tasks; using Xunit; -namespace AsbCloudWebApi.Tests.Services.Notification +namespace AsbCloudWebApi.Tests.Services.Notification; + +public class EmailNotificationTransportServiceTests { - public class EmailNotificationTransportServiceTests + private IUserRepository userRepository; + private INotificationTransportService notificationTransportService; + + private readonly NotificationDto notification = new NotificationDto() { - private IUserRepository userRepository; - private INotificationTransportService notificationTransportService; + Message = "Message", + Title = "Title", + IdUser = 1, + IdTransportType = 1, + IdState = 0, + RegistrationDate = DateTimeOffset.Now, + IdNotificationCategory = 10000, + }; + private readonly UserExtendedDto user = new UserExtendedDto() + { + Id = 1, + IdCompany = 1, + Email = "studio@yandex.ru", + IdState = 1, + Login = "studio", + Name = "Test", + Patronymic = "Test", + Phone = "22-22-22", + Position = "Test", + Surname = "Test", + }; - private readonly NotificationDto notification = new NotificationDto() - { - Message = "Message", - Title = "Title", - IdUser = 1, - IdTransportType = 1, - IdState = 0, - RegistrationDate = DateTimeOffset.Now, - IdNotificationCategory = 10000, - }; - private readonly UserExtendedDto user = new UserExtendedDto() - { - Id = 1, - IdCompany = 1, - Email = "studio@yandex.ru", - IdState = 1, - Login = "studio", - Name = "Test", - Patronymic = "Test", - Phone = "22-22-22", - Position = "Test", - Surname = "Test", - }; + private static Dictionary configSettings = new() + { + { "email:sender", "bot@digitaldrilling.ru" }, + { "email:password", "8wZrXSfP" }, + { "email:smtpServer", "smtp.timeweb.ru" } + }; - private static Dictionary configSettings = new() - { - { "email:sender", "bot@digitaldrilling.ru" }, - { "email:password", "8wZrXSfP" }, - { "email:smtpServer", "smtp.timeweb.ru" } - }; + public EmailNotificationTransportServiceTests() + { + IConfiguration configuration = new ConfigurationBuilder() + .AddInMemoryCollection(configSettings) + .Build(); - public EmailNotificationTransportServiceTests() - { - IConfiguration configuration = new ConfigurationBuilder() - .AddInMemoryCollection(configSettings) - .Build(); + userRepository = Substitute.For(); - userRepository = Substitute.For(); + notificationTransportService = new EmailNotificationTransportService(configuration, userRepository); + } - notificationTransportService = new EmailNotificationTransportService(configuration, userRepository); - } - - [Fact] - public async Task SendAsyncThrowsMailboxUnavailable() - { - userRepository.GetOrDefaultAsync(Arg.Any(), Arg.Any()).Returns(user); - var exception = await Assert.ThrowsAsync(() => notificationTransportService.SendAsync(notification, CancellationToken.None)); - Assert.Equal(SmtpStatusCode.MailboxUnavailable, exception.StatusCode); - } + [Fact] + public async Task SendAsyncThrowsMailboxUnavailable() + { + userRepository.GetOrDefaultAsync(Arg.Any(), Arg.Any()).Returns(user); + var exception = await Assert.ThrowsAsync(() => notificationTransportService.SendAsync(notification, CancellationToken.None)); + Assert.Equal(SmtpStatusCode.MailboxUnavailable, exception.StatusCode); } } diff --git a/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryExportTest.cs b/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryExportTest.cs index 856d09ae..4c5d76d9 100644 --- a/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryExportTest.cs +++ b/AsbCloudWebApi.Tests/Services/Trajectory/TrajectoryExportTest.cs @@ -9,121 +9,120 @@ using System.Threading.Tasks; using AsbCloudApp.Requests.ExportOptions; using Xunit; -namespace AsbCloudWebApi.Tests.Services.Trajectory +namespace AsbCloudWebApi.Tests.Services.Trajectory; + +public class TrajectoryExportTest { - public class TrajectoryExportTest + private const int idWell = 4; + + private IWellService wellService; + private readonly ITrajectoryEditableRepository trajectoryPlanRepository; + private readonly TrajectoryPlanExportService trajectoryPlanExportService; + + private readonly ITrajectoryEditableRepository trajectoryFactManualReposirory; + private readonly TrajectoryFactManualExportService trajectoryFactManualExportService; + + private readonly ITrajectoryNnbRepository trajectoryFactNnbRepository; + private readonly TrajectoryFactNnbExportService trajectoryFactNnbExportService; + + private readonly TrajectoryGeoPlanDto[] trajectoryPlanRows = new TrajectoryGeoPlanDto[2] { + new TrajectoryGeoPlanDto() { + Id = 1, + AzimuthGeo = 1, + AzimuthMagnetic = 2, + Comment = "комментарий", + IdUser = 1, + IdWell = 4, + Radius = 3, + UpdateDate = DateTimeOffset.Now, + VerticalDepth = 100, + WellboreDepth = 100, + ZenithAngle = 10 + }, + new TrajectoryGeoPlanDto() { + Id = 2, + AzimuthGeo = 1, + AzimuthMagnetic = 2, + Comment = "комментарий", + IdUser = 1, + IdWell = 4, + Radius = 3, + UpdateDate = DateTimeOffset.Now, + VerticalDepth = 100, + WellboreDepth = 100, + ZenithAngle = 10 + }, + }; + + private readonly TrajectoryGeoFactDto[] trajectoryFactRows = new TrajectoryGeoFactDto[2] { + new TrajectoryGeoFactDto() { + Id = 1, + AzimuthGeo = 1, + AzimuthMagnetic = 2, + Comment = "комментарий", + IdUser = 1, + IdWell = 4, + UpdateDate = DateTimeOffset.Now, + VerticalDepth = 100, + WellboreDepth = 100, + ZenithAngle = 10 + }, + new TrajectoryGeoFactDto() { + Id = 2, + AzimuthGeo = 1, + AzimuthMagnetic = 2, + Comment = "комментарий", + IdUser = 1, + IdWell = 4, + UpdateDate = DateTimeOffset.Now, + VerticalDepth = 100, + WellboreDepth = 100, + ZenithAngle = 10 + }, + }; + + private readonly WellRelatedExportRequest exportOptions = new(idWell); + + public TrajectoryExportTest() { - private const int idWell = 4; + wellService = Substitute.For(); + trajectoryPlanRepository = Substitute.For>(); + trajectoryPlanExportService = new TrajectoryPlanExportService(wellService, trajectoryPlanRepository); + + trajectoryFactManualReposirory = Substitute.For>(); + trajectoryFactManualExportService = new TrajectoryFactManualExportService(wellService, trajectoryFactManualReposirory); + + trajectoryFactNnbRepository = Substitute.For(); + trajectoryFactNnbExportService = new TrajectoryFactNnbExportService(wellService, trajectoryFactNnbRepository); + } + + [Fact] + public async Task Export_trajectory_plan() + { + trajectoryPlanRepository.GetAsync(idWell, CancellationToken.None) + .Returns(trajectoryPlanRows); - private IWellService wellService; - private readonly ITrajectoryEditableRepository trajectoryPlanRepository; - private readonly TrajectoryPlanExportService trajectoryPlanExportService; + var stream = await trajectoryPlanExportService.ExportAsync(exportOptions, CancellationToken.None); + Assert.True(stream.File.Length > 0); + } - private readonly ITrajectoryEditableRepository trajectoryFactManualReposirory; - private readonly TrajectoryFactManualExportService trajectoryFactManualExportService; + [Fact] + public async Task Export_trajectory_fact_manual() + { + trajectoryFactManualReposirory.GetAsync(idWell, CancellationToken.None) + .Returns(trajectoryFactRows); + + var stream = await trajectoryFactManualExportService.ExportAsync(exportOptions, CancellationToken.None); + Assert.True(stream.File.Length > 0); + } - private readonly ITrajectoryNnbRepository trajectoryFactNnbRepository; - private readonly TrajectoryFactNnbExportService trajectoryFactNnbExportService; - - private readonly TrajectoryGeoPlanDto[] trajectoryPlanRows = new TrajectoryGeoPlanDto[2] { - new TrajectoryGeoPlanDto() { - Id = 1, - AzimuthGeo = 1, - AzimuthMagnetic = 2, - Comment = "комментарий", - IdUser = 1, - IdWell = 4, - Radius = 3, - UpdateDate = DateTimeOffset.Now, - VerticalDepth = 100, - WellboreDepth = 100, - ZenithAngle = 10 - }, - new TrajectoryGeoPlanDto() { - Id = 2, - AzimuthGeo = 1, - AzimuthMagnetic = 2, - Comment = "комментарий", - IdUser = 1, - IdWell = 4, - Radius = 3, - UpdateDate = DateTimeOffset.Now, - VerticalDepth = 100, - WellboreDepth = 100, - ZenithAngle = 10 - }, - }; - - private readonly TrajectoryGeoFactDto[] trajectoryFactRows = new TrajectoryGeoFactDto[2] { - new TrajectoryGeoFactDto() { - Id = 1, - AzimuthGeo = 1, - AzimuthMagnetic = 2, - Comment = "комментарий", - IdUser = 1, - IdWell = 4, - UpdateDate = DateTimeOffset.Now, - VerticalDepth = 100, - WellboreDepth = 100, - ZenithAngle = 10 - }, - new TrajectoryGeoFactDto() { - Id = 2, - AzimuthGeo = 1, - AzimuthMagnetic = 2, - Comment = "комментарий", - IdUser = 1, - IdWell = 4, - UpdateDate = DateTimeOffset.Now, - VerticalDepth = 100, - WellboreDepth = 100, - ZenithAngle = 10 - }, - }; - - private readonly WellRelatedExportRequest exportOptions = new(idWell); - - public TrajectoryExportTest() - { - wellService = Substitute.For(); - trajectoryPlanRepository = Substitute.For>(); - trajectoryPlanExportService = new TrajectoryPlanExportService(wellService, trajectoryPlanRepository); - - trajectoryFactManualReposirory = Substitute.For>(); - trajectoryFactManualExportService = new TrajectoryFactManualExportService(wellService, trajectoryFactManualReposirory); - - trajectoryFactNnbRepository = Substitute.For(); - trajectoryFactNnbExportService = new TrajectoryFactNnbExportService(wellService, trajectoryFactNnbRepository); - } - - [Fact] - public async Task Export_trajectory_plan() - { - trajectoryPlanRepository.GetAsync(idWell, CancellationToken.None) - .Returns(trajectoryPlanRows); - - var stream = await trajectoryPlanExportService.ExportAsync(exportOptions, CancellationToken.None); - Assert.True(stream.File.Length > 0); - } - - [Fact] - public async Task Export_trajectory_fact_manual() - { - trajectoryFactManualReposirory.GetAsync(idWell, CancellationToken.None) - .Returns(trajectoryFactRows); - - var stream = await trajectoryFactManualExportService.ExportAsync(exportOptions, CancellationToken.None); - Assert.True(stream.File.Length > 0); - } - - [Fact] - public async Task Export_trajectory_fact_nnb() - { - trajectoryFactNnbRepository.GetAsync(idWell, CancellationToken.None) - .Returns(trajectoryFactRows); - - var stream = await trajectoryFactNnbExportService.ExportAsync(exportOptions, CancellationToken.None); - Assert.True(stream.File.Length > 0); - } + [Fact] + public async Task Export_trajectory_fact_nnb() + { + trajectoryFactNnbRepository.GetAsync(idWell, CancellationToken.None) + .Returns(trajectoryFactRows); + + var stream = await trajectoryFactNnbExportService.ExportAsync(exportOptions, CancellationToken.None); + Assert.True(stream.File.Length > 0); } } diff --git a/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs b/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs index 7216aa09..8c5961ed 100644 --- a/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs +++ b/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs @@ -12,303 +12,302 @@ using System.Threading; using System.Threading.Tasks; using Xunit; -namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation +namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation; + +public class WellCompositeOperationServiceTest { - public class WellCompositeOperationServiceTest + private WellCompositeOperationService service; + + private ICrudRepository wellSectionTypeRepository + = Substitute.For>(); + private IWellOperationCategoryRepository wellOperationCategoryRepository + = Substitute.For(); + private IWellOperationService wellOperationService + = Substitute.For(); + private IWellService wellService + = Substitute.For(); + private List idsWells; + private readonly static IEnumerable operationCategories = new List() { - private WellCompositeOperationService service; + new(){Id = 5096, Name = "Шаблонирование перед спуском"}, + new(){Id = 5008, Name = "Шаблонировка во время бурения"}, + new(){Id = 5013, Name = "Подъем КНБК"}, + new(){Id = 5003, Name = "Бурение ротором"}, + new(){Id = 5036, Name = "Промывка"}, + new(){Id = 5012, Name = "Подъем инструмента"}, + new(){Id = 5083, Name = "Проработка принудительная"}, + new(){Id = 5113, Name = "Бурение"}, + }; - private ICrudRepository wellSectionTypeRepository - = Substitute.For>(); - private IWellOperationCategoryRepository wellOperationCategoryRepository - = Substitute.For(); - private IWellOperationService wellOperationService - = Substitute.For(); - private IWellService wellService - = Substitute.For(); - private List idsWells; - private readonly static IEnumerable operationCategories = new List() + private readonly static IEnumerable sectionTypes = new List() + { + new() {Id = 2, Caption = "Направление", Order = 0}, + new() {Id = 3, Caption = "Кондуктор", Order = 1}, + new() {Id = 31, Caption = "Техническая колонна", Order = 2} + }; + + private readonly static IEnumerable wells = new List() + { + new() {Id = 55, Caption = "Скважина с ключом 55"}, + new() {Id = 64, Caption = "Скважина с ключом 64"}, + }; + + private readonly static IEnumerable wellOperations1 = new List() + { + new() { - new(){Id = 5096, Name = "Шаблонирование перед спуском"}, - new(){Id = 5008, Name = "Шаблонировка во время бурения"}, - new(){Id = 5013, Name = "Подъем КНБК"}, - new(){Id = 5003, Name = "Бурение ротором"}, - new(){Id = 5036, Name = "Промывка"}, - new(){Id = 5012, Name = "Подъем инструмента"}, - new(){Id = 5083, Name = "Проработка принудительная"}, - new(){Id = 5113, Name = "Бурение"}, - }; - - private readonly static IEnumerable sectionTypes = new List() + DepthStart = 50, + DurationHours = 1, + IdCategory = 5096, + IdWell = 55, + IdWellSectionType = 2, + OperationCategoryName = "Шаблонирование перед спуском", + WellSectionTypeCaption = "Направление" + }, + new() { - new() {Id = 2, Caption = "Направление", Order = 0}, - new() {Id = 3, Caption = "Кондуктор", Order = 1}, - new() {Id = 31, Caption = "Техническая колонна", Order = 2} - }; - - private readonly static IEnumerable wells = new List() - { - new() {Id = 55, Caption = "Скважина с ключом 55"}, - new() {Id = 64, Caption = "Скважина с ключом 64"}, - }; - - private readonly static IEnumerable wellOperations1 = new List() - { - new() - { - DepthStart = 50, - DurationHours = 1, - IdCategory = 5096, - IdWell = 55, - IdWellSectionType = 2, - OperationCategoryName = "Шаблонирование перед спуском", - WellSectionTypeCaption = "Направление" - }, - new() - { - DepthStart = 84, - DurationHours = 1, - IdCategory = 5008, - IdWell = 64, - IdWellSectionType = 2, - OperationCategoryName = "Шаблонировка во время бурения", - WellSectionTypeCaption = "Направление" - } - }; - - private readonly static IEnumerable wellOperations2 = new List() - { - new() - { - DepthStart = 10, - DurationHours = 1.5, - IdCategory = 5003, - IdWell = 55, - IdWellSectionType = 2, - OperationCategoryName = "Бурение ротором", - WellSectionTypeCaption = "Направление" - }, - new() - { - DepthStart = 20, - DurationHours = 3.5, - IdCategory = 5003, - IdWell = 64, - IdWellSectionType = 2, - OperationCategoryName = "Бурение ротором", - WellSectionTypeCaption = "Направление" - } - }; - - private readonly static IEnumerable wellOperations3 = new List() - { - new() - { - DepthStart = 1372, - DurationHours = 3, - IdCategory = 5036, - IdWell = 55, - IdWellSectionType = 3, - OperationCategoryName = "Промывка", - WellSectionTypeCaption = "Кондуктор" - }, - new() - { - DepthStart = 1435, - DurationHours = 4, - IdCategory = 5036, - IdWell = 64, - IdWellSectionType = 3, - OperationCategoryName = "Промывка", - WellSectionTypeCaption = "Кондуктор" - } - }; - - private readonly static IEnumerable wellOperations4 = new List() - { - new() - { - DepthStart = 1000, - DurationHours = 10, - IdCategory = 5012, - IdWell = 55, - IdWellSectionType = 31, - OperationCategoryName = "Подъем инструмента", - WellSectionTypeCaption = "Техническая колонна" - }, - new() - { - DepthStart = 500, - DurationHours = 5, - IdCategory = 5083, - IdWell = 55, - IdWellSectionType = 31, - OperationCategoryName = "Проработка принудительная", - WellSectionTypeCaption = "Техническая колонна" - }, - new() - { - DepthStart = 600, - DurationHours = 5, - IdCategory = 5083, - IdWell = 64, - IdWellSectionType = 31, - OperationCategoryName = "Проработка принудительная", - WellSectionTypeCaption = "Техническая колонна" - } - }; - - public WellCompositeOperationServiceTest() - { - - wellSectionTypeRepository.GetAllAsync(Arg.Any()) - .Returns(sectionTypes); - - wellOperationCategoryRepository.Get(Arg.Any()) - .Returns(operationCategories); - - idsWells = new List() { 55, 64 }; - - wellService.GetAsync(Arg.Any(), Arg.Any()) - .Returns(wells); - - service = new WellCompositeOperationService( - wellSectionTypeRepository, - wellOperationCategoryRepository, - wellService, - wellOperationService); + DepthStart = 84, + DurationHours = 1, + IdCategory = 5008, + IdWell = 64, + IdWellSectionType = 2, + OperationCategoryName = "Шаблонировка во время бурения", + WellSectionTypeCaption = "Направление" } + }; - /// - /// На вход подаются 2 операции с одинаковыми секциями (id = 2), но разными категориями (ids = 5096, 5008) и ключами скважин (ids = 55, 64) - /// Метод возвращает объект с одной композитной операцией и списком операций в разрезе 2-х скважин - /// Композитная операция должна иметь категорию 5013 - /// - /// - [Fact] - public async Task GetAsync_return_composite_and_others_with_category_5013() + private readonly static IEnumerable wellOperations2 = new List() + { + new() { - // arrange - wellOperationService.GetAsync(Arg.Any(), Arg.Any()) - .Returns(wellOperations1); - - // act - var result = await service.GetAsync(idsWells, CancellationToken.None); - - // assert - var compositeWellOperations = result.WellOperationsComposite; - Assert.Single(compositeWellOperations); - Assert.Equal(5013, compositeWellOperations.FirstOrDefault()?.IdCategory); - Assert.Equal(1, compositeWellOperations.FirstOrDefault()?.DurationHours); - Assert.Equal(84, compositeWellOperations.FirstOrDefault()?.DepthStart); - - var categoryName = compositeWellOperations.Select(o => o.OperationCategoryName).First(); - Assert.Equal("Подъем КНБК", categoryName); - } - - /// - /// На вход подаются 2 операции с одинаковыми секциями (id = 2) и категориями (id = 5003), но разными ключами скважин (ids = 55, 64) - /// Метод возвращает объект с одной композитной операцией и списком операций в разрезе 2-х скважин - /// Операция композитной скважины должна содержать данные той операции, которая содержит минимальный duration_hours - /// - /// - [Fact] - public async Task GetAsync_return_composite_with_minimum_depth_start() + DepthStart = 10, + DurationHours = 1.5, + IdCategory = 5003, + IdWell = 55, + IdWellSectionType = 2, + OperationCategoryName = "Бурение ротором", + WellSectionTypeCaption = "Направление" + }, + new() { - // arrange - wellOperationService.GetAsync(Arg.Any(), Arg.Any()) - .Returns(wellOperations2); - - // act - var result = await service.GetAsync(idsWells, CancellationToken.None); - - // assert - var compositeWellOperations = result.WellOperationsComposite; - Assert.Single(compositeWellOperations); - Assert.Equal(5113, compositeWellOperations.FirstOrDefault()!.IdCategory); - Assert.Equal(1.5, compositeWellOperations.FirstOrDefault()!.DurationHours); - Assert.Equal(10, compositeWellOperations.FirstOrDefault()!.DepthStart); + DepthStart = 20, + DurationHours = 3.5, + IdCategory = 5003, + IdWell = 64, + IdWellSectionType = 2, + OperationCategoryName = "Бурение ротором", + WellSectionTypeCaption = "Направление" } + }; - /// - /// На вход подаются 2 операции с одинаковыми секциями (id = 3) и категориями (id = 5036), но разными ключами скважин (ids = 55, 64) - /// Метод возвращает объект с одной композитной операцией и списком операций в разрезе 2-х скважин - /// Операция композитной скважины должна содержать данные той операции, которая содержит минимальный duration_hours - /// - /// - [Fact] - public async Task GetAsync_return_data3() + private readonly static IEnumerable wellOperations3 = new List() + { + new() { - // arrange - wellOperationService.GetAsync(Arg.Any(), Arg.Any()) - .Returns(wellOperations3); - - // act - var result = await service.GetAsync(idsWells, CancellationToken.None); - - // assert - var compositeWellOperations = result.WellOperationsComposite; - Assert.Single(compositeWellOperations); - Assert.Equal(5036, compositeWellOperations.FirstOrDefault()!.IdCategory); - Assert.Equal(3, compositeWellOperations.FirstOrDefault()!.DurationHours); - Assert.Equal(1372, compositeWellOperations.FirstOrDefault()!.DepthStart); - } - - /// - /// На вход подаются 3 операции с одинаковыми секциями (id = 31), но разными категориями (ids = 5012, 5083) и ключами скважин (ids = 55, 64) - /// Метод возвращает объект с одной композитной операцией и списком операций в разрезе 2-х скважин - /// Операция композитной скважины должна содержать: - /// данные той операции, которая содержит минимальный duration_hours - /// категорию с ключом 5013 - /// - /// - [Fact] - public async Task GetAsync_return_data4() + DepthStart = 1372, + DurationHours = 3, + IdCategory = 5036, + IdWell = 55, + IdWellSectionType = 3, + OperationCategoryName = "Промывка", + WellSectionTypeCaption = "Кондуктор" + }, + new() { - // arrange - wellOperationService.GetAsync(Arg.Any(), Arg.Any()) - .Returns(wellOperations4); - - // act - var result = await service.GetAsync(idsWells, CancellationToken.None); - - // assert - var compositeWellOperations = result.WellOperationsComposite; - Assert.Single(compositeWellOperations); - Assert.Equal(5013, compositeWellOperations.FirstOrDefault()!.IdCategory); - Assert.Equal(5, compositeWellOperations.FirstOrDefault()!.DurationHours); - Assert.Equal(600, compositeWellOperations.FirstOrDefault()!.DepthStart); + DepthStart = 1435, + DurationHours = 4, + IdCategory = 5036, + IdWell = 64, + IdWellSectionType = 3, + OperationCategoryName = "Промывка", + WellSectionTypeCaption = "Кондуктор" } + }; - /// - /// На вход подаются список разных операций с разными ключами скважин (ids = 55, 64) - /// Метод возвращает объект с одной композитной операцией и списком операций в разрезе 2-х скважин - /// Операция композитной скважины должна содержать глубину забоя = 1372 - /// - /// - [Fact] - public async Task GetAsync_return_data5() + private readonly static IEnumerable wellOperations4 = new List() + { + new() { - // arrange - var wellOperations = new List(); - wellOperations.AddRange(wellOperations1); - wellOperations.AddRange(wellOperations2); - wellOperations.AddRange(wellOperations3); - wellOperations.AddRange(wellOperations4); - - wellOperationService.GetAsync(Arg.Any(), Arg.Any()) - .Returns(wellOperations); - - // act - var result = await service.GetAsync(idsWells, CancellationToken.None); - - // assert - var wellOperationsCount = result.WellCompositeSourceOperations - .SelectMany(o => o.Operations).Count(); - Assert.Equal(wellOperations.Count(), wellOperationsCount); - - var lastOperationComposite = result.WellOperationsComposite.Last(); - Assert.Equal(1372, lastOperationComposite.DepthStart); + DepthStart = 1000, + DurationHours = 10, + IdCategory = 5012, + IdWell = 55, + IdWellSectionType = 31, + OperationCategoryName = "Подъем инструмента", + WellSectionTypeCaption = "Техническая колонна" + }, + new() + { + DepthStart = 500, + DurationHours = 5, + IdCategory = 5083, + IdWell = 55, + IdWellSectionType = 31, + OperationCategoryName = "Проработка принудительная", + WellSectionTypeCaption = "Техническая колонна" + }, + new() + { + DepthStart = 600, + DurationHours = 5, + IdCategory = 5083, + IdWell = 64, + IdWellSectionType = 31, + OperationCategoryName = "Проработка принудительная", + WellSectionTypeCaption = "Техническая колонна" } + }; + + public WellCompositeOperationServiceTest() + { + + wellSectionTypeRepository.GetAllAsync(Arg.Any()) + .Returns(sectionTypes); + + wellOperationCategoryRepository.Get(Arg.Any()) + .Returns(operationCategories); + + idsWells = new List() { 55, 64 }; + + wellService.GetAsync(Arg.Any(), Arg.Any()) + .Returns(wells); + + service = new WellCompositeOperationService( + wellSectionTypeRepository, + wellOperationCategoryRepository, + wellService, + wellOperationService); + } + + /// + /// На вход подаются 2 операции с одинаковыми секциями (id = 2), но разными категориями (ids = 5096, 5008) и ключами скважин (ids = 55, 64) + /// Метод возвращает объект с одной композитной операцией и списком операций в разрезе 2-х скважин + /// Композитная операция должна иметь категорию 5013 + /// + /// + [Fact] + public async Task GetAsync_return_composite_and_others_with_category_5013() + { + // arrange + wellOperationService.GetAsync(Arg.Any(), Arg.Any()) + .Returns(wellOperations1); + + // act + var result = await service.GetAsync(idsWells, CancellationToken.None); + + // assert + var compositeWellOperations = result.WellOperationsComposite; + Assert.Single(compositeWellOperations); + Assert.Equal(5013, compositeWellOperations.FirstOrDefault()?.IdCategory); + Assert.Equal(1, compositeWellOperations.FirstOrDefault()?.DurationHours); + Assert.Equal(84, compositeWellOperations.FirstOrDefault()?.DepthStart); + + var categoryName = compositeWellOperations.Select(o => o.OperationCategoryName).First(); + Assert.Equal("Подъем КНБК", categoryName); + } + + /// + /// На вход подаются 2 операции с одинаковыми секциями (id = 2) и категориями (id = 5003), но разными ключами скважин (ids = 55, 64) + /// Метод возвращает объект с одной композитной операцией и списком операций в разрезе 2-х скважин + /// Операция композитной скважины должна содержать данные той операции, которая содержит минимальный duration_hours + /// + /// + [Fact] + public async Task GetAsync_return_composite_with_minimum_depth_start() + { + // arrange + wellOperationService.GetAsync(Arg.Any(), Arg.Any()) + .Returns(wellOperations2); + + // act + var result = await service.GetAsync(idsWells, CancellationToken.None); + + // assert + var compositeWellOperations = result.WellOperationsComposite; + Assert.Single(compositeWellOperations); + Assert.Equal(5113, compositeWellOperations.FirstOrDefault()!.IdCategory); + Assert.Equal(1.5, compositeWellOperations.FirstOrDefault()!.DurationHours); + Assert.Equal(10, compositeWellOperations.FirstOrDefault()!.DepthStart); + } + + /// + /// На вход подаются 2 операции с одинаковыми секциями (id = 3) и категориями (id = 5036), но разными ключами скважин (ids = 55, 64) + /// Метод возвращает объект с одной композитной операцией и списком операций в разрезе 2-х скважин + /// Операция композитной скважины должна содержать данные той операции, которая содержит минимальный duration_hours + /// + /// + [Fact] + public async Task GetAsync_return_data3() + { + // arrange + wellOperationService.GetAsync(Arg.Any(), Arg.Any()) + .Returns(wellOperations3); + + // act + var result = await service.GetAsync(idsWells, CancellationToken.None); + + // assert + var compositeWellOperations = result.WellOperationsComposite; + Assert.Single(compositeWellOperations); + Assert.Equal(5036, compositeWellOperations.FirstOrDefault()!.IdCategory); + Assert.Equal(3, compositeWellOperations.FirstOrDefault()!.DurationHours); + Assert.Equal(1372, compositeWellOperations.FirstOrDefault()!.DepthStart); + } + + /// + /// На вход подаются 3 операции с одинаковыми секциями (id = 31), но разными категориями (ids = 5012, 5083) и ключами скважин (ids = 55, 64) + /// Метод возвращает объект с одной композитной операцией и списком операций в разрезе 2-х скважин + /// Операция композитной скважины должна содержать: + /// данные той операции, которая содержит минимальный duration_hours + /// категорию с ключом 5013 + /// + /// + [Fact] + public async Task GetAsync_return_data4() + { + // arrange + wellOperationService.GetAsync(Arg.Any(), Arg.Any()) + .Returns(wellOperations4); + + // act + var result = await service.GetAsync(idsWells, CancellationToken.None); + + // assert + var compositeWellOperations = result.WellOperationsComposite; + Assert.Single(compositeWellOperations); + Assert.Equal(5013, compositeWellOperations.FirstOrDefault()!.IdCategory); + Assert.Equal(5, compositeWellOperations.FirstOrDefault()!.DurationHours); + Assert.Equal(600, compositeWellOperations.FirstOrDefault()!.DepthStart); + } + + /// + /// На вход подаются список разных операций с разными ключами скважин (ids = 55, 64) + /// Метод возвращает объект с одной композитной операцией и списком операций в разрезе 2-х скважин + /// Операция композитной скважины должна содержать глубину забоя = 1372 + /// + /// + [Fact] + public async Task GetAsync_return_data5() + { + // arrange + var wellOperations = new List(); + wellOperations.AddRange(wellOperations1); + wellOperations.AddRange(wellOperations2); + wellOperations.AddRange(wellOperations3); + wellOperations.AddRange(wellOperations4); + + wellOperationService.GetAsync(Arg.Any(), Arg.Any()) + .Returns(wellOperations); + + // act + var result = await service.GetAsync(idsWells, CancellationToken.None); + + // assert + var wellOperationsCount = result.WellCompositeSourceOperations + .SelectMany(o => o.Operations).Count(); + Assert.Equal(wellOperations.Count(), wellOperationsCount); + + var lastOperationComposite = result.WellOperationsComposite.Last(); + Assert.Equal(1372, lastOperationComposite.DepthStart); } } diff --git a/AsbCloudWebApi.Tests/Services/WellOperationServiceTest.cs b/AsbCloudWebApi.Tests/Services/WellOperationServiceTest.cs index 3927e9b0..48b52e2f 100644 --- a/AsbCloudWebApi.Tests/Services/WellOperationServiceTest.cs +++ b/AsbCloudWebApi.Tests/Services/WellOperationServiceTest.cs @@ -4,15 +4,12 @@ using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudDb.Model; -using AsbCloudInfrastructure.Repository; -using AsbCloudInfrastructure.Services; using AsbCloudInfrastructure.Services.WellOperationService.WellOperationService; using Mapster; using NSubstitute; using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; using Xunit; diff --git a/AsbCloudWebApi/Controllers/AdminClusterController.cs b/AsbCloudWebApi/Controllers/AdminClusterController.cs index e99c7d70..f60c9788 100644 --- a/AsbCloudWebApi/Controllers/AdminClusterController.cs +++ b/AsbCloudWebApi/Controllers/AdminClusterController.cs @@ -3,18 +3,17 @@ using AsbCloudApp.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Редактор кустов для админки +/// +[Route("api/admin/cluster")] +[ApiController] +[Authorize] +public class AdminClusterController : CrudController> { - /// - /// Редактор кустов для админки - /// - [Route("api/admin/cluster")] - [ApiController] - [Authorize] - public class AdminClusterController : CrudController> - { - public AdminClusterController(ICrudRepository service) - : base(service) - { } - } + public AdminClusterController(ICrudRepository service) + : base(service) + { } } diff --git a/AsbCloudWebApi/Controllers/AdminCompanyController.cs b/AsbCloudWebApi/Controllers/AdminCompanyController.cs index 819c79e0..a97a670b 100644 --- a/AsbCloudWebApi/Controllers/AdminCompanyController.cs +++ b/AsbCloudWebApi/Controllers/AdminCompanyController.cs @@ -3,19 +3,18 @@ using AsbCloudApp.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Редактор компаний для админки +/// +[Route("api/admin/company")] +[ApiController] +[Authorize] +public class AdminCompanyController : CrudController> { - /// - /// Редактор компаний для админки - /// - [Route("api/admin/company")] - [ApiController] - [Authorize] - public class AdminCompanyController : CrudController> + public AdminCompanyController(ICrudRepository service) + : base(service) { - public AdminCompanyController(ICrudRepository service) - : base(service) - { - } } } diff --git a/AsbCloudWebApi/Controllers/AdminCompanyTypeController.cs b/AsbCloudWebApi/Controllers/AdminCompanyTypeController.cs index 71cf7b61..13ebe885 100644 --- a/AsbCloudWebApi/Controllers/AdminCompanyTypeController.cs +++ b/AsbCloudWebApi/Controllers/AdminCompanyTypeController.cs @@ -3,18 +3,17 @@ using AsbCloudApp.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Редактор типов компаний для админки +/// +[Route("api/admin/companyType")] +[ApiController] +[Authorize] +public class AdminCompanyTypeController : CrudController> { - /// - /// Редактор типов компаний для админки - /// - [Route("api/admin/companyType")] - [ApiController] - [Authorize] - public class AdminCompanyTypeController : CrudController> - { - public AdminCompanyTypeController(ICrudRepository service) - : base(service) - { } - } + public AdminCompanyTypeController(ICrudRepository service) + : base(service) + { } } \ No newline at end of file diff --git a/AsbCloudWebApi/Controllers/AdminDepositController.cs b/AsbCloudWebApi/Controllers/AdminDepositController.cs index c558d1d6..dead7e28 100644 --- a/AsbCloudWebApi/Controllers/AdminDepositController.cs +++ b/AsbCloudWebApi/Controllers/AdminDepositController.cs @@ -3,19 +3,18 @@ using AsbCloudApp.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Редактор месторождений для админки +/// +[Route("api/admin/deposit")] +[ApiController] +[Authorize] +public class AdminDepositController : CrudController> { - /// - /// Редактор месторождений для админки - /// - [Route("api/admin/deposit")] - [ApiController] - [Authorize] - public class AdminDepositController : CrudController> + public AdminDepositController(ICrudRepository service) + : base(service) { - public AdminDepositController(ICrudRepository service) - : base(service) - { - } } } diff --git a/AsbCloudWebApi/Controllers/AdminPermissionController.cs b/AsbCloudWebApi/Controllers/AdminPermissionController.cs index 4444f335..9ef9b053 100644 --- a/AsbCloudWebApi/Controllers/AdminPermissionController.cs +++ b/AsbCloudWebApi/Controllers/AdminPermissionController.cs @@ -7,56 +7,55 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Редактор разрешений пользователей для админки +/// +[Route("api/admin/permission")] +[ApiController] +[Authorize] +public class AdminPermissionController : CrudController> { - /// - /// Редактор разрешений пользователей для админки - /// - [Route("api/admin/permission")] - [ApiController] - [Authorize] - public class AdminPermissionController : CrudController> + public AdminPermissionController(ICrudRepository service) + : base(service) + { } + + [HttpGet("Autogenerated")] + [Permission] + public IActionResult GetAutogenerated() { - public AdminPermissionController(ICrudRepository service) - : base(service) - { } + var controllers = Assembly.GetExecutingAssembly().GetTypes(). + Where(type => typeof(ControllerBase).IsAssignableFrom(type) && !type.IsAbstract) + .ToList(); - [HttpGet("Autogenerated")] - [Permission] - public IActionResult GetAutogenerated() + var permissions = new SortedSet(); + foreach (var controller in controllers) { - var controllers = Assembly.GetExecutingAssembly().GetTypes(). - Where(type => typeof(ControllerBase).IsAssignableFrom(type) && !type.IsAbstract) - .ToList(); - - var permissions = new SortedSet(); - foreach (var controller in controllers) + var methods = controller.GetMethods().Where(m => m.IsPublic); + var controllerName = controller.Name.Replace("Controller", ""); + foreach (var method in methods) { - var methods = controller.GetMethods().Where(m => m.IsPublic); - var controllerName = controller.Name.Replace("Controller", ""); - foreach (var method in methods) + var httpMethod = method.GetCustomAttribute()?.HttpMethods?.First().ToLower(); + switch (httpMethod) { - var httpMethod = method.GetCustomAttribute()?.HttpMethods?.First().ToLower(); - switch (httpMethod) - { - case "get": - case "delete": - permissions.Add($"{controllerName}.{httpMethod.ToLower()}"); - continue; - case "post": - case "put": - case "patch": - permissions.Add($"{controllerName}.edit"); - continue; - default: - continue; - } - + case "get": + case "delete": + permissions.Add($"{controllerName}.{httpMethod.ToLower()}"); + continue; + case "post": + case "put": + case "patch": + permissions.Add($"{controllerName}.edit"); + continue; + default: + continue; } + } - - return Ok(permissions); - } + + return Ok(permissions); + } } \ No newline at end of file diff --git a/AsbCloudWebApi/Controllers/AdminTelemetryController.cs b/AsbCloudWebApi/Controllers/AdminTelemetryController.cs index 6a6eb16e..d81792bd 100644 --- a/AsbCloudWebApi/Controllers/AdminTelemetryController.cs +++ b/AsbCloudWebApi/Controllers/AdminTelemetryController.cs @@ -8,56 +8,55 @@ using System; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Редактор телеметрий для админки +/// +[Route("api/admin/telemetry")] +[ApiController] +[Authorize] +public class AdminTelemetryController : CrudController> { - /// - /// Редактор телеметрий для админки - /// - [Route("api/admin/telemetry")] - [ApiController] - [Authorize] - public class AdminTelemetryController : CrudController> + private readonly ITelemetryService telemetryService; + private readonly ITelemetryDataEditorService telemetryEditorService; + + public AdminTelemetryController(ICrudRepository service, + ITelemetryService telemetryService, + ITelemetryDataEditorService telemetryEditorService) + : base(service) { - private readonly ITelemetryService telemetryService; - private readonly ITelemetryDataEditorService telemetryEditorService; + this.telemetryService = telemetryService; + this.telemetryEditorService = telemetryEditorService; + } - public AdminTelemetryController(ICrudRepository service, - ITelemetryService telemetryService, - ITelemetryDataEditorService telemetryEditorService) - : base(service) - { - this.telemetryService = telemetryService; - this.telemetryEditorService = telemetryEditorService; - } + /// + /// Merge telemetries. No body required. + /// + /// + [HttpPost("/merge/{idFrom}/{idTo}")] + [Permission] + public async Task MergeTelemetriesAsync(int idFrom, int idTo, CancellationToken token) + { + var count = await telemetryService.MergeAsync(idFrom, idTo, token) + .ConfigureAwait(false); + return Ok(count); + } - /// - /// Merge telemetries. No body required. - /// - /// - [HttpPost("/merge/{idFrom}/{idTo}")] - [Permission] - public async Task MergeTelemetriesAsync(int idFrom, int idTo, CancellationToken token) - { - var count = await telemetryService.MergeAsync(idFrom, idTo, token) - .ConfigureAwait(false); - return Ok(count); - } + /// + /// Удаление куска телеметрии по запросу + /// + /// запрос + /// + /// + [HttpDelete("part")] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] + public async Task DeleteAsync([FromQuery] TelemetryPartDeleteRequest request,CancellationToken token) + { + var result = await telemetryEditorService.DeleteAsync(request, token); - /// - /// Удаление куска телеметрии по запросу - /// - /// запрос - /// - /// - [HttpDelete("part")] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] - public async Task DeleteAsync([FromQuery] TelemetryPartDeleteRequest request,CancellationToken token) - { - var result = await telemetryEditorService.DeleteAsync(request, token); - - return Ok(result); - } + return Ok(result); } } diff --git a/AsbCloudWebApi/Controllers/AdminUserController.cs b/AsbCloudWebApi/Controllers/AdminUserController.cs index f0784c35..e864891a 100644 --- a/AsbCloudWebApi/Controllers/AdminUserController.cs +++ b/AsbCloudWebApi/Controllers/AdminUserController.cs @@ -5,19 +5,18 @@ using AsbCloudInfrastructure.Repository; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -namespace AsbCloudWebApi.Controllers -{ - /// - /// Редактор пользователей для админки - /// - [Route("api/admin/user")] - [ApiController] - [Authorize] - public class AdminUserController : CrudController> - { - public AdminUserController(IUserRepository service) - : base(service) - { } +namespace AsbCloudWebApi.Controllers; + +/// +/// Редактор пользователей для админки +/// +[Route("api/admin/user")] +[ApiController] +[Authorize] +public class AdminUserController : CrudController> +{ + public AdminUserController(IUserRepository service) + : base(service) + { } - } } diff --git a/AsbCloudWebApi/Controllers/AdminUserRoleController.cs b/AsbCloudWebApi/Controllers/AdminUserRoleController.cs index 5c19378c..535ffcea 100644 --- a/AsbCloudWebApi/Controllers/AdminUserRoleController.cs +++ b/AsbCloudWebApi/Controllers/AdminUserRoleController.cs @@ -4,29 +4,28 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers -{ - /// - /// Редактор ролей пользователей для админки - /// - [Route("api/admin/role")] - [ApiController] - [Authorize] - public class AdminUserRoleController : CrudController - { - public AdminUserRoleController(IUserRoleRepository service) - : base(service) - { - UpdateForbidAsync = async (dto, token) => - { - var role = await service.GetOrDefaultAsync(dto.Id, token); - return role?.Id == 1; - }; +namespace AsbCloudWebApi.Controllers; - DeleteForbidAsync = (id, token) => - { - return Task.FromResult(id == 1); - }; - } +/// +/// Редактор ролей пользователей для админки +/// +[Route("api/admin/role")] +[ApiController] +[Authorize] +public class AdminUserRoleController : CrudController +{ + public AdminUserRoleController(IUserRoleRepository service) + : base(service) + { + UpdateForbidAsync = async (dto, token) => + { + var role = await service.GetOrDefaultAsync(dto.Id, token); + return role?.Id == 1; + }; + + DeleteForbidAsync = (id, token) => + { + return Task.FromResult(id == 1); + }; } } diff --git a/AsbCloudWebApi/Controllers/AdminWellController.cs b/AsbCloudWebApi/Controllers/AdminWellController.cs index fa4c6e60..8d55c760 100644 --- a/AsbCloudWebApi/Controllers/AdminWellController.cs +++ b/AsbCloudWebApi/Controllers/AdminWellController.cs @@ -5,18 +5,17 @@ using Microsoft.AspNetCore.Mvc; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Редактор скважин для админки +/// +[Route("api/admin/well")] +[ApiController] +[Authorize] +public class AdminWellController : CrudController> { - /// - /// Редактор скважин для админки - /// - [Route("api/admin/well")] - [ApiController] - [Authorize] - public class AdminWellController : CrudController> - { - public AdminWellController(IWellService service) - : base(service) - { } - } + public AdminWellController(IWellService service) + : base(service) + { } } diff --git a/AsbCloudWebApi/Controllers/AuthController.cs b/AsbCloudWebApi/Controllers/AuthController.cs index 3497dcab..fba8b8c0 100644 --- a/AsbCloudWebApi/Controllers/AuthController.cs +++ b/AsbCloudWebApi/Controllers/AuthController.cs @@ -8,94 +8,93 @@ using Swashbuckle.AspNetCore.Annotations; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Авторизация +/// +[Route("/auth")] +[ApiController] +public class AuthController : ControllerBase { - /// - /// Авторизация - /// - [Route("/auth")] - [ApiController] - public class AuthController : ControllerBase + private readonly IAuthService authService; + private readonly IUserRepository userRepository; + + public AuthController(IAuthService authService, IUserRepository userRepository) { - private readonly IAuthService authService; - private readonly IUserRepository userRepository; + this.authService = authService; + this.userRepository = userRepository; + } - public AuthController(IAuthService authService, IUserRepository userRepository) - { - this.authService = authService; - this.userRepository = userRepository; - } + /// + /// Аутентификация пользователя + /// + /// + /// Токен отмены задачи + /// новый токен + /// логин и пароль не подходят + [AllowAnonymous] + [HttpPost("login")] + [SwaggerOperation(OperationId = "login")] + [ProducesResponseType(typeof(UserTokenDto), (int)System.Net.HttpStatusCode.OK)] + public async Task LoginAsync([FromBody] AuthDto auth, CancellationToken token) + { + var userToken = await authService.LoginAsync(auth.Login, auth.Password, token); - /// - /// Аутентификация пользователя - /// - /// - /// Токен отмены задачи - /// новый токен - /// логин и пароль не подходят - [AllowAnonymous] - [HttpPost("login")] - [SwaggerOperation(OperationId = "login")] - [ProducesResponseType(typeof(UserTokenDto), (int)System.Net.HttpStatusCode.OK)] - public async Task LoginAsync([FromBody] AuthDto auth, CancellationToken token) - { - var userToken = await authService.LoginAsync(auth.Login, auth.Password, token); + if (userToken is null) + Forbid(); - if (userToken is null) - Forbid(); + return Ok(userToken); + } - return Ok(userToken); - } + /// + /// Продление срока действия токена + /// + /// новый токен + [Authorize] + [HttpGet("refresh")] + [ProducesResponseType(typeof(UserTokenDto), (int)System.Net.HttpStatusCode.OK)] + public async Task RefreshAsync(CancellationToken token) + { + var userToken = await authService.RefreshAsync(User, token); - /// - /// Продление срока действия токена - /// - /// новый токен - [Authorize] - [HttpGet("refresh")] - [ProducesResponseType(typeof(UserTokenDto), (int)System.Net.HttpStatusCode.OK)] - public async Task RefreshAsync(CancellationToken token) - { - var userToken = await authService.RefreshAsync(User, token); + if (userToken is null) + Forbid(); - if (userToken is null) - Forbid(); + return Ok(userToken); + } - return Ok(userToken); - } + /// + /// Отправить заявку на регистрацию. Заявка подтверждается администратором. + /// + /// Информация о новом пользователе + /// Ок + [HttpPost] + [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] + public IActionResult Register(UserRegistrationDto user) + { + authService.Register(user); + return Ok(); + } - /// - /// Отправить заявку на регистрацию. Заявка подтверждается администратором. - /// - /// Информация о новом пользователе - /// Ок - [HttpPost] - [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] - public IActionResult Register(UserRegistrationDto user) - { - authService.Register(user); - return Ok(); - } + /// + /// Смена пароля пользователя. Доступна пользователю и администратору + /// + /// Ок + [Authorize] + [HttpPut("{idUser}/ChangePassword")] + [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] + public IActionResult ChangePassword([FromRoute] int idUser, [FromBody] string newPassword) + { + var editorUserId = User.GetUserId(); - /// - /// Смена пароля пользователя. Доступна пользователю и администратору - /// - /// Ок - [Authorize] - [HttpPut("{idUser}/ChangePassword")] - [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] - public IActionResult ChangePassword([FromRoute] int idUser, [FromBody] string newPassword) - { - var editorUserId = User.GetUserId(); + if (editorUserId is null) + return Forbid(); - if (editorUserId is null) - return Forbid(); + if (!((editorUserId == idUser) || userRepository.HasPermission((int)editorUserId, "Auth.edit"))) + return Forbid(); - if (!((editorUserId == idUser) || userRepository.HasPermission((int)editorUserId, "Auth.edit"))) - return Forbid(); - - authService.ChangePassword(idUser, newPassword); - return Ok(); - } + authService.ChangePassword(idUser, newPassword); + return Ok(); } } diff --git a/AsbCloudWebApi/Controllers/BackgroundWorkController.cs b/AsbCloudWebApi/Controllers/BackgroundWorkController.cs index 58be1362..afbb1d9d 100644 --- a/AsbCloudWebApi/Controllers/BackgroundWorkController.cs +++ b/AsbCloudWebApi/Controllers/BackgroundWorkController.cs @@ -7,63 +7,62 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +[Route("api/[controller]")] +[Authorize] +[ApiController] +public class BackgroundWorkController : ControllerBase { - [Route("api/[controller]")] - [Authorize] - [ApiController] - public class BackgroundWorkController : ControllerBase + private readonly BackgroundWorker worker; + + public BackgroundWorkController(BackgroundWorker worker) { - private readonly BackgroundWorker worker; + this.worker = worker; + } - public BackgroundWorkController(BackgroundWorker worker) - { - this.worker = worker; - } + [HttpGet] + public IActionResult GetAll() + { + var result = new { + CurrentWork = (BackgroundWorkDto?)worker.CurrentWork, + worker.MainLoopLastException, + RunOnceQueue = worker.Works.Select(work => (BackgroundWorkDto)work), + Done = worker.Done.Select(work => (BackgroundWorkDto)work), + Felled = worker.Felled.Select(work => (BackgroundWorkDto)work), + }; + return Ok(result); + } - [HttpGet] - public IActionResult GetAll() - { - var result = new { - CurrentWork = (BackgroundWorkDto?)worker.CurrentWork, - worker.MainLoopLastException, - RunOnceQueue = worker.Works.Select(work => (BackgroundWorkDto)work), - Done = worker.Done.Select(work => (BackgroundWorkDto)work), - Felled = worker.Felled.Select(work => (BackgroundWorkDto)work), - }; - return Ok(result); - } + [HttpGet("current")] + public IActionResult GetCurrent() + { + var work = worker.CurrentWork; + if (work == null) + return NoContent(); - [HttpGet("current")] - public IActionResult GetCurrent() - { - var work = worker.CurrentWork; - if (work == null) - return NoContent(); + return Ok(work); + } - return Ok(work); - } + [HttpGet("failed")] + public IActionResult GetFelled() + { + var result = worker.Felled.Select(work => (BackgroundWorkDto)work); + return Ok(result); + } - [HttpGet("failed")] - public IActionResult GetFelled() - { - var result = worker.Felled.Select(work => (BackgroundWorkDto)work); - return Ok(result); - } + [HttpGet("done")] + public IActionResult GetDone() + { + var result = worker.Done.Select(work => (BackgroundWorkDto)work); + return Ok(result); + } - [HttpGet("done")] - public IActionResult GetDone() - { - var result = worker.Done.Select(work => (BackgroundWorkDto)work); - return Ok(result); - } - - [HttpPost("restart"), Obsolete("temporary method")] - public async Task RestartAsync(CancellationToken token) - { - await worker.StopAsync(token); - await worker.StartAsync(token); - return Ok(); - } + [HttpPost("restart"), Obsolete("temporary method")] + public async Task RestartAsync(CancellationToken token) + { + await worker.StopAsync(token); + await worker.StartAsync(token); + return Ok(); } } diff --git a/AsbCloudWebApi/Controllers/CrudController.cs b/AsbCloudWebApi/Controllers/CrudController.cs index 08b422c0..24ffd166 100644 --- a/AsbCloudWebApi/Controllers/CrudController.cs +++ b/AsbCloudWebApi/Controllers/CrudController.cs @@ -9,138 +9,136 @@ using System.Threading; using System.Threading.Tasks; // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + + +/// +/// CRUD контроллер для админки. +/// +/// +/// +[ApiController] +[Route("api/[controller]")] +[Authorize] +public abstract class CrudController : ControllerBase + where T : IId + where TService : ICrudRepository { + protected readonly TService service; - /// - /// CRUD контроллер для админки. - /// - /// - /// - [ApiController] - [Route("api/[controller]")] - [Authorize] - public abstract class CrudController : ControllerBase - where T : IId - where TService : ICrudRepository + public Func> InsertForbidAsync { get; protected set; } = null!; + public Func> UpdateForbidAsync { get; protected set; } = null!; + public Func> DeleteForbidAsync { get; protected set; } = null!; + + public CrudController(TService service) { - protected readonly TService service; - - public Func> InsertForbidAsync { get; protected set; } = null!; - public Func> UpdateForbidAsync { get; protected set; } = null!; - public Func> DeleteForbidAsync { get; protected set; } = null!; - - public CrudController(TService service) - { - this.service = service; - } - - /// - /// Получить все записи - /// - /// CancellationToken - /// все записи - [HttpGet] - [Permission] - public virtual async Task>> GetAllAsync(CancellationToken token) - { - var result = await service.GetAllAsync(token).ConfigureAwait(false); - return Ok(result); - } - - /// - /// Получить одну запись по Id - /// - /// id записи - /// - /// запись - [HttpGet("{id}")] - [Permission] - public virtual async Task> GetOrDefaultAsync(int id, CancellationToken token) - { - var result = await service.GetOrDefaultAsync(id, token).ConfigureAwait(false); - return Ok(result); - } - - /// - /// Добавить запись - /// - /// запись - /// - /// id - [HttpPost] - [Permission] - public virtual async Task> InsertAsync([FromBody] T value, CancellationToken token) - { - if (InsertForbidAsync is not null && await InsertForbidAsync(value, token)) - return Forbid(); - - var result = await service.InsertAsync(value, token).ConfigureAwait(false); - return Ok(result); - } - - /// - /// Добавить несколько записей
- /// При невозможности добавить любую из записей, все не будут добавлены. - ///
- /// записи - /// - /// id - [HttpPost("range")] - [Permission] - [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] - public virtual async Task> InsertRangeAsync([FromBody] IEnumerable values, CancellationToken token) - { - if (!values.Any()) - return this.ValidationBadRequest(nameof(values), "there is no values to add"); - - if (InsertForbidAsync is not null) - foreach (var value in values) - if (await InsertForbidAsync(value, token)) - return Forbid(); - - var result = await service.InsertRangeAsync(values, token).ConfigureAwait(false); - return Ok(result); - } - - /// - /// Редактировать запись по id - /// - /// запись - /// - /// 1 - успешно отредактировано, 0 - нет - [HttpPut] - [Permission] - [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] - public virtual async Task> UpdateAsync([FromBody] T value, CancellationToken token) - { - if (UpdateForbidAsync is not null && await UpdateForbidAsync(value, token)) - return Forbid(); - - var result = await service.UpdateAsync(value, token).ConfigureAwait(false); - if (result == ICrudRepository.ErrorIdNotFound) - return this.ValidationBadRequest(nameof(value.Id), $"id:{value.Id} does not exist"); - return Ok(result); - } - - /// - /// Удалить запись по id - /// - /// id записи - /// - /// 1 - успешно удалено, 0 - нет - [HttpDelete("{id}")] - [Permission] - public virtual async Task> DeleteAsync(int id, CancellationToken token) - { - if (DeleteForbidAsync is not null && await DeleteForbidAsync(id, token)) - return Forbid(); - - var result = await service.DeleteAsync(id, token).ConfigureAwait(false); - if (result == ICrudRepository.ErrorIdNotFound) - return NoContent(); - return Ok(result); - } + this.service = service; } + /// + /// Получить все записи + /// + /// CancellationToken + /// все записи + [HttpGet] + [Permission] + public virtual async Task>> GetAllAsync(CancellationToken token) + { + var result = await service.GetAllAsync(token).ConfigureAwait(false); + return Ok(result); + } + + /// + /// Получить одну запись по Id + /// + /// id записи + /// + /// запись + [HttpGet("{id}")] + [Permission] + public virtual async Task> GetOrDefaultAsync(int id, CancellationToken token) + { + var result = await service.GetOrDefaultAsync(id, token).ConfigureAwait(false); + return Ok(result); + } + + /// + /// Добавить запись + /// + /// запись + /// + /// id + [HttpPost] + [Permission] + public virtual async Task> InsertAsync([FromBody] T value, CancellationToken token) + { + if (InsertForbidAsync is not null && await InsertForbidAsync(value, token)) + return Forbid(); + + var result = await service.InsertAsync(value, token).ConfigureAwait(false); + return Ok(result); + } + + /// + /// Добавить несколько записей
+ /// При невозможности добавить любую из записей, все не будут добавлены. + ///
+ /// записи + /// + /// id + [HttpPost("range")] + [Permission] + [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] + public virtual async Task> InsertRangeAsync([FromBody] IEnumerable values, CancellationToken token) + { + if (!values.Any()) + return this.ValidationBadRequest(nameof(values), "there is no values to add"); + + if (InsertForbidAsync is not null) + foreach (var value in values) + if (await InsertForbidAsync(value, token)) + return Forbid(); + + var result = await service.InsertRangeAsync(values, token).ConfigureAwait(false); + return Ok(result); + } + + /// + /// Редактировать запись по id + /// + /// запись + /// + /// 1 - успешно отредактировано, 0 - нет + [HttpPut] + [Permission] + [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] + public virtual async Task> UpdateAsync([FromBody] T value, CancellationToken token) + { + if (UpdateForbidAsync is not null && await UpdateForbidAsync(value, token)) + return Forbid(); + + var result = await service.UpdateAsync(value, token).ConfigureAwait(false); + if (result == ICrudRepository.ErrorIdNotFound) + return this.ValidationBadRequest(nameof(value.Id), $"id:{value.Id} does not exist"); + return Ok(result); + } + + /// + /// Удалить запись по id + /// + /// id записи + /// + /// 1 - успешно удалено, 0 - нет + [HttpDelete("{id}")] + [Permission] + public virtual async Task> DeleteAsync(int id, CancellationToken token) + { + if (DeleteForbidAsync is not null && await DeleteForbidAsync(id, token)) + return Forbid(); + + var result = await service.DeleteAsync(id, token).ConfigureAwait(false); + if (result == ICrudRepository.ErrorIdNotFound) + return NoContent(); + return Ok(result); + } } diff --git a/AsbCloudWebApi/Controllers/CrudWellRelatedController.cs b/AsbCloudWebApi/Controllers/CrudWellRelatedController.cs index 245e0db8..98efad98 100644 --- a/AsbCloudWebApi/Controllers/CrudWellRelatedController.cs +++ b/AsbCloudWebApi/Controllers/CrudWellRelatedController.cs @@ -8,158 +8,156 @@ using System.Threading; using System.Threading.Tasks; // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + + +/// +/// CRUD контроллер dto связных со скважиной для админки. +/// +/// +/// +[ApiController] +[Route("api/[controller]")] +[Authorize] +public abstract class CrudWellRelatedController : CrudController + where T : IId, IWellRelated + where TService : IRepositoryWellRelated { + protected readonly IWellService wellService; - /// - /// CRUD контроллер dto связных со скважиной для админки. - /// - /// - /// - [ApiController] - [Route("api/[controller]")] - [Authorize] - public abstract class CrudWellRelatedController : CrudController - where T : IId, IWellRelated - where TService : IRepositoryWellRelated + protected CrudWellRelatedController(IWellService wellService, TService service) + : base(service) { - protected readonly IWellService wellService; - - protected CrudWellRelatedController(IWellService wellService, TService service) - : base(service) - { - this.wellService = wellService; - } - - /// - /// Получение всех записей, доступных компании пользователя. - /// - /// - /// - [HttpGet] - public override async Task>> GetAllAsync(CancellationToken token) - { - var idCompany = User.GetCompanyId(); - - if (idCompany is null) - return Forbid(); - - var wells = await wellService.GetAsync(new() { IdCompany = idCompany }, token); - if (!wells.Any()) - return NoContent(); - - var idsWells = wells.Select(w => w.Id); - var result = await service.GetByIdWellAsync(idsWells, token); - return Ok(result); - } - - /// - /// Получение всех записей, для скважины. - /// - /// - /// - /// - [HttpGet("well/{idWell}")] - public async Task>> GetByIdWellAsync(int idWell, CancellationToken token) - { - if (!await UserHasAccesToWellAsync(idWell, token)) - return Forbid(); - - var result = await service.GetByIdWellAsync(idWell, token); - return Ok(result); - } - - /// - /// Получить одну запись по Id - /// - /// id записи - /// - /// запись - [HttpGet("{id}")] - public override async Task> GetOrDefaultAsync(int id, CancellationToken token) - { - var actionResult = await base.GetOrDefaultAsync(id, token); - if(actionResult.Result is OkObjectResult okResult) - { - if (okResult.Value is IWellRelated wellRelated) - if (!await UserHasAccesToWellAsync(wellRelated.IdWell, token)) - return Forbid(); - } - - return actionResult; - } - - /// - /// Добавить запись - /// - /// запись - /// - /// id - [HttpPost] - public override async Task> InsertAsync([FromBody] T value, CancellationToken token) - { - if (!await UserHasAccesToWellAsync(value.IdWell, token)) - return Forbid(); - return await base.InsertAsync(value, token); - } - - /// - /// Добавить несколько записей
- /// При невозможности добавить любую из записей, все не будут добавлены. - ///
- /// записи - /// - /// id - [HttpPost("range")] - public override async Task> InsertRangeAsync([FromBody] IEnumerable values, CancellationToken token) - { - var idsWells = values.Select(v => v.IdWell).Distinct(); - foreach (var idWell in idsWells) - if (!await UserHasAccesToWellAsync(idWell, token)) - return Forbid(); - return await base.InsertRangeAsync(values, token); - } - - /// - /// Редактировать запись по id - /// - /// запись - /// - /// 1 - успешно отредактировано, 0 - нет - [HttpPut] - public override async Task> UpdateAsync([FromBody] T value, CancellationToken token) - { - if (!await UserHasAccesToWellAsync(value.IdWell, token)) - return Forbid(); - return await base.UpdateAsync(value, token); - } - - /// - /// Удалить запись по id - /// - /// id записи - /// - /// 1 - успешно удалено, 0 - нет - [HttpDelete("{id}")] - public override async Task> DeleteAsync(int id, CancellationToken token) - { - var item = await service.GetOrDefaultAsync(id, token); - if (item is null) - return NoContent(); - if (!await UserHasAccesToWellAsync(item.IdWell, token)) - return Forbid(); - return await base.DeleteAsync(id, token); - } - - protected async Task UserHasAccesToWellAsync(int idWell, CancellationToken token) - { - var idCompany = User.GetCompanyId(); - if (idCompany is not null && - await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token) - .ConfigureAwait(false)) - return true; - return false; - } + this.wellService = wellService; } + /// + /// Получение всех записей, доступных компании пользователя. + /// + /// + /// + [HttpGet] + public override async Task>> GetAllAsync(CancellationToken token) + { + var idCompany = User.GetCompanyId(); + + if (idCompany is null) + return Forbid(); + + var wells = await wellService.GetAsync(new() { IdCompany = idCompany }, token); + if (!wells.Any()) + return NoContent(); + + var idsWells = wells.Select(w => w.Id); + var result = await service.GetByIdWellAsync(idsWells, token); + return Ok(result); + } + + /// + /// Получение всех записей, для скважины. + /// + /// + /// + /// + [HttpGet("well/{idWell}")] + public async Task>> GetByIdWellAsync(int idWell, CancellationToken token) + { + if (!await UserHasAccesToWellAsync(idWell, token)) + return Forbid(); + + var result = await service.GetByIdWellAsync(idWell, token); + return Ok(result); + } + + /// + /// Получить одну запись по Id + /// + /// id записи + /// + /// запись + [HttpGet("{id}")] + public override async Task> GetOrDefaultAsync(int id, CancellationToken token) + { + var actionResult = await base.GetOrDefaultAsync(id, token); + if(actionResult.Result is OkObjectResult okResult) + { + if (okResult.Value is IWellRelated wellRelated) + if (!await UserHasAccesToWellAsync(wellRelated.IdWell, token)) + return Forbid(); + } + + return actionResult; + } + + /// + /// Добавить запись + /// + /// запись + /// + /// id + [HttpPost] + public override async Task> InsertAsync([FromBody] T value, CancellationToken token) + { + if (!await UserHasAccesToWellAsync(value.IdWell, token)) + return Forbid(); + return await base.InsertAsync(value, token); + } + + /// + /// Добавить несколько записей
+ /// При невозможности добавить любую из записей, все не будут добавлены. + ///
+ /// записи + /// + /// id + [HttpPost("range")] + public override async Task> InsertRangeAsync([FromBody] IEnumerable values, CancellationToken token) + { + var idsWells = values.Select(v => v.IdWell).Distinct(); + foreach (var idWell in idsWells) + if (!await UserHasAccesToWellAsync(idWell, token)) + return Forbid(); + return await base.InsertRangeAsync(values, token); + } + + /// + /// Редактировать запись по id + /// + /// запись + /// + /// 1 - успешно отредактировано, 0 - нет + [HttpPut] + public override async Task> UpdateAsync([FromBody] T value, CancellationToken token) + { + if (!await UserHasAccesToWellAsync(value.IdWell, token)) + return Forbid(); + return await base.UpdateAsync(value, token); + } + + /// + /// Удалить запись по id + /// + /// id записи + /// + /// 1 - успешно удалено, 0 - нет + [HttpDelete("{id}")] + public override async Task> DeleteAsync(int id, CancellationToken token) + { + var item = await service.GetOrDefaultAsync(id, token); + if (item is null) + return NoContent(); + if (!await UserHasAccesToWellAsync(item.IdWell, token)) + return Forbid(); + return await base.DeleteAsync(id, token); + } + + protected async Task UserHasAccesToWellAsync(int idWell, CancellationToken token) + { + var idCompany = User.GetCompanyId(); + if (idCompany is not null && + await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token) + .ConfigureAwait(false)) + return true; + return false; + } } diff --git a/AsbCloudWebApi/Controllers/DepositController.cs b/AsbCloudWebApi/Controllers/DepositController.cs index b18464b1..d7823a9b 100644 --- a/AsbCloudWebApi/Controllers/DepositController.cs +++ b/AsbCloudWebApi/Controllers/DepositController.cs @@ -6,64 +6,63 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Инфо о месторождениях +/// +[Route("api/deposit")] +[ApiController] +[Authorize] +public class DepositController : ControllerBase { - /// - /// Инфо о месторождениях - /// - [Route("api/deposit")] - [ApiController] - [Authorize] - public class DepositController : ControllerBase + private readonly IDepositRepository depositService; + + public DepositController(IDepositRepository depositService) { - private readonly IDepositRepository depositService; - - public DepositController(IDepositRepository depositService) - { - this.depositService = depositService; - } - - /// - /// Получает список доступных пользователю месторождений - /// - /// Токен отмены задачи - /// - [HttpGet] - [Permission] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetDepositsAsync(CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - - if (idCompany is null) - return Forbid(); - - var result = await depositService.GetAsync((int)idCompany, - token).ConfigureAwait(false); - return Ok(result); - } - - /// - /// Получает список доступных пользователю кустов месторождения - /// - /// - /// Токен отмены задачи - /// - [HttpGet("{depositId}")] - [Permission] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetClustersAsync(int depositId, - CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - - if (idCompany is null) - return Forbid(); - - var result = await depositService.GetClustersAsync((int)idCompany, - depositId, token).ConfigureAwait(false); - return Ok(result); - } - + this.depositService = depositService; } + + /// + /// Получает список доступных пользователю месторождений + /// + /// Токен отмены задачи + /// + [HttpGet] + [Permission] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetDepositsAsync(CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + + if (idCompany is null) + return Forbid(); + + var result = await depositService.GetAsync((int)idCompany, + token).ConfigureAwait(false); + return Ok(result); + } + + /// + /// Получает список доступных пользователю кустов месторождения + /// + /// + /// Токен отмены задачи + /// + [HttpGet("{depositId}")] + [Permission] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetClustersAsync(int depositId, + CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + + if (idCompany is null) + return Forbid(); + + var result = await depositService.GetClustersAsync((int)idCompany, + depositId, token).ConfigureAwait(false); + return Ok(result); + } + } diff --git a/AsbCloudWebApi/Controllers/DrillerController.cs b/AsbCloudWebApi/Controllers/DrillerController.cs index 347abe6e..6c078f7d 100644 --- a/AsbCloudWebApi/Controllers/DrillerController.cs +++ b/AsbCloudWebApi/Controllers/DrillerController.cs @@ -9,48 +9,47 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Справочник бурильщиков +/// +[Route("api/driller")] +[ApiController] +[Authorize] +public class DrillerController : CrudController> { - /// - /// Справочник бурильщиков - /// - [Route("api/driller")] - [ApiController] - [Authorize] - public class DrillerController : CrudController> + private IScheduleRepository scheduleRepository; + + public DrillerController(ICrudRepository service, IScheduleRepository scheduleRepository) + : base(service) { - private IScheduleRepository scheduleRepository; + this.scheduleRepository = scheduleRepository; + } - public DrillerController(ICrudRepository service, IScheduleRepository scheduleRepository) - : base(service) + /// + /// Получить список бурильщиков по ключам скважин + /// + /// массив ключей скважин + /// token + /// все записи + [HttpGet("/api/drillers")] + [Permission] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + public async Task GetAsync([FromQuery] IEnumerable idsWells, CancellationToken token) + { + var request = new GetStatRequest() { - this.scheduleRepository = scheduleRepository; - } + IdsWells = idsWells, + }; + var schedulePage = await scheduleRepository.GetPageAsync(request, token); + var drillers = schedulePage + .Select(s => s.Driller) + .Where(d => d is not null) + .GroupBy(d => d!.Id) + .Select(group => group.First()) + .OrderBy(d => d!.Surname); - /// - /// Получить список бурильщиков по ключам скважин - /// - /// массив ключей скважин - /// token - /// все записи - [HttpGet("/api/drillers")] - [Permission] - [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] - public async Task GetAsync([FromQuery] IEnumerable idsWells, CancellationToken token) - { - var request = new GetStatRequest() - { - IdsWells = idsWells, - }; - var schedulePage = await scheduleRepository.GetPageAsync(request, token); - var drillers = schedulePage - .Select(s => s.Driller) - .Where(d => d is not null) - .GroupBy(d => d!.Id) - .Select(group => group.First()) - .OrderBy(d => d!.Surname); - - return Ok(drillers); - } + return Ok(drillers); } } diff --git a/AsbCloudWebApi/Controllers/DrillingProgramController.cs b/AsbCloudWebApi/Controllers/DrillingProgramController.cs index 94e987df..b04b27bc 100644 --- a/AsbCloudWebApi/Controllers/DrillingProgramController.cs +++ b/AsbCloudWebApi/Controllers/DrillingProgramController.cs @@ -9,286 +9,285 @@ using System.ComponentModel.DataAnnotations; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Формирование программы бурения +/// +[Route("api/well/{idWell}/drillingProgram")] +[ApiController] +[Authorize] +public class DrillingProgramController : ControllerBase { - /// - /// Формирование программы бурения - /// - [Route("api/well/{idWell}/drillingProgram")] - [ApiController] - [Authorize] - public class DrillingProgramController : ControllerBase + private readonly IDrillingProgramService drillingProgramService; + private readonly IWellService wellService; + + public DrillingProgramController(IDrillingProgramService drillingProgramService, IWellService wellService) { - private readonly IDrillingProgramService drillingProgramService; - private readonly IWellService wellService; + this.drillingProgramService = drillingProgramService; + this.wellService = wellService; + } - public DrillingProgramController(IDrillingProgramService drillingProgramService, IWellService wellService) - { - this.drillingProgramService = drillingProgramService; - this.wellService = wellService; - } + /// + /// Список категорий файлов из которых состоит программа бурения + /// + /// + /// + [HttpGet("categories")] + [ProducesResponseType(typeof(FileCategoryDto[]), (int)System.Net.HttpStatusCode.OK)] + public async Task GetCategories(CancellationToken token) + { + var result = await drillingProgramService.GetCategoriesAsync(token); + return Ok(result); + } - /// - /// Список категорий файлов из которых состоит программа бурения - /// - /// - /// - [HttpGet("categories")] - [ProducesResponseType(typeof(FileCategoryDto[]), (int)System.Net.HttpStatusCode.OK)] - public async Task GetCategories(CancellationToken token) - { - var result = await drillingProgramService.GetCategoriesAsync(token); - return Ok(result); - } + /// + /// Список пользователей + /// + /// id скважины + /// + /// + [HttpGet("availableUsers")] + [ProducesResponseType(typeof(FileCategoryDto[]), (int)System.Net.HttpStatusCode.OK)] + public async Task GetAvailableUsers(int idWell, CancellationToken token) + { + var result = await drillingProgramService.GetAvailableUsers(idWell, token); + return Ok(result); + } - /// - /// Список пользователей - /// - /// id скважины - /// - /// - [HttpGet("availableUsers")] - [ProducesResponseType(typeof(FileCategoryDto[]), (int)System.Net.HttpStatusCode.OK)] - public async Task GetAvailableUsers(int idWell, CancellationToken token) - { - var result = await drillingProgramService.GetAvailableUsers(idWell, token); - return Ok(result); - } + /// + /// Состояние процесса согласования программы бурения + /// + /// id скважины + /// Токен отмены задачи + /// Возвращает файл программы бурения + [HttpGet] + [ProducesResponseType(typeof(DrillingProgramStateDto), (int)System.Net.HttpStatusCode.OK)] + public async Task GetStateAsync(int idWell, CancellationToken token) + { + var idCompany = User.GetCompanyId(); - /// - /// Состояние процесса согласования программы бурения - /// - /// id скважины - /// Токен отмены задачи - /// Возвращает файл программы бурения - [HttpGet] - [ProducesResponseType(typeof(DrillingProgramStateDto), (int)System.Net.HttpStatusCode.OK)] - public async Task GetStateAsync(int idWell, CancellationToken token) - { - var idCompany = User.GetCompanyId(); + var idUser = User.GetUserId(); - var idUser = User.GetUserId(); - - if (idCompany is null || idUser is null || - !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) - return Forbid(); - - var result = await drillingProgramService.GetStateAsync(idWell, (int)idUser, token); - return Ok(result); - } - - /// - /// Сброс ошибки формирования ПБ - /// - /// - /// - [HttpDelete("errors")] - [Permission("DrillingProgram.get")] - public IActionResult ClearError(int idWell) - { - drillingProgramService.ClearError(idWell); - return Ok(); - } - - /// - /// Загрузка файла для части программы бурения - /// - /// - /// ID части программы. Не путать с категорией файла - /// - /// - /// - [HttpPost("part/{idFileCategory}")] - [Permission("DrillingProgram.get")] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task AddFile( - int idWell, - int idFileCategory, - [FromForm] IFormFileCollection files, - CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - int? idUser = User.GetUserId(); - - if (idCompany is null || idUser is null) - return Forbid(); - - if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + if (idCompany is null || idUser is null || + !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token).ConfigureAwait(false)) - return Forbid(); + return Forbid(); - if (files.Count > 1) - return this.ValidationBadRequest(nameof(files), "only 1 file can be uploaded"); + var result = await drillingProgramService.GetStateAsync(idWell, (int)idUser, token); + return Ok(result); + } - if (files.Count == 0) - return this.ValidationBadRequest(nameof(files), "at list 1 file should be uploaded"); + /// + /// Сброс ошибки формирования ПБ + /// + /// + /// + [HttpDelete("errors")] + [Permission("DrillingProgram.get")] + public IActionResult ClearError(int idWell) + { + drillingProgramService.ClearError(idWell); + return Ok(); + } - var fileName = files[0].FileName; - - var fileStream = files[0].OpenReadStream(); - var result = await drillingProgramService.AddFile(idWell, idFileCategory, (int)idUser, fileName, fileStream, token); + /// + /// Загрузка файла для части программы бурения + /// + /// + /// ID части программы. Не путать с категорией файла + /// + /// + /// + [HttpPost("part/{idFileCategory}")] + [Permission("DrillingProgram.get")] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task AddFile( + int idWell, + int idFileCategory, + [FromForm] IFormFileCollection files, + CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + int? idUser = User.GetUserId(); - return Ok(result); - } + if (idCompany is null || idUser is null) + return Forbid(); - /// - /// Добавляет разделы программы бурения - /// - /// - /// Список категорий файлов, по которым будут добавлены части ПБ - /// - /// - [HttpPost("part")] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task AddPartsAsync(int idWell, [Required] IEnumerable idFileCategories, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - int? idUser = User.GetUserId(); + if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false)) + return Forbid(); - if (idCompany is null || idUser is null) - return Forbid(); + if (files.Count > 1) + return this.ValidationBadRequest(nameof(files), "only 1 file can be uploaded"); - if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + if (files.Count == 0) + return this.ValidationBadRequest(nameof(files), "at list 1 file should be uploaded"); + + var fileName = files[0].FileName; + + var fileStream = files[0].OpenReadStream(); + var result = await drillingProgramService.AddFile(idWell, idFileCategory, (int)idUser, fileName, fileStream, token); + + return Ok(result); + } + + /// + /// Добавляет разделы программы бурения + /// + /// + /// Список категорий файлов, по которым будут добавлены части ПБ + /// + /// + [HttpPost("part")] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task AddPartsAsync(int idWell, [Required] IEnumerable idFileCategories, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + int? idUser = User.GetUserId(); + + if (idCompany is null || idUser is null) + return Forbid(); + + if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false)) + return Forbid(); + + var result = await drillingProgramService.AddPartsAsync(idWell, idFileCategories, token); + return Ok(result); + } + + /// + /// Удаляет разделы программы бурения + /// + /// + /// Список категорий файлов, по которым будут удалены части ПБ + /// + /// + [HttpDelete("part")] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task RemovePartsAsync(int idWell, [Required] IEnumerable idFileCategories, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + int? idUser = User.GetUserId(); + + if (idCompany is null || idUser is null) + return Forbid(); + + if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false)) + return Forbid(); + + var result = await drillingProgramService.RemovePartsAsync(idWell, idFileCategories, token); + return Ok(result); + } + + /// + /// Добавить пользователя в список publishers или approvers части программы бурения + /// + /// + /// + /// + /// + /// + /// + [HttpPost("part/{idFileCategory}/user")] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task AddUserAsync(int idWell, [Required] int idUser, int idFileCategory, [Required] int idUserRole, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + int? idUserEditor = User.GetUserId(); + + if (idCompany is null || idUserEditor is null) + return Forbid(); + + if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false)) + return Forbid(); + + var result = await drillingProgramService.AddUserAsync(idWell, idFileCategory, idUser, idUserRole, token); + return Ok(result); + } + + /// + /// Удалить пользователя из списка publishers или approvers части программы бурения + /// + /// + /// + /// + /// + /// + /// + [HttpDelete("part/{idFileCategory}/user/{idUser}")] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task RemoveUserAsync(int idWell, int idUser, int idFileCategory, [Required] int idUserRole, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + int? idUserEditor = User.GetUserId(); + + if (idCompany is null || idUserEditor is null) + return Forbid(); + + if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false)) + return Forbid(); + + var result = await drillingProgramService.RemoveUserAsync(idWell, idFileCategory, idUser, idUserRole, token); + return Ok(result); + } + + /// + /// Создает метку для файла входящего в программу бурения, заменить существующую + /// + /// id скважины + /// метка файла + /// Токен отмены задачи + /// + [HttpPost("fileMark")] + [Permission("DrillingProgram.get")] + public async Task AddOrReplaceFileMarkAsync(int idWell, FileMarkDto markDto, CancellationToken token) + { + var idCompany = User.GetCompanyId(); + + var idUser = User.GetUserId(); + + if (idCompany is null || idUser is null || + !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token).ConfigureAwait(false)) - return Forbid(); + return Forbid(); - var result = await drillingProgramService.AddPartsAsync(idWell, idFileCategories, token); - return Ok(result); - } + var result = await drillingProgramService.AddOrReplaceFileMarkAsync(markDto, (int)idUser, token) + .ConfigureAwait(false); - /// - /// Удаляет разделы программы бурения - /// - /// - /// Список категорий файлов, по которым будут удалены части ПБ - /// - /// - [HttpDelete("part")] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task RemovePartsAsync(int idWell, [Required] IEnumerable idFileCategories, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - int? idUser = User.GetUserId(); + return Ok(result); + } - if (idCompany is null || idUser is null) - return Forbid(); + /// + /// Помечает метку у файла входящего, в программу бурения, как удаленную + /// + /// id скважины + /// id метки + /// Токен отмены задачи + /// + [HttpDelete("fileMark/{idMark}")] + [Permission("DrillingProgram.get")] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task MarkAsDeletedFileMarkAsync(int idWell, int idMark, + CancellationToken token) + { + var idCompany = User.GetCompanyId(); - if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) - return Forbid(); + if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false)) + return Forbid(); - var result = await drillingProgramService.RemovePartsAsync(idWell, idFileCategories, token); - return Ok(result); - } + var result = await drillingProgramService.MarkAsDeletedFileMarkAsync(idMark, token) + .ConfigureAwait(false); - /// - /// Добавить пользователя в список publishers или approvers части программы бурения - /// - /// - /// - /// - /// - /// - /// - [HttpPost("part/{idFileCategory}/user")] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task AddUserAsync(int idWell, [Required] int idUser, int idFileCategory, [Required] int idUserRole, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - int? idUserEditor = User.GetUserId(); - - if (idCompany is null || idUserEditor is null) - return Forbid(); - - if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) - return Forbid(); - - var result = await drillingProgramService.AddUserAsync(idWell, idFileCategory, idUser, idUserRole, token); - return Ok(result); - } - - /// - /// Удалить пользователя из списка publishers или approvers части программы бурения - /// - /// - /// - /// - /// - /// - /// - [HttpDelete("part/{idFileCategory}/user/{idUser}")] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task RemoveUserAsync(int idWell, int idUser, int idFileCategory, [Required] int idUserRole, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - int? idUserEditor = User.GetUserId(); - - if (idCompany is null || idUserEditor is null) - return Forbid(); - - if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) - return Forbid(); - - var result = await drillingProgramService.RemoveUserAsync(idWell, idFileCategory, idUser, idUserRole, token); - return Ok(result); - } - - /// - /// Создает метку для файла входящего в программу бурения, заменить существующую - /// - /// id скважины - /// метка файла - /// Токен отмены задачи - /// - [HttpPost("fileMark")] - [Permission("DrillingProgram.get")] - public async Task AddOrReplaceFileMarkAsync(int idWell, FileMarkDto markDto, CancellationToken token) - { - var idCompany = User.GetCompanyId(); - - var idUser = User.GetUserId(); - - if (idCompany is null || idUser is null || - !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) - return Forbid(); - - var result = await drillingProgramService.AddOrReplaceFileMarkAsync(markDto, (int)idUser, token) - .ConfigureAwait(false); - - return Ok(result); - } - - /// - /// Помечает метку у файла входящего, в программу бурения, как удаленную - /// - /// id скважины - /// id метки - /// Токен отмены задачи - /// - [HttpDelete("fileMark/{idMark}")] - [Permission("DrillingProgram.get")] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task MarkAsDeletedFileMarkAsync(int idWell, int idMark, - CancellationToken token) - { - var idCompany = User.GetCompanyId(); - - if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) - return Forbid(); - - var result = await drillingProgramService.MarkAsDeletedFileMarkAsync(idMark, token) - .ConfigureAwait(false); - - return Ok(result); - } + return Ok(result); } } diff --git a/AsbCloudWebApi/Controllers/FaqController.cs b/AsbCloudWebApi/Controllers/FaqController.cs index 6af362b0..8cec0bf5 100644 --- a/AsbCloudWebApi/Controllers/FaqController.cs +++ b/AsbCloudWebApi/Controllers/FaqController.cs @@ -8,126 +8,125 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// контроллер по работе с faq-вопросами +/// +[Route("api/faq")] +[ApiController] +[Authorize] +public class FaqController : ControllerBase { - /// - /// контроллер по работе с faq-вопросами - /// - [Route("api/faq")] - [ApiController] - [Authorize] - public class FaqController : ControllerBase + private readonly IFaqRepository faqRepository; + + public FaqController(IFaqRepository faqRepository) { - private readonly IFaqRepository faqRepository; + this.faqRepository = faqRepository; + } - public FaqController(IFaqRepository faqRepository) - { - this.faqRepository = faqRepository; - } + /// + /// получение списка faq-вопросов + /// + /// + /// + /// + [HttpGet] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetFilteredAsync( + [FromQuery] FaqRequest request, + CancellationToken token) + { + var result = await faqRepository.GetFilteredAsync(request, token).ConfigureAwait(false); + return Ok(result); + } - /// - /// получение списка faq-вопросов - /// - /// - /// - /// - [HttpGet] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetFilteredAsync( - [FromQuery] FaqRequest request, + /// + /// добавление нового вопроса + /// + /// вопрос + /// + /// + [HttpPost] + [ProducesResponseType(typeof(FaqDto), (int)System.Net.HttpStatusCode.OK)] + public async Task InsertAsync( + [FromBody] FaqDto faqDto, CancellationToken token) - { - var result = await faqRepository.GetFilteredAsync(request, token).ConfigureAwait(false); - return Ok(result); - } + { + faqDto.IdAuthorQuestion = User.GetUserId()!.Value; - /// - /// добавление нового вопроса - /// - /// вопрос - /// - /// - [HttpPost] - [ProducesResponseType(typeof(FaqDto), (int)System.Net.HttpStatusCode.OK)] - public async Task InsertAsync( - [FromBody] FaqDto faqDto, - CancellationToken token) - { - faqDto.IdAuthorQuestion = User.GetUserId()!.Value; + var result = await faqRepository.InsertAsync(faqDto, token) + .ConfigureAwait(false); - var result = await faqRepository.InsertAsync(faqDto, token) - .ConfigureAwait(false); + return Ok(result); + } - return Ok(result); - } + [HttpPut] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task UpdateAsync([FromBody] FaqDto faqDto, CancellationToken token) + { + faqDto.IdAuthorAnswer = User.GetUserId()!.Value; - [HttpPut] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task UpdateAsync([FromBody] FaqDto faqDto, CancellationToken token) - { - faqDto.IdAuthorAnswer = User.GetUserId()!.Value; + var result = await faqRepository.UpdateAsync(faqDto, token) + .ConfigureAwait(false); + return Ok(result); + } - var result = await faqRepository.UpdateAsync(faqDto, token) - .ConfigureAwait(false); - return Ok(result); - } + /// + /// Объединение 2 вопросов в один + /// + /// + /// + /// настройка, объединять ли текст 2-х вопросов в один или нет + /// + /// + /// + [HttpPost("merge")] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task MergeAsync( + [FromQuery] int sourceId1, + [FromQuery] int sourceId2, + [FromQuery] bool mergeQuestions, + CancellationToken token) + { + var result = await faqRepository.MergeAsync(sourceId1, sourceId2, mergeQuestions, token) + .ConfigureAwait(false); + return Ok(result); + } - /// - /// Объединение 2 вопросов в один - /// - /// - /// - /// настройка, объединять ли текст 2-х вопросов в один или нет - /// - /// - /// - [HttpPost("merge")] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task MergeAsync( - [FromQuery] int sourceId1, - [FromQuery] int sourceId2, - [FromQuery] bool mergeQuestions, - CancellationToken token) - { - var result = await faqRepository.MergeAsync(sourceId1, sourceId2, mergeQuestions, token) - .ConfigureAwait(false); - return Ok(result); - } + /// + /// Помечает вопрос как удаленный + /// + /// id вопроса + /// Токен отмены задачи + /// Количество удаленных из БД строк + [HttpPut("{id}")] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task MarkAsDeletedAsync(int id, CancellationToken token) + { + var result = await faqRepository.MarkAsDeletedAsync(id, token) + .ConfigureAwait(false); - /// - /// Помечает вопрос как удаленный - /// - /// id вопроса - /// Токен отмены задачи - /// Количество удаленных из БД строк - [HttpPut("{id}")] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task MarkAsDeletedAsync(int id, CancellationToken token) - { - var result = await faqRepository.MarkAsDeletedAsync(id, token) - .ConfigureAwait(false); + return Ok(result); + } - return Ok(result); - } + /// + /// Удаление вопроса + /// + /// id вопроса + /// Токен отмены задачи + /// Количество удаленных из БД строк + [HttpDelete("{id}")] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task DeleteAsync(int id, CancellationToken token) + { + var result = await faqRepository.DeleteAsync(id, token) + .ConfigureAwait(false); - /// - /// Удаление вопроса - /// - /// id вопроса - /// Токен отмены задачи - /// Количество удаленных из БД строк - [HttpDelete("{id}")] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task DeleteAsync(int id, CancellationToken token) - { - var result = await faqRepository.DeleteAsync(id, token) - .ConfigureAwait(false); - - return Ok(result); - } + return Ok(result); } } diff --git a/AsbCloudWebApi/Controllers/FileController.cs b/AsbCloudWebApi/Controllers/FileController.cs index 0c11e9a0..561f2df5 100644 --- a/AsbCloudWebApi/Controllers/FileController.cs +++ b/AsbCloudWebApi/Controllers/FileController.cs @@ -9,235 +9,233 @@ using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Repositories; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + + +/// +/// Хранение файлов +/// +[Route("api/well/{idWell}/files")] +[ApiController] +[Authorize] +public class FileController : ControllerBase { + private readonly FileService fileService; + private readonly IWellService wellService; - /// - /// Хранение файлов - /// - [Route("api/well/{idWell}/files")] - [ApiController] - [Authorize] - public class FileController : ControllerBase + public FileController(FileService fileService, IWellService wellService) { - private readonly FileService fileService; - private readonly IWellService wellService; - - public FileController(FileService fileService, IWellService wellService) - { - this.fileService = fileService; - this.wellService = wellService; - } - - /// - /// Сохраняет переданные файлы и информацию о них - /// - /// id скважины - /// id категории файла - /// Коллекция файлов - /// dependency - /// Токен отмены задачи - /// - [HttpPost] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task SaveFilesAsync(int idWell, int idCategory, - [FromForm] IFormFileCollection files, [FromServices] IUserRepository userRepository, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - int? idUser = User.GetUserId(); - - if (idCompany is null || idUser is null) - return Forbid(); - - if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) - return Forbid(); - - if (!userRepository.HasPermission((int)idUser, $"File.edit{idCategory}")) - return Forbid(); - - foreach (var file in files) - { - var fileStream = file.OpenReadStream(); - await fileService.SaveAsync(idWell, idUser ?? 0, idCategory, file.FileName, - fileStream, token).ConfigureAwait(false); - } - - return Ok(); - } - - /// - /// Возвращает информацию о файлах для скважины в выбраной категории - /// - /// - /// Токен отмены задачи - /// Список информации о файлах в этой категории - [HttpGet("/api/files")] - [Permission] - [ProducesResponseType(typeof(PaginationContainer), (int)System.Net.HttpStatusCode.OK)] - public async Task GetFilesInfoAsync( - [FromQuery] FileRequest request, - CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - - if (request.IdCategory is null || idCompany is null) - return Forbid(); - - if (!await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, - request.IdWell, token).ConfigureAwait(false)) - return Forbid(); - - var filesInfo = await fileService.GetInfosPaginatedAsync(request, token).ConfigureAwait(false); - - return Ok(filesInfo); - } - - /// - /// Возвращает файл с диска на сервере - /// - /// id запрашиваемого файла - /// Токен отмены задачи - /// Запрашиваемый файл - [HttpGet("{idFile}")] - [Permission] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] - public async Task GetFileAsync( - int idFile, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - - if (idCompany is null) - return Forbid(); - - var fileInfo = await fileService.GetOrDefaultAsync(idFile, token); - - if (fileInfo is null) - return NotFound(idFile); - - if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - fileInfo.IdWell, token).ConfigureAwait(false)) - return Forbid(); - - var fileStream = fileService.GetFileStream(fileInfo); - - return File(fileStream, "application/octet-stream", fileInfo.Name); - } - - /// - /// Помечает файл как удаленный - /// - /// id скважины - /// id запрашиваемого файла - /// dependency - /// Токен отмены задачи - /// - [HttpDelete("{idFile}")] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task DeleteAsync(int idWell, int idFile, - [FromServices] IUserRepository userRepository, - CancellationToken token) - { - int? idUser = User.GetUserId(); - - int? idCompany = User.GetCompanyId(); - - if (idUser is null || idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) - return Forbid(); - - var fileInfo = await fileService.GetOrDefaultAsync(idFile, token); - - if (fileInfo is null) - return NotFound(idFile); - - if (!userRepository.HasPermission((int)idUser, $"File.edit{fileInfo?.IdCategory}")) - return Forbid(); - - var result = await fileService.MarkAsDeletedAsync(idFile, token); - - return Ok(result); - } - - /// - /// Создает метку для файла - /// - /// id скважины - /// метка файла - /// Токен отмены задачи - /// - [HttpPost("fileMark")] - [Permission] - public async Task CreateFileMarkAsync(int idWell, FileMarkDto markDto, CancellationToken token) - { - var idCompany = User.GetCompanyId(); - - var idUser = User.GetUserId(); - - if (idCompany is null || idUser is null || - !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) - return Forbid(); - - var result = await fileService.CreateFileMarkAsync(markDto, (int)idUser, token) - .ConfigureAwait(false); - - return Ok(result); - } - - /// - /// Помечает метку у файла как удаленную - /// - /// id скважины - /// id метки - /// Токен отмены задачи - /// - [HttpDelete("fileMark")] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task DeleteFileMarkAsync(int idWell, int idMark, - CancellationToken token) - { - var idCompany = User.GetCompanyId(); - - if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) - return Forbid(); - - var result = await fileService.MarkFileMarkAsDeletedAsync(idMark, token) - .ConfigureAwait(false); - - return Ok(result); - } - - /// - /// Возвращает информацию о файле - /// - /// id запрашиваемого файла - /// Токен отмены задачи - /// Запрашиваемый файл - [HttpGet("/api/files/{idFile}")] - [Permission] - [ProducesResponseType(typeof(FileInfoDto), (int)System.Net.HttpStatusCode.OK)] - public async Task GetFileInfoAsync([FromRoute] int idFile, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - - if (idCompany is null) - return Forbid(); - - try - { - var fileInfo = await fileService.GetOrDefaultAsync(idFile, token).ConfigureAwait(false); - return Ok(fileInfo); - } - catch (FileNotFoundException ex) - { - return NotFound(ex.FileName); - } - } + this.fileService = fileService; + this.wellService = wellService; } + /// + /// Сохраняет переданные файлы и информацию о них + /// + /// id скважины + /// id категории файла + /// Коллекция файлов + /// dependency + /// Токен отмены задачи + /// + [HttpPost] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task SaveFilesAsync(int idWell, int idCategory, + [FromForm] IFormFileCollection files, [FromServices] IUserRepository userRepository, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + int? idUser = User.GetUserId(); + + if (idCompany is null || idUser is null) + return Forbid(); + + if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false)) + return Forbid(); + + if (!userRepository.HasPermission((int)idUser, $"File.edit{idCategory}")) + return Forbid(); + + foreach (var file in files) + { + var fileStream = file.OpenReadStream(); + await fileService.SaveAsync(idWell, idUser ?? 0, idCategory, file.FileName, + fileStream, token).ConfigureAwait(false); + } + + return Ok(); + } + + /// + /// Возвращает информацию о файлах для скважины в выбраной категории + /// + /// + /// Токен отмены задачи + /// Список информации о файлах в этой категории + [HttpGet("/api/files")] + [Permission] + [ProducesResponseType(typeof(PaginationContainer), (int)System.Net.HttpStatusCode.OK)] + public async Task GetFilesInfoAsync( + [FromQuery] FileRequest request, + CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + + if (request.IdCategory is null || idCompany is null) + return Forbid(); + + if (!await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, + request.IdWell, token).ConfigureAwait(false)) + return Forbid(); + + var filesInfo = await fileService.GetInfosPaginatedAsync(request, token).ConfigureAwait(false); + + return Ok(filesInfo); + } + + /// + /// Возвращает файл с диска на сервере + /// + /// id запрашиваемого файла + /// Токен отмены задачи + /// Запрашиваемый файл + [HttpGet("{idFile}")] + [Permission] + [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] + public async Task GetFileAsync( + int idFile, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + + if (idCompany is null) + return Forbid(); + + var fileInfo = await fileService.GetOrDefaultAsync(idFile, token); + + if (fileInfo is null) + return NotFound(idFile); + + if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + fileInfo.IdWell, token).ConfigureAwait(false)) + return Forbid(); + + var fileStream = fileService.GetFileStream(fileInfo); + + return File(fileStream, "application/octet-stream", fileInfo.Name); + } + + /// + /// Помечает файл как удаленный + /// + /// id скважины + /// id запрашиваемого файла + /// dependency + /// Токен отмены задачи + /// + [HttpDelete("{idFile}")] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task DeleteAsync(int idWell, int idFile, + [FromServices] IUserRepository userRepository, + CancellationToken token) + { + int? idUser = User.GetUserId(); + + int? idCompany = User.GetCompanyId(); + + if (idUser is null || idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false)) + return Forbid(); + + var fileInfo = await fileService.GetOrDefaultAsync(idFile, token); + + if (fileInfo is null) + return NotFound(idFile); + + if (!userRepository.HasPermission((int)idUser, $"File.edit{fileInfo?.IdCategory}")) + return Forbid(); + + var result = await fileService.MarkAsDeletedAsync(idFile, token); + + return Ok(result); + } + + /// + /// Создает метку для файла + /// + /// id скважины + /// метка файла + /// Токен отмены задачи + /// + [HttpPost("fileMark")] + [Permission] + public async Task CreateFileMarkAsync(int idWell, FileMarkDto markDto, CancellationToken token) + { + var idCompany = User.GetCompanyId(); + + var idUser = User.GetUserId(); + + if (idCompany is null || idUser is null || + !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false)) + return Forbid(); + + var result = await fileService.CreateFileMarkAsync(markDto, (int)idUser, token) + .ConfigureAwait(false); + + return Ok(result); + } + + /// + /// Помечает метку у файла как удаленную + /// + /// id скважины + /// id метки + /// Токен отмены задачи + /// + [HttpDelete("fileMark")] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task DeleteFileMarkAsync(int idWell, int idMark, + CancellationToken token) + { + var idCompany = User.GetCompanyId(); + + if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false)) + return Forbid(); + + var result = await fileService.MarkFileMarkAsDeletedAsync(idMark, token) + .ConfigureAwait(false); + + return Ok(result); + } + + /// + /// Возвращает информацию о файле + /// + /// id запрашиваемого файла + /// Токен отмены задачи + /// Запрашиваемый файл + [HttpGet("/api/files/{idFile}")] + [Permission] + [ProducesResponseType(typeof(FileInfoDto), (int)System.Net.HttpStatusCode.OK)] + public async Task GetFileInfoAsync([FromRoute] int idFile, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + + if (idCompany is null) + return Forbid(); + + try + { + var fileInfo = await fileService.GetOrDefaultAsync(idFile, token).ConfigureAwait(false); + return Ok(fileInfo); + } + catch (FileNotFoundException ex) + { + return NotFound(ex.FileName); + } + } } diff --git a/AsbCloudWebApi/Controllers/LimitingParameterController.cs b/AsbCloudWebApi/Controllers/LimitingParameterController.cs index 527e1646..3b2a67b1 100644 --- a/AsbCloudWebApi/Controllers/LimitingParameterController.cs +++ b/AsbCloudWebApi/Controllers/LimitingParameterController.cs @@ -7,59 +7,58 @@ using System.Collections.Generic; using System.Threading.Tasks; using System.Threading; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +[Route("api/[controller]")] +[ApiController] +[Authorize] +public class LimitingParameterController : ControllerBase { - [Route("api/[controller]")] - [ApiController] - [Authorize] - public class LimitingParameterController : ControllerBase + private readonly ILimitingParameterService limitingParameterService; + private readonly IWellService wellService; + + public LimitingParameterController(ILimitingParameterService limitingParameterService, + IWellService wellService) + { + this.limitingParameterService = limitingParameterService; + this.wellService = wellService; + } + + /// + /// Получение статистики по ограничивающим параметрам + /// + /// + /// + /// + [HttpGet("stat")] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetStatAsync([FromQuery] LimitingParameterRequest request, CancellationToken token) { - private readonly ILimitingParameterService limitingParameterService; - private readonly IWellService wellService; + if (!await UserHasAccesToWellAsync(request.IdWell, token)) + return Forbid(); + var subsystemResult = await limitingParameterService.GetStatAsync(request, token); + return Ok(subsystemResult); + } - public LimitingParameterController(ILimitingParameterService limitingParameterService, - IWellService wellService) - { - this.limitingParameterService = limitingParameterService; - this.wellService = wellService; - } + /// + /// Получение словаря названий ограничений + /// + /// + [HttpGet("names")] + [ProducesResponseType(typeof(Dictionary), (int)System.Net.HttpStatusCode.OK)] + public IActionResult GetLimitingParameteraNames() + { + var feedRegulatorData = limitingParameterService.GetLimitingParameteraNames(); + return Ok(feedRegulatorData); + } - /// - /// Получение статистики по ограничивающим параметрам - /// - /// - /// - /// - [HttpGet("stat")] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetStatAsync([FromQuery] LimitingParameterRequest request, CancellationToken token) - { - if (!await UserHasAccesToWellAsync(request.IdWell, token)) - return Forbid(); - var subsystemResult = await limitingParameterService.GetStatAsync(request, token); - return Ok(subsystemResult); - } - - /// - /// Получение словаря названий ограничений - /// - /// - [HttpGet("names")] - [ProducesResponseType(typeof(Dictionary), (int)System.Net.HttpStatusCode.OK)] - public IActionResult GetLimitingParameteraNames() - { - var feedRegulatorData = limitingParameterService.GetLimitingParameteraNames(); - return Ok(feedRegulatorData); - } - - protected async Task UserHasAccesToWellAsync(int idWell, CancellationToken token) - { - var idCompany = User.GetCompanyId(); - if (idCompany is not null && - await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token) - .ConfigureAwait(false)) - return true; - return false; - } + protected async Task UserHasAccesToWellAsync(int idWell, CancellationToken token) + { + var idCompany = User.GetCompanyId(); + if (idCompany is not null && + await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token) + .ConfigureAwait(false)) + return true; + return false; } } diff --git a/AsbCloudWebApi/Controllers/MeasureController.cs b/AsbCloudWebApi/Controllers/MeasureController.cs index f92ef71f..a4d597ea 100644 --- a/AsbCloudWebApi/Controllers/MeasureController.cs +++ b/AsbCloudWebApi/Controllers/MeasureController.cs @@ -5,104 +5,103 @@ using Microsoft.AspNetCore.Mvc; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Измерения +/// +[ApiController] +[Authorize] +[Route("api/well/{idWell}/measure")] +public class MeasureController : ControllerBase { - /// - /// Измерения - /// - [ApiController] - [Authorize] - [Route("api/well/{idWell}/measure")] - public class MeasureController : ControllerBase + private readonly IMeasureService measureService; + private readonly IWellService wellService; + + public MeasureController(IMeasureService measureService, IWellService wellService) { - private readonly IMeasureService measureService; - private readonly IWellService wellService; + this.measureService = measureService; + this.wellService = wellService; + } - public MeasureController(IMeasureService measureService, IWellService wellService) - { - this.measureService = measureService; - this.wellService = wellService; - } + [HttpGet("categories")] + [Permission] + public async Task GetCategoriesAsync([FromRoute] int idWell, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); - [HttpGet("categories")] - [Permission] - public async Task GetCategoriesAsync([FromRoute] int idWell, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); + var result = await measureService.GetCategoriesAsync(token).ConfigureAwait(false); + return Ok(result); + } - var result = await measureService.GetCategoriesAsync(token).ConfigureAwait(false); - return Ok(result); - } + [HttpGet("last/{idCategory}")] + [Permission] + public async Task GetLastAsync([FromRoute] int idWell, [FromRoute] int idCategory, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); - [HttpGet("last/{idCategory}")] - [Permission] - public async Task GetLastAsync([FromRoute] int idWell, [FromRoute] int idCategory, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); + var result = await measureService.GetLastOrDefaultAsync(idWell, idCategory, token).ConfigureAwait(false); + return Ok(result); + } - var result = await measureService.GetLastOrDefaultAsync(idWell, idCategory, token).ConfigureAwait(false); - return Ok(result); - } + /// + /// История замеров по скважине + /// + /// + /// Категория скважины. Не обязательный параметр. + /// + /// + [HttpGet("history")] + [Permission] + public async Task GetHisoryAsync([FromRoute] int idWell, CancellationToken token, + int? idCategory = null) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); - /// - /// История замеров по скважине - /// - /// - /// Категория скважины. Не обязательный параметр. - /// - /// - [HttpGet("history")] - [Permission] - public async Task GetHisoryAsync([FromRoute] int idWell, CancellationToken token, - int? idCategory = null) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); + var result = await measureService.GetHisoryAsync(idWell, idCategory, token).ConfigureAwait(false); + return Ok(result); + } - var result = await measureService.GetHisoryAsync(idWell, idCategory, token).ConfigureAwait(false); - return Ok(result); - } + [HttpPost] + [Permission] + public async Task InsertAsync([FromRoute] int idWell, MeasureDto data, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); - [HttpPost] - [Permission] - public async Task InsertAsync([FromRoute] int idWell, MeasureDto data, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); + var result = await measureService.InsertAsync(idWell, data, token).ConfigureAwait(false); + return Ok(result); + } - var result = await measureService.InsertAsync(idWell, data, token).ConfigureAwait(false); - return Ok(result); - } + [HttpPut] + [Permission] + public async Task UpdateAsync([FromRoute] int idWell, MeasureDto data, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); - [HttpPut] - [Permission] - public async Task UpdateAsync([FromRoute] int idWell, MeasureDto data, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); + var result = await measureService.UpdateAsync(idWell, data, token).ConfigureAwait(false); + return Ok(result); + } - var result = await measureService.UpdateAsync(idWell, data, token).ConfigureAwait(false); - return Ok(result); - } + [HttpDelete("history/{idData}")] + [Permission] + public async Task MarkAsDeleteAsync([FromRoute] int idWell, [FromRoute] int idData, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); - [HttpDelete("history/{idData}")] - [Permission] - public async Task MarkAsDeleteAsync([FromRoute] int idWell, [FromRoute] int idData, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); + var result = await measureService.MarkAsDeleteAsync(idWell, idData, token).ConfigureAwait(false); + return Ok(result); + } - var result = await measureService.MarkAsDeleteAsync(idWell, idData, token).ConfigureAwait(false); - return Ok(result); - } - - private async Task 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 CanUserAccessToWellAsync(int idWell, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false); } } diff --git a/AsbCloudWebApi/Controllers/OperationStatController.cs b/AsbCloudWebApi/Controllers/OperationStatController.cs index 59f907bd..7f0e06c6 100644 --- a/AsbCloudWebApi/Controllers/OperationStatController.cs +++ b/AsbCloudWebApi/Controllers/OperationStatController.cs @@ -1,4 +1,3 @@ -using System; using AsbCloudApp.Data; using AsbCloudApp.Services; using Microsoft.AspNetCore.Authorization; @@ -9,164 +8,162 @@ using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data.WellOperation; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + + +/// +/// Статистика по операциям (заведенным вручную) на скважине +/// +[ApiController] +[Authorize] +[Route("api")] +public class OperationStatController : ControllerBase { + private readonly IOperationsStatService operationsStatService; + private readonly IWellOperationService wellOperationService; + private readonly IWellService wellService; - /// - /// Статистика по операциям (заведенным вручную) на скважине - /// - [ApiController] - [Authorize] - [Route("api")] - public class OperationStatController : ControllerBase + public OperationStatController( + IOperationsStatService operationsStatService, + IWellService wellService, + IWellOperationService wellOperationService) { - private readonly IOperationsStatService operationsStatService; - private readonly IWellOperationService wellOperationService; - private readonly IWellService wellService; - - public OperationStatController( - IOperationsStatService sectionsService, - IWellService wellService, - IWellOperationService wellOperationService) - { - this.operationsStatService = sectionsService; - this.wellService = wellService; - this.wellOperationService = wellOperationService; - } - - /// - /// Формирует данные по среднему и максимальному МСП на кусту по id скважины - /// - /// id скважины с данного куста (через нее будут получены данные) - /// - /// Возвращает данные по среднему и максимальному МСП на кусту - [HttpGet("well/{idWell}/ropStat")] - [Permission] - [ProducesResponseType(typeof(ClusterRopStatDto), (int)System.Net.HttpStatusCode.OK)] - public async Task GetClusterRopStatByIdWellAsync([FromRoute] int idWell, - CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var result = await operationsStatService.GetOrDefaultRopStatAsync( - idWell, token).ConfigureAwait(false); - - return Ok(result); - } - - /// - /// Формирует данные по среднему и максимальному МСП на кусту по uid панели - /// - /// id передающей данные панели - /// - /// Возвращает данные по среднему и максимальному МСП на кусту - [HttpGet("telemetry/{uid}/ropStat")] - [ProducesResponseType(typeof(ClusterRopStatDto), (int)System.Net.HttpStatusCode.OK)] - [AllowAnonymous] - public async Task GetClusterRopStatByUidAsync([FromRoute] string uid, - CancellationToken token) - { - var idWell = wellService.TelemetryService.GetIdWellByTelemetryUid(uid); - - if (idWell is null) - return NoContent(); - - var result = await operationsStatService.GetOrDefaultRopStatAsync( - (int)idWell, token).ConfigureAwait(false); - - return Ok(result); - } - - /// - /// Получает статистику по скважинам куста - /// - /// id куста - /// - /// - [HttpGet("cluster/{idCluster}/stat")] - [Permission] - [ProducesResponseType(typeof(StatClusterDto), (int)System.Net.HttpStatusCode.OK)] - public async Task GetStatClusterAsync(int idCluster, - CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - if (idCompany is null) - return Forbid(); - - var result = await operationsStatService.GetOrDefaultStatClusterAsync(idCluster, idCompany.Value, token) - .ConfigureAwait(false); - return Ok(result); - } - - /// - /// Получает статистику по списку скважин - /// - /// список скважин - /// - /// - [HttpGet("wellsStats")] - [Permission] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetWellsStatAsync([FromQuery] IEnumerable idWells, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - if (idCompany is null) - return Forbid(); - - var allowedWells = await wellService.GetAsync(new() { IdCompany = idCompany }, token); - - var protectedIdWells = idWells.Where(id => allowedWells.Any(allowed => allowed.Id == id)); - var result = await operationsStatService.GetWellsStatAsync(protectedIdWells, token) - .ConfigureAwait(false); - return Ok(result); - } - - /// - /// Получает статистику по скважине - /// - /// id скважины - /// - /// - [HttpGet("well/{idWell}/stat")] - [Permission] - [ProducesResponseType(typeof(StatWellDto), (int)System.Net.HttpStatusCode.OK)] - public async Task GetStatWellAsync(int idWell, - CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var result = await operationsStatService.GetOrDefaultWellStatAsync(idWell, token) - .ConfigureAwait(false); - return Ok(result); - } - - /// - /// Получает данные для графика глубина-день - /// - /// - /// - /// - [HttpGet("well/{idWell}/tvd")] - [Permission] - [ProducesResponseType(typeof(IEnumerable>), (int)System.Net.HttpStatusCode.OK)] - public async Task GetTvdAsync(int idWell, - CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var result = await wellOperationService.GetTvdAsync(idWell, token); - return Ok(result); - } - - private async Task CanUserAccessToWellAsync(int idWell, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false); - } + this.operationsStatService = operationsStatService; + this.wellService = wellService; + this.wellOperationService = wellOperationService; } + /// + /// Формирует данные по среднему и максимальному МСП на кусту по id скважины + /// + /// id скважины с данного куста (через нее будут получены данные) + /// + /// Возвращает данные по среднему и максимальному МСП на кусту + [HttpGet("well/{idWell}/ropStat")] + [Permission] + [ProducesResponseType(typeof(ClusterRopStatDto), (int)System.Net.HttpStatusCode.OK)] + public async Task GetClusterRopStatByIdWellAsync([FromRoute] int idWell, + CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); + + var result = await operationsStatService.GetOrDefaultRopStatAsync( + idWell, token).ConfigureAwait(false); + + return Ok(result); + } + + /// + /// Формирует данные по среднему и максимальному МСП на кусту по uid панели + /// + /// id передающей данные панели + /// + /// Возвращает данные по среднему и максимальному МСП на кусту + [HttpGet("telemetry/{uid}/ropStat")] + [ProducesResponseType(typeof(ClusterRopStatDto), (int)System.Net.HttpStatusCode.OK)] + [AllowAnonymous] + public async Task GetClusterRopStatByUidAsync([FromRoute] string uid, + CancellationToken token) + { + var idWell = wellService.TelemetryService.GetIdWellByTelemetryUid(uid); + + if (idWell is null) + return NoContent(); + + var result = await operationsStatService.GetOrDefaultRopStatAsync( + (int)idWell, token).ConfigureAwait(false); + + return Ok(result); + } + + /// + /// Получает статистику по скважинам куста + /// + /// id куста + /// + /// + [HttpGet("cluster/{idCluster}/stat")] + [Permission] + [ProducesResponseType(typeof(StatClusterDto), (int)System.Net.HttpStatusCode.OK)] + public async Task GetStatClusterAsync(int idCluster, + CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + if (idCompany is null) + return Forbid(); + + var result = await operationsStatService.GetOrDefaultStatClusterAsync(idCluster, idCompany.Value, token) + .ConfigureAwait(false); + return Ok(result); + } + + /// + /// Получает статистику по списку скважин + /// + /// список скважин + /// + /// + [HttpGet("wellsStats")] + [Permission] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetWellsStatAsync([FromQuery] IEnumerable idWells, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + if (idCompany is null) + return Forbid(); + + var allowedWells = await wellService.GetAsync(new() { IdCompany = idCompany }, token); + + var protectedIdWells = idWells.Where(id => allowedWells.Any(allowed => allowed.Id == id)); + var result = await operationsStatService.GetWellsStatAsync(protectedIdWells, token) + .ConfigureAwait(false); + return Ok(result); + } + + /// + /// Получает статистику по скважине + /// + /// id скважины + /// + /// + [HttpGet("well/{idWell}/stat")] + [Permission] + [ProducesResponseType(typeof(StatWellDto), (int)System.Net.HttpStatusCode.OK)] + public async Task GetStatWellAsync(int idWell, + CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); + + var result = await operationsStatService.GetOrDefaultWellStatAsync(idWell, token) + .ConfigureAwait(false); + return Ok(result); + } + + /// + /// Получает данные для графика глубина-день + /// + /// + /// + /// + [HttpGet("well/{idWell}/tvd")] + [Permission] + [ProducesResponseType(typeof(IEnumerable>), (int)System.Net.HttpStatusCode.OK)] + public async Task GetTvdAsync(int idWell, + CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); + + var result = await wellOperationService.GetTvdAsync(idWell, token); + return Ok(result); + } + + private async Task CanUserAccessToWellAsync(int idWell, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false); + } } diff --git a/AsbCloudWebApi/Controllers/OperationValueController.cs b/AsbCloudWebApi/Controllers/OperationValueController.cs index cc0ce11f..a4be7910 100644 --- a/AsbCloudWebApi/Controllers/OperationValueController.cs +++ b/AsbCloudWebApi/Controllers/OperationValueController.cs @@ -3,18 +3,17 @@ using AsbCloudApp.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Целевые и нормативные значения по глубине +/// +[Route("api/[controller]")] +[ApiController] +[Authorize] +public class OperationValueController : CrudWellRelatedController> { - /// - /// Целевые и нормативные значения по глубине - /// - [Route("api/[controller]")] - [ApiController] - [Authorize] - public class OperationValueController : CrudWellRelatedController> + public OperationValueController(IRepositoryWellRelated service, IWellService wellService) : base(wellService, service) { - public OperationValueController(IRepositoryWellRelated service, IWellService wellService) : base(wellService, service) - { - } } } diff --git a/AsbCloudWebApi/Controllers/PeriodicBackgroundWorkerController.cs b/AsbCloudWebApi/Controllers/PeriodicBackgroundWorkerController.cs index 836f57be..7bc172a7 100644 --- a/AsbCloudWebApi/Controllers/PeriodicBackgroundWorkerController.cs +++ b/AsbCloudWebApi/Controllers/PeriodicBackgroundWorkerController.cs @@ -8,63 +8,62 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +[Route("api/[controller]")] +[Authorize] +[ApiController] +public class PeriodicBackgroundWorkerController : ControllerBase { - [Route("api/[controller]")] - [Authorize] - [ApiController] - public class PeriodicBackgroundWorkerController : ControllerBase + private readonly PeriodicBackgroundWorker worker; + private readonly IServiceProvider serviceProvider; + + public PeriodicBackgroundWorkerController( + PeriodicBackgroundWorker worker, + IServiceProvider serviceProvider) { - private readonly PeriodicBackgroundWorker worker; - private readonly IServiceProvider serviceProvider; + this.worker = worker; + this.serviceProvider = serviceProvider; + } - public PeriodicBackgroundWorkerController( - PeriodicBackgroundWorker worker, - IServiceProvider serviceProvider) + [HttpGet] + public IActionResult GetAll() + { + var result = new { - this.worker = worker; - this.serviceProvider = serviceProvider; - } + currentWork = (BackgroundWorkDto?)worker.CurrentWork, + worker.MainLoopLastException, + works = worker.Works.Select(work => (BackgroundWorkDto)work.Work), + }; + return Ok(result); + } - [HttpGet] - public IActionResult GetAll() + /// + /// Запуск задачи по Id + /// + /// Id задачи + /// + /// + [HttpGet("start/{workId}")] + public async Task Start(string workId, CancellationToken token) + { + var targetWork = worker.Works.FirstOrDefault(w => w.Work.Id == workId); + if(targetWork is not null) { - var result = new - { - currentWork = (BackgroundWorkDto?)worker.CurrentWork, - worker.MainLoopLastException, - works = worker.Works.Select(work => (BackgroundWorkDto)work.Work), - }; - return Ok(result); - } + using (var scope = serviceProvider.CreateScope()) { - /// - /// Запуск задачи по Id - /// - /// Id задачи - /// - /// - [HttpGet("start/{workId}")] - public async Task Start(string workId, CancellationToken token) - { - var targetWork = worker.Works.FirstOrDefault(w => w.Work.Id == workId); - if(targetWork is not null) - { - using (var scope = serviceProvider.CreateScope()) { - - var result = await targetWork.Work.Start(scope.ServiceProvider, token); - return Ok(result); - } - } - return BadRequest("Work not found by workId"); + var result = await targetWork.Work.Start(scope.ServiceProvider, token); + return Ok(result); + } } + return BadRequest("Work not found by workId"); + } - [HttpPost("restart"), Obsolete("temporary method")] - public async Task RestartAsync(CancellationToken token) - { - await worker.StopAsync(token); - await worker.StartAsync(token); - return Ok(); - } + [HttpPost("restart"), Obsolete("temporary method")] + public async Task RestartAsync(CancellationToken token) + { + await worker.StopAsync(token); + await worker.StartAsync(token); + return Ok(); } } diff --git a/AsbCloudWebApi/Controllers/ProtobufController.cs b/AsbCloudWebApi/Controllers/ProtobufController.cs index 298f38bb..9ec9976f 100644 --- a/AsbCloudWebApi/Controllers/ProtobufController.cs +++ b/AsbCloudWebApi/Controllers/ProtobufController.cs @@ -3,81 +3,80 @@ using ProtoBuf.Meta; using System.Collections.Generic; using System.Linq; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Схемы ProtoBuf +/// +[Route("api/proto")] +[ApiController] +public class ProtobufController : ControllerBase { - /// - /// Схемы ProtoBuf - /// - [Route("api/proto")] - [ApiController] - public class ProtobufController : ControllerBase + private IEnumerable GetMetaTypes() { - private IEnumerable GetMetaTypes() - { - var metaTypes = RuntimeTypeModel.Default - .GetTypes() - .OfType(); - var fileteredMetaTypes = metaTypes - .Where(t => t.Type.MemberType == System.Reflection.MemberTypes.TypeInfo) - .Where(t => !t.Type.IsGenericType) - .Where(t => !t.Type.IsArray); - return fileteredMetaTypes; - } + var metaTypes = RuntimeTypeModel.Default + .GetTypes() + .OfType(); + var fileteredMetaTypes = metaTypes + .Where(t => t.Type.MemberType == System.Reflection.MemberTypes.TypeInfo) + .Where(t => !t.Type.IsGenericType) + .Where(t => !t.Type.IsArray); + return fileteredMetaTypes; + } - /// - /// названия доступных типов - /// - /// - [HttpGet("types")] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public IActionResult GetTypes() - { - var typesNames = GetMetaTypes() - .Select(t => t.Type?.Name); - return Ok(typesNames); - } + /// + /// названия доступных типов + /// + /// + [HttpGet("types")] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public IActionResult GetTypes() + { + var typesNames = GetMetaTypes() + .Select(t => t.Type?.Name); + return Ok(typesNames); + } - /// - /// .proto файл со всеми доступными типами - /// - /// - [HttpGet("schema")] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public IActionResult GetSchema() - { - var types = GetMetaTypes().Select(mt => mt.Type); - SchemaGenerationOptions opts = new() { }; - opts.Types.AddRange(types); - var protoFileContentString = ProtoBuf.Serializer.GetProto(opts); - var protoFileContentBytes = System.Text.Encoding.UTF8.GetBytes(protoFileContentString); - return File(protoFileContentBytes, "text/plain", "types.proto"); - } + /// + /// .proto файл со всеми доступными типами + /// + /// + [HttpGet("schema")] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public IActionResult GetSchema() + { + var types = GetMetaTypes().Select(mt => mt.Type); + SchemaGenerationOptions opts = new() { }; + opts.Types.AddRange(types); + var protoFileContentString = ProtoBuf.Serializer.GetProto(opts); + var protoFileContentBytes = System.Text.Encoding.UTF8.GetBytes(protoFileContentString); + return File(protoFileContentBytes, "text/plain", "types.proto"); + } - /// - /// .proto файл со всеми доступными типами - /// - /// - [HttpGet("schema/{typeName}")] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] - public IActionResult GetSchema(string typeName) - { - if (string.IsNullOrEmpty(typeName)) - return this.ValidationBadRequest(nameof(typeName), "require typeName"); + /// + /// .proto файл со всеми доступными типами + /// + /// + [HttpGet("schema/{typeName}")] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] + public IActionResult GetSchema(string typeName) + { + if (string.IsNullOrEmpty(typeName)) + return this.ValidationBadRequest(nameof(typeName), "require typeName"); - var type = RuntimeTypeModel.Default - .GetTypes() - .OfType() - .FirstOrDefault(t => t.Type.Name.Equals(typeName, System.StringComparison.InvariantCultureIgnoreCase)); + var type = RuntimeTypeModel.Default + .GetTypes() + .OfType() + .FirstOrDefault(t => t.Type.Name.Equals(typeName, System.StringComparison.InvariantCultureIgnoreCase)); - if (type is null) - return NoContent(); + if (type is null) + return NoContent(); - SchemaGenerationOptions opts = new() { }; - opts.Types.Add(type.Type); - var protoFileContentString = ProtoBuf.Serializer.GetProto(opts); - var protoFileContentBytes = System.Text.Encoding.UTF8.GetBytes(protoFileContentString); - return File(protoFileContentBytes, "text/plain", $"{typeName}.proto"); - } + SchemaGenerationOptions opts = new() { }; + opts.Types.Add(type.Type); + var protoFileContentString = ProtoBuf.Serializer.GetProto(opts); + var protoFileContentBytes = System.Text.Encoding.UTF8.GetBytes(protoFileContentString); + return File(protoFileContentBytes, "text/plain", $"{typeName}.proto"); } } diff --git a/AsbCloudWebApi/Controllers/ReduceSamplingController.cs b/AsbCloudWebApi/Controllers/ReduceSamplingController.cs index 4edc1db2..3dd754be 100644 --- a/AsbCloudWebApi/Controllers/ReduceSamplingController.cs +++ b/AsbCloudWebApi/Controllers/ReduceSamplingController.cs @@ -8,71 +8,70 @@ using System.Linq; using AsbCloudWebApi.SignalR; using Microsoft.AspNetCore.SignalR; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Редактор кустов для админки +/// +[Route("api/admin/[controller]")] +[ApiController] +[Authorize] +public class ReduceSamplingController: ControllerBase { - /// - /// Редактор кустов для админки - /// - [Route("api/admin/[controller]")] - [ApiController] - [Authorize] - public class ReduceSamplingController: ControllerBase + private readonly IReduceSamplingService service; + private readonly IHubContext telemetryHubContext; + private const string sirnalRGroupName = "ReduceSampling"; + private const string sirnalRMethodOnProgress = "OnProgress"; + + public ReduceSamplingController( + IReduceSamplingService service, + IHubContext telemetryHubContext ) { - private readonly IReduceSamplingService service; - private readonly IHubContext telemetryHubContext; - private const string sirnalRGroupName = "ReduceSampling"; - private const string sirnalRMethodOnProgress = "OnProgress"; + this.service = service; + this.telemetryHubContext = telemetryHubContext; + } - public ReduceSamplingController( - IReduceSamplingService service, - IHubContext telemetryHubContext ) - { - this.service = service; - this.telemetryHubContext = telemetryHubContext; - } - - /// - /// Получить все задания. Задания удаляются минимум через 10 сек после выполнения, возможно позднее. - /// - /// - /// - [HttpGet] - public virtual ActionResult> GetAll(int idTelemetry) - { - var result = service.GetJobs(); - if (result.Any()) - return Ok(result); - else - return NoContent(); - } - - /// - /// Получить состояние определенной задачи - /// - /// - /// - [HttpGet("{idTelemetry}")] - public virtual ActionResult GetOrDefault(int idTelemetry) - { - var result = service.GetOrDefaultState(idTelemetry); + /// + /// Получить все задания. Задания удаляются минимум через 10 сек после выполнения, возможно позднее. + /// + /// + /// + [HttpGet] + public virtual ActionResult> GetAll(int idTelemetry) + { + var result = service.GetJobs(); + if (result.Any()) return Ok(result); - } + else + return NoContent(); + } - /// - /// Создать задачу прореживанию архива и добавить её в очередь на выполнение. - /// Если задача есть в очереди, она же и возвращается, но подписка не происходит. - /// - [HttpPost] - [Permission] - public virtual ActionResult Enqueue(int idTelemetry) - { - void onProgress(JobDto job) => - Task.Run(async () => - await telemetryHubContext.Clients.Group(sirnalRGroupName) - .SendAsync(sirnalRMethodOnProgress, job)); + /// + /// Получить состояние определенной задачи + /// + /// + /// + [HttpGet("{idTelemetry}")] + public virtual ActionResult GetOrDefault(int idTelemetry) + { + var result = service.GetOrDefaultState(idTelemetry); + return Ok(result); + } - service.TryEnqueueRediceSamplingJob(idTelemetry, onProgress, out JobDto job); - return Ok(job); - } + /// + /// Создать задачу прореживанию архива и добавить её в очередь на выполнение. + /// Если задача есть в очереди, она же и возвращается, но подписка не происходит. + /// + [HttpPost] + [Permission] + public virtual ActionResult Enqueue(int idTelemetry) + { + void onProgress(JobDto job) => + Task.Run(async () => + await telemetryHubContext.Clients.Group(sirnalRGroupName) + .SendAsync(sirnalRMethodOnProgress, job)); + + service.TryEnqueueRediceSamplingJob(idTelemetry, onProgress, out JobDto job); + return Ok(job); } } diff --git a/AsbCloudWebApi/Controllers/ReportController.cs b/AsbCloudWebApi/Controllers/ReportController.cs index 423f36c4..45d5aa42 100644 --- a/AsbCloudWebApi/Controllers/ReportController.cs +++ b/AsbCloudWebApi/Controllers/ReportController.cs @@ -10,150 +10,149 @@ using System.Threading.Tasks; using AsbCloudApp.Requests; using AsbCloudWebApi.SignalR.Clients; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Отчет (временная диаграмма с сообщениями) +/// +[Route("api/well/{idWell}/report")] +[ApiController] +public class ReportController : ControllerBase { - /// - /// Отчет (временная диаграмма с сообщениями) - /// - [Route("api/well/{idWell}/report")] - [ApiController] - public class ReportController : ControllerBase + private readonly IReportService reportService; + private readonly IWellService wellService; + private readonly IHubContext reportsHubContext; + + public ReportController( + IReportService reportService, + IWellService wellService, + IHubContext reportsHubContext) { - private readonly IReportService reportService; - private readonly IWellService wellService; - private readonly IHubContext reportsHubContext; + this.reportService = reportService; + this.wellService = wellService; + this.reportsHubContext = reportsHubContext; + } - public ReportController( - IReportService reportService, - IWellService wellService, - IHubContext reportsHubContext) - { - this.reportService = reportService; - this.wellService = wellService; - this.reportsHubContext = reportsHubContext; - } + /// + /// Создает отчет по скважине с указанными параметрами + /// + /// Id скважины + /// Параметры запроса + /// Токен для отмены задачи + /// id фоновой задачи формирования отчета + [HttpPost] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task CreateReportAsync([Required] int idWell, + [FromQuery] ReportParametersRequest request, + CancellationToken token) + { + var idCompany = User.GetCompanyId(); + var idUser = User.GetUserId(); - /// - /// Создает отчет по скважине с указанными параметрами - /// - /// Id скважины - /// Параметры запроса - /// Токен для отмены задачи - /// id фоновой задачи формирования отчета - [HttpPost] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task CreateReportAsync([Required] int idWell, - [FromQuery] ReportParametersRequest request, - CancellationToken token) - { - var idCompany = User.GetCompanyId(); - var idUser = User.GetUserId(); + if ((idCompany is null) || (idUser is null)) + return Forbid(); - if ((idCompany is null) || (idUser is null)) - return Forbid(); - - if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) - return Forbid(); - - void HandleReportProgressAsync(object progress, string id) => - Task.Run(async() => - { - await reportsHubContext.Clients.Group($"Report_{id}") - .GetReportProgress(progress, token); - }, token); - - var id = reportService.EnqueueCreateReportWork(idWell, (int)idUser, request, HandleReportProgressAsync); - - return Ok(id); - } - - /// - /// Возвращает имена всех отчетов по скважине - /// - /// id скважины - /// Токен для отмены задачи - /// Список имен существующих отчетов (отчетов) - [HttpGet] - [Permission] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetAllReportsNamesByWellAsync(int idWell, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - - if (idCompany is null) - return Forbid(); - - if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token).ConfigureAwait(false)) - return Forbid(); + return Forbid(); - var reports = await reportService.GetAllReportsByWellAsync(idWell, token).ConfigureAwait(false); + void HandleReportProgressAsync(object progress, string id) => + Task.Run(async() => + { + await reportsHubContext.Clients.Group($"Report_{id}") + .GetReportProgress(progress, token); + }, token); - return Ok(reports); - } + var id = reportService.EnqueueCreateReportWork(idWell, (int)idUser, request, HandleReportProgressAsync); - /// - /// Возвращает прогнозируемое количество страниц будущего отчета - /// - /// Id скважины - /// Параметры запроса - /// Токен для отмены задачи - /// прогнозируемое кол-во страниц отчета - [HttpGet("reportSize")] - [Permission] - [ProducesResponseType(typeof(string), (int)System.Net.HttpStatusCode.OK)] - public async Task GetReportSizeAsync([Required] int idWell, - [FromQuery] ReportParametersRequest request, - CancellationToken token) - { - int? idCompany = User.GetCompanyId(); + return Ok(id); + } - if (idCompany is null) - return Forbid(); + /// + /// Возвращает имена всех отчетов по скважине + /// + /// id скважины + /// Токен для отмены задачи + /// Список имен существующих отчетов (отчетов) + [HttpGet] + [Permission] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetAllReportsNamesByWellAsync(int idWell, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); - if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) - return Forbid(); - - int reportSize = reportService.GetReportPagesCount(idWell, - request.Begin, request.End, request.StepSeconds, request.Format); + if (idCompany is null) + return Forbid(); - return Ok(reportSize); - } + if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false)) + return Forbid(); - /// - /// Возвращает даты самого старого и самого свежего отчетов в БД - /// - /// id скважины - /// Токен для отмены задачи - /// Даты самого старого и самого свежего отчетов в БД - [HttpGet("datesRange")] - [Permission] - [ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)] - [ProducesResponseType((int)System.Net.HttpStatusCode.NoContent)] - public async Task GetReportsDateRangeAsync(int idWell, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); + var reports = await reportService.GetAllReportsByWellAsync(idWell, token).ConfigureAwait(false); - if (idCompany is null) - return Forbid(); + return Ok(reports); + } - if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + /// + /// Возвращает прогнозируемое количество страниц будущего отчета + /// + /// Id скважины + /// Параметры запроса + /// Токен для отмены задачи + /// прогнозируемое кол-во страниц отчета + [HttpGet("reportSize")] + [Permission] + [ProducesResponseType(typeof(string), (int)System.Net.HttpStatusCode.OK)] + public async Task GetReportSizeAsync([Required] int idWell, + [FromQuery] ReportParametersRequest request, + CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + + if (idCompany is null) + return Forbid(); + + if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token).ConfigureAwait(false)) - return Forbid(); + return Forbid(); + + int reportSize = reportService.GetReportPagesCount(idWell, + request.Begin, request.End, request.StepSeconds, request.Format); - var wellReportsDatesRange = reportService.GetDatesRangeOrDefault(idWell); + return Ok(reportSize); + } - if (wellReportsDatesRange is null) - return NoContent(); + /// + /// Возвращает даты самого старого и самого свежего отчетов в БД + /// + /// id скважины + /// Токен для отмены задачи + /// Даты самого старого и самого свежего отчетов в БД + [HttpGet("datesRange")] + [Permission] + [ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType((int)System.Net.HttpStatusCode.NoContent)] + public async Task GetReportsDateRangeAsync(int idWell, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); - if (wellReportsDatesRange.From == wellReportsDatesRange.To) - return NoContent(); + if (idCompany is null) + return Forbid(); - return Ok(wellReportsDatesRange); - } + if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false)) + return Forbid(); + + var wellReportsDatesRange = reportService.GetDatesRangeOrDefault(idWell); + + if (wellReportsDatesRange is null) + return NoContent(); + + if (wellReportsDatesRange.From == wellReportsDatesRange.To) + return NoContent(); + + return Ok(wellReportsDatesRange); } } diff --git a/AsbCloudWebApi/Controllers/RequestTrackerController.cs b/AsbCloudWebApi/Controllers/RequestTrackerController.cs index 82e3a433..1158838d 100644 --- a/AsbCloudWebApi/Controllers/RequestTrackerController.cs +++ b/AsbCloudWebApi/Controllers/RequestTrackerController.cs @@ -4,89 +4,87 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + + +/// +/// Мониторинг запросов, ошибок, пользователей +/// +[Route("api/[controller]")] +[ApiController] +[Authorize] +public class RequestTrackerController : ControllerBase { + private readonly IRequerstTrackerService service; - /// - /// Мониторинг запросов, ошибок, пользователей - /// - [Route("api/[controller]")] - [ApiController] - [Authorize] - public class RequestTrackerController : ControllerBase + public RequestTrackerController(IRequerstTrackerService service) { - private readonly IRequerstTrackerService service; - - public RequestTrackerController(IRequerstTrackerService service) - { - this.service = service; - } - - /// - /// Получить последние `take` запросов к серверу - /// - /// от 1 до 1000 - /// - [HttpGet] - [Permission] - public IActionResult GetAll(int take = 512) - { - var result = service.GetAll(take); - return Ok(result); - } - - /// - /// Получить последние `take` быстрых запросов к серверу - /// - /// от 1 до 1000 - /// - [HttpGet("fast")] - [Permission] - public IActionResult GetFast(int take = 512) - { - var result = service.GetFast(take); - return Ok(result); - } - - /// - /// Получить последние `take` медленных запросов к серверу - /// - /// от 1 до 1000 - /// - [HttpGet("slow")] - [Permission] - public IActionResult GetSlow(int take = 512) - { - var result = service.GetSlow(take); - return Ok(result); - } - - /// - /// Получить последние `take` ошибок при выполнении запросов - /// - /// от 1 до 1000 - /// - [HttpGet("error")] - [Permission] - public IActionResult GetError(int take = 512) - { - var result = service.GetError(take); - return Ok(result); - } - - /// - /// Получить последних пользователей обращавшихся к серверу. Уникальность пользователя проверяется по логину и Ip. - /// - /// от 1 до 1000 - /// - [HttpGet("users")] - [Permission] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public IActionResult GetUsersStat(int take = 512) - { - var result = service.GetUsersStat(take); - return Ok(result); - } + this.service = service; } + /// + /// Получить последние `take` запросов к серверу + /// + /// от 1 до 1000 + /// + [HttpGet] + [Permission] + public IActionResult GetAll(int take = 512) + { + var result = service.GetAll(take); + return Ok(result); + } + + /// + /// Получить последние `take` быстрых запросов к серверу + /// + /// от 1 до 1000 + /// + [HttpGet("fast")] + [Permission] + public IActionResult GetFast(int take = 512) + { + var result = service.GetFast(take); + return Ok(result); + } + + /// + /// Получить последние `take` медленных запросов к серверу + /// + /// от 1 до 1000 + /// + [HttpGet("slow")] + [Permission] + public IActionResult GetSlow(int take = 512) + { + var result = service.GetSlow(take); + return Ok(result); + } + + /// + /// Получить последние `take` ошибок при выполнении запросов + /// + /// от 1 до 1000 + /// + [HttpGet("error")] + [Permission] + public IActionResult GetError(int take = 512) + { + var result = service.GetError(take); + return Ok(result); + } + + /// + /// Получить последних пользователей обращавшихся к серверу. Уникальность пользователя проверяется по логину и Ip. + /// + /// от 1 до 1000 + /// + [HttpGet("users")] + [Permission] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public IActionResult GetUsersStat(int take = 512) + { + var result = service.GetUsersStat(take); + return Ok(result); + } } diff --git a/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs b/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs index d4171f25..2cd6b7e7 100644 --- a/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs @@ -14,184 +14,183 @@ using AsbCloudApp.Repositories; using AsbCloudInfrastructure.Services.DetectOperations; using Microsoft.AspNetCore.Http; -namespace AsbCloudWebApi.Controllers.SAUB +namespace AsbCloudWebApi.Controllers.SAUB; + +/// +/// Операции определенные по телеметрии САУБ +/// +[Route("api/well/{idWell}/[controller]")] +[ApiController] +[Authorize] +public class DetectedOperationController : ControllerBase { - /// - /// Операции определенные по телеметрии САУБ - /// - [Route("api/well/{idWell}/[controller]")] - [ApiController] - [Authorize] - public class DetectedOperationController : ControllerBase - { - private readonly IDetectedOperationRepository detectedOperationRepository; - private readonly IDetectedOperationService detectedOperationService; - private readonly IWellService wellService; - private readonly DetectedOperationExportService detectedOperationExportService; + private readonly IDetectedOperationRepository detectedOperationRepository; + private readonly IDetectedOperationService detectedOperationService; + private readonly IWellService wellService; + private readonly DetectedOperationExportService detectedOperationExportService; - public DetectedOperationController(IDetectedOperationService detectedOperationService, - IWellService wellService, - DetectedOperationExportService detectedOperationExportService, - IDetectedOperationRepository detectedOperationRepository) - { - this.detectedOperationService = detectedOperationService; - this.wellService = wellService; - this.detectedOperationExportService = detectedOperationExportService; - this.detectedOperationRepository = detectedOperationRepository; - } + public DetectedOperationController(IDetectedOperationService detectedOperationService, + IWellService wellService, + DetectedOperationExportService detectedOperationExportService, + IDetectedOperationRepository detectedOperationRepository) + { + this.detectedOperationService = detectedOperationService; + this.wellService = wellService; + this.detectedOperationExportService = detectedOperationExportService; + this.detectedOperationRepository = detectedOperationRepository; + } - /// - /// Добавить операции - /// - /// - /// - /// - /// - [HttpPost] - [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] - public async Task InsertRangeAsync(int idWell, IEnumerable dtos, CancellationToken token) - { - var idUser = await AssertUserHasAccessToWellAsync(idWell, token); + /// + /// Добавить операции + /// + /// + /// + /// + /// + [HttpPost] + [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] + public async Task InsertRangeAsync(int idWell, IEnumerable dtos, CancellationToken token) + { + var idUser = await AssertUserHasAccessToWellAsync(idWell, token); - var result = await detectedOperationService.InsertRangeManualAsync(idUser, idWell, dtos, token); + var result = await detectedOperationService.InsertRangeManualAsync(idUser, idWell, dtos, token); - return Ok(result); - } + return Ok(result); + } - /// - /// Обновить операции - /// - /// - /// - /// - /// - [HttpPut] - [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] - public async Task UpdateRangeAsync(int idWell, IEnumerable dtos, CancellationToken token) - { - var idUser = await AssertUserHasAccessToWellAsync(idWell, token); + /// + /// Обновить операции + /// + /// + /// + /// + /// + [HttpPut] + [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] + public async Task UpdateRangeAsync(int idWell, IEnumerable dtos, CancellationToken token) + { + var idUser = await AssertUserHasAccessToWellAsync(idWell, token); - var result = await detectedOperationService.UpdateRangeManualAsync(idUser, idWell, dtos, token); + var result = await detectedOperationService.UpdateRangeManualAsync(idUser, idWell, dtos, token); - return Ok(result); - } + return Ok(result); + } - /// - /// Удалить операции - /// - /// - /// - /// - /// - [HttpDelete] - [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] - public async Task DeleteRangeAsync(int idWell, IEnumerable ids, CancellationToken token) - { - await AssertUserHasAccessToWellAsync(idWell, token); + /// + /// Удалить операции + /// + /// + /// + /// + /// + [HttpDelete] + [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] + public async Task DeleteRangeAsync(int idWell, IEnumerable ids, CancellationToken token) + { + await AssertUserHasAccessToWellAsync(idWell, token); - var result = await detectedOperationRepository.DeleteRangeAsync(ids, token); + var result = await detectedOperationRepository.DeleteRangeAsync(ids, token); - return Ok(result); - } + return Ok(result); + } - /// - /// получить справочник операций. Отличается от операций заводимых вручную. - /// При задании id скважины вернет только те операции, которые определились в телеметрии этой скважины. - /// - /// [опционально] id скважины - /// - /// - [HttpGet] - [Route("/api/well/[controller]/categories")] - [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] - public async Task GetCategoriesAsync([FromQuery] int? idWell, CancellationToken token) - { - var result = await detectedOperationService.GetCategoriesAsync(idWell, token); - return Ok(result); - } + /// + /// получить справочник операций. Отличается от операций заводимых вручную. + /// При задании id скважины вернет только те операции, которые определились в телеметрии этой скважины. + /// + /// [опционально] id скважины + /// + /// + [HttpGet] + [Route("/api/well/[controller]/categories")] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + public async Task GetCategoriesAsync([FromQuery] int? idWell, CancellationToken token) + { + var result = await detectedOperationService.GetCategoriesAsync(idWell, token); + return Ok(result); + } - /// - /// Получить список авто определенных операций для редактирования - /// - /// - /// - /// - /// - [HttpGet] - [ProducesResponseType(typeof(PaginationContainer), StatusCodes.Status200OK)] - public async Task GetPageAsync(int idWell, [FromQuery] DetectedOperationRequest request, - CancellationToken token) - { - await AssertUserHasAccessToWellAsync(idWell, token); + /// + /// Получить список авто определенных операций для редактирования + /// + /// + /// + /// + /// + [HttpGet] + [ProducesResponseType(typeof(PaginationContainer), StatusCodes.Status200OK)] + public async Task GetPageAsync(int idWell, [FromQuery] DetectedOperationRequest request, + CancellationToken token) + { + await AssertUserHasAccessToWellAsync(idWell, token); - var well = await wellService.GetOrDefaultAsync(idWell, token); + var well = await wellService.GetOrDefaultAsync(idWell, token); - if (well?.IdTelemetry is null) - return NoContent(); + if (well?.IdTelemetry is null) + return NoContent(); - var requestToService = new DetectedOperationByTelemetryRequest(well.IdTelemetry.Value, request); + var requestToService = new DetectedOperationByTelemetryRequest(well.IdTelemetry.Value, request); - var result = await detectedOperationRepository.GetPageAsync(requestToService, token); - return Ok(result); - } - - /// - /// Получить статистику по авто определенным операциям - /// - /// - /// - /// - /// - [HttpGet("stat")] - [ProducesResponseType(typeof(DetectedOperationListDto), StatusCodes.Status200OK)] - public async Task GetAsync(int idWell, [FromQuery] DetectedOperationRequest request, CancellationToken token) - { - await AssertUserHasAccessToWellAsync(idWell, token); - - var requestToService = new DetectedOperationByWellRequest(idWell, request); + var result = await detectedOperationRepository.GetPageAsync(requestToService, token); + return Ok(result); + } + + /// + /// Получить статистику по авто определенным операциям + /// + /// + /// + /// + /// + [HttpGet("stat")] + [ProducesResponseType(typeof(DetectedOperationListDto), StatusCodes.Status200OK)] + public async Task GetAsync(int idWell, [FromQuery] DetectedOperationRequest request, CancellationToken token) + { + await AssertUserHasAccessToWellAsync(idWell, token); + + var requestToService = new DetectedOperationByWellRequest(idWell, request); - var result = await detectedOperationService.GetAsync(requestToService, token); - return Ok(result); - } + var result = await detectedOperationService.GetAsync(requestToService, token); + return Ok(result); + } - /// - /// Создает excel файл с операциями по скважине - /// - /// id скважины - /// - [HttpGet("export")] - [Permission] - [ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK, "application/octet-stream")] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] - public async Task ExportAsync(int idWell, CancellationToken token) - { - var idCompany = User.GetCompanyId(); - - if (idCompany is null) - return Forbid(); - - var host = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}"; - var stream = await detectedOperationExportService.ExportAsync(idWell, host, token); - - return File(stream, "application/octet-stream", "operations.xlsx"); - } + /// + /// Создает excel файл с операциями по скважине + /// + /// id скважины + /// + [HttpGet("export")] + [Permission] + [ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK, "application/octet-stream")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] + public async Task ExportAsync(int idWell, CancellationToken token) + { + var idCompany = User.GetCompanyId(); + + if (idCompany is null) + return Forbid(); + + var host = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}"; + var stream = await detectedOperationExportService.ExportAsync(idWell, host, token); + + return File(stream, "application/octet-stream", "operations.xlsx"); + } - private async Task AssertUserHasAccessToWellAsync(int idWell, CancellationToken token) - { - var idUser = User.GetUserId(); - var idCompany = User.GetCompanyId(); + private async Task AssertUserHasAccessToWellAsync(int idWell, CancellationToken token) + { + var idUser = User.GetUserId(); + var idCompany = User.GetCompanyId(); - if (!idUser.HasValue) - throw new ForbidException("Неизвестный пользователь"); + if (!idUser.HasValue) + throw new ForbidException("Неизвестный пользователь"); - if (!idCompany.HasValue) - throw new ForbidException("Нет доступа к скважине"); + if (!idCompany.HasValue) + throw new ForbidException("Нет доступа к скважине"); - if (!await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, idWell, token)) - throw new ForbidException("Нет доступа к скважине"); + if (!await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, idWell, token)) + throw new ForbidException("Нет доступа к скважине"); - return idUser.Value; - } - } + return idUser.Value; + } } \ No newline at end of file diff --git a/AsbCloudWebApi/Controllers/SAUB/GtrWitsController.cs b/AsbCloudWebApi/Controllers/SAUB/GtrWitsController.cs index 460eb773..e292408c 100644 --- a/AsbCloudWebApi/Controllers/SAUB/GtrWitsController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/GtrWitsController.cs @@ -15,169 +15,167 @@ using AsbCloudApp.Data; using System; using Org.BouncyCastle.Asn1.Ocsp; -namespace AsbCloudWebApi.Controllers.SAUB +namespace AsbCloudWebApi.Controllers.SAUB; + + +[Route("api/[controller]")] +[ApiController] +public class GtrWitsController : ControllerBase + { + protected readonly IWellService wellService; + private readonly ITelemetryService telemetryService; + private readonly IGtrRepository gtrRepository; + private readonly IHubContext telemetryHubContext; - [Route("api/[controller]")] - [ApiController] - public class GtrWitsController : ControllerBase + public string SignalRMethodGetDataName { get; protected set; } = "ReceiveData"; + public GtrWitsController( + ITelemetryService telemetryService, + IGtrRepository gtrRepository, + IWellService wellService, + IHubContext telemetryHubContext) { - protected readonly IWellService wellService; - private readonly ITelemetryService telemetryService; - private readonly IGtrRepository gtrRepository; - private readonly IHubContext telemetryHubContext; - - public string SignalRMethodGetDataName { get; protected set; } = "ReceiveData"; - - public GtrWitsController( - ITelemetryService telemetryService, - IGtrRepository gtrRepository, - IWellService wellService, - IHubContext telemetryHubContext) - { - this.telemetryService = telemetryService; - this.gtrRepository = gtrRepository; - this.wellService = wellService; - this.telemetryHubContext = telemetryHubContext; - } - - /// - /// Получить значение от ГТИ - /// - /// - /// - /// - /// - [HttpGet] - [Permission] - [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] - public async Task GetAllAsync([Required] int idWell, [FromQuery] GtrRequest request, CancellationToken token) - { - await AssertUserHasAccessToWellAsync(idWell, token); - - var dtos = await gtrRepository.GetAsync(idWell, request, token); - - return Ok(dtos); - } - - /// - /// Возвращает диапазон дат за которые есть телеметрия за период времени - /// - /// - /// - /// - /// - /// - [HttpGet("{idWell}/dateRange")] - [ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)] - [ProducesResponseType((int)System.Net.HttpStatusCode.NotFound)] - [ProducesResponseType((int)System.Net.HttpStatusCode.NoContent)] - public virtual async Task> GetRangeAsync( - [FromRoute] int idWell, - DateTimeOffset? geDate, - DateTimeOffset? leDate, - CancellationToken token) - { - await AssertUserHasAccessToWellAsync(idWell, token); - - var range = await gtrRepository.GetRangeAsync(idWell, geDate, leDate, token); - - return Ok(range); - } - - /// - /// Получить загруженные данные ГТИ по скважине - /// - /// Id скважины - /// Параметры запроса - /// Токен завершения задачи - /// - [HttpGet("{idWell}")] - public async Task>> GetDataAsync([Required] int idWell, - [FromQuery] GtrRequest request, - CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - - if (idCompany is null) - return Forbid(); - - bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false); - - if (!isCompanyOwnsWell) - return Forbid(); - - var content = await gtrRepository.GetAsync(idWell, request.Begin?.DateTime, - request.IntervalSec, request.ApproxPointsCount, token).ConfigureAwait(false); - - return Ok(content); - } - - /// - /// получение последних данных ГТИ по ключу record - /// - /// id скважины - /// id record - /// - /// - [HttpGet("{idWell}/{idRecord}")] - public async Task>> GetLastDataByRecordIdAsync(int idWell, int idRecord, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - - if (idCompany is null) - return Forbid(); - - bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false); - - if (!isCompanyOwnsWell) - return Forbid(); - - var content = gtrRepository.GetLastDataByRecordId(idWell, idRecord); - - return Ok(content); - } - - /// - /// Метод для получения WITS записи от панели оператора. - /// Сохраняет в БД. - /// - /// уникальный идентификатор телеметрии - /// WITS запись - /// - /// - [HttpPost("{uid}")] - public async Task PostDataAsync( - string uid, - [FromBody] IEnumerable dtos, - CancellationToken token) - { - var telemetry = telemetryService.GetOrCreateTelemetryByUid(uid); - await gtrRepository.SaveDataAsync(telemetry.Id, dtos, token).ConfigureAwait(false); - var idWell = telemetryService.GetIdWellByTelemetryUid(uid); - if (idWell is not null && dtos is not null) - _ = Task.Run(() => telemetryHubContext.Clients.Group($"well_{idWell}_gtr") - .SendAsync(SignalRMethodGetDataName, dtos), CancellationToken.None); - return Ok(); - } - - private async Task AssertUserHasAccessToWellAsync(int idWell, CancellationToken token) - { - var idUser = User.GetUserId(); - var idCompany = User.GetCompanyId(); - - if (!idUser.HasValue) - throw new ForbidException("Нет доступа к скважине"); - - if (!idCompany.HasValue) - throw new ForbidException("Нет доступа к скважине"); - - if (!await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, idWell, token)) - throw new ForbidException("Нет доступа к скважине"); - } + this.telemetryService = telemetryService; + this.gtrRepository = gtrRepository; + this.wellService = wellService; + this.telemetryHubContext = telemetryHubContext; } + /// + /// Получить значение от ГТИ + /// + /// + /// + /// + /// + [HttpGet] + [Permission] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + public async Task GetAllAsync([Required] int idWell, [FromQuery] GtrRequest request, CancellationToken token) + { + await AssertUserHasAccessToWellAsync(idWell, token); + + var dtos = await gtrRepository.GetAsync(idWell, request, token); + + return Ok(dtos); + } + + /// + /// Возвращает диапазон дат за которые есть телеметрия за период времени + /// + /// + /// + /// + /// + /// + [HttpGet("{idWell}/dateRange")] + [ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType((int)System.Net.HttpStatusCode.NotFound)] + [ProducesResponseType((int)System.Net.HttpStatusCode.NoContent)] + public virtual async Task> GetRangeAsync( + [FromRoute] int idWell, + DateTimeOffset? geDate, + DateTimeOffset? leDate, + CancellationToken token) + { + await AssertUserHasAccessToWellAsync(idWell, token); + + var range = await gtrRepository.GetRangeAsync(idWell, geDate, leDate, token); + + return Ok(range); + } + + /// + /// Получить загруженные данные ГТИ по скважине + /// + /// Id скважины + /// Параметры запроса + /// Токен завершения задачи + /// + [HttpGet("{idWell}")] + public async Task>> GetDataAsync([Required] int idWell, + [FromQuery] GtrRequest request, + CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + + if (idCompany is null) + return Forbid(); + + bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false); + + if (!isCompanyOwnsWell) + return Forbid(); + + var content = await gtrRepository.GetAsync(idWell, request.Begin?.DateTime, + request.IntervalSec, request.ApproxPointsCount, token).ConfigureAwait(false); + + return Ok(content); + } + + /// + /// получение последних данных ГТИ по ключу record + /// + /// id скважины + /// id record + /// + /// + [HttpGet("{idWell}/{idRecord}")] + public async Task>> GetLastDataByRecordIdAsync(int idWell, int idRecord, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + + if (idCompany is null) + return Forbid(); + + bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false); + + if (!isCompanyOwnsWell) + return Forbid(); + + var content = gtrRepository.GetLastDataByRecordId(idWell, idRecord); + + return Ok(content); + } + + /// + /// Метод для получения WITS записи от панели оператора. + /// Сохраняет в БД. + /// + /// уникальный идентификатор телеметрии + /// WITS запись + /// + /// + [HttpPost("{uid}")] + public async Task PostDataAsync( + string uid, + [FromBody] IEnumerable dtos, + CancellationToken token) + { + var telemetry = telemetryService.GetOrCreateTelemetryByUid(uid); + await gtrRepository.SaveDataAsync(telemetry.Id, dtos, token).ConfigureAwait(false); + var idWell = telemetryService.GetIdWellByTelemetryUid(uid); + if (idWell is not null && dtos is not null) + _ = Task.Run(() => telemetryHubContext.Clients.Group($"well_{idWell}_gtr") + .SendAsync(SignalRMethodGetDataName, dtos), CancellationToken.None); + return Ok(); + } + + private async Task AssertUserHasAccessToWellAsync(int idWell, CancellationToken token) + { + var idUser = User.GetUserId(); + var idCompany = User.GetCompanyId(); + + if (!idUser.HasValue) + throw new ForbidException("Нет доступа к скважине"); + + if (!idCompany.HasValue) + throw new ForbidException("Нет доступа к скважине"); + + if (!await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, idWell, token)) + throw new ForbidException("Нет доступа к скважине"); + } } diff --git a/AsbCloudWebApi/Controllers/SAUB/MessageController.cs b/AsbCloudWebApi/Controllers/SAUB/MessageController.cs index 086ddd69..bc89b861 100644 --- a/AsbCloudWebApi/Controllers/SAUB/MessageController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/MessageController.cs @@ -5,95 +5,94 @@ using Microsoft.AspNetCore.Mvc; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers.SAUB +namespace AsbCloudWebApi.Controllers.SAUB; + +/// +/// Сообщения панели бурильщика +/// +[Route("api/well/{idWell}/message")] +[ApiController] +public class MessageController : ControllerBase { - /// - /// Сообщения панели бурильщика - /// - [Route("api/well/{idWell}/message")] - [ApiController] - public class MessageController : ControllerBase + private readonly IMessageService messageService; + private readonly IWellService wellService; + + public MessageController(IMessageService messageService, IWellService wellService) { - private readonly IMessageService messageService; - private readonly IWellService wellService; + this.messageService = messageService; + this.wellService = wellService; + } - public MessageController(IMessageService messageService, IWellService wellService) - { - this.messageService = messageService; - this.wellService = wellService; - } + /// + /// Выдает список сообщений по скважине + /// + /// id скважины + /// Параметры запроса + /// Токен для отмены задачи + /// список сообщений по скважине + [HttpGet] + [Permission] + [ProducesResponseType(typeof(PaginationContainer), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] + public async Task GetMessagesAsync( + [FromRoute] int idWell, + [FromQuery] MessageRequestBase request, + CancellationToken token) + { - /// - /// Выдает список сообщений по скважине - /// - /// id скважины - /// Параметры запроса - /// Токен для отмены задачи - /// список сообщений по скважине - [HttpGet] - [Permission] - [ProducesResponseType(typeof(PaginationContainer), (int)System.Net.HttpStatusCode.OK)] - [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] - public async Task GetMessagesAsync( - [FromRoute] int idWell, - [FromQuery] MessageRequestBase request, - CancellationToken token) - { + if (!await UserHasAccesToWellAsync(idWell, token)) + return Forbid(); - if (!await UserHasAccesToWellAsync(idWell, token)) - return Forbid(); + if (request.Take > 1024) + return this.ValidationBadRequest(nameof(request.Take), "limit mast be less then 1024"); - if (request.Take > 1024) - return this.ValidationBadRequest(nameof(request.Take), "limit mast be less then 1024"); + var requestToService = new MessageRequest(request, idWell); - var requestToService = new MessageRequest(request, idWell); + var result = await messageService.GetMessagesAsync( + requestToService, + token) + .ConfigureAwait(false); - var result = await messageService.GetMessagesAsync( - requestToService, - token) - .ConfigureAwait(false); + if (result is null || result.Count == 0) + return NoContent(); - if (result is null || result.Count == 0) - return NoContent(); + return Ok(result); + } - return Ok(result); - } + /// + /// Выдает список сообщений по скважине + /// + /// id скважины + /// Токен для отмены задачи + /// список сообщений по скважине + [HttpGet("datesRange")] + [Permission] + [ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)] + public async Task GetMessagesDateRangeAsync(int idWell, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); - /// - /// Выдает список сообщений по скважине - /// - /// id скважины - /// Токен для отмены задачи - /// список сообщений по скважине - [HttpGet("datesRange")] - [Permission] - [ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)] - public async Task GetMessagesDateRangeAsync(int idWell, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); + if (idCompany is null) + return Forbid(); - if (idCompany is null) - return Forbid(); + bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false); - bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false); + if (!isCompanyOwnsWell) + return Forbid(); - if (!isCompanyOwnsWell) - return Forbid(); + var wellMessagesDatesRange = wellService.GetDatesRange(idWell); - var wellMessagesDatesRange = wellService.GetDatesRange(idWell); + return Ok(wellMessagesDatesRange); + } - return Ok(wellMessagesDatesRange); - } - - protected async Task UserHasAccesToWellAsync(int idWell, CancellationToken token) - { - var idCompany = User.GetCompanyId(); - if (idCompany is not null && - await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token) - .ConfigureAwait(false)) - return true; - return false; - } + protected async Task UserHasAccesToWellAsync(int idWell, CancellationToken token) + { + var idCompany = User.GetCompanyId(); + if (idCompany is not null && + await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token) + .ConfigureAwait(false)) + return true; + return false; } } diff --git a/AsbCloudWebApi/Controllers/SAUB/SetpointsController.cs b/AsbCloudWebApi/Controllers/SAUB/SetpointsController.cs index e6d82c21..09c23027 100644 --- a/AsbCloudWebApi/Controllers/SAUB/SetpointsController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/SetpointsController.cs @@ -7,156 +7,155 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers.SAUB +namespace AsbCloudWebApi.Controllers.SAUB; + +/// +/// Рекомендация уставок бурильщику +/// +[ApiController] +[Authorize] +public class SetpointsController : ControllerBase { - /// - /// Рекомендация уставок бурильщику - /// - [ApiController] - [Authorize] - public class SetpointsController : ControllerBase + private readonly ISetpointsService setpointsService; + private readonly IWellService wellService; + + public SetpointsController(ISetpointsService setpointsService, IWellService wellService) { - private readonly ISetpointsService setpointsService; - private readonly IWellService wellService; + this.setpointsService = setpointsService; + this.wellService = wellService; + } - public SetpointsController(ISetpointsService setpointsService, IWellService wellService) - { - this.setpointsService = setpointsService; - this.wellService = wellService; - } + /// + /// Получает список запросов на изменение уставок. + /// + /// + /// + [HttpGet("api/well/{idWell}/setpointsNames")] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + [AllowAnonymous] + public IActionResult GetSetpointsNamesByIdWellAsync([FromRoute] int idWell) + { + var result = setpointsService.GetSetpointsNames(); + return Ok(result); + } - /// - /// Получает список запросов на изменение уставок. - /// - /// - /// - [HttpGet("api/well/{idWell}/setpointsNames")] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - [AllowAnonymous] - public IActionResult GetSetpointsNamesByIdWellAsync([FromRoute] int idWell) - { - var result = setpointsService.GetSetpointsNames(); - return Ok(result); - } + /// + /// Добавляет запрос на изменение заданий панели оператора. + /// + /// + /// + /// + /// + [HttpPost("api/well/{idWell}/setpoints")] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] + public async Task InsertAsync(int idWell, SetpointsRequestDto setpoints, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + int? idUser = User.GetUserId(); - /// - /// Добавляет запрос на изменение заданий панели оператора. - /// - /// - /// - /// - /// - [HttpPost("api/well/{idWell}/setpoints")] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] - public async Task InsertAsync(int idWell, SetpointsRequestDto setpoints, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - int? idUser = User.GetUserId(); + if (idCompany is null || idUser is null) + return Forbid(); - if (idCompany is null || idUser is null) - return Forbid(); + if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false)) + return Forbid(); - if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) - return Forbid(); + setpoints.IdAuthor = idUser ?? -1; + setpoints.IdWell = idWell; + setpoints.IdState = 1; - setpoints.IdAuthor = idUser ?? -1; - setpoints.IdWell = idWell; - setpoints.IdState = 1; + if (!setpoints.Setpoints.Any()) + return this.ValidationBadRequest(nameof(setpoints.Setpoints), "Wrong setpoints count"); - if (!setpoints.Setpoints.Any()) - return this.ValidationBadRequest(nameof(setpoints.Setpoints), "Wrong setpoints count"); + var result = await setpointsService.InsertAsync(setpoints, token) + .ConfigureAwait(false); - var result = await setpointsService.InsertAsync(setpoints, token) - .ConfigureAwait(false); + return Ok(result); + } - return Ok(result); - } + /// + /// Получает список запросов на изменение уставок. + /// + /// + /// + /// + [HttpGet("api/well/{idWell}/setpoints")] + [Permission] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetByIdWellAsync([FromRoute] int idWell, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + int? idUser = User.GetUserId(); - /// - /// Получает список запросов на изменение уставок. - /// - /// - /// - /// - [HttpGet("api/well/{idWell}/setpoints")] - [Permission] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetByIdWellAsync([FromRoute] int idWell, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - int? idUser = User.GetUserId(); + if (idCompany is null || idUser is null) + return Forbid(); - if (idCompany is null || idUser is null) - return Forbid(); + var result = await setpointsService.GetAsync(idWell, token) + .ConfigureAwait(false); - var result = await setpointsService.GetAsync(idWell, token) - .ConfigureAwait(false); + return Ok(result); + } - return Ok(result); - } + /// + /// Отчет о принятии, или отклонении уставок оператором. + /// После уставка будет не изменяемой. + /// + /// + /// + /// можно передать только новый state ex.: {state:3} - принято + /// + /// + [HttpPut("api/telemetry/{uid}/setpoints/{id}")] + [ProducesResponseType(typeof(SetpointsRequestDto), (int)System.Net.HttpStatusCode.OK)] + [AllowAnonymous] + public async Task UpdateByTelemetryUidAsync([FromRoute] string uid, int id, SetpointsRequestDto setpointsRequestDto, CancellationToken token) + { + var result = await setpointsService.UpdateStateAsync(setpointsRequestDto, token) + .ConfigureAwait(false); - /// - /// Отчет о принятии, или отклонении уставок оператором. - /// После уставка будет не изменяемой. - /// - /// - /// - /// можно передать только новый state ex.: {state:3} - принято - /// - /// - [HttpPut("api/telemetry/{uid}/setpoints/{id}")] - [ProducesResponseType(typeof(SetpointsRequestDto), (int)System.Net.HttpStatusCode.OK)] - [AllowAnonymous] - public async Task UpdateByTelemetryUidAsync([FromRoute] string uid, int id, SetpointsRequestDto setpointsRequestDto, CancellationToken token) - { - var result = await setpointsService.UpdateStateAsync(setpointsRequestDto, token) - .ConfigureAwait(false); + return Ok(result); + } - return Ok(result); - } + /// + /// Получает запросы на изменение уставок панели. + /// !!SIDE EFFECT: изменяет состояние запросов уставок на отправлено, это не позволит удалить эти уставки после отправки на панель. + /// + /// + /// + /// + [HttpGet("api/telemetry/{uid}/setpoints")] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + [AllowAnonymous] + public async Task GetByTelemetryUidAsync([FromRoute] string uid, CancellationToken token) + { + var result = await setpointsService.GetForPanelAsync(uid, token) + .ConfigureAwait(false); - /// - /// Получает запросы на изменение уставок панели. - /// !!SIDE EFFECT: изменяет состояние запросов уставок на отправлено, это не позволит удалить эти уставки после отправки на панель. - /// - /// - /// - /// - [HttpGet("api/telemetry/{uid}/setpoints")] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - [AllowAnonymous] - public async Task GetByTelemetryUidAsync([FromRoute] string uid, CancellationToken token) - { - var result = await setpointsService.GetForPanelAsync(uid, token) - .ConfigureAwait(false); + return Ok(result); + } - return Ok(result); - } + /// + /// Пробует удалить запрос на изменение уставок. Это будет выполнено, если запрос еще не был отправлен на панель. + /// + /// + /// + /// + /// 1 - удалено, 0 и меньше - не удалено + [HttpDelete("api/well/{idWell}/setpoints/{id}")] + [Permission] + public async Task TryDeleteByIdWellAsync(int idWell, int id, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + int? idUser = User.GetUserId(); - /// - /// Пробует удалить запрос на изменение уставок. Это будет выполнено, если запрос еще не был отправлен на панель. - /// - /// - /// - /// - /// 1 - удалено, 0 и меньше - не удалено - [HttpDelete("api/well/{idWell}/setpoints/{id}")] - [Permission] - public async Task TryDeleteByIdWellAsync(int idWell, int id, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - int? idUser = User.GetUserId(); + if (idCompany is null || idUser is null) + return Forbid(); - if (idCompany is null || idUser is null) - return Forbid(); + var result = await setpointsService.TryDelete(id, token) + .ConfigureAwait(false); - var result = await setpointsService.TryDelete(id, token) - .ConfigureAwait(false); - - return Ok(result); - } + return Ok(result); } } diff --git a/AsbCloudWebApi/Controllers/SAUB/TelemetryController.cs b/AsbCloudWebApi/Controllers/SAUB/TelemetryController.cs index d5f1a71a..0adbba81 100644 --- a/AsbCloudWebApi/Controllers/SAUB/TelemetryController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/TelemetryController.cs @@ -10,113 +10,112 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers.SAUB +namespace AsbCloudWebApi.Controllers.SAUB; + +/// +/// Инфо о передающих телеметрию устройствах +/// +[Route("api/telemetry")] +[ApiController] +public class TelemetryController : ControllerBase { - /// - /// Инфо о передающих телеметрию устройствах - /// - [Route("api/telemetry")] - [ApiController] - public class TelemetryController : ControllerBase + private readonly ITelemetryService telemetryService; + private readonly IMessageService messageService; + private readonly IEventService eventService; + private readonly ITelemetryUserService telemetryUserService; + private readonly IHubContext telemetryHubContext; + + public TelemetryController( + ITelemetryService telemetryService, + IMessageService messageService, + IEventService eventService, + ITelemetryUserService telemetryUserService, + IHubContext telemetryHubContext) { - private readonly ITelemetryService telemetryService; - private readonly IMessageService messageService; - private readonly IEventService eventService; - private readonly ITelemetryUserService telemetryUserService; - private readonly IHubContext telemetryHubContext; + this.telemetryService = telemetryService; + this.messageService = messageService; + this.eventService = eventService; + this.telemetryUserService = telemetryUserService; + this.telemetryHubContext = telemetryHubContext; + } - public TelemetryController( - ITelemetryService telemetryService, - IMessageService messageService, - IEventService eventService, - ITelemetryUserService telemetryUserService, - IHubContext telemetryHubContext) - { - this.telemetryService = telemetryService; - this.messageService = messageService; - this.eventService = eventService; - this.telemetryUserService = telemetryUserService; - this.telemetryHubContext = telemetryHubContext; - } + /// + /// Информация о версиях ПО по телеметриям, данные от которых приходили не позднее From + /// + /// + [HttpGet("Active")] + [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] + public async Task GetTelemetriesInfoByLastData(CancellationToken token) + { + var from = DateTimeOffset.UtcNow.AddDays(-1); + var stream = await telemetryService.GetTelemetriesInfoByLastData(from, token); + return File(stream, "text/csv", $"Software versions by active telemetries from {from :yy-MM-dd hh-mm}.csv"); + } - /// - /// Информация о версиях ПО по телеметриям, данные от которых приходили не позднее From - /// - /// - [HttpGet("Active")] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] - public async Task GetTelemetriesInfoByLastData(CancellationToken token) - { - var from = DateTimeOffset.UtcNow.AddDays(-1); - var stream = await telemetryService.GetTelemetriesInfoByLastData(from, token); - return File(stream, "text/csv", $"Software versions by active telemetries from {from :yy-MM-dd hh-mm}.csv"); - } + /// + /// Принимает общую информацию по скважине + /// + /// Уникальный идентификатор отправителя + /// Информация об отправителе + /// Токен отмены задачи + /// + [HttpPost("{uid}/info")] + public async Task PostInfoAsync(string uid, [FromBody] TelemetryInfoDto info, + CancellationToken token) + { + await telemetryService.UpdateInfoAsync(uid, info, token).ConfigureAwait(false); + return Ok(); + } - /// - /// Принимает общую информацию по скважине - /// - /// Уникальный идентификатор отправителя - /// Информация об отправителе - /// Токен отмены задачи - /// - [HttpPost("{uid}/info")] - public async Task PostInfoAsync(string uid, [FromBody] TelemetryInfoDto info, - CancellationToken token) - { - await telemetryService.UpdateInfoAsync(uid, info, token).ConfigureAwait(false); - return Ok(); - } + /// + /// Принимает список новых сообщений от телеметрии + /// + /// Уникальный идентификатор отправителя + /// сообщения + /// Токен для отмены задачи + /// + [HttpPost("{uid}/message")] + public async Task PostMessagesAsync(string uid, [FromBody] IEnumerable dtos, + CancellationToken token) + { + var idWell = telemetryService.GetIdWellByTelemetryUid(uid); + await messageService.InsertAsync(uid, dtos, token).ConfigureAwait(false); - /// - /// Принимает список новых сообщений от телеметрии - /// - /// Уникальный идентификатор отправителя - /// сообщения - /// Токен для отмены задачи - /// - [HttpPost("{uid}/message")] - public async Task PostMessagesAsync(string uid, [FromBody] IEnumerable dtos, - CancellationToken token) - { - var idWell = telemetryService.GetIdWellByTelemetryUid(uid); - await messageService.InsertAsync(uid, dtos, token).ConfigureAwait(false); + if (dtos.Any()) + await Task.Run(() => telemetryHubContext.Clients.Group($"well_{idWell}") + .SendAsync("ReceiveMessages", dtos), token).ConfigureAwait(false); - if (dtos.Any()) - await Task.Run(() => telemetryHubContext.Clients.Group($"well_{idWell}") - .SendAsync("ReceiveMessages", dtos), token).ConfigureAwait(false); + return Ok(); + } - return Ok(); - } + /// + /// Принимает справочник событий + /// + /// Уникальный идентификатор отправителя + /// справочник событий + /// Токен для отмены задачи + /// + [HttpPost("{uid}/event")] + public async Task PostEventsAsync(string uid, [FromBody] List events, + CancellationToken token) + { + await eventService.UpsertAsync(uid, events, token) + .ConfigureAwait(false); + return Ok(); + } - /// - /// Принимает справочник событий - /// - /// Уникальный идентификатор отправителя - /// справочник событий - /// Токен для отмены задачи - /// - [HttpPost("{uid}/event")] - public async Task PostEventsAsync(string uid, [FromBody] List events, - CancellationToken token) - { - await eventService.UpsertAsync(uid, events, token) - .ConfigureAwait(false); - return Ok(); - } - - /// - /// Принимает справочник пользователей телеметрии - /// - /// Уникальный идентификатор отправителя - /// справочник пользователей телеметрии - /// - /// - [HttpPost("{uid}/user")] - public async Task PostUsersAsync(string uid, [FromBody] List users, - CancellationToken token) - { - await telemetryUserService.UpsertAsync(uid, users, token); - return Ok(); - } + /// + /// Принимает справочник пользователей телеметрии + /// + /// Уникальный идентификатор отправителя + /// справочник пользователей телеметрии + /// + /// + [HttpPost("{uid}/user")] + public async Task PostUsersAsync(string uid, [FromBody] List users, + CancellationToken token) + { + await telemetryUserService.UpsertAsync(uid, users, token); + return Ok(); } } diff --git a/AsbCloudWebApi/Controllers/SAUB/TelemetryDataBaseController.cs b/AsbCloudWebApi/Controllers/SAUB/TelemetryDataBaseController.cs index 0b271f0b..c5c9136c 100644 --- a/AsbCloudWebApi/Controllers/SAUB/TelemetryDataBaseController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/TelemetryDataBaseController.cs @@ -13,191 +13,190 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers.SAUB +namespace AsbCloudWebApi.Controllers.SAUB; + +[ApiController] +[Authorize] +[Route("api/[controller]")] +public abstract class TelemetryDataBaseController : ControllerBase + where TDto : ITelemetryData { - [ApiController] - [Authorize] - [Route("api/[controller]")] - public abstract class TelemetryDataBaseController : ControllerBase - where TDto : ITelemetryData + protected readonly IWellService wellService; + private readonly ITelemetryService telemetryService; + private readonly ITelemetryDataService telemetryDataService; + protected readonly IHubContext telemetryHubContext; + + public TelemetryDataBaseController( + ITelemetryService telemetryService, + ITelemetryDataService telemetryDataService, + IWellService wellService, + IHubContext telemetryHubContext) { - protected readonly IWellService wellService; - private readonly ITelemetryService telemetryService; - private readonly ITelemetryDataService telemetryDataService; - protected readonly IHubContext telemetryHubContext; + this.telemetryService = telemetryService; + this.telemetryDataService = telemetryDataService; + this.wellService = wellService; + this.telemetryHubContext = telemetryHubContext; - public TelemetryDataBaseController( - ITelemetryService telemetryService, - ITelemetryDataService telemetryDataService, - IWellService wellService, - IHubContext telemetryHubContext) + } + + protected abstract Task SignalRNotifyAsync(int idWell, IEnumerable dtos, CancellationToken token); + + /// + /// Принимает данные от разных систем по скважине + /// + /// Уникальный идентификатор отправителя + /// Данные + /// Токен для отмены задачи + /// + [HttpPost("{uid}")] + [AllowAnonymous] + public virtual async Task PostDataAsync(string uid, [FromBody] IEnumerable dtos, + CancellationToken token) + { + await telemetryDataService.UpdateDataAsync(uid, dtos, token).ConfigureAwait(false); + + var idWell = telemetryService.GetIdWellByTelemetryUid(uid); + if (idWell is not null && dtos.Any()) + _ = Task.Run(() => SignalRNotifyAsync(idWell.Value, dtos, CancellationToken.None)); + + return Ok(); + } + + /// + /// Возвращает данные САУБ по скважине. + /// По умолчанию за последние 10 минут. + /// + /// id скважины + /// дата начала выборки. По умолчанию: текущее время - intervalSec + /// интервал времени даты начала выборки, секунды + /// желаемое количество точек. Если в выборке точек будет больше, то выборка будет прорежена. + /// Токен завершения задачи + /// + [HttpGet("{idWell}")] + [Permission] + public virtual async Task>> GetDataAsync(int idWell, + DateTime begin = default, + int intervalSec = 600, + int approxPointsCount = 1024, + //TODO: сделать cancellationToken обязательным + CancellationToken token = default) + { + int? idCompany = User.GetCompanyId(); + + if (idCompany is null) + return Forbid(); + + bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false); + + if (!isCompanyOwnsWell) + return Forbid(); + + var content = await telemetryDataService.GetByWellAsync(idWell, begin, + intervalSec, approxPointsCount, token).ConfigureAwait(false); + + return Ok(content); + } + + /// + /// Новая версия. Возвращает данные САУБ по скважине. + /// По умолчанию за последние 10 минут. + /// + /// id скважины + /// + /// Токен завершения задачи + /// + [HttpGet("{idWell}/data")] + [Permission] + public virtual async Task>> GetData2Async(int idWell, + [FromQuery]TelemetryDataRequest request, + CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + + if (idCompany is null) + return Forbid(); + + bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false); + + if (!isCompanyOwnsWell) + return Forbid(); + + var content = await telemetryDataService.GetByWellAsync(idWell, request, token); + + return Ok(content); + } + + /// + /// Возвращает диапазон дат за которые есть телеметрия за период времени + /// + /// + /// + /// + /// + /// + [HttpGet("{idWell}/dateRange")] + [ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType((int)System.Net.HttpStatusCode.NotFound)] + [ProducesResponseType((int)System.Net.HttpStatusCode.NoContent)] + public virtual async Task> GetRangeAsync( + [FromRoute] int idWell, + [Required] DateTimeOffset geDate, + DateTimeOffset? leDate, + CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + + if (idCompany is null) + return Forbid(); + + bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false); + + if (!isCompanyOwnsWell) + return Forbid(); + + var content = await telemetryDataService.GetRangeAsync(idWell, geDate, leDate, token); + + if (content is null) + return NoContent(); + + return Ok(content); + } + + /// + /// Возвращает диапазон дат сохраненных данных. + /// + /// id скважины + /// Токен завершения задачи + /// + [HttpGet("{idWell}/datesRange")] + [Permission] + [ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType((int)System.Net.HttpStatusCode.NotFound)] + [ProducesResponseType((int)System.Net.HttpStatusCode.NoContent)] + public virtual async Task> GetDataDatesRangeAsync(int idWell, + CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + + if (idCompany is null) + return Forbid(); + + bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false); + + if (!isCompanyOwnsWell) + return Forbid(); + try { - this.telemetryService = telemetryService; - this.telemetryDataService = telemetryDataService; - this.wellService = wellService; - this.telemetryHubContext = telemetryHubContext; - + var dataDatesRange = wellService.GetDatesRange(idWell); + return Ok(dataDatesRange); } - - protected abstract Task SignalRNotifyAsync(int idWell, IEnumerable dtos, CancellationToken token); - - /// - /// Принимает данные от разных систем по скважине - /// - /// Уникальный идентификатор отправителя - /// Данные - /// Токен для отмены задачи - /// - [HttpPost("{uid}")] - [AllowAnonymous] - public virtual async Task PostDataAsync(string uid, [FromBody] IEnumerable dtos, - CancellationToken token) + catch(KeyNotFoundException) { - await telemetryDataService.UpdateDataAsync(uid, dtos, token).ConfigureAwait(false); - - var idWell = telemetryService.GetIdWellByTelemetryUid(uid); - if (idWell is not null && dtos.Any()) - _ = Task.Run(() => SignalRNotifyAsync(idWell.Value, dtos, CancellationToken.None)); - - return Ok(); - } - - /// - /// Возвращает данные САУБ по скважине. - /// По умолчанию за последние 10 минут. - /// - /// id скважины - /// дата начала выборки. По умолчанию: текущее время - intervalSec - /// интервал времени даты начала выборки, секунды - /// желаемое количество точек. Если в выборке точек будет больше, то выборка будет прорежена. - /// Токен завершения задачи - /// - [HttpGet("{idWell}")] - [Permission] - public virtual async Task>> GetDataAsync(int idWell, - DateTime begin = default, - int intervalSec = 600, - int approxPointsCount = 1024, - //TODO: сделать cancellationToken обязательным - CancellationToken token = default) - { - int? idCompany = User.GetCompanyId(); - - if (idCompany is null) - return Forbid(); - - bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false); - - if (!isCompanyOwnsWell) - return Forbid(); - - var content = await telemetryDataService.GetByWellAsync(idWell, begin, - intervalSec, approxPointsCount, token).ConfigureAwait(false); - - return Ok(content); - } - - /// - /// Новая версия. Возвращает данные САУБ по скважине. - /// По умолчанию за последние 10 минут. - /// - /// id скважины - /// - /// Токен завершения задачи - /// - [HttpGet("{idWell}/data")] - [Permission] - public virtual async Task>> GetData2Async(int idWell, - [FromQuery]TelemetryDataRequest request, - CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - - if (idCompany is null) - return Forbid(); - - bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false); - - if (!isCompanyOwnsWell) - return Forbid(); - - var content = await telemetryDataService.GetByWellAsync(idWell, request, token); - - return Ok(content); - } - - /// - /// Возвращает диапазон дат за которые есть телеметрия за период времени - /// - /// - /// - /// - /// - /// - [HttpGet("{idWell}/dateRange")] - [ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)] - [ProducesResponseType((int)System.Net.HttpStatusCode.NotFound)] - [ProducesResponseType((int)System.Net.HttpStatusCode.NoContent)] - public virtual async Task> GetRangeAsync( - [FromRoute] int idWell, - [Required] DateTimeOffset geDate, - DateTimeOffset? leDate, - CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - - if (idCompany is null) - return Forbid(); - - bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false); - - if (!isCompanyOwnsWell) - return Forbid(); - - var content = await telemetryDataService.GetRangeAsync(idWell, geDate, leDate, token); - - if (content is null) - return NoContent(); - - return Ok(content); - } - - /// - /// Возвращает диапазон дат сохраненных данных. - /// - /// id скважины - /// Токен завершения задачи - /// - [HttpGet("{idWell}/datesRange")] - [Permission] - [ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)] - [ProducesResponseType((int)System.Net.HttpStatusCode.NotFound)] - [ProducesResponseType((int)System.Net.HttpStatusCode.NoContent)] - public virtual async Task> GetDataDatesRangeAsync(int idWell, - CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - - if (idCompany is null) - return Forbid(); - - bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false); - - if (!isCompanyOwnsWell) - return Forbid(); - try - { - var dataDatesRange = wellService.GetDatesRange(idWell); - return Ok(dataDatesRange); - } - catch(KeyNotFoundException) - { - return NoContent(); - } + return NoContent(); } } } diff --git a/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSaubController.cs b/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSaubController.cs index d760efab..a873c49b 100644 --- a/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSaubController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSaubController.cs @@ -10,63 +10,62 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers.SAUB +namespace AsbCloudWebApi.Controllers.SAUB; + +/// +/// Данные АКБ +/// +[Route("api/[controller]")] +[ApiController] +public class TelemetryDataSaubController : TelemetryDataBaseController { - /// - /// Данные АКБ - /// - [Route("api/[controller]")] - [ApiController] - public class TelemetryDataSaubController : TelemetryDataBaseController + private readonly ITelemetryDataSaubService telemetryDataSaubService; + + public TelemetryDataSaubController( + ITelemetryService telemetryService, + ITelemetryDataSaubService telemetryDataService, + IWellService wellService, + IHubContext telemetryHubContext) + : base( + telemetryService, + telemetryDataService, + wellService, + telemetryHubContext) { - private readonly ITelemetryDataSaubService telemetryDataSaubService; + telemetryDataSaubService = telemetryDataService; + } - public TelemetryDataSaubController( - ITelemetryService telemetryService, - ITelemetryDataSaubService telemetryDataService, - IWellService wellService, - IHubContext telemetryHubContext) - : base( - telemetryService, - telemetryDataService, - wellService, - telemetryHubContext) - { - telemetryDataSaubService = telemetryDataService; - } + /// + /// Выгрузка архива. Не более 3-х суток. Формат даты строгий. + /// + /// id скважины (из адресной строки) + /// начало интервала в формате: yyyy-MM-DD HH:mm + /// конец интервала в формате: yyyy-MM-DD HH:mm + /// + /// + [HttpGet("{idWell}/export/csv")] + [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public async Task GetZippedCsv(int idWell, DateTime beginDate, DateTime endDate, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); - /// - /// Выгрузка архива. Не более 3-х суток. Формат даты строгий. - /// - /// id скважины (из адресной строки) - /// начало интервала в формате: yyyy-MM-DD HH:mm - /// конец интервала в формате: yyyy-MM-DD HH:mm - /// - /// - [HttpGet("{idWell}/export/csv")] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] - [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task GetZippedCsv(int idWell, DateTime beginDate, DateTime endDate, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); + if (idCompany is null) + return Forbid(); - if (idCompany is null) - return Forbid(); + bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false); - bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false); + if (!isCompanyOwnsWell) + return Forbid(); - if (!isCompanyOwnsWell) - return Forbid(); + var stream = await telemetryDataSaubService.GetZippedCsv(idWell, beginDate, endDate, token).ConfigureAwait(false); + var fileName = $"DataSaub idWell{idWell} {beginDate:yyyy-MM-DDTHH-mm} - {endDate:yyyy-MM-DDTHH-mm}.zip"; + return File(stream, "application/octet-stream", fileName); + } - var stream = await telemetryDataSaubService.GetZippedCsv(idWell, beginDate, endDate, token).ConfigureAwait(false); - var fileName = $"DataSaub idWell{idWell} {beginDate:yyyy-MM-DDTHH-mm} - {endDate:yyyy-MM-DDTHH-mm}.zip"; - return File(stream, "application/octet-stream", fileName); - } - - protected override Task SignalRNotifyAsync(int idWell, IEnumerable dtos, CancellationToken token) - { - return telemetryHubContext.Clients.Group($"well_{idWell}").ReceiveDataSaub(dtos, token); - } + protected override Task SignalRNotifyAsync(int idWell, IEnumerable dtos, CancellationToken token) + { + return telemetryHubContext.Clients.Group($"well_{idWell}").ReceiveDataSaub(dtos, token); } } diff --git a/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSpinController.cs b/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSpinController.cs index 0ff369da..dd7cb2de 100644 --- a/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSpinController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSpinController.cs @@ -8,30 +8,29 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers.SAUB -{ - /// - /// Данные осциллятора и демпфера - /// - [Route("api/[controller]")] - [ApiController] - public class TelemetryDataSpinController : TelemetryDataBaseController - { - public TelemetryDataSpinController( - ITelemetryService telemetryService, - ITelemetryDataService telemetryDataService, - IWellService wellService, - IHubContext telemetryHubContext) - : base( - telemetryService, - telemetryDataService, - wellService, - telemetryHubContext) - {} +namespace AsbCloudWebApi.Controllers.SAUB; - protected override Task SignalRNotifyAsync(int idWell, IEnumerable dtos, CancellationToken token) - { - return telemetryHubContext.Clients.Group($"well_{idWell}").ReceiveDataSpin(dtos, token); - } +/// +/// Данные осциллятора и демпфера +/// +[Route("api/[controller]")] +[ApiController] +public class TelemetryDataSpinController : TelemetryDataBaseController +{ + public TelemetryDataSpinController( + ITelemetryService telemetryService, + ITelemetryDataService telemetryDataService, + IWellService wellService, + IHubContext telemetryHubContext) + : base( + telemetryService, + telemetryDataService, + wellService, + telemetryHubContext) + {} + + protected override Task SignalRNotifyAsync(int idWell, IEnumerable dtos, CancellationToken token) + { + return telemetryHubContext.Clients.Group($"well_{idWell}").ReceiveDataSpin(dtos, token); } } diff --git a/AsbCloudWebApi/Controllers/SAUB/TelemetryWirelineRunOutController.cs b/AsbCloudWebApi/Controllers/SAUB/TelemetryWirelineRunOutController.cs index 719190a7..2930f054 100644 --- a/AsbCloudWebApi/Controllers/SAUB/TelemetryWirelineRunOutController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/TelemetryWirelineRunOutController.cs @@ -10,104 +10,101 @@ using System.Threading; using AsbCloudApp.Repositories; using System.ComponentModel.DataAnnotations; -namespace AsbCloudWebApi.Controllers.SAUB +namespace AsbCloudWebApi.Controllers.SAUB; + + +/// +/// Наработка талевого каната +/// +[ApiController] +[Authorize] +[Route("api/[controller]")] +public class TelemetryWirelineRunOutController : ControllerBase { + private readonly ITelemetryService telemetryService; + private readonly IWellService wellService; + private readonly IHubContext telemetryHubContext; + private readonly ITelemetryWirelineRunOutRepository repository; + private static string SirnalRMethodGetDataName => "ReceiveWirelineRunOut"; - /// - /// Наработка талевого каната - /// - [ApiController] - [Authorize] - [Route("api/[controller]")] - public class TelemetryWirelineRunOutController : ControllerBase + public TelemetryWirelineRunOutController( + ITelemetryService telemetryService, + IWellService wellService, + IHubContext telemetryHubContext, + ITelemetryWirelineRunOutRepository repository) { - private readonly ITelemetryService telemetryService; - private readonly IWellService wellService; - private readonly IHubContext telemetryHubContext; - private readonly ITelemetryWirelineRunOutRepository repository; - private static string SirnalRMethodGetDataName => "ReceiveWirelineRunOut"; - - public TelemetryWirelineRunOutController( - ITelemetryService telemetryService, - IWellService wellService, - IHubContext telemetryHubContext, - ITelemetryWirelineRunOutRepository repository) - { - this.telemetryService = telemetryService; - this.wellService = wellService; - this.telemetryHubContext = telemetryHubContext; - this.repository = repository; - } - - /// - /// Принимает данные от панели - /// - /// - /// - /// - /// - [HttpPost("{uid}")] - [AllowAnonymous] - public async Task PostDataAsync(string uid, [FromBody, Required] TelemetryWirelineRunOutBaseDto dto, CancellationToken token) - { - var data = await repository.AddOrUpdateAsync(uid, dto, token); - - var idWell = telemetryService.GetIdWellByTelemetryUid(uid); - if (idWell is not null) - _ = Task.Run(async () => - { - var clients = telemetryHubContext.Clients.Group($"well_{idWell}"); - await clients.SendAsync(SirnalRMethodGetDataName, dto); - }, CancellationToken.None); - - return Ok(); - } - - /// - /// Выдает данные по скважине - /// - /// - /// - /// - [HttpGet("{idWell}")] - [Permission] - public async Task> GetDataAsync(int idWell, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - - if (idCompany is null) - return Forbid(); - - bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false); - - if (!isCompanyOwnsWell) - return Forbid(); - - var dto = await repository.GetOrDefaultAsync(idWell, token); - - if (dto is null) - return NoContent(); - return Ok(dto); - } - - /// - /// Выдает данные по всем доступным скважинам - /// - /// - /// - [HttpGet] - [Permission] - public async Task>> GetAllAsync(CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - if (idCompany is null) - return Forbid(); - - var dtos = await repository.GetAllAsync((int)idCompany, token); - return Ok(dtos); - } + this.telemetryService = telemetryService; + this.wellService = wellService; + this.telemetryHubContext = telemetryHubContext; + this.repository = repository; } + /// + /// Принимает данные от панели + /// + /// + /// + /// + /// + [HttpPost("{uid}")] + [AllowAnonymous] + public async Task PostDataAsync(string uid, [FromBody, Required] TelemetryWirelineRunOutBaseDto dto, CancellationToken token) + { + var data = await repository.AddOrUpdateAsync(uid, dto, token); + var idWell = telemetryService.GetIdWellByTelemetryUid(uid); + if (idWell is not null) + _ = Task.Run(async () => + { + var clients = telemetryHubContext.Clients.Group($"well_{idWell}"); + await clients.SendAsync(SirnalRMethodGetDataName, dto); + }, CancellationToken.None); + + return Ok(); + } + + /// + /// Выдает данные по скважине + /// + /// + /// + /// + [HttpGet("{idWell}")] + [Permission] + public async Task> GetDataAsync(int idWell, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + + if (idCompany is null) + return Forbid(); + + bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false); + + if (!isCompanyOwnsWell) + return Forbid(); + + var dto = await repository.GetOrDefaultAsync(idWell, token); + + if (dto is null) + return NoContent(); + return Ok(dto); + } + + /// + /// Выдает данные по всем доступным скважинам + /// + /// + /// + [HttpGet] + [Permission] + public async Task>> GetAllAsync(CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + if (idCompany is null) + return Forbid(); + + var dtos = await repository.GetAllAsync((int)idCompany, token); + return Ok(dtos); + } } diff --git a/AsbCloudWebApi/Controllers/ScheduleController.cs b/AsbCloudWebApi/Controllers/ScheduleController.cs index 6effe4e6..459fc608 100644 --- a/AsbCloudWebApi/Controllers/ScheduleController.cs +++ b/AsbCloudWebApi/Controllers/ScheduleController.cs @@ -6,41 +6,40 @@ using System; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + + +/// +/// Расписание бурильщиков +/// +[Route("api/schedule")] +[ApiController] +[Authorize] +public class ScheduleController : CrudWellRelatedController { + private readonly IScheduleRepository scheduleService; + + public ScheduleController(IScheduleRepository scheduleService, IWellService wellService) + : base(wellService, scheduleService) + { + this.scheduleService = service; + } /// - /// Расписание бурильщиков + /// Получить бурильщика работавшего на скважине в определенное время. /// - [Route("api/schedule")] - [ApiController] - [Authorize] - public class ScheduleController : CrudWellRelatedController + /// Идентификатор скважины + /// Рабочее время + /// + /// бурильщик + [HttpGet("driller")] + public async Task> GetDrillerAsync(int idWell, DateTimeOffset workTime, CancellationToken token) { - private readonly IScheduleRepository scheduleService; - - public ScheduleController(IScheduleRepository scheduleService, IWellService wellService) - : base(wellService, scheduleService) - { - this.scheduleService = service; - } - - /// - /// Получить бурильщика работавшего на скважине в определенное время. - /// - /// Идентификатор скважины - /// Рабочее время - /// - /// бурильщик - [HttpGet("driller")] - public async Task> GetDrillerAsync(int idWell, DateTimeOffset workTime, CancellationToken token) - { - if (!await UserHasAccesToWellAsync(idWell, token)) - return Forbid(); - - var result = await scheduleService.GetOrDefaultDrillerAsync(idWell, workTime, token); - return Ok(result); - } + if (!await UserHasAccesToWellAsync(idWell, token)) + return Forbid(); + var result = await scheduleService.GetOrDefaultDrillerAsync(idWell, workTime, token); + return Ok(result); } + } diff --git a/AsbCloudWebApi/Controllers/SlipsStatController.cs b/AsbCloudWebApi/Controllers/SlipsStatController.cs index 6c61c0e3..e167f951 100644 --- a/AsbCloudWebApi/Controllers/SlipsStatController.cs +++ b/AsbCloudWebApi/Controllers/SlipsStatController.cs @@ -10,43 +10,42 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Аналитика по удержанию в клиньях +/// +[Route("api/slipsStat")] +[ApiController] +[Authorize] +public class SlipsStatController : ControllerBase { - /// - /// Аналитика по удержанию в клиньях - /// - [Route("api/slipsStat")] - [ApiController] - [Authorize] - public class SlipsStatController : ControllerBase + private readonly ISlipsStatService slipsAnalyticsService; + + public SlipsStatController(ISlipsStatService slipsAnalyticsService) { - private readonly ISlipsStatService slipsAnalyticsService; + this.slipsAnalyticsService = slipsAnalyticsService; + } - public SlipsStatController(ISlipsStatService slipsAnalyticsService) - { - this.slipsAnalyticsService = slipsAnalyticsService; - } + /// + /// Получить аналитику по удержанию в клиньях (по бурильщикам) + /// + /// Параметры запроса + /// Токен отмены задачи + /// Список бурильщиков + [HttpGet] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetAllAsync( + [FromQuery] OperationStatRequest request, + CancellationToken token) + { + var idUser = User.GetUserId(); - /// - /// Получить аналитику по удержанию в клиньях (по бурильщикам) - /// - /// Параметры запроса - /// Токен отмены задачи - /// Список бурильщиков - [HttpGet] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetAllAsync( - [FromQuery] OperationStatRequest request, - CancellationToken token) - { - var idUser = User.GetUserId(); + if (!idUser.HasValue) + throw new ForbidException("Не удается вас опознать"); - if (!idUser.HasValue) - throw new ForbidException("Не удается вас опознать"); - - var data = await slipsAnalyticsService.GetAllAsync(request, token).ConfigureAwait(false); - return Ok(data); - } + var data = await slipsAnalyticsService.GetAllAsync(request, token).ConfigureAwait(false); + return Ok(data); } } diff --git a/AsbCloudWebApi/Controllers/Subsystems/AdminSubsystemController.cs b/AsbCloudWebApi/Controllers/Subsystems/AdminSubsystemController.cs index 8872df9f..53a2cb11 100644 --- a/AsbCloudWebApi/Controllers/Subsystems/AdminSubsystemController.cs +++ b/AsbCloudWebApi/Controllers/Subsystems/AdminSubsystemController.cs @@ -4,20 +4,19 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -namespace AsbCloudWebApi.Controllers.Subsystems -{ - /// - /// Редактор подсистем для админки - /// - [Route("api/admin/subsystem")] - [ApiController] - [Authorize] - public class AdminSubsystemController : CrudController> - { - public AdminSubsystemController(ICrudRepository service) - : base(service) - { - } - } -} +namespace AsbCloudWebApi.Controllers.Subsystems; + +/// +/// Редактор подсистем для админки +/// +[Route("api/admin/subsystem")] +[ApiController] +[Authorize] +public class AdminSubsystemController : CrudController> +{ + public AdminSubsystemController(ICrudRepository service) + : base(service) + { + } +} diff --git a/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs b/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs index 8a5b2801..b4402ca6 100644 --- a/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs +++ b/AsbCloudWebApi/Controllers/Subsystems/SubsystemController.cs @@ -10,84 +10,83 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers.Subsystems +namespace AsbCloudWebApi.Controllers.Subsystems; + +/// +/// Наработка подсистем +/// +[Route("api/[controller]")] +[ApiController] +[Authorize] +public class SubsystemController : ControllerBase { - /// - /// Наработка подсистем - /// - [Route("api/[controller]")] - [ApiController] - [Authorize] - public class SubsystemController : ControllerBase + private readonly ISubsystemService subsystemService; + private readonly ITelemetryDataSaubService telemetryDataSaubService; + private readonly IWellService wellService; + + public SubsystemController( + ISubsystemService subsystemService, + IWellService wellService, + ITelemetryDataSaubService telemetryDataSaubService) { - private readonly ISubsystemService subsystemService; - private readonly ITelemetryDataSaubService telemetryDataSaubService; - private readonly IWellService wellService; + this.subsystemService = subsystemService; + this.wellService = wellService; + this.telemetryDataSaubService = telemetryDataSaubService; + } - public SubsystemController( - ISubsystemService subsystemService, - IWellService wellService, - ITelemetryDataSaubService telemetryDataSaubService) - { - this.subsystemService = subsystemService; - this.wellService = wellService; - this.telemetryDataSaubService = telemetryDataSaubService; - } + /// + /// получить статистику + /// + [HttpGet("stat")] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] + public async Task GetStatAsync([FromQuery] SubsystemRequest request, CancellationToken token) + { + if (!await UserHasAccessToWellAsync(request.IdWell, token)) + return Forbid(); + var subsystemResult = await subsystemService.GetStatAsync(request, token); + return Ok(subsystemResult); + } - /// - /// получить статистику - /// - [HttpGet("stat")] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] - public async Task GetStatAsync([FromQuery] SubsystemRequest request, CancellationToken token) - { - if (!await UserHasAccessToWellAsync(request.IdWell, token)) - return Forbid(); - var subsystemResult = await subsystemService.GetStatAsync(request, token); - return Ok(subsystemResult); - } + /// + /// получить период, за который будет рассчитываться статистика + /// + [HttpGet("operationsPeriod/{idWell}")] + [ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)] + public async Task GetStatDateRangeAsync([FromRoute] int idWell, CancellationToken token) + { + if (!await UserHasAccessToWellAsync(idWell, token)) + return Forbid(); - /// - /// получить период, за который будет рассчитываться статистика - /// - [HttpGet("operationsPeriod/{idWell}")] - [ProducesResponseType(typeof(DatesRangeDto), (int)System.Net.HttpStatusCode.OK)] - public async Task GetStatDateRangeAsync([FromRoute] int idWell, CancellationToken token) - { + var dateRange = telemetryDataSaubService.GetRange(idWell); + + return Ok(dateRange); + } + + [HttpGet("drillerDetectedOperationStat")] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetByWellsAsync([FromQuery] GetStatRequest request, + CancellationToken token) + { + if (!request.IdsWells.Any()) + return NoContent(); + + foreach(var idWell in request.IdsWells) if (!await UserHasAccessToWellAsync(idWell, token)) return Forbid(); - var dateRange = telemetryDataSaubService.GetRange(idWell); + var result = await subsystemService.GetByWellsAsync(request, token); - return Ok(dateRange); - } + return Ok(result); + } - [HttpGet("drillerDetectedOperationStat")] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetByWellsAsync([FromQuery] GetStatRequest request, - CancellationToken token) - { - if (!request.IdsWells.Any()) - return NoContent(); - - foreach(var idWell in request.IdsWells) - if (!await UserHasAccessToWellAsync(idWell, token)) - return Forbid(); - - var result = await subsystemService.GetByWellsAsync(request, token); - - return Ok(result); - } - - private async Task UserHasAccessToWellAsync(int idWell, CancellationToken token) - { - var idCompany = User.GetCompanyId(); - if (idCompany is not null && - await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token) - .ConfigureAwait(false)) - return true; - return false; - } + private async Task UserHasAccessToWellAsync(int idWell, CancellationToken token) + { + var idCompany = User.GetCompanyId(); + if (idCompany is not null && + await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token) + .ConfigureAwait(false)) + return true; + return false; } } \ No newline at end of file diff --git a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryController.cs b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryController.cs index 643aed2c..9fc73eae 100644 --- a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryController.cs +++ b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryController.cs @@ -10,74 +10,72 @@ using System.Threading.Tasks; using AsbCloudApp.Requests.ExportOptions; using AsbCloudInfrastructure.Services.Trajectory.Export; -namespace AsbCloudWebApi.Controllers.Trajectory +namespace AsbCloudWebApi.Controllers.Trajectory; + + +/// +/// Плановые и фактические траектории (загрузка и хранение) +/// +[ApiController] +[Authorize] +public abstract class TrajectoryController : ControllerBase + where TDto : TrajectoryGeoDto { + protected abstract string TemplateFileName { get; } - /// - /// Плановые и фактические траектории (загрузка и хранение) - /// - [ApiController] - [Authorize] - public abstract class TrajectoryController : ControllerBase - where TDto : TrajectoryGeoDto + private readonly IWellService wellService; + private readonly TrajectoryExportService trajectoryExportService; + private readonly ITrajectoryRepository trajectoryRepository; + + protected TrajectoryController(IWellService wellService, + TrajectoryExportService trajectoryExportService, + ITrajectoryRepository trajectoryRepository) { - protected abstract string TemplateFileName { get; } - - private readonly IWellService wellService; - private readonly TrajectoryExportService trajectoryExportService; - private readonly ITrajectoryRepository trajectoryRepository; - - protected TrajectoryController(IWellService wellService, - TrajectoryExportService trajectoryExportService, - ITrajectoryRepository trajectoryRepository) - { - this.trajectoryExportService = trajectoryExportService; - this.wellService = wellService; - this.trajectoryRepository = trajectoryRepository; - } - - /// - /// Формируем excel файл с текущими строками траектории - /// - /// id скважины - /// Токен отмены задачи - /// Запрашиваемый файл - [HttpGet("export")] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] - [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task ExportAsync([FromRoute] int idWell, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, - token).ConfigureAwait(false)) - return Forbid(); - - var exportOptions = new WellRelatedExportRequest(idWell); - var (fileName, file) = await trajectoryExportService.ExportAsync(exportOptions, token); - return File(file, "application/octet-stream", fileName); - } - - /// - /// Получаем список всех строк координат траектории (для клиента) - /// - /// ключ скважины - /// Токен отмены задачи - /// Список добавленных координат траектории - [HttpGet] - public async Task>> GetAsync(int idWell, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, - token).ConfigureAwait(false)) - return Forbid(); - var result = await trajectoryRepository.GetAsync(idWell, token); - return Ok(result); - } - - protected async Task CanUserAccessToWellAsync(int idWell, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false); - } + this.trajectoryExportService = trajectoryExportService; + this.wellService = wellService; + this.trajectoryRepository = trajectoryRepository; } + /// + /// Формируем excel файл с текущими строками траектории + /// + /// id скважины + /// Токен отмены задачи + /// Запрашиваемый файл + [HttpGet("export")] + [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public async Task ExportAsync([FromRoute] int idWell, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, + token).ConfigureAwait(false)) + return Forbid(); + + var exportOptions = new WellRelatedExportRequest(idWell); + var (fileName, file) = await trajectoryExportService.ExportAsync(exportOptions, token); + return File(file, "application/octet-stream", fileName); + } + + /// + /// Получаем список всех строк координат траектории (для клиента) + /// + /// ключ скважины + /// Токен отмены задачи + /// Список добавленных координат траектории + [HttpGet] + public async Task>> GetAsync(int idWell, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, + token).ConfigureAwait(false)) + return Forbid(); + var result = await trajectoryRepository.GetAsync(idWell, token); + return Ok(result); + } + + protected async Task CanUserAccessToWellAsync(int idWell, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false); + } } diff --git a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs index c83eafc8..2f7a71df 100644 --- a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs +++ b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryEditableController.cs @@ -13,186 +13,185 @@ using AsbCloudApp.Requests.ParserOptions; using AsbCloudApp.Services.Parsers; using AsbCloudInfrastructure.Services.Trajectory.Export; -namespace AsbCloudWebApi.Controllers.Trajectory +namespace AsbCloudWebApi.Controllers.Trajectory; + + +/// +/// Плановые и фактические траектории (загрузка и хранение) +/// +[ApiController] +[Authorize] +public abstract class TrajectoryEditableController : TrajectoryController + where TDto : TrajectoryGeoDto { + private readonly IParserService parserService; + private readonly ITrajectoryEditableRepository trajectoryRepository; + + protected TrajectoryEditableController(IWellService wellService, + IParserService parserService, + TrajectoryExportService trajectoryExportService, + ITrajectoryEditableRepository trajectoryRepository) + : base(wellService, trajectoryExportService, trajectoryRepository) + { + this.parserService = parserService; + this.trajectoryRepository = trajectoryRepository; + } + + /// + /// Возвращает excel шаблон для заполнения строк траектории + /// + /// Запрашиваемый файл + [HttpGet("template")] + [AllowAnonymous] + [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public IActionResult GetTemplate() + { + var stream = parserService.GetTemplateFile(); + return File(stream, "application/octet-stream", TemplateFileName); + } + + /// + /// Импортирует координаты из excel (xlsx) файла + /// + /// id скважины + /// Коллекция из одного файла xlsx + /// Токен отмены задачи + /// количество успешно записанных строк в БД + [HttpPost("parse")] + [ProducesResponseType((int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] + public async Task>> Parse(int idWell, + [FromForm] IFormFileCollection files, + CancellationToken token) + { + var idUser = User.GetUserId(); + + if (!idUser.HasValue) + return Forbid(); + + if (!await CanUserAccessToWellAsync(idWell, token)) + return Forbid(); + + var stream = files.GetExcelFile(); + + try + { + var options = new WellRelatedParserRequest(idWell); + var dto = parserService.Parse(stream, options); + + return Ok(dto); + } + catch (FileFormatException ex) + { + return this.ValidationBadRequest(nameof(files), ex.Message); + } + } + + /// + /// Добавление + /// + /// + /// + /// + /// + [HttpPost] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task InsertRangeAsync(int idWell, [FromBody] IEnumerable dtos, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token)) + return Forbid(); + + var idUser = User.GetUserId(); + + if (!idUser.HasValue) + return Forbid(); + + foreach (var dto in dtos) + { + dto.IdUser = idUser.Value; + dto.IdWell = idWell; + } + + var result = await trajectoryRepository.AddRangeAsync(dtos, token); + return Ok(result); + } + + /// + /// Удалить все по скважине и добавить новые + /// + /// + /// + /// + /// + [HttpPost("replace")] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task ClearAndInsertRangeAsync(int idWell, [FromBody] IEnumerable dtos, CancellationToken token) + { + //TODO: это вся радость требует рефакторинга. + //Удаление с добавлением новых записей должно происходить в рамках одной транзакции, да и вообще должно быть реализовано на уровне репозиторий. + //Рефакторинг будет когда доберёмся до журнала изменений для траекторий. + if (!await CanUserAccessToWellAsync(idWell, token)) + return Forbid(); + + var idUser = User.GetUserId(); + + if (!idUser.HasValue) + return Forbid(); + + foreach (var dto in dtos) + { + dto.IdUser = idUser.Value; + dto.IdWell = idWell; + } + + await trajectoryRepository.DeleteByIdWellAsync(idWell, token); + var result = await trajectoryRepository.AddRangeAsync(dtos, token); + return Ok(result); + } /// - /// Плановые и фактические траектории (загрузка и хранение) + /// Изменить выбранную строку с координатами /// - [ApiController] - [Authorize] - public abstract class TrajectoryEditableController : TrajectoryController - where TDto : TrajectoryGeoDto - { - private readonly IParserService parserService; - private readonly ITrajectoryEditableRepository trajectoryRepository; + /// + /// + /// + /// + /// количество успешно обновленных строк в БД + [HttpPut("{idRow}")] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task UpdateAsync(int idWell, int idRow, + [FromBody] TDto row, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); + int? idUser = User.GetUserId(); + if (!idUser.HasValue) + return Forbid(); + row.Id = idRow; + row.IdUser = idUser.Value; + row.IdWell = idWell; + var result = await trajectoryRepository.UpdateAsync(row, token); + return Ok(result); + } - protected TrajectoryEditableController(IWellService wellService, - IParserService parserService, - TrajectoryExportService trajectoryExportService, - ITrajectoryEditableRepository trajectoryRepository) - : base(wellService, trajectoryExportService, trajectoryRepository) - { - this.parserService = parserService; - this.trajectoryRepository = trajectoryRepository; - } - - /// - /// Возвращает excel шаблон для заполнения строк траектории - /// - /// Запрашиваемый файл - [HttpGet("template")] - [AllowAnonymous] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK, "application/octet-stream")] - [ProducesResponseType(StatusCodes.Status204NoContent)] - public IActionResult GetTemplate() - { - var stream = parserService.GetTemplateFile(); - return File(stream, "application/octet-stream", TemplateFileName); - } - - /// - /// Импортирует координаты из excel (xlsx) файла - /// - /// id скважины - /// Коллекция из одного файла xlsx - /// Токен отмены задачи - /// количество успешно записанных строк в БД - [HttpPost("parse")] - [ProducesResponseType((int)System.Net.HttpStatusCode.OK)] - [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] - public async Task>> Parse(int idWell, - [FromForm] IFormFileCollection files, - CancellationToken token) - { - var idUser = User.GetUserId(); - - if (!idUser.HasValue) + /// + /// Удалить выбранную строку с координатами + /// + /// + /// + /// + /// количество успешно удаленных строк из БД + [HttpDelete("{idRow}")] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task DeleteAsync(int idWell, int idRow, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, + token).ConfigureAwait(false)) return Forbid(); - if (!await CanUserAccessToWellAsync(idWell, token)) - return Forbid(); + var result = await trajectoryRepository.DeleteRangeAsync(new int[] { idRow }, token); - var stream = files.GetExcelFile(); - - try - { - var options = new WellRelatedParserRequest(idWell); - var dto = parserService.Parse(stream, options); - - return Ok(dto); - } - catch (FileFormatException ex) - { - return this.ValidationBadRequest(nameof(files), ex.Message); - } - } - - /// - /// Добавление - /// - /// - /// - /// - /// - [HttpPost] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task InsertRangeAsync(int idWell, [FromBody] IEnumerable dtos, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token)) - return Forbid(); - - var idUser = User.GetUserId(); - - if (!idUser.HasValue) - return Forbid(); - - foreach (var dto in dtos) - { - dto.IdUser = idUser.Value; - dto.IdWell = idWell; - } - - var result = await trajectoryRepository.AddRangeAsync(dtos, token); - return Ok(result); - } - - /// - /// Удалить все по скважине и добавить новые - /// - /// - /// - /// - /// - [HttpPost("replace")] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task ClearAndInsertRangeAsync(int idWell, [FromBody] IEnumerable dtos, CancellationToken token) - { - //TODO: это вся радость требует рефакторинга. - //Удаление с добавлением новых записей должно происходить в рамках одной транзакции, да и вообще должно быть реализовано на уровне репозиторий. - //Рефакторинг будет когда доберёмся до журнала изменений для траекторий. - if (!await CanUserAccessToWellAsync(idWell, token)) - return Forbid(); - - var idUser = User.GetUserId(); - - if (!idUser.HasValue) - return Forbid(); - - foreach (var dto in dtos) - { - dto.IdUser = idUser.Value; - dto.IdWell = idWell; - } - - await trajectoryRepository.DeleteByIdWellAsync(idWell, token); - var result = await trajectoryRepository.AddRangeAsync(dtos, token); - return Ok(result); - } - - /// - /// Изменить выбранную строку с координатами - /// - /// - /// - /// - /// - /// количество успешно обновленных строк в БД - [HttpPut("{idRow}")] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task UpdateAsync(int idWell, int idRow, - [FromBody] TDto row, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - int? idUser = User.GetUserId(); - if (!idUser.HasValue) - return Forbid(); - row.Id = idRow; - row.IdUser = idUser.Value; - row.IdWell = idWell; - var result = await trajectoryRepository.UpdateAsync(row, token); - return Ok(result); - } - - /// - /// Удалить выбранную строку с координатами - /// - /// - /// - /// - /// количество успешно удаленных строк из БД - [HttpDelete("{idRow}")] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task DeleteAsync(int idWell, int idRow, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, - token).ConfigureAwait(false)) - return Forbid(); - - var result = await trajectoryRepository.DeleteRangeAsync(new int[] { idRow }, token); - - return Ok(result); - } + return Ok(result); } } \ No newline at end of file diff --git a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryPlanController.cs b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryPlanController.cs index 10d34ed8..a9c9a3b0 100644 --- a/AsbCloudWebApi/Controllers/Trajectory/TrajectoryPlanController.cs +++ b/AsbCloudWebApi/Controllers/Trajectory/TrajectoryPlanController.cs @@ -9,47 +9,46 @@ using System.Threading; using System.Threading.Tasks; using AsbCloudInfrastructure.Services.Trajectory.Parser; -namespace AsbCloudWebApi.Controllers.Trajectory +namespace AsbCloudWebApi.Controllers.Trajectory; + +/// +/// Плановая траектория (загрузка и хранение) +/// +[Route("api/well/{idWell}/[controller]")] +[ApiController] +public class TrajectoryPlanController : TrajectoryEditableController { - /// - /// Плановая траектория (загрузка и хранение) - /// - [Route("api/well/{idWell}/[controller]")] - [ApiController] - public class TrajectoryPlanController : TrajectoryEditableController - { - private readonly TrajectoryService trajectoryVisualizationService; + private readonly TrajectoryService trajectoryVisualizationService; - protected override string TemplateFileName => "ЕЦП_шаблон_файла_плановая_траектория.xlsx"; + protected override string TemplateFileName => "ЕЦП_шаблон_файла_плановая_траектория.xlsx"; - public TrajectoryPlanController(IWellService wellService, - TrajectoryPlanParser parserService, - TrajectoryPlanExportService trajectoryExportService, - ITrajectoryEditableRepository trajectoryRepository, - TrajectoryService trajectoryVisualizationService) - : base(wellService, parserService, trajectoryExportService, trajectoryRepository) - { - this.trajectoryVisualizationService = trajectoryVisualizationService; - } + public TrajectoryPlanController(IWellService wellService, + TrajectoryPlanParser parserService, + TrajectoryPlanExportService trajectoryExportService, + ITrajectoryEditableRepository trajectoryRepository, + TrajectoryService trajectoryVisualizationService) + : base(wellService, parserService, trajectoryExportService, trajectoryRepository) + { + this.trajectoryVisualizationService = trajectoryVisualizationService; + } - /// - /// Получение координат для визуализации траектории (плановой и фактической) - /// - /// - /// - /// - [HttpGet("trajectoryCartesianPlanFact")] - [ProducesResponseType( - typeof(TrajectoryPlanFactDto, IEnumerable>), - (int)System.Net.HttpStatusCode.OK)] - public async Task GetTrajectoryCartesianPlanFactAsync(int idWell, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, - token).ConfigureAwait(false)) - return Forbid(); + /// + /// Получение координат для визуализации траектории (плановой и фактической) + /// + /// + /// + /// + [HttpGet("trajectoryCartesianPlanFact")] + [ProducesResponseType( + typeof(TrajectoryPlanFactDto, IEnumerable>), + (int)System.Net.HttpStatusCode.OK)] + public async Task GetTrajectoryCartesianPlanFactAsync(int idWell, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, + token).ConfigureAwait(false)) + return Forbid(); - var result = await trajectoryVisualizationService.GetTrajectoryCartesianAsync(idWell, token); - return Ok(result); - } - } + var result = await trajectoryVisualizationService.GetTrajectoryCartesianAsync(idWell, token); + return Ok(result); + } } \ No newline at end of file diff --git a/AsbCloudWebApi/Controllers/UserSettingsController.cs b/AsbCloudWebApi/Controllers/UserSettingsController.cs index 04a4d5cb..bee87e4d 100644 --- a/AsbCloudWebApi/Controllers/UserSettingsController.cs +++ b/AsbCloudWebApi/Controllers/UserSettingsController.cs @@ -6,103 +6,102 @@ using System.ComponentModel.DataAnnotations; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Контроллер настроек для пользователя +/// +[Route("api/[controller]")] +[ApiController] +[Authorize] +public class UserSettingsController : ControllerBase { - /// - /// Контроллер настроек для пользователя - /// - [Route("api/[controller]")] - [ApiController] - [Authorize] - public class UserSettingsController : ControllerBase + private readonly IUserSettingsRepository service; + + public UserSettingsController(IUserSettingsRepository service) { - private readonly IUserSettingsRepository service; + this.service = service; + } - public UserSettingsController(IUserSettingsRepository service) - { - this.service = service; - } + /// + /// Получить настройки + /// + /// + /// + /// + [HttpGet("{key}")] + [ProducesResponseType(typeof(object), (int)System.Net.HttpStatusCode.OK)] + [Produces("application/json")] + public virtual async Task GetAsync( + [StringLength(255, MinimumLength = 1, ErrorMessage = "The key value cannot less then 1 character and greater then 255. ")] + string key, + CancellationToken token) + { + var userId = User.GetUserId(); + if (userId is null) + return Forbid(); - /// - /// Получить настройки - /// - /// - /// - /// - [HttpGet("{key}")] - [ProducesResponseType(typeof(object), (int)System.Net.HttpStatusCode.OK)] - [Produces("application/json")] - public virtual async Task GetAsync( - [StringLength(255, MinimumLength = 1, ErrorMessage = "The key value cannot less then 1 character and greater then 255. ")] - string key, - CancellationToken token) - { - var userId = User.GetUserId(); - if (userId is null) - return Forbid(); + var result = await service.GetOrDefaultAsync((int)userId, key, token).ConfigureAwait(false); + var actionResult = new JsonResult(result); + actionResult.ContentType = "application/json"; + return actionResult; + } - var result = await service.GetOrDefaultAsync((int)userId, key, token).ConfigureAwait(false); - var actionResult = new JsonResult(result); - actionResult.ContentType = "application/json"; - return actionResult; - } + /// + /// записать новые или обновить старые + /// + /// + /// + /// + /// + [HttpPut("{key}")] + [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] + public virtual async Task> UpsertAsync(string key, [FromBody] System.Text.Json.JsonDocument value, CancellationToken token) + { + var userId = User.GetUserId(); + if (userId is null) + return Forbid(); - /// - /// записать новые или обновить старые - /// - /// - /// - /// - /// - [HttpPut("{key}")] - [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] - public virtual async Task> UpsertAsync(string key, [FromBody] System.Text.Json.JsonDocument value, CancellationToken token) - { - var userId = User.GetUserId(); - if (userId is null) - return Forbid(); + var result = await service.UpsertAsync((int)userId, key, value, token).ConfigureAwait(false); + if (result < 0) + return this.ValidationBadRequest(nameof(key), "not found"); - var result = await service.UpsertAsync((int)userId, key, value, token).ConfigureAwait(false); - if (result < 0) - return this.ValidationBadRequest(nameof(key), "not found"); + return Ok(result); + } - return Ok(result); - } + /// + /// Удалить настройки пользователя по ключу + /// + /// + /// + /// + [HttpDelete("{key}")] + [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] + public virtual async Task> DeleteAsync(string key, CancellationToken token) + { + var userId = User.GetUserId(); + if (userId is null) + return Forbid(); - /// - /// Удалить настройки пользователя по ключу - /// - /// - /// - /// - [HttpDelete("{key}")] - [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)] - public virtual async Task> DeleteAsync(string key, CancellationToken token) - { - var userId = User.GetUserId(); - if (userId is null) - return Forbid(); + var result = await service.DeleteAsync((int)userId, key, token).ConfigureAwait(false); + if (result < 0) + return this.ValidationBadRequest(nameof(key), "not found"); - var result = await service.DeleteAsync((int)userId, key, token).ConfigureAwait(false); - if (result < 0) - return this.ValidationBadRequest(nameof(key), "not found"); + return Ok(result); + } - return Ok(result); - } - - /// - /// Удалить ВСЕ настройки пользователя. Для админки. - /// - /// - /// - /// - [HttpDelete("/api/admin/user/{idUser}/settings")] - [Permission] - public virtual async Task> DeleteAllAsync(int idUser, CancellationToken token) - { - var result = await service.DeleteAsync(idUser, token).ConfigureAwait(false); - - return Ok(result); - } + /// + /// Удалить ВСЕ настройки пользователя. Для админки. + /// + /// + /// + /// + [HttpDelete("/api/admin/user/{idUser}/settings")] + [Permission] + public virtual async Task> DeleteAllAsync(int idUser, CancellationToken token) + { + var result = await service.DeleteAsync(idUser, token).ConfigureAwait(false); + + return Ok(result); } } diff --git a/AsbCloudWebApi/Controllers/WITS/WitsControllerAbstract.cs b/AsbCloudWebApi/Controllers/WITS/WitsControllerAbstract.cs index 1c050b66..ae80152e 100644 --- a/AsbCloudWebApi/Controllers/WITS/WitsControllerAbstract.cs +++ b/AsbCloudWebApi/Controllers/WITS/WitsControllerAbstract.cs @@ -12,115 +12,114 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers.WITS +namespace AsbCloudWebApi.Controllers.WITS; + +[Route("api/[controller]")] +[ApiController] +public abstract class WitsControllerAbstract : ControllerBase + where TDto : ITelemetryData { - [Route("api/[controller]")] - [ApiController] - public abstract class WitsControllerAbstract : ControllerBase - where TDto : ITelemetryData + private readonly ITelemetryService telemetryService; + private readonly IHubContext telemetryHubContext; + protected abstract string SirnalRMethodGetDataName { get; } + + public WitsControllerAbstract( + ITelemetryService telemetryService, + IHubContext telemetryHubContext) { - private readonly ITelemetryService telemetryService; - private readonly IHubContext telemetryHubContext; - protected abstract string SirnalRMethodGetDataName { get; } + this.telemetryService = telemetryService; + this.telemetryHubContext = telemetryHubContext; + } - public WitsControllerAbstract( - ITelemetryService telemetryService, - IHubContext telemetryHubContext) - { - this.telemetryService = telemetryService; - this.telemetryHubContext = telemetryHubContext; - } + /// + /// Метод для получения WITS записи от панели оператора. + /// Созраняет в БД. + /// Ретранслирует заинтересованным через SignalR. + /// + /// уникальный идентификатор телеметрии + /// WITS запись + /// + /// + /// + [HttpPost("{uid}")] + [AllowAnonymous] + public async virtual Task PostDataAsync( + string uid, + [FromBody] IEnumerable dtos, + [FromServices] IWitsRecordRepository witsRecordRepository, + CancellationToken token) + { + var telemetry = telemetryService.GetOrCreateTelemetryByUid(uid); + await witsRecordRepository.SaveDataAsync(telemetry.Id, dtos, token).ConfigureAwait(false); + var idWell = telemetryService.GetIdWellByTelemetryUid(uid); + if (idWell != null && dtos.Any()) + _ = Task.Run(() => telemetryHubContext.Clients.Group($"well_{idWell}_wits") + .SendAsync(SirnalRMethodGetDataName, dtos), CancellationToken.None); - /// - /// Метод для получения WITS записи от панели оператора. - /// Созраняет в БД. - /// Ретранслирует заинтересованным через SignalR. - /// - /// уникальный идентификатор телеметрии - /// WITS запись - /// - /// - /// - [HttpPost("{uid}")] - [AllowAnonymous] - public async virtual Task PostDataAsync( - string uid, - [FromBody] IEnumerable dtos, - [FromServices] IWitsRecordRepository witsRecordRepository, - CancellationToken token) - { - var telemetry = telemetryService.GetOrCreateTelemetryByUid(uid); - await witsRecordRepository.SaveDataAsync(telemetry.Id, dtos, token).ConfigureAwait(false); - var idWell = telemetryService.GetIdWellByTelemetryUid(uid); - if (idWell != null && dtos.Any()) - _ = Task.Run(() => telemetryHubContext.Clients.Group($"well_{idWell}_wits") - .SendAsync(SirnalRMethodGetDataName, dtos), CancellationToken.None); + return Ok(); + } - return Ok(); - } + /// + /// Получение последней пришедшей WITS записи. + /// + /// id скважины + /// + /// + [HttpGet("{idWell}/last")] + public virtual ActionResult> GetLastData( + int idWell, + [FromServices] IWitsRecordRepository witsRecordRepository) + { + var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); + if (telemetry is null) + return NoContent(); + var dto = witsRecordRepository.GetLastOrDefault(telemetry.Id); + return Ok(new[] { dto }); + } - /// - /// Получение последней пришедшей WITS записи. - /// - /// id скважины - /// - /// - [HttpGet("{idWell}/last")] - public virtual ActionResult> GetLastData( - int idWell, - [FromServices] IWitsRecordRepository witsRecordRepository) - { - var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); - if (telemetry is null) - return NoContent(); - var dto = witsRecordRepository.GetLastOrDefault(telemetry.Id); - return Ok(new[] { dto }); - } + /// + /// Получение списка архивных WITS записей за период. + /// + /// id скважины + /// начало диапазона + /// конец диапазона + /// + /// + /// + [HttpGet("{idWell}")] + public async virtual Task>> GetDataAsync( + int idWell, + [Required] DateTime begin, + [Required] DateTime end, + [FromServices] IWitsRecordRepository witsRecordRepository, + CancellationToken token) + { + var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); + if (telemetry is null) + return NoContent(); + var dtos = await witsRecordRepository.GetAsync(telemetry.Id, begin, end, token); + return Ok(dtos); + } - /// - /// Получение списка архивных WITS записей за период. - /// - /// id скважины - /// начало диапазона - /// конец диапазона - /// - /// - /// - [HttpGet("{idWell}")] - public async virtual Task>> GetDataAsync( - int idWell, - [Required] DateTime begin, - [Required] DateTime end, - [FromServices] IWitsRecordRepository witsRecordRepository, - CancellationToken token) - { - var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); - if (telemetry is null) - return NoContent(); - var dtos = await witsRecordRepository.GetAsync(telemetry.Id, begin, end, token); - return Ok(dtos); - } - - /// - /// Получение статистики по WITS записи. - /// Диапазон дат и общее количество записей. - /// - /// id скважины - /// - /// - /// - [HttpGet("{idWell}/datesRange")] - [ProducesResponseType(StatusCodes.Status200OK, Type = typeof((DateTime begin, DateTime end, int count)?))] - public async virtual Task GetDatesRangeAsync( - int idWell, - [FromServices] IWitsRecordRepository witsRecordRepository, - CancellationToken token) - { - var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); - if (telemetry is null) - return NoContent(); - var dtos = await witsRecordRepository.GetStatAsync(telemetry.Id, token); - return Ok(dtos); - } + /// + /// Получение статистики по WITS записи. + /// Диапазон дат и общее количество записей. + /// + /// id скважины + /// + /// + /// + [HttpGet("{idWell}/datesRange")] + [ProducesResponseType(StatusCodes.Status200OK, Type = typeof((DateTime begin, DateTime end, int count)?))] + public async virtual Task GetDatesRangeAsync( + int idWell, + [FromServices] IWitsRecordRepository witsRecordRepository, + CancellationToken token) + { + var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell); + if (telemetry is null) + return NoContent(); + var dtos = await witsRecordRepository.GetStatAsync(telemetry.Id, token); + return Ok(dtos); } } diff --git a/AsbCloudWebApi/Controllers/WITS/WitsInfoController.cs b/AsbCloudWebApi/Controllers/WITS/WitsInfoController.cs index 023a4314..9bb49023 100644 --- a/AsbCloudWebApi/Controllers/WITS/WitsInfoController.cs +++ b/AsbCloudWebApi/Controllers/WITS/WitsInfoController.cs @@ -2,70 +2,69 @@ using AsbCloudInfrastructure.Services; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; -namespace AsbCloudWebApi.Controllers.WITS +namespace AsbCloudWebApi.Controllers.WITS; + +/// +/// Инфо о WITS параметрах +/// +[Route("api/[controller]")] +[ApiController] +public class WitsInfoController : ControllerBase { - /// - /// Инфо о WITS параметрах - /// - [Route("api/[controller]")] - [ApiController] - public class WitsInfoController : ControllerBase + private readonly WitsInfoService witsInfoService; + + public WitsInfoController(WitsInfoService witsInfoService) { - private readonly WitsInfoService witsInfoService; + this.witsInfoService = witsInfoService; + } - public WitsInfoController(WitsInfoService witsInfoService) - { - this.witsInfoService = witsInfoService; - } + /// + /// Список всех WITS items для всех известных records + /// + /// + [HttpGet("item")] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public IActionResult GetItems() + { + var result = witsInfoService.GetItems(); + return Ok(result); + } - /// - /// Список всех WITS items для всех известных records - /// - /// - [HttpGet("item")] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public IActionResult GetItems() - { - var result = witsInfoService.GetItems(); - return Ok(result); - } + /// + /// Список всех WITS items для конкретной record + /// + /// + /// + [HttpGet("item/{idRecord}")] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public IActionResult GetItems(int idRecord) + { + var result = witsInfoService.GetItems(idRecord); + return Ok(result); + } - /// - /// Список всех WITS items для конкретной record - /// - /// - /// - [HttpGet("item/{idRecord}")] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public IActionResult GetItems(int idRecord) - { - var result = witsInfoService.GetItems(idRecord); - return Ok(result); - } + /// + /// Список описаний всех wits records + /// + /// + [HttpGet("record")] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public IActionResult GetRecordInfo() + { + var result = witsInfoService.GetRecords(); + return Ok(result); + } - /// - /// Список описаний всех wits records - /// - /// - [HttpGet("record")] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public IActionResult GetRecordInfo() - { - var result = witsInfoService.GetRecords(); - return Ok(result); - } - - /// - /// Описание конкретной record - /// - /// - /// - [HttpGet("record/{idRecord}")] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public IActionResult GetRecordInfo(int idRecord) - { - var result = witsInfoService.GetRecords(idRecord); - return Ok(result); - } + /// + /// Описание конкретной record + /// + /// + /// + [HttpGet("record/{idRecord}")] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public IActionResult GetRecordInfo(int idRecord) + { + var result = witsInfoService.GetRecords(idRecord); + return Ok(result); } } diff --git a/AsbCloudWebApi/Controllers/WITS/WitsRecord1Controller.cs b/AsbCloudWebApi/Controllers/WITS/WitsRecord1Controller.cs index f1c0043b..2fd8fa06 100644 --- a/AsbCloudWebApi/Controllers/WITS/WitsRecord1Controller.cs +++ b/AsbCloudWebApi/Controllers/WITS/WitsRecord1Controller.cs @@ -4,21 +4,20 @@ using AsbCloudWebApi.SignalR; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; -namespace AsbCloudWebApi.Controllers.WITS +namespace AsbCloudWebApi.Controllers.WITS; + +/// +/// WITS записи id = 1 +/// +[Route("api/[controller]")] +[ApiController] +public class WitsRecord1Controller : WitsControllerAbstract { - /// - /// WITS записи id = 1 - /// - [Route("api/[controller]")] - [ApiController] - public class WitsRecord1Controller : WitsControllerAbstract - { - protected override string SirnalRMethodGetDataName => "ReceiveWitsRecord1"; + protected override string SirnalRMethodGetDataName => "ReceiveWitsRecord1"; - public WitsRecord1Controller( - ITelemetryService telemetryService, - IHubContext telemetryHubContext) - : base(telemetryService, telemetryHubContext) { } + public WitsRecord1Controller( + ITelemetryService telemetryService, + IHubContext telemetryHubContext) + : base(telemetryService, telemetryHubContext) { } - } } diff --git a/AsbCloudWebApi/Controllers/WITS/WitsRecord50Controller.cs b/AsbCloudWebApi/Controllers/WITS/WitsRecord50Controller.cs index 3a2a04fb..f439871a 100644 --- a/AsbCloudWebApi/Controllers/WITS/WitsRecord50Controller.cs +++ b/AsbCloudWebApi/Controllers/WITS/WitsRecord50Controller.cs @@ -4,19 +4,18 @@ using AsbCloudWebApi.SignalR; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; -namespace AsbCloudWebApi.Controllers.WITS +namespace AsbCloudWebApi.Controllers.WITS; + +/// +/// WITS записи id = 50 (SIB receiver) +/// +[Route("api/[controller]")] +[ApiController] +public class WitsRecord50Controller : WitsControllerAbstract { - /// - /// WITS записи id = 50 (SIB receiver) - /// - [Route("api/[controller]")] - [ApiController] - public class WitsRecord50Controller : WitsControllerAbstract - { - protected override string SirnalRMethodGetDataName => "ReceiveWitsRecord50"; - public WitsRecord50Controller( - ITelemetryService telemetryService, - IHubContext telemetryHubContext) - : base(telemetryService, telemetryHubContext) { } - } + protected override string SirnalRMethodGetDataName => "ReceiveWitsRecord50"; + public WitsRecord50Controller( + ITelemetryService telemetryService, + IHubContext telemetryHubContext) + : base(telemetryService, telemetryHubContext) { } } diff --git a/AsbCloudWebApi/Controllers/WITS/WitsRecord60Controller.cs b/AsbCloudWebApi/Controllers/WITS/WitsRecord60Controller.cs index ddbdcaad..3265afc1 100644 --- a/AsbCloudWebApi/Controllers/WITS/WitsRecord60Controller.cs +++ b/AsbCloudWebApi/Controllers/WITS/WitsRecord60Controller.cs @@ -4,19 +4,18 @@ using AsbCloudWebApi.SignalR; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; -namespace AsbCloudWebApi.Controllers.WITS +namespace AsbCloudWebApi.Controllers.WITS; + +/// +/// WITS записи id = 60 (SIB receiver) +/// +[Route("api/[controller]")] +[ApiController] +public class WitsRecord60Controller : WitsControllerAbstract { - /// - /// WITS записи id = 60 (SIB receiver) - /// - [Route("api/[controller]")] - [ApiController] - public class WitsRecord60Controller : WitsControllerAbstract - { - protected override string SirnalRMethodGetDataName => "ReceiveWitsRecord60"; - public WitsRecord60Controller( - ITelemetryService telemetryService, - IHubContext telemetryHubContext) - : base(telemetryService, telemetryHubContext) { } - } + protected override string SirnalRMethodGetDataName => "ReceiveWitsRecord60"; + public WitsRecord60Controller( + ITelemetryService telemetryService, + IHubContext telemetryHubContext) + : base(telemetryService, telemetryHubContext) { } } diff --git a/AsbCloudWebApi/Controllers/WITS/WitsRecord61Controller.cs b/AsbCloudWebApi/Controllers/WITS/WitsRecord61Controller.cs index 51a5e280..34f526a0 100644 --- a/AsbCloudWebApi/Controllers/WITS/WitsRecord61Controller.cs +++ b/AsbCloudWebApi/Controllers/WITS/WitsRecord61Controller.cs @@ -4,19 +4,18 @@ using AsbCloudWebApi.SignalR; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; -namespace AsbCloudWebApi.Controllers.WITS +namespace AsbCloudWebApi.Controllers.WITS; + +/// +/// WITS записи id = 61 (SIB receiver) +/// +[Route("api/[controller]")] +[ApiController] +public class WitsRecord61Controller : WitsControllerAbstract { - /// - /// WITS записи id = 61 (SIB receiver) - /// - [Route("api/[controller]")] - [ApiController] - public class WitsRecord61Controller : WitsControllerAbstract - { - protected override string SirnalRMethodGetDataName => "ReceiveWitsRecord61"; - public WitsRecord61Controller( - ITelemetryService telemetryService, - IHubContext telemetryHubContext) - : base(telemetryService, telemetryHubContext) { } - } + protected override string SirnalRMethodGetDataName => "ReceiveWitsRecord61"; + public WitsRecord61Controller( + ITelemetryService telemetryService, + IHubContext telemetryHubContext) + : base(telemetryService, telemetryHubContext) { } } diff --git a/AsbCloudWebApi/Controllers/WITS/WitsRecord7Controller.cs b/AsbCloudWebApi/Controllers/WITS/WitsRecord7Controller.cs index c68ca6ab..040c815b 100644 --- a/AsbCloudWebApi/Controllers/WITS/WitsRecord7Controller.cs +++ b/AsbCloudWebApi/Controllers/WITS/WitsRecord7Controller.cs @@ -4,19 +4,18 @@ using AsbCloudWebApi.SignalR; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; -namespace AsbCloudWebApi.Controllers.WITS +namespace AsbCloudWebApi.Controllers.WITS; + +/// +/// WITS записи id = 7 +/// +[Route("api/[controller]")] +[ApiController] +public class WitsRecord7Controller : WitsControllerAbstract { - /// - /// WITS записи id = 7 - /// - [Route("api/[controller]")] - [ApiController] - public class WitsRecord7Controller : WitsControllerAbstract - { - protected override string SirnalRMethodGetDataName => "ReceiveWitsRecord7"; - public WitsRecord7Controller( - ITelemetryService telemetryService, - IHubContext telemetryHubContext) - : base(telemetryService, telemetryHubContext) { } - } + protected override string SirnalRMethodGetDataName => "ReceiveWitsRecord7"; + public WitsRecord7Controller( + ITelemetryService telemetryService, + IHubContext telemetryHubContext) + : base(telemetryService, telemetryHubContext) { } } diff --git a/AsbCloudWebApi/Controllers/WITS/WitsRecord8Controller.cs b/AsbCloudWebApi/Controllers/WITS/WitsRecord8Controller.cs index 499573ba..14006686 100644 --- a/AsbCloudWebApi/Controllers/WITS/WitsRecord8Controller.cs +++ b/AsbCloudWebApi/Controllers/WITS/WitsRecord8Controller.cs @@ -4,19 +4,18 @@ using AsbCloudWebApi.SignalR; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; -namespace AsbCloudWebApi.Controllers.WITS +namespace AsbCloudWebApi.Controllers.WITS; + +/// +/// WITS записи id = 8 +/// +[Route("api/[controller]")] +[ApiController] +public class WitsRecord8Controller : WitsControllerAbstract { - /// - /// WITS записи id = 8 - /// - [Route("api/[controller]")] - [ApiController] - public class WitsRecord8Controller : WitsControllerAbstract - { - protected override string SirnalRMethodGetDataName => "ReceiveWitsRecord8"; - public WitsRecord8Controller( - ITelemetryService telemetryService, - IHubContext telemetryHubContext) - : base(telemetryService, telemetryHubContext) { } - } + protected override string SirnalRMethodGetDataName => "ReceiveWitsRecord8"; + public WitsRecord8Controller( + ITelemetryService telemetryService, + IHubContext telemetryHubContext) + : base(telemetryService, telemetryHubContext) { } } diff --git a/AsbCloudWebApi/Controllers/WellCompositeController.cs b/AsbCloudWebApi/Controllers/WellCompositeController.cs index 59a4b867..00a34dfe 100644 --- a/AsbCloudWebApi/Controllers/WellCompositeController.cs +++ b/AsbCloudWebApi/Controllers/WellCompositeController.cs @@ -8,87 +8,85 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + + +/// +/// Композитная скважина +/// +[Route("api/well/{idWell}/composite")] +[ApiController] +[Authorize] +public class WellCompositeController : ControllerBase { + private readonly IWellCompositeRepository wellCompositeRepository; + private readonly IWellService wellService; - /// - /// Композитная скважина - /// - [Route("api/well/{idWell}/composite")] - [ApiController] - [Authorize] - public class WellCompositeController : ControllerBase + public WellCompositeController(IWellCompositeRepository wellCompositeRepository, + IWellService wellService) { - private readonly IWellCompositeRepository wellCompositeRepository; - private readonly IWellService wellService; - - public WellCompositeController(IWellCompositeRepository wellCompositeRepository, - IWellService wellService) - { - this.wellCompositeRepository = wellCompositeRepository; - this.wellService = wellService; - } - - /// - /// Получает композитную скважину для скважины - /// - /// id скважины для которой собрана композитная скважина - /// - /// - [HttpGet] - [Permission] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetAsync(int idWell, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var result = await wellCompositeRepository.GetAsync(idWell, token).ConfigureAwait(false); - return Ok(result); - } - - /// - /// Создает или заменяет композитную скважину для скважины с idWell - /// - /// id скважины для которой собрана композитная скважина - /// Секции композитной скважины - /// - /// - [HttpPost] - [Permission] - public async Task SaveAsync(int idWell, IEnumerable wellComposites, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var result = await wellCompositeRepository.SaveAsync(idWell, wellComposites, token).ConfigureAwait(false); - return Ok(result); - } - - /// - /// Получение РТК по композитной скважине - /// - /// - /// - /// - [HttpGet("compositeProcessMap")] - [Permission] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetCompositeProcessMap(int idWell, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var result = await wellCompositeRepository.GetCompositeProcessMap(idWell, token).ConfigureAwait(false); - return Ok(result); - } - - private async Task CanUserAccessToWellAsync(int idWell, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false); - } + this.wellCompositeRepository = wellCompositeRepository; + this.wellService = wellService; } + /// + /// Получает композитную скважину для скважины + /// + /// id скважины для которой собрана композитная скважина + /// + /// + [HttpGet] + [Permission] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetAsync(int idWell, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); + + var result = await wellCompositeRepository.GetAsync(idWell, token).ConfigureAwait(false); + return Ok(result); + } + + /// + /// Создает или заменяет композитную скважину для скважины с idWell + /// + /// id скважины для которой собрана композитная скважина + /// Секции композитной скважины + /// + /// + [HttpPost] + [Permission] + public async Task SaveAsync(int idWell, IEnumerable wellComposites, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); + + var result = await wellCompositeRepository.SaveAsync(idWell, wellComposites, token).ConfigureAwait(false); + return Ok(result); + } + + /// + /// Получение РТК по композитной скважине + /// + /// + /// + /// + [HttpGet("compositeProcessMap")] + [Permission] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetCompositeProcessMap(int idWell, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); + + var result = await wellCompositeRepository.GetCompositeProcessMap(idWell, token).ConfigureAwait(false); + return Ok(result); + } + + private async Task CanUserAccessToWellAsync(int idWell, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false); + } } diff --git a/AsbCloudWebApi/Controllers/WellCompositeOperationController.cs b/AsbCloudWebApi/Controllers/WellCompositeOperationController.cs index 07272e5d..33a20df9 100644 --- a/AsbCloudWebApi/Controllers/WellCompositeOperationController.cs +++ b/AsbCloudWebApi/Controllers/WellCompositeOperationController.cs @@ -7,46 +7,44 @@ using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Data.WellOperation; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + + +[ApiController] +[Authorize] +[Route("api/[controller]")] +public class WellCompositeOperationController : ControllerBase { + private readonly IWellCompositeOperationService wellCompositeOperationService; + private readonly IWellService wellService; - [ApiController] - [Authorize] - [Route("api/[controller]")] - public class WellCompositeOperationController : ControllerBase + public WellCompositeOperationController(IWellCompositeOperationService wellCompositeOperationService, IWellService wellService) { - private readonly IWellCompositeOperationService wellCompositeOperationService; - private readonly IWellService wellService; - - public WellCompositeOperationController(IWellCompositeOperationService wellCompositeOperationService, IWellService wellService) - { - this.wellCompositeOperationService = wellCompositeOperationService; - this.wellService = wellService; - } - - [HttpGet] - [ProducesResponseType(typeof(WellCompositeOperationDto), (int)System.Net.HttpStatusCode.OK)] - public async Task GetAsync([FromQuery] IEnumerable idsWells, CancellationToken token) - { - foreach (var idWell in idsWells) - if (!await UserHasAccessToWellAsync(idWell, token)) - return Forbid(); - - var result = await wellCompositeOperationService.GetAsync(idsWells, token) - .ConfigureAwait(false); - - return Ok(result); - } - - protected async Task UserHasAccessToWellAsync(int idWell, CancellationToken token) - { - var idCompany = User.GetCompanyId(); - if (idCompany is not null && - await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token) - .ConfigureAwait(false)) - return true; - return false; - } + this.wellCompositeOperationService = wellCompositeOperationService; + this.wellService = wellService; } + [HttpGet] + [ProducesResponseType(typeof(WellCompositeOperationDto), (int)System.Net.HttpStatusCode.OK)] + public async Task GetAsync([FromQuery] IEnumerable idsWells, CancellationToken token) + { + foreach (var idWell in idsWells) + if (!await UserHasAccessToWellAsync(idWell, token)) + return Forbid(); + + var result = await wellCompositeOperationService.GetAsync(idsWells, token) + .ConfigureAwait(false); + + return Ok(result); + } + + protected async Task UserHasAccessToWellAsync(int idWell, CancellationToken token) + { + var idCompany = User.GetCompanyId(); + if (idCompany is not null && + await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token) + .ConfigureAwait(false)) + return true; + return false; + } } diff --git a/AsbCloudWebApi/Controllers/WellContactController.cs b/AsbCloudWebApi/Controllers/WellContactController.cs index 1bd43564..d7769db2 100644 --- a/AsbCloudWebApi/Controllers/WellContactController.cs +++ b/AsbCloudWebApi/Controllers/WellContactController.cs @@ -9,200 +9,199 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// контроллер с контактной информацией по скважине +/// +[Route("api/well/{idWell}/[controller]")] +[ApiController] +[Authorize] +public class WellContactController : ControllerBase { - /// - /// контроллер с контактной информацией по скважине - /// - [Route("api/well/{idWell}/[controller]")] - [ApiController] - [Authorize] - public class WellContactController : ControllerBase + private readonly IWellContactService wellContactsRepository; + private readonly IWellService wellService; + + public WellContactController(IWellContactService wellContactsRepository, IWellService wellService) { - private readonly IWellContactService wellContactsRepository; - private readonly IWellService wellService; + this.wellContactsRepository = wellContactsRepository; + this.wellService = wellService; + } - public WellContactController(IWellContactService wellContactsRepository, IWellService wellService) + /// + /// получение списка типов контактов + /// + /// + /// + [HttpGet("type")] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetTypesAsync(CancellationToken token) + { + var result = await wellContactsRepository.GetTypesAsync(token); + return Ok(result); + } + + /// + /// Получение контактов по типу контакта и ключу скважины + /// + /// ключ скважины + /// тип контакта + /// + /// + [HttpGet("type/{contactTypeId}")] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetByTypeAsync(int idWell, int contactTypeId, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); + + var request = new WellContactRequest() { - this.wellContactsRepository = wellContactsRepository; - this.wellService = wellService; - } + IdsWells = new int[] { idWell }, + ContactTypeId = contactTypeId + }; - /// - /// получение списка типов контактов - /// - /// - /// - [HttpGet("type")] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetTypesAsync(CancellationToken token) - { - var result = await wellContactsRepository.GetTypesAsync(token); - return Ok(result); - } + var result = await wellContactsRepository.GetAllAsync(request, token); + return Ok(result); + } - /// - /// Получение контактов по типу контакта и ключу скважины - /// - /// ключ скважины - /// тип контакта - /// - /// - [HttpGet("type/{contactTypeId}")] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetByTypeAsync(int idWell, int contactTypeId, CancellationToken token) + /// + /// Получение контактов по массиву ключей скважины + /// + /// ключи скважин + /// + /// + [HttpGet("/api/well/[controller]")] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetAllAsync([FromQuery] IEnumerable idsWells, CancellationToken token) + { + foreach(var idWell in idsWells) { if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) return Forbid(); - - var request = new WellContactRequest() - { - IdsWells = new int[] { idWell }, - ContactTypeId = contactTypeId - }; - - var result = await wellContactsRepository.GetAllAsync(request, token); - return Ok(result); } - /// - /// Получение контактов по массиву ключей скважины - /// - /// ключи скважин - /// - /// - [HttpGet("/api/well/[controller]")] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetAllAsync([FromQuery] IEnumerable idsWells, CancellationToken token) + var request = new WellContactRequest() { - foreach(var idWell in idsWells) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - } + IdsWells = idsWells + }; - var request = new WellContactRequest() - { - IdsWells = idsWells - }; + var result = await wellContactsRepository.GetAllAsync(request, token); + return Ok(result); + } - var result = await wellContactsRepository.GetAllAsync(request, token); - return Ok(result); - } + /// + /// Получение контакта по ключу + /// + /// ключ скважины + /// ключ контакта + /// + /// + [HttpGet("{id}")] + [ProducesResponseType(typeof(ContactDto), (int)System.Net.HttpStatusCode.OK)] + public async Task GetAsync(int idWell, int id, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); - /// - /// Получение контакта по ключу - /// - /// ключ скважины - /// ключ контакта - /// - /// - [HttpGet("{id}")] - [ProducesResponseType(typeof(ContactDto), (int)System.Net.HttpStatusCode.OK)] - public async Task GetAsync(int idWell, int id, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); + var result = await wellContactsRepository.GetAsync(idWell, id, token); + return Ok(result); + } - var result = await wellContactsRepository.GetAsync(idWell, id, token); - return Ok(result); - } + /// + /// добавление нового контакта + /// + /// контакт + /// + /// + [HttpPost] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task InsertAsync( + [FromBody] ContactDto contactDto, + CancellationToken token) + { + if (!await CanUserAccessToWellAsync(contactDto.IdWell, token).ConfigureAwait(false)) + return Forbid(); - /// - /// добавление нового контакта - /// - /// контакт - /// - /// - [HttpPost] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task InsertAsync( - [FromBody] ContactDto contactDto, - CancellationToken token) - { - if (!await CanUserAccessToWellAsync(contactDto.IdWell, token).ConfigureAwait(false)) - return Forbid(); + var result = await wellContactsRepository.InsertAsync(contactDto, token); - var result = await wellContactsRepository.InsertAsync(contactDto, token); + return Ok(result); + } - return Ok(result); - } + /// + /// изменение контакта + /// + /// контакт + /// + /// + [HttpPut] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task UpdateAsync( + [FromBody] ContactDto contactDto, + CancellationToken token) + { + if (!await CanUserAccessToWellAsync(contactDto.IdWell, token).ConfigureAwait(false)) + return Forbid(); - /// - /// изменение контакта - /// - /// контакт - /// - /// - [HttpPut] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task UpdateAsync( - [FromBody] ContactDto contactDto, - CancellationToken token) - { - if (!await CanUserAccessToWellAsync(contactDto.IdWell, token).ConfigureAwait(false)) - return Forbid(); + var result = await wellContactsRepository.UpdateAsync(contactDto, token); - var result = await wellContactsRepository.UpdateAsync(contactDto, token); - - return Ok(result); - } + return Ok(result); + } - /// - /// Удаление контакта - /// - /// ключ скважины - /// id контакта - /// Токен отмены задачи - /// Количество удаленных из БД строк - [HttpDelete("{id}")] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task DeleteAsync(int idWell, int id, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); + /// + /// Удаление контакта + /// + /// ключ скважины + /// id контакта + /// Токен отмены задачи + /// Количество удаленных из БД строк + [HttpDelete("{id}")] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task DeleteAsync(int idWell, int id, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); - var result = await wellContactsRepository.DeleteAsync(idWell, id, token); + var result = await wellContactsRepository.DeleteAsync(idWell, id, token); - return Ok(result); - } + return Ok(result); + } - /// - /// Скопировать контакты в другую скважину - /// - /// ключ скважины, откуда копировать контакты - /// ключ скважины, куда копировать контакты - /// - /// - /// - [HttpPost("copy/{idWellTarget}")] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task CopyAsync( - int idWell, - int idWellTarget, - [FromBody] IEnumerable contactIds, - CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); + /// + /// Скопировать контакты в другую скважину + /// + /// ключ скважины, откуда копировать контакты + /// ключ скважины, куда копировать контакты + /// + /// + /// + [HttpPost("copy/{idWellTarget}")] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task CopyAsync( + int idWell, + int idWellTarget, + [FromBody] IEnumerable contactIds, + CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); - if (!await CanUserAccessToWellAsync(idWellTarget, token).ConfigureAwait(false)) - return Forbid(); + if (!await CanUserAccessToWellAsync(idWellTarget, token).ConfigureAwait(false)) + return Forbid(); - var result = await wellContactsRepository.CopyAsync(idWell, idWellTarget, contactIds, token); + var result = await wellContactsRepository.CopyAsync(idWell, idWellTarget, contactIds, token); - return Ok(result); - } + return Ok(result); + } - private async Task CanUserAccessToWellAsync(int idWell, CancellationToken token) - { - int? idCompany = User.GetCompanyId(); - return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token); - } + private async Task CanUserAccessToWellAsync(int idWell, CancellationToken token) + { + int? idCompany = User.GetCompanyId(); + return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token); } } diff --git a/AsbCloudWebApi/Controllers/WellController.cs b/AsbCloudWebApi/Controllers/WellController.cs index 4f00eb98..98e44773 100644 --- a/AsbCloudWebApi/Controllers/WellController.cs +++ b/AsbCloudWebApi/Controllers/WellController.cs @@ -9,145 +9,144 @@ using System.ComponentModel.DataAnnotations; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + +/// +/// Инфо о скважине +/// +[Route("api/well")] +[ApiController] +[Authorize] +public class WellController : ControllerBase { - /// - /// Инфо о скважине - /// - [Route("api/well")] - [ApiController] - [Authorize] - public class WellController : ControllerBase + private readonly IWellService wellService; + + public WellController(IWellService wellService) { - private readonly IWellService wellService; + this.wellService = wellService; + } - public WellController(IWellService wellService) - { - this.wellService = wellService; - } + /// + /// Возвращает список доступных скважин + /// + /// Токен отмены задачи + /// Список скважин + [HttpGet] + [Permission] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetWellsAsync(CancellationToken token) + { + var idCompany = User.GetCompanyId(); - /// - /// Возвращает список доступных скважин - /// - /// Токен отмены задачи - /// Список скважин - [HttpGet] - [Permission] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetWellsAsync(CancellationToken token) - { - var idCompany = User.GetCompanyId(); + if (idCompany is null) + return NoContent(); - if (idCompany is null) - return NoContent(); + var wells = await wellService.GetAsync(new() { IdCompany = idCompany }, + token).ConfigureAwait(false); - var wells = await wellService.GetAsync(new() { IdCompany = idCompany }, - token).ConfigureAwait(false); + return Ok(wells); + } - return Ok(wells); - } + /// + /// Возвращает список доступных скважин + /// + /// Токен отмены задачи + /// Список скважин + [HttpGet("wellTree")] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetWellTreeAsync(CancellationToken token) + { + var idCompany = User.GetCompanyId(); - /// - /// Возвращает список доступных скважин - /// - /// Токен отмены задачи - /// Список скважин - [HttpGet("wellTree")] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetWellTreeAsync(CancellationToken token) - { - var idCompany = User.GetCompanyId(); + if (idCompany is null) + return NoContent(); - if (idCompany is null) - return NoContent(); + var wells = await wellService.GetWellTreeAsync((int)idCompany, + token).ConfigureAwait(false); - var wells = await wellService.GetWellTreeAsync((int)idCompany, - token).ConfigureAwait(false); + return Ok(wells); + } - return Ok(wells); - } + /// + /// Возвращает информацию о требуемой скважине + /// + /// Id требуемой скважины + /// Токен отмены задачи + /// Информация о требуемой скважине + [HttpGet("{idWell}")] + [Permission] + [ProducesResponseType(typeof(WellMapInfoWithTelemetryStat), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType((int)System.Net.HttpStatusCode.NoContent)] + public async Task GetAsync(int idWell, CancellationToken token) + { + var idCompany = User.GetCompanyId(); - /// - /// Возвращает информацию о требуемой скважине - /// - /// Id требуемой скважины - /// Токен отмены задачи - /// Информация о требуемой скважине - [HttpGet("{idWell}")] - [Permission] - [ProducesResponseType(typeof(WellMapInfoWithTelemetryStat), (int)System.Net.HttpStatusCode.OK)] - [ProducesResponseType((int)System.Net.HttpStatusCode.NoContent)] - public async Task GetAsync(int idWell, CancellationToken token) - { - var idCompany = User.GetCompanyId(); + if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync(idCompany ?? default, idWell, token).ConfigureAwait(false)) + return Forbid(); - if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync(idCompany ?? default, idWell, token).ConfigureAwait(false)) - return Forbid(); + var well = await wellService.GetOrDefaultStatAsync(idWell, token); - var well = await wellService.GetOrDefaultStatAsync(idWell, token); + return Ok(well); + } - return Ok(well); - } + /// + /// Редактирует указанные поля скважины + /// + /// Объект параметров скважины. + /// IdWellType: 1 - Наклонно-направленная, 2 - Горизонтальная. + /// State: 0 - Неизвестно, 1 - В работе, 2 - Завершена. + /// Токен отмены задачи + /// + [HttpPut] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task UpdateWellAsync(WellDto dto, + CancellationToken token) + { + var idCompany = User.GetCompanyId(); - /// - /// Редактирует указанные поля скважины - /// - /// Объект параметров скважины. - /// IdWellType: 1 - Наклонно-направленная, 2 - Горизонтальная. - /// State: 0 - Неизвестно, 1 - В работе, 2 - Завершена. - /// Токен отмены задачи - /// - [HttpPut] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task UpdateWellAsync(WellDto dto, - CancellationToken token) - { - var idCompany = User.GetCompanyId(); + if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + dto.Id, token).ConfigureAwait(false)) + return Forbid(); - if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - dto.Id, token).ConfigureAwait(false)) - return Forbid(); + var result = await wellService.UpdateAsync(dto, token) + .ConfigureAwait(false); - var result = await wellService.UpdateAsync(dto, token) - .ConfigureAwait(false); + return Ok(result); - return Ok(result); + } - } + /// + /// Обновляет статус скважины + /// + /// ключ скважины + /// статус: 0 - Неизвестно, 1 - В работе, 2 - Завершена. + /// + /// + [HttpPut("{idWell}/state")] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task UpdateWellStateAsync(int idWell, + [Range(0, 2, ErrorMessage = "Статус некорректен")] int idState, + CancellationToken token) + { + var idCompany = User.GetCompanyId(); - /// - /// Обновляет статус скважины - /// - /// ключ скважины - /// статус: 0 - Неизвестно, 1 - В работе, 2 - Завершена. - /// - /// - [HttpPut("{idWell}/state")] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task UpdateWellStateAsync(int idWell, - [Range(0, 2, ErrorMessage = "Статус некорректен")] int idState, - CancellationToken token) - { - var idCompany = User.GetCompanyId(); + if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false)) + return Forbid(); - if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) - return Forbid(); + var dto = await wellService.GetOrDefaultAsync(idWell, token); + + if (dto is null) + return this.ValidationBadRequest(nameof(idWell), $"Скважина с id: {idWell} недоступна"); - var dto = await wellService.GetOrDefaultAsync(idWell, token); - - if (dto is null) - return this.ValidationBadRequest(nameof(idWell), $"Скважина с id: {idWell} недоступна"); + dto.IdState = idState; - dto.IdState = idState; + var result = await wellService.UpdateAsync(dto, token) + .ConfigureAwait(false); - var result = await wellService.UpdateAsync(dto, token) - .ConfigureAwait(false); + return Ok(result); - return Ok(result); - - } } } diff --git a/AsbCloudWebApi/Controllers/WellFinalDocumentsController.cs b/AsbCloudWebApi/Controllers/WellFinalDocumentsController.cs index 1d16f564..62a83c0d 100644 --- a/AsbCloudWebApi/Controllers/WellFinalDocumentsController.cs +++ b/AsbCloudWebApi/Controllers/WellFinalDocumentsController.cs @@ -10,170 +10,168 @@ using System.ComponentModel.DataAnnotations; using AsbCloudApp.Repositories; using AsbCloudApp.Data.User; -namespace AsbCloudWebApi.Controllers +namespace AsbCloudWebApi.Controllers; + + +/// +/// Дело скважины +/// +[Route("api/[controller]")] +[ApiController] +[Authorize] +public class WellFinalDocumentsController : ControllerBase { + private readonly IWellFinalDocumentsService wellFinalDocumentsService; + private readonly IWellService wellService; + private readonly IFileCategoryService fileCategoryService; + private readonly IWellFinalDocumentsRepository wellFinalDocumentsRepository; - /// - /// Дело скважины - /// - [Route("api/[controller]")] - [ApiController] - [Authorize] - public class WellFinalDocumentsController : ControllerBase + public WellFinalDocumentsController( + IWellFinalDocumentsService wellFinalDocumentsService, + IWellService wellService, + IFileCategoryService fileCategoryService, + IWellFinalDocumentsRepository wellFinalDocumentsRepository) { - private readonly IWellFinalDocumentsService wellFinalDocumentsService; - private readonly IWellService wellService; - private readonly IFileCategoryService fileCategoryService; - private readonly IWellFinalDocumentsRepository wellFinalDocumentsRepository; - - public WellFinalDocumentsController( - IWellFinalDocumentsService wellFinalDocumentsService, - IWellService wellService, - IFileCategoryService fileCategoryService, - IWellFinalDocumentsRepository wellFinalDocumentsRepository) - { - this.wellFinalDocumentsService = wellFinalDocumentsService; - this.wellService = wellService; - this.fileCategoryService = fileCategoryService; - this.wellFinalDocumentsRepository = wellFinalDocumentsRepository; - } - - /// - /// Получение всех записей - /// - /// - /// - /// - [HttpGet("{idWell}")] - [Permission] - [ProducesResponseType(typeof(WellCaseDto), (int)System.Net.HttpStatusCode.OK)] - public async Task GetAsync(int idWell, CancellationToken token) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var idUser = User!.GetUserId()!; - var data = await wellFinalDocumentsRepository.GetByWellIdAsync(idWell, idUser.Value, token); - return Ok(data); - } - - /// - /// Получение списка ответственных - /// - /// - /// - /// - [HttpGet("{idWell}/availableUsers")] - [Permission] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] - public async Task GetAvailableUsersAsync(int idWell, CancellationToken token ) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var data = await wellFinalDocumentsRepository.GetAvailableUsersAsync(idWell, token); - return Ok(data); - } - - /// - /// Обновление всех записей по скважине - /// - /// - /// - /// - /// - [HttpPut("{idWell}")] - [Permission("WellFinalDocuments.editPublisher")] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task UpdateRangeAsync(int idWell, [Required] IEnumerable dtos, CancellationToken token ) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - var data = await wellFinalDocumentsService.UpdateRangeAsync(idWell, dtos, token); - return Ok(data); - } - - /// - /// Повторно оповестить ответственных за загрузку - /// - /// - /// - /// - /// количество оповещенных публикаторов - [HttpPut("{idWell}/reNotifyPublishers")] - [Permission("WellFinalDocuments.editPublisher")] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task ReNotifyPublishersAsync(int idWell, [Required] int idCategory, CancellationToken token ) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var idUser = User!.GetUserId()!; - var data = await wellFinalDocumentsService.ReNotifyPublishersAsync(idWell, idUser.Value, idCategory, token); - return Ok(data); - } - - /// - /// Получение истории файлов - /// - /// - /// - /// - /// - [HttpGet("{idWell}/history")] - [Permission] - [ProducesResponseType(typeof(WellFinalDocumentsHistoryDto), (int)System.Net.HttpStatusCode.OK)] - public async Task GetFilesHistoryByIdCategoryAsync(int idWell, - [Required] int idCategory, - CancellationToken token ) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var data = await this.wellFinalDocumentsService.GetFilesHistoryByIdCategoryAsync(idWell, idCategory, token); - return Ok(data); - } - - /// - /// Сохранение файла - /// - /// - /// - /// - /// - /// - [HttpPost("{idWell}")] - [Permission] - [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task SaveCategoryFileAsync(int idWell, [Required] int idCategory, [Required] IFormFile file, CancellationToken token ) - { - if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) - return Forbid(); - - var idUser = User!.GetUserId()!; - var fileStream = file.OpenReadStream(); - var data = await this.wellFinalDocumentsService.SaveCategoryFileAsync(idWell, idCategory, idUser.Value, fileStream, file.FileName, token); - return Ok(data); - } - - /// - /// Получение справочника категорий файлов - /// - /// - [HttpGet("wellCaseCategories")] - [Permission] - public async Task GetWellCaseCategoriesAsync(CancellationToken token) - { - var data = await fileCategoryService.GetWellCaseCategoriesAsync(token); - return Ok(data); - } - - private async Task CanUserAccessToWellAsync(int idWell, CancellationToken token ) - { - int? idCompany = User.GetCompanyId(); - return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false); - } + this.wellFinalDocumentsService = wellFinalDocumentsService; + this.wellService = wellService; + this.fileCategoryService = fileCategoryService; + this.wellFinalDocumentsRepository = wellFinalDocumentsRepository; } + /// + /// Получение всех записей + /// + /// + /// + /// + [HttpGet("{idWell}")] + [Permission] + [ProducesResponseType(typeof(WellCaseDto), (int)System.Net.HttpStatusCode.OK)] + public async Task GetAsync(int idWell, CancellationToken token) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); + + var idUser = User!.GetUserId()!; + var data = await wellFinalDocumentsRepository.GetByWellIdAsync(idWell, idUser.Value, token); + return Ok(data); + } + + /// + /// Получение списка ответственных + /// + /// + /// + /// + [HttpGet("{idWell}/availableUsers")] + [Permission] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetAvailableUsersAsync(int idWell, CancellationToken token ) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); + + var data = await wellFinalDocumentsRepository.GetAvailableUsersAsync(idWell, token); + return Ok(data); + } + + /// + /// Обновление всех записей по скважине + /// + /// + /// + /// + /// + [HttpPut("{idWell}")] + [Permission("WellFinalDocuments.editPublisher")] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task UpdateRangeAsync(int idWell, [Required] IEnumerable dtos, CancellationToken token ) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); + var data = await wellFinalDocumentsService.UpdateRangeAsync(idWell, dtos, token); + return Ok(data); + } + + /// + /// Повторно оповестить ответственных за загрузку + /// + /// + /// + /// + /// количество оповещенных публикаторов + [HttpPut("{idWell}/reNotifyPublishers")] + [Permission("WellFinalDocuments.editPublisher")] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task ReNotifyPublishersAsync(int idWell, [Required] int idCategory, CancellationToken token ) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); + + var idUser = User!.GetUserId()!; + var data = await wellFinalDocumentsService.ReNotifyPublishersAsync(idWell, idUser.Value, idCategory, token); + return Ok(data); + } + + /// + /// Получение истории файлов + /// + /// + /// + /// + /// + [HttpGet("{idWell}/history")] + [Permission] + [ProducesResponseType(typeof(WellFinalDocumentsHistoryDto), (int)System.Net.HttpStatusCode.OK)] + public async Task GetFilesHistoryByIdCategoryAsync(int idWell, + [Required] int idCategory, + CancellationToken token ) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); + + var data = await this.wellFinalDocumentsService.GetFilesHistoryByIdCategoryAsync(idWell, idCategory, token); + return Ok(data); + } + + /// + /// Сохранение файла + /// + /// + /// + /// + /// + /// + [HttpPost("{idWell}")] + [Permission] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task SaveCategoryFileAsync(int idWell, [Required] int idCategory, [Required] IFormFile file, CancellationToken token ) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); + + var idUser = User!.GetUserId()!; + var fileStream = file.OpenReadStream(); + var data = await this.wellFinalDocumentsService.SaveCategoryFileAsync(idWell, idCategory, idUser.Value, fileStream, file.FileName, token); + return Ok(data); + } + + /// + /// Получение справочника категорий файлов + /// + /// + [HttpGet("wellCaseCategories")] + [Permission] + public async Task GetWellCaseCategoriesAsync(CancellationToken token) + { + var data = await fileCategoryService.GetWellCaseCategoriesAsync(token); + return Ok(data); + } + + private async Task CanUserAccessToWellAsync(int idWell, CancellationToken token ) + { + int? idCompany = User.GetCompanyId(); + return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false); + } } diff --git a/AsbCloudWebApi/Conventions/ApiExplorerGroupPerVersionConvention.cs b/AsbCloudWebApi/Conventions/ApiExplorerGroupPerVersionConvention.cs index db3de7d8..bd247c38 100644 --- a/AsbCloudWebApi/Conventions/ApiExplorerGroupPerVersionConvention.cs +++ b/AsbCloudWebApi/Conventions/ApiExplorerGroupPerVersionConvention.cs @@ -1,13 +1,12 @@ using Microsoft.AspNetCore.Mvc.ApplicationModels; using System.Linq; -namespace AsbCloudWebApi.Conventions +namespace AsbCloudWebApi.Conventions; + +public class ApiExplorerGroupPerVersionConvention : IControllerModelConvention { - public class ApiExplorerGroupPerVersionConvention : IControllerModelConvention + public void Apply(ControllerModel controller) { - public void Apply(ControllerModel controller) - { - controller.ApiExplorer.GroupName = "v1"; - } + controller.ApiExplorer.GroupName = "v1"; } } \ No newline at end of file diff --git a/AsbCloudWebApi/Converters/DateOnlyJsonConverter.cs b/AsbCloudWebApi/Converters/DateOnlyJsonConverter.cs index c2b0282b..5f5a1da2 100644 --- a/AsbCloudWebApi/Converters/DateOnlyJsonConverter.cs +++ b/AsbCloudWebApi/Converters/DateOnlyJsonConverter.cs @@ -2,21 +2,19 @@ using System; using System.Text.Json; using System.Text.Json.Serialization; -namespace AsbCloudWebApi.Converters +namespace AsbCloudWebApi.Converters; + + +public class DateOnlyJsonConverter : JsonConverter { - - public class DateOnlyJsonConverter : JsonConverter + public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return DateOnly.FromDateTime(reader.GetDateTime()); - } - - public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options) - { - var isoDate = value.ToString("O"); - writer.WriteStringValue(isoDate); - } + return DateOnly.FromDateTime(reader.GetDateTime()); } + public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options) + { + var isoDate = value.ToString("O"); + writer.WriteStringValue(isoDate); + } } diff --git a/AsbCloudWebApi/Converters/DateOnlyTypeConverter.cs b/AsbCloudWebApi/Converters/DateOnlyTypeConverter.cs index 03f4b552..9c3c9712 100644 --- a/AsbCloudWebApi/Converters/DateOnlyTypeConverter.cs +++ b/AsbCloudWebApi/Converters/DateOnlyTypeConverter.cs @@ -4,48 +4,46 @@ using System.Globalization; using System.Text.Json; using System.Text.Json.Serialization; -namespace AsbCloudWebApi.Converters +namespace AsbCloudWebApi.Converters; + + +public class DateOnlyTypeConverter : TypeConverter { - - public class DateOnlyTypeConverter : TypeConverter + public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) { - public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) + if (sourceType == typeof(string)) { - if (sourceType == typeof(string)) - { - return true; - } - return base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) - { - if (value is string 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); - } - - public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType) - { - if (destinationType == typeof(string)) - { - return true; - } - return base.CanConvertTo(context, destinationType); - } - public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType) - { - if (destinationType == typeof(string) && value is DateOnly date) - { - return date.ToString("O"); - } - return base.ConvertTo(context, culture, value, destinationType); + return true; } + return base.CanConvertFrom(context, sourceType); } + public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) + { + if (value is string 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); + } + + public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType) + { + if (destinationType == typeof(string)) + { + return true; + } + return base.CanConvertTo(context, destinationType); + } + public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType) + { + if (destinationType == typeof(string) && value is DateOnly date) + { + return date.ToString("O"); + } + return base.ConvertTo(context, culture, value, destinationType); + } } diff --git a/AsbCloudWebApi/Converters/JsonValueJsonConverter.cs b/AsbCloudWebApi/Converters/JsonValueJsonConverter.cs index 6ff6c52b..096c5946 100644 --- a/AsbCloudWebApi/Converters/JsonValueJsonConverter.cs +++ b/AsbCloudWebApi/Converters/JsonValueJsonConverter.cs @@ -4,71 +4,70 @@ using System.Text.Json.Serialization; using System.Text.Json; using AsbCloudApp.Data.GTR; -namespace AsbCloudWebApi.Converters +namespace AsbCloudWebApi.Converters; + +public class JsonValueJsonConverter : JsonConverter { - public class JsonValueJsonConverter : JsonConverter + public override JsonValue Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - public override JsonValue Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + if (reader.TokenType == JsonTokenType.String) { - if (reader.TokenType == JsonTokenType.String) - { - var stringVal = reader.GetString() ?? string.Empty; - return new JsonValue(stringVal); - } - - if (reader.TokenType == JsonTokenType.Number) - { - if (reader.TryGetInt32(out int intVal)) - return new JsonValue(intVal); - - if (reader.TryGetDouble(out double doubleVal)) - return new JsonValue((float)doubleVal); - } - - throw new FormatException($"Wrong format at position {reader.Position}"); + var stringVal = reader.GetString() ?? string.Empty; + return new JsonValue(stringVal); } - public override void Write(Utf8JsonWriter writer, JsonValue value, JsonSerializerOptions options) + if (reader.TokenType == JsonTokenType.Number) { - if (value.Value is string strValue) - { - writer.WriteStringValue(FormatString(strValue)); - return; - } + if (reader.TryGetInt32(out int intVal)) + return new JsonValue(intVal); - if (value.Value is int intValue) - { - writer.WriteNumberValue(intValue); - return; - } - - if (value.Value is short shortValue) - { - writer.WriteNumberValue(shortValue); - return; - } - - if (value.Value is float floatValue) - { - writer.WriteRawValue(floatValue.ToString("#0.0##", CultureInfo.InvariantCulture), true); - return; - } - - if (value.Value is double doubleValue) - { - writer.WriteRawValue(doubleValue.ToString("#0.0##", CultureInfo.InvariantCulture), true); - return; - } - - var typeName = value.Value.GetType().Name; - throw new NotImplementedException($"{typeName} is not supported type for WITS value"); + if (reader.TryGetDouble(out double doubleVal)) + return new JsonValue((float)doubleVal); } - private static string FormatString(string value) - => value - .Replace("\"", "") - .Trim() - .Replace("\r", "") - .Replace("\n", ""); + throw new FormatException($"Wrong format at position {reader.Position}"); } + + public override void Write(Utf8JsonWriter writer, JsonValue value, JsonSerializerOptions options) + { + if (value.Value is string strValue) + { + writer.WriteStringValue(FormatString(strValue)); + return; + } + + if (value.Value is int intValue) + { + writer.WriteNumberValue(intValue); + return; + } + + if (value.Value is short shortValue) + { + writer.WriteNumberValue(shortValue); + return; + } + + if (value.Value is float floatValue) + { + writer.WriteRawValue(floatValue.ToString("#0.0##", CultureInfo.InvariantCulture), true); + return; + } + + if (value.Value is double doubleValue) + { + writer.WriteRawValue(doubleValue.ToString("#0.0##", CultureInfo.InvariantCulture), true); + return; + } + + var typeName = value.Value.GetType().Name; + throw new NotImplementedException($"{typeName} is not supported type for WITS value"); + } + + private static string FormatString(string value) + => value + .Replace("\"", "") + .Trim() + .Replace("\r", "") + .Replace("\n", ""); } diff --git a/AsbCloudWebApi/Converters/TimeOnlyTypeConverter.cs b/AsbCloudWebApi/Converters/TimeOnlyTypeConverter.cs index e59b4e2c..a7177bfa 100644 --- a/AsbCloudWebApi/Converters/TimeOnlyTypeConverter.cs +++ b/AsbCloudWebApi/Converters/TimeOnlyTypeConverter.cs @@ -2,45 +2,43 @@ using System; using System.ComponentModel; using System.Globalization; -namespace AsbCloudWebApi.Converters +namespace AsbCloudWebApi.Converters; + + +public class TimeOnlyTypeConverter : TypeConverter { - - public class TimeOnlyTypeConverter : TypeConverter + public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) { - public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) + if (sourceType == typeof(string)) { - if (sourceType == typeof(string)) - { - return true; - } - return base.CanConvertFrom(context, sourceType); - } - - public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) - { - if (value is string str) - { - return TimeOnly.Parse(str); - } - return base.ConvertFrom(context, culture, value); - } - - public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType) - { - if (destinationType == typeof(string)) - { - return true; - } - return base.CanConvertTo(context, destinationType); - } - public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType) - { - if (destinationType == typeof(string) && value is TimeOnly date) - { - return date.ToString("O"); - } - return base.ConvertTo(context, culture, value, destinationType); + return true; } + return base.CanConvertFrom(context, sourceType); } + public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) + { + if (value is string str) + { + return TimeOnly.Parse(str); + } + return base.ConvertFrom(context, culture, value); + } + + public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType) + { + if (destinationType == typeof(string)) + { + return true; + } + return base.CanConvertTo(context, destinationType); + } + public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType) + { + if (destinationType == typeof(string) && value is TimeOnly date) + { + return date.ToString("O"); + } + return base.ConvertTo(context, culture, value, destinationType); + } } diff --git a/AsbCloudWebApi/DependencyInjection.cs b/AsbCloudWebApi/DependencyInjection.cs index 8266ad6e..88f92545 100644 --- a/AsbCloudWebApi/DependencyInjection.cs +++ b/AsbCloudWebApi/DependencyInjection.cs @@ -20,143 +20,142 @@ using System.IO; using System.Reflection; using System.Threading.Tasks; -namespace AsbCloudWebApi +namespace AsbCloudWebApi; + +public static class DependencyInjection { - public static class DependencyInjection + public static void AddSwagger(this IServiceCollection services) { - public static void AddSwagger(this IServiceCollection services) + services.AddSwaggerGen(c => { - services.AddSwaggerGen(c => + c.MapType(() => new OpenApiSchema { Type = "string", Example = new OpenApiString("0.00:00:00") }); + c.MapType(() => new OpenApiSchema { Type = "string", Format = "date" }); + c.MapType(() => new OpenApiSchema { - c.MapType(() => new OpenApiSchema { Type = "string", Example = new OpenApiString("0.00:00:00") }); - c.MapType(() => new OpenApiSchema { Type = "string", Format = "date" }); - c.MapType(() => new OpenApiSchema + AnyOf = new OpenApiSchema[] { - AnyOf = new OpenApiSchema[] - { - new OpenApiSchema {Type = "string", Format = "string" }, - new OpenApiSchema {Type = "number", Format = "int32" }, - new OpenApiSchema {Type = "number", Format = "float" }, - } - }); - - c.CustomOperationIds(e => - { - return $"{e.ActionDescriptor.RouteValues["action"]}"; - }); - - c.SwaggerDoc("v1", new OpenApiInfo { Title = "ASB cloud web api", Version = "v1" }); - c.SwaggerDoc("signalr", new OpenApiInfo { Title = "SignalR client methods", Version = "signalr" }); - c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme - { - Description = @"JWT Authorization header using the Bearer scheme. Enter 'Bearer' [space] and then your token in the text input below. Example: 'Bearer 12345abcdef'", - Name = "Authorization", - In = ParameterLocation.Header, - Type = SecuritySchemeType.ApiKey, - Scheme = "Bearer", - }); - - c.AddSecurityRequirement(new OpenApiSecurityRequirement() - { - { - new OpenApiSecurityScheme - { - Reference = new OpenApiReference - { - Type = ReferenceType.SecurityScheme, - Id = "Bearer" - }, - Scheme = "oauth2", - Name = "Bearer", - In = ParameterLocation.Header, - }, - new List() - } - }); - - var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; - var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); - var includeControllerXmlComment = true; - c.IncludeXmlComments(xmlPath, includeControllerXmlComment); - c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "AsbCloudApp.xml"), includeControllerXmlComment); - - c.AddSignalRSwaggerGen(options => - { - options.DisplayInDocument("signalr"); - options.UseHubXmlCommentsSummaryAsTagDescription = true; - options.UseHubXmlCommentsSummaryAsTag = true; - options.UseXmlComments(xmlPath); - }); + new OpenApiSchema {Type = "string", Format = "string" }, + new OpenApiSchema {Type = "number", Format = "int32" }, + new OpenApiSchema {Type = "number", Format = "float" }, + } }); - } - public static void AddJWTAuthentication(this IServiceCollection services) - { - services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) - .AddJwtBearer(options => + c.CustomOperationIds(e => + { + return $"{e.ActionDescriptor.RouteValues["action"]}"; + }); + + c.SwaggerDoc("v1", new OpenApiInfo { Title = "ASB cloud web api", Version = "v1" }); + c.SwaggerDoc("signalr", new OpenApiInfo { Title = "SignalR client methods", Version = "signalr" }); + c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme + { + Description = @"JWT Authorization header using the Bearer scheme. Enter 'Bearer' [space] and then your token in the text input below. Example: 'Bearer 12345abcdef'", + Name = "Authorization", + In = ParameterLocation.Header, + Type = SecuritySchemeType.ApiKey, + Scheme = "Bearer", + }); + + c.AddSecurityRequirement(new OpenApiSecurityRequirement() + { { - options.RequireHttpsMetadata = false; - options.TokenValidationParameters = new TokenValidationParameters + new OpenApiSecurityScheme { - ValidateIssuer = true, - ValidIssuer = AuthService.issuer, - ValidateAudience = true, - ValidAudience = AuthService.audience, - ValidateLifetime = true, - IssuerSigningKey = AuthService.securityKey, - ValidateIssuerSigningKey = true, - }; - - options.Events = new JwtBearerEvents - { - OnMessageReceived = context => + Reference = new OpenApiReference { - var accessToken = context.Request.Query["access_token"]; - - var path = context.HttpContext.Request.Path; - if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/hubs")) - { - context.Token = accessToken; - } - - return Task.CompletedTask; + Type = ReferenceType.SecurityScheme, + Id = "Bearer" }, - OnTokenValidated = context => + Scheme = "oauth2", + Name = "Bearer", + In = ParameterLocation.Header, + }, + new List() + } + }); + + var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; + var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); + var includeControllerXmlComment = true; + c.IncludeXmlComments(xmlPath, includeControllerXmlComment); + c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "AsbCloudApp.xml"), includeControllerXmlComment); + + c.AddSignalRSwaggerGen(options => + { + options.DisplayInDocument("signalr"); + options.UseHubXmlCommentsSummaryAsTagDescription = true; + options.UseHubXmlCommentsSummaryAsTag = true; + options.UseXmlComments(xmlPath); + }); + }); + } + + public static void AddJWTAuthentication(this IServiceCollection services) + { + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(options => + { + options.RequireHttpsMetadata = false; + options.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuer = true, + ValidIssuer = AuthService.issuer, + ValidateAudience = true, + ValidAudience = AuthService.audience, + ValidateLifetime = true, + IssuerSigningKey = AuthService.securityKey, + ValidateIssuerSigningKey = true, + }; + + options.Events = new JwtBearerEvents + { + OnMessageReceived = context => + { + var accessToken = context.Request.Query["access_token"]; + + var path = context.HttpContext.Request.Path; + if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/hubs")) { - var idUser = context.Principal?.GetUserId(); - if (idUser is null) - { - context.Fail("idUser is null"); - return Task.CompletedTask; - } - - var userService = context.HttpContext.RequestServices.GetRequiredService(); - var user = userService.GetOrDefault(idUser.Value); - - if (user is null) - { - context.Fail("user is null"); - } - else if (user.IdState != User.ActiveStateId) - { - context.Fail("user is not active"); - } + context.Token = accessToken; + } + return Task.CompletedTask; + }, + OnTokenValidated = context => + { + var idUser = context.Principal?.GetUserId(); + if (idUser is null) + { + context.Fail("idUser is null"); return Task.CompletedTask; } - }; - }); - } - public static void AddNotificationTransportServices(this IServiceCollection services) - { - services.AddTransient(); - services.AddTransient(); + var userService = context.HttpContext.RequestServices.GetRequiredService(); + var user = userService.GetOrDefault(idUser.Value); - services.AddTransient(); - } + if (user is null) + { + context.Fail("user is null"); + } + else if (user.IdState != User.ActiveStateId) + { + context.Fail("user is not active"); + } - public static void AddIntegrationEvents(this IServiceCollection services) => services - .AddTransient, WellInfoHub>(); + return Task.CompletedTask; + } + }; + }); } + + public static void AddNotificationTransportServices(this IServiceCollection services) + { + services.AddTransient(); + services.AddTransient(); + + services.AddTransient(); + } + + public static void AddIntegrationEvents(this IServiceCollection services) => services + .AddTransient, WellInfoHub>(); } diff --git a/AsbCloudWebApi/Middlewares/PermissionsMiddlware.cs b/AsbCloudWebApi/Middlewares/PermissionsMiddlware.cs index 3c4eb9d7..fa3d908f 100644 --- a/AsbCloudWebApi/Middlewares/PermissionsMiddlware.cs +++ b/AsbCloudWebApi/Middlewares/PermissionsMiddlware.cs @@ -8,77 +8,75 @@ using Microsoft.Extensions.DependencyInjection; using System; using System.Threading.Tasks; -namespace AsbCloudWebApi.Middlewares +namespace AsbCloudWebApi.Middlewares; + + +public class PermissionsMiddlware { + private readonly RequestDelegate next; + private readonly UserConnectionsLimitMiddlware userConnectionsLimitMiddlware; - public class PermissionsMiddlware + public PermissionsMiddlware(RequestDelegate next, IConfiguration configuration) { - private readonly RequestDelegate next; - private readonly UserConnectionsLimitMiddlware userConnectionsLimitMiddlware; - - public PermissionsMiddlware(RequestDelegate next, IConfiguration configuration) - { - this.next = next; - userConnectionsLimitMiddlware = new UserConnectionsLimitMiddlware(next, configuration); - } - - public async Task InvokeAsync(HttpContext context) - { - var endpoint = context.GetEndpoint(); - var permission = endpoint?.Metadata.GetMetadata(); - if (permission is null) - { - await next(context); - return; - } - - var idUser = context.User.GetUserId(); - if (idUser is null) - { - await context.ForbidAsync(); - return; - } - - var controllerName = endpoint!.Metadata - .GetMetadata() - ?.ControllerName; - - bool isAuthorized; - if (idUser == 1) - isAuthorized = true; - else - { - var permissionName = permission.Name; - if (string.IsNullOrEmpty(permissionName)) - { - var httpMethod = endpoint.Metadata - .GetMetadata() - ?.HttpMethods[0] - .ToLower(); - - permissionName = httpMethod switch - { - "get" or "delete" => $"{controllerName}.{httpMethod}", - "post" or "put" or "patch" => $"{controllerName}.edit", - _ => throw new NotImplementedException(), - }; - PermissionAttribute.Registered.Add(permissionName); - } - else if (permissionName.Contains("[controller]")) - { - permissionName = permissionName.Replace("[controller]", controllerName); - PermissionAttribute.Registered.Add(permissionName); - } - - var userService = context.RequestServices.GetRequiredService(); - isAuthorized = userService.HasPermission(idUser.Value, permissionName); - } - - if (isAuthorized) - await userConnectionsLimitMiddlware.InvokeAsync(context, idUser!.Value, controllerName!); - else - await context.ForbidAsync(); - } + this.next = next; + userConnectionsLimitMiddlware = new UserConnectionsLimitMiddlware(next, configuration); } + public async Task InvokeAsync(HttpContext context) + { + var endpoint = context.GetEndpoint(); + var permission = endpoint?.Metadata.GetMetadata(); + if (permission is null) + { + await next(context); + return; + } + + var idUser = context.User.GetUserId(); + if (idUser is null) + { + await context.ForbidAsync(); + return; + } + + var controllerName = endpoint!.Metadata + .GetMetadata() + ?.ControllerName; + + bool isAuthorized; + if (idUser == 1) + isAuthorized = true; + else + { + var permissionName = permission.Name; + if (string.IsNullOrEmpty(permissionName)) + { + var httpMethod = endpoint.Metadata + .GetMetadata() + ?.HttpMethods[0] + .ToLower(); + + permissionName = httpMethod switch + { + "get" or "delete" => $"{controllerName}.{httpMethod}", + "post" or "put" or "patch" => $"{controllerName}.edit", + _ => throw new NotImplementedException(), + }; + PermissionAttribute.Registered.Add(permissionName); + } + else if (permissionName.Contains("[controller]")) + { + permissionName = permissionName.Replace("[controller]", controllerName); + PermissionAttribute.Registered.Add(permissionName); + } + + var userService = context.RequestServices.GetRequiredService(); + isAuthorized = userService.HasPermission(idUser.Value, permissionName); + } + + if (isAuthorized) + await userConnectionsLimitMiddlware.InvokeAsync(context, idUser!.Value, controllerName!); + else + await context.ForbidAsync(); + } } diff --git a/AsbCloudWebApi/Middlewares/RequerstTrackerMiddleware.cs b/AsbCloudWebApi/Middlewares/RequerstTrackerMiddleware.cs index 62c3ff56..b4e757e0 100644 --- a/AsbCloudWebApi/Middlewares/RequerstTrackerMiddleware.cs +++ b/AsbCloudWebApi/Middlewares/RequerstTrackerMiddleware.cs @@ -3,54 +3,52 @@ using Microsoft.Extensions.DependencyInjection; using System.Linq; using System.Threading.Tasks; -namespace AsbCloudWebApi.Middlewares +namespace AsbCloudWebApi.Middlewares; + + +public class RequerstTrackerMiddleware { + private readonly RequestDelegate next; - public class RequerstTrackerMiddleware + public RequerstTrackerMiddleware(RequestDelegate next) { - private readonly RequestDelegate next; - - public RequerstTrackerMiddleware(RequestDelegate next) - { - this.next = next; - } - - public async Task InvokeAsync(HttpContext context) - { - var service = context.RequestServices.GetRequiredService(); - var clientIp = context.Request.Headers["X-Real-IP"].FirstOrDefault(); - var requestLog = new AsbCloudApp.Data.RequestLogDto - { - UserLogin = context.User.Identity?.Name ?? string.Empty, - UserIp = clientIp ?? context.Connection?.RemoteIpAddress?.ToString(), - RequestMethod = context.Request.Method, - RequestPath = context.Request.Path.Value, - RequestContentLength = context.Request.ContentLength, - Referer = context.Request.Headers["Referer"].ToString(), - }; - { - var userIdString = context.User?.FindFirst("id")?.Value; - if (!string.IsNullOrEmpty(userIdString) && int.TryParse(userIdString, out int userId)) - requestLog.UserId = userId; - } - var sw = System.Diagnostics.Stopwatch.StartNew(); - try - { - await next.Invoke(context); - sw.Stop(); - requestLog.ElapsedMilliseconds = sw.ElapsedMilliseconds; - requestLog.Status = context.Response.StatusCode; - service.RegisterRequest(requestLog); - } - catch (System.Exception ex) - { - sw.Stop(); - requestLog.ElapsedMilliseconds = sw.ElapsedMilliseconds; - requestLog.Status = context.Response.StatusCode; - service.RegisterRequestError(requestLog, ex); - throw; - } - } + this.next = next; } + public async Task InvokeAsync(HttpContext context) + { + var service = context.RequestServices.GetRequiredService(); + var clientIp = context.Request.Headers["X-Real-IP"].FirstOrDefault(); + var requestLog = new AsbCloudApp.Data.RequestLogDto + { + UserLogin = context.User.Identity?.Name ?? string.Empty, + UserIp = clientIp ?? context.Connection?.RemoteIpAddress?.ToString(), + RequestMethod = context.Request.Method, + RequestPath = context.Request.Path.Value, + RequestContentLength = context.Request.ContentLength, + Referer = context.Request.Headers["Referer"].ToString(), + }; + { + var userIdString = context.User?.FindFirst("id")?.Value; + if (!string.IsNullOrEmpty(userIdString) && int.TryParse(userIdString, out int userId)) + requestLog.UserId = userId; + } + var sw = System.Diagnostics.Stopwatch.StartNew(); + try + { + await next.Invoke(context); + sw.Stop(); + requestLog.ElapsedMilliseconds = sw.ElapsedMilliseconds; + requestLog.Status = context.Response.StatusCode; + service.RegisterRequest(requestLog); + } + catch (System.Exception ex) + { + sw.Stop(); + requestLog.ElapsedMilliseconds = sw.ElapsedMilliseconds; + requestLog.Status = context.Response.StatusCode; + service.RegisterRequestError(requestLog, ex); + throw; + } + } } diff --git a/AsbCloudWebApi/Middlewares/SimplifyExceptionsMiddleware.cs b/AsbCloudWebApi/Middlewares/SimplifyExceptionsMiddleware.cs index 20c995b3..ef742133 100644 --- a/AsbCloudWebApi/Middlewares/SimplifyExceptionsMiddleware.cs +++ b/AsbCloudWebApi/Middlewares/SimplifyExceptionsMiddleware.cs @@ -6,62 +6,61 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -namespace AsbCloudWebApi.Middlewares +namespace AsbCloudWebApi.Middlewares; + +public class SimplifyExceptionsMiddleware { - public class SimplifyExceptionsMiddleware + private readonly RequestDelegate next; + + public SimplifyExceptionsMiddleware(RequestDelegate next) { - private readonly RequestDelegate next; + this.next = next; + } - public SimplifyExceptionsMiddleware(RequestDelegate next) + public async Task InvokeAsync(HttpContext context) + { + try { - this.next = next; + await next.Invoke(context); } - - public async Task InvokeAsync(HttpContext context) + catch (ArgumentInvalidException ex) { - try - { - await next.Invoke(context); - } - catch (ArgumentInvalidException ex) - { - Console.WriteLine($"ArgumentException in {context.Request.Method}: {ex.Message}"); - context.Response.Clear(); - context.Response.StatusCode = 400; - context.Response.ContentType = "application/json"; - var body = MakeJsonBody(ex); - await context.Response.WriteAsync(body); - } - catch (ForbidException ex) - { - Console.WriteLine($"ForbidException in {context.Request.Method}: {ex.Message}"); - context.Response.Clear(); - context.Response.StatusCode = 403; - } - catch (OperationCanceledException ex) - { - Console.WriteLine(ex.Message); - } - catch (Exception ex) // TODO: find explicit exception. Use Trace. Add body size to message. - { - if (context.Response.HasStarted) - throw; - - context.Response.Clear(); - context.Response.StatusCode = 500; - - if (ex.Message.Contains("Reading the request body timed out due to data arriving too slowly. See MinRequestBodyDataRate.")) - Console.WriteLine("Reading the request body timed out due to data arriving too slowly."); - else - throw; - } + Console.WriteLine($"ArgumentException in {context.Request.Method}: {ex.Message}"); + context.Response.Clear(); + context.Response.StatusCode = 400; + context.Response.ContentType = "application/json"; + var body = MakeJsonBody(ex); + await context.Response.WriteAsync(body); } - - private static string MakeJsonBody(ArgumentInvalidException ex) + catch (ForbidException ex) { - var problem = new ValidationProblemDetails(ex.ErrorState); - var buffer = System.Text.Json.JsonSerializer.Serialize(problem); - return buffer; + Console.WriteLine($"ForbidException in {context.Request.Method}: {ex.Message}"); + context.Response.Clear(); + context.Response.StatusCode = 403; + } + catch (OperationCanceledException ex) + { + Console.WriteLine(ex.Message); + } + catch (Exception ex) // TODO: find explicit exception. Use Trace. Add body size to message. + { + if (context.Response.HasStarted) + throw; + + context.Response.Clear(); + context.Response.StatusCode = 500; + + if (ex.Message.Contains("Reading the request body timed out due to data arriving too slowly. See MinRequestBodyDataRate.")) + Console.WriteLine("Reading the request body timed out due to data arriving too slowly."); + else + throw; } } + + private static string MakeJsonBody(ArgumentInvalidException ex) + { + var problem = new ValidationProblemDetails(ex.ErrorState); + var buffer = System.Text.Json.JsonSerializer.Serialize(problem); + return buffer; + } } diff --git a/AsbCloudWebApi/Middlewares/UserConnectionsLimitMiddlware.cs b/AsbCloudWebApi/Middlewares/UserConnectionsLimitMiddlware.cs index f905d4f2..35cd7d93 100644 --- a/AsbCloudWebApi/Middlewares/UserConnectionsLimitMiddlware.cs +++ b/AsbCloudWebApi/Middlewares/UserConnectionsLimitMiddlware.cs @@ -5,69 +5,67 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -namespace AsbCloudWebApi.Middlewares +namespace AsbCloudWebApi.Middlewares; + + +/// +/// This is not real middleware it`s part of PermissionsMiddlware. +/// DO NOT register it in setup.cs as middleware. +/// +class UserConnectionsLimitMiddlware { + private readonly int parallelRequestsToController; + private readonly RequestDelegate next; + private readonly byte[] responseBody; + private readonly ConcurrentDictionary> stat = new (); + private readonly IEnumerable? controllerNames; - /// - /// This is not real middleware it`s part of PermissionsMiddlware. - /// DO NOT register it in setup.cs as middleware. - /// - class UserConnectionsLimitMiddlware + public UserConnectionsLimitMiddlware(RequestDelegate next, IConfiguration configuration) { - private readonly int parallelRequestsToController; - private readonly RequestDelegate next; - private readonly byte[] responseBody; - private readonly ConcurrentDictionary> stat = new (); - private readonly IEnumerable? controllerNames; + const int parallelRequestsToControllerDefault = 8; + this.next = next; + + var parallelRequestsToController = configuration.GetSection("userLimits")?.GetValue("parallelRequestsToController") ?? parallelRequestsToControllerDefault; + this.parallelRequestsToController = parallelRequestsToController > 0 + ? parallelRequestsToController + : parallelRequestsToControllerDefault; - public UserConnectionsLimitMiddlware(RequestDelegate next, IConfiguration configuration) - { - const int parallelRequestsToControllerDefault = 8; - this.next = next; - - var parallelRequestsToController = configuration.GetSection("userLimits")?.GetValue("parallelRequestsToController") ?? parallelRequestsToControllerDefault; - this.parallelRequestsToController = parallelRequestsToController > 0 - ? parallelRequestsToController - : parallelRequestsToControllerDefault; + controllerNames = configuration.GetSection("userLimits")?.GetValue>("controllerNames"); - controllerNames = configuration.GetSection("userLimits")?.GetValue>("controllerNames"); - - var bodyText = $"Too Many Requests

Too Many Requests

I only allow {this.parallelRequestsToController} parallel requests per user. Try again soon.

"; - responseBody = System.Text.Encoding.UTF8.GetBytes(bodyText); - } - - public async Task InvokeAsync(HttpContext context, int idUser, string controllerName) - { - if(controllerNames?.Any(n => controllerName.StartsWith(n)) == false) - { - await next(context); - return; - } - - var userStat = stat.GetOrAdd(idUser, idUser => new()); - var count = userStat.AddOrUpdate(controllerName, 0, (k, v) => v); - - if(count + 1 < parallelRequestsToController) - { - try - { - userStat[controllerName]++; - await next(context); - } - finally - { - userStat[controllerName]--; - } - } - else - { - context.Response.Clear(); - context.Response.StatusCode = (int)System.Net.HttpStatusCode.TooManyRequests; - context.Response.Headers.RetryAfter = "1000"; - context.Response.Headers.ContentType = "text/html"; - await context.Response.BodyWriter.WriteAsync(responseBody); - } - } + var bodyText = $"Too Many Requests

Too Many Requests

I only allow {this.parallelRequestsToController} parallel requests per user. Try again soon.

"; + responseBody = System.Text.Encoding.UTF8.GetBytes(bodyText); } + public async Task InvokeAsync(HttpContext context, int idUser, string controllerName) + { + if(controllerNames?.Any(n => controllerName.StartsWith(n)) == false) + { + await next(context); + return; + } + + var userStat = stat.GetOrAdd(idUser, idUser => new()); + var count = userStat.AddOrUpdate(controllerName, 0, (k, v) => v); + + if(count + 1 < parallelRequestsToController) + { + try + { + userStat[controllerName]++; + await next(context); + } + finally + { + userStat[controllerName]--; + } + } + else + { + context.Response.Clear(); + context.Response.StatusCode = (int)System.Net.HttpStatusCode.TooManyRequests; + context.Response.Headers.RetryAfter = "1000"; + context.Response.Headers.ContentType = "text/html"; + await context.Response.BodyWriter.WriteAsync(responseBody); + } + } } diff --git a/AsbCloudWebApi/PermissionAttribute.cs b/AsbCloudWebApi/PermissionAttribute.cs index 4d192eac..8720754e 100644 --- a/AsbCloudWebApi/PermissionAttribute.cs +++ b/AsbCloudWebApi/PermissionAttribute.cs @@ -1,29 +1,28 @@ using System; using System.Collections.Concurrent; -namespace AsbCloudWebApi +namespace AsbCloudWebApi; + +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] +public class PermissionAttribute : Attribute { - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] - public class PermissionAttribute : Attribute + public static ConcurrentBag Registered { get; } = new(); + + public string Name { get; set; } = null!; + + /// + /// Проверка наличия у пользователя разрешения с именем "{ControllerName}.{http_method}". + /// Пример автоматической генерации имени: "Message.get", где "Message" - имя контроллера MessageController. + /// + public PermissionAttribute() { } + + /// + /// Проверка наличия у пользователя указанного разрешения. + /// + /// Имя разрешения (default = ControllerName.http_method) + public PermissionAttribute(string name) { - public static ConcurrentBag Registered { get; } = new(); - - public string Name { get; set; } = null!; - - /// - /// Проверка наличия у пользователя разрешения с именем "{ControllerName}.{http_method}". - /// Пример автоматической генерации имени: "Message.get", где "Message" - имя контроллера MessageController. - /// - public PermissionAttribute() { } - - /// - /// Проверка наличия у пользователя указанного разрешения. - /// - /// Имя разрешения (default = ControllerName.http_method) - public PermissionAttribute(string name) - { - Name = name; - Registered.Add(name); - } + Name = name; + Registered.Add(name); } } diff --git a/AsbCloudWebApi/Program.cs b/AsbCloudWebApi/Program.cs index e1b6445b..4645a382 100644 --- a/AsbCloudWebApi/Program.cs +++ b/AsbCloudWebApi/Program.cs @@ -1,24 +1,23 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; -namespace AsbCloudWebApi -{ - public class Program - { - // Uncomment next line to find wired exceptions by tracing. - //static TraceListenerView trace4debug = new TraceListenerView(); - public static void Main(string[] args) - { - var host = CreateHostBuilder(args).Build(); - AsbCloudInfrastructure.Startup.BeforeRunHandler(host); - host.Run(); - } +namespace AsbCloudWebApi; - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); +public class Program +{ + // Uncomment next line to find wired exceptions by tracing. + //static TraceListenerView trace4debug = new TraceListenerView(); + public static void Main(string[] args) + { + var host = CreateHostBuilder(args).Build(); + AsbCloudInfrastructure.Startup.BeforeRunHandler(host); + host.Run(); } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); } diff --git a/AsbCloudWebApi/SignalR/Clients/INotificationHubClient.cs b/AsbCloudWebApi/SignalR/Clients/INotificationHubClient.cs index c4cf6500..ae94ab64 100644 --- a/AsbCloudWebApi/SignalR/Clients/INotificationHubClient.cs +++ b/AsbCloudWebApi/SignalR/Clients/INotificationHubClient.cs @@ -3,21 +3,20 @@ using SignalRSwaggerGen.Attributes; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.SignalR.Clients +namespace AsbCloudWebApi.SignalR.Clients; + +/// +/// Hub по работе с уведомлениями +/// +[SignalRHub] +public interface INotificationHubClient { /// - /// Hub по работе с уведомлениями + /// Отправка клиенту сообщения с уведомлением. + /// Для подписки на метод необходимо отправить connectionId /// - [SignalRHub] - public interface INotificationHubClient - { - /// - /// Отправка клиенту сообщения с уведомлением. - /// Для подписки на метод необходимо отправить connectionId - /// - /// сообщение с уведомлением - /// - /// - Task ReceiveNotifications(NotificationMessage message, CancellationToken token); - } + /// сообщение с уведомлением + /// + /// + Task ReceiveNotifications(NotificationMessage message, CancellationToken token); } diff --git a/AsbCloudWebApi/SignalR/Clients/IReportHubClient.cs b/AsbCloudWebApi/SignalR/Clients/IReportHubClient.cs index d5b5b58b..26a53c2e 100644 --- a/AsbCloudWebApi/SignalR/Clients/IReportHubClient.cs +++ b/AsbCloudWebApi/SignalR/Clients/IReportHubClient.cs @@ -2,21 +2,20 @@ using SignalRSwaggerGen.Attributes; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.SignalR.Clients +namespace AsbCloudWebApi.SignalR.Clients; + +/// +/// Hub по работе с отчетами +/// +[SignalRHub] +public interface IReportHubClient { /// - /// Hub по работе с отчетами + /// Отправка клиенту сообщения о статусе формирования отчета. + /// Для подписки на метод необходимо отправить сообщение в формате $"Report_{id}" /// - [SignalRHub] - public interface IReportHubClient - { - /// - /// Отправка клиенту сообщения о статусе формирования отчета. - /// Для подписки на метод необходимо отправить сообщение в формате $"Report_{id}" - /// - /// статус формирования отчета - /// - /// - Task GetReportProgress(object progress, CancellationToken token); - } + /// статус формирования отчета + /// + /// + Task GetReportProgress(object progress, CancellationToken token); } diff --git a/AsbCloudWebApi/SignalR/Clients/ITelemetryHubClient.cs b/AsbCloudWebApi/SignalR/Clients/ITelemetryHubClient.cs index 0c2e7642..5c19b77f 100644 --- a/AsbCloudWebApi/SignalR/Clients/ITelemetryHubClient.cs +++ b/AsbCloudWebApi/SignalR/Clients/ITelemetryHubClient.cs @@ -5,49 +5,48 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.SignalR.Clients +namespace AsbCloudWebApi.SignalR.Clients; + +/// +/// Hub по работе с телеметрией +/// +[SignalRHub] +public interface ITelemetryHubClient { /// - /// Hub по работе с телеметрией + /// Отправка клиенту уведомления о доставке с панели drill test данных. + /// Для подписки на метод необходимо отправить сообщение в формате $"well_{idWell}" /// - [SignalRHub] - public interface ITelemetryHubClient - { - /// - /// Отправка клиенту уведомления о доставке с панели drill test данных. - /// Для подписки на метод необходимо отправить сообщение в формате $"well_{idWell}" - /// - /// - /// - /// - Task ReceiveDrilltestData(IEnumerable dtos, CancellationToken token); + /// + /// + /// + Task ReceiveDrilltestData(IEnumerable dtos, CancellationToken token); - /// - /// Обновление записей РТК - /// Для подписки на метод необходимо отправить сообщение "ProcessMapWellDrilling" - /// - /// - /// - /// - Task UpdateProcessMap(IEnumerable dtos, CancellationToken token); + /// + /// Обновление записей РТК + /// Для подписки на метод необходимо отправить сообщение "ProcessMapWellDrilling" + /// + /// + /// + /// + Task UpdateProcessMap(IEnumerable dtos, CancellationToken token); - /// - /// Отправка сауб-данных клиенту. - /// Для подписки на метод необходимо отправить сообщение в формате $"well_{idWell}" - /// - /// - /// - /// - Task ReceiveDataSaub(IEnumerable dtos, CancellationToken token); + /// + /// Отправка сауб-данных клиенту. + /// Для подписки на метод необходимо отправить сообщение в формате $"well_{idWell}" + /// + /// + /// + /// + Task ReceiveDataSaub(IEnumerable dtos, CancellationToken token); - /// - /// Отправка спин-данных клиенту. - /// Для подписки на метод необходимо отправить сообщение в формате $"well_{idWell}" - /// - /// - /// - /// - Task ReceiveDataSpin(IEnumerable dtos, CancellationToken token); + /// + /// Отправка спин-данных клиенту. + /// Для подписки на метод необходимо отправить сообщение в формате $"well_{idWell}" + /// + /// + /// + /// + Task ReceiveDataSpin(IEnumerable dtos, CancellationToken token); - } } diff --git a/AsbCloudWebApi/SignalR/Clients/IWellInfoHubClient.cs b/AsbCloudWebApi/SignalR/Clients/IWellInfoHubClient.cs index 5f5b42e9..45b37502 100644 --- a/AsbCloudWebApi/SignalR/Clients/IWellInfoHubClient.cs +++ b/AsbCloudWebApi/SignalR/Clients/IWellInfoHubClient.cs @@ -3,21 +3,20 @@ using SignalRSwaggerGen.Attributes; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.SignalR.Clients +namespace AsbCloudWebApi.SignalR.Clients; + +/// +/// Hub по работе с информацией о скважине +/// +[SignalRHub] +public interface IWellInfoHubClient { /// - /// Hub по работе с информацией о скважине + /// Отправка клиенту сообщения об обновлении информации о скважине + /// Для подписки на метод необходимо отправить сообщение в формате $"well_info_{idWell}" /// - [SignalRHub] - public interface IWellInfoHubClient - { - /// - /// Отправка клиенту сообщения об обновлении информации о скважине - /// Для подписки на метод необходимо отправить сообщение в формате $"well_info_{idWell}" - /// - /// информация о скважине - /// - /// - Task UpdateWellInfo(object wellInfo, CancellationToken token); - } + /// информация о скважине + /// + /// + Task UpdateWellInfo(object wellInfo, CancellationToken token); } diff --git a/AsbCloudWebApi/SignalR/ReportsHub.cs b/AsbCloudWebApi/SignalR/ReportsHub.cs index f9972f36..d6ade824 100644 --- a/AsbCloudWebApi/SignalR/ReportsHub.cs +++ b/AsbCloudWebApi/SignalR/ReportsHub.cs @@ -7,54 +7,53 @@ using Microsoft.AspNetCore.Mvc; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudWebApi.SignalR +namespace AsbCloudWebApi.SignalR; + +// SignalR manual: +// https://docs.microsoft.com/ru-ru/aspnet/core/signalr/introduction?view=aspnetcore-5.0 +//[SignalRHub] +/// +/// ReportsHub +/// +[Authorize] +public class ReportsHub : BaseHub { - // SignalR manual: - // https://docs.microsoft.com/ru-ru/aspnet/core/signalr/introduction?view=aspnetcore-5.0 - //[SignalRHub] - /// - /// ReportsHub - /// - [Authorize] - public class ReportsHub : BaseHub + private readonly IWellService wellService; + private readonly IReportService reportService; + + public ReportsHub(IWellService wellService, IReportService reportService) { - private readonly IWellService wellService; - private readonly IReportService reportService; + this.wellService = wellService; + this.reportService = reportService; + } - public ReportsHub(IWellService wellService, IReportService reportService) - { - this.wellService = wellService; - this.reportService = reportService; - } + /// + /// Добавление в группу, отправка данных о формировании отчета + /// + /// группа + /// ключ скважины + /// параметры запроса + /// + public async Task CreateReport(string groupName, int idWell, ReportParametersRequest request) + { + var idUser = Context.User?.GetUserId(); + var idCompany = Context.User?.GetCompanyId(); - /// - /// Добавление в группу, отправка данных о формировании отчета - /// - /// группа - /// ключ скважины - /// параметры запроса - /// - public async Task CreateReport(string groupName, int idWell, ReportParametersRequest request) - { - var idUser = Context.User?.GetUserId(); - var idCompany = Context.User?.GetCompanyId(); + if ((idCompany is null) || (idUser is null)) + return; - if ((idCompany is null) || (idUser is null)) - return; + if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, CancellationToken.None)) + return; - if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, CancellationToken.None)) - return; + await base.AddToGroup(groupName); - await base.AddToGroup(groupName); + void HandleReportProgressAsync(object progress, string id) => + Task.Run(async () => + { + await Clients.Group(groupName) + .GetReportProgress(progress, CancellationToken.None); + }, CancellationToken.None); - void HandleReportProgressAsync(object progress, string id) => - Task.Run(async () => - { - await Clients.Group(groupName) - .GetReportProgress(progress, CancellationToken.None); - }, CancellationToken.None); - - var id = reportService.EnqueueCreateReportWork(idWell, (int)idUser, request, HandleReportProgressAsync); - } + var id = reportService.EnqueueCreateReportWork(idWell, (int)idUser, request, HandleReportProgressAsync); } } diff --git a/AsbCloudWebApi/SignalR/TelemetryHub.cs b/AsbCloudWebApi/SignalR/TelemetryHub.cs index df4cab22..9d96cffd 100644 --- a/AsbCloudWebApi/SignalR/TelemetryHub.cs +++ b/AsbCloudWebApi/SignalR/TelemetryHub.cs @@ -1,14 +1,13 @@ using AsbCloudWebApi.SignalR.Clients; using Microsoft.AspNetCore.Authorization; -namespace AsbCloudWebApi.SignalR -{ - // SignalR manual: - // https://docs.microsoft.com/ru-ru/aspnet/core/signalr/introduction?view=aspnetcore-5.0 +namespace AsbCloudWebApi.SignalR; - [Authorize] - public class TelemetryHub : BaseHub - { - - } +// SignalR manual: +// https://docs.microsoft.com/ru-ru/aspnet/core/signalr/introduction?view=aspnetcore-5.0 + +[Authorize] +public class TelemetryHub : BaseHub +{ + } \ No newline at end of file diff --git a/AsbCloudWebApi/Startup.cs b/AsbCloudWebApi/Startup.cs index b4830fb9..7545fca0 100644 --- a/AsbCloudWebApi/Startup.cs +++ b/AsbCloudWebApi/Startup.cs @@ -12,147 +12,146 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.ResponseCompression; using AsbCloudWebApi.Conventions; -namespace AsbCloudWebApi +namespace AsbCloudWebApi; + +public class Startup { - public class Startup + public IConfiguration Configuration { get; } + public Startup(IConfiguration configuration) { - public IConfiguration Configuration { get; } - public Startup(IConfiguration configuration) + Configuration = configuration; + } + + public void ConfigureServices(IServiceCollection services) + { + services.AddControllers() + .AddJsonOptions(new System.Action(options => + { + options.JsonSerializerOptions.NumberHandling = + System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals | + System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString; + + options.JsonSerializerOptions.Converters.Add(new DateOnlyJsonConverter()); + options.JsonSerializerOptions.Converters.Add(new JsonValueJsonConverter()); + })) + .AddProtoBufNet(); + + services.AddControllers(options => options.UseDateOnlyTimeOnlyStringConverters()); + + ProtobufModel.EnsureRegistered(); + + services.AddSwagger(); + + services.AddInfrastructure(Configuration); + + services.AddNotificationTransportServices(); + + services.AddIntegrationEvents(); + + services.AddJWTAuthentication(); + + services.AddSignalR() + .Services.AddSingleton(); + + services.AddCors(options => { - Configuration = configuration; + options.AddPolicy("ClientPermission", policy => + { + policy.AllowAnyHeader() + .AllowAnyMethod() + .WithOrigins( + "http://0.0.0.0", + "http://*", + "http://localhost", + + "http://0.0.0.0:3000", + "http://*:3000", + "http://localhost:3000", + + "http://0.0.0.0:5000", + "http://*:5000", + "http://localhost:5000", + + "https://0.0.0.0", + "https://*", + "https://localhost", + + "https://0.0.0.0:3000", + "https://*:3000", + "https://localhost:3000", + + "https://0.0.0.0:5001", + "https://*:5001", + "https://localhost:5001", + + "https://0.0.0.0:443", + "https://*:443", + "https://localhost:443", + + "http://cloud.autodrilling.ru", + "http://cloud.digitaldrilling.ru", + "http://test.digitaldrilling.ru", + + "https://cloud.autodrilling.ru", + "https://cloud.digitaldrilling.ru", + "https://testdigitaldrilling.ru", + + "smb2-digital-drilling-frontend-smb2-dev.apps.okd.cloud.nedra.digital", + "http://smb2-digital-drilling-frontend-smb2-dev.apps.okd.cloud.nedra.digital", + "https://smb2-digital-drilling-frontend-smb2-dev.apps.okd.cloud.nedra.digital" + ) + .AllowCredentials(); + }); + }); + + services.AddResponseCompression(options => + { + options.EnableForHttps = true; + options.Providers.Add(); + }); + + services.AddMvc(c => + c.Conventions.Add(new ApiExplorerGroupPerVersionConvention()) + ); + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + app.UseSwagger(); + app.UseSwaggerUI(c => + { + c.SwaggerEndpoint("/swagger/v1/swagger.json", "V1"); + c.SwaggerEndpoint("/swagger/signalr/swagger.json", "signalr"); + c.EnablePersistAuthorization(); + c.EnableFilter(); + c.DisplayOperationId(); + }); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); } - public void ConfigureServices(IServiceCollection services) + app.UseCors("ClientPermission"); + app.UseRouting(); + + app.UseResponseCaching(); + app.UseResponseCompression(); + + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseMiddleware(Configuration); + app.UseMiddleware(); + app.UseMiddleware(); + + app.UseEndpoints(endpoints => { - services.AddControllers() - .AddJsonOptions(new System.Action(options => - { - options.JsonSerializerOptions.NumberHandling = - System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals | - System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString; - - options.JsonSerializerOptions.Converters.Add(new DateOnlyJsonConverter()); - options.JsonSerializerOptions.Converters.Add(new JsonValueJsonConverter()); - })) - .AddProtoBufNet(); - - services.AddControllers(options => options.UseDateOnlyTimeOnlyStringConverters()); - - ProtobufModel.EnsureRegistered(); - - services.AddSwagger(); - - services.AddInfrastructure(Configuration); - - services.AddNotificationTransportServices(); - - services.AddIntegrationEvents(); - - services.AddJWTAuthentication(); - - services.AddSignalR() - .Services.AddSingleton(); - - services.AddCors(options => - { - options.AddPolicy("ClientPermission", policy => - { - policy.AllowAnyHeader() - .AllowAnyMethod() - .WithOrigins( - "http://0.0.0.0", - "http://*", - "http://localhost", - - "http://0.0.0.0:3000", - "http://*:3000", - "http://localhost:3000", - - "http://0.0.0.0:5000", - "http://*:5000", - "http://localhost:5000", - - "https://0.0.0.0", - "https://*", - "https://localhost", - - "https://0.0.0.0:3000", - "https://*:3000", - "https://localhost:3000", - - "https://0.0.0.0:5001", - "https://*:5001", - "https://localhost:5001", - - "https://0.0.0.0:443", - "https://*:443", - "https://localhost:443", - - "http://cloud.autodrilling.ru", - "http://cloud.digitaldrilling.ru", - "http://test.digitaldrilling.ru", - - "https://cloud.autodrilling.ru", - "https://cloud.digitaldrilling.ru", - "https://testdigitaldrilling.ru", - - "smb2-digital-drilling-frontend-smb2-dev.apps.okd.cloud.nedra.digital", - "http://smb2-digital-drilling-frontend-smb2-dev.apps.okd.cloud.nedra.digital", - "https://smb2-digital-drilling-frontend-smb2-dev.apps.okd.cloud.nedra.digital" - ) - .AllowCredentials(); - }); - }); - - services.AddResponseCompression(options => - { - options.EnableForHttps = true; - options.Providers.Add(); - }); - - services.AddMvc(c => - c.Conventions.Add(new ApiExplorerGroupPerVersionConvention()) - ); - } - - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - app.UseSwagger(); - app.UseSwaggerUI(c => - { - c.SwaggerEndpoint("/swagger/v1/swagger.json", "V1"); - c.SwaggerEndpoint("/swagger/signalr/swagger.json", "signalr"); - c.EnablePersistAuthorization(); - c.EnableFilter(); - c.DisplayOperationId(); - }); - - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseCors("ClientPermission"); - app.UseRouting(); - - app.UseResponseCaching(); - app.UseResponseCompression(); - - app.UseAuthentication(); - app.UseAuthorization(); - - app.UseMiddleware(Configuration); - app.UseMiddleware(); - app.UseMiddleware(); - - app.UseEndpoints(endpoints => - { - endpoints.MapControllers(); - endpoints.MapHub("/hubs/wellInfo"); - endpoints.MapHub("/hubs/notifications"); - endpoints.MapHub("/hubs/telemetry"); - endpoints.MapHub("/hubs/reports"); - }); - } + endpoints.MapControllers(); + endpoints.MapHub("/hubs/wellInfo"); + endpoints.MapHub("/hubs/notifications"); + endpoints.MapHub("/hubs/telemetry"); + endpoints.MapHub("/hubs/reports"); + }); } }