diff --git a/AsbCloudApp/Data/LimitingParameterDataDto.cs b/AsbCloudApp/Data/LimitingParameterDataDto.cs
index ee957947..83db213b 100644
--- a/AsbCloudApp/Data/LimitingParameterDataDto.cs
+++ b/AsbCloudApp/Data/LimitingParameterDataDto.cs
@@ -21,12 +21,12 @@ namespace AsbCloudApp.Data
///
/// Дата начала ограничения
///
- public DateTimeOffset DateStart { get; set; }
+ public DateTime DateStart { get; set; }
///
/// Дата окончания ограничения
///
- public DateTimeOffset DateEnd { get; set; }
+ public DateTime DateEnd { get; set; }
///
/// Глубина начала ограничения
diff --git a/AsbCloudApp/Data/ProcessMapDto.cs b/AsbCloudApp/Data/ProcessMap/ProcessMapDto.cs
similarity index 98%
rename from AsbCloudApp/Data/ProcessMapDto.cs
rename to AsbCloudApp/Data/ProcessMap/ProcessMapDto.cs
index 72990b03..9a460acb 100644
--- a/AsbCloudApp/Data/ProcessMapDto.cs
+++ b/AsbCloudApp/Data/ProcessMap/ProcessMapDto.cs
@@ -1,6 +1,6 @@
using System;
-namespace AsbCloudApp.Data
+namespace AsbCloudApp.Data.ProcessMap
{
#nullable enable
///
diff --git a/AsbCloudApp/Data/ProcessMap/ProcessMapReportDto.cs b/AsbCloudApp/Data/ProcessMap/ProcessMapReportDto.cs
new file mode 100644
index 00000000..514de0f9
--- /dev/null
+++ b/AsbCloudApp/Data/ProcessMap/ProcessMapReportDto.cs
@@ -0,0 +1,58 @@
+using System;
+
+namespace AsbCloudApp.Data.ProcessMap
+{
+#nullable enable
+ ///
+ /// Модель РТК
+ ///
+ public class ProcessMapReportDto
+ {
+ ///
+ /// Идентификатор скважины
+ ///
+ public int IdWell { get; set; }
+
+ ///
+ /// Глубина по стволу, м
+ ///
+ /// на начало интервала
+ ///
+ ///
+ public double DepthStart { get; set; }
+
+ ///
+ /// Дата/ время
+ ///
+ /// на начало интервала
+ ///
+ ///
+ public DateTime DateStart { get; set; }
+
+ ///
+ /// Время мех бурения, ч
+ ///
+ public double MechDrillingHours { get; set; }
+
+ ///
+ /// Слайд
+ ///
+ public ProcessMapReportRowDto Slide { get; set; } = null!;
+
+ ///
+ /// Ротор
+ ///
+ public ProcessMapReportRowDto Rotor { get; set; } = null!;
+
+ ///
+ /// название секции скважины
+ ///
+ public int IdWellSectionType { get; set; }
+
+ ///
+ /// название секции скважины
+ ///
+ public string WellSectionTypeName { get; set; } = null!;
+ }
+#nullable disable
+}
diff --git a/AsbCloudApp/Data/ProcessMap/ProcessMapReportParamsDto.cs b/AsbCloudApp/Data/ProcessMap/ProcessMapReportParamsDto.cs
new file mode 100644
index 00000000..cf180f07
--- /dev/null
+++ b/AsbCloudApp/Data/ProcessMap/ProcessMapReportParamsDto.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AsbCloudApp.Data.ProcessMap
+{
+#nullable enable
+ ///
+ /// Параметры РТК
+ ///
+ public class ProcessMapReportParamsDto
+ {
+ ///
+ /// Уставка план
+ ///
+ public double? SetpointPlan { get; set; }
+
+ ///
+ /// Уставка факт
+ ///
+ public double? SetpointFact { get; set; }
+
+ ///
+ /// Факт
+ ///
+ public double? Fact { get; set; }
+
+ ///
+ /// Ограничение
+ ///
+ public double? Limit { get; set; }
+
+ ///
+ /// Процент бурения по уставке ,%
+ ///
+ public double? PercDrillingSetpoint { get; set; }
+ }
+#nullable disable
+}
diff --git a/AsbCloudApp/Data/ProcessMap/ProcessMapReportRowDto.cs b/AsbCloudApp/Data/ProcessMap/ProcessMapReportRowDto.cs
new file mode 100644
index 00000000..737f73ea
--- /dev/null
+++ b/AsbCloudApp/Data/ProcessMap/ProcessMapReportRowDto.cs
@@ -0,0 +1,45 @@
+namespace AsbCloudApp.Data.ProcessMap
+{
+#nullable enable
+ ///
+ /// Строки РТК
+ ///
+ public class ProcessMapReportRowDto
+ {
+ ///
+ /// Проходка, м
+ ///
+ public double? DeltaDepth { get; set; }
+
+ ///
+ /// Перепад давления, атм
+ ///
+ public ProcessMapReportParamsDto PressureDiff { get; set; } = new();
+
+ ///
+ /// Нагрузка, т
+ ///
+ public ProcessMapReportParamsDto AxialLoad { get; set; } = new();
+
+ ///
+ /// Момент на ВСП, кНхМ
+ ///
+ public ProcessMapReportParamsDto TopDriveTorque { get; set; } = new();
+
+ ///
+ /// Ограничение скорости, м/ч
+ ///
+ public ProcessMapReportParamsDto SpeedLimit { get; set; } = new();
+
+ ///
+ /// Процент использования системы АПД, %
+ ///
+ public double Usage { get; set; }
+
+ ///
+ /// Фактическая механическая скорость, м/ч
+ ///
+ public double Rop { get; set; }
+ }
+#nullable disable
+}
diff --git a/AsbCloudApp/Data/SAUB/TelemetryDataSaubStatDto.cs b/AsbCloudApp/Data/SAUB/TelemetryDataSaubStatDto.cs
new file mode 100644
index 00000000..90bbd5f0
--- /dev/null
+++ b/AsbCloudApp/Data/SAUB/TelemetryDataSaubStatDto.cs
@@ -0,0 +1,117 @@
+using System;
+
+namespace AsbCloudApp.Data.SAUB
+{
+#nullable enable
+ ///
+ /// Статистика телеметрии САУБ (усредненные значения) по интервалам глубины
+ ///
+ public class TelemetryDataSaubStatDto
+ {
+ ///
+ /// Кол-во записей в интервале
+ ///
+ public int Count { get; set; }
+
+ ///
+ /// Дата начала интервала
+ ///
+ public DateTime DateMin { get; set; }
+
+ ///
+ /// Дата окончания интервала
+ ///
+ public DateTime DateMax { get; set; }
+
+ ///
+ /// Глубина начала интервала
+ ///
+ public float WellDepthMin { get; set; }
+
+ ///
+ /// Глубина окончания интервала
+ ///
+ public float WellDepthMax { get; set; }
+
+ ///
+ /// Давление
+ ///
+ public float Pressure { get; set; }
+
+ ///
+ /// действующее задание давления
+ ///
+ public float PressureSp { get; set; }
+
+ ///
+ /// Давление при холостом ходе.
+ ///
+ public float PressureIdle { get; set; }
+
+ ///
+ /// задание давления для роторного режима
+ ///
+ public float PressureSpRotor { get; set; }
+
+ ///
+ /// задание давления для режима слайда
+ ///
+ public float PressureSpSlide { get; set; }
+
+ ///
+ /// ограничение макс перепада давления
+ ///
+ public float PressureDeltaLimitMax { get; set; }
+
+ ///
+ /// осевая нагрузка
+ ///
+ public float AxialLoad { get; set; }
+
+ ///
+ /// задание осевой нагрузки
+ ///
+ public float AxialLoadSp { get; set; }
+
+ ///
+ /// ограничение макс. осевой нагрузки
+ ///
+ public float AxialLoadLimitMax { get; set; }
+
+ ///
+ /// момент ротора
+ ///
+ public float RotorTorque { get; set; }
+
+ ///
+ /// задание момента ротора
+ ///
+ public float RotorTorqueSp { get; set; }
+
+ ///
+ /// момент ротора на х.х.
+ ///
+ public float RotorTorqueLimitMax { get; set; }
+
+ ///
+ /// Талевый блок. Скорость
+ ///
+ public float BlockSpeed { get; set; }
+
+ ///
+ /// Талевый блок. Задание скорости
+ ///
+ public float BlockSpeedSp { get; set; }
+
+ ///
+ /// Талевый блок. Задание скорости для роторного бурения
+ ///
+ public float BlockSpeedSpRotor { get; set; }
+
+ ///
+ /// Талевый блок. Задание скорости для режима слайда
+ ///
+ public float BlockSpeedSpSlide { get; set; }
+ }
+#nullable disable
+}
diff --git a/AsbCloudApp/Repositories/ILimitingParameterRepository.cs b/AsbCloudApp/Repositories/ILimitingParameterRepository.cs
index 507270ef..a9b61823 100644
--- a/AsbCloudApp/Repositories/ILimitingParameterRepository.cs
+++ b/AsbCloudApp/Repositories/ILimitingParameterRepository.cs
@@ -20,6 +20,16 @@ namespace AsbCloudApp.Repositories
///
///
Task> GetLimitingParametersAsync(LimitingParameterRequest request, WellDto wellDto, CancellationToken token);
+
+ ///
+ /// Получение списка ограничивающих параметров по идентификатору скважины
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task> GetLimitingParametersAsync(LimitingParameterRequest request, int idTelemetry, double timezoneHours, CancellationToken token);
}
#nullable disable
}
diff --git a/AsbCloudApp/Services/IWellOperationService.cs b/AsbCloudApp/Repositories/IWellOperationRepository.cs
similarity index 75%
rename from AsbCloudApp/Services/IWellOperationService.cs
rename to AsbCloudApp/Repositories/IWellOperationRepository.cs
index 61b9b4b0..4075445f 100644
--- a/AsbCloudApp/Services/IWellOperationService.cs
+++ b/AsbCloudApp/Repositories/IWellOperationRepository.cs
@@ -5,13 +5,13 @@ using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-namespace AsbCloudApp.Services
+namespace AsbCloudApp.Repositories
{
#nullable enable
///
/// сервис операций по скважине
///
- public interface IWellOperationService
+ public interface IWellOperationRepository
{
///
/// список названий операций
@@ -19,61 +19,6 @@ namespace AsbCloudApp.Services
///
IEnumerable GetCategories();
- // TODO: объединить параметры в объект запроса
- ///
- /// Получить список операций
- ///
- ///
- ///
- ///
- Task> GetOperationsAsync(
- WellOperationRequest request,
- CancellationToken token);
-
- ///
- /// Получить статистику операции по скважине с группировкой по категориям
- ///
- ///
- ///
- ///
- Task> GetGroupOperationsStatAsync(
- WellOperationRequest request,
- CancellationToken token);
-
- ///
- /// Получить операцию по id
- ///
- ///
- ///
- ///
- Task GetOrDefaultAsync(int id, CancellationToken token);
-
- ///
- /// Добавить несколько операций за один раз
- ///
- ///
- ///
- ///
- Task InsertRangeAsync(
- IEnumerable wellOperationDtos, CancellationToken token);
-
- ///
- /// Обновить существующую операцию
- ///
- ///
- ///
- ///
- Task UpdateAsync(WellOperationDto item,
- CancellationToken token);
-
- ///
- /// Удалить операции по id
- ///
- ///
- ///
- ///
- Task DeleteAsync(IEnumerable ids, CancellationToken token);
-
///
/// Список секций
///
@@ -86,6 +31,64 @@ namespace AsbCloudApp.Services
///
///
DateTimeOffset? FirstOperationDate(int idWell);
+
+ ///
+ /// Получить страницу списка операций
+ ///
+ ///
+ ///
+ ///
+ Task> GetAsync(WellOperationRequest request, CancellationToken token);
+
+ ///
+ /// Получить страницу списка операций
+ ///
+ ///
+ ///
+ ///
+ Task> GetPageAsync(WellOperationRequest request, CancellationToken token);
+
+ ///
+ /// Получить операцию по id
+ ///
+ ///
+ ///
+ ///
+ Task GetOrDefaultAsync(int id, CancellationToken token);
+
+ ///
+ /// Получить статистику операции по скважине с группировкой по категориям
+ ///
+ ///
+ ///
+ ///
+ Task> GetGroupOperationsStatAsync(
+ WellOperationRequest request,
+ CancellationToken token);
+
+ ///
+ /// Добавить несколько операций за один раз
+ ///
+ ///
+ ///
+ ///
+ Task InsertRangeAsync(IEnumerable wellOperationDtos, CancellationToken token);
+
+ ///
+ /// Обновить существующую операцию
+ ///
+ ///
+ ///
+ ///
+ Task UpdateAsync(WellOperationDto dto, CancellationToken token);
+
+ ///
+ /// Удалить операции по id
+ ///
+ ///
+ ///
+ ///
+ Task DeleteAsync(IEnumerable ids, CancellationToken token);
}
#nullable disable
-}
+}
\ No newline at end of file
diff --git a/AsbCloudApp/Services/IProcessMapReportService.cs b/AsbCloudApp/Services/IProcessMapReportService.cs
new file mode 100644
index 00000000..a4bf783b
--- /dev/null
+++ b/AsbCloudApp/Services/IProcessMapReportService.cs
@@ -0,0 +1,20 @@
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace AsbCloudApp.Services
+{
+ ///
+ /// Сервис формирования РТК.
+ ///
+ public interface IProcessMapReportService
+ {
+ ///
+ /// Сформировать.
+ ///
+ ///
+ ///
+ ///
+ Task MakeReportAsync(int idWell, CancellationToken token = default);
+ }
+}
diff --git a/AsbCloudApp/Services/IProcessMapRepository.cs b/AsbCloudApp/Services/IProcessMapRepository.cs
index a898fa4a..8c9ab6f0 100644
--- a/AsbCloudApp/Services/IProcessMapRepository.cs
+++ b/AsbCloudApp/Services/IProcessMapRepository.cs
@@ -1,4 +1,4 @@
-using AsbCloudApp.Data;
+using AsbCloudApp.Data.ProcessMap;
using System;
using System.Collections.Generic;
using System.Threading;
diff --git a/AsbCloudApp/Services/IProcessMapService.cs b/AsbCloudApp/Services/IProcessMapService.cs
new file mode 100644
index 00000000..3d2eeff4
--- /dev/null
+++ b/AsbCloudApp/Services/IProcessMapService.cs
@@ -0,0 +1,24 @@
+using AsbCloudApp.Data.ProcessMap;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace AsbCloudApp.Services
+{
+#nullable enable
+ ///
+ /// Сервис формирования РТК
+ ///
+ public interface IProcessMapService
+ {
+ ///
+ /// Получение моделей РТК
+ ///
+ ///
+ ///
+ ///
+ Task> GetProcessMapAsync(int idWell, CancellationToken token);
+ }
+#nullable disable
+}
diff --git a/AsbCloudApp/Services/ITelemetryDataSaubService.cs b/AsbCloudApp/Services/ITelemetryDataSaubService.cs
new file mode 100644
index 00000000..d6bdcb6f
--- /dev/null
+++ b/AsbCloudApp/Services/ITelemetryDataSaubService.cs
@@ -0,0 +1,26 @@
+using AsbCloudApp.Data.SAUB;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+#nullable enable
+namespace AsbCloudApp.Services
+{
+ ///
+ /// Телеметрия САУБ
+ ///
+ public interface ITelemetryDataSaubService : ITelemetryDataService
+ {
+ ///
+ /// усредненная статистика по 1м за весь период
+ ///
+ /// МЕДЛЕННЫЙ ЗАПРОС
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task> GetTelemetryDataStatAsync(int idTelemetry, CancellationToken token);
+ }
+}
+#nullable disable
\ No newline at end of file
diff --git a/AsbCloudApp/Services/ITelemetryDataService.cs b/AsbCloudApp/Services/ITelemetryDataService.cs
index 8efc74ae..585843ff 100644
--- a/AsbCloudApp/Services/ITelemetryDataService.cs
+++ b/AsbCloudApp/Services/ITelemetryDataService.cs
@@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
+
#nullable enable
namespace AsbCloudApp.Services
{
@@ -33,7 +34,7 @@ namespace AsbCloudApp.Services
///
///
///
- Task UpdateDataAsync(string uid, IEnumerable dtos, CancellationToken token = default);
+ Task UpdateDataAsync(string uid, IEnumerable dtos, CancellationToken token);
}
}
#nullable disable
\ No newline at end of file
diff --git a/AsbCloudDb/Model/WellOperation.cs b/AsbCloudDb/Model/WellOperation.cs
index 8ef65c91..4abe21fb 100644
--- a/AsbCloudDb/Model/WellOperation.cs
+++ b/AsbCloudDb/Model/WellOperation.cs
@@ -10,6 +10,9 @@ namespace AsbCloudDb.Model
[Table("t_well_operation"), Comment("Данные по операциям на скважине")]
public class WellOperation : IId
{
+ public const int IdOperationTypePlan = 0;
+ public const int IdOperationTypeFact = 1;
+
[Key]
[Column("id")]
public int Id { get; set; }
@@ -23,6 +26,9 @@ namespace AsbCloudDb.Model
[Column("id_category"), Comment("Id категории операции")]
public int IdCategory { get; set; }
+ ///
+ /// Тип 0 = План или 1 = Факт
+ ///
[Column("id_type"), Comment("0 = План или 1 = Факт")]
public int IdType { get; set; }
diff --git a/AsbCloudDb/Model/WellOperationCategory.cs b/AsbCloudDb/Model/WellOperationCategory.cs
index 4cafa51e..3781a9e6 100644
--- a/AsbCloudDb/Model/WellOperationCategory.cs
+++ b/AsbCloudDb/Model/WellOperationCategory.cs
@@ -2,7 +2,6 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
-using System;
namespace AsbCloudDb.Model
{
diff --git a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj
index c9f3963d..1a8e2432 100644
--- a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj
+++ b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj
@@ -13,6 +13,7 @@
+
@@ -30,6 +31,7 @@
+
diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs
index b2625b8d..1b7b05d1 100644
--- a/AsbCloudInfrastructure/DependencyInjection.cs
+++ b/AsbCloudInfrastructure/DependencyInjection.cs
@@ -13,6 +13,7 @@ using AsbCloudInfrastructure.Services.DailyReport;
using AsbCloudInfrastructure.Services.DetectOperations;
using AsbCloudInfrastructure.Services.DrillingProgram;
using AsbCloudInfrastructure.Services.PlannedTrajectory;
+using AsbCloudInfrastructure.Services.ProcessMap;
using AsbCloudInfrastructure.Services.SAUB;
using AsbCloudInfrastructure.Services.Subsystems;
using AsbCloudInfrastructure.Services.WellOperationService;
@@ -124,9 +125,9 @@ namespace AsbCloudInfrastructure
services.AddTransient();
services.AddTransient();
services.AddTransient();
- services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
services.AddTransient();
services.AddTransient();
services.AddTransient();
@@ -137,6 +138,8 @@ namespace AsbCloudInfrastructure
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
// admin crud services:
services.AddTransient, CrudCacheRepositoryBase>(s =>
@@ -181,7 +184,7 @@ namespace AsbCloudInfrastructure
services.AddTransient, CrudCacheRepositoryBase>();
// TelemetryData services
- services.AddTransient, TelemetryDataSaubService>();
+ services.AddTransient();
services.AddTransient, TelemetryDataSpinService>();
// Wits
diff --git a/AsbCloudInfrastructure/Repository/LimitingParameterRepository.cs b/AsbCloudInfrastructure/Repository/LimitingParameterRepository.cs
index 88c5f869..9c05d743 100644
--- a/AsbCloudInfrastructure/Repository/LimitingParameterRepository.cs
+++ b/AsbCloudInfrastructure/Repository/LimitingParameterRepository.cs
@@ -3,6 +3,7 @@ using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudDb.Model;
using Microsoft.EntityFrameworkCore;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
@@ -19,41 +20,49 @@ namespace AsbCloudInfrastructure.Repository
{
this.context = context;
}
+
public async Task> GetLimitingParametersAsync(LimitingParameterRequest request, WellDto wellDto, CancellationToken token)
{
- var query = BuildQuery(request, wellDto);
+ var timezoneOffset = wellDto.Timezone.Hours;
+ var IdTelemetry = wellDto.IdTelemetry!.Value;
+ return await GetLimitingParametersAsync(request, IdTelemetry, timezoneOffset, token);
+ }
+
+ public async Task> GetLimitingParametersAsync(LimitingParameterRequest request, int idTelemetry, double timezoneHours, CancellationToken token)
+ {
+ var timezoneSpan = TimeSpan.FromHours(timezoneHours);
+ var query = BuildQuery(request, idTelemetry, timezoneHours);
var data = (await query.ToListAsync(token))
.Select(x => new LimitingParameterDataDto
{
- IdWell = wellDto.Id,
+ IdWell = request.IdWell,
IdTelemetry = x.IdTelemetry,
IdFeedRegulator = x.IdFeedRegulator,
- DateStart = x.DateStart,
- DateEnd = x.DateEnd,
+ DateStart = DateTime.SpecifyKind(x.DateStart.UtcDateTime + timezoneSpan, DateTimeKind.Unspecified),
+ DateEnd = DateTime.SpecifyKind(x.DateEnd.UtcDateTime + timezoneSpan, DateTimeKind.Unspecified),
DepthStart = x.DepthStart,
DepthEnd = x.DepthEnd
});
-
return data;
}
- private IQueryable BuildQuery(LimitingParameterRequest request, WellDto wellDto)
+ private IQueryable BuildQuery(LimitingParameterRequest request, int idTelemetry, double timezoneHours)
{
var query = context.LimitingParameter
.OrderBy(x => x.Id)
- .Where(x => x.IdTelemetry == wellDto.IdTelemetry)
+ .Where(x => x.IdTelemetry == idTelemetry)
.AsNoTracking();
if (request.GtDate.HasValue)
{
- var gtDate = request.GtDate.Value.ToUtcDateTimeOffset(wellDto.Timezone.Hours);
+ var gtDate = request.GtDate.Value.ToUtcDateTimeOffset(timezoneHours);
query = query.Where(x => x.DateEnd >= gtDate);
}
if (request.LtDate.HasValue)
{
- var ltDate = request.LtDate.Value.ToUtcDateTimeOffset(wellDto.Timezone.Hours);
+ var ltDate = request.LtDate.Value.ToUtcDateTimeOffset(timezoneHours);
query = query.Where(x => x.DateStart <= ltDate);
}
diff --git a/AsbCloudInfrastructure/Repository/ProcessMapRepository.cs b/AsbCloudInfrastructure/Repository/ProcessMapRepository.cs
index eb2eadac..f24ce61d 100644
--- a/AsbCloudInfrastructure/Repository/ProcessMapRepository.cs
+++ b/AsbCloudInfrastructure/Repository/ProcessMapRepository.cs
@@ -1,4 +1,5 @@
using AsbCloudApp.Data;
+using AsbCloudApp.Data.ProcessMap;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Mapster;
diff --git a/AsbCloudInfrastructure/Repository/TelemetryWirelineRunOutRepository.cs b/AsbCloudInfrastructure/Repository/TelemetryWirelineRunOutRepository.cs
index 134a1ac8..325bb2b4 100644
--- a/AsbCloudInfrastructure/Repository/TelemetryWirelineRunOutRepository.cs
+++ b/AsbCloudInfrastructure/Repository/TelemetryWirelineRunOutRepository.cs
@@ -2,9 +2,7 @@
using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
-using AsbCloudDb;
using AsbCloudDb.Model;
-using AsbCloudInfrastructure.Services.SAUB;
using Mapster;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
diff --git a/AsbCloudInfrastructure/Services/WellOperationService/WellOperationService.cs b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs
similarity index 71%
rename from AsbCloudInfrastructure/Services/WellOperationService/WellOperationService.cs
rename to AsbCloudInfrastructure/Repository/WellOperationRepository.cs
index 54e559ba..e47a9460 100644
--- a/AsbCloudInfrastructure/Services/WellOperationService/WellOperationService.cs
+++ b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs
@@ -9,35 +9,31 @@ using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Threading;
using System.Threading.Tasks;
+using System.Threading;
+using AsbCloudApp.Repositories;
-namespace AsbCloudInfrastructure.Services.WellOperationService
+namespace AsbCloudInfrastructure.Repository
{
#nullable enable
- public class WellOperationService : IWellOperationService
+ ///
+ /// репозиторий операций по скважине
+ ///
+ public class WellOperationRepository : IWellOperationRepository
{
private readonly IAsbCloudDbContext db;
private readonly IMemoryCache memoryCache;
private readonly IWellService wellService;
+ private static Dictionary? firstOperationsCache = null;
- private Dictionary? firstOperationsCache = null;
-
- public const int idOperationTypePlan = 0;
- public const int idOperationTypeFact = 1;
-
- public WellOperationService(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService)
+ public WellOperationRepository(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService)
{
this.db = db;
this.memoryCache = memoryCache;
this.wellService = wellService;
}
- public IDictionary GetSectionTypes()
- => memoryCache
- .GetOrCreateBasic(db)
- .ToDictionary(s => s.Id, s => s.Caption);
-
+ ///
public IEnumerable GetCategories()
{
var allCategories = memoryCache
@@ -56,6 +52,13 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
return result;
}
+ ///
+ public IDictionary GetSectionTypes()
+ => memoryCache
+ .GetOrCreateBasic(db)
+ .ToDictionary(s => s.Id, s => s.Caption);
+
+ ///
public DateTimeOffset? FirstOperationDate(int idWell)
{
if (firstOperationsCache is null)
@@ -65,8 +68,8 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
.Select(g => new Tuple
(
g.Key,
- g.Where(o => o.IdType == idOperationTypePlan).Min(o => o.DateStart),
- g.Where(o => o.IdType == idOperationTypeFact).Min(o => o.DateStart)
+ g.Where(o => o.IdType == WellOperation.IdOperationTypePlan).Min(o => o.DateStart),
+ g.Where(o => o.IdType == WellOperation.IdOperationTypeFact).Min(o => o.DateStart)
));
firstOperationsCache = query
@@ -76,13 +79,24 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
return firstOperationsCache?.GetValueOrDefault(idWell);
}
- public async Task> GetOperationsAsync(
+ ///
+ public async Task> GetAsync(
WellOperationRequest request,
CancellationToken token)
{
- var timezone = wellService.GetTimezone(request.IdWell);
+ var query = BuildQuery(request)
+ .AsNoTracking();
+ var result = await query.ToArrayAsync(token);
+ return result;
+ }
- var query = BuildQuery(request);
+ ///
+ public async Task> GetPageAsync(
+ WellOperationRequest request,
+ CancellationToken token)
+ {
+ var query = BuildQuery(request)
+ .AsNoTracking();
var result = new PaginationContainer
{
@@ -91,44 +105,45 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
Count = await query.CountAsync(token).ConfigureAwait(false),
};
- if (result.Skip > 0)
- query = query.Skip(result.Skip!);
-
- var entities = await query.Take(result.Take).AsNoTracking()
- .ToListAsync(token).ConfigureAwait(false);
-
- if (!entities.Any())
- return result;
-
- var nptHours = 0d;
-
- var dateStart = query.Min(o => o.DateStart);
- foreach (var entity in entities)
- {
- var dto = entity.Adapt();
- dto.Day = (entity.DateStart - dateStart).TotalDays;
- dto.WellSectionTypeName = entity.WellSectionType.Caption;
- dto.DateStart = entity.DateStart.ToRemoteDateTime(timezone.Hours);
- dto.CategoryName = entity.OperationCategory.Name;
- if (entity.IdType == idOperationTypeFact)
- {
- if (WellOperationCategory.NonProductiveTimeSubIds.Contains(entity.IdCategory))
- nptHours += entity.DurationHours;
- dto.NptHours = nptHours;
- }
- result.Items.Add(dto);
- }
+ query = query
+ .Skip(result.Skip)
+ .Take(result.Take);
+ result.Items = await query.ToListAsync(token);
return result;
}
+ ///
+ public async Task GetOrDefaultAsync(int id,
+ CancellationToken token)
+ {
+ var entity = await db.WellOperations
+ .Include(s => s.WellSectionType)
+ .Include(s => s.OperationCategory)
+ .FirstOrDefaultAsync(e => e.Id == id, token)
+ .ConfigureAwait(false);
+
+ if (entity is null)
+ return null;
+
+ var timezone = wellService.GetTimezone(entity.IdWell);
+
+ var dto = entity.Adapt();
+ dto.WellSectionTypeName = entity.WellSectionType.Caption;
+ dto.DateStart = entity.DateStart.ToRemoteDateTime(timezone.Hours);
+ dto.CategoryName = entity.OperationCategory.Name;
+ return dto;
+ }
+
+ ///
public async Task> GetGroupOperationsStatAsync(
WellOperationRequest request,
CancellationToken token)
{
- var query = BuildQuery(request);
+ var query = BuildQuery(request);
var entities = await query
- .Select(o => new {
+ .Select(o => new
+ {
o.IdCategory,
DurationMinutes = o.DurationHours * 60,
DurationDepth = o.DepthEnd - o.DepthStart
@@ -163,7 +178,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
.GroupBy(o => o.IdParent)
.Select(g => new WellGroupOpertionDto
{
- IdCategory = g.Key.HasValue ? g.Key.Value : defaultId,
+ IdCategory = g.Key ?? defaultId,
Category = g.Key.HasValue ? parentRelationDictionary[g.Key.Value].Name : "unknown",
Count = g.Sum(o => o.Count),
DeltaDepth = g.Sum(o => o.DeltaDepth),
@@ -175,27 +190,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
return dtos;
}
- public async Task GetOrDefaultAsync(int id,
- CancellationToken token)
- {
- var entity = await db.WellOperations
- .Include(s => s.WellSectionType)
- .Include(s => s.OperationCategory)
- .FirstOrDefaultAsync(e => e.Id == id, token)
- .ConfigureAwait(false);
-
- if (entity is null)
- return null;
-
- var timezone = wellService.GetTimezone(entity.IdWell);
-
- var dto = entity.Adapt();
- dto.WellSectionTypeName = entity.WellSectionType.Caption;
- dto.DateStart = entity.DateStart.ToRemoteDateTime(timezone.Hours);
- dto.CategoryName = entity.OperationCategory.Name;
- return dto;
- }
-
+ ///
public async Task InsertRangeAsync(
IEnumerable wellOperationDtos,
CancellationToken token)
@@ -221,6 +216,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
.ConfigureAwait(false);
}
+ ///
public async Task UpdateAsync(
WellOperationDto dto, CancellationToken token)
{
@@ -232,6 +228,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
.ConfigureAwait(false);
}
+ ///
public async Task DeleteAsync(IEnumerable ids,
CancellationToken token)
{
@@ -241,14 +238,53 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
.ConfigureAwait(false);
}
- private IQueryable BuildQuery(WellOperationRequest request)
+ ///
+ /// В результате попрежнему требуется конвертировать дату
+ ///
+ ///
+ ///
+ private IQueryable BuildQuery(WellOperationRequest request)
{
var timezone = wellService.GetTimezone(request.IdWell);
+ var timeZoneOffset = TimeSpan.FromHours(timezone.Hours);
var query = db.WellOperations
.Include(s => s.WellSectionType)
.Include(s => s.OperationCategory)
- .Where(s => s.IdWell == request.IdWell);
+ .Where(o => o.IdWell == request.IdWell)
+ .Select(o => new WellOperationDto
+ {
+ Id = o.Id,
+ IdType = o.IdType,
+ IdWell = o.IdWell,
+ IdWellSectionType = o.IdWellSectionType,
+ IdCategory = o.IdCategory,
+
+ CategoryName = o.WellSectionType.Caption,
+ WellSectionTypeName = o.WellSectionType.Caption,
+
+ DateStart = DateTime.SpecifyKind( o.DateStart.UtcDateTime + timeZoneOffset, DateTimeKind.Unspecified),
+ DepthStart = o.DepthStart,
+ DepthEnd = o.DepthEnd,
+ DurationHours = o.DurationHours,
+ CategoryInfo = o.CategoryInfo,
+ Comment = o.Comment,
+
+ NptHours = db.WellOperations
+ .Where(subOp => subOp.IdWell == request.IdWell)
+ .Where(subOp => subOp.IdType == 1)
+ .Where(subOp => WellOperationCategory.NonProductiveTimeSubIds.Contains(subOp.IdCategory))
+ .Where(subOp => subOp.DateStart <= o.DateStart)
+ .Select(subOp => subOp.DurationHours)
+ .Sum(),
+
+ Day = (o.DateStart - db.WellOperations
+ .Where(subOp => subOp.IdWell == request.IdWell)
+ .Where(subOp => subOp.IdType == o.IdType)
+ .Where(subOp => subOp.DateStart <= o.DateStart)
+ .Min(subOp => subOp.DateStart))
+ .TotalHours,
+ });
if (request.OperationType.HasValue)
query = query.Where(e => e.IdType == request.OperationType.Value);
diff --git a/AsbCloudInfrastructure/Services/LimitingParameterService.cs b/AsbCloudInfrastructure/Services/LimitingParameterService.cs
index 0a609507..848fbdf2 100644
--- a/AsbCloudInfrastructure/Services/LimitingParameterService.cs
+++ b/AsbCloudInfrastructure/Services/LimitingParameterService.cs
@@ -40,7 +40,6 @@ namespace AsbCloudInfrastructure.Services
var data = (await limitingParameterRepository.GetLimitingParametersAsync(request, well, token))
.GroupBy(x => x.IdFeedRegulator);
-
List result = new List(data.Count());
foreach (var item in data)
{
@@ -107,7 +106,7 @@ namespace AsbCloudInfrastructure.Services
return (float)result;
}
- private DateTimeOffset GetDate(double depth, LimitingParameterDataDto dto)
+ private DateTime GetDate(double depth, LimitingParameterDataDto dto)
{
var a = depth - dto.DepthStart;
var b = dto.DepthEnd - dto.DepthStart;
diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs
new file mode 100644
index 00000000..da7f3f79
--- /dev/null
+++ b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportService.cs
@@ -0,0 +1,203 @@
+using AsbCloudApp.Data.ProcessMap;
+using AsbCloudApp.Services;
+using ClosedXML.Excel;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace AsbCloudInfrastructure.Services.ProcessMap
+{
+#nullable enable
+ public class ProcessMapReportService : IProcessMapReportService
+ {
+ const int firstColumn = 2;
+ const int lastColumn = 27;
+
+ const int headerRowsCount = 3;
+
+ private readonly IProcessMapService processMapService;
+
+ public ProcessMapReportService(IProcessMapService processMapService)
+ {
+ this.processMapService = processMapService;
+ }
+
+ public async Task MakeReportAsync(int idWell, CancellationToken token)
+ {
+ var stream = GetExcelTemplateStream();
+ using var workbook = new XLWorkbook(stream, XLEventTracking.Disabled);
+
+ var data = await processMapService.GetProcessMapAsync(idWell, token);
+
+ FillProcessMapToWorkbook(workbook, data);
+
+ MemoryStream memoryStream = new MemoryStream();
+ workbook.SaveAs(memoryStream, new SaveOptions { });
+ memoryStream.Seek(0, SeekOrigin.Begin);
+ return memoryStream;
+ }
+
+ private static void FillProcessMapToWorkbook(XLWorkbook workbook, IEnumerable data)
+ {
+ var sheet = workbook.Worksheets.FirstOrDefault();
+ if (sheet is null)
+ return;
+ var dataBySections = data.GroupBy(p => p.IdWellSectionType);
+ FillSheet(sheet, dataBySections);
+ }
+
+ private static void FillSheet(IXLWorksheet sheet, IEnumerable> dataBySections)
+ {
+ var startRow = headerRowsCount + 1;
+ foreach (var sectionData in dataBySections)
+ {
+ if(sectionData.Any())
+ startRow = FillSection(sheet, sectionData, startRow);
+ }
+ }
+
+ private static int FillSection(IXLWorksheet sheet, IGrouping sectionData, int row)
+ {
+ var rowStart = row;
+
+ var sectionName = sectionData.FirstOrDefault()?.WellSectionTypeName
+ ?? sectionData.Key.ToString();
+
+ sheet.Range(row, firstColumn, row, lastColumn)
+ .Merge()
+ .FirstCell()
+ .SetVal(sectionName);
+
+ row++;
+
+ foreach (var interval in sectionData)
+ row = FillIntervalData(sheet, interval, row);
+
+ var sectionStyle = sheet.Range(rowStart, firstColumn, row - 1, lastColumn).Style;
+ SetBorders(sectionStyle);
+ return row;
+ }
+
+ private static int FillIntervalData(IXLWorksheet sheet, ProcessMapReportDto interval, int row)
+ {
+ const int columnDepth = firstColumn;
+ const int columnDate = firstColumn + 1;
+ const int columnRopTime = firstColumn + 2;
+ const int columnMode = firstColumn + 3;
+
+ int rowRotor = row;
+ int rowSlide = row + 1;
+
+ sheet.Range(rowRotor, columnDepth, rowSlide, columnDepth)
+ .Merge().FirstCell()
+ .SetVal(interval.DepthStart, "0.0");
+
+ sheet.Range(rowRotor, columnDate, rowSlide, columnDate)
+ .Merge().FirstCell()
+ .SetVal(interval.DateStart);
+
+ sheet.Range(rowRotor, columnRopTime, rowSlide, columnRopTime)
+ .Merge().FirstCell()
+ .SetVal(interval.MechDrillingHours);
+
+ row = FillIntervalModeData(sheet, "Ротор", interval.Rotor, columnMode, row);
+ row = FillIntervalModeData(sheet, "Слайд", interval.Rotor, columnMode, row);
+
+ return row;
+ }
+
+ private static int FillIntervalModeData(IXLWorksheet sheet, string modeName, ProcessMapReportRowDto modeData, int column, int row)
+ {
+ int columnDeltaDepth = column + 1;
+ int columnPressure = columnDeltaDepth + 1;
+ int columnLoad = columnPressure + 5;
+ int columnTorque = columnLoad + 5;
+ int columnSpeed = columnTorque + 5;
+ int columnUsage = columnSpeed + 4;
+ int columnRop = columnUsage + 1;
+
+ sheet.Cell(row, column)
+ .SetVal(modeName);
+
+ sheet.Cell(row, columnDeltaDepth)
+ .SetVal(modeData.DeltaDepth);
+
+ FillIntervalModeDataParam(sheet, modeData.PressureDiff, columnPressure, row);
+ FillIntervalModeDataParam(sheet, modeData.AxialLoad, columnLoad, row);
+ FillIntervalModeDataParam(sheet, modeData.TopDriveTorque, columnTorque, row);
+ FillIntervalModeDataSpeed(sheet, modeData.SpeedLimit, columnSpeed, row);
+
+ sheet.Cell(row, columnUsage)
+ .SetVal(modeData.Usage);
+
+ sheet.Cell(row, columnRop)
+ .SetVal(modeData.Rop);
+
+ return row + 1;
+ }
+
+ private static void FillIntervalModeDataParam(IXLWorksheet sheet, ProcessMapReportParamsDto dataParam, int column, int row)
+ {
+ const int columnOffsetSpPlan = 0;
+ const int columnOffsetSpFact = 1;
+ const int columnOffsetFact = 2;
+ const int columnOffsetLimit = 3;
+ const int columnOffsetPercent = 4;
+
+ sheet.Cell(row, column + columnOffsetSpPlan)
+ .SetVal(dataParam.SetpointPlan);
+
+ sheet.Cell(row, column + columnOffsetSpFact)
+ .SetVal(dataParam.SetpointFact);
+
+ sheet.Cell(row, column + columnOffsetFact)
+ .SetVal(dataParam.Fact);
+
+ sheet.Cell(row, column + columnOffsetLimit)
+ .SetVal(dataParam.Limit);
+
+ sheet.Cell(row, column + columnOffsetPercent)
+ .SetVal(dataParam.PercDrillingSetpoint);
+ }
+
+ private static void FillIntervalModeDataSpeed(IXLWorksheet sheet, ProcessMapReportParamsDto dataParam, int column, int row)
+ {
+ const int columnOffsetSpPlan = 0;
+ const int columnOffsetSpFact = 1;
+ const int columnOffsetFact = 2;
+ const int columnOffsetPercent = 3;
+
+ sheet.Cell(row, column + columnOffsetSpPlan)
+ .SetVal(dataParam.SetpointPlan);
+
+ sheet.Cell(row, column + columnOffsetSpFact)
+ .SetVal(dataParam.SetpointFact);
+
+ sheet.Cell(row, column + columnOffsetFact)
+ .SetVal(dataParam.Fact);
+
+ sheet.Cell(row, column + columnOffsetPercent)
+ .SetVal(dataParam.PercDrillingSetpoint);
+ }
+
+ private static Stream GetExcelTemplateStream()
+ {
+ var stream = System.Reflection.Assembly.GetExecutingAssembly()
+ .GetManifestResourceStream("AsbCloudInfrastructure.Services.ProcessMap.ProcessMapReportTemplate.xlsx");
+ return stream!;
+ }
+
+ private static IXLStyle SetBorders(IXLStyle style)
+ {
+ style.Border.RightBorder = XLBorderStyleValues.Thin ;
+ style.Border.LeftBorder = XLBorderStyleValues.Thin;
+ style.Border.TopBorder = XLBorderStyleValues.Thin ;
+ style.Border.BottomBorder = XLBorderStyleValues.Thin ;
+ style.Border.InsideBorder = XLBorderStyleValues.Thin ;
+ return style;
+ }
+ }
+#nullable disable
+}
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportTemplate.xlsx b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportTemplate.xlsx
new file mode 100644
index 00000000..64b328cd
Binary files /dev/null and b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapReportTemplate.xlsx differ
diff --git a/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs
new file mode 100644
index 00000000..0884896d
--- /dev/null
+++ b/AsbCloudInfrastructure/Services/ProcessMap/ProcessMapService.cs
@@ -0,0 +1,346 @@
+using AsbCloudApp.Data;
+using AsbCloudApp.Data.ProcessMap;
+using AsbCloudApp.Data.SAUB;
+using AsbCloudApp.Exceptions;
+using AsbCloudApp.Repositories;
+using AsbCloudApp.Requests;
+using AsbCloudApp.Services;
+using AsbCloudApp.Services.Subsystems;
+using AsbCloudDb.Model;
+using AsbCloudApp.Data.Subsystems;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using AsbCloudInfrastructure.Services.Subsystems;
+
+namespace AsbCloudInfrastructure.Services.ProcessMap
+{
+#nullable enable
+ public partial class ProcessMapService : IProcessMapService
+ {
+ private readonly IWellService wellService;
+ private readonly IWellOperationRepository wellOperationRepository;
+ private readonly IProcessMapRepository processMapRepository;
+ private readonly ITelemetryDataSaubService telemetryDataSaubService;
+ private readonly ILimitingParameterRepository limitingParameterRepository;
+ private readonly ISubsystemOperationTimeService subsystemOperationTimeService;
+
+ public ProcessMapService(
+ IWellService wellService,
+ IWellOperationRepository wellOperationService,
+ IProcessMapRepository processMapRepository,
+ ITelemetryDataSaubService telemetryDataSaubService,
+ ILimitingParameterRepository limitingParameterRepository,
+ ISubsystemOperationTimeService subsystemOperationTimeService)
+ {
+ this.wellService = wellService;
+ this.wellOperationRepository = wellOperationService;
+ this.processMapRepository = processMapRepository;
+ this.telemetryDataSaubService = telemetryDataSaubService;
+ this.limitingParameterRepository = limitingParameterRepository;
+ this.subsystemOperationTimeService = subsystemOperationTimeService;
+ }
+
+ public async Task> GetProcessMapAsync(int idWell, CancellationToken token)
+ {
+ var well = wellService.GetOrDefault(idWell)
+ ?? throw new ArgumentInvalidException("idWell not found", nameof(idWell));
+ var idTelemetry = well.IdTelemetry
+ ?? throw new ArgumentInvalidException("telemetry by well not found", nameof(idWell));
+
+ var processMap = (await processMapRepository.GetByIdWellAsync(idWell, token))!;
+ var factDrillingOperations = await GetFactDrillingOperationsAsync(idWell, token);
+ var telemetryDataStat = await telemetryDataSaubService.GetTelemetryDataStatAsync(idTelemetry, token);
+ var limitingParameters = await limitingParameterRepository.GetLimitingParametersAsync(new(), well, token);
+ var subsystemsOperationTime = await GetOperationTimeAsync(idWell, token);
+
+ var result = factDrillingOperations
+ .GroupBy(o => o.IdWellSectionType)
+ .SelectMany(sectionOperations =>
+ {
+ var sectionProcessMap = processMap.Where(p => p.IdWellSectionType == sectionOperations.Key);
+ return HandleSection(sectionOperations, sectionProcessMap, telemetryDataStat, limitingParameters, subsystemsOperationTime!);
+ })
+ .ToList();
+
+ return result;
+ }
+
+ private Task?> GetOperationTimeAsync(int idWell, CancellationToken token)
+ {
+ var request = new SubsystemOperationTimeRequest
+ {
+ IdWell = idWell,
+ IdsSubsystems = new int[] { SubsystemOperationTimeService.IdSubsystemAKB, SubsystemOperationTimeService.IdSubsystemSpin },
+ };
+ return subsystemOperationTimeService.GetOperationTimeAsync(request, token);
+ }
+
+ private async Task> GetFactDrillingOperationsAsync(int idWell, CancellationToken token)
+ {
+ var operationsRequest = new WellOperationRequest
+ {
+ IdWell = idWell,
+ OperationCategoryIds = WellOperationCategory.MechanicalDrillingSubIds,
+ OperationType = WellOperation.IdOperationTypeFact,
+ SortFields = new[] { nameof(WellOperation.DateStart) }
+ };
+
+ var allFactDrillingOperations = await wellOperationRepository.GetAsync(operationsRequest, token);
+ var factDrillingOperations = allFactDrillingOperations.Where(o => o.DepthEnd > o.DepthStart);
+ return factDrillingOperations;
+ }
+
+ private static IEnumerable HandleSection(
+ IEnumerable sectionOperations,
+ IEnumerable sectionProcessMap,
+ IEnumerable telemetryDataStat,
+ IEnumerable limitingParameters,
+ IEnumerable subsystemsOperationTime)
+ {
+ var minDepth = sectionOperations.Min(o => o.DepthStart);
+ var maxDepth = sectionOperations.Max(o => o.DepthEnd);
+
+ var depthIntervals = SplitByIntervals(minDepth, maxDepth).ToArray();
+ var result = new ProcessMapReportDto[depthIntervals.Length];
+
+ for (var i = 0; i < depthIntervals.Length; i++ )
+ result[i] = MakeProcessMapReportDto(depthIntervals[i], sectionOperations, sectionProcessMap, telemetryDataStat, limitingParameters, subsystemsOperationTime);
+
+ return result;
+ }
+
+ private static ProcessMapReportDto MakeProcessMapReportDto(
+ (double min, double max) depthInterval,
+ IEnumerable sectionOperations,
+ IEnumerable sectionProcessMap,
+ IEnumerable telemetryDataStat,
+ IEnumerable limitingParameters,
+ IEnumerable subsystemsOperationTime)
+ {
+ var dto = new ProcessMapReportDto{
+ DepthStart = depthInterval.min
+ };
+
+ // TODO: trim items by detpth intervals. Use linear interpolation.
+ var intervalOperations = sectionOperations.Where(o => o.DepthEnd >= depthInterval.min && o.DepthStart <= depthInterval.max);
+ var intervalProcessMap = sectionProcessMap.Where(map => map.DepthEnd >= depthInterval.min && map.DepthStart <= depthInterval.max);
+ var intervalTelemetryDataStat = CalcIntervalTelemetryDataStat(depthInterval, telemetryDataStat);
+ var intervalLimitingParametrs = limitingParameters.Where(l => l.DepthEnd >= depthInterval.min && l.DepthStart <= depthInterval.max);
+ var intervalSubsystemsOperationTime = subsystemsOperationTime.Where(o => o.DepthEnd >= depthInterval.min && o.DepthStart <= depthInterval.max);
+
+ var firstIntervalOperation = intervalOperations.FirstOrDefault();
+ if (firstIntervalOperation is not null)
+ {
+ dto.DateStart = GetInterpolatedDate(firstIntervalOperation, depthInterval.min);
+ dto.IdWell = firstIntervalOperation.IdWell;
+ dto.IdWellSectionType = firstIntervalOperation.IdWellSectionType;
+ dto.WellSectionTypeName = firstIntervalOperation.WellSectionTypeName;
+ dto.MechDrillingHours = CalcHours(depthInterval, intervalOperations);
+ }
+
+ // TODO: Разделить интервальные коллекции на ротор и слайд. Пока нет готовой методики.
+ var slideOperations = intervalOperations.Where(o => o.IdCategory == WellOperationCategory.IdSlide);
+ var rotorOperations = intervalOperations.Where(o => o.IdCategory == WellOperationCategory.IdRotor);
+
+ dto.Slide = CalcDrillModeStat(depthInterval, slideOperations, intervalProcessMap, intervalTelemetryDataStat, intervalLimitingParametrs, intervalSubsystemsOperationTime);
+ dto.Rotor = CalcDrillModeStat(depthInterval, rotorOperations, intervalProcessMap, intervalTelemetryDataStat, intervalLimitingParametrs, intervalSubsystemsOperationTime);
+
+ return dto;
+ }
+
+ private static TelemetryDataSaubStatDto? CalcIntervalTelemetryDataStat((double min, double max) depthInterval, IEnumerable telemetryDataStat)
+ {
+ TelemetryDataSaubStatDto[] data = telemetryDataStat
+ .Where(d => d.WellDepthMin <= depthInterval.max && d.WellDepthMax >= depthInterval.min)
+ .ToArray();
+
+ if (!data.Any())
+ return null;
+
+ if (data.Length == 1)
+ return data.First();
+
+ var result = new TelemetryDataSaubStatDto
+ {
+ WellDepthMin = data.Min(d => d.WellDepthMin),
+ WellDepthMax = data.Max(d => d.WellDepthMax),
+ DateMin = data.Min(d => d.DateMin),
+ DateMax = data.Max(d => d.DateMax),
+ };
+
+ var intervalDeltaDepth = result.WellDepthMax - result.WellDepthMin;
+
+ foreach (var item in data)
+ {
+ var itemWeight = (item.WellDepthMax - item.WellDepthMin) / intervalDeltaDepth;
+
+ result.Pressure += item.Pressure * itemWeight;
+ result.PressureSp += item.PressureSp * itemWeight;
+ result.PressureSpRotor += item.PressureSpSlide * itemWeight;
+ result.PressureIdle += item.PressureIdle * itemWeight;
+
+ result.AxialLoad += item.AxialLoad * itemWeight;
+ result.AxialLoadSp += item.AxialLoadSp * itemWeight;
+ result.AxialLoadLimitMax += item.AxialLoadLimitMax * itemWeight;
+
+ result.RotorTorque += item.RotorTorque * itemWeight;
+ result.RotorTorqueSp += item.RotorTorqueSp * itemWeight;
+ result.RotorTorqueLimitMax += item.RotorTorqueLimitMax * itemWeight;
+
+ result.BlockSpeed += item.BlockSpeed * itemWeight;
+ result.BlockSpeedSp += item.BlockSpeedSp * itemWeight;
+ result.BlockSpeedSpRotor += item.BlockSpeedSpRotor * itemWeight;
+ result.BlockSpeedSpSlide += item.BlockSpeedSpSlide * itemWeight;
+ }
+
+ return result;
+ }
+
+ private static ProcessMapReportRowDto CalcDrillModeStat(
+ (double min, double max) depthInterval,
+ IEnumerable intervalModeOperations,
+ IEnumerable intervalProcessMap,
+ TelemetryDataSaubStatDto? telemetryDataStat,
+ IEnumerable intervalLimitingParametrs,
+ IEnumerable intervalSubsystemsOperationTime)
+ {
+ var dto = new ProcessMapReportRowDto();
+ if (intervalModeOperations.Any())
+ {
+ var deltaDepth = CalcDeltaDepth(depthInterval, intervalModeOperations);
+ dto.DeltaDepth = deltaDepth;
+ dto.Rop = deltaDepth / CalcHours(depthInterval, intervalModeOperations);
+ };
+
+ if (intervalProcessMap.Any())
+ {
+ var processMapFirst = intervalProcessMap.First();
+ dto.PressureDiff.SetpointPlan = processMapFirst.Pressure.Plan;
+ dto.AxialLoad.SetpointPlan = processMapFirst.AxialLoad.Plan;
+ dto.TopDriveTorque.SetpointPlan = processMapFirst.TopDriveTorque.Plan;
+ //dto.SpeedLimit.SetpointPlan = null;
+ }
+
+ if (telemetryDataStat is not null)
+ {
+ dto.PressureDiff.SetpointFact = telemetryDataStat.PressureSp;
+ dto.PressureDiff.Fact = telemetryDataStat.Pressure;
+ dto.PressureDiff.Limit = telemetryDataStat.PressureDeltaLimitMax;
+
+ dto.AxialLoad.SetpointFact = telemetryDataStat.AxialLoadSp;
+ dto.AxialLoad.Fact = telemetryDataStat.AxialLoad;
+ dto.AxialLoad.Limit = telemetryDataStat.AxialLoadLimitMax;
+
+ dto.TopDriveTorque.SetpointFact = telemetryDataStat.RotorTorqueSp;
+ dto.TopDriveTorque.Fact = telemetryDataStat.RotorTorque;
+ dto.TopDriveTorque.Limit = telemetryDataStat.RotorTorqueLimitMax;
+
+ dto.SpeedLimit.SetpointFact = telemetryDataStat.BlockSpeedSp;
+ dto.SpeedLimit.Fact = telemetryDataStat.BlockSpeed;
+ //dto.SpeedLimit.Limit = mull;
+ }
+
+ if(intervalLimitingParametrs.Any())
+ {
+ const int idLimParamRop = 1;
+ const int idLimParamPressure = 2;
+ const int idLimParamAxialLoad = 3;
+ const int idLimParamTorque = 4;
+
+ var intervalLimitingParametrsStat = intervalLimitingParametrs
+ .GroupBy(p => p.IdFeedRegulator)
+ .Select(g => new
+ {
+ IdLimParam = g.Key,
+ SumDepth = g.Sum(p => p.DepthEnd - p.DepthStart),
+ });
+
+ var totalDepth = intervalLimitingParametrsStat
+ .Sum(s => s.SumDepth);
+
+ if (totalDepth > 0)
+ {
+ dto.AxialLoad.PercDrillingSetpoint = intervalLimitingParametrsStat
+ .FirstOrDefault(s => s.IdLimParam == idLimParamAxialLoad)?.SumDepth / totalDepth;
+
+ dto.PressureDiff.PercDrillingSetpoint = intervalLimitingParametrsStat
+ .FirstOrDefault(s => s.IdLimParam == idLimParamPressure)?.SumDepth / totalDepth;
+
+ dto.TopDriveTorque.PercDrillingSetpoint = intervalLimitingParametrsStat
+ .FirstOrDefault(s => s.IdLimParam == idLimParamTorque)?.SumDepth / totalDepth;
+
+ dto.SpeedLimit.PercDrillingSetpoint = intervalLimitingParametrsStat
+ .FirstOrDefault(s => s.IdLimParam == idLimParamRop)?.SumDepth / totalDepth;
+ }
+ }
+
+ if (intervalSubsystemsOperationTime.Any() && dto.DeltaDepth > 0)
+ {
+ dto.Usage = intervalSubsystemsOperationTime.Sum(t => t.DepthEnd - t.DepthStart) / dto.DeltaDepth.Value;
+ }
+
+ return dto;
+ }
+
+ private static double CalcDeltaDepth((double min, double max) depthInterval, IEnumerable intervalOperations)
+ {
+ var ddepth = 0d;
+ foreach (var operation in intervalOperations)
+ {
+ var depthStart = operation.DepthStart > depthInterval.min
+ ? operation.DepthStart
+ : depthInterval.min;
+
+ var depthEnd = operation.DepthEnd < depthInterval.max
+ ? operation.DepthEnd
+ : depthInterval.max;
+
+ ddepth += (depthEnd - depthEnd);
+ }
+ return ddepth;
+ }
+
+ private static double CalcHours((double min, double max) depthInterval, IEnumerable intervalOperations)
+ {
+ var hours = 0d;
+ foreach (var operation in intervalOperations)
+ {
+ var dateStart = operation.DepthStart > depthInterval.min
+ ? operation.DateStart
+ : GetInterpolatedDate(operation, depthInterval.min);
+
+ var dateEnd = operation.DepthEnd < depthInterval.max
+ ? operation.DateStart + TimeSpan.FromHours(operation.DurationHours)
+ : GetInterpolatedDate(operation, depthInterval.max);
+
+ hours += (dateEnd - dateStart).TotalHours;
+ }
+ return hours;
+ }
+
+ private static DateTime GetInterpolatedDate(WellOperationDto operation, double depth)
+ {
+ var ratio = (depth - operation.DepthStart) / (operation.DepthEnd - operation.DepthStart);
+ var deltaHours = operation.DurationHours * ratio;
+ var interpolatedDate = operation.DateStart + TimeSpan.FromHours(deltaHours);
+ return interpolatedDate;
+ }
+
+ private static IEnumerable<(double min, double max)> SplitByIntervals(double min, double max)
+ {
+ const double step = 100;
+ var iMin = min;
+ var iMax = (1 + (int)(min / step)) * step;
+ for (; iMax < max; iMax += step)
+ {
+ yield return (iMin, iMax);
+ iMin = iMax;
+ }
+ yield return (iMin, max);
+ }
+ }
+#nullable disable
+}
diff --git a/AsbCloudInfrastructure/Services/ProcessMap/XLExtentions.cs b/AsbCloudInfrastructure/Services/ProcessMap/XLExtentions.cs
new file mode 100644
index 00000000..7117e1cf
--- /dev/null
+++ b/AsbCloudInfrastructure/Services/ProcessMap/XLExtentions.cs
@@ -0,0 +1,63 @@
+using ClosedXML.Excel;
+using System;
+
+namespace AsbCloudInfrastructure.Services.ProcessMap;
+
+internal static class XLExtentions
+{
+ public static IXLCell SetVal(this IXLCell cell, object value)
+ {
+ switch (value)
+ {
+ case DateTime dateTime:
+ cell.SetVal(dateTime);
+ break;
+ case IFormattable formattable:
+ cell.SetVal(formattable);
+ break;
+ case string valueString:
+ cell.SetVal(valueString);
+ break;
+ default:
+ cell.Value = value;
+ break;
+ }
+
+ return cell;
+ }
+
+ public static IXLCell SetVal(this IXLCell cell, string value, bool adaptRowHeight = false)
+ {
+ cell.Value = value;
+ if (adaptRowHeight)
+ {
+ var colWidth = cell.WorksheetColumn().Width;
+ var maxCharsToWrap = colWidth / (0.1d * cell.Style.Font.FontSize);
+ if (value.Length > maxCharsToWrap)
+ {
+ var row = cell.WorksheetRow();
+ var baseHeight = row.Height;
+ row.Height = 0.5d * baseHeight * Math.Ceiling(1d + value.Length / maxCharsToWrap);
+ }
+ }
+
+ return cell;
+ }
+
+ public static IXLCell SetVal(this IXLCell cell, DateTime value, string dateFormat = "DD.MM.YYYY HH:MM:SS")
+ {
+ cell.Value = value;
+ cell.DataType = XLDataType.DateTime;
+ cell.Style.DateFormat.Format = dateFormat;
+
+ return cell;
+ }
+
+ public static IXLCell SetVal(this IXLCell cell, IFormattable value, string format = "0.00")
+ {
+ cell.Value = value;
+ cell.DataType = XLDataType.Number;
+ cell.Style.NumberFormat.Format = format;
+ return cell;
+ }
+}
diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs
index 941bc012..d8f7736c 100644
--- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs
+++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataBaseService.cs
@@ -17,8 +17,8 @@ namespace AsbCloudInfrastructure.Services.SAUB
where TEntity : class, ITelemetryData
{
protected readonly IAsbCloudDbContext db;
- private readonly ITelemetryService telemetryService;
- private readonly TelemetryDataCache telemetryDataCache;
+ protected readonly ITelemetryService telemetryService;
+ protected readonly TelemetryDataCache telemetryDataCache;
public TelemetryDataBaseService(
IAsbCloudDbContext db,
diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs
index 9d666c1c..8ec8cb10 100644
--- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs
+++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataSaubService.cs
@@ -2,12 +2,17 @@
using AsbCloudApp.Services;
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.Services.SAUB
{
#nullable enable
- public class TelemetryDataSaubService : TelemetryDataBaseService
+ public class TelemetryDataSaubService : TelemetryDataBaseService, ITelemetryDataSaubService
{
private readonly ITelemetryUserService telemetryUserService;
@@ -21,6 +26,54 @@ namespace AsbCloudInfrastructure.Services.SAUB
this.telemetryUserService = telemetryUserService;
}
+ public async Task> GetTelemetryDataStatAsync(int idTelemetry, CancellationToken token)
+ {
+ var timezone = telemetryService.GetTimezone(idTelemetry);
+ var timezoneOffset = TimeSpan.FromHours(timezone.Hours);
+
+ var query = db.Set()
+ .Where(t => t.IdTelemetry == idTelemetry)
+ .Where(t => t.BlockPosition > 0.0001)
+ .Where(t => t.WellDepth > 0.0001)
+ .Where(t => t.WellDepth - t.BitDepth < 0.01)
+ .GroupBy(t => new { H = t.DateTime.Hour, W = Math.Truncate(t.WellDepth!.Value) })
+ .Select(g => new TelemetryDataSaubStatDto
+ {
+ Count = g.Count(),
+
+ DateMin = DateTime.SpecifyKind(g.Min(t => t.DateTime.UtcDateTime) + timezoneOffset, DateTimeKind.Unspecified),
+ DateMax = DateTime.SpecifyKind(g.Max(t => t.DateTime.UtcDateTime) + timezoneOffset, DateTimeKind.Unspecified),
+
+ WellDepthMin = g.Min(t => t.WellDepth!.Value),
+ WellDepthMax = g.Max(t => t.WellDepth!.Value),
+
+ Pressure = g.Average(t => t.Pressure!.Value),
+ PressureSp = g.Average(t => t.PressureSp!.Value),
+ PressureSpRotor = g.Average(t => t.PressureSpRotor!.Value),
+ PressureSpSlide = g.Average(t => t.PressureSpSlide!.Value),
+ PressureIdle = g.Average(t => t.PressureIdle!.Value),
+ PressureDeltaLimitMax = g.Average(t => t.PressureDeltaLimitMax!.Value),
+
+ AxialLoad = g.Average(t => t.AxialLoad!.Value),
+ AxialLoadSp = g.Average(t => t.AxialLoadSp!.Value),
+ AxialLoadLimitMax = g.Average(t => t.AxialLoadLimitMax!.Value),
+
+ RotorTorque = g.Average(t => t.RotorTorque!.Value),
+ RotorTorqueSp = g.Average(t => t.RotorTorqueSp!.Value),
+ RotorTorqueLimitMax = g.Average(t => t.RotorTorqueLimitMax!.Value),
+
+ BlockSpeed = g.Average(t => t.BlockSpeed!.Value),
+ BlockSpeedSp = g.Average(t => t.BlockSpeedSp!.Value),
+ BlockSpeedSpRotor = g.Average(t => t.BlockSpeedSpRotor!.Value),
+ BlockSpeedSpSlide = g.Average(t => t.BlockSpeedSpSlide!.Value),
+ })
+ .Where(s => s.WellDepthMin != s.WellDepthMax)
+ .Where(s => s.Count > 3)
+ .OrderBy(t => t.DateMin);
+
+ return await query.ToArrayAsync(token);
+ }
+
public override TelemetryDataSaub Convert(TelemetryDataSaubDto src, double timezoneOffset)
{
var entity = src.Adapt();
diff --git a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs
index 818eef38..4ffaa620 100644
--- a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs
+++ b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs
@@ -204,7 +204,7 @@ namespace AsbCloudInfrastructure.Services
}));
if(!docs.Any())
- throw new Exception("Нет такой категории, или в нее уже загружен документ");
+ throw new ArgumentInvalidException("Нет такой категории, или в нее уже загружен документ", nameof(idCategory));
var message = requester.MakeDisplayName() + " ожидает от Вас загрузку на портал документа «{{0}}»";
await GenerateMessageAsync(docs, message, token);
diff --git a/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs b/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs
index 116b23de..b9daba10 100644
--- a/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs
+++ b/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs
@@ -134,7 +134,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
var wellType = (await memoryCache
.GetOrCreateBasicAsync(db, token))
.FirstOrDefault(t => t.Id == well.IdWellType);
- var statWellDto = new StatWellDto()
+ var statWellDto = new StatWellDto
{
Id = well.Id,
Caption = well.Caption,
@@ -142,10 +142,9 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
IdState = well.IdState,
State = wellService.GetStateText(well.IdState),
LastTelemetryDate = wellService.GetLastTelemetryDate(well.Id).DateTime,
+ Companies = await wellService.GetCompaniesAsync(well.Id, token)
};
- statWellDto.Companies = await wellService.GetCompaniesAsync(well.Id, token);
-
if (well.WellOperations is null)
return statWellDto;
@@ -175,8 +174,8 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
.ToDictionary(s => s.Id);
var sections = new List(sectionTypes.Count);
- var operationsPlan = operations.Where(o => o.IdType == WellOperationService.idOperationTypePlan);
- var operationsFact = operations.Where(o => o.IdType == WellOperationService.idOperationTypeFact);
+ var operationsPlan = operations.Where(o => o.IdType == WellOperation.IdOperationTypePlan);
+ var operationsFact = operations.Where(o => o.IdType == WellOperation.IdOperationTypeFact);
foreach ((var id, var sectionType) in sectionTypes)
{
@@ -195,8 +194,8 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
private static PlanFactBase GetStatTotal(IEnumerable operations,
int idWellState, double timezoneOffsetH)
{
- var operationsPlan = operations.Where(o => o.IdType == WellOperationService.idOperationTypePlan);
- var operationsFact = operations.Where(o => o.IdType == WellOperationService.idOperationTypeFact);
+ var operationsPlan = operations.Where(o => o.IdType == WellOperation.IdOperationTypePlan);
+ var operationsFact = operations.Where(o => o.IdType == WellOperation.IdOperationTypeFact);
var factEnd = CalcStat(operationsFact, timezoneOffsetH);
if (factEnd is not null && idWellState != 2)
factEnd.End = null;
@@ -369,12 +368,12 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
.ConfigureAwait(false);
var wellOperationsPlan = wellOperations
- .Where(o => o.IdType == WellOperationService.idOperationTypePlan)
+ .Where(o => o.IdType == WellOperation.IdOperationTypePlan)
.OrderBy(o => o.DateStart)
.ThenBy(o => o.DepthEnd);
var wellOperationsFact = wellOperations
- .Where(o => o.IdType == WellOperationService.idOperationTypeFact)
+ .Where(o => o.IdType == WellOperation.IdOperationTypeFact)
.OrderBy(o => o.DateStart)
.ThenBy(o => o.DepthEnd);
diff --git a/AsbCloudInfrastructure/Services/WellOperationService/WellOperationImportService.cs b/AsbCloudInfrastructure/Services/WellOperationService/WellOperationImportService.cs
index 81771165..e9ed3d11 100644
--- a/AsbCloudInfrastructure/Services/WellOperationService/WellOperationImportService.cs
+++ b/AsbCloudInfrastructure/Services/WellOperationService/WellOperationImportService.cs
@@ -65,6 +65,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
}
}
+ // TODO: use WellOperationRepository instead of DB
public WellOperationImportService(IAsbCloudDbContext db, IWellService wellService)
{
this.db = db;
diff --git a/AsbCloudInfrastructure/Services/WellOperationService/WellOperationRepository.cs b/AsbCloudInfrastructure/Services/WellOperationService/WellOperationRepository.cs
deleted file mode 100644
index 6251bae9..00000000
--- a/AsbCloudInfrastructure/Services/WellOperationService/WellOperationRepository.cs
+++ /dev/null
@@ -1,242 +0,0 @@
-using AsbCloudApp.Data;
-using AsbCloudApp.Requests;
-using AsbCloudApp.Services;
-using AsbCloudDb;
-using AsbCloudDb.Model;
-using Mapster;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Caching.Memory;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using System.Threading;
-using System.Collections;
-
-namespace AsbCloudInfrastructure.Services.WellOperationService
-{
-#nullable enable
-
-
- /*
- var opsQuery = db.WellOperations
- .Where( o => o.IdWell == idWell )
- .Where( o => o.IdType == idType )
- .Select( o => new {
- o.Id,
- o.IdType,
- o.IdWell,
- o.IdWellSectionType,
- o.IdCategory,
-
- o.Well,
- o.WellSectionType,
- o.OperationCategory,
-
- o.DateStart,
- o.DepthStart,
- o.DepthEnd,
- o.DurationHours,
- o.CategoryInfo,
- o.Comment,
-
- nptHours = db.WellOperations
- .Where(subOp => subOp.IdWell == idWell)
- .Where(subOp => subOp.IdType == idType)
- .Where(subOp => nptCats.Contains( subOp.IdCategory ))
- .Where(subOp => subOp.DateStart <= o.DateStart)
- .Select(subOp => subOp.DurationHours)
- .Sum(),
- Day = o.DateStart - db.WellOperations
- .Where(subOp => subOp.IdWell == idWell)
- .Where(subOp => subOp.IdType == idType)
- .Where(subOp => subOp.DateStart <= o.DateStart)
- .Min(subOp => subOp.DateStart),
- })
- .OrderBy(o => o.DateStart);
- */
- public class WellOperationRepository
- {
- private readonly IAsbCloudDbContext db;
- private readonly IMemoryCache memoryCache;
- private readonly IWellService wellService;
- private static Dictionary? firstOperationsCache = null;
-
- public const int idOperationTypePlan = 0;
- public const int idOperationTypeFact = 1;
-
- public WellOperationRepository(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService)
- {
- this.db = db;
- this.memoryCache = memoryCache;
- this.wellService = wellService;
- }
-
- public IDictionary GetSectionTypes()
- => memoryCache
- .GetOrCreateBasic(db)
- .ToDictionary(s => s.Id, s => s.Caption);
-
- public IEnumerable GetCategories()
- {
- var allCategories = memoryCache
- .GetOrCreateBasic(db);
-
- var parentIds = allCategories
- .Select(o => o.IdParent)
- .Distinct();
-
- var operationCategories = allCategories
- .Where(o => !parentIds.Contains(o.Id))
- .OrderBy(o => o.IdParent)
- .ThenBy(o => o.Name);
-
- var result = operationCategories.Adapt>();
- return result;
- }
-
- public DateTimeOffset? FirstOperationDate(int idWell)
- {
- if (firstOperationsCache is null)
- {
- var query = db.WellOperations
- .GroupBy(o => o.IdWell)
- .Select(g => new Tuple
- (
- g.Key,
- g.Where(o => o.IdType == idOperationTypePlan).Min(o => o.DateStart),
- g.Where(o => o.IdType == idOperationTypeFact).Min(o => o.DateStart)
- ));
-
- firstOperationsCache = query
- .ToDictionary(f => f.Item1, f => f.Item3 ?? f.Item2);
- }
-
- return firstOperationsCache?.GetValueOrDefault(idWell);
- }
-
- public async Task GetOrDefaultAsync(int id,
- CancellationToken token)
- {
- var entity = await db.WellOperations
- .Include(s => s.WellSectionType)
- .Include(s => s.OperationCategory)
- .FirstOrDefaultAsync(e => e.Id == id, token)
- .ConfigureAwait(false);
-
- if (entity is null)
- return null;
-
- var timezone = wellService.GetTimezone(entity.IdWell);
-
- var dto = entity.Adapt();
- dto.WellSectionTypeName = entity.WellSectionType.Caption;
- dto.DateStart = entity.DateStart.ToRemoteDateTime(timezone.Hours);
- dto.CategoryName = entity.OperationCategory.Name;
- return dto;
- }
-
- public Task> GetAsync(WellOperationRequest request,
- CancellationToken token)
- {
- return Task.FromResult(Enumerable.Empty());
- }
-
- public async Task InsertRangeAsync(
- IEnumerable wellOperationDtos,
- CancellationToken token)
- {
- var firstOperation = wellOperationDtos
- .FirstOrDefault();
- if (firstOperation is null)
- return 0;
-
- var idWell = firstOperation.IdWell;
-
- var timezone = wellService.GetTimezone(idWell);
- foreach (var dto in wellOperationDtos)
- {
- var entity = dto.Adapt();
- entity.Id = default;
- entity.DateStart = dto.DateStart.ToUtcDateTimeOffset(timezone.Hours);
- entity.IdWell = idWell;
- db.WellOperations.Add(entity);
- }
-
- return await db.SaveChangesAsync(token)
- .ConfigureAwait(false);
- }
-
- public async Task UpdateAsync(
- WellOperationDto dto, CancellationToken token)
- {
- var timezone = wellService.GetTimezone(dto.IdWell);
- var entity = dto.Adapt();
- entity.DateStart = dto.DateStart.ToUtcDateTimeOffset(timezone.Hours);
- db.WellOperations.Update(entity);
- return await db.SaveChangesAsync(token)
- .ConfigureAwait(false);
- }
-
- public async Task DeleteAsync(IEnumerable ids,
- CancellationToken token)
- {
- var query = db.WellOperations.Where(e => ids.Contains(e.Id));
- db.WellOperations.RemoveRange(query);
- return await db.SaveChangesAsync(token)
- .ConfigureAwait(false);
- }
-
- private IQueryable BuildQuery(WellOperationRequest request)
- {
- var timezone = wellService.GetTimezone(request.IdWell);
-
- var query = db.WellOperations
- .Include(s => s.WellSectionType)
- .Include(s => s.OperationCategory)
- .Where(s => s.IdWell == request.IdWell);
-
- if (request.OperationType.HasValue)
- query = query.Where(e => e.IdType == request.OperationType.Value);
-
- if (request.SectionTypeIds?.Any() == true)
- query = query.Where(e => request.SectionTypeIds.Contains(e.IdWellSectionType));
-
- if (request.OperationCategoryIds?.Any() == true)
- query = query.Where(e => request.OperationCategoryIds.Contains(e.IdCategory));
-
- if (request.GeDepth.HasValue)
- query = query.Where(e => e.DepthEnd >= request.GeDepth.Value);
-
- if (request.LeDepth.HasValue)
- query = query.Where(e => e.DepthEnd <= request.LeDepth.Value);
-
- if (request.GeDate.HasValue)
- {
- var geDateOffset = request.GeDate.Value.ToUtcDateTimeOffset(timezone.Hours);
- query = query.Where(e => e.DateStart >= geDateOffset);
- }
-
- if (request.LeDate.HasValue)
- {
- var leDateOffset = request.LeDate.Value.ToUtcDateTimeOffset(timezone.Hours);
- query = query.Where(e => e.DateStart <= leDateOffset);
- }
-
- if (request.SortFields?.Any() == true)
- {
- query = query.SortBy(request.SortFields);
- }
- else
- {
- query = query
- .OrderBy(e => e.DateStart)
- .ThenBy(e => e.DepthEnd)
- .ThenBy(e => e.Id);
- }
-
- return query;
- }
- }
-#nullable disable
-}
diff --git a/AsbCloudInfrastructure/Services/WellService.cs b/AsbCloudInfrastructure/Services/WellService.cs
index 3d73dbe4..967c44ca 100644
--- a/AsbCloudInfrastructure/Services/WellService.cs
+++ b/AsbCloudInfrastructure/Services/WellService.cs
@@ -1,5 +1,6 @@
using AsbCloudApp.Data;
using AsbCloudApp.Exceptions;
+using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.EfCache;
@@ -23,7 +24,7 @@ namespace AsbCloudInfrastructure.Services
private readonly ITelemetryService telemetryService;
private readonly ICrudRepository companyTypesService;
private readonly ITimezoneService timezoneService;
- private readonly IWellOperationService wellOperationService;
+ private readonly IWellOperationRepository wellOperationRepository;
public ITelemetryService TelemetryService => telemetryService;
@@ -42,7 +43,7 @@ namespace AsbCloudInfrastructure.Services
this.telemetryService = telemetryService;
this.timezoneService = timezoneService;
- this.wellOperationService = new WellOperationService.WellOperationService(db, memoryCache, this);
+ this.wellOperationRepository = new WellOperationRepository(db, memoryCache, this);
companyTypesService = new CrudCacheRepositoryBase(dbContext, memoryCache);
}
@@ -216,7 +217,7 @@ namespace AsbCloudInfrastructure.Services
if (entity.Timezone is null)
dto.Timezone = GetTimezone(entity.Id);
- dto.StartDate = wellOperationService.FirstOperationDate(entity.Id)?.ToRemoteDateTime(dto.Timezone.Hours);
+ dto.StartDate = wellOperationRepository.FirstOperationDate(entity.Id)?.ToRemoteDateTime(dto.Timezone.Hours);
dto.WellType = entity.WellType?.Caption;
dto.Cluster = entity.Cluster?.Caption;
dto.Deposit = entity.Cluster?.Deposit?.Caption;
diff --git a/AsbCloudInfrastructure/Validators/ProcessMapValidator.cs b/AsbCloudInfrastructure/Validators/ProcessMapValidator.cs
index 22de04ad..661d01be 100644
--- a/AsbCloudInfrastructure/Validators/ProcessMapValidator.cs
+++ b/AsbCloudInfrastructure/Validators/ProcessMapValidator.cs
@@ -1,4 +1,4 @@
-using AsbCloudApp.Data;
+using AsbCloudApp.Data.ProcessMap;
using FluentValidation;
namespace AsbCloudInfrastructure.Validators
diff --git a/AsbCloudWebApi/Controllers/ProcessMapController.cs b/AsbCloudWebApi/Controllers/ProcessMapController.cs
index 6d4681ed..f5c955aa 100644
--- a/AsbCloudWebApi/Controllers/ProcessMapController.cs
+++ b/AsbCloudWebApi/Controllers/ProcessMapController.cs
@@ -1,4 +1,4 @@
-using AsbCloudApp.Data;
+using AsbCloudApp.Data.ProcessMap;
using AsbCloudApp.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@@ -20,12 +20,14 @@ namespace AsbCloudWebApi.Controllers
public class ProcessMapController : CrudWellRelatedController
{
private readonly ITelemetryService telemetryService;
+ private readonly IProcessMapReportService processMapReportService;
- public ProcessMapController(IWellService wellService, IProcessMapRepository service,
+ public ProcessMapController(IWellService wellService, IProcessMapRepository repository, IProcessMapReportService processMapReportService,
ITelemetryService telemetryService)
- : base(wellService, service)
+ : base(wellService, repository)
{
this.telemetryService = telemetryService;
+ this.processMapReportService = processMapReportService;
}
///
@@ -77,14 +79,28 @@ namespace AsbCloudWebApi.Controllers
/// Выгрузка расширенной РТК
///
///
+ /// ///
///
///
[HttpGet]
[Route("getReportFile/{wellId}")]
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)]
- public Task GetReportFileAsync(int wellId)
+ public async Task GetReportFileAsync(int wellId, CancellationToken token)
{
- throw new NotImplementedException();
+ var stream = await processMapReportService.MakeReportAsync(wellId, token);
+ if (stream != null)
+ {
+ var well = await wellService.GetOrDefaultAsync(wellId, token);
+ if (well is null)
+ return NoContent();
+ else
+ {
+ var fileName = $"РТК по скважине {well.Caption} куст {well.Cluster}.xlsx";
+ return File(stream, "application/octet-stream", fileName);
+ }
+ }
+ else
+ return NoContent();
}
///
diff --git a/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSaubController.cs b/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSaubController.cs
index b9ff1d88..4248778b 100644
--- a/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSaubController.cs
+++ b/AsbCloudWebApi/Controllers/SAUB/TelemetryDataSaubController.cs
@@ -15,7 +15,7 @@ namespace AsbCloudWebApi.Controllers.SAUB
{
public TelemetryDataSaubController(
ITelemetryService telemetryService,
- ITelemetryDataService telemetryDataService,
+ ITelemetryDataSaubService telemetryDataService,
IWellService wellService,
IHubContext telemetryHubContext)
: base(
diff --git a/AsbCloudWebApi/Controllers/SAUB/TelemetryWirelineRunOutController.cs b/AsbCloudWebApi/Controllers/SAUB/TelemetryWirelineRunOutController.cs
index c32fd408..c7829193 100644
--- a/AsbCloudWebApi/Controllers/SAUB/TelemetryWirelineRunOutController.cs
+++ b/AsbCloudWebApi/Controllers/SAUB/TelemetryWirelineRunOutController.cs
@@ -24,7 +24,7 @@ namespace AsbCloudWebApi.Controllers.SAUB
private readonly IWellService wellService;
private readonly IHubContext telemetryHubContext;
private readonly ITelemetryWirelineRunOutRepository repository;
- private string SirnalRMethodGetDataName => "ReceiveWirelineRunOut";
+ private static string SirnalRMethodGetDataName => "ReceiveWirelineRunOut";
public TelemetryWirelineRunOutController(
ITelemetryService telemetryService,
diff --git a/AsbCloudWebApi/Controllers/WellOperationController.cs b/AsbCloudWebApi/Controllers/WellOperationController.cs
index 2fc8a757..46ce1683 100644
--- a/AsbCloudWebApi/Controllers/WellOperationController.cs
+++ b/AsbCloudWebApi/Controllers/WellOperationController.cs
@@ -1,4 +1,5 @@
using AsbCloudApp.Data;
+using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using Microsoft.AspNetCore.Authorization;
@@ -20,13 +21,13 @@ namespace AsbCloudWebApi.Controllers
[Authorize]
public class WellOperationController : ControllerBase
{
- private readonly IWellOperationService operationService;
+ private readonly IWellOperationRepository operationRepository;
private readonly IWellService wellService;
private readonly IWellOperationImportService wellOperationImportService;
- public WellOperationController(IWellOperationService operationService, IWellService wellService, IWellOperationImportService wellOperationImportService)
+ public WellOperationController(IWellOperationRepository operationService, IWellService wellService, IWellOperationImportService wellOperationImportService)
{
- this.operationService = operationService;
+ this.operationRepository = operationService;
this.wellService = wellService;
this.wellOperationImportService = wellOperationImportService;
}
@@ -41,7 +42,7 @@ namespace AsbCloudWebApi.Controllers
[ProducesResponseType(typeof(IDictionary), (int)System.Net.HttpStatusCode.OK)]
public IActionResult GetSectionTypes()
{
- var result = operationService.GetSectionTypes();
+ var result = operationRepository.GetSectionTypes();
return Ok(result);
}
@@ -55,7 +56,7 @@ namespace AsbCloudWebApi.Controllers
[ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)]
public IActionResult GetCategories()
{
- var result = operationService.GetCategories();
+ var result = operationRepository.GetCategories();
return Ok(result);
}
@@ -78,7 +79,7 @@ namespace AsbCloudWebApi.Controllers
return Forbid();
var requestToService = new WellOperationRequest(request, idWell);
- var result = await operationService.GetOperationsAsync(
+ var result = await operationRepository.GetPageAsync(
requestToService,
token)
.ConfigureAwait(false);
@@ -105,7 +106,7 @@ namespace AsbCloudWebApi.Controllers
return Forbid();
var requestToService = new WellOperationRequest(request, idWell);
- var result = await operationService.GetGroupOperationsStatAsync(
+ var result = await operationRepository.GetGroupOperationsStatAsync(
requestToService,
token)
.ConfigureAwait(false);
@@ -129,7 +130,7 @@ namespace AsbCloudWebApi.Controllers
if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
return Forbid();
- var result = await operationService.GetOrDefaultAsync(idOperation, token).ConfigureAwait(false);
+ var result = await operationRepository.GetOrDefaultAsync(idOperation, token).ConfigureAwait(false);
return Ok(result);
}
@@ -152,7 +153,7 @@ namespace AsbCloudWebApi.Controllers
foreach(var value in values)
value.IdWell= idWell;
- var result = await operationService.InsertRangeAsync(values, token)
+ var result = await operationRepository.InsertRangeAsync(values, token)
.ConfigureAwait(false);
return Ok(result);
@@ -178,7 +179,7 @@ namespace AsbCloudWebApi.Controllers
value.IdWell= idWell;
value.Id = idOperation;
- var result = await operationService.UpdateAsync(value, token)
+ var result = await operationRepository.UpdateAsync(value, token)
.ConfigureAwait(false);
return Ok(result);
}
@@ -199,7 +200,7 @@ namespace AsbCloudWebApi.Controllers
token).ConfigureAwait(false))
return Forbid();
- var result = await operationService.DeleteAsync(new int[] { idOperation }, token)
+ var result = await operationRepository.DeleteAsync(new int[] { idOperation }, token)
.ConfigureAwait(false);
return Ok(result);
diff --git a/ConsoleApp1/ServiceFactory.cs b/ConsoleApp1/ServiceFactory.cs
index bf7c9a42..eceb5f9b 100644
--- a/ConsoleApp1/ServiceFactory.cs
+++ b/ConsoleApp1/ServiceFactory.cs
@@ -1,4 +1,5 @@
using AsbCloudDb.Model;
+using AsbCloudInfrastructure.Repository;
using AsbCloudInfrastructure.Services;
using AsbCloudInfrastructure.Services.SAUB;
using AsbCloudInfrastructure.Services.WellOperationService;
@@ -71,7 +72,7 @@ namespace ConsoleApp1
public static WellService MakeWellService()
=> new (Context, memoryCache, MakeTelemetryService(), TimezoneService);
- public static WellOperationService MakeWellOperationsService()
+ public static WellOperationRepository MakeWellOperationRepository()
=> new (Context, memoryCache, MakeWellService());
public static OperationsStatService MakeOperationsStatService()