diff --git a/AsbCloudApp/Data/DetectedOperation/DetectedOperationDto.cs b/AsbCloudApp/Data/DetectedOperation/DetectedOperationDto.cs
index 2b0fc768..e81a45fb 100644
--- a/AsbCloudApp/Data/DetectedOperation/DetectedOperationDto.cs
+++ b/AsbCloudApp/Data/DetectedOperation/DetectedOperationDto.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace AsbCloudApp.Data.DetectedOperation;
@@ -29,6 +30,11 @@ public class DetectedOperationDto: IId
///
[Required]
public int IdUserAtStart { get; set; }
+
+ ///
+ /// Пользователь панели оператора
+ ///
+ public string? TelemetryUserName { get; set; }
///
/// Дата завершения операции в часовом поясе скважины
@@ -72,14 +78,14 @@ public class DetectedOperationDto: IId
[Required]
public WellOperationCategoryDto OperationCategory { get; set; } = null!;
- ///
- /// Пользователь панели оператора
- ///
- public string? TelemetryUserName { get; set; }
-
///
/// Ключевой параметр операции
///
[Required]
public double Value { get; set; }
+
+ ///
+ /// Доп. инфо по операции
+ ///
+ public IDictionary ExtraData { get; set; } = new Dictionary();
}
\ No newline at end of file
diff --git a/AsbCloudApp/Data/SAUB/TelemetryDataSaubDto.cs b/AsbCloudApp/Data/SAUB/TelemetryDataSaubDto.cs
index e1e7cf96..8f2794fc 100644
--- a/AsbCloudApp/Data/SAUB/TelemetryDataSaubDto.cs
+++ b/AsbCloudApp/Data/SAUB/TelemetryDataSaubDto.cs
@@ -13,6 +13,11 @@ namespace AsbCloudApp.Data.SAUB
///
[Required]
public DateTime DateTime { get; set; }
+
+ ///
+ /// Пользователь САУБ
+ ///
+ public int? IdUser { get; set; }
///
/// Режим работы САУБ:
diff --git a/AsbCloudApp/Repositories/IDetectedOperationRepository.cs b/AsbCloudApp/Repositories/IDetectedOperationRepository.cs
index 5a52b455..d7fe5865 100644
--- a/AsbCloudApp/Repositories/IDetectedOperationRepository.cs
+++ b/AsbCloudApp/Repositories/IDetectedOperationRepository.cs
@@ -1,15 +1,17 @@
-using AsbCloudApp.Data.DetectedOperation;
+using System;
+using AsbCloudApp.Data.DetectedOperation;
using AsbCloudApp.Requests;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
+using AsbCloudApp.Services;
namespace AsbCloudApp.Repositories;
///
/// Таблица автоматически определенных операций
///
-public interface IDetectedOperationRepository
+public interface IDetectedOperationRepository : ICrudRepository
{
///
/// Добавление записей
@@ -63,4 +65,11 @@ public interface IDetectedOperationRepository
///
///
Task DeleteRange(int idUser, IEnumerable ids, CancellationToken token);
+
+ ///
+ /// Получение дат последних определённых операций
+ ///
+ ///
+ ///
+ Task> GetLastDetectedDatesAsync(CancellationToken token);
}
diff --git a/AsbCloudApp/Services/IDetectedOperationService.cs b/AsbCloudApp/Services/IDetectedOperationService.cs
index 5109fa56..998032ba 100644
--- a/AsbCloudApp/Services/IDetectedOperationService.cs
+++ b/AsbCloudApp/Services/IDetectedOperationService.cs
@@ -1,4 +1,5 @@
-using AsbCloudApp.Data;
+using System;
+using AsbCloudApp.Data;
using AsbCloudApp.Data.DetectedOperation;
using AsbCloudApp.Requests;
using System.Collections.Generic;
@@ -52,5 +53,14 @@ namespace AsbCloudApp.Services
///
///
Task> GetOperationsStatAsync(DetectedOperationByWellRequest request, CancellationToken token);
+
+ ///
+ /// Определение операций
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task> DetectOperationsAsync(int idTelemetry, DateTimeOffset? beginDate, CancellationToken token);
}
}
diff --git a/AsbCloudApp/Services/ITelemetryDataService.cs b/AsbCloudApp/Services/ITelemetryDataService.cs
index bb40771b..9cf4a805 100644
--- a/AsbCloudApp/Services/ITelemetryDataService.cs
+++ b/AsbCloudApp/Services/ITelemetryDataService.cs
@@ -23,18 +23,27 @@ namespace AsbCloudApp.Services
/// кол-во элементов до которых эти данные прореживаются
///
///
- Task> GetAsync(int idWell,
+ Task> GetByWellAsync(int idWell,
DateTime dateBegin = default, double intervalSec = 600d,
int approxPointsCount = 1024, CancellationToken token = default);
///
- /// Получить данные тех. процесса
+ /// Получить данные тех. процесса по скважине
///
///
///
///
///
- Task> GetAsync(int idWell, TelemetryDataRequest request, CancellationToken token);
+ Task> GetByWellAsync(int idWell, TelemetryDataRequest request, CancellationToken token);
+
+ ///
+ /// Получение данных тех. процесса по телеметрии
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task> GetByTelemetryAsync(int idTelemetry, TelemetryDataRequest request, CancellationToken token);
///
/// Период за который есть данные по скважине в рамках временного интервала
diff --git a/AsbCloudDb/Model/DetectedOperation.cs b/AsbCloudDb/Model/DetectedOperation.cs
index c1f66c79..df5abbb1 100644
--- a/AsbCloudDb/Model/DetectedOperation.cs
+++ b/AsbCloudDb/Model/DetectedOperation.cs
@@ -8,7 +8,7 @@ using System.Text.Json.Serialization;
namespace AsbCloudDb.Model
{
[Table("t_detected_operation"), Comment("автоматически определенные операции по телеметрии")]
- public class DetectedOperation
+ public class DetectedOperation : IId
{
[Key]
[Column("id")]
@@ -20,14 +20,14 @@ namespace AsbCloudDb.Model
[Column("id_category"), Comment("Id категории операции")]
public int IdCategory { get; set; }
- [Column("id_user"), Comment("Id пользователя по телеметрии на момент начала операции")]
- public int IdUsersAtStart { get; set; }
-
[Column("date_start", TypeName = "timestamp with time zone"), Comment("Дата начала операции")]
public DateTimeOffset DateStart { get; set; }
[Column("date_end", TypeName = "timestamp with time zone"), Comment("Дата начала операции")]
public DateTimeOffset DateEnd { get; set; }
+
+ [Column("id_user"), Comment("Id пользователя по телеметрии на момент начала операции")]
+ public int IdUsersAtStart { get; set; }
[NotMapped]
public double DurationMinutes => (DateEnd - DateStart).TotalMinutes;
diff --git a/AsbCloudInfrastructure/Repository/DetectedOperationRepository.cs b/AsbCloudInfrastructure/Repository/DetectedOperationRepository.cs
index 50ec6c9e..21db64ba 100644
--- a/AsbCloudInfrastructure/Repository/DetectedOperationRepository.cs
+++ b/AsbCloudInfrastructure/Repository/DetectedOperationRepository.cs
@@ -15,37 +15,46 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Repository;
-public class DetectedOperationRepository : IDetectedOperationRepository
+public class DetectedOperationRepository : CrudRepositoryBase,
+ IDetectedOperationRepository
{
- private readonly IAsbCloudDbContext db;
private readonly ITelemetryService telemetryService;
- public DetectedOperationRepository(
- IAsbCloudDbContext db,
+ public DetectedOperationRepository(IAsbCloudDbContext context,
ITelemetryService telemetryService)
+ : base(context)
{
- this.db = db;
this.telemetryService = telemetryService;
}
public async Task Delete(int idUser, DetectedOperationByTelemetryRequest request, CancellationToken token)
{
var query = BuildQuery(request);
- db.Set().RemoveRange(query);
- return await db.SaveChangesAsync(token);
+ dbContext.Set().RemoveRange(query);
+ return await dbContext.SaveChangesAsync(token);
}
public async Task DeleteRange(int idUser, IEnumerable ids, CancellationToken token)
{
- var query = db.Set()
+ var query = dbContext.Set()
.Where(e => ids.Contains( e.Id));
- db.Set()
+ dbContext.Set()
.RemoveRange(query);
- return await db.SaveChangesAsync(token);
+ return await dbContext.SaveChangesAsync(token);
}
+ public async Task> GetLastDetectedDatesAsync(CancellationToken token) =>
+ await dbContext.Set()
+ .GroupBy(o => o.IdTelemetry)
+ .Select(g => new
+ {
+ IdTelemetry = g.Key,
+ LastDate = g.Max(o => o.DateEnd)
+ })
+ .ToDictionaryAsync(x => x.IdTelemetry, x => x.LastDate, token);
+
public async Task> Get(DetectedOperationByTelemetryRequest request, CancellationToken token)
{
var query = BuildQuery(request)
@@ -63,14 +72,14 @@ public class DetectedOperationRepository : IDetectedOperationRepository
return 0;
var entities = dtos.Select(Convert);
- var dbset = db.Set();
+ var dbset = dbContext.Set();
foreach(var entity in entities)
{
entity.Id = default;
dbset.Add(entity);
}
- return await db.SaveChangesWithExceptionHandling(token);
+ return await dbContext.SaveChangesWithExceptionHandling(token);
}
public async Task Update(int idUser, IEnumerable dtos, CancellationToken token)
@@ -89,7 +98,7 @@ public class DetectedOperationRepository : IDetectedOperationRepository
if (ids.Length != dtos.Count())
throw new ArgumentInvalidException(nameof(dtos), "Все записи должны иметь уникальные Id");
- var dbSet = db.Set();
+ var dbSet = dbContext.Set();
var existingEntitiesCount = await dbSet
.Where(o => ids.Contains(o.Id))
@@ -106,7 +115,7 @@ public class DetectedOperationRepository : IDetectedOperationRepository
for(var i = 0; i < entities.Length; i++)
entries[i] = dbSet.Update(entities[i]);
- var result = await db.SaveChangesWithExceptionHandling(token);
+ var result = await dbContext.SaveChangesWithExceptionHandling(token);
for (var i = 0; i < entries.Length; i++)
entries[i].State = EntityState.Detached;
@@ -131,7 +140,7 @@ public class DetectedOperationRepository : IDetectedOperationRepository
private IQueryable BuildQuery(DetectedOperationByTelemetryRequest request)
{
- var query = db.Set()
+ var query = dbContext.Set()
.Where(o => o.IdTelemetry == request.IdTelemetry);
if (request.IdsCategories.Any())
@@ -173,19 +182,19 @@ public class DetectedOperationRepository : IDetectedOperationRepository
return query;
}
- private static DetectedOperationDto Convert(DetectedOperation entity, TimeSpan offset)
+ protected virtual DetectedOperationDto Convert(DetectedOperation src, TimeSpan offset)
{
- var dto = entity.Adapt();
- dto.DateStart = entity.DateStart.ToOffset(offset);
- dto.DateEnd = entity.DateEnd.ToOffset(offset);
+ var dto = src.Adapt();
+ dto.DateStart = src.DateStart.ToOffset(offset);
+ dto.DateEnd = src.DateEnd.ToOffset(offset);
return dto;
}
- private static DetectedOperation Convert(DetectedOperationDto dto)
+ protected override DetectedOperation Convert(DetectedOperationDto src)
{
- var entity = dto.Adapt();
- entity.DateStart = dto.DateStart.ToUniversalTime();
- entity.DateEnd = dto.DateEnd.ToUniversalTime();
+ var entity = src.Adapt();
+ entity.DateStart = src.DateStart.ToUniversalTime();
+ entity.DateEnd = src.DateEnd.ToUniversalTime();
return entity;
}
}
diff --git a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs
index 00349a6c..c6edb30b 100644
--- a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs
+++ b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs
@@ -60,16 +60,15 @@ public class WellOperationRepository : IWellOperationRepository
OperationType = WellOperation.IdOperationTypePlan,
};
- var entities = await BuildQuery(request)
+ var dtos = await BuildQuery(request)
.AsNoTracking()
- .ToArrayAsync(token)
- .ConfigureAwait(false);
+ .ToArrayAsync(token);
var dateLastAssosiatedPlanOperation = await GetDateLastAssosiatedPlanOperationAsync(idWell, currentDate, timezone.Hours, token);
-
+
var result = new WellOperationPlanDto()
{
- WellOperationsPlan = entities,
+ WellOperationsPlan = dtos.Select(Convert),
DateLastAssosiatedPlanOperation = dateLastAssosiatedPlanOperation
};
@@ -211,7 +210,7 @@ public class WellOperationRepository : IWellOperationRepository
var dtos = await query.ToArrayAsync(token);
- return dtos;
+ return dtos.Select(Convert);
}
///
@@ -219,21 +218,19 @@ public class WellOperationRepository : IWellOperationRepository
WellOperationRequest request,
CancellationToken token)
{
- var query = BuildQuery(request)
- .AsNoTracking();
-
+ var query = BuildQuery(request);
+
var result = new PaginationContainer
{
Skip = request.Skip ?? 0,
Take = request.Take ?? 32,
- Count = await query.CountAsync(token).ConfigureAwait(false),
+ Count = await query.CountAsync(token),
};
- query = query
- .Skip(result.Skip)
- .Take(result.Take);
+ var dtos = await query.ToArrayAsync(token);
+
+ result.Items = dtos.Select(Convert);
- result.Items = await query.ToArrayAsync(token);
return result;
}
@@ -384,12 +381,13 @@ public class WellOperationRepository : IWellOperationRepository
/// В результате попрежнему требуется конвертировать дату
///
///
+ ///
///
private IQueryable BuildQuery(WellOperationRequest request)
{
var timezone = wellService.GetTimezone(request.IdWell);
- var timeZoneOffset = TimeSpan.FromHours(timezone.Hours);
-
+ var timeZoneOffset = timezone.Hours;
+
var query = db.WellOperations
.Include(s => s.WellSectionType)
.Include(s => s.OperationCategory)
@@ -413,20 +411,20 @@ public class WellOperationRepository : IWellOperationRepository
if (request.GeDate.HasValue)
{
- var geDateOffset = request.GeDate.Value.ToUtcDateTimeOffset(timezone.Hours);
+ var geDateOffset = request.GeDate.Value.ToUtcDateTimeOffset(timeZoneOffset);
query = query.Where(e => e.DateStart >= geDateOffset);
}
if (request.LtDate.HasValue)
{
- var ltDateOffset = request.LtDate.Value.ToUtcDateTimeOffset(timezone.Hours);
+ var ltDateOffset = request.LtDate.Value.ToUtcDateTimeOffset(timeZoneOffset);
query = query.Where(e => e.DateStart < ltDateOffset);
}
var currentWellOperations = db.WellOperations
.Where(subOp => subOp.IdWell == request.IdWell);
- var wellOperationsWithCategoryNPT = currentWellOperations
+ var wellOperationsWithCategoryNpt = currentWellOperations
.Where(subOp => subOp.IdType == 1)
.Where(subOp => WellOperationCategory.NonProductiveTimeSubIds.Contains(subOp.IdCategory));
@@ -442,14 +440,14 @@ public class WellOperationRepository : IWellOperationRepository
CategoryName = o.OperationCategory.Name,
WellSectionTypeName = o.WellSectionType.Caption,
- DateStart = DateTime.SpecifyKind(o.DateStart.UtcDateTime + timeZoneOffset, DateTimeKind.Unspecified),
+ DateStart = o.DateStart,
DepthStart = o.DepthStart,
DepthEnd = o.DepthEnd,
DurationHours = o.DurationHours,
CategoryInfo = o.CategoryInfo,
Comment = o.Comment,
- NptHours = wellOperationsWithCategoryNPT
+ NptHours = wellOperationsWithCategoryNpt
.Where(subOp => subOp.DateStart <= o.DateStart)
.Select(subOp => subOp.DurationHours)
.Sum(),
@@ -460,22 +458,39 @@ public class WellOperationRepository : IWellOperationRepository
.Min(subOp => subOp.DateStart))
.TotalDays,
IdUser = o.IdUser,
- LastUpdateDate = DateTime.SpecifyKind(o.LastUpdateDate.UtcDateTime + timeZoneOffset, DateTimeKind.Unspecified)
+ LastUpdateDate = o.LastUpdateDate,
});
if (request.SortFields?.Any() == true)
{
dtos = dtos.SortBy(request.SortFields);
}
- else
- {
- dtos = dtos
- .OrderBy(e => e.DateStart)
- .ThenBy(e => e.DepthEnd)
- .ThenBy(e => e.Id);
- }
- return dtos;
+ dtos = dtos
+ .OrderBy(e => e.DateStart)
+ .ThenBy(e => e.DepthEnd)
+ .ThenBy(e => e.Id);
+
+ if (request.Skip.HasValue)
+ dtos = dtos.Skip(request.Skip.Value);
+
+ if (request.Take.HasValue)
+ dtos = dtos.Take(request.Take.Value);
+
+ return dtos.AsNoTracking();
+ }
+
+ private WellOperationDto Convert(WellOperationDto dto)
+ {
+ var timezone = wellService.GetTimezone(dto.IdWell);
+ var timezoneOffset = TimeSpan.FromHours(timezone.Hours);
+
+ var dtoWithRemoteDateTime = dto.Adapt();
+
+ dtoWithRemoteDateTime.DateStart = dto.DateStart.ToOffset(TimeSpan.FromHours(timezoneOffset.Hours));
+ dtoWithRemoteDateTime.LastUpdateDate = dto.LastUpdateDate?.ToOffset(TimeSpan.FromHours(timezoneOffset.Hours));
+
+ return dtoWithRemoteDateTime;
}
public async Task RemoveDuplicates(Action onProgressCallback, CancellationToken token)
diff --git a/AsbCloudInfrastructure/Services/DetectOperations/DetectableTelemetry.cs b/AsbCloudInfrastructure/Services/DetectOperations/DetectableTelemetry.cs
index 55a605f2..9c72c4e8 100644
--- a/AsbCloudInfrastructure/Services/DetectOperations/DetectableTelemetry.cs
+++ b/AsbCloudInfrastructure/Services/DetectOperations/DetectableTelemetry.cs
@@ -5,8 +5,8 @@ namespace AsbCloudInfrastructure.Services.DetectOperations;
public class DetectableTelemetry
{
public DateTimeOffset DateTime { get; set; }
- public int? IdUser { get; set; }
public int Mode { get; set; }
+ public int? IdUser { get; set; }
public float WellDepth { get; set; }
public float Pressure { get; set; }
public float HookWeight { get; set; }
diff --git a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs
index 987f274f..3ba4350a 100644
--- a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs
+++ b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationExportService.cs
@@ -19,9 +19,9 @@ namespace AsbCloudInfrastructure.Services.DetectOperations;
public class DetectedOperationExportService
{
- private readonly IAsbCloudDbContext db;
- private readonly IWellService wellService;
+ private readonly IWellService wellService;
private readonly IWellOperationCategoryRepository wellOperationCategoryRepository;
+ private readonly IDetectedOperationService detectedOperationService;
private const int headerRowsCount = 1;
private const string cellDepositName = "B1";
@@ -40,15 +40,14 @@ public class DetectedOperationExportService
private const int columnIdReasonOfEnd = 9;
private const int columnComment = 10;
- public DetectedOperationExportService(
- IAsbCloudDbContext db,
- IWellService wellService,
- IWellOperationCategoryRepository wellOperationCategoryRepository)
+ public DetectedOperationExportService(IWellService wellService,
+ IWellOperationCategoryRepository wellOperationCategoryRepository,
+ IDetectedOperationService detectedOperationService)
{
- this.db = db;
- this.wellService = wellService;
+ this.wellService = wellService;
this.wellOperationCategoryRepository = wellOperationCategoryRepository;
- }
+ this.detectedOperationService = detectedOperationService;
+ }
///
/// Экспорт excel файла с операциями по скважине
@@ -68,12 +67,12 @@ public class DetectedOperationExportService
if (!well.IdTelemetry.HasValue)
throw new ArgumentInvalidException(nameof(idWell), $"Well {idWell} has no telemetry");
- var operations = await WorkOperationDetection.DetectOperationsAsync(well.IdTelemetry.Value, DateTime.UnixEpoch, db, token);
+ var operations = await detectedOperationService.DetectOperationsAsync(well.IdTelemetry.Value, DateTime.UnixEpoch, token);
return await GenerateExcelFileStreamAsync(well, host, operations, token);
}
- private async Task GenerateExcelFileStreamAsync(WellDto well, string host, IEnumerable operationDetectorResults,
+ private async Task GenerateExcelFileStreamAsync(WellDto well, string host, IEnumerable operationDetectorResults,
CancellationToken cancellationToken)
{
using var excelTemplateStream = await GetExcelTemplateStreamAsync(cancellationToken);
@@ -88,7 +87,7 @@ public class DetectedOperationExportService
return memoryStream;
}
- private void AddToWorkbook(XLWorkbook workbook, WellDto well, string host, IEnumerable operations)
+ private void AddToWorkbook(XLWorkbook workbook, WellDto well, string host, IEnumerable operations)
{
const string sheetName = "Операции";
@@ -104,14 +103,17 @@ public class DetectedOperationExportService
AddToSheet(sheet, well, host, orderedOperations);
}
- private void AddToSheet(IXLWorksheet sheet, WellDto well, string host, IList operations)
+ private void AddToSheet(IXLWorksheet sheet, WellDto well, string host, IList operations)
{
var wellOperationCategories = wellOperationCategoryRepository.Get(true);
sheet.Cell(cellDepositName).SetCellValue(well.Deposit);
sheet.Cell(cellClusterName).SetCellValue(well.Cluster);
sheet.Cell(cellWellName).SetCellValue(well.Caption);
- sheet.Cell(cellDeltaDate).SetCellValue((TimeSpan)(Enumerable.Max(operations, (Func)(o => o.DateEnd)) - Enumerable.Min(operations, (Func)(o => o.DateStart))));
+
+ var deltaDate = operations.Max(o => o.DateEnd - o.DateStart);
+
+ sheet.Cell(cellDeltaDate).SetCellValue(deltaDate);
for (int i = 0; i < operations.Count; i++)
{
@@ -157,7 +159,7 @@ public class DetectedOperationExportService
}
}
- private static string GetCategoryName(IEnumerable wellOperationCategories, DetectedOperation current)
+ private static string GetCategoryName(IEnumerable wellOperationCategories, DetectedOperationDto current)
{
var idCategory = current.IdCategory;
if (idCategory == WellOperationCategory.IdSlide &&
@@ -198,7 +200,7 @@ public class DetectedOperationExportService
return memoryStream;
}
- private static string CreateComment(DetectedOperation operation)
+ private static string CreateComment(DetectedOperationDto operation)
{
switch (operation.IdCategory)
{
diff --git a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs
index bd8fba77..06415870 100644
--- a/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs
+++ b/AsbCloudInfrastructure/Services/DetectOperations/DetectedOperationService.cs
@@ -1,16 +1,16 @@
-using AsbCloudApp.Data;
+using System;
+using AsbCloudApp.Data;
using AsbCloudApp.Data.DetectedOperation;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
-using AsbCloudDb;
using AsbCloudDb.Model;
using Mapster;
-using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
namespace AsbCloudInfrastructure.Services.DetectOperations;
@@ -19,21 +19,29 @@ public class DetectedOperationService : IDetectedOperationService
private readonly IDetectedOperationRepository operationRepository;
private readonly IWellOperationCategoryRepository wellOperationCategoryRepository;
private readonly IWellService wellService;
- private readonly IRepositoryWellRelated operationValueService;
- private readonly IScheduleRepository scheduleService;
+ private readonly IRepositoryWellRelated operationValueRepository;
+ private readonly IScheduleRepository scheduleRepository;
+ private readonly ITelemetryDataSaubService telemetryDataSaubService;
+ private static readonly DetectorAbstract[] detectors = {
+ new DetectorDrilling(),
+ new DetectorSlipsTime()
+ };
+
public DetectedOperationService(
IDetectedOperationRepository operationRepository,
IWellOperationCategoryRepository wellOperationCategoryRepository,
IWellService wellService,
IRepositoryWellRelated operationValueRepository,
- IScheduleRepository scheduleRepository)
+ IScheduleRepository scheduleRepository,
+ ITelemetryDataSaubService telemetryDataSaubService)
{
this.operationRepository = operationRepository;
this.wellOperationCategoryRepository = wellOperationCategoryRepository;
this.wellService = wellService;
- this.operationValueService = operationValueRepository;
- this.scheduleService = scheduleRepository;
+ this.operationValueRepository = operationValueRepository;
+ this.scheduleRepository = scheduleRepository;
+ this.telemetryDataSaubService = telemetryDataSaubService;
}
public async Task GetAsync(DetectedOperationByWellRequest request, CancellationToken token)
@@ -60,8 +68,8 @@ public class DetectedOperationService : IDetectedOperationService
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 operationValues = await operationValueRepository.GetByIdWellAsync(request.IdWell, token);
+ var schedules = await scheduleRepository.GetByIdWellAsync(request.IdWell, token);
var dtos = data.Select(o => Convert(o, operationValues, schedules));
return dtos;
}
@@ -103,9 +111,7 @@ public class DetectedOperationService : IDetectedOperationService
if (!operations.Any())
return Enumerable.Empty();
-
- var operationValues = await operationValueService.GetByIdWellAsync(request.IdWell, token);
-
+
var dtos = operations
.GroupBy(o => (o.IdCategory, o.OperationCategory.Name))
.OrderBy(g => g.Key)
@@ -126,6 +132,69 @@ public class DetectedOperationService : IDetectedOperationService
return dtos;
}
+ public async Task> DetectOperationsAsync(int idTelemetry, DateTimeOffset? beginDate, CancellationToken token)
+ {
+ const int take = 4 * 86_400;
+
+ var detectedOperations = new List();
+ DetectedOperationDto? lastDetectedOperation = null;
+ const int minOperationLength = 5;
+ const int maxDetectorsInterpolationFrameLength = 30;
+ const int gap = maxDetectorsInterpolationFrameLength + minOperationLength;
+
+ while (true)
+ {
+ var request = new TelemetryDataRequest
+ {
+ GeDate = beginDate,
+ Take = take,
+ Order = 0
+ };
+
+ var detectableTelemetries = (await telemetryDataSaubService.GetByTelemetryAsync(idTelemetry, request, token))
+ .Where(t => t.BlockPosition >= 0)
+ .Select(t => new DetectableTelemetry
+ {
+ DateTime = t.DateTime,
+ IdUser = t.IdUser,
+ Mode = t.Mode,
+ WellDepth = t.WellDepth,
+ Pressure = t.Pressure,
+ HookWeight = t.HookWeight,
+ BlockPosition = t.BlockPosition,
+ BitDepth = t.BitDepth,
+ RotorSpeed = t.RotorSpeed,
+ }).ToArray();
+
+ if (detectableTelemetries.Length < gap)
+ break;
+
+ var isDetected = false;
+ var positionBegin = 0;
+ var positionEnd = detectableTelemetries.Length - gap;
+ while (positionEnd > positionBegin)
+ {
+ foreach (var detector in detectors)
+ {
+ if (!detector.TryDetect(idTelemetry, detectableTelemetries, positionBegin, positionEnd, lastDetectedOperation, out var result))
+ continue;
+
+ detectedOperations.Add(result!.Operation);
+ lastDetectedOperation = result.Operation;
+ isDetected = true;
+ positionBegin = result.TelemetryEnd;
+ break;
+ }
+
+ positionBegin += 1;
+ }
+
+ beginDate = isDetected ? lastDetectedOperation!.DateEnd : detectableTelemetries[positionEnd].DateTime;
+ }
+
+ return detectedOperations;
+ }
+
public async Task DeleteAsync(DetectedOperationByWellRequest request, CancellationToken token)
{
var well = await wellService.GetOrDefaultAsync(request.IdWell, token);
diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs
index 228d0810..6c5b99de 100644
--- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs
+++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorAbstract.cs
@@ -35,7 +35,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
protected const int IdReasonOfEnd_Custom1 = 10_000;
- public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, DetectedOperation? previousOperation,
+ public bool TryDetect(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end, DetectedOperationDto? previousOperation,
out OperationDetectorResult? result)
{
// Проверка соответствия критерию начала операции
@@ -82,9 +82,9 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
protected virtual bool IsValidOperationDetectorResult(OperationDetectorResult operationDetectorResult)
=> operationDetectorResult.Operation.DateEnd - operationDetectorResult.Operation.DateStart > TimeSpan.FromSeconds(3);
- protected abstract bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation);
+ protected abstract bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation);
- protected virtual int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
+ protected virtual int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation)
=> DetectBegin(telemetry, position, previousOperation)
? IdReasonOfEnd_NotDetected
: IdReasonOfEnd_NotDetectBegin;
@@ -110,16 +110,16 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
return result;
}
- private DetectedOperation MakeDetectedOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end)
+ private DetectedOperationDto MakeDetectedOperation(int idTelemetry, DetectableTelemetry[] telemetry, int begin, int end)
{
var pBegin = telemetry[begin];
var pEnd = telemetry[end];
var (IdCategory, ExtraData) = GetSpecificInformation(telemetry, begin, end);
- var operation = new DetectedOperation
+ var operation = new DetectedOperationDto
{
IdCategory = IdCategory,
IdTelemetry = idTelemetry,
- IdUsersAtStart = pBegin.IdUser ?? -1,
+ IdUserAtStart = pBegin.IdUser ?? -1,
DateStart = pBegin.DateTime,
DateEnd = pEnd.DateTime,
DepthStart = (double)pBegin.WellDepth,
diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs
index 68eda39e..88084bfe 100644
--- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs
+++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorDrilling.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using AsbCloudApp.Data.DetectedOperation;
using AsbCloudDb.Model;
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors;
@@ -12,7 +13,7 @@ public class DetectorDrilling : DetectorAbstract
public const string ExtraDataKeyDispersionOfNormalizedRotorSpeed = "dispersionOfNormalizedRotorSpeed";
public const string ExtraDataKeyAvgRotorSpeed = "avgRotorSpeed";
- protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
+ protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation)
{
var point0 = telemetry[position];
var delta = point0.WellDepth - point0.BitDepth;
@@ -25,7 +26,7 @@ public class DetectorDrilling : DetectorAbstract
return true;
}
- protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
+ protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation)
{
var point0 = telemetry[position];
var delta = point0.WellDepth - point0.BitDepth;
diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs
index 58bdba27..9388918d 100644
--- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs
+++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/DetectorSlipsTime.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using AsbCloudApp.Data.DetectedOperation;
using AsbCloudDb.Model;
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors;
@@ -9,7 +10,7 @@ public class DetectorSlipsTime : DetectorAbstract
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end)
=> CalcDeltaMinutes(telemetry, begin, end);
- protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperation? previousOperation)
+ protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation)
{
var point0 = telemetry[position];
var delta = point0.WellDepth - point0.BitDepth;
diff --git a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDetectorResult.cs b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDetectorResult.cs
index fcab00bd..8325d86c 100644
--- a/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDetectorResult.cs
+++ b/AsbCloudInfrastructure/Services/DetectOperations/Detectors/OperationDetectorResult.cs
@@ -1,4 +1,4 @@
-using AsbCloudDb.Model;
+using AsbCloudApp.Data.DetectedOperation;
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
{
@@ -7,6 +7,6 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
{
public int TelemetryBegin { get; set; }
public int TelemetryEnd { get; set; }
- public DetectedOperation Operation { get; set; } = null!;
+ public DetectedOperationDto Operation { get; set; } = null!;
}
}
diff --git a/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs b/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs
index aece226e..f562e744 100644
--- a/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs
+++ b/AsbCloudInfrastructure/Services/DetectOperations/WorkOperationDetection.cs
@@ -1,12 +1,11 @@
-using AsbCloudDb.Model;
-using Microsoft.EntityFrameworkCore;
-using System;
-using System.Collections.Generic;
+using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
+using AsbCloudApp.Data;
+using AsbCloudApp.Repositories;
+using AsbCloudApp.Services;
using AsbCloudInfrastructure.Background;
using Microsoft.Extensions.DependencyInjection;
@@ -14,19 +13,6 @@ namespace AsbCloudInfrastructure.Services.DetectOperations;
public class WorkOperationDetection: Work
{
- private static readonly DetectorAbstract[] detectors = new DetectorAbstract[]
- {
- new DetectorDrilling(),
- new DetectorSlipsTime()
- // new DetectorRotor(),
- // new DetectorSlide(),
- //new DetectorDevelopment(),
- //new DetectorTemplating(),
- //new DetectorStaticSurveying(),
- //new DetectorFlashingBeforeConnection(),
- //new DetectorFlashing(),
- //new DetectorTemplatingWhileDrilling(),
- };
public WorkOperationDetection()
:base("Operation detection")
@@ -42,115 +28,27 @@ public class WorkOperationDetection: Work
protected override async Task Action(string id, IServiceProvider services, Action onProgressCallback, CancellationToken token)
{
- using var db = services.GetRequiredService();
- db.Database.SetCommandTimeout(TimeSpan.FromMinutes(5));
- var lastDetectedDates = await db.DetectedOperations
- .GroupBy(o => o.IdTelemetry)
- .Select(g => new
- {
- IdTelemetry = g.Key,
- LastDate = g.Max(o => o.DateEnd)
- })
- .ToListAsync(token);
+ var telemetryRepository = services.GetRequiredService>();
+ var detectedOperationRepository = services.GetRequiredService();
+ var detectedOperationService = services.GetRequiredService();
- var telemetryIds = await db.Telemetries
- .Where(t => t.Info != null && t.TimeZone != null)
+ var telemetryIds = (await telemetryRepository.GetAllAsync(token))
.Select(t => t.Id)
- .ToListAsync(token);
+ .ToArray();
- var joinedlastDetectedDates = telemetryIds
- .GroupJoin(lastDetectedDates,
- t => t,
- o => o.IdTelemetry,
- (outer, inner) => new
- {
- IdTelemetry = outer,
- inner.SingleOrDefault()?.LastDate,
- });
+ var lastDetectedDates = await detectedOperationRepository.GetLastDetectedDatesAsync(token);
- var affected = 0;
- var count = joinedlastDetectedDates.Count();
- var i = 0d;
- foreach (var item in joinedlastDetectedDates)
+ for (var i = 0; i < telemetryIds.Length; i++)
{
- var stopwatch = Stopwatch.StartNew();
- var startDate = item.LastDate ?? DateTimeOffset.MinValue;
- onProgressCallback($"start detecting telemetry: {item.IdTelemetry} from {startDate}", i++ / count);
- var newOperations = await DetectOperationsAsync(item.IdTelemetry, startDate, db, token);
- stopwatch.Stop();
- if (newOperations.Any())
- {
- db.DetectedOperations.AddRange(newOperations);
- affected += await db.SaveChangesAsync(token);
- }
+ var telemetryId = telemetryIds[i];
+
+ var beginDate = lastDetectedDates.TryGetValue(telemetryId, out var date) ? date : (DateTimeOffset?)null;
+
+ onProgressCallback($"Start detecting telemetry: {telemetryId} from {beginDate}", i++ / telemetryIds.Length);
+ var detectedOperations = await detectedOperationService.DetectOperationsAsync(telemetryId, beginDate, token);
+
+ if (detectedOperations.Any())
+ await detectedOperationRepository.InsertRangeAsync(detectedOperations, token);
}
}
-
- //todo: move this logic to DetectedOperationsService
- internal static async Task> DetectOperationsAsync(int idTelemetry, DateTimeOffset begin, IAsbCloudDbContext db, CancellationToken token)
- {
- var query = db.TelemetryDataSaub
- .AsNoTracking()
- .Where(d => d.IdTelemetry == idTelemetry)
- .Where(d => d.BlockPosition >= 0)
- .Select(d => new DetectableTelemetry
- {
- DateTime = d.DateTime,
- IdUser = d.IdUser,
- Mode = d.Mode,
- WellDepth = d.WellDepth,
- Pressure = d.Pressure,
- HookWeight = d.HookWeight,
- BlockPosition = d.BlockPosition,
- BitDepth = d.BitDepth,
- RotorSpeed = d.RotorSpeed,
- })
- .OrderBy(d => d.DateTime);
-
- var take = 4 * 86_400; // 4 дня
- var startDate = begin;
- var detectedOperations = new List(8);
- DetectedOperation? lastDetectedOperation = null;
- const int minOperationLength = 5;
- const int maxDetectorsInterpolationFrameLength = 30;
- const int gap = maxDetectorsInterpolationFrameLength + minOperationLength;
-
- while (true)
- {
- var data = await query
- .Where(d => d.DateTime > startDate)
- .Take(take)
- .ToArrayAsync(token);
-
- if (data.Length < gap)
- break;
-
- var isDetected = false;
- var positionBegin = 0;
- var positionEnd = data.Length - gap;
- while (positionEnd > positionBegin)
- {
- foreach (var detector in detectors)
- {
- if (!detector.TryDetect(idTelemetry, data, positionBegin, positionEnd, lastDetectedOperation, out var result))
- continue;
-
- detectedOperations.Add(result!.Operation);
- lastDetectedOperation = result.Operation;
- isDetected = true;
- positionBegin = result.TelemetryEnd;
- break;
- }
-
- positionBegin += 1;
- }
-
- if (isDetected)
- startDate = lastDetectedOperation!.DateEnd;
- else
- startDate = data[positionEnd].DateTime;
- }
-
- return detectedOperations;
- }
}
diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs
index e296692c..f9cc64ee 100644
--- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs
+++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs
@@ -11,6 +11,7 @@ using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using AsbCloudApp.Requests;
namespace AsbCloudInfrastructure.Services.SAUB
{
@@ -22,7 +23,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
protected readonly ITelemetryService telemetryService;
protected readonly ITelemetryDataCache telemetryDataCache;
- public TelemetryDataBaseService(
+ protected TelemetryDataBaseService(
IAsbCloudDbContext db,
ITelemetryService telemetryService,
ITelemetryDataCache telemetryDataCache)
@@ -86,7 +87,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
}
///
- public virtual async Task> GetAsync(int idWell,
+ public virtual async Task> GetByWellAsync(int idWell,
DateTime dateBegin = default, double intervalSec = 600d,
int approxPointsCount = 1024, CancellationToken token = default)
{
@@ -146,23 +147,41 @@ namespace AsbCloudInfrastructure.Services.SAUB
}
///
- public virtual async Task> GetAsync(int idWell, AsbCloudApp.Requests.TelemetryDataRequest request, CancellationToken token)
+ public virtual async Task> GetByWellAsync(int idWell, TelemetryDataRequest request, CancellationToken token)
{
var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell);
if (telemetry is null)
return Enumerable.Empty();
- var timezone = telemetryService.GetTimezone(telemetry.Id);
+ return await GetByTelemetryAsync(telemetry.Id, request, token);
+ }
- var cache = telemetryDataCache.GetOrDefault(telemetry.Id, request);
+ public async Task> GetByTelemetryAsync(int idTelemetry, TelemetryDataRequest request, CancellationToken token)
+ {
+ var timezone = telemetryService.GetTimezone(idTelemetry);
+
+ var cache = telemetryDataCache.GetOrDefault(idTelemetry, request);
+
if(cache is not null)
return cache;
+
+ var query = BuildQuery(idTelemetry, request);
+ var entities = await query
+ .AsNoTracking()
+ .ToArrayAsync(token);
+
+ var dtos = entities.Select(e => Convert(e, timezone.Hours));
+
+ return dtos;
+ }
+
+ private IQueryable BuildQuery(int idTelemetry, TelemetryDataRequest request)
+ {
var dbSet = db.Set();
var query = dbSet
- .Where(d => d.IdTelemetry == telemetry.Id)
- .AsNoTracking();
+ .Where(d => d.IdTelemetry == idTelemetry);
if (request.GeDate.HasValue)
{
@@ -196,12 +215,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
break;
}
- var entities = await query
- .ToArrayAsync(token);
-
- var dtos = entities.Select(e => Convert(e, timezone.Hours));
-
- return dtos;
+ return query;
}
///
@@ -263,9 +277,9 @@ namespace AsbCloudInfrastructure.Services.SAUB
return telemetryDataCache.GetOrDefaultDataDateRange(telemetry.Id);
}
- public abstract TDto Convert(TEntity src, double timezoneOffset);
+ protected abstract TDto Convert(TEntity src, double timezoneOffset);
- public abstract TEntity Convert(TDto src, double timezoneOffset);
+ protected abstract TEntity Convert(TDto src, double timezoneOffset);
}
}
diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs
index fdced02c..92db8e4d 100644
--- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs
+++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs
@@ -111,7 +111,7 @@ public class TelemetryDataSaubService : TelemetryDataBaseService();
var telemetryUser = telemetryUserService
@@ -122,7 +122,7 @@ public class TelemetryDataSaubService : TelemetryDataBaseService();
var telemetryUser = telemetryUserService.GetOrDefault(src.IdTelemetry, src.IdUser ?? int.MinValue);
@@ -151,7 +151,7 @@ public class TelemetryDataSaubService : TelemetryDataBaseService 32_768
};
- var data = await GetAsync(idWell, beginDate, intervalSec, approxPointsCount, token);
+ var data = await GetByWellAsync(idWell, beginDate, intervalSec, approxPointsCount, token);
var fileName = $"DataSaub idWell{idWell}";
if (telemetry.Info is not null)
diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSpinService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSpinService.cs
index dab1e851..3a6f60d4 100644
--- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSpinService.cs
+++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSpinService.cs
@@ -16,14 +16,14 @@ namespace AsbCloudInfrastructure.Services.SAUB
: base(db, telemetryService, telemetryDataCache)
{ }
- public override TelemetryDataSpin Convert(TelemetryDataSpinDto src, double timezoneOffset)
+ protected override TelemetryDataSpin Convert(TelemetryDataSpinDto src, double timezoneOffset)
{
var entity = src.Adapt();
entity.DateTime = src.DateTime.ToUtcDateTimeOffset(timezoneOffset);
return entity;
}
- public override TelemetryDataSpinDto Convert(TelemetryDataSpin src, double timezoneOffset)
+ protected override TelemetryDataSpinDto Convert(TelemetryDataSpin src, double timezoneOffset)
{
var dto = src.Adapt();
dto.DateTime = src.DateTime.ToRemoteDateTime(timezoneOffset);
diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationExportService.cs b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationExportService.cs
index 89cf1494..5ce7a2e2 100644
--- a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationExportService.cs
+++ b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationExportService.cs
@@ -96,7 +96,7 @@ public class WellOperationExportService : IWellOperationExportService
row.Cell(DefaultTemplateInfo.ColumnCategoryInfo).SetCellValue(operation.CategoryInfo);
row.Cell(DefaultTemplateInfo.ColumnDepthStart).SetCellValue(operation.DepthStart);
row.Cell(DefaultTemplateInfo.ColumnDepthEnd).SetCellValue(operation.DepthEnd);
- row.Cell(DefaultTemplateInfo.ColumnDate).SetCellValue(operation.DateStart);
+ row.Cell(DefaultTemplateInfo.ColumnDate).SetCellValue(operation.DateStart.DateTime);
row.Cell(DefaultTemplateInfo.ColumnDuration).SetCellValue(operation.DurationHours);
row.Cell(DefaultTemplateInfo.ColumnComment).SetCellValue(operation.Comment);
}
diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs
index b8042275..800979e5 100644
--- a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs
+++ b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs
@@ -5,20 +5,24 @@ using System.Linq;
using AsbCloudApp.Data;
using AsbCloudApp.Data.WellOperationImport;
using AsbCloudApp.Repositories;
+using AsbCloudApp.Services;
using AsbCloudApp.Services.WellOperationImport;
namespace AsbCloudInfrastructure.Services.WellOperationImport;
public class WellOperationImportService : IWellOperationImportService
{
+ private readonly IWellService wellService;
private readonly IWellOperationRepository wellOperationRepository;
private static readonly DateTime dateLimitMin = new(2001, 1, 1, 0, 0, 0);
private static readonly DateTime dateLimitMax = new(2099, 1, 1, 0, 0, 0);
private static readonly TimeSpan drillingDurationLimitMax = TimeSpan.FromDays(366);
- public WellOperationImportService(IWellOperationRepository wellOperationRepository)
+ public WellOperationImportService(IWellService wellService,
+ IWellOperationRepository wellOperationRepository)
{
+ this.wellService = wellService;
this.wellOperationRepository = wellOperationRepository;
}
@@ -30,8 +34,12 @@ public class WellOperationImportService : IWellOperationImportService
var categories = wellOperationRepository.GetCategories(false);
var wellOperations = new List();
-
- foreach (var row in sheet.Rows)
+
+ var rows = sheet.Rows.OrderBy(r => r.Date);
+
+ var prevRow = new RowDto();
+
+ foreach (var row in rows)
{
try
{
@@ -58,15 +66,18 @@ public class WellOperationImportService : IWellOperationImportService
if (row.Date < dateLimitMin && row.Date > dateLimitMax)
throw new FileFormatException(
$"Лист '{sheet.Name}'. Строка '{row.Number}' неправильно получена дата начала операции");
-
- if (wellOperations.LastOrDefault()?.DateStart > row.Date)
+
+ if (prevRow.Date > row.Date)
throw new FileFormatException(
$"Лист '{sheet.Name}' строка '{row.Number}' дата позднее даты предыдущей операции");
if (row.Duration is not (>= 0d and <= 240d))
throw new FileFormatException($"Лист '{sheet.Name}'. Строка '{row.Number}' некорректная длительность операции");
- wellOperations.Add(new WellOperationDto
+ var timezone = wellService.GetTimezone(idWell);
+ var timezoneOffset = TimeSpan.FromHours(timezone.Hours);
+
+ var wellOperation = new WellOperationDto
{
IdWell = idWell,
IdUser = idUser,
@@ -76,10 +87,14 @@ public class WellOperationImportService : IWellOperationImportService
CategoryInfo = row.CategoryInfo,
DepthStart = row.DepthStart,
DepthEnd = row.DepthEnd,
- DateStart = row.Date,
+ DateStart = new DateTimeOffset(row.Date, timezoneOffset),
DurationHours = row.Duration,
Comment = row.Comment
- });
+ };
+
+ wellOperations.Add(wellOperation);
+
+ prevRow = row;
}
catch (FileFormatException ex)
{
diff --git a/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj b/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj
index a9d7713a..1c641f69 100644
--- a/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj
+++ b/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj
@@ -18,6 +18,14 @@
+
+
+
+
+
+
+
+
diff --git a/AsbCloudWebApi.IntegrationTests/Clients/IWellOperationClient.cs b/AsbCloudWebApi.IntegrationTests/Clients/IWellOperationClient.cs
index 07754ed1..8e2db98f 100644
--- a/AsbCloudWebApi.IntegrationTests/Clients/IWellOperationClient.cs
+++ b/AsbCloudWebApi.IntegrationTests/Clients/IWellOperationClient.cs
@@ -6,16 +6,22 @@ namespace AsbCloudWebApi.IntegrationTests.Clients;
public interface IWellOperationClient
{
- private const string BaseRoute = "/api/well/{idWell}/wellOperations";
+ private const string BaseRoute = "/api/well/{idWell}/wellOperations";
- [Post(BaseRoute + "/{idType}/{deleteBeforeInsert}")]
- Task> InsertRangeAsync(int idWell, int idType, bool deleteBeforeInsert, [Body] IEnumerable dtos);
+ [Post(BaseRoute + "/{idType}/{deleteBeforeInsert}")]
+ Task> InsertRangeAsync(int idWell, int idType, bool deleteBeforeInsert, [Body] IEnumerable dtos);
- [Put(BaseRoute + "/{idOperation}")]
- Task> UpdateAsync(int idWell, int idOperation, [Body] WellOperationDto value, CancellationToken token);
+ [Put(BaseRoute + "/{idOperation}")]
+ Task> UpdateAsync(int idWell, int idOperation, [Body] WellOperationDto value, CancellationToken token);
[Get(BaseRoute + "/plan")]
Task>> GetPageOperationsPlanAsync(int idWell,
[Query] WellOperationRequestBase request,
CancellationToken token);
+
+ [Multipart]
+ [Post(BaseRoute + "/import/plan/default")]
+ Task>> ImportPlanDefaultExcelFileAsync(int idWell,
+ [AliasAs("files")] IEnumerable streams,
+ CancellationToken token);
}
\ No newline at end of file
diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/WellOperationControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/WellOperationControllerTest.cs
index 46ce1d4d..a47d5f09 100644
--- a/AsbCloudWebApi.IntegrationTests/Controllers/WellOperationControllerTest.cs
+++ b/AsbCloudWebApi.IntegrationTests/Controllers/WellOperationControllerTest.cs
@@ -2,7 +2,10 @@ using AsbCloudApp.Data;
using AsbCloudDb.Model;
using AsbCloudWebApi.IntegrationTests.Clients;
using System.Net;
+using System.Reflection;
using AsbCloudApp.Requests;
+using AsbCloudWebApi.IntegrationTests.Data;
+using Refit;
using Xunit;
namespace AsbCloudWebApi.IntegrationTests.Controllers;
@@ -28,7 +31,7 @@ public class WellOperationControllerTest : BaseIntegrationTest
DepthEnd = 20.0,
Day = 0.0,
NptHours = 0.0,
- DateStart = new DateTimeOffset(new DateTime(2023, 02, 03, 1, 0, 0, DateTimeKind.Unspecified)),
+ DateStart = new DateTimeOffset(new DateTime(2023, 1, 10), TimeSpan.FromHours(Defaults.Wells[0].Timezone.Hours)),
DurationHours = 1.0,
Comment = "1",
IdUser = 1,
@@ -117,4 +120,37 @@ public class WellOperationControllerTest : BaseIntegrationTest
var excludeProps = new[] { nameof(WellOperationDto.Id) };
MatchHelper.Match(dto, wellOperation, excludeProps);
}
+
+ [Fact]
+ public async Task ImportPlanDefaultExcelFileAsync_returns_success()
+ {
+ //arrange
+ //TODO: вынести в метод расширения. Сделать когда доберёмся до рефакторинга операций по скважине
+ var resourceName = Assembly.GetExecutingAssembly()
+ .GetManifestResourceNames()
+ .FirstOrDefault(n => n.EndsWith("WellOperationsPlan.xlsx"));
+
+ if (string.IsNullOrWhiteSpace(resourceName))
+ throw new ArgumentNullException(nameof(resourceName));
+
+ var stream = Assembly.GetExecutingAssembly()
+ .GetManifestResourceStream(resourceName);
+
+ if (stream is null)
+ throw new ArgumentNullException(nameof(stream));
+
+ var memoryStream = new MemoryStream();
+ stream.CopyTo(memoryStream);
+ memoryStream.Position = 0;
+
+ //act
+ var streamPart = new StreamPart(memoryStream, "WellOperations.xlsx", "application/octet-stream");
+
+ var response = await client.ImportPlanDefaultExcelFileAsync(idWell, new[] { streamPart }, CancellationToken.None);
+
+ //assert
+ Assert.NotNull(response.Content);
+ Assert.Equal(4, response.Content.Count());
+ Assert.True(response.Content.All(w => Math.Abs(w.DateStart.Offset.Hours - Defaults.Wells[0].Timezone.Hours) < 0.1));
+ }
}
\ No newline at end of file
diff --git a/AsbCloudWebApi.IntegrationTests/WellOperationsPlan.xlsx b/AsbCloudWebApi.IntegrationTests/WellOperationsPlan.xlsx
new file mode 100644
index 00000000..dd1a2781
Binary files /dev/null and b/AsbCloudWebApi.IntegrationTests/WellOperationsPlan.xlsx differ
diff --git a/AsbCloudWebApi.Tests/Services/DetectedOperations/Detectors/DetectorDrillingTests.cs b/AsbCloudWebApi.Tests/Services/DetectedOperations/Detectors/DetectorDrillingTests.cs
index 8a61dd15..bd8c5690 100644
--- a/AsbCloudWebApi.Tests/Services/DetectedOperations/Detectors/DetectorDrillingTests.cs
+++ b/AsbCloudWebApi.Tests/Services/DetectedOperations/Detectors/DetectorDrillingTests.cs
@@ -1,5 +1,5 @@
using System.Collections.Generic;
-using AsbCloudDb.Model;
+using AsbCloudApp.Data.DetectedOperation;
using AsbCloudInfrastructure.Services.DetectOperations;
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
using Xunit;
@@ -10,8 +10,7 @@ public class DetectorDrillingTests : DetectorDrilling
{
private const int idSlide = 5002;
private const int idRotor = 5003;
- private const int idSlideWithOscillation = 12000;
-
+
[Theory]
[MemberData(nameof(TelemetryRangeDrillingRotor))]
public void DefineDrillingOperation_ShouldReturn_DrillingRotor(DetectableTelemetry[] telemetryRange)
@@ -54,7 +53,7 @@ public class DetectorDrillingTests : DetectorDrilling
//arrange
var operationDetectorResult = new OperationDetectorResult
{
- Operation = new DetectedOperation
+ Operation = new DetectedOperationDto
{
DepthStart = 5000,
DepthEnd = 6000,
@@ -76,7 +75,7 @@ public class DetectorDrillingTests : DetectorDrilling
//arrange
var operationDetectorResult = new OperationDetectorResult
{
- Operation = new DetectedOperation
+ Operation = new DetectedOperationDto
{
DepthStart = 5000,
DepthEnd = 5000,
@@ -201,7 +200,6 @@ public class DetectorDrillingTests : DetectorDrilling
{
new DetectableTelemetry
{
- IdUser = 1,
WellDepth = 415.306f,
Pressure = 53.731934f,
HookWeight = 41.049942f,
@@ -211,7 +209,6 @@ public class DetectorDrillingTests : DetectorDrilling
},
new DetectableTelemetry
{
- IdUser = 1,
WellDepth = 415.311f,
Pressure = 57.660595f,
HookWeight = 40.898712f,
@@ -221,7 +218,6 @@ public class DetectorDrillingTests : DetectorDrilling
},
new DetectableTelemetry
{
- IdUser = 1,
WellDepth = 415.326f,
Pressure = 59.211086f,
HookWeight = 40.882797f,
@@ -231,7 +227,6 @@ public class DetectorDrillingTests : DetectorDrilling
},
new DetectableTelemetry
{
- IdUser = 1,
WellDepth = 415.344f,
Pressure = 59.484406f,
HookWeight = 40.91972f,
@@ -241,7 +236,6 @@ public class DetectorDrillingTests : DetectorDrilling
},
new DetectableTelemetry
{
- IdUser = 1,
WellDepth = 415.364f,
Pressure = 60.739918f,
HookWeight = 40.795666f,
@@ -251,7 +245,6 @@ public class DetectorDrillingTests : DetectorDrilling
},
new DetectableTelemetry
{
- IdUser = 1,
WellDepth = 415.378f,
Pressure = 62.528984f,
HookWeight = 40.52114f,
@@ -261,7 +254,6 @@ public class DetectorDrillingTests : DetectorDrilling
},
new DetectableTelemetry
{
- IdUser = 1,
WellDepth = 415.392f,
Pressure = 67.0039f,
HookWeight = 38.878895f,
@@ -271,7 +263,6 @@ public class DetectorDrillingTests : DetectorDrilling
},
new DetectableTelemetry
{
- IdUser = 1,
WellDepth = 415.392f,
Pressure = 65.72418f,
HookWeight = 42.53173f,
@@ -281,7 +272,6 @@ public class DetectorDrillingTests : DetectorDrilling
},
new DetectableTelemetry
{
- IdUser = 1,
WellDepth = 415.392f,
Pressure = 56.82195f,
HookWeight = 43.15844f,
diff --git a/AsbCloudWebApi.Tests/Services/WellOperationExport/WellOperationExportServiceTest.cs b/AsbCloudWebApi.Tests/Services/WellOperationExport/WellOperationExportServiceTest.cs
index 2590df26..3d66aab9 100644
--- a/AsbCloudWebApi.Tests/Services/WellOperationExport/WellOperationExportServiceTest.cs
+++ b/AsbCloudWebApi.Tests/Services/WellOperationExport/WellOperationExportServiceTest.cs
@@ -117,7 +117,7 @@ namespace AsbCloudWebApi.Tests.Services.WellOperationExport
wellOperationImportTemplateService = new WellOperationImportTemplateService();
wellOperationExportService = new WellOperationExportService(wellOperationRepository, wellService, wellOperationImportTemplateService);
- wellOperationImportService = new WellOperationImportService(wellOperationRepository);
+ wellOperationImportService = new WellOperationImportService(wellService, wellOperationRepository);
wellOperationDefaultExcelParser = new WellOperationDefaultExcelParser();
this.output = output;
}
diff --git a/AsbCloudWebApi/Controllers/SAUB/TelemetryDataBaseController.cs b/AsbCloudWebApi/Controllers/SAUB/TelemetryDataBaseController.cs
index 4c8ec124..5ff378de 100644
--- a/AsbCloudWebApi/Controllers/SAUB/TelemetryDataBaseController.cs
+++ b/AsbCloudWebApi/Controllers/SAUB/TelemetryDataBaseController.cs
@@ -92,7 +92,7 @@ namespace AsbCloudWebApi.Controllers.SAUB
if (!isCompanyOwnsWell)
return Forbid();
- var content = await telemetryDataService.GetAsync(idWell, begin,
+ var content = await telemetryDataService.GetByWellAsync(idWell, begin,
intervalSec, approxPointsCount, token).ConfigureAwait(false);
return Ok(content);
@@ -123,7 +123,7 @@ namespace AsbCloudWebApi.Controllers.SAUB
if (!isCompanyOwnsWell)
return Forbid();
- var content = await telemetryDataService.GetAsync(idWell, request, token);
+ var content = await telemetryDataService.GetByWellAsync(idWell, request, token);
return Ok(content);
}
diff --git a/AsbCloudWebApi/Controllers/WellOperationController.cs b/AsbCloudWebApi/Controllers/WellOperationController.cs
index 83f2987a..0d53a4ad 100644
--- a/AsbCloudWebApi/Controllers/WellOperationController.cs
+++ b/AsbCloudWebApi/Controllers/WellOperationController.cs
@@ -281,7 +281,6 @@ namespace AsbCloudWebApi.Controllers
foreach (var wellOperation in wellOperations)
{
wellOperation.IdWell = idWell;
- wellOperation.LastUpdateDate = DateTimeOffset.UtcNow;
wellOperation.IdUser = User.GetUserId();
wellOperation.IdType = idType;
}
@@ -313,7 +312,6 @@ namespace AsbCloudWebApi.Controllers
value.IdWell = idWell;
value.Id = idOperation;
- value.LastUpdateDate = DateTimeOffset.UtcNow;
value.IdUser = User.GetUserId();
var result = await operationRepository.UpdateAsync(value, token)