Merge branch 'dev' into feature/change-log-refactoring

This commit is contained in:
on.nemtina 2024-05-20 14:12:06 +05:00
commit 6af038496c
31 changed files with 1217 additions and 563 deletions

View File

@ -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>

View File

@ -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);
}
}

View File

@ -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; }
}

View File

@ -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)

View File

@ -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;
}
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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

View File

@ -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
{

View File

@ -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);
}

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}

View 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();
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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,

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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;