WellOperationService to WellOperationRepository

This commit is contained in:
ngfrolov 2022-12-28 17:38:53 +05:00
parent fb4bb375e1
commit 7585aefc4e
12 changed files with 219 additions and 462 deletions

View File

@ -5,13 +5,13 @@ using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AsbCloudApp.Services namespace AsbCloudApp.Repositories
{ {
#nullable enable #nullable enable
/// <summary> /// <summary>
/// сервис операций по скважине /// сервис операций по скважине
/// </summary> /// </summary>
public interface IWellOperationService public interface IWellOperationRepository
{ {
/// <summary> /// <summary>
/// список названий операций /// список названий операций
@ -19,61 +19,6 @@ namespace AsbCloudApp.Services
/// <returns></returns> /// <returns></returns>
IEnumerable<WellOperationCategoryDto> GetCategories(); IEnumerable<WellOperationCategoryDto> GetCategories();
// TODO: объединить параметры в объект запроса
/// <summary>
/// Получить список операций
/// </summary>
/// <param name="request"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<PaginationContainer<WellOperationDto>> GetOperationsAsync(
WellOperationRequest request,
CancellationToken token);
/// <summary>
/// Получить статистику операции по скважине с группировкой по категориям
/// </summary>
/// <param name="request"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<WellGroupOpertionDto>> GetGroupOperationsStatAsync(
WellOperationRequest request,
CancellationToken token);
/// <summary>
/// Получить операцию по id
/// </summary>
/// <param name="id"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<WellOperationDto?> GetOrDefaultAsync(int id, CancellationToken token);
/// <summary>
/// Добавить несколько операций за один раз
/// </summary>
/// <param name="wellOperationDtos"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> InsertRangeAsync(
IEnumerable<WellOperationDto> wellOperationDtos, CancellationToken token);
/// <summary>
/// Обновить существующую операцию
/// </summary>
/// <param name="item"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> UpdateAsync(WellOperationDto item,
CancellationToken token);
/// <summary>
/// Удалить операции по id
/// </summary>
/// <param name="ids"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> DeleteAsync(IEnumerable<int> ids, CancellationToken token);
/// <summary> /// <summary>
/// Список секций /// Список секций
/// </summary> /// </summary>
@ -88,12 +33,62 @@ namespace AsbCloudApp.Services
DateTimeOffset? FirstOperationDate(int idWell); DateTimeOffset? FirstOperationDate(int idWell);
/// <summary> /// <summary>
/// Получение операций по идентификатору скважины /// Получить страницу списка операций
/// </summary> /// </summary>
/// <param name="idWell"></param> /// <param name="request"></param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<IEnumerable<WellOperationDto>> GetOperationsByIdWellAsync(int idWell, CancellationToken token); Task<IEnumerable<WellOperationDto>> GetAsync(WellOperationRequest request, CancellationToken token);
/// <summary>
/// Получить страницу списка операций
/// </summary>
/// <param name="request"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<PaginationContainer<WellOperationDto>> GetPageAsync(WellOperationRequest request, CancellationToken token);
/// <summary>
/// Получить операцию по id
/// </summary>
/// <param name="id"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<WellOperationDto?> GetOrDefaultAsync(int id, CancellationToken token);
/// <summary>
/// Получить статистику операции по скважине с группировкой по категориям
/// </summary>
/// <param name="request"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<WellGroupOpertionDto>> GetGroupOperationsStatAsync(
WellOperationRequest request,
CancellationToken token);
/// <summary>
/// Добавить несколько операций за один раз
/// </summary>
/// <param name="wellOperationDtos"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> InsertRangeAsync(IEnumerable<WellOperationDto> wellOperationDtos, CancellationToken token);
/// <summary>
/// Обновить существующую операцию
/// </summary>
/// <param name="dto"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> UpdateAsync(WellOperationDto dto, CancellationToken token);
/// <summary>
/// Удалить операции по id
/// </summary>
/// <param name="ids"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<int> DeleteAsync(IEnumerable<int> ids, CancellationToken token);
} }
#nullable disable #nullable disable
} }

View File

