Add DetectedOperation repository

This commit is contained in:
ngfrolov 2024-02-08 11:38:25 +05:00
parent b263f7973b
commit b7dcf313a2
Signed by untrusted user who does not match committer: ng.frolov
GPG Key ID: E99907A0357B29A7
21 changed files with 708 additions and 439 deletions

View File

@ -1,100 +1,85 @@
using System; using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace AsbCloudApp.Data.DetectedOperation namespace AsbCloudApp.Data.DetectedOperation;
/// <summary>
/// Автоматически определенная операция
/// </summary>
public class DetectedOperationDto: IId
{ {
/// <inheritdoc/>
[Required]
public int Id { get; set; }
/// <summary> /// <summary>
/// Автоматически определяемая операция /// Id телеметрии
/// </summary> /// </summary>
public class DetectedOperationDto : IId, IWellRelated [Required]
{ public int IdTelemetry { get; set; }
/// <inheritdoc/>
[Required]
public int Id { get; set; }
/// <inheritdoc/> /// <summary>
[Required] /// Id названия/описания операции
public int IdWell { get; set; } /// </summary>
[Required]
public int IdCategory { get; set; }
/// <summary> /// <summary>
/// Id телеметрии /// Id пользователя панели на момент начала операции
/// </summary> /// </summary>
[Required] [Required]
public int IdTelemetry { get; set; } public int IdUserAtStart { get; set; }
/// <summary> /// <summary>
/// Id названия/описания операции /// Дата завершения операции в часовом поясе скважины
/// </summary> /// </summary>
[Required] [Required]
public int IdCategory { get; set; } public DateTimeOffset DateEnd { get; set; }
/// <summary> /// <summary>
/// Id пользователя панели /// Дата начала операции в часовом поясе скважины
/// </summary> /// </summary>
[Required] [Required]
public int IdUsersAtStart { get; set; } public DateTimeOffset DateStart { get; set; }
/// <summary> /// <summary>
/// Дата начала операции в часовом поясе скважины /// глубина на завершения операции, м
/// </summary> /// </summary>
[Required] [Required]
public DateTime DateStart { get; set; } public double DepthEnd { get; set; }
/// <summary> /// <summary>
/// Дата завершения операции в часовом поясе скважины /// глубина на начало операции, м
/// </summary> /// </summary>
[Required] [Required]
public DateTime DateEnd { get; set; } public double DepthStart { get; set; }
/// <summary> /// <summary>
/// Продолжительность операции в минутах /// Продолжительность операции в минутах
/// </summary> /// </summary>
[Required] [Required]
public double DurationMinutes => (DateEnd - DateStart).TotalMinutes; public double DurationMinutes => (DateEnd - DateStart).TotalMinutes;
/// <summary> /// <summary>
/// глубина на начало операции, м /// Флаг включенной подсистемы
/// </summary> /// </summary>
[Required] [Required]
public double DepthStart { get; set; } public int EnabledSubsystems { get; set; }
/// <summary> /// <summary>
/// глубина на завершения операции, м /// название/описание операции
/// </summary> /// </summary>
[Required] [Required]
public double DepthEnd { get; set; } public WellOperationCategoryDto OperationCategory { get; set; } = null!;
/// <summary> /// <summary>
/// название/описание операции /// Пользователь панели оператора
/// </summary> /// </summary>
[Required] public string? TelemetryUserName { get; set; }
public WellOperationCategoryDto OperationCategory { get; set; } = null!;
/// <summary> /// <summary>
/// Пользователь панели оператора /// Ключевой параметр операции
/// </summary> /// </summary>
public string? TelemetryUserName { get; set; } [Required]
public double Value { get; set; }
/// <summary> }
/// Бурильщик
/// </summary>
public DrillerDto? Driller { get; set; }
/// <summary>
/// Целевые/нормативные показатели
/// </summary>
public OperationValueDto? OperationValue { get; set; }
/// <summary>
/// Ключевой параметр операции
/// </summary>
[Required]
public double Value { get; set; }
/// <summary>
/// Флаг включенной подсистемы
/// </summary>
[Required]
public int EnabledSubsystems { get; set; }
}
}

View File

@ -13,7 +13,7 @@ namespace AsbCloudApp.Data.DetectedOperation
/// Список всех операций /// Список всех операций
/// </summary> /// </summary>
[Required] [Required]
public IEnumerable<DetectedOperationDto> Operations { get; set; } = Enumerable.Empty<DetectedOperationDto>(); public IEnumerable<DetectedOperationWithDrillerDto> Operations { get; set; } = Enumerable.Empty<DetectedOperationWithDrillerDto>();
/// <summary> /// <summary>
/// Статистика по бурильщикам /// Статистика по бурильщикам

View File

@ -1,3 +1,5 @@
using System;
namespace AsbCloudApp.Data namespace AsbCloudApp.Data
{ {
/// <summary> /// <summary>
@ -20,6 +22,11 @@ namespace AsbCloudApp.Data
/// </summary> /// </summary>
public bool IsOverride { get; set; } public bool IsOverride { get; set; }
/// <summary>
/// Ñìåùåíèå ÷àñîâîãî ïîÿñà
/// </summary>
public TimeSpan Offset { get => TimeSpan.FromHours(Hours); }
/// <inheritdoc/> /// <inheritdoc/>
public override bool Equals(object? obj) public override bool Equals(object? obj)
{ {

View File

@ -86,6 +86,14 @@ namespace AsbCloudApp.Data
second = fullDate.Second; second = fullDate.Second;
} }
/// <inheritdoc/>
public TimeDto(DateTimeOffset fullDate)
{
hour = fullDate.Hour;
minute = fullDate.Minute;
second = fullDate.Second;
}
/// <summary> /// <summary>
/// Makes System.TimeOnly /// Makes System.TimeOnly
/// </summary> /// </summary>

View File

@ -7,7 +7,7 @@ using System.Threading;
namespace AsbCloudApp.Repositories; namespace AsbCloudApp.Repositories;
/// <summary> /// <summary>
/// Таблица автоопределенных операций /// Таблица автоматически определенных операций
/// </summary> /// </summary>
public interface IDetectedOperationRepository public interface IDetectedOperationRepository
{ {
@ -18,15 +18,15 @@ public interface IDetectedOperationRepository
/// <param name="dtos"></param> /// <param name="dtos"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<int> Insert(int idUser, IEnumerable<DetectedOperationDto> dtos, CancellationToken token); Task<int> Insert(int? idUser, IEnumerable<DetectedOperationDto> dtos, CancellationToken token);
/// <summary> /// <summary>
/// Получить автоматически определенные по телеметрии операции /// Получить автоматически определенные операции по телеметрии
/// </summary> /// </summary>
/// <param name="request"></param> /// <param name="request"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<IEnumerable<DetectedOperationDto>> Get(DetectedOperationRequest request, CancellationToken token); Task<IEnumerable<DetectedOperationDto>> Get(DetectedOperationByTelemetryRequest request, CancellationToken token);
/// <summary> /// <summary>
/// Редактирование записей /// Редактирование записей
@ -49,10 +49,11 @@ public interface IDetectedOperationRepository
/// <summary> /// <summary>
/// Удалить операции /// Удалить операции
/// </summary> /// </summary>
/// <param name="idUser"></param>
/// <param name="request"></param> /// <param name="request"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<int> DeleteAsync(int idUser, DetectedOperationRequest request, CancellationToken token); Task<int> Delete(int idUser, DetectedOperationByTelemetryRequest request, CancellationToken token);
/// <summary> /// <summary>
/// Удаление записей /// Удаление записей

View File

@ -0,0 +1,17 @@
using AsbCloudApp.Data;
using System.Collections.Generic;
namespace AsbCloudApp.Repositories
{
/// <summary>
/// сервис операций по скважине
/// </summary>
public interface IWellOperationCategoryRepository
{
/// <summary>
/// список названий операций
/// </summary>
/// <returns></returns>
IEnumerable<WellOperationCategoryDto> Get(bool includeParents);
}
}

View File

@ -1,68 +1,114 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq;
namespace AsbCloudApp.Requests namespace AsbCloudApp.Requests;
/// <summary>
/// Запрос на получение операций определенных по телеметрии
/// </summary>
public class DetectedOperationByTelemetryRequest : DetectedOperationRequest
{ {
/// <summary> /// <summary>
/// /// id телеметрии
/// </summary> /// </summary>
public class DetectedOperationByWellRequest : DetectedOperationRequest [Required]
{ public int IdTelemetry { get; set; }
/// <summary>
/// категория операций
/// </summary>
[Required]
public int IdWell { get; set; }
}
/// <summary> /// <summary>
/// /// Запрос на получение операций определенных по id телеметрии
/// </summary> /// </summary>
public class DetectedOperationByTelemetryRequest : DetectedOperationRequest public DetectedOperationByTelemetryRequest()
{ {}
/// <summary>
/// Список id телеметрий
/// пустой список - нет фильтрации
/// </summary>
public IEnumerable<int> IdsTelemetries { get; set; } = Array.Empty<int>();
}
/// <summary> /// <summary>
/// Параметры запроса на получение операций определенных по телеметрии /// Запрос на получение операций определенных по id телеметрии. Copy
/// </summary> /// </summary>
public class DetectedOperationRequest : RequestBase /// <param name="idTelemetry"></param>
/// <param name="request"></param>
public DetectedOperationByTelemetryRequest(int idTelemetry, DetectedOperationRequest request)
:base(request)
{ {
/// <summary> IdTelemetry = idTelemetry;
/// категории операций }
/// </summary> }
public IEnumerable<int> IdsCategories { get; set; } = Array.Empty<int>();
/// <summary>
/// <summary> /// Запрос на получение операций определенных по id скважины
/// Больше или равно дате /// </summary>
/// </summary> public class DetectedOperationByWellRequest : DetectedOperationRequest
public DateTimeOffset? GeDateStart { get; set; } {
/// <summary>
/// <summary> /// id скважины
/// Меньше или равно дате /// </summary>
/// </summary> [Required]
public DateTimeOffset? LeDateEnd { get; set; } public int IdWell { get; set; }
/// <summary> /// <summary>
/// Больше или равно глубины забоя /// Запрос на получение операций определенных по id скважины
/// </summary> /// </summary>
public double? GeDepth { get; set; } public DetectedOperationByWellRequest()
{}
/// <summary>
/// Меньше или равно глубины забоя /// <summary>
/// </summary> /// Запрос на получение операций определенных по id скважины. Copy
public double? LeDepth { get; set; } /// </summary>
public DetectedOperationByWellRequest(int idWell, DetectedOperationRequest request)
/// <summary> : base(request)
/// Фильтр по пользователю панели {
/// </summary> IdWell = idWell;
public int? IdTelemetryUser { get; set; } }
}
/// <summary>
/// Запрос на получение операций определенных по телеметрии
/// </summary>
public class DetectedOperationRequest : RequestBase
{
/// <summary>
/// категории операций
/// </summary>
public IEnumerable<int> IdsCategories { get; set; }
/// <summary>
/// Больше или равно дате
/// </summary>
public DateTimeOffset? GeDateStart { get; set; }
/// <summary>
/// Меньше или равно дате
/// </summary>
public DateTimeOffset? LeDateEnd { get; set; }
/// <summary>
/// Больше или равно глубины забоя
/// </summary>
public double? GeDepthStart { get; set; }
/// <summary>
/// Меньше или равно глубины забоя
/// </summary>
public double? LeDepthEnd { get; set; }
/// <summary>
/// Запрос на получение операций определенных по телеметрии
/// </summary>
public DetectedOperationRequest()
{
IdsCategories = new List<int>();
}
/// <summary>
/// Запрос на получение операций определенных по телеметрии. Copy
/// </summary>
/// <param name="request"></param>
public DetectedOperationRequest(DetectedOperationRequest request)
: base(request)
{
IdsCategories = request.IdsCategories;
GeDateStart = request.GeDateStart;
LeDateEnd = request.LeDateEnd;
GeDepthStart = request.GeDepthStart;
LeDepthEnd = request.LeDepthEnd;
} }
} }

View File

@ -23,5 +23,23 @@ namespace AsbCloudApp.Requests
/// Указать направление сортировки можно через пробел "asc" или "desc" /// Указать направление сортировки можно через пробел "asc" или "desc"
/// </summary> /// </summary>
public IEnumerable<string>? SortFields { get; set; } public IEnumerable<string>? SortFields { get; set; }
/// <summary>
/// Базовые параметры запроса
/// </summary>
public RequestBase()
{
}
/// <summary>
/// Базовые параметры запроса. Копирующий конструктор
/// </summary>
/// <param name="request"></param>
public RequestBase(RequestBase request)
{
Skip = request.Skip;
Take = request.Take;
SortFields = request.SortFields;
}
} }
} }

View File

@ -19,7 +19,7 @@ namespace AsbCloudApp.Services
/// <param name="idWell"></param> /// <param name="idWell"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<IEnumerable<WellOperationCategoryDto>?> GetCategoriesAsync(int? idWell, CancellationToken token); Task<IEnumerable<WellOperationCategoryDto>> GetCategoriesAsync(int? idWell, CancellationToken token);
/// <summary> /// <summary>
/// Получить автоматически определенные по телеметрии операции с анализом по бурильщикам /// Получить автоматически определенные по телеметрии операции с анализом по бурильщикам
@ -27,7 +27,7 @@ namespace AsbCloudApp.Services
/// <param name="request"></param> /// <param name="request"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<DetectedOperationListDto?> GetAsync(DetectedOperationRequest request, CancellationToken token); Task<DetectedOperationListDto> GetAsync(DetectedOperationByWellRequest request, CancellationToken token);
/// <summary> /// <summary>
/// Получить автоматически определенные по телеметрии операции /// Получить автоматически определенные по телеметрии операции
@ -35,7 +35,7 @@ namespace AsbCloudApp.Services
/// <param name="request"></param> /// <param name="request"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<IEnumerable<DetectedOperationDto>> GetOperationsAsync(DetectedOperationRequest request, CancellationToken token); Task<IEnumerable<DetectedOperationWithDrillerDto>> GetOperationsAsync(DetectedOperationByWellRequest request, CancellationToken token);
/// <summary> /// <summary>
/// Удалить операции /// Удалить операции
@ -43,7 +43,7 @@ namespace AsbCloudApp.Services
/// <param name="request"></param> /// <param name="request"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<int> DeleteAsync(DetectedOperationRequest request, CancellationToken token); Task<int> DeleteAsync(DetectedOperationByWellRequest request, CancellationToken token);
/// <summary> /// <summary>
/// Статистика по операциям /// Статистика по операциям
@ -51,6 +51,6 @@ namespace AsbCloudApp.Services
/// <param name="request"></param> /// <param name="request"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<IEnumerable<DetectedOperationStatDto>?> GetOperationsStatAsync(DetectedOperationRequest request, CancellationToken token); Task<IEnumerable<DetectedOperationStatDto>> GetOperationsStatAsync(DetectedOperationByWellRequest request, CancellationToken token);
} }
} }

