diff --git a/AsbCloudApp/Data/SectionByOperationsDto.cs b/AsbCloudApp/Data/SectionByOperationsDto.cs
new file mode 100644
index 00000000..80d2a3b4
--- /dev/null
+++ b/AsbCloudApp/Data/SectionByOperationsDto.cs
@@ -0,0 +1,47 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace AsbCloudApp.Data;
+
+///
+/// Параметры секции определяемые по операциям из ГГД
+///
+public class SectionByOperationsDto
+{
+ ///
+ /// Id скважины
+ ///
+ public int IdWell { get; set; }
+
+ ///
+ /// 0 = план или 1 = факт или прогноз = 2
+ ///
+ public int IdType { get; set; }
+
+ ///
+ /// id секции скважины
+ ///
+ public int IdWellSectionType { get; set; }
+
+ ///
+ /// Глубина начала первой операции в секции, м
+ ///
+ [Range(0, 50_000)]
+ public double DepthStart { get; set; }
+
+ ///
+ /// Дата начала первой операции в секции
+ ///
+ public DateTimeOffset DateStart { get; set; }
+
+ ///
+ /// Глубина после завершения последней операции операции в секции, м
+ ///
+ [Range(0, 50_000)]
+ public double DepthEnd { get; set; }
+
+ ///
+ /// Дата после завершения последней операции операции в секции
+ ///
+ public DateTimeOffset DateEnd { get; set; }
+}
diff --git a/AsbCloudApp/Repositories/IWellOperationRepository.cs b/AsbCloudApp/Repositories/IWellOperationRepository.cs
index b02d3e42..faab324f 100644
--- a/AsbCloudApp/Repositories/IWellOperationRepository.cs
+++ b/AsbCloudApp/Repositories/IWellOperationRepository.cs
@@ -97,5 +97,13 @@ namespace AsbCloudApp.Repositories
///
///
Task DeleteAsync(IEnumerable ids, CancellationToken token);
+
+ ///
+ /// Получить секции скважин из операций ГГД. Секцие поделены на плановые и фактические.
+ ///
+ ///
+ ///
+ ///
+ Task> GetSectionsAsync(IEnumerable idsWells, CancellationToken token);
}
}
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/Background/todo.md b/AsbCloudInfrastructure/Background/todo.md
new file mode 100644
index 00000000..f30ce6c4
--- /dev/null
+++ b/AsbCloudInfrastructure/Background/todo.md
@@ -0,0 +1,5 @@
+#
+-
+- . .
+ - /
+ - /
diff --git a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs
index f0eb5f6d..cd913980 100644
--- a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs
+++ b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs
@@ -13,394 +13,452 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-namespace AsbCloudInfrastructure.Repository
+namespace AsbCloudInfrastructure.Repository;
+
+
+///
+/// репозиторий операций по скважине
+///
+public class WellOperationRepository : IWellOperationRepository
{
+ private const string KeyCacheSections = "OperationsBySectionSummarties";
+ private readonly IAsbCloudDbContext db;
+ private readonly IMemoryCache memoryCache;
+ private readonly IWellService wellService;
- ///
- /// репозиторий операций по скважине
- ///
- public class WellOperationRepository : IWellOperationRepository
+ public WellOperationRepository(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService)
{
- private readonly IAsbCloudDbContext db;
- private readonly IMemoryCache memoryCache;
- private readonly IWellService wellService;
- private static Dictionary? firstOperationsCache = null;
-
- public WellOperationRepository(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService)
- {
- this.db = db;
- this.memoryCache = memoryCache;
- this.wellService = wellService;
- }
-
- ///
- public IEnumerable GetCategories(bool includeParents)
- {
- var categories = memoryCache
- .GetOrCreateBasic(db.Set());
-
- if (!includeParents)
- {
- var parentIds = categories
- .Select(o => o.IdParent)
- .Distinct();
-
- categories = categories
- .Where(o => !parentIds.Contains(o.Id));
- }
-
- var result = categories
- .OrderBy(o => o.Name)
- .Adapt>();
-
- return result;
- }
-
- ///
- public IEnumerable GetSectionTypes() =>
- memoryCache
- .GetOrCreateBasic(db.Set())
- .OrderBy(s => s.Order)
- .Select(s => s.Adapt());
-
-
-
- public async Task GetOperationsPlanAsync(int idWell, DateTime? currentDate, CancellationToken token)
- {
- var timezone = wellService.GetTimezone(idWell);
- var request = new WellOperationRequest()
- {
- IdWell = idWell,
- OperationType = WellOperation.IdOperationTypePlan,
- };
-
- var entities = await BuildQuery(request)
- .AsNoTracking()
- .ToArrayAsync(token)
- .ConfigureAwait(false);
-
- var dateLastAssosiatedPlanOperation = await GetDateLastAssosiatedPlanOperationAsync(idWell, currentDate, timezone.Hours, token);
-
- var result = new WellOperationPlanDto()
- {
- WellOperationsPlan = entities,
- DateLastAssosiatedPlanOperation = dateLastAssosiatedPlanOperation
- };
-
- return result;
- }
-
- private async Task GetDateLastAssosiatedPlanOperationAsync(
- int idWell,
- DateTime? lessThenDate,
- double timeZoneHours,
- CancellationToken token)
- {
- if (lessThenDate is null)
- return null;
-
- var currentDateOffset = lessThenDate.Value.ToUtcDateTimeOffset(timeZoneHours);
- var timeZoneOffset = TimeSpan.FromHours(timeZoneHours);
-
- var lastFactOperation = await db.WellOperations
- .Where(o => o.IdWell == idWell)
- .Where(o => o.IdType == WellOperation.IdOperationTypeFact)
- .Where(o => o.IdPlan != null)
- .Where(o => o.DateStart < currentDateOffset)
- .Include(x => x.OperationPlan)
- .OrderByDescending(x => x.DateStart)
- .FirstOrDefaultAsync(token)
- .ConfigureAwait(false);
-
- if (lastFactOperation is not null)
- return DateTime.SpecifyKind(lastFactOperation.OperationPlan.DateStart.UtcDateTime + timeZoneOffset, DateTimeKind.Unspecified);
- return null;
- }
-
- ///
- 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 == WellOperation.IdOperationTypePlan).Min(o => o.DateStart),
- g.Where(o => o.IdType == WellOperation.IdOperationTypeFact).Min(o => o.DateStart)
- ));
-
- firstOperationsCache = query
- .ToDictionary(f => f.Item1, f => f.Item3 ?? f.Item2);
- }
-
- return firstOperationsCache?.GetValueOrDefault(idWell);
- }
-
- ///
- public async Task> GetAsync(
- WellOperationRequest request,
- CancellationToken token)
- {
- var query = BuildQuery(request)
- .AsNoTracking();
- var result = await query.ToArrayAsync(token);
- return result;
- }
-
- ///
- public async Task> GetPageAsync(
- WellOperationRequest request,
- CancellationToken token)
- {
- var query = BuildQuery(request)
- .AsNoTracking();
-
- var result = new PaginationContainer
- {
- Skip = request.Skip ?? 0,
- Take = request.Take ?? 32,
- Count = await query.CountAsync(token).ConfigureAwait(false),
- };
-
- query = query
- .Skip(result.Skip)
- .Take(result.Take);
-
- result.Items = await query.ToArrayAsync(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)
- {
- // TODO: Rename controller method
- request.OperationType = WellOperation.IdOperationTypeFact;
- var query = BuildQuery(request);
- var entities = await query
- .Select(o => new
- {
- o.IdCategory,
- DurationMinutes = o.DurationHours * 60,
- DurationDepth = o.DepthEnd - o.DepthStart
- })
- .ToListAsync(token);
- var parentRelationDictionary = GetCategories(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 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 timeZoneOffset = TimeSpan.FromHours(timezone.Hours);
-
- var query = db.WellOperations
- .Include(s => s.WellSectionType)
- .Include(s => s.OperationCategory)
- .Where(o => o.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.LtDate.HasValue)
- {
- var ltDateOffset = request.LtDate.Value.ToUtcDateTimeOffset(timezone.Hours);
- query = query.Where(e => e.DateStart < ltDateOffset);
- }
-
- var currentWellOperations = db.WellOperations
- .Where(subOp => subOp.IdWell == request.IdWell);
-
- var wellOperationsWithCategoryNPT = currentWellOperations
- .Where(subOp => subOp.IdType == 1)
- .Where(subOp => WellOperationCategory.NonProductiveTimeSubIds.Contains(subOp.IdCategory));
-
- var result = query.Select(o => new WellOperationDto
- {
- Id = o.Id,
- IdPlan = o.IdPlan,
- IdType = o.IdType,
- IdWell = o.IdWell,
- IdWellSectionType = o.IdWellSectionType,
- IdCategory = o.IdCategory,
- IdParentCategory = o.OperationCategory.IdParent,
-
- CategoryName = o.OperationCategory.Name,
- 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 = wellOperationsWithCategoryNPT
- .Where(subOp => subOp.DateStart <= o.DateStart)
- .Select(subOp => subOp.DurationHours)
- .Sum(),
-
- Day = (o.DateStart - currentWellOperations
- .Where(subOp => subOp.IdType == o.IdType)
- .Where(subOp => subOp.DateStart <= o.DateStart)
- .Min(subOp => subOp.DateStart))
- .TotalDays,
- IdUser = o.IdUser,
- LastUpdateDate = o.LastUpdateDate.ToOffset(TimeSpan.FromHours(timezone.Hours))
- });
-
- if (request.SortFields?.Any() == true)
- {
- result = result.SortBy(request.SortFields);
- }
- else
- {
- result = result
- .OrderBy(e => e.DateStart)
- .ThenBy(e => e.DepthEnd)
- .ThenBy(e => e.Id);
- };
-
- return result;
- }
+ this.db = db;
+ this.memoryCache = memoryCache;
+ this.wellService = wellService;
}
+ ///
+ public IEnumerable GetCategories(bool includeParents)
+ {
+ var categories = memoryCache
+ .GetOrCreateBasic(db.Set());
+
+ if (!includeParents)
+ {
+ var parentIds = categories
+ .Select(o => o.IdParent)
+ .Distinct();
+
+ categories = categories
+ .Where(o => !parentIds.Contains(o.Id));
+ }
+
+ var result = categories
+ .OrderBy(o => o.Name)
+ .Adapt>();
+
+ return result;
+ }
+
+ ///
+ public IEnumerable GetSectionTypes() =>
+ memoryCache
+ .GetOrCreateBasic(db.Set())
+ .OrderBy(s => s.Order)
+ .Select(s => s.Adapt());
+
+ public async Task GetOperationsPlanAsync(int idWell, DateTime? currentDate, CancellationToken token)
+ {
+ var timezone = wellService.GetTimezone(idWell);
+ var request = new WellOperationRequest()
+ {
+ IdWell = idWell,
+ OperationType = WellOperation.IdOperationTypePlan,
+ };
+
+ var entities = await BuildQuery(request)
+ .AsNoTracking()
+ .ToArrayAsync(token)
+ .ConfigureAwait(false);
+
+ var dateLastAssosiatedPlanOperation = await GetDateLastAssosiatedPlanOperationAsync(idWell, currentDate, timezone.Hours, token);
+
+ var result = new WellOperationPlanDto()
+ {
+ WellOperationsPlan = entities,
+ DateLastAssosiatedPlanOperation = dateLastAssosiatedPlanOperation
+ };
+
+ return result;
+ }
+
+ private async Task GetDateLastAssosiatedPlanOperationAsync(
+ int idWell,
+ DateTime? lessThenDate,
+ double timeZoneHours,
+ CancellationToken token)
+ {
+ if (lessThenDate is null)
+ return null;
+
+ var currentDateOffset = lessThenDate.Value.ToUtcDateTimeOffset(timeZoneHours);
+ var timeZoneOffset = TimeSpan.FromHours(timeZoneHours);
+
+ var lastFactOperation = await db.WellOperations
+ .Where(o => o.IdWell == idWell)
+ .Where(o => o.IdType == WellOperation.IdOperationTypeFact)
+ .Where(o => o.IdPlan != null)
+ .Where(o => o.DateStart < currentDateOffset)
+ .Include(x => x.OperationPlan)
+ .OrderByDescending(x => x.DateStart)
+ .FirstOrDefaultAsync(token)
+ .ConfigureAwait(false);
+
+ if (lastFactOperation is not null)
+ return DateTime.SpecifyKind(lastFactOperation.OperationPlan.DateStart.UtcDateTime + timeZoneOffset, DateTimeKind.Unspecified);
+ return null;
+ }
+
+ ///
+ public async Task> GetSectionsAsync(IEnumerable idsWells, CancellationToken token)
+ {
+ var cache = await memoryCache.GetOrCreateAsync(KeyCacheSections, async (entry) =>
+ {
+ entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30);
+
+ var query = db.Set()
+ .GroupBy(operation => new
+ {
+ operation.IdWell,
+ operation.IdType,
+ operation.IdWellSectionType,
+ })
+ .Select(group => new
+ {
+ group.Key.IdWell,
+ group.Key.IdType,
+ group.Key.IdWellSectionType,
+
+ First = group
+ .OrderBy(operation => operation.DateStart)
+ .Select(operation => new
+ {
+ operation.DateStart,
+ operation.DepthStart,
+ })
+ .First(),
+
+ Last = group
+ .OrderByDescending(operation => operation.DateStart)
+ .Select(operation => new
+ {
+ operation.DateStart,
+ operation.DurationHours,
+ operation.DepthEnd,
+ })
+ .First(),
+ });
+ var dbData = await query.ToArrayAsync(token);
+ var sections = dbData.Select(
+ item => new SectionByOperationsDto
+ {
+ IdWell = item.IdWell,
+ IdType = item.IdType,
+ IdWellSectionType = item.IdWellSectionType,
+
+ DateStart = item.First.DateStart,
+ DepthStart = item.First.DepthStart,
+
+ DateEnd = item.Last.DateStart.AddHours(item.Last.DurationHours),
+ DepthEnd = item.Last.DepthEnd,
+ })
+ .ToArray()
+ .AsEnumerable();
+
+ entry.Value = sections;
+ return sections;
+ });
+
+ var sections = cache.Where(s => idsWells.Contains(s.IdWell));
+ return sections;
+ }
+
+ ///
+ public DateTimeOffset? FirstOperationDate(int idWell)
+ {
+ var sections = GetSectionsAsync(new[] { idWell }, CancellationToken.None).Result;
+ var first = sections.FirstOrDefault(section => section.IdType == WellOperation.IdOperationTypeFact)
+ ?? sections.FirstOrDefault(section => section.IdType == WellOperation.IdOperationTypePlan);
+
+ return first?.DateStart;
+ }
+
+ ///
+ public async Task> GetAsync(
+ WellOperationRequest request,
+ CancellationToken token)
+ {
+ var query = BuildQuery(request)
+ .AsNoTracking();
+ var result = await query.ToArrayAsync(token);
+ return result;
+ }
+
+ ///
+ public async Task> GetPageAsync(
+ WellOperationRequest request,
+ CancellationToken token)
+ {
+ var query = BuildQuery(request)
+ .AsNoTracking();
+
+ var result = new PaginationContainer
+ {
+ Skip = request.Skip ?? 0,
+ Take = request.Take ?? 32,
+ Count = await query.CountAsync(token).ConfigureAwait(false),
+ };
+
+ query = query
+ .Skip(result.Skip)
+ .Take(result.Take);
+
+ result.Items = await query.ToArrayAsync(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)
+ {
+ // TODO: Rename controller method
+ request.OperationType = WellOperation.IdOperationTypeFact;
+ var query = BuildQuery(request);
+ var entities = await query
+ .Select(o => new
+ {
+ o.IdCategory,
+ DurationMinutes = o.DurationHours * 60,
+ DurationDepth = o.DepthEnd - o.DepthStart
+ })
+ .ToListAsync(token);
+ var parentRelationDictionary = GetCategories(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 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);
+ }
+
+ var result = await db.SaveChangesAsync(token);
+ if (result > 0)
+ memoryCache.Remove(KeyCacheSections);
+ return result;
+
+ }
+
+ ///
+ 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);
+
+ var result = await db.SaveChangesAsync(token);
+ if (result > 0)
+ memoryCache.Remove(KeyCacheSections);
+ return result;
+ }
+
+ ///
+ public async Task DeleteAsync(IEnumerable ids,
+ CancellationToken token)
+ {
+ var query = db.WellOperations.Where(e => ids.Contains(e.Id));
+ db.WellOperations.RemoveRange(query);
+
+ var result = await db.SaveChangesAsync(token);
+ if (result > 0)
+ memoryCache.Remove(KeyCacheSections);
+ return result;
+ }
+
+ ///
+ /// В результате попрежнему требуется конвертировать дату
+ ///
+ ///
+ ///
+ 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(o => o.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.LtDate.HasValue)
+ {
+ var ltDateOffset = request.LtDate.Value.ToUtcDateTimeOffset(timezone.Hours);
+ query = query.Where(e => e.DateStart < ltDateOffset);
+ }
+
+ var currentWellOperations = db.WellOperations
+ .Where(subOp => subOp.IdWell == request.IdWell);
+
+ var wellOperationsWithCategoryNPT = currentWellOperations
+ .Where(subOp => subOp.IdType == 1)
+ .Where(subOp => WellOperationCategory.NonProductiveTimeSubIds.Contains(subOp.IdCategory));
+
+ var result = query.Select(o => new WellOperationDto
+ {
+ Id = o.Id,
+ IdPlan = o.IdPlan,
+ IdType = o.IdType,
+ IdWell = o.IdWell,
+ IdWellSectionType = o.IdWellSectionType,
+ IdCategory = o.IdCategory,
+ IdParentCategory = o.OperationCategory.IdParent,
+
+ CategoryName = o.OperationCategory.Name,
+ 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 = wellOperationsWithCategoryNPT
+ .Where(subOp => subOp.DateStart <= o.DateStart)
+ .Select(subOp => subOp.DurationHours)
+ .Sum(),
+
+ Day = (o.DateStart - currentWellOperations
+ .Where(subOp => subOp.IdType == o.IdType)
+ .Where(subOp => subOp.DateStart <= o.DateStart)
+ .Min(subOp => subOp.DateStart))
+ .TotalDays,
+ IdUser = o.IdUser,
+ LastUpdateDate = o.LastUpdateDate.ToOffset(TimeSpan.FromHours(timezone.Hours))
+ });
+
+ if (request.SortFields?.Any() == true)
+ {
+ result = result.SortBy(request.SortFields);
+ }
+ else
+ {
+ result = result
+ .OrderBy(e => e.DateStart)
+ .ThenBy(e => e.DepthEnd)
+ .ThenBy(e => e.Id);
+ };
+
+ return result;
+ }
}
diff --git a/AsbCloudInfrastructure/Services/WellboreService.cs b/AsbCloudInfrastructure/Services/WellboreService.cs
index 5e0e439e..396243d6 100644
--- a/AsbCloudInfrastructure/Services/WellboreService.cs
+++ b/AsbCloudInfrastructure/Services/WellboreService.cs
@@ -35,7 +35,7 @@ public class WellboreService : IWellboreService
}
public async Task> GetWellboresAsync(WellboreRequest request,
- CancellationToken cancellationToken)
+ CancellationToken token)
{
var wellbores = new List(request.Ids.Count());
var skip = request.Skip ?? 0;
@@ -44,26 +44,43 @@ public class WellboreService : IWellboreService
var sections = wellOperationRepository.GetSectionTypes()
.ToDictionary(w => w.Id, w => w);
- var ids = request.Ids.GroupBy(i => i.idWell);
+ var ids = request.Ids.GroupBy(i => i.idWell, i => i.idSection);
+
+ var idsWells = request.Ids.Select(i => i.idWell);
+
+ var allSections = await wellOperationRepository.GetSectionsAsync(idsWells, token);
foreach (var id in ids)
{
- var well = await wellService.GetOrDefaultAsync(id.Key, cancellationToken);
+ var well = await wellService.GetOrDefaultAsync(id.Key, token);
if (well is null)
continue;
- var wellOperations = await GetFactOperationsAsync(well.Id, id.Select(i => i.idSection), cancellationToken);
- var groupedOperations = wellOperations.GroupBy(o => o.IdWellSectionType);
- var wellWellbores = groupedOperations.Select(group => new WellboreDto {
- Id = group.Key,
- Name = sections[group.Key].Caption,
+ var wellTimezoneOffset = TimeSpan.FromHours(well.Timezone.Hours);
+
+ var wellFactSections = allSections
+ .Where(section => section.IdWell == id.Key)
+ .Where(section => section.IdType == WellOperation.IdOperationTypeFact);
+
+ var idsSections = id
+ .Where(i => i.HasValue)
+ .Select(i => i!.Value);
+
+ if (idsSections.Any())
+ wellFactSections = wellFactSections
+ .Where(section => idsSections.Contains(section.IdWellSectionType));
+
+ var wellWellbores = wellFactSections.Select(section => new WellboreDto {
+ Id = section.IdWellSectionType,
+ Name = sections[section.IdWellSectionType].Caption,
Well = well.Adapt(),
- DateStart = group.Min(operation => operation.DateStart).ToUtcDateTimeOffset(well.Timezone.Hours).ToOffset(TimeSpan.FromHours(well.Timezone.Hours)),
- DateEnd = group.Max(operation => operation.DateStart.AddHours(operation.DurationHours)).ToUtcDateTimeOffset(well.Timezone.Hours).ToOffset(TimeSpan.FromHours(well.Timezone.Hours)),
- DepthStart = group.Min(operation => operation.DepthStart),
- DepthEnd = group.Max(operation => operation.DepthEnd),
+ DateStart = section.DateStart.ToOffset(wellTimezoneOffset),
+ DateEnd = section.DateEnd.ToOffset(wellTimezoneOffset),
+ DepthStart = section.DepthStart,
+ DepthEnd = section.DepthEnd,
});
+
wellbores.AddRange(wellWellbores);
}
@@ -71,22 +88,4 @@ public class WellboreService : IWellboreService
.OrderBy(w => w.Well.Id).ThenBy(w => w.Id)
.Skip(skip).Take(take);
}
-
- private async Task> GetFactOperationsAsync(int idWell, IEnumerable idsSections,
- CancellationToken cancellationToken)
- {
- var request = new WellOperationRequest
- {
- IdWell = idWell,
- OperationType = WellOperation.IdOperationTypeFact,
- SortFields = new[] { "DateStart asc" },
- };
-
- request.SectionTypeIds = idsSections.All(i => i.HasValue)
- ? idsSections.Select(i => i!.Value)
- : null;
-
- return (await wellOperationRepository.GetAsync(request, cancellationToken))
- .OrderBy(o => o.DateStart);
- }
}
\ No newline at end of file