diff --git a/AsbCloudApp/Data/WellOperation/WellOperationDto.cs b/AsbCloudApp/Data/WellOperation/WellOperationDto.cs
index b940a9ae..13f070a3 100644
--- a/AsbCloudApp/Data/WellOperation/WellOperationDto.cs
+++ b/AsbCloudApp/Data/WellOperation/WellOperationDto.cs
@@ -1,119 +1,22 @@
-using System;
-using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace AsbCloudApp.Data.WellOperation;
///
-/// Операция по скважине
+/// Операция по скважине c Day и NPV
///
-public class WellOperationDto : ItemInfoDto,
- IId,
- IWellRelated,
- IValidatableObject
+public class WellOperationDto : WellOperationBaseDto
{
- ///
- [Required]
- public int Id { get; set; }
+ ///
+ /// Кол-во дней от даты начала первой плановой (а если её нет, то фактической) операции
+ ///
+ [Required]
+ public double Day { get; set; }
- ///
- [Required]
- public int IdWell { get; set; }
+ ///
+ /// Кол-во часов НПВ от даты начала первой плановой (а если её нет, то фактической) операции
+ ///
+ [Required]
+ public double NptHours { get; set; }
- ///
- /// Id секции скважины
- ///
- public int IdWellSectionType { get; set; }
-
- ///
- /// 0 = план или 1 = факт или прогноз = 2
- ///
- [Required]
- public int IdType { get; set; }
-
- ///
- /// id категории операции
- ///
- public int IdCategory { get; set; }
-
- ///
- /// Глубина на начало операции, м
- ///
- public double DepthStart { get; set; }
-
- ///
- /// Глубина после завершения операции, м
- ///
- [Required]
- [Range(0, 50_000)]
- public double DepthEnd { get; set; }
-
- ///
- /// Дата начала операции
- ///
- [Required]
- public DateTimeOffset DateStart { get; set; }
-
- ///
- /// Продолжительность, часы
- ///
- public double DurationHours { get; set; }
-
- ///
- /// Наименование секции
- ///
- public string? WellSectionTypeCaption { get; set; }
-
- ///
- /// Наименование категории
- ///
- public string? OperationCategoryName { get; set; }
-
- ///
- /// id плановой операции для сопоставления
- ///
- public int? IdPlan { get; set; }
-
- ///
- /// Ключ родителя у категории
- ///
- public int? IdParentCategory { get; set; }
-
- ///
- /// дополнительная информация по операции
- ///
- [StringLength(8192)]
- public string? CategoryInfo { get; set; }
-
- ///
- /// Кол-во дней от даты начала первой плановой (а если её нет, то фактической) операции
- ///
- [Required]
- public double Day { get; set; }
-
- ///
- /// Кол-во часов НПВ от даты начала первой плановой (а если её нет, то фактической) операции
- ///
- [Required]
- public double NptHours { get; set; }
-
- ///
- /// Полезный комментарий
- ///
- [StringLength(4096, ErrorMessage = "Комментарий не может быть длиннее 4096 символов")]
- public string? Comment { get; set; }
-
- ///
- /// Валидация даты
- ///
- ///
- ///
- public IEnumerable Validate(ValidationContext validationContext)
- {
- var gtDate = new DateTimeOffset(2010, 1, 1, 0, 0, 0, TimeSpan.Zero);
- if (DateStart <= gtDate)
- yield return new ValidationResult(
- $"{nameof(DateStart)}: DateStart не может быть меньше {gtDate}",
- new[] { nameof(DateStart) });
- }
}
\ No newline at end of file
diff --git a/AsbCloudApp/Repositories/IWellOperationRepository.cs b/AsbCloudApp/Repositories/IWellOperationRepository.cs
index 612d58d9..c6b3c724 100644
--- a/AsbCloudApp/Repositories/IWellOperationRepository.cs
+++ b/AsbCloudApp/Repositories/IWellOperationRepository.cs
@@ -18,46 +18,6 @@ namespace AsbCloudApp.Repositories
///
IEnumerable GetSectionTypes();
- ///
- /// Получить страницу списка операций
- ///
- ///
- ///
- ///
- Task> GetAsync(WellOperationRequest request, CancellationToken token);
-
- ///
- /// Получить страницу списка операций
- ///
- ///
- ///
- ///
- Task> GetPageAsync(WellOperationRequest request, CancellationToken token);
-
- ///
- /// Получить страницу с операцией
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- Task?> GetPageAsync(int idWell,
- int id,
- int operationType,
- int? take,
- IEnumerable? sortFields,
- CancellationToken token);
-
- ///
- /// Получить статистику операции по скважине с группировкой по категориям
- ///
- ///
- ///
- ///
- Task> GetGroupOperationsStatAsync(WellOperationRequest request, CancellationToken token);
///
/// Добавить несколько операций
@@ -66,7 +26,7 @@ namespace AsbCloudApp.Repositories
///
///
///
- Task InsertRangeAsync(IEnumerable dtos, bool deleteBeforeInsert, CancellationToken token);
+ Task InsertRangeAsync(IEnumerable dtos, bool deleteBeforeInsert, CancellationToken token);
///
/// Обновить существующую операцию
@@ -74,7 +34,7 @@ namespace AsbCloudApp.Repositories
///
///
///
- Task UpdateRangeAsync(IEnumerable dtos, CancellationToken token);
+ Task UpdateRangeAsync(IEnumerable dtos, CancellationToken token);
///
/// Удалить операции по id
@@ -106,6 +66,14 @@ namespace AsbCloudApp.Repositories
///
///
///
- (WellOperationDto First, WellOperationDto Last)? GetFirstAndLastFact(int idWell);
+ (WellOperationBaseDto First, WellOperationBaseDto Last)? GetFirstAndLastFact(int idWell);
+
+ ///
+ /// Получить список операций по запросу
+ ///
+ ///
+ ///
+ ///
+ Task> GetAll(WellOperationRequest request, CancellationToken token);
}
}
\ No newline at end of file
diff --git a/AsbCloudApp/Services/IWellOperationService.cs b/AsbCloudApp/Services/IWellOperationService.cs
new file mode 100644
index 00000000..fc755237
--- /dev/null
+++ b/AsbCloudApp/Services/IWellOperationService.cs
@@ -0,0 +1,58 @@
+using AsbCloudApp.Data;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using AsbCloudApp.Data.WellOperation;
+using AsbCloudApp.Requests;
+
+namespace AsbCloudApp.Services
+{
+ ///
+ /// Сервис по представлению данных по операциям
+ ///
+ public interface IWellOperationService
+ {
+ ///
+ /// Получить страницу списка операций
+ ///
+ ///
+ ///
+ ///
+ Task> GetAsync(WellOperationRequest request, CancellationToken token);
+
+ ///
+ /// Получить страницу списка операций
+ ///
+ ///
+ ///
+ ///
+ Task> GetPageAsync(WellOperationRequest request, CancellationToken token);
+
+ ///
+ /// Получить страницу с операцией
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task?> GetPageAsync(int idWell,
+ int id,
+ int operationType,
+ int? take,
+ IEnumerable? sortFields,
+ CancellationToken token);
+
+ ///
+ /// Получить статистику операции по скважине с группировкой по категориям
+ ///
+ ///
+ ///
+ ///
+ Task> GetGroupOperationsStatAsync(WellOperationRequest request, CancellationToken token);
+ }
+
+
+}
diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs
index 5ce1ada0..b3943a6c 100644
--- a/AsbCloudInfrastructure/DependencyInjection.cs
+++ b/AsbCloudInfrastructure/DependencyInjection.cs
@@ -40,6 +40,7 @@ using AsbCloudInfrastructure.Services.Trajectory.Export;
using AsbCloudInfrastructure.Services.Trajectory.Parser;
using AsbCloudInfrastructure.Services.WellOperations.Factories;
using AsbCloudInfrastructure.Services.WellOperationService;
+using AsbCloudInfrastructure.Services.WellOperationService.WellOperationService;
using Mapster;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
@@ -317,6 +318,7 @@ namespace AsbCloudInfrastructure
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
services.AddTransient<
IChangeLogRepository,
diff --git a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs
index 843956cb..1e0d1add 100644
--- a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs
+++ b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs
@@ -17,7 +17,7 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Repository;
-public class WellOperationRepository : CrudRepositoryBase,
+public class WellOperationRepository : CrudRepositoryBase,
IWellOperationRepository
{
private const string cacheKeyWellOperations = "FirstAndLastFactWellsOperations";
@@ -40,139 +40,14 @@ public class WellOperationRepository : CrudRepositoryBase wellOperationCategoryRepository.Get(true, false).ToDictionary(c => c.Id));
LazyWellSectionTypes = new(() => GetSectionTypes().ToDictionary(c => c.Id));
}
-
+
public IEnumerable GetSectionTypes() =>
memoryCache
.GetOrCreateBasic(dbContext.WellSectionTypes)
.OrderBy(s => s.Order)
.Select(s => s.Adapt());
- public async Task> GetAsync(WellOperationRequest request, CancellationToken token)
- {
- var (items, _) = await GetWithDaysAndNpvAsync(request, token);
- return items;
- }
-
- public async Task> GetPageAsync(WellOperationRequest request, CancellationToken token)
- {
- request.Skip = request.Skip ?? 0;
- request.Take = request.Take ?? 32;
-
- var (items, count) = await GetWithDaysAndNpvAsync(request, token);
-
- var paginationContainer = new PaginationContainer
- {
- Skip = request.Skip!.Value,
- Take = request.Take!.Value,
- Count = count,
- Items = items
- };
-
- return paginationContainer;
- }
-
- public async Task?> GetPageAsync(int idWell,
- int id,
- int operationType,
- int? take,
- IEnumerable? sortFields,
- CancellationToken token)
- {
- var request = new WellOperationRequest(new[] { idWell })
- {
- OperationType = operationType,
- SortFields = sortFields,
- };
-
- var (wellOperations, count) = await GetWithDaysAndNpvAsync(request, token);
-
- var skip = 0;
- take ??= 32;
-
- while (skip < count)
- {
- var page = wellOperations.Skip(skip)
- .Take(take.Value);
-
- if (page.Any(x => x.Id == id))
- {
- var paginationContainer = new PaginationContainer
- {
- Skip = skip,
- Take = take.Value,
- Items = page,
- Count = count
- };
-
- return paginationContainer;
- }
-
- skip += take.Value;
- }
-
- return null;
- }
-
- public async Task> GetGroupOperationsStatAsync(WellOperationRequest request, CancellationToken token)
- {
- var query = BuildQuery(request);
- var entities = await query
- .Select(o => new
- {
- o.IdCategory,
- DurationMinutes = o.DurationHours * 60,
- DurationDepth = o.DepthEnd - o.DepthStart
- })
- .ToArrayAsync(token);
-
- var parentRelationDictionary = wellOperationCategoryRepository.Get(true)
- .ToDictionary(c => c.Id, c => new
- {
- c.Name,
- c.IdParent
- });
-
- var dtos = entities
- .GroupBy(o => o.IdCategory)
- .Select(g => new WellGroupOpertionDto
- {
- IdCategory = g.Key,
- Category = parentRelationDictionary[g.Key].Name,
- Count = g.Count(),
- MinutesAverage = g.Average(o => o.DurationMinutes),
- MinutesMin = g.Min(o => o.DurationMinutes),
- MinutesMax = g.Max(o => o.DurationMinutes),
- TotalMinutes = g.Sum(o => o.DurationMinutes),
- DeltaDepth = g.Sum(o => o.DurationDepth),
- IdParent = parentRelationDictionary[g.Key].IdParent
- });
-
- while (dtos.All(x => x.IdParent != null))
- {
- dtos = dtos
- .GroupBy(o => o.IdParent!)
- .Select(g =>
- {
- var idCategory = g.Key ?? int.MinValue;
- var category = parentRelationDictionary.GetValueOrDefault(idCategory);
- var newDto = new WellGroupOpertionDto
- {
- IdCategory = idCategory,
- Category = category?.Name ?? "unknown",
- Count = g.Sum(o => o.Count),
- DeltaDepth = g.Sum(o => o.DeltaDepth),
- TotalMinutes = g.Sum(o => o.TotalMinutes),
- Items = g.ToList(),
- IdParent = category?.IdParent,
- };
- return newDto;
- });
- }
-
- return dtos;
- }
-
- public async Task InsertRangeAsync(IEnumerable dtos,
+ public async Task InsertRangeAsync(IEnumerable dtos,
bool deleteBeforeInsert,
CancellationToken token)
{
@@ -189,7 +64,7 @@ public class WellOperationRepository : CrudRepositoryBase UpdateRangeAsync(IEnumerable dtos, CancellationToken token)
+ public override async Task UpdateRangeAsync(IEnumerable dtos, CancellationToken token)
{
EnsureValidWellOperations(dtos);
@@ -223,7 +98,7 @@ public class WellOperationRepository : CrudRepositoryBase dtos)
+ private static void EnsureValidWellOperations(IEnumerable dtos)
{
if (dtos.GroupBy(d => d.IdType).Count() > 1)
throw new ArgumentInvalidException(nameof(dtos), "Все операции должны быть одного типа");
@@ -232,101 +107,6 @@ public class WellOperationRepository : CrudRepositoryBase> GetByIdsWells(IEnumerable idsWells, CancellationToken token)
- {
- var query = GetQuery()
- .Where(e => idsWells.Contains(e.IdWell))
- .OrderBy(e => e.DateStart);
- var entities = await query.ToArrayAsync(token);
- return entities;
- }
-
- private async Task<(IEnumerable items, int count)> GetWithDaysAndNpvAsync(WellOperationRequest request, CancellationToken token)
- {
- var entities = await GetByIdsWells(request.IdsWell, token);
- var groupedByWellAndType = entities
- .GroupBy(e => new { e.IdWell, e.IdType });
-
- var result = new List();
- var count = 0;
- foreach (var wellOperationsWithType in groupedByWellAndType)
- {
- var firstWellOperation = wellOperationsWithType.MinBy(e => e.DateStart);
-
- var operationsWithNpt = wellOperationsWithType
- .Where(o => WellOperationCategory.NonProductiveTimeSubIds.Contains(o.IdCategory));
-
- IEnumerable filteredWellOperations = FilterByRequest(wellOperationsWithType.AsQueryable(), request);
-
- count += filteredWellOperations.Count();
-
- if (request.Skip != null)
- filteredWellOperations = filteredWellOperations.Skip((int)request.Skip);
- if (request.Take != null)
- filteredWellOperations = filteredWellOperations.Take((int)request.Take);
-
- var timezoneOffset = wellService.GetTimezone(wellOperationsWithType.Key.IdWell).Offset;
-
- var dtos = filteredWellOperations
- .Select(entity =>
- {
- var dto = Convert(entity, timezoneOffset);
- dto.Day = (entity.DateStart - firstWellOperation.DateStart).TotalDays;
- dto.NptHours = operationsWithNpt
- .Where(o => o.DateStart <= entity.DateStart)
- .Sum(e => e.DurationHours);
- return dto;
- });
-
- result.AddRange(dtos);
- }
-
- return (result, count);
- }
-
- private static IQueryable FilterByRequest(IQueryable entities, WellOperationRequest request)
- {
- if (request.OperationType.HasValue)
- entities = entities.Where(e => e.IdType == request.OperationType.Value);
- if (request.SectionTypeIds?.Any() is true)
- entities = entities.Where(e => request.SectionTypeIds.Contains(e.IdWellSectionType));
- if (request.OperationCategoryIds?.Any() is true)
- entities = entities.Where(e => request.OperationCategoryIds.Contains(e.IdCategory));
- if (request.GeDepth.HasValue)
- entities = entities.Where(e => e.DepthEnd >= request.GeDepth.Value);
- if (request.LeDepth.HasValue)
- entities = entities.Where(e => e.DepthEnd <= request.LeDepth.Value);
-
- if (request.GeDate.HasValue)
- {
- var geDateUtc = request.GeDate.Value.UtcDateTime;
- entities = entities.Where(e => e.DateStart >= geDateUtc);
- }
-
- if (request.LeDate.HasValue)
- {
- var leDateUtc = request.LeDate.Value.UtcDateTime;
- entities = entities.Where(e => e.DateStart <= leDateUtc);
- }
- if (request.SortFields?.Any() is true)
- entities = entities.AsQueryable().SortBy(request.SortFields);
- else
- entities = entities.AsQueryable().OrderBy(e => e.DateStart);
-
- return entities;
- }
-
- private IQueryable BuildQuery(WellOperationRequest request)
- {
- var query = GetQuery()
- .Where(e => request.IdsWell.Contains(e.IdWell))
- .OrderBy(e => e.DateStart)
- .AsQueryable();
- query = FilterByRequest(query, request);
-
- return query;
- }
-
public async Task> GetSectionsAsync(IEnumerable idsWells, CancellationToken token)
{
const string keyCacheSections = "OperationsBySectionSummarties";
@@ -415,7 +195,7 @@ public class WellOperationRepository : CrudRepositoryBase
{
@@ -462,16 +242,16 @@ public class WellOperationRepository : CrudRepositoryBase();
entity.DateStart = src.DateStart.UtcDateTime;
return entity;
}
- private WellOperationDto Convert(WellOperation src, TimeSpan timezoneOffset)
+ private WellOperationBaseDto Convert(WellOperation src, TimeSpan timezoneOffset)
{
- var dto = src.Adapt();
+ var dto = src.Adapt();
dto.DateStart = src.DateStart.ToOffset(timezoneOffset);
dto.LastUpdateDate = src.LastUpdateDate.ToOffset(timezoneOffset);
@@ -479,4 +259,58 @@ public class WellOperationRepository : CrudRepositoryBase> GetAll(WellOperationRequest request, CancellationToken token)
+ {
+ var timezoneOffsetDictionary = new Dictionary();
+ foreach (var idWell in request.IdsWell)
+ {
+ var offset = wellService.GetTimezone(idWell).Offset;
+ timezoneOffsetDictionary.Add(idWell, offset);
+ }
+
+ var query = GetQuery()
+ .Where(e => request.IdsWell.Contains(e.IdWell))
+ .OrderBy(e => e.DateStart)
+ .AsQueryable();
+ query = FilterByRequest(query, request);
+
+ var entities = await query.ToArrayAsync(token);
+
+ var dtos = entities.Select(o => Convert(o, timezoneOffsetDictionary[o.IdWell]));
+ return dtos;
+ }
+
+
+ public static IQueryable FilterByRequest(IQueryable entities, WellOperationRequest request)
+ {
+ if (request.OperationType.HasValue)
+ entities = entities.Where(e => e.IdType == request.OperationType.Value);
+ if (request.SectionTypeIds?.Any() is true)
+ entities = entities.Where(e => request.SectionTypeIds.Contains(e.IdWellSectionType));
+ if (request.OperationCategoryIds?.Any() is true)
+ entities = entities.Where(e => request.OperationCategoryIds.Contains(e.IdCategory));
+ if (request.GeDepth.HasValue)
+ entities = entities.Where(e => e.DepthEnd >= request.GeDepth.Value);
+ if (request.LeDepth.HasValue)
+ entities = entities.Where(e => e.DepthEnd <= request.LeDepth.Value);
+
+ if (request.GeDate.HasValue)
+ {
+ var geDateUtc = request.GeDate.Value.UtcDateTime;
+ entities = entities.Where(e => e.DateStart >= geDateUtc);
+ }
+
+ if (request.LeDate.HasValue)
+ {
+ var leDateUtc = request.LeDate.Value.UtcDateTime;
+ entities = entities.Where(e => e.DateStart <= leDateUtc);
+ }
+ if (request.SortFields?.Any() is true)
+ entities = entities.AsQueryable().SortBy(request.SortFields);
+ else
+ entities = entities.AsQueryable().OrderBy(e => e.DateStart);
+
+ return entities;
+ }
}
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs
index 08ac2420..4e94a571 100644
--- a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs
+++ b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs
@@ -32,27 +32,30 @@ public class DailyReportService : IDailyReportService
private readonly ISubsystemService subsystemService;
private readonly IProcessMapReportDrillingService processMapReportDrillingService;
private readonly IDetectedOperationService detectedOperationService;
+ private readonly IWellOperationService wellOperationService;
- public DailyReportService(IWellService wellService,
+ public DailyReportService(IWellService wellService,
ITrajectoryNnbRepository trajectoryFactNnbRepository,
- IDailyReportRepository dailyReportRepository,
- IScheduleRepository scheduleRepository,
- IWellOperationRepository wellOperationRepository,
- ISubsystemService subsystemService,
+ IDailyReportRepository dailyReportRepository,
+ IScheduleRepository scheduleRepository,
+ IWellOperationRepository wellOperationRepository,
+ ISubsystemService subsystemService,
IProcessMapReportDrillingService processMapReportDrillingService,
- IDetectedOperationService detectedOperationService)
- {
- this.wellService = wellService;
- this.trajectoryFactNnbRepository = trajectoryFactNnbRepository;
- this.dailyReportRepository = dailyReportRepository;
- this.scheduleRepository = scheduleRepository;
- this.wellOperationRepository = wellOperationRepository;
- this.subsystemService = subsystemService;
- this.processMapReportDrillingService = processMapReportDrillingService;
- this.detectedOperationService = detectedOperationService;
- }
+ IDetectedOperationService detectedOperationService,
+ IWellOperationService wellOperationService)
+ {
+ this.wellService = wellService;
+ this.trajectoryFactNnbRepository = trajectoryFactNnbRepository;
+ this.dailyReportRepository = dailyReportRepository;
+ this.scheduleRepository = scheduleRepository;
+ this.wellOperationRepository = wellOperationRepository;
+ this.subsystemService = subsystemService;
+ this.processMapReportDrillingService = processMapReportDrillingService;
+ this.detectedOperationService = detectedOperationService;
+ this.wellOperationService = wellOperationService;
+ }
- public async Task UpdateOrInsertAsync(int idWell, DateOnly dateDailyReport, int idUser, TBlock editableBlock,
+ public async Task UpdateOrInsertAsync(int idWell, DateOnly dateDailyReport, int idUser, TBlock editableBlock,
CancellationToken cancellationToken)
where TBlock : ItemInfoDto
{
@@ -118,7 +121,7 @@ public class DailyReportService : IDailyReportService
LeDate = leDate
};
- var factWellOperations = (await wellOperationRepository.GetAsync(factOperationRequest, cancellationToken))
+ var factWellOperations = (await wellOperationService.GetAsync(factOperationRequest, cancellationToken))
.OrderBy(o => o.DateStart)
.ThenBy(o => o.DepthStart);
@@ -191,7 +194,7 @@ public class DailyReportService : IDailyReportService
LeDate = leDateFactWellOperation
};
- var factWellOperations = await wellOperationRepository.GetAsync(factWellOperationRequest, cancellationToken);
+ var factWellOperations = await wellOperationService.GetAsync(factWellOperationRequest, cancellationToken);
if (request.SortFields?.Contains("DateStart desc") == true)
{
diff --git a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDrillingService.cs b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDrillingService.cs
index e0d1287d..cae5bdce 100644
--- a/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDrillingService.cs
+++ b/AsbCloudInfrastructure/Services/ProcessMaps/Report/ProcessMapReportDrillingService.cs
@@ -26,13 +26,15 @@ public class ProcessMapReportDrillingService : IProcessMapReportDrillingService
private readonly IDataSaubStatRepository dataSaubStatRepository;
private readonly IWellOperationRepository wellOperationRepository;
private readonly IWellOperationCategoryRepository wellOperationCategoryRepository;
+ private readonly IWellOperationService wellOperationService;
public ProcessMapReportDrillingService(IWellService wellService,
IChangeLogRepository processMapPlanRotorRepository,
IChangeLogRepository processMapPlanSlideRepository,
IDataSaubStatRepository dataSaubStatRepository,
IWellOperationRepository wellOperationRepository,
- IWellOperationCategoryRepository wellOperationCategoryRepository
+ IWellOperationCategoryRepository wellOperationCategoryRepository,
+ IWellOperationService wellOperationService
)
{
this.wellService = wellService;
@@ -41,6 +43,7 @@ public class ProcessMapReportDrillingService : IProcessMapReportDrillingService
this.dataSaubStatRepository = dataSaubStatRepository;
this.wellOperationRepository = wellOperationRepository;
this.wellOperationCategoryRepository = wellOperationCategoryRepository;
+ this.wellOperationService = wellOperationService;
}
public async Task> GetAsync(int idWell, DataSaubStatRequest request, CancellationToken token)
@@ -72,7 +75,7 @@ public class ProcessMapReportDrillingService : IProcessMapReportDrillingService
GeDepth = geDepth,
LeDepth = leDepth
};
- var wellOperations = await wellOperationRepository
+ var wellOperations = await wellOperationService
.GetAsync(requestWellOperationFact, token);
var orderedWellOperations = wellOperations
diff --git a/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs b/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs
index 34665720..209161f7 100644
--- a/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs
+++ b/AsbCloudInfrastructure/Services/WellCompositeOperationService.cs
@@ -17,8 +17,8 @@ public class WellCompositeOperationService : IWellCompositeOperationService
{
private readonly ICrudRepository wellSectionTypeRepository;
private readonly IWellOperationCategoryRepository wellOperationCategoryRepository;
- private readonly IWellOperationRepository wellOperationRepository;
private readonly IWellService wellService;
+ private readonly IWellOperationService wellOperationService;
///
/// Тип секции "Транспортный стол"
@@ -206,12 +206,10 @@ public class WellCompositeOperationService : IWellCompositeOperationService
public WellCompositeOperationService(
ICrudRepository wellSectionTypeRepository,
IWellOperationCategoryRepository wellOperationCategoryRepository,
- IWellOperationRepository wellOperationRepository,
IWellService wellService)
{
this.wellSectionTypeRepository = wellSectionTypeRepository;
this.wellOperationCategoryRepository = wellOperationCategoryRepository;
- this.wellOperationRepository = wellOperationRepository;
this.wellService = wellService;
}
@@ -235,7 +233,7 @@ public class WellCompositeOperationService : IWellCompositeOperationService
SectionTypeIds = idsWellSectionTypes,
OperationType = WellOperation.IdOperationTypeFact
};
- var operations = await wellOperationRepository.GetAsync(wellOperationRequest, token);
+ var operations = await wellOperationService.GetAsync(wellOperationRequest, token);
var operationsForComposite = operations.Select(o => CreateCompositeOperation(o, sectionsDict, categoriesDict));
diff --git a/AsbCloudInfrastructure/Services/WellOperationService/WellOperationService.cs b/AsbCloudInfrastructure/Services/WellOperationService/WellOperationService.cs
new file mode 100644
index 00000000..c1ff4eb3
--- /dev/null
+++ b/AsbCloudInfrastructure/Services/WellOperationService/WellOperationService.cs
@@ -0,0 +1,232 @@
+using AsbCloudApp.Data;
+using AsbCloudApp.Data.WellOperation;
+using AsbCloudApp.Repositories;
+using AsbCloudApp.Requests;
+using AsbCloudApp.Services;
+using AsbCloudDb;
+using AsbCloudDb.Model;
+using Mapster;
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace AsbCloudInfrastructure.Services.WellOperationService.WellOperationService;
+public class WellOperationService : IWellOperationService
+{
+ private readonly IWellService wellService;
+ private readonly IWellOperationRepository wellOperationRepository;
+ private readonly IWellOperationCategoryRepository wellOperationCategoryRepository;
+
+ public WellOperationService(
+ IWellService wellService,
+ IWellOperationRepository wellOperationRepository,
+ IWellOperationCategoryRepository wellOperationCategoryRepository)
+ {
+ this.wellService = wellService;
+ this.wellOperationRepository = wellOperationRepository;
+ this.wellOperationCategoryRepository = wellOperationCategoryRepository;
+ }
+
+ public async Task> GetAsync(WellOperationRequest request, CancellationToken token)
+ {
+ var (items, _) = await GetWithDaysAndNpvAsync(request, token);
+ return items;
+ }
+
+ public async Task> GetPageAsync(WellOperationRequest request, CancellationToken token)
+ {
+ request.Skip = request.Skip ?? 0;
+ request.Take = request.Take ?? 32;
+
+ var (items, count) = await GetWithDaysAndNpvAsync(request, token);
+
+ var paginationContainer = new PaginationContainer
+ {
+ Skip = request.Skip!.Value,
+ Take = request.Take!.Value,
+ Count = count,
+ Items = items
+ };
+
+ return paginationContainer;
+ }
+
+ public async Task?> GetPageAsync(int idWell,
+ int id,
+ int operationType,
+ int? take,
+ IEnumerable? sortFields,
+ CancellationToken token)
+ {
+ var request = new WellOperationRequest(new[] { idWell })
+ {
+ OperationType = operationType,
+ SortFields = sortFields,
+ };
+
+ var (wellOperations, count) = await GetWithDaysAndNpvAsync(request, token);
+
+ var skip = 0;
+ take ??= 32;
+
+ while (skip < count)
+ {
+ var page = wellOperations.Skip(skip)
+ .Take(take.Value);
+
+ if (page.Any(x => x.Id == id))
+ {
+ var paginationContainer = new PaginationContainer
+ {
+ Skip = skip,
+ Take = take.Value,
+ Items = page,
+ Count = count
+ };
+
+ return paginationContainer;
+ }
+
+ skip += take.Value;
+ }
+
+ return null;
+ }
+
+ public async Task> GetGroupOperationsStatAsync(WellOperationRequest request, CancellationToken token)
+ {
+ var wellOperationsBaseDto = await wellOperationRepository.GetAll(request, token);
+ var wellOperationsData = wellOperationsBaseDto
+ .Select(o => new
+ {
+ o.IdCategory,
+ DurationMinutes = o.DurationHours * 60,
+ DurationDepth = o.DepthEnd - o.DepthStart
+ });
+
+ var parentRelationDictionary = wellOperationCategoryRepository.Get(true)
+ .ToDictionary(c => c.Id, c => new
+ {
+ c.Name,
+ c.IdParent
+ });
+
+ var dtos = wellOperationsData
+ .GroupBy(o => o.IdCategory)
+ .Select(g => new WellGroupOpertionDto
+ {
+ IdCategory = g.Key,
+ Category = parentRelationDictionary[g.Key].Name,
+ Count = g.Count(),
+ MinutesAverage = g.Average(o => o.DurationMinutes),
+ MinutesMin = g.Min(o => o.DurationMinutes),
+ MinutesMax = g.Max(o => o.DurationMinutes),
+ TotalMinutes = g.Sum(o => o.DurationMinutes),
+ DeltaDepth = g.Sum(o => o.DurationDepth),
+ IdParent = parentRelationDictionary[g.Key].IdParent
+ });
+
+ while (dtos.All(x => x.IdParent != null))
+ {
+ dtos = dtos
+ .GroupBy(o => o.IdParent!)
+ .Select(g =>
+ {
+ var idCategory = g.Key ?? int.MinValue;
+ var category = parentRelationDictionary.GetValueOrDefault(idCategory);
+ var newDto = new WellGroupOpertionDto
+ {
+ IdCategory = idCategory,
+ Category = category?.Name ?? "unknown",
+ Count = g.Sum(o => o.Count),
+ DeltaDepth = g.Sum(o => o.DeltaDepth),
+ TotalMinutes = g.Sum(o => o.TotalMinutes),
+ Items = g.ToList(),
+ IdParent = category?.IdParent,
+ };
+ return newDto;
+ });
+ }
+
+ return dtos;
+ }
+
+ private async Task<(IEnumerable items, int count)> GetWithDaysAndNpvAsync(WellOperationRequest request, CancellationToken token)
+ {
+ var requestByWellIds = new WellOperationRequest(request.IdsWell);
+ var wellOperationsBaseDtos = await wellOperationRepository.GetAll(requestByWellIds, token);
+ var groupedByWellAndTypeDtos = wellOperationsBaseDtos
+ .GroupBy(e => new { e.IdWell, e.IdType });
+
+ var result = new List();
+ var count = 0;
+ foreach (var wellOperationsWithTypeDto in groupedByWellAndTypeDtos)
+ {
+ var firstWellOperation = wellOperationsWithTypeDto.MinBy(e => e.DateStart)!;
+
+ var operationsWithNpt = wellOperationsWithTypeDto
+ .Where(o => WellOperationCategory.NonProductiveTimeSubIds.Contains(o.IdCategory));
+
+ var filteredWellOperations = FilterByRequest(wellOperationsWithTypeDto, request);
+
+ count += filteredWellOperations.Count();
+
+ if (request.Skip != null)
+ filteredWellOperations = filteredWellOperations.Skip((int)request.Skip);
+ if (request.Take != null)
+ filteredWellOperations = filteredWellOperations.Take((int)request.Take);
+
+ var timezoneOffset = wellService.GetTimezone(wellOperationsWithTypeDto.Key.IdWell).Offset;
+
+ var dtos = filteredWellOperations
+ .Select(dto =>
+ {
+ var newDto = dto.Adapt();
+ newDto.Day = (dto.DateStart - firstWellOperation.DateStart).TotalDays;
+ newDto.NptHours = operationsWithNpt
+ .Where(o => o.DateStart <= dto.DateStart)
+ .Sum(e => e.DurationHours);
+ return newDto;
+ });
+
+ result.AddRange(dtos);
+ }
+
+ return (result, count);
+ }
+
+ public static IEnumerable FilterByRequest(IEnumerable dtos, WellOperationRequest request)
+ {
+ if (request.OperationType.HasValue)
+ dtos = dtos.Where(e => e.IdType == request.OperationType.Value);
+ if (request.SectionTypeIds?.Any() is true)
+ dtos = dtos.Where(e => request.SectionTypeIds.Contains(e.IdWellSectionType));
+ if (request.OperationCategoryIds?.Any() is true)
+ dtos = dtos.Where(e => request.OperationCategoryIds.Contains(e.IdCategory));
+ if (request.GeDepth.HasValue)
+ dtos = dtos.Where(e => e.DepthEnd >= request.GeDepth.Value);
+ if (request.LeDepth.HasValue)
+ dtos = dtos.Where(e => e.DepthEnd <= request.LeDepth.Value);
+
+ if (request.GeDate.HasValue)
+ {
+ var geDateUtc = request.GeDate.Value.UtcDateTime;
+ dtos = dtos.Where(e => e.DateStart >= geDateUtc);
+ }
+
+ if (request.LeDate.HasValue)
+ {
+ var leDateUtc = request.LeDate.Value.UtcDateTime;
+ dtos = dtos.Where(e => e.DateStart <= leDateUtc);
+ }
+ if (request.SortFields?.Any() is true)
+ dtos = dtos.AsQueryable().SortBy(request.SortFields);
+ else
+ dtos = dtos.AsQueryable().OrderBy(e => e.DateStart);
+
+ return dtos;
+ }
+}
diff --git a/AsbCloudInfrastructure/Services/WellOperations/Factories/WellOperationExportServiceFactory.cs b/AsbCloudInfrastructure/Services/WellOperations/Factories/WellOperationExportServiceFactory.cs
index 40768e86..6872aa96 100644
--- a/AsbCloudInfrastructure/Services/WellOperations/Factories/WellOperationExportServiceFactory.cs
+++ b/AsbCloudInfrastructure/Services/WellOperations/Factories/WellOperationExportServiceFactory.cs
@@ -16,18 +16,18 @@ public class WellOperationExportServiceFactory : IExportServiceFactory
public WellOperationExportServiceFactory(IServiceProvider serviceProvider)
{
- var wellOperationRepository = serviceProvider.GetRequiredService();
+ var wellOperationService = serviceProvider.GetRequiredService();
var wellService = serviceProvider.GetRequiredService();
exportServices = new Dictionary>
{
{
WellOperation.IdOperationTypeFact,
- () => new WellOperationExport(wellOperationRepository, wellService)
+ () => new WellOperationExport(wellOperationService, wellService)
},
{
WellOperation.IdOperationTypePlan,
- () => new WellOperationExport(wellOperationRepository, wellService)
+ () => new WellOperationExport(wellOperationService, wellService)
}
};
}
diff --git a/AsbCloudInfrastructure/Services/WellOperations/WellOperationExport.cs b/AsbCloudInfrastructure/Services/WellOperations/WellOperationExport.cs
index cdb58cc6..f17ed63e 100644
--- a/AsbCloudInfrastructure/Services/WellOperations/WellOperationExport.cs
+++ b/AsbCloudInfrastructure/Services/WellOperations/WellOperationExport.cs
@@ -1,50 +1,50 @@
-using System;
-using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
using AsbCloudApp.Data.WellOperation;
-using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Requests.ExportOptions;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.ExcelServices;
using AsbCloudInfrastructure.Services.ExcelServices.Templates;
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services.WellOperations;
public class WellOperationExport : ExcelExportService
where TTemplate : class, ITemplateParameters, new()
{
- private readonly IWellService wellService;
- private readonly IWellOperationRepository wellOperationRepository;
+ private readonly IWellService wellService;
+ private readonly IWellOperationService wellOperationService;
- public WellOperationExport(IWellOperationRepository wellOperationRepository,
- IWellService wellService)
- {
- this.wellOperationRepository = wellOperationRepository;
- this.wellService = wellService;
- }
+ public WellOperationExport(
+ IWellOperationService wellOperationService,
+ IWellService wellService)
+ {
+ this.wellService = wellService;
+ this.wellOperationService = wellOperationService;
+ }
- protected override async Task BuildFileNameAsync(WellOperationExportRequest options, CancellationToken token)
- {
- var caption = await wellService.GetWellCaptionByIdAsync(options.IdWell, token);
+ protected override async Task BuildFileNameAsync(WellOperationExportRequest options, CancellationToken token)
+ {
+ var caption = await wellService.GetWellCaptionByIdAsync(options.IdWell, token);
- return options.IdType switch
- {
- WellOperation.IdOperationTypeFact => $"{caption}_Фактические_операции.xlsx",
- WellOperation.IdOperationTypePlan => $"{caption}_Плановые_операции.xlsx",
- _ => throw new ArgumentOutOfRangeException(nameof(options.IdType))
- };
- }
+ return options.IdType switch
+ {
+ WellOperation.IdOperationTypeFact => $"{caption}_Фактические_операции.xlsx",
+ WellOperation.IdOperationTypePlan => $"{caption}_Плановые_операции.xlsx",
+ _ => throw new ArgumentOutOfRangeException(nameof(options.IdType))
+ };
+ }
- protected override Task> GetDtosAsync(WellOperationExportRequest options, CancellationToken token)
- {
- var request = new WellOperationRequest(new[] { options.IdWell })
- {
- OperationType = options.IdType,
- };
-
- return wellOperationRepository.GetAsync(request, token);
- }
+ protected override Task> GetDtosAsync(WellOperationExportRequest options, CancellationToken token)
+ {
+ var request = new WellOperationRequest(new[] { options.IdWell })
+ {
+ OperationType = options.IdType,
+ };
+
+ return wellOperationService.GetAsync(request, token);
+ }
}
\ No newline at end of file
diff --git a/AsbCloudWebApi.Tests/Services/DailyReportServiceTest.cs b/AsbCloudWebApi.Tests/Services/DailyReportServiceTest.cs
index 90c00957..0bbcb431 100644
--- a/AsbCloudWebApi.Tests/Services/DailyReportServiceTest.cs
+++ b/AsbCloudWebApi.Tests/Services/DailyReportServiceTest.cs
@@ -207,10 +207,11 @@ public class DailyReportServiceTest
private readonly ITrajectoryNnbRepository trajectoryFactNnbRepositoryMock = Substitute.For();
private readonly IDailyReportRepository dailyReportRepositoryMock = Substitute.For();
private readonly IScheduleRepository scheduleRepositoryMock = Substitute.For();
- private readonly IWellOperationRepository wellOperationRepositoryMock = Substitute.For();
private readonly ISubsystemService subsystemServiceMock = Substitute.For();
private readonly IProcessMapReportDrillingService processMapReportWellDrillingServiceMock = Substitute.For();
private readonly IDetectedOperationService detectedOperationServiceMock = Substitute.For();
+ private readonly IWellOperationService wellOperationServiceMock = Substitute.For();
+ private readonly IWellOperationRepository wellOperationRepositoryMock = Substitute.For();
private readonly DailyReportService dailyReportService;
@@ -252,7 +253,8 @@ public class DailyReportServiceTest
wellOperationRepositoryMock,
subsystemServiceMock,
processMapReportWellDrillingServiceMock,
- detectedOperationServiceMock);
+ detectedOperationServiceMock,
+ wellOperationServiceMock);
dailyReportRepositoryMock.InsertAsync(Arg.Any(), Arg.Any())
.ReturnsForAnyArgs(idDailyReport);
@@ -269,7 +271,7 @@ public class DailyReportServiceTest
trajectoryFactNnbRepositoryMock.GetByRequestAsync(Arg.Any(), Arg.Any())
.ReturnsForAnyArgs(new[] { fakeLastFactTrajectory });
- wellOperationRepositoryMock.GetAsync(Arg.Any(), Arg.Any())
+ wellOperationServiceMock.GetAsync(Arg.Any(), Arg.Any())
.ReturnsForAnyArgs(new[] { fakeFirstFactWellOperation, fakeLastFactWellOperation });
wellOperationRepositoryMock.GetDatesRangeAsync(Arg.Any(), Arg.Any(), Arg.Any())
diff --git a/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs b/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs
index b5ac6d1f..b8bf0791 100644
--- a/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs
+++ b/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs
@@ -22,8 +22,8 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation
= Substitute.For>();
private IWellOperationCategoryRepository wellOperationCategoryRepository
= Substitute.For();
- private IWellOperationRepository wellOperationRepository
- = Substitute.For();
+ private IWellOperationService wellOperationService
+ = Substitute.For();
private IWellService wellService
= Substitute.For();
private List idsWells;
@@ -175,7 +175,6 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation
service = new WellCompositeOperationService(
wellSectionTypeRepository,
wellOperationCategoryRepository,
- wellOperationRepository,
wellService);
}
@@ -189,7 +188,7 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation
public async Task GetAsync_return_composite_and_others_with_category_5013()
{
// arrange
- wellOperationRepository.GetAsync(Arg.Any(), Arg.Any())
+ wellOperationService.GetAsync(Arg.Any(), Arg.Any())
.Returns(wellOperations1);
// act
@@ -216,7 +215,7 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation
public async Task GetAsync_return_composite_with_minimum_depth_start()
{
// arrange
- wellOperationRepository.GetAsync(Arg.Any(), Arg.Any())
+ wellOperationService.GetAsync(Arg.Any(), Arg.Any())
.Returns(wellOperations2);
// act
@@ -240,7 +239,7 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation
public async Task GetAsync_return_data3()
{
// arrange
- wellOperationRepository.GetAsync(Arg.Any(), Arg.Any())
+ wellOperationService.GetAsync(Arg.Any(), Arg.Any())
.Returns(wellOperations3);
// act
@@ -266,7 +265,7 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation
public async Task GetAsync_return_data4()
{
// arrange
- wellOperationRepository.GetAsync(Arg.Any(), Arg.Any())
+ wellOperationService.GetAsync(Arg.Any(), Arg.Any())
.Returns(wellOperations4);
// act
@@ -296,7 +295,7 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation
wellOperations.AddRange(wellOperations3);
wellOperations.AddRange(wellOperations4);
- wellOperationRepository.GetAsync(Arg.Any(), Arg.Any())
+ wellOperationService.GetAsync(Arg.Any(), Arg.Any())
.Returns(wellOperations);
// act
diff --git a/AsbCloudWebApi/Controllers/WellOperationController.cs b/AsbCloudWebApi/Controllers/WellOperationController.cs
index 90b7404f..6bb4fe28 100644
--- a/AsbCloudWebApi/Controllers/WellOperationController.cs
+++ b/AsbCloudWebApi/Controllers/WellOperationController.cs
@@ -38,6 +38,7 @@ public class WellOperationController : ControllerBase
private readonly IWellOperationRepository wellOperationRepository;
private readonly IWellOperationCategoryRepository wellOperationCategoryRepository;
private readonly IWellService wellService;
+ private readonly IWellOperationService wellOperationService;
private readonly WellOperationParserFactory wellOperationParserFactory;
private readonly WellOperationExportServiceFactory wellOperationExportServiceFactory;
@@ -47,7 +48,8 @@ public class WellOperationController : ControllerBase
IWellService wellService,
IUserRepository userRepository,
WellOperationParserFactory wellOperationParserFactory,
- WellOperationExportServiceFactory wellOperationExportServiceFactory)
+ WellOperationExportServiceFactory wellOperationExportServiceFactory,
+ IWellOperationService wellOperationService)
{
this.wellOperationRepository = wellOperationRepository;
this.wellOperationCategoryRepository = wellOperationCategoryRepository;
@@ -55,6 +57,7 @@ public class WellOperationController : ControllerBase
this.userRepository = userRepository;
this.wellOperationParserFactory = wellOperationParserFactory;
this.wellOperationExportServiceFactory = wellOperationExportServiceFactory;
+ this.wellOperationService = wellOperationService;
}
///
@@ -159,7 +162,7 @@ public class WellOperationController : ControllerBase
var requestToservice = new WellOperationRequest(request, new[] { idWell });
- var result = await wellOperationRepository.GetGroupOperationsStatAsync(requestToservice, token);
+ var result = await wellOperationService.GetGroupOperationsStatAsync(requestToservice, token);
return Ok(result);
}
@@ -197,7 +200,7 @@ public class WellOperationController : ControllerBase
var requestToService = new WellOperationRequest(request, new[] { idWell });
- var result = await wellOperationRepository.GetPageAsync(requestToService, token);
+ var result = await wellOperationService.GetPageAsync(requestToService, token);
return Ok(result);
}
@@ -224,7 +227,7 @@ public class WellOperationController : ControllerBase
if (!await CanUserAccessToWellAsync(idWell, token))
return Forbid();
- var paginationContainer = await wellOperationRepository.GetPageAsync(idWell, id, operationType, take, sortFields, token);
+ var paginationContainer = await wellOperationService.GetPageAsync(idWell, id, operationType, take, sortFields, token);
if (paginationContainer == null)
return NoContent();