using AsbCloudApp.Data; using AsbCloudApp.Services; using AsbCloudDb.Model; using AsbCloudInfrastructure.Services.Cache; 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 { public class WellOperationService : IWellOperationService { private readonly IAsbCloudDbContext db; private readonly IWellService wellService; private readonly CacheTable cachedOperationCategories; private readonly CacheTable cachedSectionTypes; public const int idOperationBhaAssembly = 1025; public const int idOperationBhaDisassembly = 1026; public const int idOperationNonProductiveTime = 1043; public const int idOperationDrilling = 1001; public const int idOperationBhaDown = 1046; public const int idOperationBhaUp = 1047; public const int idOperationCasingDown = 1048; public const int idOperationTypePlan = 0; public const int idOperationTypeFact = 1; public WellOperationService(IAsbCloudDbContext db, CacheDb cache, IWellService wellService) { this.db = db; this.wellService = wellService; cachedOperationCategories = cache.GetCachedTable((DbContext)db); cachedSectionTypes = cache.GetCachedTable((DbContext)db); } public IDictionary GetSectionTypes() => cachedSectionTypes.ToDictionary(s => s.Id, s => s.Caption); public IEnumerable GetCategories() { var operationTypes = cachedOperationCategories .Distinct().OrderBy(o => o.Name); var result = operationTypes.Adapt(); return result; } public async Task> GetOperationsAsync( int idWell, int? operationType = default, IEnumerable sectionTypeIds = default, IEnumerable operationCategoryIds = default, DateTime begin = default, DateTime end = default, double minDepth = double.MinValue, double maxDepth = double.MaxValue, int skip = 0, int take = 32, CancellationToken token = default) { var timezone = wellService.GetTimezone(idWell); var query = db.WellOperations .Include(s => s.WellSectionType) .Include(s => s.OperationCategory) .Where(s => s.IdWell == idWell); var dateStart = query.Min(o => o.DateStart); if (operationType != default) query = query.Where(e => e.IdType == (int)operationType); if (sectionTypeIds != default && sectionTypeIds.Any()) query = query.Where(e => sectionTypeIds.Contains(e.IdWellSectionType)); if (operationCategoryIds != default && operationCategoryIds.Any()) query = query.Where(e => operationCategoryIds.Contains(e.IdCategory)); if (minDepth != double.MinValue) query = query.Where(e => e.DepthEnd >= minDepth); if (maxDepth != double.MaxValue) query = query.Where(e => e.DepthEnd <= maxDepth); if (begin != default) { var beginOffset = begin.ToUtcDateTimeOffset(timezone.Hours); query = query.Where(e => e.DateStart >= beginOffset); } if (end != default) { var endOffset = end.ToUtcDateTimeOffset(timezone.Hours); query = query.Where(e => e.DateStart <= endOffset); } var result = new PaginationContainer { Skip = skip, Take = take, Count = await query.CountAsync(token).ConfigureAwait(false), }; query = query .OrderBy(e => e.DateStart) .ThenBy(e => e.DepthEnd) .ThenBy(e => e.Id); if (skip > 0) query = query.Skip(skip); var entities = await query.Take(take).AsNoTracking() .ToListAsync(token).ConfigureAwait(false); var nptHours = 0d; 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(entity.IdCategory == idOperationNonProductiveTime) nptHours += entity.DurationHours; dto.NptHours = nptHours; } result.Items.Add(dto); } return result; } public async Task GetAsync(int id, CancellationToken token = default) { 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(int idWell, IEnumerable wellOperationDtos, CancellationToken token = default) { 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(int idWell, int idOperation, WellOperationDto dto, CancellationToken token = default) { var timezone = wellService.GetTimezone(idWell); var entity = dto.Adapt(); entity.Id = idOperation; 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 = default) { var query = db.WellOperations.Where(e => ids.Contains(e.Id)); db.WellOperations.RemoveRange(query); return await db.SaveChangesAsync(token) .ConfigureAwait(false); } } }