@ -10,6 +10,9 @@ namespace AsbCloudDb.Model
[Table("t_well_operation"), Comment("Данные по операциям на скважине")] [Table("t_well_operation"), Comment("Данные по операциям на скважине")]
public class WellOperation : IId public class WellOperation : IId
{ {
public const int IdOperationTypePlan = 0;
public const int IdOperationTypeFact = 1;
[Key] [Key]
[Column("id")] [Column("id")]
public int Id { get; set; } public int Id { get; set; }
@ -23,6 +26,9 @@ namespace AsbCloudDb.Model
[Column("id_category"), Comment("Id категории операции")] [Column("id_category"), Comment("Id категории операции")]
public int IdCategory { get; set; } public int IdCategory { get; set; }
/// <summary>
/// Тип 0 = План или 1 = Факт
/// </summary>
[Column("id_type"), Comment("0 = План или 1 = Факт")] [Column("id_type"), Comment("0 = План или 1 = Факт")]
public int IdType { get; set; } public int IdType { get; set; }

View File

@ -124,7 +124,7 @@ namespace AsbCloudInfrastructure
services.AddTransient<ITimezoneService, TimezoneService>(); services.AddTransient<ITimezoneService, TimezoneService>();
services.AddTransient<IWellService, WellService>(); services.AddTransient<IWellService, WellService>();
services.AddTransient<IWellOperationImportService, WellOperationImportService>(); services.AddTransient<IWellOperationImportService, WellOperationImportService>();
services.AddTransient<IWellOperationService, WellOperationService>(); services.AddTransient<IWellOperationRepository, WellOperationRepository>();
services.AddTransient<IScheduleReportService, ScheduleReportService>(); services.AddTransient<IScheduleReportService, ScheduleReportService>();
services.AddTransient<IDailyReportService, DailyReportService>(); services.AddTransient<IDailyReportService, DailyReportService>();
services.AddTransient<IDetectedOperationService, DetectedOperationService>(); services.AddTransient<IDetectedOperationService, DetectedOperationService>();

View File

@ -9,35 +9,31 @@ using Microsoft.Extensions.Caching.Memory;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Threading;
using AsbCloudApp.Repositories;
namespace AsbCloudInfrastructure.Services.WellOperationService namespace AsbCloudInfrastructure.Repository
{ {
#nullable enable #nullable enable
public class WellOperationService : IWellOperationService /// <summary>
/// репозиторий операций по скважине
/// </summary>
public class WellOperationRepository : IWellOperationRepository
{ {
private readonly IAsbCloudDbContext db; private readonly IAsbCloudDbContext db;
private readonly IMemoryCache memoryCache; private readonly IMemoryCache memoryCache;
private readonly IWellService wellService; private readonly IWellService wellService;
private static Dictionary<int, DateTimeOffset?>? firstOperationsCache = null;
private Dictionary<int, DateTimeOffset?>? firstOperationsCache = null; public WellOperationRepository(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService)
public const int idOperationTypePlan = 0;
public const int idOperationTypeFact = 1;
public WellOperationService(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService)
{ {
this.db = db; this.db = db;
this.memoryCache = memoryCache; this.memoryCache = memoryCache;
this.wellService = wellService; this.wellService = wellService;
} }
public IDictionary<int, string> GetSectionTypes() /// <inheritdoc/>
=> memoryCache
.GetOrCreateBasic<WellSectionType>(db)
.ToDictionary(s => s.Id, s => s.Caption);
public IEnumerable<WellOperationCategoryDto> GetCategories() public IEnumerable<WellOperationCategoryDto> GetCategories()
{ {
var allCategories = memoryCache var allCategories = memoryCache
@ -56,6 +52,13 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
return result; return result;
} }
/// <inheritdoc/>
public IDictionary<int, string> GetSectionTypes()
=> memoryCache
.GetOrCreateBasic<WellSectionType>(db)
.ToDictionary(s => s.Id, s => s.Caption);
/// <inheritdoc/>
public DateTimeOffset? FirstOperationDate(int idWell) public DateTimeOffset? FirstOperationDate(int idWell)
{ {
if (firstOperationsCache is null) if (firstOperationsCache is null)
@ -65,8 +68,8 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
.Select(g => new Tuple<int, DateTimeOffset?, DateTimeOffset?> .Select(g => new Tuple<int, DateTimeOffset?, DateTimeOffset?>
( (
g.Key, g.Key,
g.Where(o => o.IdType == idOperationTypePlan).Min(o => o.DateStart), g.Where(o => o.IdType == WellOperation.IdOperationTypePlan).Min(o => o.DateStart),
g.Where(o => o.IdType == idOperationTypeFact).Min(o => o.DateStart) g.Where(o => o.IdType == WellOperation.IdOperationTypeFact).Min(o => o.DateStart)
)); ));
firstOperationsCache = query firstOperationsCache = query
@ -76,13 +79,24 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
return firstOperationsCache?.GetValueOrDefault(idWell); return firstOperationsCache?.GetValueOrDefault(idWell);
} }
public async Task<PaginationContainer<WellOperationDto>> GetOperationsAsync( /// <inheritdoc/>
public async Task<IEnumerable<WellOperationDto>> GetAsync(
WellOperationRequest request, WellOperationRequest request,
CancellationToken token) 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); /// <inheritdoc/>
public async Task<PaginationContainer<WellOperationDto>> GetPageAsync(
WellOperationRequest request,
CancellationToken token)
{
var query = BuildQuery(request)
.AsNoTracking();
var result = new PaginationContainer<WellOperationDto> var result = new PaginationContainer<WellOperationDto>
{ {
@ -91,81 +105,45 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
Count = await query.CountAsync(token).ConfigureAwait(false), Count = await query.CountAsync(token).ConfigureAwait(false),
}; };
if (result.Skip > 0) query = query
query = query.Skip(result.Skip!); .Skip(result.Skip)
.Take(result.Take);
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<WellOperationDto>();
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);
}
result.Items = await query.ToListAsync(token);
return result; return result;
} }
public async Task<IEnumerable<WellOperationDto>> GetOperationsByIdWellAsync(int idWell, CancellationToken token) /// <inheritdoc/>
public async Task<WellOperationDto?> GetOrDefaultAsync(int id,
CancellationToken token)
{ {
var timezone = wellService.GetTimezone(idWell); var entity = await db.WellOperations
var query = BuildQuery(idWell); .Include(s => s.WellSectionType)
var dateStart = query.Min(o => o.DateStart); .Include(s => s.OperationCategory)
.FirstOrDefaultAsync(e => e.Id == id, token)
query = query
.OrderBy(e => e.DateStart)
.ThenBy(e => e.DepthEnd)
.ThenBy(e => e.Id);
var entities = await query.AsNoTracking()
.ToListAsync(token)
.ConfigureAwait(false); .ConfigureAwait(false);
var nptHours = 0d; if (entity is null)
var result = new List<WellOperationDto>(); return null;
foreach (var entity in entities) var timezone = wellService.GetTimezone(entity.IdWell);
{
var dto = entity.Adapt<WellOperationDto>();
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.Add(dto);
}
return result; var dto = entity.Adapt<WellOperationDto>();
dto.WellSectionTypeName = entity.WellSectionType.Caption;
dto.DateStart = entity.DateStart.ToRemoteDateTime(timezone.Hours);
dto.CategoryName = entity.OperationCategory.Name;
return dto;
} }
/// <inheritdoc/>
public async Task<IEnumerable<WellGroupOpertionDto>> GetGroupOperationsStatAsync( public async Task<IEnumerable<WellGroupOpertionDto>> GetGroupOperationsStatAsync(
WellOperationRequest request, WellOperationRequest request,
CancellationToken token) CancellationToken token)
{ {
var query = BuildQuery(request); var query = BuildQuery(request);
var entities = await query var entities = await query
.Select(o => new { .Select(o => new
{
o.IdCategory, o.IdCategory,
DurationMinutes = o.DurationHours * 60, DurationMinutes = o.DurationHours * 60,
DurationDepth = o.DepthEnd - o.DepthStart DurationDepth = o.DepthEnd - o.DepthStart
@ -200,7 +178,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
.GroupBy(o => o.IdParent) .GroupBy(o => o.IdParent)
.Select(g => new WellGroupOpertionDto .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", Category = g.Key.HasValue ? parentRelationDictionary[g.Key.Value].Name : "unknown",
Count = g.Sum(o => o.Count), Count = g.Sum(o => o.Count),
DeltaDepth = g.Sum(o => o.DeltaDepth), DeltaDepth = g.Sum(o => o.DeltaDepth),
@ -212,27 +190,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
return dtos; return dtos;
} }
public async Task<WellOperationDto?> GetOrDefaultAsync(int id, /// <inheritdoc/>
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<WellOperationDto>();
dto.WellSectionTypeName = entity.WellSectionType.Caption;
dto.DateStart = entity.DateStart.ToRemoteDateTime(timezone.Hours);
dto.CategoryName = entity.OperationCategory.Name;
return dto;
}
public async Task<int> InsertRangeAsync( public async Task<int> InsertRangeAsync(
IEnumerable<WellOperationDto> wellOperationDtos, IEnumerable<WellOperationDto> wellOperationDtos,
CancellationToken token) CancellationToken token)
@ -258,6 +216,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
.ConfigureAwait(false); .ConfigureAwait(false);
} }
/// <inheritdoc/>
public async Task<int> UpdateAsync( public async Task<int> UpdateAsync(
WellOperationDto dto, CancellationToken token) WellOperationDto dto, CancellationToken token)
{ {
@ -269,6 +228,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
.ConfigureAwait(false); .ConfigureAwait(false);
} }
/// <inheritdoc/>
public async Task<int> DeleteAsync(IEnumerable<int> ids, public async Task<int> DeleteAsync(IEnumerable<int> ids,
CancellationToken token) CancellationToken token)
{ {
@ -278,14 +238,55 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
.ConfigureAwait(false); .ConfigureAwait(false);
} }
private IQueryable<WellOperation> BuildQuery(WellOperationRequest request) /// <summary>
/// В результате попрежнему требуется конвертировать дату
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
private IQueryable<WellOperationDto> BuildQuery(WellOperationRequest request)
{ {
var timezone = wellService.GetTimezone(request.IdWell); var timezone = wellService.GetTimezone(request.IdWell);
var timeZoneOffset = TimeSpan.FromHours(timezone.Hours);
var query = db.WellOperations var query = db.WellOperations
.Include(s => s.WellSectionType) .Include(s => s.WellSectionType)
.Include(s => s.OperationCategory) .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,
//o.Well,
//o.OperationCategory,
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) if (request.OperationType.HasValue)
query = query.Where(e => e.IdType == request.OperationType.Value); query = query.Where(e => e.IdType == request.OperationType.Value);

View File

@ -1 +0,0 @@
,ASB/andas,asb,19.12.2022 11:39,file:///C:/Users/andas/AppData/Roaming/LibreOffice/4;

View File

@ -1,8 +1,9 @@
using AsbCloudApp.Data; using AsbCloudApp.Data;
using AsbCloudApp.Data.ProcessMap; using AsbCloudApp.Data.ProcessMap;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services; using AsbCloudApp.Services;
using AsbCloudDb.Model; using AsbCloudDb.Model;
using DocumentFormat.OpenXml.Bibliography;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -14,33 +15,37 @@ namespace AsbCloudInfrastructure.Services.ProcessMap
#nullable enable #nullable enable
public class ProcessMapService : IProcessMapService public class ProcessMapService : IProcessMapService
{ {
private readonly IWellOperationService wellOperationService; private readonly IWellOperationRepository wellOperationRepository;
private readonly IProcessMapRepository processMapRepository; private readonly IProcessMapRepository processMapRepository;
public ProcessMapService(IWellOperationService wellOperationService, public ProcessMapService(IWellOperationRepository wellOperationService,
IProcessMapRepository processMapRepository) IProcessMapRepository processMapRepository)
{ {
this.wellOperationService = wellOperationService; this.wellOperationRepository = wellOperationService;
this.processMapRepository = processMapRepository; this.processMapRepository = processMapRepository;
} }
public async Task<IEnumerable<ProcessMapReportDto>> GetProcessMapAsync(int idWell, CancellationToken token) public async Task<IEnumerable<ProcessMapReportDto>> GetProcessMapAsync(int idWell, CancellationToken token)
{ {
var categoryIds = new int[] { WellOperationCategory.IdSlide, WellOperationCategory.IdRotor }; var categoryIds = new int[] { WellOperationCategory.IdSlide, WellOperationCategory.IdRotor };
var allOperations = (await wellOperationService.GetOperationsByIdWellAsync(idWell, token).ConfigureAwait(false))
.Where(x => categoryIds.Contains(x.IdCategory))
.Where(x => x.IdType == 1)
.OrderBy(x => x.IdWellSectionType)
.ThenBy(x => x.DateStart)
.ToList();
var processMapDtos = await processMapRepository.GetByIdWellAsync(idWell, token).ConfigureAwait(false);
var result = allOperations var operationsRequest = new WellOperationRequest
.GroupBy(x => x.IdWellSectionType) {
.SelectMany(x => handleSections(allOperations, processMapDtos!, x)) IdWell = idWell,
.ToList(); OperationCategoryIds = categoryIds,
OperationType = 1,
SortFields = new[]{ nameof(WellOperation.DateStart) }
};
var allOperations = await wellOperationRepository.GetPageAsync(operationsRequest, token);
throw new NotImplementedException();
//var processMapDtos = await processMapRepository.GetByIdWellAsync(idWell, token).ConfigureAwait(false);
return result; //var result = allOperations
// .GroupBy(x => x.IdWellSectionType)
// .SelectMany(x => handleSections(allOperations, processMapDtos!, x))
// .ToList();
//return result;
} }
private static List<ProcessMapReportDto> handleSections(IEnumerable<WellOperationDto> allWellOperation, IEnumerable<ProcessMapDto> processMap, IEnumerable<WellOperationDto> wellOperation) private static List<ProcessMapReportDto> handleSections(IEnumerable<WellOperationDto> allWellOperation, IEnumerable<ProcessMapDto> processMap, IEnumerable<WellOperationDto> wellOperation)

View File

@ -134,7 +134,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
var wellType = (await memoryCache var wellType = (await memoryCache
.GetOrCreateBasicAsync<WellType>(db, token)) .GetOrCreateBasicAsync<WellType>(db, token))
.FirstOrDefault(t => t.Id == well.IdWellType); .FirstOrDefault(t => t.Id == well.IdWellType);
var statWellDto = new StatWellDto() var statWellDto = new StatWellDto
{ {
Id = well.Id, Id = well.Id,
Caption = well.Caption, Caption = well.Caption,
@ -142,10 +142,9 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
IdState = well.IdState, IdState = well.IdState,
State = wellService.GetStateText(well.IdState), State = wellService.GetStateText(well.IdState),
LastTelemetryDate = wellService.GetLastTelemetryDate(well.Id).DateTime, 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) if (well.WellOperations is null)
return statWellDto; return statWellDto;
@ -175,8 +174,8 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
.ToDictionary(s => s.Id); .ToDictionary(s => s.Id);
var sections = new List<StatSectionDto>(sectionTypes.Count); var sections = new List<StatSectionDto>(sectionTypes.Count);
var operationsPlan = operations.Where(o => o.IdType == WellOperationService.idOperationTypePlan); var operationsPlan = operations.Where(o => o.IdType == WellOperation.IdOperationTypePlan);
var operationsFact = operations.Where(o => o.IdType == WellOperationService.idOperationTypeFact); var operationsFact = operations.Where(o => o.IdType == WellOperation.IdOperationTypeFact);
foreach ((var id, var sectionType) in sectionTypes) foreach ((var id, var sectionType) in sectionTypes)
{ {
@ -195,8 +194,8 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
private static PlanFactBase<StatOperationsDto> GetStatTotal(IEnumerable<WellOperation> operations, private static PlanFactBase<StatOperationsDto> GetStatTotal(IEnumerable<WellOperation> operations,
int idWellState, double timezoneOffsetH) int idWellState, double timezoneOffsetH)
{ {
var operationsPlan = operations.Where(o => o.IdType == WellOperationService.idOperationTypePlan); var operationsPlan = operations.Where(o => o.IdType == WellOperation.IdOperationTypePlan);
var operationsFact = operations.Where(o => o.IdType == WellOperationService.idOperationTypeFact); var operationsFact = operations.Where(o => o.IdType == WellOperation.IdOperationTypeFact);
var factEnd = CalcStat(operationsFact, timezoneOffsetH); var factEnd = CalcStat(operationsFact, timezoneOffsetH);
if (factEnd is not null && idWellState != 2) if (factEnd is not null && idWellState != 2)
factEnd.End = null; factEnd.End = null;
@ -369,12 +368,12 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
.ConfigureAwait(false); .ConfigureAwait(false);
var wellOperationsPlan = wellOperations var wellOperationsPlan = wellOperations
.Where(o => o.IdType == WellOperationService.idOperationTypePlan) .Where(o => o.IdType == WellOperation.IdOperationTypePlan)
.OrderBy(o => o.DateStart) .OrderBy(o => o.DateStart)
.ThenBy(o => o.DepthEnd); .ThenBy(o => o.DepthEnd);
var wellOperationsFact = wellOperations var wellOperationsFact = wellOperations
.Where(o => o.IdType == WellOperationService.idOperationTypeFact) .Where(o => o.IdType == WellOperation.IdOperationTypeFact)
.OrderBy(o => o.DateStart) .OrderBy(o => o.DateStart)
.ThenBy(o => o.DepthEnd); .ThenBy(o => o.DepthEnd);

View File

@ -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<int, DateTimeOffset?>? 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<int, string> GetSectionTypes()
=> memoryCache
.GetOrCreateBasic<WellSectionType>(db)
.ToDictionary(s => s.Id, s => s.Caption);
public IEnumerable<WellOperationCategoryDto> GetCategories()
{
var allCategories = memoryCache
.GetOrCreateBasic<WellOperationCategory>(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<IEnumerable<WellOperationCategoryDto>>();
return result;
}
public DateTimeOffset? FirstOperationDate(int idWell)
{
if (firstOperationsCache is null)
{
var query = db.WellOperations
.GroupBy(o => o.IdWell)
.Select(g => new Tuple<int, DateTimeOffset?, DateTimeOffset?>
(
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<WellOperationDto?> 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<WellOperationDto>();
dto.WellSectionTypeName = entity.WellSectionType.Caption;
dto.DateStart = entity.DateStart.ToRemoteDateTime(timezone.Hours);
dto.CategoryName = entity.OperationCategory.Name;
return dto;
}
public Task<IEnumerable<WellOperationDto>> GetAsync(WellOperationRequest request,
CancellationToken token)
{
return Task.FromResult(Enumerable.Empty<WellOperationDto>());
}
public async Task<int> InsertRangeAsync(
IEnumerable<WellOperationDto> 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<WellOperation>();
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<int> UpdateAsync(
WellOperationDto dto, CancellationToken token)
{
var timezone = wellService.GetTimezone(dto.IdWell);
var entity = dto.Adapt<WellOperation>();
entity.DateStart = dto.DateStart.ToUtcDateTimeOffset(timezone.Hours);
db.WellOperations.Update(entity);
return await db.SaveChangesAsync(token)
.ConfigureAwait(false);
}
public async Task<int> DeleteAsync(IEnumerable<int> 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<WellOperation> 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
}

View File

@ -1,5 +1,6 @@
using AsbCloudApp.Data; using AsbCloudApp.Data;
using AsbCloudApp.Exceptions; using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services; using AsbCloudApp.Services;
using AsbCloudDb.Model; using AsbCloudDb.Model;
using AsbCloudInfrastructure.EfCache; using AsbCloudInfrastructure.EfCache;
@ -23,7 +24,7 @@ namespace AsbCloudInfrastructure.Services
private readonly ITelemetryService telemetryService; private readonly ITelemetryService telemetryService;
private readonly ICrudRepository<CompanyTypeDto> companyTypesService; private readonly ICrudRepository<CompanyTypeDto> companyTypesService;
private readonly ITimezoneService timezoneService; private readonly ITimezoneService timezoneService;
private readonly IWellOperationService wellOperationService; private readonly IWellOperationRepository wellOperationRepository;
public ITelemetryService TelemetryService => telemetryService; public ITelemetryService TelemetryService => telemetryService;
@ -42,7 +43,7 @@ namespace AsbCloudInfrastructure.Services
this.telemetryService = telemetryService; this.telemetryService = telemetryService;
this.timezoneService = timezoneService; this.timezoneService = timezoneService;
this.wellOperationService = new WellOperationService.WellOperationService(db, memoryCache, this); this.wellOperationRepository = new WellOperationRepository(db, memoryCache, this);
companyTypesService = new CrudCacheRepositoryBase<CompanyTypeDto, CompanyType>(dbContext, memoryCache); companyTypesService = new CrudCacheRepositoryBase<CompanyTypeDto, CompanyType>(dbContext, memoryCache);
} }
@ -216,7 +217,7 @@ namespace AsbCloudInfrastructure.Services
if (entity.Timezone is null) if (entity.Timezone is null)
dto.Timezone = GetTimezone(entity.Id); 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.WellType = entity.WellType?.Caption;
dto.Cluster = entity.Cluster?.Caption; dto.Cluster = entity.Cluster?.Caption;
dto.Deposit = entity.Cluster?.Deposit?.Caption; dto.Deposit = entity.Cluster?.Deposit?.Caption;

View File

@ -1,4 +1,5 @@
using AsbCloudApp.Data; using AsbCloudApp.Data;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests; using AsbCloudApp.Requests;
using AsbCloudApp.Services; using AsbCloudApp.Services;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
@ -20,13 +21,13 @@ namespace AsbCloudWebApi.Controllers
[Authorize] [Authorize]
public class WellOperationController : ControllerBase public class WellOperationController : ControllerBase
{ {
private readonly IWellOperationService operationService; private readonly IWellOperationRepository operationRepository;
private readonly IWellService wellService; private readonly IWellService wellService;
private readonly IWellOperationImportService wellOperationImportService; 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.wellService = wellService;
this.wellOperationImportService = wellOperationImportService; this.wellOperationImportService = wellOperationImportService;
} }
@ -41,7 +42,7 @@ namespace AsbCloudWebApi.Controllers
[ProducesResponseType(typeof(IDictionary<int, string>), (int)System.Net.HttpStatusCode.OK)] [ProducesResponseType(typeof(IDictionary<int, string>), (int)System.Net.HttpStatusCode.OK)]
public IActionResult GetSectionTypes() public IActionResult GetSectionTypes()
{ {
var result = operationService.GetSectionTypes(); var result = operationRepository.GetSectionTypes();
return Ok(result); return Ok(result);
} }
@ -55,7 +56,7 @@ namespace AsbCloudWebApi.Controllers
[ProducesResponseType(typeof(IEnumerable<WellOperationCategoryDto>), (int)System.Net.HttpStatusCode.OK)] [ProducesResponseType(typeof(IEnumerable<WellOperationCategoryDto>), (int)System.Net.HttpStatusCode.OK)]
public IActionResult GetCategories() public IActionResult GetCategories()
{ {
var result = operationService.GetCategories(); var result = operationRepository.GetCategories();
return Ok(result); return Ok(result);
} }
@ -78,7 +79,7 @@ namespace AsbCloudWebApi.Controllers
return Forbid(); return Forbid();
var requestToService = new WellOperationRequest(request, idWell); var requestToService = new WellOperationRequest(request, idWell);
var result = await operationService.GetOperationsAsync( var result = await operationRepository.GetPageAsync(
requestToService, requestToService,
token) token)
.ConfigureAwait(false); .ConfigureAwait(false);
@ -105,7 +106,7 @@ namespace AsbCloudWebApi.Controllers
return Forbid(); return Forbid();
var requestToService = new WellOperationRequest(request, idWell); var requestToService = new WellOperationRequest(request, idWell);
var result = await operationService.GetGroupOperationsStatAsync( var result = await operationRepository.GetGroupOperationsStatAsync(
requestToService, requestToService,
token) token)
.ConfigureAwait(false); .ConfigureAwait(false);
@ -129,7 +130,7 @@ namespace AsbCloudWebApi.Controllers
if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false))
return Forbid(); return Forbid();
var result = await operationService.GetOrDefaultAsync(idOperation, token).ConfigureAwait(false); var result = await operationRepository.GetOrDefaultAsync(idOperation, token).ConfigureAwait(false);
return Ok(result); return Ok(result);
} }
@ -152,7 +153,7 @@ namespace AsbCloudWebApi.Controllers
foreach(var value in values) foreach(var value in values)
value.IdWell= idWell; value.IdWell= idWell;
var result = await operationService.InsertRangeAsync(values, token) var result = await operationRepository.InsertRangeAsync(values, token)
.ConfigureAwait(false); .ConfigureAwait(false);
return Ok(result); return Ok(result);
@ -178,7 +179,7 @@ namespace AsbCloudWebApi.Controllers
value.IdWell= idWell; value.IdWell= idWell;
value.Id = idOperation; value.Id = idOperation;
var result = await operationService.UpdateAsync(value, token) var result = await operationRepository.UpdateAsync(value, token)
.ConfigureAwait(false); .ConfigureAwait(false);
return Ok(result); return Ok(result);
} }
@ -199,7 +200,7 @@ namespace AsbCloudWebApi.Controllers
token).ConfigureAwait(false)) token).ConfigureAwait(false))
return Forbid(); return Forbid();
var result = await operationService.DeleteAsync(new int[] { idOperation }, token) var result = await operationRepository.DeleteAsync(new int[] { idOperation }, token)
.ConfigureAwait(false); .ConfigureAwait(false);
return Ok(result); return Ok(result);

View File

@ -1,21 +1,10 @@
using AsbCloudApp.Data; using AsbCloudApp.Requests;
using AsbCloudApp.Data.DailyReport;
using AsbCloudDb;
using AsbCloudDb.Model; using AsbCloudDb.Model;
using AsbCloudInfrastructure; using AsbCloudInfrastructure;
using AsbCloudInfrastructure.Services.DailyReport; using AsbCloudInfrastructure.Repository;
using AsbCloudInfrastructure.Services.SAUB; using Microsoft.Extensions.Caching.Memory;
using ClosedXML.Excel;
using DocumentFormat.OpenXml.Wordprocessing;
using Microsoft.EntityFrameworkCore;
using Org.BouncyCastle.Utilities.Collections;
using System; using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1 namespace ConsoleApp1
{ {
@ -29,7 +18,9 @@ namespace ConsoleApp1
DependencyInjection.MapsterSetup(); DependencyInjection.MapsterSetup();
var sw = System.Diagnostics.Stopwatch.StartNew(); var sw = System.Diagnostics.Stopwatch.StartNew();
var repo = new WellOperationRepository(db, new MemoryCache(new MemoryCacheOptions()), ServiceFactory.MakeWellService());
var req = new WellOperationRequest { IdWell = 88, OperationType = 1, Skip = 70};
var res = repo.GetPageAsync(req, CancellationToken.None).Result;
sw.Stop(); sw.Stop();
Console.WriteLine($"total time: {sw.ElapsedMilliseconds} ms"); Console.WriteLine($"total time: {sw.ElapsedMilliseconds} ms");

View File

@ -1,4 +1,5 @@
using AsbCloudDb.Model; using AsbCloudDb.Model;
using AsbCloudInfrastructure.Repository;
using AsbCloudInfrastructure.Services; using AsbCloudInfrastructure.Services;
using AsbCloudInfrastructure.Services.SAUB; using AsbCloudInfrastructure.Services.SAUB;
using AsbCloudInfrastructure.Services.WellOperationService; using AsbCloudInfrastructure.Services.WellOperationService;
@ -71,7 +72,7 @@ namespace ConsoleApp1
public static WellService MakeWellService() public static WellService MakeWellService()
=> new (Context, memoryCache, MakeTelemetryService(), TimezoneService); => new (Context, memoryCache, MakeTelemetryService(), TimezoneService);
public static WellOperationService MakeWellOperationsService() public static WellOperationRepository MakeWellOperationRepository()
=> new (Context, memoryCache, MakeWellService()); => new (Context, memoryCache, MakeWellService());
public static OperationsStatService MakeOperationsStatService() public static OperationsStatService MakeOperationsStatService()