forked from ddrilling/AsbCloudServer
Merge branch 'dev' into feature/change-log-refactoring
This commit is contained in:
commit
6af038496c
@ -19,15 +19,6 @@ namespace AsbCloudApp.Repositories
|
||||
Task<IEnumerable<DepositDto>> GetAsync(int idCompany,
|
||||
CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Список месторождений/кустов/скважин у которых заполненны параметры бурения
|
||||
/// </summary>
|
||||
/// <param name="idCompany"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<DepositDto>> GetAllWithDrillParamsAsync(int idCompany,
|
||||
CancellationToken token = default);
|
||||
|
||||
/// <summary>
|
||||
/// Список кустов месторождения доступных компании
|
||||
/// </summary>
|
||||
|
@ -1,9 +1,9 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Data.WellOperation;
|
||||
using AsbCloudApp.Requests;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data.WellOperation;
|
||||
using AsbCloudApp.Requests;
|
||||
|
||||
namespace AsbCloudApp.Repositories
|
||||
{
|
||||
@ -54,7 +54,7 @@ namespace AsbCloudApp.Repositories
|
||||
/// <summary>
|
||||
/// Обновить существующую операцию
|
||||
/// </summary>
|
||||
/// <param name="dto"></param>
|
||||
/// <param name="dtos"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> UpdateRangeAsync(IEnumerable<WellOperationDto> dtos, CancellationToken token);
|
||||
@ -83,5 +83,12 @@ namespace AsbCloudApp.Repositories
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, int idType, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает первую и последнюю фактическую операцию
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <returns></returns>
|
||||
(WellOperationDto First, WellOperationDto Last)? GetFirstAndLastFact(int idWell);
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace AsbCloudApp.Requests;
|
||||
|
||||
@ -46,6 +47,34 @@ public class WellOperationRequestBase : RequestBase
|
||||
/// Идентификаторы конструкций секции
|
||||
/// </summary>
|
||||
public IEnumerable<int>? SectionTypeIds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public WellOperationRequestBase()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
public WellOperationRequestBase(WellOperationRequestBase request)
|
||||
{
|
||||
GeDepth = request.GeDepth;
|
||||
LeDepth = request.LeDepth;
|
||||
GeDate = request.GeDate;
|
||||
LeDate = request.LeDate;
|
||||
|
||||
OperationCategoryIds = request.OperationCategoryIds;
|
||||
OperationType = request.OperationType;
|
||||
SectionTypeIds = request.SectionTypeIds;
|
||||
|
||||
Skip = request.Skip;
|
||||
Take = request.Take;
|
||||
SortFields = request.SortFields;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -61,24 +90,15 @@ public class WellOperationRequest : WellOperationRequestBase
|
||||
|
||||
/// <inheritdoc />
|
||||
public WellOperationRequest(WellOperationRequestBase request, IEnumerable<int> idsWell)
|
||||
: this(idsWell)
|
||||
: base(request)
|
||||
{
|
||||
GeDepth = request.GeDepth;
|
||||
LeDepth = request.LeDepth;
|
||||
GeDate = request.GeDate;
|
||||
LeDate = request.LeDate;
|
||||
|
||||
OperationCategoryIds = request.OperationCategoryIds;
|
||||
OperationType = request.OperationType;
|
||||
SectionTypeIds = request.SectionTypeIds;
|
||||
|
||||
Skip = request.Skip;
|
||||
Take = request.Take;
|
||||
SortFields = request.SortFields;
|
||||
IdsWell = idsWell;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Идентификаторы скважин
|
||||
/// </summary>
|
||||
public IEnumerable<int>? IdsWell { get; }
|
||||
[Required]
|
||||
[Length(1, 100)]
|
||||
public IEnumerable<int> IdsWell { get; }
|
||||
}
|
@ -223,11 +223,12 @@ namespace AsbCloudDb
|
||||
private static string FormatValue(object? v)
|
||||
=> v switch
|
||||
{
|
||||
null => "NULL",
|
||||
string vStr => $"'{EscapeCurlyBraces(vStr)}'",
|
||||
DateTime vDate => $"'{FormatDateValue(vDate)}'",
|
||||
DateTimeOffset vDate => $"'{FormatDateValue(vDate.UtcDateTime)}'",
|
||||
IFormattable vFormattable => FormatFormattableValue(vFormattable),
|
||||
_ => System.Text.Json.JsonSerializer.Serialize(v),
|
||||
_ => $"'{EscapeCurlyBraces(JsonSerializer.Serialize(v))}'",
|
||||
};
|
||||
|
||||
private static string EscapeCurlyBraces(string vStr)
|
||||
|
Binary file not shown.
@ -10,56 +10,36 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudInfrastructure.Repository
|
||||
{
|
||||
namespace AsbCloudInfrastructure.Repository;
|
||||
|
||||
public class DepositRepository : IDepositRepository
|
||||
{
|
||||
private readonly IAsbCloudDbContext db;
|
||||
private readonly IWellService wellService;
|
||||
private readonly ITelemetryService telemetryService;
|
||||
|
||||
public DepositRepository(IAsbCloudDbContext db, IWellService wellService)
|
||||
public DepositRepository(IAsbCloudDbContext db, ITelemetryService telemetryService)
|
||||
{
|
||||
this.db = db;
|
||||
this.wellService = wellService;
|
||||
this.telemetryService = telemetryService;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IEnumerable<DepositDto>> GetAsync(int idCompany,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var wellEntities = await (from well in db.Wells
|
||||
var wellsQuery = db.Set<Well>()
|
||||
.Include(w => w.RelationCompaniesWells)
|
||||
.Include(w => w.WellType)
|
||||
.Include(w => w.Cluster)
|
||||
.ThenInclude(c => c.Deposit)
|
||||
where well.RelationCompaniesWells.Any(r => r.IdCompany == idCompany)
|
||||
select well).ToListAsync(token)
|
||||
.ConfigureAwait(false);
|
||||
.Where(well => well.RelationCompaniesWells.Any(r => r.IdCompany == idCompany));
|
||||
|
||||
var wellEntities = await wellsQuery.ToArrayAsync(token);
|
||||
|
||||
var gDepositEntities = GroupWells(wellEntities);
|
||||
|
||||
var dtos = CreateDepositDto(gDepositEntities);
|
||||
|
||||
return dtos;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IEnumerable<DepositDto>> GetAllWithDrillParamsAsync(int idCompany,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var wellEntities = await (from well in db.Wells
|
||||
.Include(w => w.RelationCompaniesWells)
|
||||
.Include(w => w.WellType)
|
||||
.Include(w => w.Cluster)
|
||||
.ThenInclude(c => c.Deposit)
|
||||
where well.RelationCompaniesWells.Any(r => r.IdCompany == idCompany)
|
||||
select well).ToListAsync(token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var gDepositEntities = GroupWells(wellEntities);
|
||||
|
||||
var dtos = CreateDepositDto(gDepositEntities);
|
||||
var dtos = CreateDepositDto(gDepositEntities)
|
||||
.ToArray();
|
||||
|
||||
return dtos;
|
||||
}
|
||||
@ -87,7 +67,7 @@ namespace AsbCloudInfrastructure.Repository
|
||||
.GroupBy(c => c.Key.Deposit);
|
||||
|
||||
private IQueryable<Well> GetWellsForCompany(int idCompany)
|
||||
=> db.Wells
|
||||
=> db.Set<Well>()
|
||||
.Include(w => w.RelationCompaniesWells)
|
||||
.ThenInclude(r => r.Company)
|
||||
.Include(w => w.Cluster)
|
||||
@ -112,8 +92,12 @@ namespace AsbCloudInfrastructure.Repository
|
||||
{
|
||||
var dto = well.Adapt<WellDto>();
|
||||
dto.WellType = well.WellType.Caption;
|
||||
dto.LastTelemetryDate = wellService.GetLastTelemetryDate(well.Id)
|
||||
.ToOffset(TimeSpan.FromHours(well.Timezone.Hours));
|
||||
|
||||
dto.LastTelemetryDate = DateTimeOffset.MinValue;
|
||||
|
||||
if (well.IdTelemetry != null)
|
||||
dto.LastTelemetryDate = telemetryService.GetDatesRange(well.IdTelemetry.Value).To;
|
||||
|
||||
dto.Cluster = gCluster.Key.Caption;
|
||||
dto.Deposit = gDeposit.Key.Caption;
|
||||
return dto;
|
||||
@ -123,5 +107,3 @@ namespace AsbCloudInfrastructure.Repository
|
||||
return dtos;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Requests;
|
||||
using AsbCloudDb;
|
||||
using AsbCloudDb.Model;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@ -68,11 +69,12 @@ namespace AsbCloudInfrastructure.Repository
|
||||
var entities = dtos.Select(dto =>
|
||||
{
|
||||
var entity = dto.Adapt<DrillTest>();
|
||||
entity.TimeStampStart = dto.TimeStampStart.ToUniversalTime();
|
||||
entity.IdTelemetry = idTelemetry;
|
||||
return entity;
|
||||
});
|
||||
db.DrillTests.AddRange(entities);
|
||||
var result = await db.SaveChangesAsync(token);
|
||||
|
||||
var result = await db.Database.ExecInsertOrUpdateAsync(db.Set<DrillTest>(), entities, token);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Data.WellOperation;
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Repositories;
|
||||
@ -14,26 +9,36 @@ 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;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudInfrastructure.Repository;
|
||||
|
||||
public class WellOperationRepository : CrudRepositoryBase<WellOperationDto, WellOperation>,
|
||||
IWellOperationRepository
|
||||
{
|
||||
private const string cacheKeyWellOperations = "FirstAndLastFactWellsOperations";
|
||||
private readonly IMemoryCache memoryCache;
|
||||
private readonly IWellOperationCategoryRepository wellOperationCategoryRepository;
|
||||
private readonly IWellService wellService;
|
||||
private Lazy<IDictionary<int, WellOperationCategoryDto>> LazyWellCategories { get; }
|
||||
private Lazy<IDictionary<int, WellSectionTypeDto>> LazyWellSectionTypes { get; }
|
||||
|
||||
public WellOperationRepository(IAsbCloudDbContext context,
|
||||
IMemoryCache memoryCache,
|
||||
IWellOperationCategoryRepository wellOperationCategoryRepository,
|
||||
IWellService wellService)
|
||||
: base(context, dbSet => dbSet.Include(e => e.WellSectionType)
|
||||
.Include(e => e.OperationCategory))
|
||||
: base(context, dbSet => dbSet)
|
||||
{
|
||||
this.memoryCache = memoryCache;
|
||||
this.wellOperationCategoryRepository = wellOperationCategoryRepository;
|
||||
this.wellService = wellService;
|
||||
|
||||
LazyWellCategories = new(() => wellOperationCategoryRepository.Get(true, false).ToDictionary(c => c.Id));
|
||||
LazyWellSectionTypes = new(() => GetSectionTypes().ToDictionary(c => c.Id));
|
||||
}
|
||||
|
||||
public IEnumerable<WellSectionTypeDto> GetSectionTypes() =>
|
||||
@ -44,38 +49,23 @@ public class WellOperationRepository : CrudRepositoryBase<WellOperationDto, Well
|
||||
|
||||
public async Task<IEnumerable<WellOperationDto>> GetAsync(WellOperationRequest request, CancellationToken token)
|
||||
{
|
||||
var query = BuildQuery(request);
|
||||
|
||||
if (request.Skip.HasValue)
|
||||
query = query.Skip(request.Skip.Value);
|
||||
|
||||
if (request.Take.HasValue)
|
||||
query = query.Take(request.Take.Value);
|
||||
|
||||
var entities = await query.AsNoTracking()
|
||||
.ToArrayAsync(token);
|
||||
|
||||
return await ConvertWithDrillingDaysAndNpvHoursAsync(entities, token);
|
||||
var (items, _) = await GetWithDaysAndNpvAsync(request, token);
|
||||
return items;
|
||||
}
|
||||
|
||||
public async Task<PaginationContainer<WellOperationDto>> GetPageAsync(WellOperationRequest request, CancellationToken token)
|
||||
{
|
||||
var skip = request.Skip ?? 0;
|
||||
var take = request.Take ?? 32;
|
||||
request.Skip = request.Skip ?? 0;
|
||||
request.Take = request.Take ?? 32;
|
||||
|
||||
var query = BuildQuery(request);
|
||||
|
||||
var entities = await query.Skip(skip)
|
||||
.Take(take)
|
||||
.AsNoTracking()
|
||||
.ToArrayAsync(token);
|
||||
var (items, count) = await GetWithDaysAndNpvAsync(request, token);
|
||||
|
||||
var paginationContainer = new PaginationContainer<WellOperationDto>
|
||||
{
|
||||
Skip = skip,
|
||||
Take = take,
|
||||
Count = await query.CountAsync(token),
|
||||
Items = await ConvertWithDrillingDaysAndNpvHoursAsync(entities, token)
|
||||
Skip = request.Skip!.Value,
|
||||
Take = request.Take!.Value,
|
||||
Count = count,
|
||||
Items = items
|
||||
};
|
||||
|
||||
return paginationContainer;
|
||||
@ -146,8 +136,18 @@ public class WellOperationRepository : CrudRepositoryBase<WellOperationDto, Well
|
||||
{
|
||||
EnsureValidWellOperations(dtos);
|
||||
|
||||
var result = 0;
|
||||
|
||||
if (!deleteBeforeInsert)
|
||||
return await InsertRangeAsync(dtos, token);
|
||||
{
|
||||
result = await InsertRangeAsync(dtos, token);
|
||||
|
||||
if (result > 0)
|
||||
memoryCache.Remove(cacheKeyWellOperations);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
var idType = dtos.First().IdType;
|
||||
var idWell = dtos.First().IdWell;
|
||||
@ -159,14 +159,26 @@ public class WellOperationRepository : CrudRepositoryBase<WellOperationDto, Well
|
||||
|
||||
await DeleteRangeAsync(existingOperationIds, token);
|
||||
|
||||
return await InsertRangeAsync(dtos, token);
|
||||
result = await InsertRangeAsync(dtos, token);
|
||||
|
||||
if (result > 0)
|
||||
memoryCache.Remove(cacheKeyWellOperations);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
public override Task<int> UpdateRangeAsync(IEnumerable<WellOperationDto> dtos, CancellationToken token)
|
||||
public override async Task<int> UpdateRangeAsync(IEnumerable<WellOperationDto> dtos, CancellationToken token)
|
||||
{
|
||||
EnsureValidWellOperations(dtos);
|
||||
|
||||
return base.UpdateRangeAsync(dtos, token);
|
||||
var result = await base.UpdateRangeAsync(dtos, token);
|
||||
|
||||
if (result > 0)
|
||||
memoryCache.Remove(cacheKeyWellOperations);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
private static void EnsureValidWellOperations(IEnumerable<WellOperationDto> dtos)
|
||||
@ -178,42 +190,97 @@ public class WellOperationRepository : CrudRepositoryBase<WellOperationDto, Well
|
||||
throw new ArgumentInvalidException(nameof(dtos), "Все операции должны принадлежать одной скважине");
|
||||
}
|
||||
|
||||
private IQueryable<WellOperation> BuildQuery(WellOperationRequest request)
|
||||
private async Task<IEnumerable<WellOperation>> GetByIdsWells(IEnumerable<int> idsWells, CancellationToken token)
|
||||
{
|
||||
var query = GetQuery()
|
||||
.Where(e => request.IdsWell != null && request.IdsWell.Contains(e.IdWell))
|
||||
.Where(e => idsWells.Contains(e.IdWell))
|
||||
.OrderBy(e => e.DateStart);
|
||||
var entities = await query.ToArrayAsync(token);
|
||||
return entities;
|
||||
}
|
||||
|
||||
private async Task<(IEnumerable<WellOperationDto> 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<WellOperationDto>();
|
||||
var count = 0;
|
||||
foreach (var wellOperationsWithType in groupedByWellAndType)
|
||||
{
|
||||
var firstWellOperation = wellOperationsWithType
|
||||
.OrderBy(e => e.DateStart)
|
||||
.AsQueryable();
|
||||
.FirstOrDefault()!;
|
||||
|
||||
var operationsWithNpt = wellOperationsWithType
|
||||
.Where(o => WellOperationCategory.NonProductiveTimeSubIds.Contains(o.IdCategory));
|
||||
|
||||
IEnumerable<WellOperation> 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 dtos = filteredWellOperations
|
||||
.Select(entity =>
|
||||
{
|
||||
var dto = Convert(entity);
|
||||
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<WellOperation> FilterByRequest(IQueryable<WellOperation> entities, WellOperationRequest request)
|
||||
{
|
||||
if (request.OperationType.HasValue)
|
||||
query = query.Where(e => e.IdType == request.OperationType.Value);
|
||||
|
||||
entities = entities.Where(e => e.IdType == request.OperationType.Value);
|
||||
if (request.SectionTypeIds?.Any() is true)
|
||||
query = query.Where(e => request.SectionTypeIds.Contains(e.IdWellSectionType));
|
||||
|
||||
entities = entities.Where(e => request.SectionTypeIds.Contains(e.IdWellSectionType));
|
||||
if (request.OperationCategoryIds?.Any() is true)
|
||||
query = query.Where(e => request.OperationCategoryIds.Contains(e.IdCategory));
|
||||
|
||||
entities = entities.Where(e => request.OperationCategoryIds.Contains(e.IdCategory));
|
||||
if (request.GeDepth.HasValue)
|
||||
query = query.Where(e => e.DepthEnd >= request.GeDepth.Value);
|
||||
|
||||
entities = entities.Where(e => e.DepthEnd >= request.GeDepth.Value);
|
||||
if (request.LeDepth.HasValue)
|
||||
query = query.Where(e => e.DepthEnd <= request.LeDepth.Value);
|
||||
entities = entities.Where(e => e.DepthEnd <= request.LeDepth.Value);
|
||||
|
||||
if (request.GeDate.HasValue)
|
||||
{
|
||||
var geDateUtc = request.GeDate.Value.UtcDateTime;
|
||||
query = query.Where(e => e.DateStart >= geDateUtc);
|
||||
entities = entities.Where(e => e.DateStart >= geDateUtc);
|
||||
}
|
||||
|
||||
if (request.LeDate.HasValue)
|
||||
{
|
||||
var leDateUtc = request.LeDate.Value.UtcDateTime;
|
||||
query = query.Where(e => e.DateStart <= leDateUtc);
|
||||
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;
|
||||
}
|
||||
|
||||
if (request.SortFields?.Any() is true)
|
||||
query = query.SortBy(request.SortFields);
|
||||
private IQueryable<WellOperation> BuildQuery(WellOperationRequest request)
|
||||
{
|
||||
var query = GetQuery()
|
||||
.Where(e => request.IdsWell.Contains(e.IdWell))
|
||||
.OrderBy(e => e.DateStart)
|
||||
.AsQueryable();
|
||||
query = FilterByRequest(query, request);
|
||||
|
||||
return query;
|
||||
}
|
||||
@ -284,7 +351,7 @@ public class WellOperationRepository : CrudRepositoryBase<WellOperationDto, Well
|
||||
return sections;
|
||||
});
|
||||
|
||||
return cache;
|
||||
return cache!;
|
||||
}
|
||||
|
||||
public async Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, int idType, CancellationToken cancellationToken)
|
||||
@ -306,41 +373,51 @@ public class WellOperationRepository : CrudRepositoryBase<WellOperationDto, Well
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<WellOperationDto>> ConvertWithDrillingDaysAndNpvHoursAsync(IEnumerable<WellOperation> entities,
|
||||
CancellationToken token)
|
||||
public (WellOperationDto First, WellOperationDto Last)? GetFirstAndLastFact(int idWell)
|
||||
{
|
||||
var idsWell = entities.Select(e => e.IdWell).Distinct();
|
||||
|
||||
var currentWellOperations = GetQuery()
|
||||
.Where(entity => idsWell.Contains(entity.IdWell));
|
||||
|
||||
var dateFirstDrillingOperationByIdWell = await currentWellOperations
|
||||
.Where(entity => entity.IdType == WellOperation.IdOperationTypeFact)
|
||||
.GroupBy(entity => entity.IdWell)
|
||||
.ToDictionaryAsync(g => g.Key, g => g.Min(o => o.DateStart), token);
|
||||
|
||||
var operationsWithNptByIdWell = await currentWellOperations.Where(entity =>
|
||||
entity.IdType == WellOperation.IdOperationTypeFact &&
|
||||
WellOperationCategory.NonProductiveTimeSubIds.Contains(entity.IdCategory))
|
||||
.GroupBy(entity => entity.IdWell)
|
||||
.ToDictionaryAsync(g => g.Key, g => g.Select(o => o), token);
|
||||
|
||||
var dtos = entities.Select(entity =>
|
||||
var cachedDictionary = memoryCache.GetOrCreate(cacheKeyWellOperations, (entry) =>
|
||||
{
|
||||
var dto = Convert(entity);
|
||||
|
||||
if (dateFirstDrillingOperationByIdWell.TryGetValue(entity.IdWell, out var dateFirstDrillingOperation))
|
||||
dto.Day = (entity.DateStart - dateFirstDrillingOperation).TotalDays;
|
||||
|
||||
if (operationsWithNptByIdWell.TryGetValue(entity.IdWell, out var wellOperationsWithNtp))
|
||||
dto.NptHours = wellOperationsWithNtp
|
||||
.Where(o => o.DateStart <= entity.DateStart)
|
||||
.Sum(e => e.DurationHours);
|
||||
|
||||
return dto;
|
||||
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5);
|
||||
var query = dbContext.Set<WellOperation>()
|
||||
.Where(o => o.IdType == WellOperation.IdOperationTypeFact)
|
||||
.GroupBy(o => o.IdWell)
|
||||
.Select(group => new
|
||||
{
|
||||
IdWell = group.Key,
|
||||
FirstFact = group.OrderBy(o => o.DateStart).First(),
|
||||
LastFact = group.OrderBy(o => o.DateStart).Last(),
|
||||
});
|
||||
|
||||
return dtos;
|
||||
var entities = query.ToArray();
|
||||
|
||||
var dictionary = entities.ToDictionary(s => s.IdWell, s => (Convert(s.FirstFact), Convert(s.LastFact)));
|
||||
entry.Value = dictionary;
|
||||
|
||||
return dictionary;
|
||||
|
||||
})!;
|
||||
|
||||
var firstAndLast = cachedDictionary.GetValueOrDefault(idWell);
|
||||
return firstAndLast;
|
||||
|
||||
}
|
||||
|
||||
public override async Task<int> DeleteAsync(int id, CancellationToken token)
|
||||
{
|
||||
var result = await base.DeleteAsync(id, token);
|
||||
if (result > 0)
|
||||
memoryCache.Remove(cacheKeyWellOperations);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task<int> DeleteRangeAsync(IEnumerable<int> ids, CancellationToken token)
|
||||
{
|
||||
var result = await base.DeleteRangeAsync(ids, token);
|
||||
if (result > 0)
|
||||
memoryCache.Remove(cacheKeyWellOperations);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override WellOperation Convert(WellOperationDto src)
|
||||
@ -355,9 +432,13 @@ public class WellOperationRepository : CrudRepositoryBase<WellOperationDto, Well
|
||||
//TODO: пока такое получение TimeZone скважины, нужно исправить на Lazy
|
||||
//Хоть мы и тянем данные из кэша, но от получения TimeZone в этом методе нужно избавиться, пока так
|
||||
var timeZoneOffset = wellService.GetTimezone(src.IdWell).Offset;
|
||||
|
||||
var dto = src.Adapt<WellOperationDto>();
|
||||
dto.DateStart = src.DateStart.ToOffset(timeZoneOffset);
|
||||
dto.LastUpdateDate = src.LastUpdateDate.ToOffset(timeZoneOffset);
|
||||
|
||||
dto.OperationCategoryName = LazyWellCategories.Value.TryGetValue(src.IdCategory, out WellOperationCategoryDto? category) ? category.Name : string.Empty;
|
||||
dto.WellSectionTypeCaption = LazyWellSectionTypes.Value.TryGetValue(src.IdWellSectionType, out WellSectionTypeDto? sectionType) ? sectionType.Caption : string.Empty;
|
||||
return dto;
|
||||
}
|
||||
}
|
@ -142,14 +142,13 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
return Task.CompletedTask;
|
||||
|
||||
var telemetry = telemetryService.GetOrCreateTelemetryByUid(uid);
|
||||
var timezone = telemetryService.GetTimezone(telemetry.Id);
|
||||
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
var entity = dto.Adapt<TelemetryMessage>();
|
||||
entity.Id = 0;
|
||||
entity.IdTelemetry = telemetry.Id;
|
||||
entity.DateTime = dto.Date.ToOffset(TimeSpan.FromHours(timezone.Hours));
|
||||
entity.DateTime = dto.Date.ToUniversalTime();
|
||||
db.TelemetryMessages.Add(entity);
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
if (dateBegin == default)
|
||||
{
|
||||
var dateRange = telemetryDataCache.GetOrDefaultDataDateRange(telemetry.Id);
|
||||
dateBeginUtc = (dateRange?.To ?? DateTimeOffset.UtcNow)
|
||||
dateBeginUtc = (dateRange?.To.ToUniversalTime() ?? DateTimeOffset.UtcNow)
|
||||
.AddSeconds(-intervalSec);
|
||||
}
|
||||
else
|
||||
|
@ -152,8 +152,8 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
if (!cacheItem.LastData.Any())
|
||||
return null;
|
||||
|
||||
var from = cacheItem.FirstByDate.DateTime;
|
||||
var to = cacheItem.LastData[^1].DateTime;
|
||||
var from = DateTime.SpecifyKind(cacheItem.FirstByDate.DateTime, DateTimeKind.Unspecified);
|
||||
var to = DateTime.SpecifyKind(cacheItem.LastData[^1].DateTime, DateTimeKind.Unspecified);
|
||||
|
||||
return new DatesRangeDto
|
||||
{
|
||||
|
@ -144,7 +144,63 @@ public class WellCompositeOperationService : IWellCompositeOperationService
|
||||
{ (6, 5095) },
|
||||
{ (6, 5012) },
|
||||
{ (6, 5040) },
|
||||
{ (6, 5092) }
|
||||
{ (6, 5092) },
|
||||
|
||||
{ (5, 5001) },
|
||||
{ (5, 5015) },
|
||||
{ (5, 5046) },
|
||||
{ (5, 5037) },
|
||||
{ (5, 5097) },
|
||||
{ (5, 5057) },
|
||||
{ (5, 5113) },
|
||||
{ (5, 5036) },
|
||||
{ (5, 5008) },
|
||||
{ (5, 5003) },
|
||||
{ (5, 5036) },
|
||||
{ (5, 5013) },
|
||||
{ (5, 5000) },
|
||||
{ (5, 5029) },
|
||||
{ (5, 5022) },
|
||||
{ (5, 5017) },
|
||||
{ (5, 5019) },
|
||||
{ (5, 5042) },
|
||||
{ (5, 5046) },
|
||||
|
||||
{ (2, 5096) },
|
||||
{ (2, 5008) },
|
||||
{ (2, 5002) },
|
||||
{ (2, 5003) },
|
||||
|
||||
{ (3, 5096) },
|
||||
{ (3, 5008) },
|
||||
{ (3, 5002) },
|
||||
{ (3, 5003) },
|
||||
{ (3, 5085) },
|
||||
{ (3, 5014) },
|
||||
|
||||
{ (31, 5002) },
|
||||
{ (31, 5003) },
|
||||
{ (31, 5014) },
|
||||
{ (31, 5012) },
|
||||
{ (31, 5083) },
|
||||
|
||||
{ (4, 5002) },
|
||||
{ (4, 5003) },
|
||||
{ (4, 5085) },
|
||||
{ (4, 5087) },
|
||||
{ (4, 5014) },
|
||||
{ (4, 5053) },
|
||||
{ (4, 5084) },
|
||||
{ (4, 5086) },
|
||||
|
||||
{ (6, 5002) },
|
||||
{ (6, 5003) },
|
||||
{ (6, 5085) },
|
||||
{ (6, 5036) },
|
||||
{ (6, 5035) },
|
||||
{ (6, 5021) },
|
||||
{ (6, 5086) },
|
||||
|
||||
};
|
||||
|
||||
public WellCompositeOperationService(
|
||||
@ -221,8 +277,8 @@ public class WellCompositeOperationService : IWellCompositeOperationService
|
||||
compositeOperation.DepthStart = compositeDepth;
|
||||
compositeDepth = compositeOperation.DepthStart;
|
||||
|
||||
compositeDay += compositeOperation.DurationHours;
|
||||
compositeOperation.Day = compositeDay / 24;
|
||||
compositeDay += compositeOperation.DurationHours;
|
||||
|
||||
compositeOperations.Add(compositeOperation);
|
||||
}
|
||||
|
@ -37,12 +37,16 @@ public class WellInfoService
|
||||
var telemetryDataSaubCache = services.GetRequiredService<ITelemetryDataCache<TelemetryDataSaubDto>>();
|
||||
var messageHub = services.GetRequiredService<IIntegrationEventHandler<UpdateWellInfoEvent>>();
|
||||
|
||||
var wells = await wellService.GetAllAsync(token);
|
||||
var entries = await wellService.GetAllAsync(token);
|
||||
var wells = entries.ToList();
|
||||
var activeWells = wells.Where(well => well.IdState == 1);
|
||||
|
||||
var wellsIds = activeWells.Select(w => w.Id);
|
||||
|
||||
var processMapPlanWellDrillingRequests = wellsIds.Select(id => new ProcessMapPlanBaseRequestWithWell(id));
|
||||
var processMapPlanWellDrillingRequests = wellsIds.Select(id => new ProcessMapPlanBaseRequestWithWell(id)
|
||||
{
|
||||
Moment = DateTimeOffset.UtcNow.AddDays(1)
|
||||
});
|
||||
var processMapPlanWellDrillings = new List<ProcessMapPlanDrillingDto>();
|
||||
foreach (var processMapPlanWellDrillingRequest in processMapPlanWellDrillingRequests)
|
||||
{
|
||||
@ -96,14 +100,21 @@ public class WellInfoService
|
||||
int? idSection = wellLastFactSection?.Id;
|
||||
ProcessMapPlanDrillingDto? processMapPlanWellDrilling = null;
|
||||
|
||||
if (idSection.HasValue)
|
||||
if(idSection.HasValue && currentDepth.HasValue)
|
||||
{
|
||||
processMapPlanWellDrilling = wellProcessMaps.FirstOrDefault(p => p.IdWellSectionType == idSection);
|
||||
processMapPlanWellDrilling = wellProcessMaps
|
||||
.Where(p => p.IdWellSectionType == idSection)
|
||||
.Where(p => p.DepthStart <= currentDepth.Value && p.DepthEnd >= currentDepth.Value)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
else if(currentDepth.HasValue)
|
||||
{
|
||||
processMapPlanWellDrilling = wellProcessMaps.FirstOrDefault(p => p.DepthStart <= currentDepth.Value && p.DepthEnd >= currentDepth.Value);
|
||||
}
|
||||
else if (idSection.HasValue)
|
||||
{
|
||||
processMapPlanWellDrilling = wellProcessMaps.FirstOrDefault(p => p.IdWellSectionType == idSection);
|
||||
}
|
||||
|
||||
double? planTotalDepth = null;
|
||||
planTotalDepth = wellDepthByProcessMap.FirstOrDefault(p => p.Id == well.Id)?.DepthEnd;
|
||||
|
Binary file not shown.
Binary file not shown.
@ -42,7 +42,7 @@ public class WellOperationExport<TTemplate> : ExcelExportService<WellOperationDt
|
||||
{
|
||||
var request = new WellOperationRequest(new[] { options.IdWell })
|
||||
{
|
||||
OperationType = options.IdType
|
||||
OperationType = options.IdType,
|
||||
};
|
||||
|
||||
return wellOperationRepository.GetAsync(request, token);
|
||||
|
@ -273,9 +273,8 @@ namespace AsbCloudInfrastructure.Services
|
||||
if (entity.Timezone is null)
|
||||
dto.Timezone = GetTimezone(entity.Id);
|
||||
|
||||
dto.StartDate = dbContext.WellOperations.Where(e => e.IdType == WellOperation.IdOperationTypeFact)
|
||||
.AsNoTracking()
|
||||
.MinOrDefault(e => e.DateStart)?.ToRemoteDateTime(dto.Timezone.Hours);
|
||||
dto.StartDate = wellOperationRepository
|
||||
.GetFirstAndLastFact(entity.Id)?.First?.DateStart;
|
||||
dto.WellType = entity.WellType.Caption;
|
||||
dto.Cluster = entity.Cluster.Caption;
|
||||
dto.Deposit = entity.Cluster.Deposit.Caption;
|
||||
|
@ -0,0 +1,29 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Data.DrillTestReport;
|
||||
using AsbCloudApp.Data.SAUB;
|
||||
using AsbCloudApp.Requests;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Refit;
|
||||
|
||||
namespace AsbCloudWebApi.IntegrationTests.Clients;
|
||||
|
||||
public interface IDrillTestControllerClient
|
||||
{
|
||||
[Post("/api/telemetry/{uid}/DrillTest")]
|
||||
Task<IApiResponse> PostDataAsync(
|
||||
string uid,
|
||||
IEnumerable<DrillTestBaseDto> dtos,
|
||||
CancellationToken token);
|
||||
|
||||
[Get("/api/well/{idWell}/DrillTest")]
|
||||
Task<IApiResponse<PhysicalFileResult>> GenerateReportAsync(
|
||||
int idWell,
|
||||
int id,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
[HttpGet("/api/well/{idWell}/DrillTest/all")]
|
||||
Task<IApiResponse<PaginationContainer<DrillTestReportInfoDto>>> GetListAsync(
|
||||
int idWell,
|
||||
FileReportRequest request,
|
||||
CancellationToken cancellationToken);
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
using AsbCloudApp.Data.SAUB;
|
||||
using Refit;
|
||||
|
||||
namespace AsbCloudWebApi.IntegrationTests.Clients;
|
||||
public interface ITelemetryControllerClient
|
||||
{
|
||||
private const string BaseRoute = "/api/telemetry";
|
||||
|
||||
[Get($"{BaseRoute}/Active")]
|
||||
Task<IApiResponse> GetTelemetriesInfoByLastData(CancellationToken token);
|
||||
|
||||
[Post($"{BaseRoute}/{{uid}}/info")]
|
||||
Task<IApiResponse> PostInfoAsync(string uid, [Body] TelemetryInfoDto info, CancellationToken token);
|
||||
|
||||
[Post($"{BaseRoute}/{{uid}}/message")]
|
||||
Task<IApiResponse> PostMessagesAsync(string uid, [Body] IEnumerable<TelemetryMessageDto> dtos, CancellationToken token);
|
||||
|
||||
[Post($"{BaseRoute}/{{uid}}/event")]
|
||||
Task<IApiResponse> PostEventsAsync(string uid, [Body] IEnumerable<EventDto> dtos, CancellationToken token);
|
||||
|
||||
[Post($"{BaseRoute}/{{uid}}/user")]
|
||||
Task<IApiResponse> PostUsersAsync(string uid, [Body] IEnumerable<TelemetryUserDto> dtos, CancellationToken token);
|
||||
}
|
12
AsbCloudWebApi.IntegrationTests/Clients/IWellClient.cs
Normal file
12
AsbCloudWebApi.IntegrationTests/Clients/IWellClient.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using AsbCloudApp.Data;
|
||||
using Refit;
|
||||
|
||||
namespace AsbCloudWebApi.IntegrationTests.Clients;
|
||||
|
||||
public interface IWellClient
|
||||
{
|
||||
private const string BaseRoute = "/api/well";
|
||||
|
||||
[Get(BaseRoute)]
|
||||
Task<IApiResponse<IEnumerable<WellDto>>> GetWellsAsync();
|
||||
}
|
@ -1,9 +1,6 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Requests;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudWebApi.IntegrationTests.Clients;
|
||||
using AsbCloudWebApi.IntegrationTests.Data;
|
||||
using System;
|
||||
using Xunit;
|
||||
|
||||
namespace AsbCloudWebApi.IntegrationTests.Controllers;
|
||||
|
@ -0,0 +1,77 @@
|
||||
using AsbCloudApp.Data.SAUB;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudWebApi.IntegrationTests.Clients;
|
||||
using Xunit;
|
||||
|
||||
namespace AsbCloudWebApi.IntegrationTests.Controllers;
|
||||
|
||||
public class DrillTestControllerTest : BaseIntegrationTest
|
||||
{
|
||||
private readonly IDrillTestControllerClient client;
|
||||
static readonly string uid = DateTime.UtcNow.ToString("yyyyMMdd_HHmmssfff");
|
||||
private static readonly SimpleTimezone timezone = new() { TimezoneId = "a", Hours = 5 };
|
||||
private static readonly Telemetry telemetry = new Telemetry() { Id = 1, RemoteUid = uid, TimeZone = timezone, Info = new() };
|
||||
private readonly IEnumerable<DrillTestBaseDto> drillTests = [new DrillTestBaseDto {
|
||||
DepthStart = 12,
|
||||
Id = 1,
|
||||
Params = [ new DrillTestParamsDto() {
|
||||
DepthDrillStep = 1,
|
||||
DepthSpeed = 2,
|
||||
Speed = 3,
|
||||
Step = 4,
|
||||
TimeDrillStep = 5,
|
||||
Workload = 6,
|
||||
}, new DrillTestParamsDto() {
|
||||
DepthDrillStep = 7,
|
||||
DepthSpeed = 8,
|
||||
Speed = 9,
|
||||
Step = 10,
|
||||
TimeDrillStep = 11,
|
||||
Workload = 12,
|
||||
}],
|
||||
TimeStampStart = DateTimeOffset.UtcNow.ToOffset(TimeSpan.FromHours(5))
|
||||
}];
|
||||
|
||||
public DrillTestControllerTest(WebAppFactoryFixture factory)
|
||||
: base(factory)
|
||||
{
|
||||
client = factory.GetAuthorizedHttpClient<IDrillTestControllerClient>(string.Empty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PostDataAsync()
|
||||
{
|
||||
// arrange
|
||||
dbContext.CleanupDbSet<DrillTest>();
|
||||
dbContext.CleanupDbSet<Telemetry>();
|
||||
dbContext.Set<Telemetry>().Add(telemetry);
|
||||
dbContext.SaveChanges();
|
||||
|
||||
// act
|
||||
var response = await client.PostDataAsync(uid, drillTests, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode);
|
||||
var count = dbContext.Set<DrillTest>().Count();
|
||||
Assert.Equal(1, count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PostDataAsync_twice_should_be_ok()
|
||||
{
|
||||
// arrange
|
||||
dbContext.CleanupDbSet<DrillTest>();
|
||||
dbContext.CleanupDbSet<Telemetry>();
|
||||
dbContext.Set<Telemetry>().Add(telemetry);
|
||||
dbContext.SaveChanges();
|
||||
|
||||
// act
|
||||
_ = await client.PostDataAsync(uid, drillTests, CancellationToken.None);
|
||||
var response = await client.PostDataAsync(uid, drillTests, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode);
|
||||
var count = dbContext.Set<DrillTest>().Count();
|
||||
Assert.Equal(1, count);
|
||||
}
|
||||
}
|
@ -0,0 +1,233 @@
|
||||
using AsbCloudApp.Data.SAUB;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudWebApi.IntegrationTests.Clients;
|
||||
using Xunit;
|
||||
|
||||
namespace AsbCloudWebApi.IntegrationTests.Controllers;
|
||||
public class TelemetryControllerTest : BaseIntegrationTest
|
||||
{
|
||||
private ITelemetryControllerClient client;
|
||||
static readonly string uid = DateTime.UtcNow.ToString("yyyyMMdd_HHmmssfff");
|
||||
|
||||
private static readonly SimpleTimezone timezone = new() {TimezoneId = "a", Hours = 5 };
|
||||
private static readonly Telemetry telemetry = new Telemetry() {Id = 1, RemoteUid = uid, TimeZone = timezone, Info = new() };
|
||||
private readonly IEnumerable<EventDto> events = [new() { Id = 1, EventType = 1, IdCategory = 1, IdSound = 1, Message = "there is no spoon {tag1}", Tag = "tag1" }];
|
||||
private readonly IEnumerable<TelemetryUserDto> users = [new TelemetryUserDto() { Id = 1, Level = 0, Name = "Neo", Patronymic = "Kianovich", Surname = "Theone" }];
|
||||
private readonly IEnumerable<TelemetryMessageDto> messages = [new TelemetryMessageDto() { Id = 100, IdEvent = 1, WellDepth = 5, Date = DateTimeOffset.Now.ToOffset(TimeSpan.FromHours(5)), Arg0 = "3.14", IdTelemetryUser = 1 }];
|
||||
private readonly IEnumerable<TelemetryDataSaub> telemetryDataSaubEntities = [new TelemetryDataSaub()
|
||||
{
|
||||
IdTelemetry = telemetry.Id,
|
||||
DateTime = DateTimeOffset.UtcNow,
|
||||
AxialLoad = 2,
|
||||
WellDepth = 5,
|
||||
BitDepth = 5,
|
||||
BlockPosition = 5,
|
||||
BlockSpeed = 5,
|
||||
}];
|
||||
private readonly TelemetryInfoDto telemetryInfoDto = new()
|
||||
{
|
||||
TimeZoneId = timezone.TimezoneId,
|
||||
TimeZoneOffsetTotalHours = timezone.Hours,
|
||||
Cluster = "cluster1",
|
||||
};
|
||||
|
||||
public TelemetryControllerTest(WebAppFactoryFixture factory)
|
||||
: base(factory)
|
||||
{
|
||||
client = factory.GetAuthorizedHttpClient<ITelemetryControllerClient>(string.Empty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetTelemetriesInfoByLastData()
|
||||
{
|
||||
// Arrange
|
||||
dbContext.CleanupDbSet<Telemetry>();
|
||||
dbContext.Set<Telemetry>().Add(telemetry);
|
||||
dbContext.Set<TelemetryDataSaub>().AddRange(telemetryDataSaubEntities);
|
||||
dbContext.SaveChanges();
|
||||
|
||||
// Act
|
||||
var response = await client.GetTelemetriesInfoByLastData(CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PostInfoAsync()
|
||||
{
|
||||
// arrange
|
||||
dbContext.CleanupDbSet<Telemetry>();
|
||||
|
||||
// act
|
||||
var response = await client.PostInfoAsync(uid, telemetryInfoDto, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode);
|
||||
var telemetriesCount = dbContext.Set<Telemetry>().Count();
|
||||
|
||||
Assert.Equal(1, telemetriesCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PostInfoAsync_twice_should_be_ok()
|
||||
{
|
||||
// arrange
|
||||
dbContext.CleanupDbSet<Telemetry>();
|
||||
|
||||
// act
|
||||
_ = await client.PostInfoAsync(uid, telemetryInfoDto, CancellationToken.None);
|
||||
var response = await client.PostInfoAsync(uid, telemetryInfoDto, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode);
|
||||
var telemetriesCount = dbContext.Set<Telemetry>().Count();
|
||||
|
||||
Assert.Equal(1, telemetriesCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PostUsersAsync()
|
||||
{
|
||||
// arrange
|
||||
dbContext.CleanupDbSet<Telemetry>();
|
||||
dbContext.Set<Telemetry>().Add(telemetry);
|
||||
dbContext.SaveChanges();
|
||||
|
||||
// act
|
||||
var response = await client.PostUsersAsync(uid, users, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode);
|
||||
var telemetriesCount = dbContext.Set<Telemetry>().Count();
|
||||
var telemetryUserCount = dbContext.Set<TelemetryUser>().Count();
|
||||
|
||||
Assert.Equal(1, telemetriesCount);
|
||||
Assert.Equal(1, telemetryUserCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PostUsers_twice_should_be_ok()
|
||||
{
|
||||
// arrange
|
||||
dbContext.CleanupDbSet<TelemetryUser>();
|
||||
dbContext.CleanupDbSet<Telemetry>();
|
||||
dbContext.Set<Telemetry>().Add(telemetry);
|
||||
dbContext.SaveChanges();
|
||||
|
||||
// act
|
||||
_ = await client.PostUsersAsync(uid, users, CancellationToken.None);
|
||||
var response = await client.PostUsersAsync(uid, users, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode);
|
||||
var telemetriesCount = dbContext.Set<Telemetry>().Count();
|
||||
var telemetryUserCount = dbContext.Set<TelemetryUser>().Count();
|
||||
|
||||
Assert.Equal(1, telemetriesCount);
|
||||
Assert.Equal(1, telemetryUserCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PostEventsAsync()
|
||||
{
|
||||
// arrange
|
||||
dbContext.CleanupDbSet<TelemetryEvent>();
|
||||
dbContext.CleanupDbSet<Telemetry>();
|
||||
dbContext.Set<Telemetry>().Add(telemetry);
|
||||
dbContext.SaveChanges();
|
||||
|
||||
// act
|
||||
var response = await client.PostEventsAsync(uid, events, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode);
|
||||
var telemetriesCount = dbContext.Set<Telemetry>().Count();
|
||||
var telemetryEventCount = dbContext.Set<TelemetryEvent>().Count();
|
||||
|
||||
Assert.Equal(1, telemetriesCount);
|
||||
Assert.Equal(1, telemetryEventCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PostEventsAsync_twice_should_be_ok()
|
||||
{
|
||||
// arrange
|
||||
dbContext.CleanupDbSet<TelemetryEvent>();
|
||||
dbContext.CleanupDbSet<Telemetry>();
|
||||
dbContext.Set<Telemetry>().Add(telemetry);
|
||||
dbContext.SaveChanges();
|
||||
|
||||
// act
|
||||
_ = await client.PostEventsAsync(uid, events, CancellationToken.None);
|
||||
var response = await client.PostEventsAsync(uid, events, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode);
|
||||
var telemetriesCount = dbContext.Set<Telemetry>().Count();
|
||||
var telemetryEventCount = dbContext.Set<TelemetryEvent>().Count();
|
||||
|
||||
Assert.Equal(1, telemetriesCount);
|
||||
Assert.Equal(1, telemetryEventCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PostMessagesAsync()
|
||||
{
|
||||
// arrange
|
||||
dbContext.CleanupDbSet<TelemetryMessage>();
|
||||
dbContext.CleanupDbSet<TelemetryEvent>();
|
||||
dbContext.CleanupDbSet<TelemetryUser>();
|
||||
dbContext.CleanupDbSet<Telemetry>();
|
||||
|
||||
dbContext.Set<Telemetry>().Add(telemetry);
|
||||
dbContext.SaveChanges();
|
||||
|
||||
// act
|
||||
_ = await client.PostEventsAsync(uid, events, CancellationToken.None);
|
||||
_ = await client.PostUsersAsync(uid, users, CancellationToken.None);
|
||||
var response = await client.PostMessagesAsync(uid, messages, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode);
|
||||
var telemetriesCount = dbContext.Set<Telemetry>().Count();
|
||||
var telemetryEventCount = dbContext.Set<TelemetryEvent>().Count();
|
||||
var telemetryUserCount = dbContext.Set<TelemetryUser>().Count();
|
||||
var telemetryMessageCount = dbContext.Set<TelemetryMessage>().Count();
|
||||
|
||||
Assert.Equal(1, telemetriesCount);
|
||||
Assert.Equal(1, telemetryEventCount);
|
||||
Assert.Equal(1, telemetryUserCount);
|
||||
Assert.Equal(1, telemetryMessageCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PostMessagesAsync_twice_should_be_ok()
|
||||
{
|
||||
// arrange
|
||||
dbContext.CleanupDbSet<TelemetryMessage>();
|
||||
dbContext.CleanupDbSet<TelemetryEvent>();
|
||||
dbContext.CleanupDbSet<TelemetryUser>();
|
||||
dbContext.CleanupDbSet<Telemetry>();
|
||||
dbContext.Set<Telemetry>().Add(telemetry);
|
||||
dbContext.SaveChanges();
|
||||
|
||||
// act
|
||||
_ = await client.PostEventsAsync(uid, events, CancellationToken.None);
|
||||
_ = await client.PostUsersAsync(uid, users, CancellationToken.None);
|
||||
_ = await client.PostMessagesAsync(uid, messages, CancellationToken.None);
|
||||
var response = await client.PostMessagesAsync(uid, messages, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode);
|
||||
var telemetriesCount = dbContext.Set<Telemetry>().Count();
|
||||
var telemetryEventCount = dbContext.Set<TelemetryEvent>().Count();
|
||||
var telemetryUserCount = dbContext.Set<TelemetryUser>().Count();
|
||||
var telemetryMessageCount = dbContext.Set<TelemetryMessage>().Count();
|
||||
|
||||
Assert.Equal(1, telemetriesCount);
|
||||
Assert.Equal(1, telemetryEventCount);
|
||||
Assert.Equal(1, telemetryUserCount);
|
||||
Assert.Equal(2, telemetryMessageCount);
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Data.WellOperation;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudInfrastructure;
|
||||
using AsbCloudWebApi.IntegrationTests.Clients;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Net;
|
||||
using Xunit;
|
||||
|
||||
namespace AsbCloudWebApi.IntegrationTests.Controllers;
|
||||
|
||||
public class WellControllerTest : BaseIntegrationTest
|
||||
{
|
||||
|
||||
private static readonly WellOperationDto wellOperationDto = new()
|
||||
{
|
||||
DateStart = DateTimeOffset.UtcNow,
|
||||
Day = 1,
|
||||
DepthEnd = 1000,
|
||||
DepthStart = 500,
|
||||
DurationHours = 5,
|
||||
Id = 1,
|
||||
IdCategory = 5095,
|
||||
IdPlan = null,
|
||||
IdType = 1,
|
||||
IdUser = 1,
|
||||
IdWell = 1,
|
||||
IdWellSectionType = 1,
|
||||
NptHours = 5
|
||||
};
|
||||
|
||||
private readonly IWellClient wellClient;
|
||||
private readonly IWellOperationClient wellOperationClient;
|
||||
|
||||
public WellControllerTest(WebAppFactoryFixture factory)
|
||||
: base(factory)
|
||||
{
|
||||
wellClient = factory.GetAuthorizedHttpClient<IWellClient>(string.Empty);
|
||||
wellOperationClient = factory.GetAuthorizedHttpClient<IWellOperationClient>(string.Empty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckDateStartForWell_returns_success()
|
||||
{
|
||||
//act
|
||||
var wellOperationDto1 = wellOperationDto.Adapt<WellOperationDto>();
|
||||
wellOperationDto1.DateStart = DateTimeOffset.UtcNow;
|
||||
wellOperationDto1.Id = 2;
|
||||
|
||||
var wellOperations = new List<WellOperationDto>() { wellOperationDto, wellOperationDto1 };
|
||||
var insertedRedult = await wellOperationClient.InsertRangeAsync(1, false, wellOperations);
|
||||
|
||||
var wellResponse = await wellClient.GetWellsAsync();
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.OK, wellResponse.StatusCode);
|
||||
Assert.NotNull(wellResponse.Content);
|
||||
|
||||
var expectedCount = await dbContext.Wells.CountAsync();
|
||||
Assert.Equal(expectedCount, wellResponse.Content.Count());
|
||||
|
||||
var actualFirstStartDate = wellResponse.Content.ElementAt(0).StartDate!.Value.ToUniversalTime();
|
||||
var expectedFirstStartDate = wellOperations.MinByOrDefault(o => o.DateStart)!.DateStart.ToUniversalTime();
|
||||
Assert.Equal(expectedFirstStartDate.ToString(), actualFirstStartDate.ToString());
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
@ -27,7 +27,7 @@ public class WellOperationControllerTest : BaseIntegrationTest
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Успешное добавление операций (без предварительной очистки данных)
|
||||
/// Óñïåøíîå äîáàâëåíèå îïåðàöèé (áåç ïðåäâàðèòåëüíîé î÷èñòêè äàííûõ)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Fact]
|
||||
@ -46,7 +46,7 @@ public class WellOperationControllerTest : BaseIntegrationTest
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Успешное добавление операций (с предварительной очисткой данных)
|
||||
/// Óñïåøíîå äîáàâëåíèå îïåðàöèé (ñ ïðåäâàðèòåëüíîé î÷èñòêîé äàííûõ)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Fact]
|
||||
@ -65,7 +65,7 @@ public class WellOperationControllerTest : BaseIntegrationTest
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Успешное обновление операций
|
||||
/// Óñïåøíîå îáíîâëåíèå îïåðàöèé
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Fact]
|
||||
@ -87,7 +87,7 @@ public class WellOperationControllerTest : BaseIntegrationTest
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение плановых операций
|
||||
/// Ïîëó÷åíèå ïëàíîâûõ îïåðàöèé
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Fact]
|
||||
@ -144,7 +144,7 @@ public class WellOperationControllerTest : BaseIntegrationTest
|
||||
IdWellSectionType = 2,
|
||||
IdCategory = WellOperationCategory.IdSlide,
|
||||
IdPlan = null,
|
||||
CategoryInfo = "Доп.инфо",
|
||||
CategoryInfo = "Äîï.èíôî",
|
||||
IdType = idType,
|
||||
DepthStart = 10.0,
|
||||
DepthEnd = 20.0,
|
||||
@ -201,7 +201,7 @@ public class WellOperationControllerTest : BaseIntegrationTest
|
||||
var stream = responseTemplate.Content;
|
||||
|
||||
using var workbook = new XLWorkbook(stream);
|
||||
var sheet = workbook.GetWorksheet("Справочники");
|
||||
var sheet = workbook.GetWorksheet("Ñïðàâî÷íèêè");
|
||||
|
||||
var count = sheet.RowsUsed().Count() - 1;
|
||||
|
||||
@ -230,6 +230,60 @@ public class WellOperationControllerTest : BaseIntegrationTest
|
||||
Assert.True(notExistedInDb.Count() == 0);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(WellOperation.IdOperationTypePlan)]
|
||||
[InlineData(WellOperation.IdOperationTypeFact)]
|
||||
public async Task GetPageOperationsAsyncWithDaysAndNpv_returns_success(int idType)
|
||||
{
|
||||
//arrange
|
||||
const int pageSize = 10;
|
||||
const int pageIndex = 0;
|
||||
|
||||
var well = await dbContext.Wells.FirstAsync();
|
||||
var entity1 = CreateWellOperation(well.Id);
|
||||
|
||||
var entity2 = entity1.Adapt<WellOperation>();
|
||||
entity2.DateStart = entity2.DateStart.AddDays(1);
|
||||
entity2.IdCategory = WellOperationCategory.IdEquipmentDrillingRepair;
|
||||
entity2.DurationHours = 2;
|
||||
|
||||
var entity3 = entity2.Adapt<WellOperation>();
|
||||
entity3.DateStart = entity3.DateStart.AddDays(1);
|
||||
entity3.IdCategory = WellOperationCategory.IdEquipmentDrillingRepair;
|
||||
entity3.DurationHours = 3;
|
||||
|
||||
dbContext.WellOperations.Add(entity1);
|
||||
dbContext.WellOperations.Add(entity2);
|
||||
dbContext.WellOperations.Add(entity3);
|
||||
|
||||
await dbContext.SaveChangesAsync();
|
||||
|
||||
var request = new WellOperationRequestBase
|
||||
{
|
||||
OperationType = WellOperation.IdOperationTypePlan,
|
||||
Skip = pageIndex,
|
||||
Take = pageSize,
|
||||
SortFields = [nameof(WellOperation.DateStart)]
|
||||
};
|
||||
|
||||
//act
|
||||
var response = await client.GetPageOperationsAsync(well.Id, request);
|
||||
|
||||
//assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.NotNull(response.Content);
|
||||
|
||||
var items = response.Content.Items.ToArray();
|
||||
|
||||
Assert.Equal(0, items[0].Day);
|
||||
Assert.Equal(1, items[1].Day);
|
||||
Assert.Equal(2, items[2].Day);
|
||||
|
||||
Assert.Equal(0, items[0].NptHours);
|
||||
Assert.Equal(2, items[1].NptHours);
|
||||
Assert.Equal(5, items[2].NptHours);
|
||||
}
|
||||
|
||||
private static WellOperation CreateWellOperation(int idWell, int idType = WellOperation.IdOperationTypePlan) =>
|
||||
new()
|
||||
{
|
||||
@ -237,7 +291,7 @@ public class WellOperationControllerTest : BaseIntegrationTest
|
||||
IdWellSectionType = 2,
|
||||
IdCategory = WellOperationCategory.IdSlide,
|
||||
IdPlan = null,
|
||||
CategoryInfo = "Доп.инфо",
|
||||
CategoryInfo = "Äîï.èíôî",
|
||||
LastUpdateDate = new DateTimeOffset(new DateTime(2023, 1, 10)).ToUniversalTime(),
|
||||
IdType = idType,
|
||||
DepthStart = 10.0,
|
||||
|
@ -21,7 +21,7 @@ public class WorkTest
|
||||
((ISupportRequiredService)serviceProviderMock).GetRequiredService(typeof(IServiceScopeFactory)).Returns(serviceScopeFactoryMock);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Fact, MethodImpl(MethodImplOptions.NoOptimization)]
|
||||
public async Task Start_ShouldReturn_Success()
|
||||
{
|
||||
//arrange
|
||||
@ -50,7 +50,7 @@ public class WorkTest
|
||||
Assert.InRange(lastState.ExecutionTime, TimeSpan.Zero, executionTime);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Fact, MethodImpl(MethodImplOptions.NoOptimization)]
|
||||
public async Task ExecutionWork_Invokes_Callback()
|
||||
{
|
||||
//arrange
|
||||
|
@ -43,26 +43,6 @@ namespace AsbCloudWebApi.Controllers
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получает список доступных пользователю месторождений (только скважины с параметрами бурения)
|
||||
/// </summary>
|
||||
/// <param name="token"> Токен отмены задачи </param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("drillParamsWells")]
|
||||
[Permission]
|
||||
[ProducesResponseType(typeof(IEnumerable<DepositDto>), (int)System.Net.HttpStatusCode.OK)]
|
||||
public async Task<IActionResult> GetDepositsDrillParamsAsync(CancellationToken token)
|
||||
{
|
||||
int? idCompany = User.GetCompanyId();
|
||||
|
||||
if (idCompany is null)
|
||||
return Forbid();
|
||||
|
||||
var result = await depositService.GetAllWithDrillParamsAsync((int)idCompany,
|
||||
token).ConfigureAwait(false);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получает список доступных пользователю кустов месторождения
|
||||
/// </summary>
|
||||
|
@ -16,6 +16,7 @@ using AsbCloudApp.Requests.ExportOptions;
|
||||
using AsbCloudApp.Requests.ParserOptions;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudInfrastructure.Services.WellOperations.Factories;
|
||||
using System.Linq;
|
||||
|
||||
namespace AsbCloudWebApi.Controllers;
|
||||
|
||||
@ -250,6 +251,35 @@ public class WellOperationController : ControllerBase
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаляет выбранные операции по скважине
|
||||
/// </summary>
|
||||
/// <param name="idWell">id скважины</param>
|
||||
/// <param name="ids">ids выбранных операций</param>
|
||||
/// <param name="token">Токен отмены задачи</param>
|
||||
/// <returns>Количество удаленных из БД строк</returns>
|
||||
[HttpDelete]
|
||||
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
|
||||
public async Task<IActionResult> DeleteRangeAsync([FromRoute] int idWell, IEnumerable<int> ids, CancellationToken token)
|
||||
{
|
||||
if (!await CanUserAccessToWellAsync(idWell, token))
|
||||
return Forbid();
|
||||
|
||||
if (!await CanUserEditWellOperationsAsync(idWell, token))
|
||||
return Forbid();
|
||||
|
||||
if (!ids.Any())
|
||||
return this.ValidationBadRequest(nameof(ids), "Пустой список операций");
|
||||
|
||||
var result = await wellOperationRepository.DeleteRangeAsync(ids, token);
|
||||
|
||||
if(result == ICrudRepository<WellOperationDto>.ErrorIdNotFound)
|
||||
return this.ValidationBadRequest(nameof(ids), "Минимум одна из операций не найдена в базе");
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Формирование excel файла с операциями на скважине
|
||||
/// </summary>
|
||||
|
@ -44,6 +44,9 @@ namespace AsbCloudWebApi.Middlewares
|
||||
}
|
||||
catch (Exception ex) // TODO: find explicit exception. Use Trace. Add body size to message.
|
||||
{
|
||||
if (context.Response.HasStarted)
|
||||
throw;
|
||||
|
||||
context.Response.Clear();
|
||||
context.Response.StatusCode = 500;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user