View File

@ -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<int> 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");
}
}
}

View File

@ -7,7 +7,7 @@ using System.Reflection;
namespace AsbCloudDb namespace AsbCloudDb
{ {
public static class EFExtentionsSortBy public static class EFExtensionsSortBy
{ {
struct TypeAcessor struct TypeAcessor
{ {

View File

@ -329,6 +329,8 @@ namespace AsbCloudInfrastructure
services.AddTransient<IProcessMapPlanService<ProcessMapPlanWellReamDto>, ProcessMapPlanService<ProcessMapPlanWellReamDto>>(); services.AddTransient<IProcessMapPlanService<ProcessMapPlanWellReamDto>, ProcessMapPlanService<ProcessMapPlanWellReamDto>>();
services.AddTransient<IWellSectionPlanRepository, WellSectionPlanRepository>(); services.AddTransient<IWellSectionPlanRepository, WellSectionPlanRepository>();
services.AddTransient<IWellOperationCategoryRepository, WellOperationCategoryRepository>();
services.AddTransient<IDetectedOperationRepository, DetectedOperationRepository>();
services.AddSingleton<ParserServiceFactory>(); services.AddSingleton<ParserServiceFactory>();

View File

@ -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<int> Delete(int idUser, DetectedOperationByTelemetryRequest request, CancellationToken token)
{
var query = BuildQuery(request);
db.Set<DetectedOperation>().RemoveRange(query);
return await db.SaveChangesAsync(token);
}
public async Task<int> DeleteRange(int idUser, IEnumerable<int> ids, CancellationToken token)
{
var query = db.Set<DetectedOperation>()
.Where(e => ids.Contains( e.Id));
db.Set<DetectedOperation>()
.RemoveRange(query);
return await db.SaveChangesAsync(token);
}
public async Task<IEnumerable<DetectedOperationDto>> 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<int> Insert(int? idUser, IEnumerable<DetectedOperationDto> dtos, CancellationToken token)
{
if(!dtos.Any())
return 0;
var entities = dtos.Select(Convert);
var dbset = db.Set<DetectedOperation>();
foreach(var entity in entities)
{
entity.Id = default;
dbset.Add(entity);
}
return await db.SaveChangesWithExceptionHandling(token);
}
public async Task<int> Update(int idUser, IEnumerable<DetectedOperationDto> 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<DetectedOperation>();
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<DetectedOperation>[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<int> UpdateOrInsert(int idUser, IEnumerable<DetectedOperationDto> 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<DetectedOperation> BuildQuery(DetectedOperationByTelemetryRequest request)
{
var query = db.Set<DetectedOperation>()
.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<DetectedOperationDto>();
dto.DateStart = entity.DateStart.ToOffset(offset);
dto.DateEnd = entity.DateEnd.ToOffset(offset);
return dto;
}
private static DetectedOperation Convert(DetectedOperationDto dto)
{
var entity = dto.Adapt<DetectedOperation>();
entity.DateStart = dto.DateStart.ToUniversalTime();
entity.DateEnd = dto.DateEnd.ToUniversalTime();
return entity;
}
}

View File

@ -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<WellOperationCategoryDto> Get(bool includeParents)
{
var categories = memoryCache
.GetOrCreateBasic(db.Set<WellOperationCategory>());
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<IEnumerable<WellOperationCategoryDto>>();
return result;
}
}

View File

@ -28,35 +28,20 @@ public class WellOperationRepository : IWellOperationRepository
private readonly IAsbCloudDbContext db; private readonly IAsbCloudDbContext db;
private readonly IMemoryCache memoryCache; private readonly IMemoryCache memoryCache;
private readonly IWellService wellService; 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.db = db;
this.memoryCache = memoryCache; this.memoryCache = memoryCache;
this.wellService = wellService; this.wellService = wellService;
this.wellOperationCategoryRepository = wellOperationCategoryRepository;
} }
/// <inheritdoc/> /// <inheritdoc/>
public IEnumerable<WellOperationCategoryDto> GetCategories(bool includeParents) public IEnumerable<WellOperationCategoryDto> GetCategories(bool includeParents)
{ {
var categories = memoryCache return wellOperationCategoryRepository.Get(includeParents);
.GetOrCreateBasic(db.Set<WellOperationCategory>());
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<IEnumerable<WellOperationCategoryDto>>();
return result;
} }
/// <inheritdoc/> /// <inheritdoc/>

View File

@ -282,7 +282,7 @@ public class DailyReportService : IDailyReportService
var leDateEnd = dailyReport.Date.AddDays(1).ToDateTime(TimeOnly.MinValue, DateTimeKind.Unspecified); var leDateEnd = dailyReport.Date.AddDays(1).ToDateTime(TimeOnly.MinValue, DateTimeKind.Unspecified);
dailyReport.TimeBalanceBlock.WellOperationSlipsTimeCount = (await detectedOperationService.GetAsync( dailyReport.TimeBalanceBlock.WellOperationSlipsTimeCount = (await detectedOperationService.GetAsync(
new DetectedOperationRequest new DetectedOperationByWellRequest
{ {
IdsCategories = new[] { idWellOperationSlipsTime }, IdsCategories = new[] { idWellOperationSlipsTime },
IdWell = dailyReport.IdWell, IdWell = dailyReport.IdWell,

View File

@ -1,5 +1,6 @@
using AsbCloudApp.Data; using AsbCloudApp.Data;
using AsbCloudApp.Data.DetectedOperation; using AsbCloudApp.Data.DetectedOperation;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests; using AsbCloudApp.Requests;
using AsbCloudApp.Services; using AsbCloudApp.Services;
using AsbCloudDb; using AsbCloudDb;
@ -11,274 +12,200 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; 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<OperationValueDto> operationValueService;
private readonly IScheduleRepository scheduleService;
public class DetectedOperationService : IDetectedOperationService public DetectedOperationService(
IDetectedOperationRepository operationRepository,
IWellOperationCategoryRepository wellOperationCategoryRepository,
IWellService wellService,
IRepositoryWellRelated<OperationValueDto> operationValueRepository,
IScheduleRepository scheduleRepository)
{ {
private readonly IAsbCloudDbContext db; this.operationRepository = operationRepository;
private readonly IWellService wellService; this.wellOperationCategoryRepository = wellOperationCategoryRepository;
private readonly IRepositoryWellRelated<OperationValueDto> operationValueService; this.wellService = wellService;
private readonly IScheduleRepository scheduleService; this.operationValueService = operationValueRepository;
this.scheduleService = scheduleRepository;
}
public DetectedOperationService(IAsbCloudDbContext db, IWellService wellService, public async Task<DetectedOperationListDto> GetAsync(DetectedOperationByWellRequest request, CancellationToken token)
IRepositoryWellRelated<OperationValueDto> operationValueService, IScheduleRepository scheduleService) {
var dtos = await GetOperationsAsync(request, token);
if (dtos?.Any() != true)
return new DetectedOperationListDto();
var stats = GetOperationsDrillersStat(dtos);
var result = new DetectedOperationListDto
{ {
this.db = db; Operations = dtos,
this.wellService = wellService; Stats = stats
this.operationValueService = operationValueService; };
this.scheduleService = scheduleService; return result;
}
public async Task<IEnumerable<DetectedOperationWithDrillerDto>> GetOperationsAsync(DetectedOperationByWellRequest request, CancellationToken token)
{
var well = await wellService.GetOrDefaultAsync(request.IdWell, token);
if (well?.IdTelemetry is null)
return Enumerable.Empty<DetectedOperationWithDrillerDto>();
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<IEnumerable<WellOperationCategoryDto>> GetCategoriesAsync(int? idWell, CancellationToken token)
{
if(idWell is null)
{
return wellOperationCategoryRepository.Get(false);
} }
else
public async Task<DetectedOperationListDto?> GetAsync(DetectedOperationRequest request, CancellationToken token)
{ {
var dtos = await GetOperationsAsync(request, token); var well = await wellService.GetOrDefaultAsync((int )idWell, token);
if (dtos?.Any() != true)
return null;
var stats = GetOperationsDrillersStat(dtos);
var result = new DetectedOperationListDto
{
Operations = dtos,
Stats = stats
};
return result;
}
public async Task<IEnumerable<DetectedOperationDto>> GetOperationsAsync(DetectedOperationRequest request, CancellationToken token)
{
var well = await wellService.GetOrDefaultAsync(request.IdWell, token);
if (well?.IdTelemetry is null) if (well?.IdTelemetry is null)
return Enumerable.Empty<DetectedOperationDto>(); return Enumerable.Empty<WellOperationCategoryDto>();
var query = BuildQuery(well, request).AsNoTracking(); var request = new DetectedOperationByTelemetryRequest()
{
var data = await query.ToListAsync(token); IdTelemetry = well.IdTelemetry.Value
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<DetectedOperationDrillersStatDto> GetOperationsDrillersStat(IEnumerable<DetectedOperationDto> operations)
{
var groups = operations.GroupBy(o => o.Driller);
var stats = new List<DetectedOperationDrillersStatDto>(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<IEnumerable<DetectedOperationStatDto>?> 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<int> 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,
}; };
}
private static double DeltaToTarget(DetectedOperationDto op) var operations = await operationRepository.Get(request, token);
{ var categories = operations
return (op.IdCategory) switch .Select(o => o.OperationCategory)
{ .Distinct();
WellOperationCategory.IdRotor => 0, return categories;
WellOperationCategory.IdSlide => 0,
WellOperationCategory.IdSlipsTime => op.Value - op.OperationValue?.TargetValue??0,
_ => 0,
};
}
private IQueryable<DetectedOperation> BuildQueryBase(WellDto well, DetectedOperationRequest request)
{
var query = db.Set<DetectedOperation>()
.Where(o => o.IdTelemetry == well.IdTelemetry);
if (request.IdsTelemetries.Any())
{
query = query
.Union(db.Set<DetectedOperation>().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<DetectedOperation> BuildQuery(WellDto well, DetectedOperationRequest request)
{
IQueryable<DetectedOperation> 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<OperationValueDto> operationValues, IEnumerable<ScheduleDto> schedules)
{
var dto = operation.Adapt<DetectedOperationDto>();
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<IEnumerable<WellOperationCategoryDto>?> GetCategoriesAsync(int? idWell, CancellationToken token)
{
IQueryable<WellOperationCategory> 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<WellOperationCategoryDto>())
.ToArrayAsync(token);
return result;
} }
} }
public async Task<IEnumerable<DetectedOperationStatDto>> 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<DetectedOperationStatDto>();
var requestByTelemetry = new DetectedOperationByTelemetryRequest(well.IdTelemetry.Value, request);
var operations = await operationRepository.Get(requestByTelemetry, token);
if (!operations.Any())
return Enumerable.Empty<DetectedOperationStatDto>();
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<int> 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<DetectedOperationDrillersStatDto> GetOperationsDrillersStat(IEnumerable<DetectedOperationWithDrillerDto> operations)
{
var groups = operations.GroupBy(o => o.Driller);
var stats = new List<DetectedOperationDrillersStatDto>(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<OperationValueDto> operationValues, IEnumerable<ScheduleDto> schedules)
{
var dto = operation.Adapt<DetectedOperationWithDrillerDto>();
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;
}
} }

View File

@ -45,17 +45,16 @@ internal class SubsystemService : ISubsystemService
if(!well.IdTelemetry.HasValue) if(!well.IdTelemetry.HasValue)
return Enumerable.Empty<SubsystemStatDto>(); return Enumerable.Empty<SubsystemStatDto>();
var detectedOperationSummaryRequest = new DetectedOperationRequest var detectedOperationSummaryRequest = new DetectedOperationByWellRequest
{ {
IdWell = request.IdWell, IdWell = request.IdWell,
IdsTelemetries = new[] { well.IdTelemetry.Value },
IdsCategories = WellOperationCategory.MechanicalDrillingSubIds, IdsCategories = WellOperationCategory.MechanicalDrillingSubIds,
GeDateStart = request.GeDate, GeDateStart = request.GeDate,
LeDateEnd = request.LeDate, LeDateEnd = request.LeDate,
GeDepth = request.GeDepth, GeDepthStart = request.GeDepth,
LeDepth = request.LeDepth, LeDepthEnd = request.LeDepth,
}; };
var operations = await detectedOperationService.GetOperationsAsync(detectedOperationSummaryRequest, var operations = await detectedOperationService.GetOperationsAsync(detectedOperationSummaryRequest,
@ -78,7 +77,7 @@ internal class SubsystemService : ISubsystemService
return result; return result;
} }
private async Task<IEnumerable<SubsystemStatDto>> CalcStatAsync(IEnumerable<DetectedOperationDto> operations, CancellationToken token) private async Task<IEnumerable<SubsystemStatDto>> CalcStatAsync(IEnumerable<DetectedOperationWithDrillerDto> operations, CancellationToken token)
{ {
if (!subsystems.Any()) if (!subsystems.Any())
subsystems = (await subsystemRepository.GetAllAsync(token)).ToDictionary(s => s.Id, s => s); subsystems = (await subsystemRepository.GetAllAsync(token)).ToDictionary(s => s.Id, s => s);
@ -92,7 +91,7 @@ internal class SubsystemService : ISubsystemService
return stat; return stat;
} }
private SubsystemStatDto CalcOscillationStat(IEnumerable<DetectedOperationDto> operations) private SubsystemStatDto CalcOscillationStat(IEnumerable<DetectedOperationWithDrillerDto> operations)
{ {
operations = operations.Where(o => o.IdCategory == WellOperationCategory.IdSlide); operations = operations.Where(o => o.IdCategory == WellOperationCategory.IdSlide);
@ -114,7 +113,7 @@ internal class SubsystemService : ISubsystemService
return oscillationStat; return oscillationStat;
} }
private IEnumerable<SubsystemStatDto> CalcApdStat(IEnumerable<DetectedOperationDto> operations) private IEnumerable<SubsystemStatDto> CalcApdStat(IEnumerable<DetectedOperationWithDrillerDto> operations)
{ {
var apdRotorAndSlide = operations var apdRotorAndSlide = operations
.Where(o => WellOperationCategory.MechanicalDrillingSubIds.Contains(o.IdCategory)) .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, private static (double SumDepthInterval, double UsedTimeHours, int Count) AggregateOperations(int idSubsystem,
IEnumerable<DetectedOperationDto> operations) => IEnumerable<DetectedOperationWithDrillerDto> operations) =>
idSubsystem switch idSubsystem switch
{ {
IdSubsystemAPDRotor => CalcOperationsByEnableSubsystems(operations, EnabledSubsystemsFlags.AutoRotor), IdSubsystemAPDRotor => CalcOperationsByEnableSubsystems(operations, EnabledSubsystemsFlags.AutoRotor),
@ -180,7 +179,7 @@ internal class SubsystemService : ISubsystemService
}; };
private static (double SumDepthInterval, double UsedTimeHours, int OperationCount) CalcOperationsByEnableSubsystems( private static (double SumDepthInterval, double UsedTimeHours, int OperationCount) CalcOperationsByEnableSubsystems(
IEnumerable<DetectedOperationDto> operations, IEnumerable<DetectedOperationWithDrillerDto> operations,
EnabledSubsystemsFlags enabledSubsystems) EnabledSubsystemsFlags enabledSubsystems)
{ {
var filtered = operations.Where(o => enabledSubsystems.HasEnabledSubsystems(o.EnabledSubsystems)); var filtered = operations.Where(o => enabledSubsystems.HasEnabledSubsystems(o.EnabledSubsystems));
@ -215,7 +214,7 @@ internal class SubsystemService : ISubsystemService
var leDateUtc = leDate?.ToUtcDateTimeOffset(hoursOffset); var leDateUtc = leDate?.ToUtcDateTimeOffset(hoursOffset);
var request = new DetectedOperationRequest var request = new DetectedOperationByWellRequest
{ {
IdWell = well.Id, IdWell = well.Id,
IdsCategories = WellOperationCategory.MechanicalDrillingSubIds, IdsCategories = WellOperationCategory.MechanicalDrillingSubIds,

View File

@ -36,13 +36,18 @@ namespace AsbCloudInfrastructure.Services
.ThenInclude(r => r.Company) .ThenInclude(r => r.Company)
.AsNoTracking(); .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) : base(db, memoryCache, MakeQueryWell)
{ {
this.telemetryService = telemetryService; this.telemetryService = telemetryService;
this.timezoneService = timezoneService; this.timezoneService = timezoneService;
this.wellInfoService = wellInfoService; this.wellInfoService = wellInfoService;
this.wellOperationRepository = new WellOperationRepository(db, memoryCache, this); this.wellOperationRepository = new WellOperationRepository(db, memoryCache, this, wellOperationCategoryRepository);
companyTypesService = new CrudCacheRepositoryBase<CompanyTypeDto, CompanyType>(dbContext, memoryCache); companyTypesService = new CrudCacheRepositoryBase<CompanyTypeDto, CompanyType>(dbContext, memoryCache);
} }

View File

@ -10,6 +10,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNet.WebApi.Core" Version="5.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.26" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.26" />
<PackageReference Include="Microsoft.Extensions.ApiDescription.Server" Version="8.0.1"> <PackageReference Include="Microsoft.Extensions.ApiDescription.Server" Version="8.0.1">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>

View File

@ -57,7 +57,7 @@ namespace AsbCloudWebApi.Controllers.SAUB
[HttpGet] [HttpGet]
[ProducesResponseType(typeof(DetectedOperationListDto), (int)System.Net.HttpStatusCode.OK)] [ProducesResponseType(typeof(DetectedOperationListDto), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetAsync( public async Task<IActionResult> GetAsync(
[FromQuery] DetectedOperationRequest request, [FromQuery] DetectedOperationByWellRequest request,
CancellationToken token) CancellationToken token)
{ {
if (!await UserHasAccessToWellAsync(request.IdWell, token)) if (!await UserHasAccessToWellAsync(request.IdWell, token))
@ -76,7 +76,7 @@ namespace AsbCloudWebApi.Controllers.SAUB
[HttpGet("stat")] [HttpGet("stat")]
[ProducesResponseType(typeof(IEnumerable<DetectedOperationStatDto>), (int)System.Net.HttpStatusCode.OK)] [ProducesResponseType(typeof(IEnumerable<DetectedOperationStatDto>), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetStatAsync( public async Task<IActionResult> GetStatAsync(
[FromQuery] DetectedOperationRequest request, [FromQuery] DetectedOperationByWellRequest request,
CancellationToken token) CancellationToken token)
{ {
if (!await UserHasAccessToWellAsync(request.IdWell, token)) if (!await UserHasAccessToWellAsync(request.IdWell, token))
@ -98,7 +98,7 @@ namespace AsbCloudWebApi.Controllers.SAUB
[Permission] [Permission]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> DeleteAsync( public async Task<IActionResult> DeleteAsync(
[FromQuery] DetectedOperationRequest request, [FromQuery] DetectedOperationByWellRequest request,
CancellationToken token) CancellationToken token)
{ {
if (!await UserHasAccessToWellAsync(request.IdWell, token)) if (!await UserHasAccessToWellAsync(request.IdWell, token))