forked from ddrilling/AsbCloudServer
Удержание в клиньях получение статистики
1. Добавлены интеграционные тесты 2. Добавлены TODO дял дальнейшего рефакторинга 3. Сделан небольшой рефакторинг метода получения статистики по удержанию в клиньях
This commit is contained in:
parent
6045333f53
commit
c1729d06c7
@ -7,21 +7,25 @@ namespace AsbCloudApp.Requests
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class OperationStatRequest
|
public class OperationStatRequest
|
||||||
{
|
{
|
||||||
|
//TODO: использовать DateOnly. Поправить naming
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Дата начала операции в UTC
|
/// Дата начала операции в UTC
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime? DateStartUTC { get; set; }
|
public DateTime? DateStartUTC { get; set; }
|
||||||
|
|
||||||
|
//TODO: использовать DateOnly. Поправить naming
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Дата окончания операции в UTC
|
/// Дата окончания операции в UTC
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime? DateEndUTC { get; set; }
|
public DateTime? DateEndUTC { get; set; }
|
||||||
|
|
||||||
|
//TODO: поправить naming
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Минимальная продолжительность операции, мин
|
/// Минимальная продолжительность операции, мин
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double? DurationMinutesMin { get; set; }
|
public double? DurationMinutesMin { get; set; }
|
||||||
|
|
||||||
|
//TODO: поправить naming
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Максимальная продолжительность операции, мин
|
/// Максимальная продолжительность операции, мин
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -78,11 +78,14 @@ public class SlipsStatService : ISlipsStatService
|
|||||||
.Where(o => o.IdCategory == WellOperationCategory.IdSlipsTime)
|
.Where(o => o.IdCategory == WellOperationCategory.IdSlipsTime)
|
||||||
.AsNoTracking();
|
.AsNoTracking();
|
||||||
|
|
||||||
if (request.DateStartUTC.HasValue && request.DateEndUTC.HasValue)
|
if (request.DateStartUTC.HasValue)
|
||||||
detectedOperationsQuery = detectedOperationsQuery
|
detectedOperationsQuery = detectedOperationsQuery
|
||||||
.Where(o => o.DateStart < request.DateEndUTC)
|
|
||||||
.Where(o => o.DateEnd > request.DateStartUTC);
|
.Where(o => o.DateEnd > request.DateStartUTC);
|
||||||
|
|
||||||
|
if (request.DateEndUTC.HasValue)
|
||||||
|
detectedOperationsQuery = detectedOperationsQuery
|
||||||
|
.Where(o => o.DateStart < request.DateEndUTC);
|
||||||
|
|
||||||
if (request.DurationMinutesMin.HasValue)
|
if (request.DurationMinutesMin.HasValue)
|
||||||
{
|
{
|
||||||
var durationMinutesMin = TimeSpan.FromMinutes(request.DurationMinutesMin.Value);
|
var durationMinutesMin = TimeSpan.FromMinutes(request.DurationMinutesMin.Value);
|
||||||
@ -105,11 +108,13 @@ public class SlipsStatService : ISlipsStatService
|
|||||||
Operation = o,
|
Operation = o,
|
||||||
IdWell = telemetries[o.IdTelemetry],
|
IdWell = telemetries[o.IdTelemetry],
|
||||||
schedules.FirstOrDefault(s =>
|
schedules.FirstOrDefault(s =>
|
||||||
s.IdWell == telemetries[o.IdTelemetry]
|
s.IdWell == telemetries[o.IdTelemetry] &&
|
||||||
&& s.DrillStart <= o.DateStart
|
s.DrillStart <= o.DateStart &&
|
||||||
&& s.DrillEnd >= o.DateStart
|
s.DrillEnd > o.DateStart && (
|
||||||
&& new TimeDto(s.ShiftStart) <= new TimeDto(o.DateStart.DateTime)
|
s.ShiftStart > s.ShiftEnd
|
||||||
&& new TimeDto(s.ShiftEnd) >= new TimeDto(o.DateStart.DateTime))
|
) ^ (s.ShiftStart <= new TimeDto(o.DateStart.DateTime).MakeTimeOnly() &&
|
||||||
|
s.ShiftEnd > new TimeDto(o.DateStart.DateTime).MakeTimeOnly()
|
||||||
|
))
|
||||||
?.Driller,
|
?.Driller,
|
||||||
Section = sections.FirstOrDefault(s =>
|
Section = sections.FirstOrDefault(s =>
|
||||||
s.IdWell == telemetries[o.IdTelemetry]
|
s.IdWell == telemetries[o.IdTelemetry]
|
||||||
@ -133,20 +138,21 @@ public class SlipsStatService : ISlipsStatService
|
|||||||
{
|
{
|
||||||
Operation = o,
|
Operation = o,
|
||||||
schedules.FirstOrDefault(s =>
|
schedules.FirstOrDefault(s =>
|
||||||
s.IdWell == o.IdWell
|
s.IdWell == o.IdWell &&
|
||||||
&& s.DrillStart <= o.DateStart
|
s.DrillStart <= o.DateStart &&
|
||||||
&& s.DrillEnd >= o.DateStart
|
s.DrillEnd > o.DateStart && (
|
||||||
&& new TimeDto(s.ShiftStart) <= new TimeDto(o.DateStart.DateTime)
|
s.ShiftStart > s.ShiftEnd
|
||||||
&& new TimeDto(s.ShiftEnd) >= new TimeDto(o.DateStart.DateTime))
|
) ^ (s.ShiftStart <= new TimeDto(o.DateStart.DateTime).MakeTimeOnly() &&
|
||||||
|
s.ShiftEnd > new TimeDto(o.DateStart.DateTime).MakeTimeOnly()
|
||||||
|
))
|
||||||
?.Driller,
|
?.Driller,
|
||||||
})
|
})
|
||||||
.Where(o => o.Driller != null)
|
.Where(o => o.Driller != null)
|
||||||
.GroupBy(o => new { o.Driller!.Id, o.Operation.IdWellSectionType });
|
.GroupBy(o => new { o.Driller!.Id, o.Operation.IdWellSectionType });
|
||||||
|
|
||||||
|
|
||||||
var stats = detectedOperationsGroupedByDrillerAndSection.Select(group => new SlipsStatDto
|
var stats = detectedOperationsGroupedByDrillerAndSection.Select(group => new SlipsStatDto
|
||||||
{
|
{
|
||||||
DrillerName = $"{group.First().Driller!.Name} {group.First().Driller!.Patronymic} {group.First().Driller!.Surname}",
|
DrillerName = $"{group.First().Driller!.Surname} {group.First().Driller!.Name} {group.First().Driller!.Patronymic}",
|
||||||
SlipsCount = group.Count(),
|
SlipsCount = group.Count(),
|
||||||
SlipsTimeInMinutes = group
|
SlipsTimeInMinutes = group
|
||||||
.Sum(y => (y.Operation.DateEnd - y.Operation.DateStart).TotalMinutes),
|
.Sum(y => (y.Operation.DateEnd - y.Operation.DateStart).TotalMinutes),
|
||||||
|
13
AsbCloudWebApi.IntegrationTests/Clients/ISlipsTimeClient.cs
Normal file
13
AsbCloudWebApi.IntegrationTests/Clients/ISlipsTimeClient.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
|
using Refit;
|
||||||
|
|
||||||
|
namespace AsbCloudWebApi.IntegrationTests.Clients;
|
||||||
|
|
||||||
|
public interface ISlipsTimeClient
|
||||||
|
{
|
||||||
|
private const string BaseRoute = "/api/slipsStat";
|
||||||
|
|
||||||
|
[Get(BaseRoute)]
|
||||||
|
Task<IApiResponse<IEnumerable<SlipsStatDto>>> GetAll([Query] OperationStatRequest request);
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
|
using AsbCloudDb.Model;
|
||||||
|
using AsbCloudWebApi.IntegrationTests.Clients;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace AsbCloudWebApi.IntegrationTests.Controllers;
|
||||||
|
|
||||||
|
public class SlipsStatControllerTest : BaseIntegrationTest
|
||||||
|
{
|
||||||
|
private static readonly Schedule schedule = new()
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
IdDriller = Data.Defaults.Drillers[0].Id,
|
||||||
|
IdWell = Data.Defaults.Wells[0].Id,
|
||||||
|
ShiftStart = new TimeOnly(8, 0, 0),
|
||||||
|
ShiftEnd = new TimeOnly(20, 0, 0),
|
||||||
|
DrillStart = new DateTimeOffset(new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc)),
|
||||||
|
DrillEnd = new DateTimeOffset(new DateTime(2024, 2, 1, 0, 0, 0, DateTimeKind.Utc))
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly DetectedOperation detectedOperation = new()
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
IdTelemetry = Data.Defaults.Telemetries[0].Id,
|
||||||
|
IdCategory = WellOperationCategory.IdSlipsTime,
|
||||||
|
DateStart = new DateTimeOffset(new DateTime(2024, 1, 23, 15, 0, 0, 0, DateTimeKind.Utc)),
|
||||||
|
DateEnd = new DateTimeOffset(new DateTime(2024, 1, 23, 15, 2, 0, 0, DateTimeKind.Utc)),
|
||||||
|
ExtraData = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "test", 5 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly WellOperation factWellOperation = new()
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
IdWell = Data.Defaults.Wells[0].Id,
|
||||||
|
IdWellSectionType = 1,
|
||||||
|
IdCategory = WellOperationCategory.IdRotor,
|
||||||
|
IdType = WellOperation.IdOperationTypeFact,
|
||||||
|
DepthStart = 0,
|
||||||
|
DepthEnd = 100,
|
||||||
|
LastUpdateDate = DateTimeOffset.UtcNow,
|
||||||
|
DateStart = new DateTimeOffset(new DateTime(2024, 1, 15, 15, 0, 0, DateTimeKind.Utc)),
|
||||||
|
DurationHours = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly ISlipsTimeClient slipsTimeClient;
|
||||||
|
|
||||||
|
public SlipsStatControllerTest(WebAppFactoryFixture factory)
|
||||||
|
: base(factory)
|
||||||
|
{
|
||||||
|
slipsTimeClient = factory.GetAuthorizedHttpClient<ISlipsTimeClient>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetAll_returns_success()
|
||||||
|
{
|
||||||
|
//arrange
|
||||||
|
dbContext.Schedule.Add(schedule);
|
||||||
|
dbContext.DetectedOperations.Add(detectedOperation);
|
||||||
|
dbContext.WellOperations.Add(factWellOperation);
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
var request = new OperationStatRequest
|
||||||
|
{
|
||||||
|
DateStartUTC = schedule.DrillStart.DateTime,
|
||||||
|
DateEndUTC = schedule.DrillEnd.DateTime,
|
||||||
|
DurationMinutesMin = 0,
|
||||||
|
DurationMinutesMax = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
var dtoExpected = new SlipsStatDto
|
||||||
|
{
|
||||||
|
DrillerName = $"{Data.Defaults.Drillers[0].Surname} {Data.Defaults.Drillers[0].Name} {Data.Defaults.Drillers[0].Patronymic}",
|
||||||
|
WellCount = 1,
|
||||||
|
SectionCaption = "Пилотный ствол",
|
||||||
|
SlipsCount = 1,
|
||||||
|
SlipsTimeInMinutes = (detectedOperation.DateEnd - detectedOperation.DateStart).TotalMinutes,
|
||||||
|
SectionDepth = factWellOperation.DepthEnd - factWellOperation.DepthStart,
|
||||||
|
};
|
||||||
|
|
||||||
|
//act
|
||||||
|
var response = await slipsTimeClient.GetAll(request);
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.NotNull(response.Content);
|
||||||
|
Assert.Single(response.Content);
|
||||||
|
|
||||||
|
var dtoActual = response.Content.First();
|
||||||
|
MatchHelper.Match(dtoExpected, dtoActual);
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,16 @@ namespace AsbCloudWebApi.IntegrationTests.Data
|
|||||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2211:Поля, не являющиеся константами, не должны быть видимыми", Justification = "<Ожидание>")]
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2211:Поля, не являющиеся константами, не должны быть видимыми", Justification = "<Ожидание>")]
|
||||||
public static class Defaults
|
public static class Defaults
|
||||||
{
|
{
|
||||||
|
public static Driller[] Drillers = new Driller[]
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
Name = "test",
|
||||||
|
Surname = "test"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public static Deposit[] Deposits = new Deposit[] {
|
public static Deposit[] Deposits = new Deposit[] {
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
@ -32,6 +42,19 @@ namespace AsbCloudWebApi.IntegrationTests.Data
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static Telemetry[] Telemetries = new Telemetry[]
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
RemoteUid = "555-555-555",
|
||||||
|
TimeZone = new SimpleTimezone
|
||||||
|
{
|
||||||
|
Hours = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public static Well[] Wells = new Well[] {
|
public static Well[] Wells = new Well[] {
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
@ -42,7 +65,7 @@ namespace AsbCloudWebApi.IntegrationTests.Data
|
|||||||
Caption = "Well1",
|
Caption = "Well1",
|
||||||
Latitude = 10,
|
Latitude = 10,
|
||||||
Longitude = 20,
|
Longitude = 20,
|
||||||
IdTelemetry = null,
|
IdTelemetry = Telemetries[0].Id,
|
||||||
Timezone = new SimpleTimezone{
|
Timezone = new SimpleTimezone{
|
||||||
Hours = 1
|
Hours = 1
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ using Bogus;
|
|||||||
|
|
||||||
namespace AsbCloudWebApi.IntegrationTests.TestFakers;
|
namespace AsbCloudWebApi.IntegrationTests.TestFakers;
|
||||||
|
|
||||||
|
//TODO: выпилить
|
||||||
public static class EntitiesFaker
|
public static class EntitiesFaker
|
||||||
{
|
{
|
||||||
public static Faker<Deposit> Deposit { get; } = new Faker<Deposit>()
|
public static Faker<Deposit> Deposit { get; } = new Faker<Deposit>()
|
||||||
|
@ -60,6 +60,8 @@ public class WebAppFactoryFixture : WebApplicationFactory<Startup>,
|
|||||||
dbContext.AddRange(Data.Defaults.Clusters);
|
dbContext.AddRange(Data.Defaults.Clusters);
|
||||||
dbContext.AddRange(Data.Defaults.Wells);
|
dbContext.AddRange(Data.Defaults.Wells);
|
||||||
dbContext.AddRange(Data.Defaults.RelationsCompanyWell);
|
dbContext.AddRange(Data.Defaults.RelationsCompanyWell);
|
||||||
|
dbContext.AddRange(Data.Defaults.Telemetries);
|
||||||
|
dbContext.AddRange(Data.Defaults.Drillers);
|
||||||
await dbContext.SaveChangesAsync();
|
await dbContext.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user