From b7dcf313a2cb77680aa40a88b2cd412566d60996 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Thu, 8 Feb 2024 11:38:25 +0500 Subject: [PATCH] Add DetectedOperation repository --- .../DetectedOperation/DetectedOperationDto.cs | 151 +++--- .../DetectedOperationListDto.cs | 2 +- AsbCloudApp/Data/SimpleTimezoneDto.cs | 7 + AsbCloudApp/Data/TimeDto.cs | 8 + .../IDetectedOperationRepository.cs | 11 +- .../IWellOperationCategoryRepository.cs | 17 + .../Requests/DetectedOperationRequest.cs | 150 +++--- AsbCloudApp/Requests/RequestBase.cs | 18 + .../Services/IDetectedOperationService.cs | 10 +- AsbCloudDb/EFExtensionsExceptionHandling.cs | 33 ++ ...entionOrderBy.cs => EFExtensionsSortBy.cs} | 2 +- AsbCloudInfrastructure/DependencyInjection.cs | 2 + .../Repository/DetectedOperationRepository.cs | 191 ++++++++ .../WellOperationCategoryRepository.cs | 44 ++ .../Repository/WellOperationRepository.cs | 23 +- .../DailyReport/DailyReportService.cs | 2 +- .../DetectedOperationService.cs | 439 ++++++++---------- .../Services/Subsystems/SubsystemService.cs | 21 +- .../Services/WellService.cs | 9 +- AsbCloudWebApi/AsbCloudWebApi.csproj | 1 + .../SAUB/DetectedOperationController.cs | 6 +- 21 files changed, 708 insertions(+), 439 deletions(-) create mode 100644 AsbCloudApp/Repositories/IWellOperationCategoryRepository.cs create mode 100644 AsbCloudDb/EFExtensionsExceptionHandling.cs rename AsbCloudDb/{EFExtentionOrderBy.cs => EFExtensionsSortBy.cs} (99%) create mode 100644 AsbCloudInfrastructure/Repository/DetectedOperationRepository.cs create mode 100644 AsbCloudInfrastructure/Repository/WellOperationCategoryRepository.cs diff --git a/AsbCloudApp/Data/DetectedOperation/DetectedOperationDto.cs b/AsbCloudApp/Data/DetectedOperation/DetectedOperationDto.cs index 0386e8b3..2b0fc768 100644 --- a/AsbCloudApp/Data/DetectedOperation/DetectedOperationDto.cs +++ b/AsbCloudApp/Data/DetectedOperation/DetectedOperationDto.cs @@ -1,100 +1,85 @@ using System; using System.ComponentModel.DataAnnotations; -namespace AsbCloudApp.Data.DetectedOperation +namespace AsbCloudApp.Data.DetectedOperation; + +/// +/// Автоматически определенная операция +/// +public class DetectedOperationDto: IId { + /// + [Required] + public int Id { get; set; } + /// - /// Автоматически определяемая операция + /// Id телеметрии /// - public class DetectedOperationDto : IId, IWellRelated - { - /// - [Required] - public int Id { get; set; } + [Required] + public int IdTelemetry { get; set; } - /// - [Required] - public int IdWell { get; set; } + /// + /// Id названия/описания операции + /// + [Required] + public int IdCategory { get; set; } - /// - /// Id телеметрии - /// - [Required] - public int IdTelemetry { get; set; } + /// + /// Id пользователя панели на момент начала операции + /// + [Required] + public int IdUserAtStart { get; set; } - /// - /// Id названия/описания операции - /// - [Required] - public int IdCategory { get; set; } + /// + /// Дата завершения операции в часовом поясе скважины + /// + [Required] + public DateTimeOffset DateEnd { get; set; } - /// - /// Id пользователя панели - /// - [Required] - public int IdUsersAtStart { get; set; } + /// + /// Дата начала операции в часовом поясе скважины + /// + [Required] + public DateTimeOffset DateStart { get; set; } - /// - /// Дата начала операции в часовом поясе скважины - /// - [Required] - public DateTime DateStart { get; set; } + /// + /// глубина на завершения операции, м + /// + [Required] + public double DepthEnd { get; set; } - /// - /// Дата завершения операции в часовом поясе скважины - /// - [Required] - public DateTime DateEnd { get; set; } + /// + /// глубина на начало операции, м + /// + [Required] + public double DepthStart { get; set; } - /// - /// Продолжительность операции в минутах - /// - [Required] - public double DurationMinutes => (DateEnd - DateStart).TotalMinutes; + /// + /// Продолжительность операции в минутах + /// + [Required] + public double DurationMinutes => (DateEnd - DateStart).TotalMinutes; - /// - /// глубина на начало операции, м - /// - [Required] - public double DepthStart { get; set; } + /// + /// Флаг включенной подсистемы + /// + [Required] + public int EnabledSubsystems { get; set; } - /// - /// глубина на завершения операции, м - /// - [Required] - public double DepthEnd { get; set; } + /// + /// название/описание операции + /// + [Required] + public WellOperationCategoryDto OperationCategory { get; set; } = null!; - /// - /// название/описание операции - /// - [Required] - public WellOperationCategoryDto OperationCategory { get; set; } = null!; + /// + /// Пользователь панели оператора + /// + public string? TelemetryUserName { get; set; } - /// - /// Пользователь панели оператора - /// - public string? TelemetryUserName { get; set; } - - /// - /// Бурильщик - /// - public DrillerDto? Driller { get; set; } - - /// - /// Целевые/нормативные показатели - /// - public OperationValueDto? OperationValue { get; set; } - - /// - /// Ключевой параметр операции - /// - [Required] - public double Value { get; set; } - - /// - /// Флаг включенной подсистемы - /// - [Required] - public int EnabledSubsystems { get; set; } - } -} + /// + /// Ключевой параметр операции + /// + [Required] + public double Value { get; set; } +} \ No newline at end of file diff --git a/AsbCloudApp/Data/DetectedOperation/DetectedOperationListDto.cs b/AsbCloudApp/Data/DetectedOperation/DetectedOperationListDto.cs index fef979bb..32dd6040 100644 --- a/AsbCloudApp/Data/DetectedOperation/DetectedOperationListDto.cs +++ b/AsbCloudApp/Data/DetectedOperation/DetectedOperationListDto.cs @@ -13,7 +13,7 @@ namespace AsbCloudApp.Data.DetectedOperation /// Список всех операций /// [Required] - public IEnumerable Operations { get; set; } = Enumerable.Empty(); + public IEnumerable Operations { get; set; } = Enumerable.Empty(); /// /// Статистика по бурильщикам diff --git a/AsbCloudApp/Data/SimpleTimezoneDto.cs b/AsbCloudApp/Data/SimpleTimezoneDto.cs index 3ec75814..e878bacf 100644 --- a/AsbCloudApp/Data/SimpleTimezoneDto.cs +++ b/AsbCloudApp/Data/SimpleTimezoneDto.cs @@ -1,3 +1,5 @@ +using System; + namespace AsbCloudApp.Data { /// @@ -20,6 +22,11 @@ namespace AsbCloudApp.Data /// public bool IsOverride { get; set; } + /// + /// + /// + public TimeSpan Offset { get => TimeSpan.FromHours(Hours); } + /// public override bool Equals(object? obj) { diff --git a/AsbCloudApp/Data/TimeDto.cs b/AsbCloudApp/Data/TimeDto.cs index 6a3620f2..20ffa4ac 100644 --- a/AsbCloudApp/Data/TimeDto.cs +++ b/AsbCloudApp/Data/TimeDto.cs @@ -86,6 +86,14 @@ namespace AsbCloudApp.Data second = fullDate.Second; } + /// + public TimeDto(DateTimeOffset fullDate) + { + hour = fullDate.Hour; + minute = fullDate.Minute; + second = fullDate.Second; + } + /// /// Makes System.TimeOnly /// diff --git a/AsbCloudApp/Repositories/IDetectedOperationRepository.cs b/AsbCloudApp/Repositories/IDetectedOperationRepository.cs index 2684b265..5a52b455 100644 --- a/AsbCloudApp/Repositories/IDetectedOperationRepository.cs +++ b/AsbCloudApp/Repositories/IDetectedOperationRepository.cs @@ -7,7 +7,7 @@ using System.Threading; namespace AsbCloudApp.Repositories; /// -/// Таблица автоопределенных операций +/// Таблица автоматически определенных операций /// public interface IDetectedOperationRepository { @@ -18,15 +18,15 @@ public interface IDetectedOperationRepository /// /// /// - Task Insert(int idUser, IEnumerable dtos, CancellationToken token); + Task Insert(int? idUser, IEnumerable dtos, CancellationToken token); /// - /// Получить автоматически определенные по телеметрии операции + /// Получить автоматически определенные операции по телеметрии /// /// /// /// - Task> Get(DetectedOperationRequest request, CancellationToken token); + Task> Get(DetectedOperationByTelemetryRequest request, CancellationToken token); /// /// Редактирование записей @@ -49,10 +49,11 @@ public interface IDetectedOperationRepository /// /// Удалить операции /// + /// /// /// /// - Task DeleteAsync(int idUser, DetectedOperationRequest request, CancellationToken token); + Task Delete(int idUser, DetectedOperationByTelemetryRequest request, CancellationToken token); /// /// Удаление записей diff --git a/AsbCloudApp/Repositories/IWellOperationCategoryRepository.cs b/AsbCloudApp/Repositories/IWellOperationCategoryRepository.cs new file mode 100644 index 00000000..4e18c231 --- /dev/null +++ b/AsbCloudApp/Repositories/IWellOperationCategoryRepository.cs @@ -0,0 +1,17 @@ +using AsbCloudApp.Data; +using System.Collections.Generic; + +namespace AsbCloudApp.Repositories +{ + /// + /// сервис операций по скважине + /// + public interface IWellOperationCategoryRepository + { + /// + /// список названий операций + /// + /// + IEnumerable Get(bool includeParents); + } +} \ No newline at end of file diff --git a/AsbCloudApp/Requests/DetectedOperationRequest.cs b/AsbCloudApp/Requests/DetectedOperationRequest.cs index a9c079d7..243d6e9f 100644 --- a/AsbCloudApp/Requests/DetectedOperationRequest.cs +++ b/AsbCloudApp/Requests/DetectedOperationRequest.cs @@ -1,68 +1,114 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.Linq; -namespace AsbCloudApp.Requests +namespace AsbCloudApp.Requests; + +/// +/// Запрос на получение операций определенных по телеметрии +/// +public class DetectedOperationByTelemetryRequest : DetectedOperationRequest { /// - /// + /// id телеметрии /// - public class DetectedOperationByWellRequest : DetectedOperationRequest - { - /// - /// категория операций - /// - [Required] - public int IdWell { get; set; } - } + [Required] + public int IdTelemetry { get; set; } /// - /// + /// Запрос на получение операций определенных по id телеметрии /// - public class DetectedOperationByTelemetryRequest : DetectedOperationRequest - { - /// - /// Список id телеметрий - /// пустой список - нет фильтрации - /// - public IEnumerable IdsTelemetries { get; set; } = Array.Empty(); - } + public DetectedOperationByTelemetryRequest() + {} /// - /// Параметры запроса на получение операций определенных по телеметрии + /// Запрос на получение операций определенных по id телеметрии. Copy /// - public class DetectedOperationRequest : RequestBase + /// + /// + public DetectedOperationByTelemetryRequest(int idTelemetry, DetectedOperationRequest request) + :base(request) { - /// - /// категории операций - /// - public IEnumerable IdsCategories { get; set; } = Array.Empty(); - - /// - /// Больше или равно дате - /// - public DateTimeOffset? GeDateStart { get; set; } - - /// - /// Меньше или равно дате - /// - public DateTimeOffset? LeDateEnd { get; set; } - - /// - /// Больше или равно глубины забоя - /// - public double? GeDepth { get; set; } - - /// - /// Меньше или равно глубины забоя - /// - public double? LeDepth { get; set; } - - /// - /// Фильтр по пользователю панели - /// - public int? IdTelemetryUser { get; set; } - + IdTelemetry = idTelemetry; + } +} + +/// +/// Запрос на получение операций определенных по id скважины +/// +public class DetectedOperationByWellRequest : DetectedOperationRequest +{ + /// + /// id скважины + /// + [Required] + public int IdWell { get; set; } + + /// + /// Запрос на получение операций определенных по id скважины + /// + public DetectedOperationByWellRequest() + {} + + /// + /// Запрос на получение операций определенных по id скважины. Copy + /// + public DetectedOperationByWellRequest(int idWell, DetectedOperationRequest request) + : base(request) + { + IdWell = idWell; + } +} + +/// +/// Запрос на получение операций определенных по телеметрии +/// +public class DetectedOperationRequest : RequestBase +{ + /// + /// категории операций + /// + public IEnumerable IdsCategories { get; set; } + + /// + /// Больше или равно дате + /// + public DateTimeOffset? GeDateStart { get; set; } + + /// + /// Меньше или равно дате + /// + public DateTimeOffset? LeDateEnd { get; set; } + + /// + /// Больше или равно глубины забоя + /// + public double? GeDepthStart { get; set; } + + /// + /// Меньше или равно глубины забоя + /// + public double? LeDepthEnd { get; set; } + + /// + /// Запрос на получение операций определенных по телеметрии + /// + public DetectedOperationRequest() + { + IdsCategories = new List(); + } + + /// + /// Запрос на получение операций определенных по телеметрии. Copy + /// + /// + public DetectedOperationRequest(DetectedOperationRequest request) + : base(request) + { + IdsCategories = request.IdsCategories; + GeDateStart = request.GeDateStart; + LeDateEnd = request.LeDateEnd; + GeDepthStart = request.GeDepthStart; + LeDepthEnd = request.LeDepthEnd; } } diff --git a/AsbCloudApp/Requests/RequestBase.cs b/AsbCloudApp/Requests/RequestBase.cs index 2ae96e54..c5d70a68 100644 --- a/AsbCloudApp/Requests/RequestBase.cs +++ b/AsbCloudApp/Requests/RequestBase.cs @@ -23,5 +23,23 @@ namespace AsbCloudApp.Requests /// Указать направление сортировки можно через пробел "asc" или "desc" /// public IEnumerable? SortFields { get; set; } + + /// + /// Базовые параметры запроса + /// + public RequestBase() + { + } + + /// + /// Базовые параметры запроса. Копирующий конструктор + /// + /// + public RequestBase(RequestBase request) + { + Skip = request.Skip; + Take = request.Take; + SortFields = request.SortFields; + } } } diff --git a/AsbCloudApp/Services/IDetectedOperationService.cs b/AsbCloudApp/Services/IDetectedOperationService.cs index e4f8f201..5109fa56 100644 --- a/AsbCloudApp/Services/IDetectedOperationService.cs +++ b/AsbCloudApp/Services/IDetectedOperationService.cs @@ -19,7 +19,7 @@ namespace AsbCloudApp.Services /// /// /// - Task?> GetCategoriesAsync(int? idWell, CancellationToken token); + Task> GetCategoriesAsync(int? idWell, CancellationToken token); /// /// Получить автоматически определенные по телеметрии операции с анализом по бурильщикам @@ -27,7 +27,7 @@ namespace AsbCloudApp.Services /// /// /// - Task GetAsync(DetectedOperationRequest request, CancellationToken token); + Task GetAsync(DetectedOperationByWellRequest request, CancellationToken token); /// /// Получить автоматически определенные по телеметрии операции @@ -35,7 +35,7 @@ namespace AsbCloudApp.Services /// /// /// - Task> GetOperationsAsync(DetectedOperationRequest request, CancellationToken token); + Task> GetOperationsAsync(DetectedOperationByWellRequest request, CancellationToken token); /// /// Удалить операции @@ -43,7 +43,7 @@ namespace AsbCloudApp.Services /// /// /// - Task DeleteAsync(DetectedOperationRequest request, CancellationToken token); + Task DeleteAsync(DetectedOperationByWellRequest request, CancellationToken token); /// /// Статистика по операциям @@ -51,6 +51,6 @@ namespace AsbCloudApp.Services /// /// /// - Task?> GetOperationsStatAsync(DetectedOperationRequest request, CancellationToken token); + Task> GetOperationsStatAsync(DetectedOperationByWellRequest request, CancellationToken token); } } diff --git a/AsbCloudDb/EFExtensionsExceptionHandling.cs b/AsbCloudDb/EFExtensionsExceptionHandling.cs new file mode 100644 index 00000000..77b8fe07 --- /dev/null +++ b/AsbCloudDb/EFExtensionsExceptionHandling.cs @@ -0,0 +1,33 @@ +using AsbCloudDb.Model; +using Microsoft.EntityFrameworkCore; +using Npgsql; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudDb +{ + public static class EFExtensionsExceptionHandling + { + public static async Task SaveChangesWithExceptionHandling(this IAsbCloudDbContext db, CancellationToken token) + { + try + { + var result = await db.SaveChangesAsync(token); + return result; + } + catch (DbUpdateException ex) + { + if (ex.InnerException is PostgresException pgException) + TryConvertPostgresExceptionToValidateException(pgException); + throw; + } + } + + private static void TryConvertPostgresExceptionToValidateException(PostgresException pgException) + { + if (pgException.SqlState == PostgresErrorCodes.ForeignKeyViolation) + throw new ArgumentException(pgException.Message + "\r\n" + pgException.Detail, "dtos"); + } + } +} diff --git a/AsbCloudDb/EFExtentionOrderBy.cs b/AsbCloudDb/EFExtensionsSortBy.cs similarity index 99% rename from AsbCloudDb/EFExtentionOrderBy.cs rename to AsbCloudDb/EFExtensionsSortBy.cs index 0b46c29b..933281c7 100644 --- a/AsbCloudDb/EFExtentionOrderBy.cs +++ b/AsbCloudDb/EFExtensionsSortBy.cs @@ -7,7 +7,7 @@ using System.Reflection; namespace AsbCloudDb { - public static class EFExtentionsSortBy + public static class EFExtensionsSortBy { struct TypeAcessor { diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 5b131299..f99aa054 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -329,6 +329,8 @@ namespace AsbCloudInfrastructure services.AddTransient, ProcessMapPlanService>(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); services.AddSingleton(); diff --git a/AsbCloudInfrastructure/Repository/DetectedOperationRepository.cs b/AsbCloudInfrastructure/Repository/DetectedOperationRepository.cs new file mode 100644 index 00000000..50ec6c9e --- /dev/null +++ b/AsbCloudInfrastructure/Repository/DetectedOperationRepository.cs @@ -0,0 +1,191 @@ +using AsbCloudApp.Data.DetectedOperation; +using AsbCloudApp.Exceptions; +using AsbCloudApp.Repositories; +using AsbCloudApp.Requests; +using AsbCloudApp.Services; +using AsbCloudDb; +using AsbCloudDb.Model; +using Mapster; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudInfrastructure.Repository; + +public class DetectedOperationRepository : IDetectedOperationRepository +{ + private readonly IAsbCloudDbContext db; + private readonly ITelemetryService telemetryService; + + public DetectedOperationRepository( + IAsbCloudDbContext db, + ITelemetryService telemetryService) + { + this.db = db; + this.telemetryService = telemetryService; + } + + public async Task Delete(int idUser, DetectedOperationByTelemetryRequest request, CancellationToken token) + { + var query = BuildQuery(request); + db.Set().RemoveRange(query); + return await db.SaveChangesAsync(token); + } + + public async Task DeleteRange(int idUser, IEnumerable ids, CancellationToken token) + { + var query = db.Set() + .Where(e => ids.Contains( e.Id)); + + db.Set() + .RemoveRange(query); + + return await db.SaveChangesAsync(token); + } + + public async Task> Get(DetectedOperationByTelemetryRequest request, CancellationToken token) + { + var query = BuildQuery(request) + .Include(o => o.OperationCategory); + var entities = await query.ToArrayAsync(token); + var offset = telemetryService.GetTimezone(request.IdTelemetry).Offset; + var dtos = entities.Select(o => Convert(o, offset)); + + return dtos; + } + + public async Task Insert(int? idUser, IEnumerable dtos, CancellationToken token) + { + if(!dtos.Any()) + return 0; + + var entities = dtos.Select(Convert); + var dbset = db.Set(); + foreach(var entity in entities) + { + entity.Id = default; + dbset.Add(entity); + } + + return await db.SaveChangesWithExceptionHandling(token); + } + + public async Task Update(int idUser, 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 dbSet = db.Set(); + + var existingEntitiesCount = await dbSet + .Where(o => ids.Contains(o.Id)) + .CountAsync(token); + + if (ids.Length != existingEntitiesCount) + throw new ArgumentInvalidException(nameof(dtos), "Все записи должны существовать в БД"); + + var entities = dtos + .Select(Convert) + .ToArray(); + + var entries = new Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry[entities.Length]; + for(var i = 0; i < entities.Length; i++) + entries[i] = dbSet.Update(entities[i]); + + var result = await db.SaveChangesWithExceptionHandling(token); + + for (var i = 0; i < entries.Length; i++) + entries[i].State = EntityState.Detached; + + return result; + } + + public async Task UpdateOrInsert(int idUser, IEnumerable dtos, CancellationToken token) + { + var result = 0; + + var itemsToInsert = dtos.Where(e => e.Id == 0); + if (itemsToInsert.Any()) + result += await Insert(idUser, itemsToInsert, token); + + var itemsToUpdate = dtos.Where(e => e.Id != 0); + if (itemsToUpdate.Any()) + result += await Update(idUser, itemsToUpdate, token); + + return result; + } + + private IQueryable BuildQuery(DetectedOperationByTelemetryRequest request) + { + var query = db.Set() + .Where(o => o.IdTelemetry == request.IdTelemetry); + + if (request.IdsCategories.Any()) + query = query.Where(o => request.IdsCategories.Contains(o.IdCategory)); + + if (request.GeDepthStart is not null) + query = query.Where(o => o.DepthStart >= request.GeDepthStart); + + if (request.LeDepthEnd is not null) + query = query.Where(o => o.DepthEnd <= request.LeDepthEnd); + + if (request.GeDateStart is not null) + { + var geDate = request.GeDateStart.Value.ToUniversalTime(); + query = query.Where(o => o.DateStart >= geDate); + } + + if (request.LeDateEnd is not null) + { + var leDate = request.LeDateEnd.Value.ToUniversalTime(); + query = query.Where(o => o.DateEnd <= leDate); + } + + if (request.SortFields?.Any() == true) + { + query = query.SortBy(request.SortFields); + } + else + query = query + .OrderBy(o => o.DateStart) + .ThenBy(o => o.DepthStart); + + if (request.Skip.HasValue) + query = query.Skip((int)request.Skip); + + if (request.Take.HasValue) + query = query.Take((int)request.Take); + + return query; + } + + private static DetectedOperationDto Convert(DetectedOperation entity, TimeSpan offset) + { + var dto = entity.Adapt(); + dto.DateStart = entity.DateStart.ToOffset(offset); + dto.DateEnd = entity.DateEnd.ToOffset(offset); + return dto; + } + + private static DetectedOperation Convert(DetectedOperationDto dto) + { + var entity = dto.Adapt(); + entity.DateStart = dto.DateStart.ToUniversalTime(); + entity.DateEnd = dto.DateEnd.ToUniversalTime(); + return entity; + } +} diff --git a/AsbCloudInfrastructure/Repository/WellOperationCategoryRepository.cs b/AsbCloudInfrastructure/Repository/WellOperationCategoryRepository.cs new file mode 100644 index 00000000..84da5f3d --- /dev/null +++ b/AsbCloudInfrastructure/Repository/WellOperationCategoryRepository.cs @@ -0,0 +1,44 @@ +using AsbCloudApp.Data; +using AsbCloudApp.Repositories; +using AsbCloudDb.Model; +using Mapster; +using Microsoft.Extensions.Caching.Memory; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace AsbCloudInfrastructure.Repository; + +public class WellOperationCategoryRepository : IWellOperationCategoryRepository +{ + private readonly IAsbCloudDbContext db; + private readonly IMemoryCache memoryCache; + + public WellOperationCategoryRepository(IAsbCloudDbContext db, IMemoryCache memoryCache) + { + this.db = db; + this.memoryCache = memoryCache; + } + + public IEnumerable Get(bool includeParents) + { + var categories = memoryCache + .GetOrCreateBasic(db.Set()); + + if (!includeParents) + { + var parentIds = categories + .Select(o => o.IdParent) + .Distinct(); + + categories = categories + .Where(o => !parentIds.Contains(o.Id)); + } + + var result = categories + .OrderBy(o => o.Name) + .Adapt>(); + + return result; + } +} diff --git a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs index c9d3c7fc..1330a282 100644 --- a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs +++ b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs @@ -28,35 +28,20 @@ public class WellOperationRepository : IWellOperationRepository private readonly IAsbCloudDbContext db; private readonly IMemoryCache memoryCache; private readonly IWellService wellService; + private readonly IWellOperationCategoryRepository wellOperationCategoryRepository; - public WellOperationRepository(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService) + public WellOperationRepository(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService, IWellOperationCategoryRepository wellOperationCategoryRepository) { this.db = db; this.memoryCache = memoryCache; this.wellService = wellService; + this.wellOperationCategoryRepository = wellOperationCategoryRepository; } /// public IEnumerable GetCategories(bool includeParents) { - var categories = memoryCache - .GetOrCreateBasic(db.Set()); - - if (!includeParents) - { - var parentIds = categories - .Select(o => o.IdParent) - .Distinct(); - - categories = categories - .Where(o => !parentIds.Contains(o.Id)); - } - - var result = categories - .OrderBy(o => o.Name) - .Adapt>(); - - return result; + return wellOperationCategoryRepository.Get(includeParents); } /// diff --git a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs index e4271c8f..87108fd2 100644 --- a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs +++ b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs @@ -282,7 +282,7 @@ public class DailyReportService : IDailyReportService var leDateEnd = dailyReport.Date.AddDays(1).ToDateTime(TimeOnly.MinValue, DateTimeKind.Unspecified); dailyReport.TimeBalanceBlock.WellOperationSlipsTimeCount = (await detectedOperationService.GetAsync( - new DetectedOperationRequest + new DetectedOperationByWellRequest { IdsCategories = new[] { idWellOperationSlipsTime }, IdWell = dailyReport.IdWell, diff --git a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs index 23a5d20b..bd8fba77 100644 --- a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs +++ b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs @@ -1,5 +1,6 @@ using AsbCloudApp.Data; using AsbCloudApp.Data.DetectedOperation; +using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudDb; @@ -11,274 +12,200 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services.DetectOperations +namespace AsbCloudInfrastructure.Services.DetectOperations; + +public class DetectedOperationService : IDetectedOperationService { + private readonly IDetectedOperationRepository operationRepository; + private readonly IWellOperationCategoryRepository wellOperationCategoryRepository; + private readonly IWellService wellService; + private readonly IRepositoryWellRelated operationValueService; + private readonly IScheduleRepository scheduleService; - public class DetectedOperationService : IDetectedOperationService + public DetectedOperationService( + IDetectedOperationRepository operationRepository, + IWellOperationCategoryRepository wellOperationCategoryRepository, + IWellService wellService, + IRepositoryWellRelated operationValueRepository, + IScheduleRepository scheduleRepository) { - private readonly IAsbCloudDbContext db; - private readonly IWellService wellService; - private readonly IRepositoryWellRelated operationValueService; - private readonly IScheduleRepository scheduleService; + this.operationRepository = operationRepository; + this.wellOperationCategoryRepository = wellOperationCategoryRepository; + this.wellService = wellService; + this.operationValueService = operationValueRepository; + this.scheduleService = scheduleRepository; + } - public DetectedOperationService(IAsbCloudDbContext db, IWellService wellService, - IRepositoryWellRelated operationValueService, IScheduleRepository scheduleService) + public async Task GetAsync(DetectedOperationByWellRequest request, CancellationToken token) + { + var dtos = await GetOperationsAsync(request, token); + if (dtos?.Any() != true) + return new DetectedOperationListDto(); + + var stats = GetOperationsDrillersStat(dtos); + var result = new DetectedOperationListDto { - this.db = db; - this.wellService = wellService; - this.operationValueService = operationValueService; - this.scheduleService = scheduleService; + Operations = dtos, + Stats = stats + }; + return result; + } + + public async Task> GetOperationsAsync(DetectedOperationByWellRequest request, CancellationToken token) + { + var well = await wellService.GetOrDefaultAsync(request.IdWell, token); + if (well?.IdTelemetry is null) + return Enumerable.Empty(); + + var requestByTelemetry = new DetectedOperationByTelemetryRequest(well.IdTelemetry.Value, request); + var data = await operationRepository.Get(requestByTelemetry, token); + + var operationValues = await operationValueService.GetByIdWellAsync(request.IdWell, token); + var schedules = await scheduleService.GetByIdWellAsync(request.IdWell, token); + var dtos = data.Select(o => Convert(o, operationValues, schedules)); + return dtos; + } + + public async Task> GetCategoriesAsync(int? idWell, CancellationToken token) + { + if(idWell is null) + { + return wellOperationCategoryRepository.Get(false); } - - public async Task GetAsync(DetectedOperationRequest request, CancellationToken token) + else { - var dtos = await GetOperationsAsync(request, token); - if (dtos?.Any() != true) - return null; - - var stats = GetOperationsDrillersStat(dtos); - var result = new DetectedOperationListDto - { - Operations = dtos, - Stats = stats - }; - return result; - } - - public async Task> GetOperationsAsync(DetectedOperationRequest request, CancellationToken token) - { - var well = await wellService.GetOrDefaultAsync(request.IdWell, token); + var well = await wellService.GetOrDefaultAsync((int )idWell, token); if (well?.IdTelemetry is null) - return Enumerable.Empty(); + return Enumerable.Empty(); - var query = BuildQuery(well, request).AsNoTracking(); - - var data = await query.ToListAsync(token); - - var operationValues = await operationValueService.GetByIdWellAsync(request.IdWell, token); - var schedules = await scheduleService.GetByIdWellAsync(request.IdWell, token); - var dtos = data.Select(o => Convert(o, well, operationValues, schedules)); - return dtos; - } - - private static IEnumerable GetOperationsDrillersStat(IEnumerable operations) - { - var groups = operations.GroupBy(o => o.Driller); - - var stats = new List(groups.Count()); - foreach (var group in groups) - { - var itemsWithTarget = group.Where(i => i.OperationValue is not null); - var stat = new DetectedOperationDrillersStatDto - { - Driller = group.Key, - AverageValue = group.Sum(e => e.Value) / group.Count(), - Count = group.Count(), - }; - if (itemsWithTarget.Any()) - { - var itemsOutOfTarget = itemsWithTarget.Where(o => !IsTargetOk(o)); - stat.AverageTargetValue = itemsWithTarget.Average(e => e.OperationValue?.TargetValue); - stat.Efficiency = 100d * itemsOutOfTarget.Count() / itemsWithTarget.Count(); - stat.Loss = itemsOutOfTarget.Sum(DeltaToTarget); - } - - stats.Add(stat); - } - return stats; - } - - public async Task?> GetOperationsStatAsync(DetectedOperationRequest request, CancellationToken token) - { - var well = await wellService.GetOrDefaultAsync(request.IdWell, token); - if (well?.IdTelemetry is null || well.Timezone is null) - return null; - - var query = BuildQuery(well, request) - ?.AsNoTracking(); - - if (query is null) - return null; - - var entities = await query - .Select(o => new { - o.IdCategory, - DurationMinutes = (o.DateEnd - o.DateStart).TotalMinutes, - o.Value, - }) - .ToListAsync(token); - - if (!entities.Any()) - return null; - - var operationValues = await operationValueService.GetByIdWellAsync(request.IdWell, token); - var categories = await query - .Select(o => new {o.IdCategory, o.OperationCategory.Name }) - .Distinct() - .ToDictionaryAsync(c=>c.IdCategory, c=>c.Name, token); - - var dtos = entities - .GroupBy(o => o.IdCategory) - .OrderBy(g => g.Key) - .Select(g => new DetectedOperationStatDto{ - IdCategory = g.Key, - Category = categories[g.Key], - Count = g.Count(), - MinutesAverage = g.Average(o => o.DurationMinutes), - MinutesMin = g.Min(o => o.DurationMinutes), - MinutesMax = g.Max(o => o.DurationMinutes), - MinutesTotal = g.Sum(o => o.DurationMinutes), - ValueAverage = g.Average(o => o.Value), - ValueMax = g.Max(o => o.Value), - ValueMin = g.Min(o => o.Value), - }); - - return dtos; - } - - public async Task DeleteAsync(DetectedOperationRequest request, CancellationToken token) - { - var well = await wellService.GetOrDefaultAsync(request.IdWell, token); - if (well?.IdTelemetry is null || well.Timezone is null) - return 0; - - var query = BuildQueryBase(well, request); - - if (query is null) - return 0; - - db.DetectedOperations.RemoveRange(query); - return await db.SaveChangesAsync(token); - } - - private static bool IsTargetOk(DetectedOperationDto op) - { - return (op.IdCategory) switch - { - WellOperationCategory.IdRotor => op.Value > op.OperationValue?.TargetValue, - WellOperationCategory.IdSlide => op.Value > op.OperationValue?.TargetValue, - WellOperationCategory.IdSlipsTime => op.Value > op.OperationValue?.TargetValue, - _ => op.Value > op.OperationValue?.TargetValue, + var request = new DetectedOperationByTelemetryRequest() + { + IdTelemetry = well.IdTelemetry.Value }; - } - private static double DeltaToTarget(DetectedOperationDto op) - { - return (op.IdCategory) switch - { - WellOperationCategory.IdRotor => 0, - WellOperationCategory.IdSlide => 0, - WellOperationCategory.IdSlipsTime => op.Value - op.OperationValue?.TargetValue??0, - _ => 0, - }; - } - - private IQueryable BuildQueryBase(WellDto well, DetectedOperationRequest request) - { - var query = db.Set() - .Where(o => o.IdTelemetry == well.IdTelemetry); - - if (request.IdsTelemetries.Any()) - { - query = query - .Union(db.Set().Where(o => request.IdsTelemetries.Contains(o.IdTelemetry))); - } - - if (request.IdsCategories.Any()) - query = query.Where(o => request.IdsCategories.Contains(o.IdCategory)); - - if (request.GeDateStart is not null) - query = query.Where(o => o.DateStart >= request.GeDateStart.Value.Date.ToUtcDateTimeOffset(well.Timezone.Hours)); - - if (request.LeDateEnd is not null) - query = query.Where(o => o.DateEnd <= request.LeDateEnd.Value.Date.ToUtcDateTimeOffset(well.Timezone.Hours)); - - if (request.GeDepth is not null) - query = query.Where(o => o.DepthStart >= request.GeDepth); - - if (request.LeDepth is not null) - query = query.Where(o => o.DepthEnd <= request.LeDepth); - - if (request.IdTelemetryUser is not null) - query = query.Where(o => o.IdUsersAtStart == request.IdTelemetryUser); - - return query; - } - - private IQueryable BuildQuery(WellDto well, DetectedOperationRequest request) - { - IQueryable query = BuildQueryBase(well, request) - .Include(o => o.OperationCategory); - - if (request.SortFields?.Any() == true) - { - query = query.SortBy(request.SortFields); - } - else - query = query - .OrderBy(o => o.DateStart) - .ThenBy(o => o.DepthStart); - - if (request.Skip.HasValue) - query = query.Skip((int)request.Skip); - - if (request.Take.HasValue) - query = query.Take((int)request.Take); - - return query; - } - - private static DetectedOperationDto Convert(DetectedOperation operation, WellDto well, IEnumerable operationValues, IEnumerable schedules) - { - var dto = operation.Adapt(); - dto.IdWell = well.Id; - var dateStart = operation.DateStart.ToRemoteDateTime(well.Timezone.Hours); - dto.DateStart = dateStart; - dto.DateEnd = operation.DateEnd.ToRemoteDateTime(well.Timezone.Hours); - dto.OperationValue = operationValues.FirstOrDefault(v => v.IdOperationCategory == dto.IdCategory - && v.DepthStart <= dto.DepthStart - && v.DepthEnd > dto.DepthStart); - - var timeStart = new TimeDto(dateStart); - var driller = schedules.FirstOrDefault(s => - s.DrillStart <= dateStart && - s.DrillEnd > dateStart && ( - s.ShiftStart > s.ShiftEnd - ) ^ (s.ShiftStart <= timeStart && - s.ShiftEnd > timeStart - )) - ?.Driller; - dto.Driller = driller; - return dto; - } - - public async Task?> GetCategoriesAsync(int? idWell, CancellationToken token) - { - IQueryable query; - if(idWell is null) - { - query = db.WellOperationCategories; - } - else - { - var well = await wellService.GetOrDefaultAsync((int )idWell, token); - if (well?.IdTelemetry is null) - return null; - var idTelemetry = (int)well.IdTelemetry; - query = db.DetectedOperations - .Include(o => o.OperationCategory) - .Where(o => o.IdTelemetry == idTelemetry) - .Select(o => o.OperationCategory) - .Distinct(); - } - - var result = await query - .Where(c => c.Id < 1000) - .AsNoTracking() - .Select(c => c.Adapt()) - .ToArrayAsync(token); - return result; + var operations = await operationRepository.Get(request, token); + var categories = operations + .Select(o => o.OperationCategory) + .Distinct(); + return categories; } } + public async Task> GetOperationsStatAsync(DetectedOperationByWellRequest request, CancellationToken token) + { + var well = await wellService.GetOrDefaultAsync(request.IdWell, token); + if (well?.IdTelemetry is null || well.Timezone is null) + return Enumerable.Empty(); + + var requestByTelemetry = new DetectedOperationByTelemetryRequest(well.IdTelemetry.Value, request); + + var operations = await operationRepository.Get(requestByTelemetry, token); + + if (!operations.Any()) + return Enumerable.Empty(); + + var operationValues = await operationValueService.GetByIdWellAsync(request.IdWell, token); + + var dtos = operations + .GroupBy(o => (o.IdCategory, o.OperationCategory.Name)) + .OrderBy(g => g.Key) + .Select(g => new DetectedOperationStatDto + { + IdCategory = g.Key.IdCategory, + Category = g.Key.Name, + Count = g.Count(), + MinutesAverage = g.Average(o => o.DurationMinutes), + MinutesMin = g.Min(o => o.DurationMinutes), + MinutesMax = g.Max(o => o.DurationMinutes), + MinutesTotal = g.Sum(o => o.DurationMinutes), + ValueAverage = g.Average(o => o.Value), + ValueMax = g.Max(o => o.Value), + ValueMin = g.Min(o => o.Value), + }); + + return dtos; + } + + public async Task DeleteAsync(DetectedOperationByWellRequest request, CancellationToken token) + { + var well = await wellService.GetOrDefaultAsync(request.IdWell, token); + if (well?.IdTelemetry is null || well.Timezone is null) + return 0; + + var requestByTelemetry = new DetectedOperationByTelemetryRequest(well.IdTelemetry.Value, request); + var result = await operationRepository.Delete(-1, requestByTelemetry, token); + return result; + } + + private static IEnumerable GetOperationsDrillersStat(IEnumerable operations) + { + var groups = operations.GroupBy(o => o.Driller); + + var stats = new List(groups.Count()); + foreach (var group in groups) + { + var itemsWithTarget = group.Where(i => i.OperationValue is not null); + var stat = new DetectedOperationDrillersStatDto + { + Driller = group.Key, + AverageValue = group.Sum(e => e.Value) / group.Count(), + Count = group.Count(), + }; + if (itemsWithTarget.Any()) + { + var itemsOutOfTarget = itemsWithTarget.Where(o => !IsTargetOk(o)); + stat.AverageTargetValue = itemsWithTarget.Average(e => e.OperationValue?.TargetValue); + stat.Efficiency = 100d * itemsOutOfTarget.Count() / itemsWithTarget.Count(); + stat.Loss = itemsOutOfTarget.Sum(DeltaToTarget); + } + + stats.Add(stat); + } + return stats; + } + + private static bool IsTargetOk(DetectedOperationWithDrillerDto op) + { + return (op.IdCategory) switch + { + WellOperationCategory.IdRotor => op.Value > op.OperationValue?.TargetValue, + WellOperationCategory.IdSlide => op.Value > op.OperationValue?.TargetValue, + WellOperationCategory.IdSlipsTime => op.Value > op.OperationValue?.TargetValue, + _ => op.Value > op.OperationValue?.TargetValue, + }; + } + + private static double DeltaToTarget(DetectedOperationWithDrillerDto op) + { + return (op.IdCategory) switch + { + WellOperationCategory.IdRotor => 0, + WellOperationCategory.IdSlide => 0, + WellOperationCategory.IdSlipsTime => op.Value - op.OperationValue?.TargetValue??0, + _ => 0, + }; + } + + + private static DetectedOperationWithDrillerDto Convert(DetectedOperationDto operation, IEnumerable operationValues, IEnumerable schedules) + { + var dto = operation.Adapt(); + dto.OperationValue = operationValues.FirstOrDefault(v => v.IdOperationCategory == dto.IdCategory + && v.DepthStart <= dto.DepthStart + && v.DepthEnd > dto.DepthStart); + + var dateStart = dto.DateStart; + var timeStart = new TimeDto(dateStart); + var driller = schedules.FirstOrDefault(s => + s.DrillStart <= dateStart && + s.DrillEnd > dateStart && ( + s.ShiftStart > s.ShiftEnd + ) ^ (s.ShiftStart <= timeStart && + s.ShiftEnd > timeStart + )) + ?.Driller; + dto.Driller = driller; + + return dto; + } } diff --git a/AsbCloudInfrastructure/Services/Subsystems/SubsystemService.cs b/AsbCloudInfrastructure/Services/Subsystems/SubsystemService.cs index fd27efdf..93c5ab2f 100644 --- a/AsbCloudInfrastructure/Services/Subsystems/SubsystemService.cs +++ b/AsbCloudInfrastructure/Services/Subsystems/SubsystemService.cs @@ -45,17 +45,16 @@ internal class SubsystemService : ISubsystemService if(!well.IdTelemetry.HasValue) return Enumerable.Empty(); - var detectedOperationSummaryRequest = new DetectedOperationRequest - { + var detectedOperationSummaryRequest = new DetectedOperationByWellRequest + { IdWell = request.IdWell, - IdsTelemetries = new[] { well.IdTelemetry.Value }, IdsCategories = WellOperationCategory.MechanicalDrillingSubIds, GeDateStart = request.GeDate, LeDateEnd = request.LeDate, - GeDepth = request.GeDepth, - LeDepth = request.LeDepth, + GeDepthStart = request.GeDepth, + LeDepthEnd = request.LeDepth, }; var operations = await detectedOperationService.GetOperationsAsync(detectedOperationSummaryRequest, @@ -78,7 +77,7 @@ internal class SubsystemService : ISubsystemService return result; } - private async Task> CalcStatAsync(IEnumerable operations, CancellationToken token) + private async Task> CalcStatAsync(IEnumerable operations, CancellationToken token) { if (!subsystems.Any()) subsystems = (await subsystemRepository.GetAllAsync(token)).ToDictionary(s => s.Id, s => s); @@ -92,7 +91,7 @@ internal class SubsystemService : ISubsystemService return stat; } - private SubsystemStatDto CalcOscillationStat(IEnumerable operations) + private SubsystemStatDto CalcOscillationStat(IEnumerable operations) { operations = operations.Where(o => o.IdCategory == WellOperationCategory.IdSlide); @@ -114,7 +113,7 @@ internal class SubsystemService : ISubsystemService return oscillationStat; } - private IEnumerable CalcApdStat(IEnumerable operations) + private IEnumerable CalcApdStat(IEnumerable operations) { var apdRotorAndSlide = operations .Where(o => WellOperationCategory.MechanicalDrillingSubIds.Contains(o.IdCategory)) @@ -169,7 +168,7 @@ internal class SubsystemService : ISubsystemService } private static (double SumDepthInterval, double UsedTimeHours, int Count) AggregateOperations(int idSubsystem, - IEnumerable operations) => + IEnumerable operations) => idSubsystem switch { IdSubsystemAPDRotor => CalcOperationsByEnableSubsystems(operations, EnabledSubsystemsFlags.AutoRotor), @@ -180,7 +179,7 @@ internal class SubsystemService : ISubsystemService }; private static (double SumDepthInterval, double UsedTimeHours, int OperationCount) CalcOperationsByEnableSubsystems( - IEnumerable operations, + IEnumerable operations, EnabledSubsystemsFlags enabledSubsystems) { var filtered = operations.Where(o => enabledSubsystems.HasEnabledSubsystems(o.EnabledSubsystems)); @@ -215,7 +214,7 @@ internal class SubsystemService : ISubsystemService var leDateUtc = leDate?.ToUtcDateTimeOffset(hoursOffset); - var request = new DetectedOperationRequest + var request = new DetectedOperationByWellRequest { IdWell = well.Id, IdsCategories = WellOperationCategory.MechanicalDrillingSubIds, diff --git a/AsbCloudInfrastructure/Services/WellService.cs b/AsbCloudInfrastructure/Services/WellService.cs index befa8851..4d6ec10a 100644 --- a/AsbCloudInfrastructure/Services/WellService.cs +++ b/AsbCloudInfrastructure/Services/WellService.cs @@ -36,13 +36,18 @@ namespace AsbCloudInfrastructure.Services .ThenInclude(r => r.Company) .AsNoTracking(); - public WellService(IAsbCloudDbContext db, IMemoryCache memoryCache, ITelemetryService telemetryService, ITimezoneService timezoneService, WellInfoService wellInfoService) + 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; - this.wellOperationRepository = new WellOperationRepository(db, memoryCache, this); + this.wellOperationRepository = new WellOperationRepository(db, memoryCache, this, wellOperationCategoryRepository); companyTypesService = new CrudCacheRepositoryBase(dbContext, memoryCache); } diff --git a/AsbCloudWebApi/AsbCloudWebApi.csproj b/AsbCloudWebApi/AsbCloudWebApi.csproj index d0485b9a..6b29ff20 100644 --- a/AsbCloudWebApi/AsbCloudWebApi.csproj +++ b/AsbCloudWebApi/AsbCloudWebApi.csproj @@ -10,6 +10,7 @@ + all diff --git a/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs b/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs index 02f2d4cb..1f487773 100644 --- a/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs +++ b/AsbCloudWebApi/Controllers/SAUB/DetectedOperationController.cs @@ -57,7 +57,7 @@ namespace AsbCloudWebApi.Controllers.SAUB [HttpGet] [ProducesResponseType(typeof(DetectedOperationListDto), (int)System.Net.HttpStatusCode.OK)] public async Task GetAsync( - [FromQuery] DetectedOperationRequest request, + [FromQuery] DetectedOperationByWellRequest request, CancellationToken token) { if (!await UserHasAccessToWellAsync(request.IdWell, token)) @@ -76,7 +76,7 @@ namespace AsbCloudWebApi.Controllers.SAUB [HttpGet("stat")] [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] public async Task GetStatAsync( - [FromQuery] DetectedOperationRequest request, + [FromQuery] DetectedOperationByWellRequest request, CancellationToken token) { if (!await UserHasAccessToWellAsync(request.IdWell, token)) @@ -98,7 +98,7 @@ namespace AsbCloudWebApi.Controllers.SAUB [Permission] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] public async Task DeleteAsync( - [FromQuery] DetectedOperationRequest request, + [FromQuery] DetectedOperationByWellRequest request, CancellationToken token) { if (!await UserHasAccessToWellAsync(request.IdWell, token))