forked from ddrilling/AsbCloudServer
Add DetectedOperation repository
This commit is contained in:
parent
b263f7973b
commit
b7dcf313a2
@ -1,100 +1,85 @@
|
||||
using System;
|
||||
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>
|
||||
/// Автоматически определяемая операция
|
||||
/// Id телеметрии
|
||||
/// </summary>
|
||||
public class DetectedOperationDto : IId, IWellRelated
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
[Required]
|
||||
public int Id { get; set; }
|
||||
[Required]
|
||||
public int IdTelemetry { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
[Required]
|
||||
public int IdWell { get; set; }
|
||||
/// <summary>
|
||||
/// Id названия/описания операции
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int IdCategory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id телеметрии
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int IdTelemetry { get; set; }
|
||||
/// <summary>
|
||||
/// Id пользователя панели на момент начала операции
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int IdUserAtStart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id названия/описания операции
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int IdCategory { get; set; }
|
||||
/// <summary>
|
||||
/// Дата завершения операции в часовом поясе скважины
|
||||
/// </summary>
|
||||
[Required]
|
||||
public DateTimeOffset DateEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id пользователя панели
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int IdUsersAtStart { get; set; }
|
||||
/// <summary>
|
||||
/// Дата начала операции в часовом поясе скважины
|
||||
/// </summary>
|
||||
[Required]
|
||||
public DateTimeOffset DateStart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Дата начала операции в часовом поясе скважины
|
||||
/// </summary>
|
||||
[Required]
|
||||
public DateTime DateStart { get; set; }
|
||||
/// <summary>
|
||||
/// глубина на завершения операции, м
|
||||
/// </summary>
|
||||
[Required]
|
||||
public double DepthEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Дата завершения операции в часовом поясе скважины
|
||||
/// </summary>
|
||||
[Required]
|
||||
public DateTime DateEnd { get; set; }
|
||||
/// <summary>
|
||||
/// глубина на начало операции, м
|
||||
/// </summary>
|
||||
[Required]
|
||||
public double DepthStart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Продолжительность операции в минутах
|
||||
/// </summary>
|
||||
[Required]
|
||||
public double DurationMinutes => (DateEnd - DateStart).TotalMinutes;
|
||||
/// <summary>
|
||||
/// Продолжительность операции в минутах
|
||||
/// </summary>
|
||||
[Required]
|
||||
public double DurationMinutes => (DateEnd - DateStart).TotalMinutes;
|
||||
|
||||
/// <summary>
|
||||
/// глубина на начало операции, м
|
||||
/// </summary>
|
||||
[Required]
|
||||
public double DepthStart { get; set; }
|
||||
/// <summary>
|
||||
/// Флаг включенной подсистемы
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int EnabledSubsystems { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// глубина на завершения операции, м
|
||||
/// </summary>
|
||||
[Required]
|
||||
public double DepthEnd { get; set; }
|
||||
/// <summary>
|
||||
/// название/описание операции
|
||||
/// </summary>
|
||||
[Required]
|
||||
public WellOperationCategoryDto OperationCategory { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// название/описание операции
|
||||
/// </summary>
|
||||
[Required]
|
||||
public WellOperationCategoryDto OperationCategory { get; set; } = null!;
|
||||
/// <summary>
|
||||
/// Пользователь панели оператора
|
||||
/// </summary>
|
||||
public string? TelemetryUserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Пользователь панели оператора
|
||||
/// </summary>
|
||||
public string? TelemetryUserName { 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; }
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Ключевой параметр операции
|
||||
/// </summary>
|
||||
[Required]
|
||||
public double Value { get; set; }
|
||||
}
|
@ -13,7 +13,7 @@ namespace AsbCloudApp.Data.DetectedOperation
|
||||
/// Список всех операций
|
||||
/// </summary>
|
||||
[Required]
|
||||
public IEnumerable<DetectedOperationDto> Operations { get; set; } = Enumerable.Empty<DetectedOperationDto>();
|
||||
public IEnumerable<DetectedOperationWithDrillerDto> Operations { get; set; } = Enumerable.Empty<DetectedOperationWithDrillerDto>();
|
||||
|
||||
/// <summary>
|
||||
/// Статистика по бурильщикам
|
||||
|
@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace AsbCloudApp.Data
|
||||
{
|
||||
/// <summary>
|
||||
@ -20,6 +22,11 @@ namespace AsbCloudApp.Data
|
||||
/// </summary>
|
||||
public bool IsOverride { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Ñìåùåíèå ÷àñîâîãî ïîÿñà
|
||||
/// </summary>
|
||||
public TimeSpan Offset { get => TimeSpan.FromHours(Hours); }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
|
@ -86,6 +86,14 @@ namespace AsbCloudApp.Data
|
||||
second = fullDate.Second;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public TimeDto(DateTimeOffset fullDate)
|
||||
{
|
||||
hour = fullDate.Hour;
|
||||
minute = fullDate.Minute;
|
||||
second = fullDate.Second;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes System.TimeOnly
|
||||
/// </summary>
|
||||
|
@ -7,7 +7,7 @@ using System.Threading;
|
||||
namespace AsbCloudApp.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// Таблица автоопределенных операций
|
||||
/// Таблица автоматически определенных операций
|
||||
/// </summary>
|
||||
public interface IDetectedOperationRepository
|
||||
{
|
||||
@ -18,15 +18,15 @@ public interface IDetectedOperationRepository
|
||||
/// <param name="dtos"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> Insert(int idUser, IEnumerable<DetectedOperationDto> dtos, CancellationToken token);
|
||||
Task<int> Insert(int? idUser, IEnumerable<DetectedOperationDto> dtos, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Получить автоматически определенные по телеметрии операции
|
||||
/// Получить автоматически определенные операции по телеметрии
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<DetectedOperationDto>> Get(DetectedOperationRequest request, CancellationToken token);
|
||||
Task<IEnumerable<DetectedOperationDto>> Get(DetectedOperationByTelemetryRequest request, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Редактирование записей
|
||||
@ -49,10 +49,11 @@ public interface IDetectedOperationRepository
|
||||
/// <summary>
|
||||
/// Удалить операции
|
||||
/// </summary>
|
||||
/// <param name="idUser"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> DeleteAsync(int idUser, DetectedOperationRequest request, CancellationToken token);
|
||||
Task<int> Delete(int idUser, DetectedOperationByTelemetryRequest request, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Удаление записей
|
||||
|
17
AsbCloudApp/Repositories/IWellOperationCategoryRepository.cs
Normal file
17
AsbCloudApp/Repositories/IWellOperationCategoryRepository.cs
Normal 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);
|
||||
}
|
||||
}
|
@ -1,68 +1,114 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
|
||||
namespace AsbCloudApp.Requests
|
||||
namespace AsbCloudApp.Requests;
|
||||
|
||||
/// <summary>
|
||||
/// Запрос на получение операций определенных по телеметрии
|
||||
/// </summary>
|
||||
public class DetectedOperationByTelemetryRequest : DetectedOperationRequest
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// id телеметрии
|
||||
/// </summary>
|
||||
public class DetectedOperationByWellRequest : DetectedOperationRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// категория операций
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int IdWell { get; set; }
|
||||
}
|
||||
[Required]
|
||||
public int IdTelemetry { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// Запрос на получение операций определенных по id телеметрии
|
||||
/// </summary>
|
||||
public class DetectedOperationByTelemetryRequest : DetectedOperationRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Список id телеметрий
|
||||
/// пустой список - нет фильтрации
|
||||
/// </summary>
|
||||
public IEnumerable<int> IdsTelemetries { get; set; } = Array.Empty<int>();
|
||||
}
|
||||
public DetectedOperationByTelemetryRequest()
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Параметры запроса на получение операций определенных по телеметрии
|
||||
/// Запрос на получение операций определенных по id телеметрии. Copy
|
||||
/// </summary>
|
||||
public class DetectedOperationRequest : RequestBase
|
||||
/// <param name="idTelemetry"></param>
|
||||
/// <param name="request"></param>
|
||||
public DetectedOperationByTelemetryRequest(int idTelemetry, DetectedOperationRequest request)
|
||||
:base(request)
|
||||
{
|
||||
/// <summary>
|
||||
/// категории операций
|
||||
/// </summary>
|
||||
public IEnumerable<int> IdsCategories { get; set; } = Array.Empty<int>();
|
||||
|
||||
/// <summary>
|
||||
/// Больше или равно дате
|
||||
/// </summary>
|
||||
public DateTimeOffset? GeDateStart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Меньше или равно дате
|
||||
/// </summary>
|
||||
public DateTimeOffset? LeDateEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Больше или равно глубины забоя
|
||||
/// </summary>
|
||||
public double? GeDepth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Меньше или равно глубины забоя
|
||||
/// </summary>
|
||||
public double? LeDepth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Фильтр по пользователю панели
|
||||
/// </summary>
|
||||
public int? IdTelemetryUser { get; set; }
|
||||
|
||||
IdTelemetry = idTelemetry;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Запрос на получение операций определенных по id скважины
|
||||
/// </summary>
|
||||
public class DetectedOperationByWellRequest : DetectedOperationRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// id скважины
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int IdWell { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Запрос на получение операций определенных по id скважины
|
||||
/// </summary>
|
||||
public DetectedOperationByWellRequest()
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Запрос на получение операций определенных по id скважины. Copy
|
||||
/// </summary>
|
||||
public DetectedOperationByWellRequest(int idWell, DetectedOperationRequest request)
|
||||
: base(request)
|
||||
{
|
||||
IdWell = idWell;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
|
@ -23,5 +23,23 @@ namespace AsbCloudApp.Requests
|
||||
/// Указать направление сортировки можно через пробел "asc" или "desc"
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ namespace AsbCloudApp.Services
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<WellOperationCategoryDto>?> GetCategoriesAsync(int? idWell, CancellationToken token);
|
||||
Task<IEnumerable<WellOperationCategoryDto>> GetCategoriesAsync(int? idWell, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Получить автоматически определенные по телеметрии операции с анализом по бурильщикам
|
||||
@ -27,7 +27,7 @@ namespace AsbCloudApp.Services
|
||||
/// <param name="request"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<DetectedOperationListDto?> GetAsync(DetectedOperationRequest request, CancellationToken token);
|
||||
Task<DetectedOperationListDto> GetAsync(DetectedOperationByWellRequest request, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Получить автоматически определенные по телеметрии операции
|
||||
@ -35,7 +35,7 @@ namespace AsbCloudApp.Services
|
||||
/// <param name="request"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<DetectedOperationDto>> GetOperationsAsync(DetectedOperationRequest request, CancellationToken token);
|
||||
Task<IEnumerable<DetectedOperationWithDrillerDto>> GetOperationsAsync(DetectedOperationByWellRequest request, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Удалить операции
|
||||
@ -43,7 +43,7 @@ namespace AsbCloudApp.Services
|
||||
/// <param name="request"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> DeleteAsync(DetectedOperationRequest request, CancellationToken token);
|
||||
Task<int> DeleteAsync(DetectedOperationByWellRequest request, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Статистика по операциям
|
||||
@ -51,6 +51,6 @@ namespace AsbCloudApp.Services
|
||||
/// <param name="request"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<DetectedOperationStatDto>?> GetOperationsStatAsync(DetectedOperationRequest request, CancellationToken token);
|
||||
Task<IEnumerable<DetectedOperationStatDto>> GetOperationsStatAsync(DetectedOperationByWellRequest request, CancellationToken token);
|
||||
}
|
||||
}
|
||||
|
33
AsbCloudDb/EFExtensionsExceptionHandling.cs
Normal file
33
AsbCloudDb/EFExtensionsExceptionHandling.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ using System.Reflection;
|
||||
|
||||
namespace AsbCloudDb
|
||||
{
|
||||
public static class EFExtentionsSortBy
|
||||
public static class EFExtensionsSortBy
|
||||
{
|
||||
struct TypeAcessor
|
||||
{
|
@ -329,6 +329,8 @@ namespace AsbCloudInfrastructure
|
||||
services.AddTransient<IProcessMapPlanService<ProcessMapPlanWellReamDto>, ProcessMapPlanService<ProcessMapPlanWellReamDto>>();
|
||||
|
||||
services.AddTransient<IWellSectionPlanRepository, WellSectionPlanRepository>();
|
||||
services.AddTransient<IWellOperationCategoryRepository, WellOperationCategoryRepository>();
|
||||
services.AddTransient<IDetectedOperationRepository, DetectedOperationRepository>();
|
||||
|
||||
services.AddSingleton<ParserServiceFactory>();
|
||||
|
||||
|
191
AsbCloudInfrastructure/Repository/DetectedOperationRepository.cs
Normal file
191
AsbCloudInfrastructure/Repository/DetectedOperationRepository.cs
Normal 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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<WellOperationCategoryDto> GetCategories(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;
|
||||
return wellOperationCategoryRepository.Get(includeParents);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
@ -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,
|
||||
|
@ -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<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;
|
||||
private readonly IWellService wellService;
|
||||
private readonly IRepositoryWellRelated<OperationValueDto> 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<OperationValueDto> operationValueService, IScheduleRepository scheduleService)
|
||||
public async Task<DetectedOperationListDto> 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<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);
|
||||
}
|
||||
|
||||
public async Task<DetectedOperationListDto?> 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<IEnumerable<DetectedOperationDto>> 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<DetectedOperationDto>();
|
||||
return Enumerable.Empty<WellOperationCategoryDto>();
|
||||
|
||||
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<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,
|
||||
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<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;
|
||||
var operations = await operationRepository.Get(request, token);
|
||||
var categories = operations
|
||||
.Select(o => o.OperationCategory)
|
||||
.Distinct();
|
||||
return categories;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -45,17 +45,16 @@ internal class SubsystemService : ISubsystemService
|
||||
if(!well.IdTelemetry.HasValue)
|
||||
return Enumerable.Empty<SubsystemStatDto>();
|
||||
|
||||
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<IEnumerable<SubsystemStatDto>> CalcStatAsync(IEnumerable<DetectedOperationDto> operations, CancellationToken token)
|
||||
private async Task<IEnumerable<SubsystemStatDto>> CalcStatAsync(IEnumerable<DetectedOperationWithDrillerDto> 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<DetectedOperationDto> operations)
|
||||
private SubsystemStatDto CalcOscillationStat(IEnumerable<DetectedOperationWithDrillerDto> operations)
|
||||
{
|
||||
operations = operations.Where(o => o.IdCategory == WellOperationCategory.IdSlide);
|
||||
|
||||
@ -114,7 +113,7 @@ internal class SubsystemService : ISubsystemService
|
||||
return oscillationStat;
|
||||
}
|
||||
|
||||
private IEnumerable<SubsystemStatDto> CalcApdStat(IEnumerable<DetectedOperationDto> operations)
|
||||
private IEnumerable<SubsystemStatDto> CalcApdStat(IEnumerable<DetectedOperationWithDrillerDto> 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<DetectedOperationDto> operations) =>
|
||||
IEnumerable<DetectedOperationWithDrillerDto> 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<DetectedOperationDto> operations,
|
||||
IEnumerable<DetectedOperationWithDrillerDto> 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,
|
||||
|
@ -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<CompanyTypeDto, CompanyType>(dbContext, memoryCache);
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi.Core" Version="5.3.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.26" />
|
||||
<PackageReference Include="Microsoft.Extensions.ApiDescription.Server" Version="8.0.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
|
@ -57,7 +57,7 @@ namespace AsbCloudWebApi.Controllers.SAUB
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(DetectedOperationListDto), (int)System.Net.HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> 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<DetectedOperationStatDto>), (int)System.Net.HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> 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<IActionResult> DeleteAsync(
|
||||
[FromQuery] DetectedOperationRequest request,
|
||||
[FromQuery] DetectedOperationByWellRequest request,
|
||||
CancellationToken token)
|
||||
{
|
||||
if (!await UserHasAccessToWellAsync(request.IdWell, token))
|
||||
|
Loading…
Reference in New Issue
Block a user