diff --git a/AsbCloudInfrastructure/Services/WellOperationService/WellOperationRepository.cs b/AsbCloudInfrastructure/Services/WellOperationService/WellOperationRepository.cs new file mode 100644 index 00000000..6251bae9 --- /dev/null +++ b/AsbCloudInfrastructure/Services/WellOperationService/WellOperationRepository.cs @@ -0,0 +1,242 @@ +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 +}