diff --git a/AsbCloudApp/Services/IOperationsStatService.cs b/AsbCloudApp/Services/IOperationsStatService.cs
index 1f9ed6a6..0861d8b1 100644
--- a/AsbCloudApp/Services/IOperationsStatService.cs
+++ b/AsbCloudApp/Services/IOperationsStatService.cs
@@ -36,14 +36,6 @@ namespace AsbCloudApp.Services
///
Task GetOrDefaultWellStatAsync(int idWell, CancellationToken token);
- ///
- /// Получить данные для графика TVD
- ///
- ///
- ///
- ///
- Task>> GetTvdAsync(int idWell, CancellationToken token);
-
///
/// Получить статистику по набору скважин
///
diff --git a/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs b/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs
index b1756101..3ac8e25e 100644
--- a/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs
+++ b/AsbCloudInfrastructure/Services/WellOperationService/OperationsStatService.cs
@@ -418,82 +418,6 @@ public class OperationsStatService : IOperationsStatService
return dDepth / (dHours + double.Epsilon);
}
- public async Task>> GetTvdAsync(int idWell, CancellationToken token)
- {
- var wellOperations = (await GetOperationsAsync(idWell, token)).ToArray();
- if (!wellOperations.Any())
- return Enumerable.Empty>();
-
- var tzOffsetHours = wellService.GetTimezone(idWell).Hours;
- var tvd = new List>(wellOperations.Length);
- var (Plan, Fact) = wellOperations.FirstOrDefault();
- var dateStart = Plan?.DateStart ?? Fact!.DateStart;
- int? iLastMatch = null;
- int iLastFact = 0;
- var nptHours = 0d;
-
- DateTimeOffset? firstDateStartFact = Fact!.DateStart;
- DateTimeOffset? firstDateStartPlan = Plan?.DateStart;
-
- for (int i = 0; i < wellOperations.Length; i++)
- {
- var item = wellOperations[i];
- var plan = item.Plan;
- var fact = item.Fact;
-
- var planFactPredict = new PlanFactPredictBase();
- if (plan is not null)
- {
- planFactPredict.Plan = Convert(plan, tzOffsetHours);
-
- if (!firstDateStartPlan.HasValue) {
- firstDateStartPlan = planFactPredict.Plan.DateStart;
- }
-
- planFactPredict.Plan.Day = (planFactPredict.Plan.DateStart - firstDateStartPlan.Value).TotalDays;
-
- if (fact is not null)
- iLastMatch = i;
- }
-
- if (fact is not null)
- {
- if(WellOperationCategory.NonProductiveTimeSubIds.Contains(fact.IdCategory))
- nptHours += fact.DurationHours;
-
- planFactPredict.Fact = Convert(fact, tzOffsetHours);
- planFactPredict.Fact.Day = (planFactPredict.Fact.DateStart - firstDateStartFact.Value).TotalDays;
-
- planFactPredict.Fact.NptHours = nptHours;
- iLastFact = i;
- }
-
- tvd.Add(planFactPredict);
- }
-
- if (iLastMatch is null || iLastMatch == wellOperations.Length - 1)
- return tvd;
-
- var lastMatchPlan = wellOperations[iLastMatch.Value].Plan!;
- var lastMatchPlanOperationEnd = lastMatchPlan.DateStart.AddHours(lastMatchPlan.DurationHours);
- var lastFact = wellOperations[iLastFact].Fact!;
- var lastFactDateEnd = lastFact.DateStart.AddHours(lastFact.DurationHours);
- var startOffset = lastFactDateEnd - lastMatchPlanOperationEnd;
-
- for (int i = iLastMatch.Value + 1; i < wellOperations.Length; i++)
- {
- if (wellOperations[i].Plan is null)
- continue;
- var predict = Convert(wellOperations[i].Plan!, tzOffsetHours);
- predict.IdType = 2;
- predict.DateStart = predict.DateStart + startOffset;
- predict.Day = (predict.DateStart - dateStart).TotalDays;
- tvd[i].Predict = predict;
- }
-
- return tvd;
- }
-
private async Task> GetOperationsAsync(int idWell, CancellationToken token)
{
var query = db.WellOperations
diff --git a/AsbCloudInfrastructure/Services/WellOperationService/ScheduleReportService.cs b/AsbCloudInfrastructure/Services/WellOperationService/ScheduleReportService.cs
index dc6495e0..aee3c9d1 100644
--- a/AsbCloudInfrastructure/Services/WellOperationService/ScheduleReportService.cs
+++ b/AsbCloudInfrastructure/Services/WellOperationService/ScheduleReportService.cs
@@ -15,7 +15,7 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
{
public class ScheduleReportService : IScheduleReportService
{
- private readonly IOperationsStatService operationsStatService;
+ private readonly IWellOperationService wellOperationService;
private readonly IWellService wellService;
const string sheetNameSchedule = "Сетевой график";
const string sheetNameSchedulePlan = "План";
@@ -24,15 +24,15 @@ namespace AsbCloudInfrastructure.Services.WellOperationService
const string sheetNameTvd = "ГГД";
const int maxChartsToWrap = 88;
- public ScheduleReportService(IOperationsStatService operationsStatService, IWellService wellService)
+ public ScheduleReportService(IWellOperationService wellOperationService, IWellService wellService)
{
- this.operationsStatService = operationsStatService;
+ this.wellOperationService = wellOperationService;
this.wellService = wellService;
}
public async Task MakeReportAsync(int idWell, CancellationToken token = default)
{
- var tvd = await operationsStatService.GetTvdAsync(idWell, token);
+ var tvd = await wellOperationService.GetTvdAsync(idWell, token);
var well = await wellService.GetOrDefaultAsync(idWell, token)
?? throw new ArgumentInvalidException(nameof(idWell), "idWell doesn`t exist");
diff --git a/AsbCloudWebApi.Tests/Services/WellOperationServiceTest.cs b/AsbCloudWebApi.Tests/Services/WellOperationServiceTest.cs
new file mode 100644
index 00000000..3927e9b0
--- /dev/null
+++ b/AsbCloudWebApi.Tests/Services/WellOperationServiceTest.cs
@@ -0,0 +1,135 @@
+using AsbCloudApp.Data;
+using AsbCloudApp.Data.WellOperation;
+using AsbCloudApp.Repositories;
+using AsbCloudApp.Requests;
+using AsbCloudApp.Services;
+using AsbCloudDb.Model;
+using AsbCloudInfrastructure.Repository;
+using AsbCloudInfrastructure.Services;
+using AsbCloudInfrastructure.Services.WellOperationService.WellOperationService;
+using Mapster;
+using NSubstitute;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace AsbCloudWebApi.Tests.Services;
+public class WellOperationServiceTest
+{
+ private const int idWell = 1;
+ private readonly IWellOperationService wellOperationServiceMock = Substitute.For();
+ private readonly IWellOperationRepository wellOperationRepositoryMock = Substitute.For();
+ private readonly IWellService wellServiceMock = Substitute.For();
+ private readonly IWellOperationCategoryRepository wellOperationCategoryRepositoryMock = Substitute.For();
+
+ private readonly SimpleTimezoneDto timeZone = new SimpleTimezoneDto()
+ {
+ Hours = 5,
+ };
+ private readonly WellOperationBaseDto wellOperation = new WellOperationBaseDto()
+ {
+ IdWell = idWell,
+ Id = 1,
+ IdType = WellOperation.IdOperationTypeFact,
+ DepthStart = 1,
+ DepthEnd = 2,
+ DateStart = DateTimeOffset.UtcNow,
+ DurationHours = 3,
+ IdCategory = WellOperationCategory.NonProductiveTimeSubIds.FirstOrDefault(),
+ IdWellSectionType = 1
+ };
+ private readonly List wellOperations = new List();
+
+ private readonly IEnumerable> tvds = new List>()
+ {
+ new PlanFactPredictBase()
+ {
+ Fact = new WellOperationDto(),
+ Plan = new WellOperationDto(),
+ Predict = new WellOperationDto()
+ }
+ };
+
+
+ public WellOperationServiceTest()
+ {
+ //wellOperationServiceMock.GetTvdAsync(Arg.Any(), Arg.Any())
+ // .Returns(tvds);
+ wellServiceMock
+ .GetTimezone(Arg.Any())
+ .Returns(timeZone);
+
+ //фактическая операция, у которой нет плановой для сопоставления
+ var wellOperation1 = wellOperation.Adapt();
+
+ //фактическая операция, у которой есть плановая для сопоставления
+ var wellOperation2 = wellOperation1.Adapt();
+ wellOperation2.Id = wellOperation1.Id + 1;
+ wellOperation2.IdPlan = wellOperation1.Id;
+ wellOperation2.IdType = WellOperation.IdOperationTypeFact;
+ wellOperation2.DateStart = wellOperation1.DateStart.AddDays(1);
+
+ //плановая операция
+ var wellOperation3 = wellOperation1.Adapt();
+ wellOperation3.Id = wellOperation1.Id + 2;
+ wellOperation3.IdType = WellOperation.IdOperationTypePlan;
+ wellOperation3.DateStart = wellOperation1.DateStart.AddDays(2);
+
+ wellOperations.Add(wellOperation1);
+ wellOperations.Add(wellOperation2);
+ wellOperations.Add(wellOperation3);
+
+ wellOperationRepositoryMock.GetAll(Arg.Any(), Arg.Any())
+ .Returns(wellOperations);
+ wellOperationServiceMock = new WellOperationService(wellServiceMock, wellOperationRepositoryMock, wellOperationCategoryRepositoryMock);
+ }
+
+ [Fact]
+ public async Task GetTvdAsync_ShouldReturn_Success()
+ {
+ var factOperations = wellOperations
+ .Where(o => o.IdType == WellOperation.IdOperationTypeFact);
+
+ //act
+ var data = await wellOperationServiceMock.GetTvdAsync(idWell, CancellationToken.None);
+
+ var actualFactNptHours = data
+ .Where(o => o.Fact != null)
+ .Select(o => o.Fact!.NptHours)
+ .ToArray();
+
+ var factOperationsWithNpt = factOperations
+ .Where(o => WellOperationCategory.NonProductiveTimeSubIds.Contains(o.IdCategory));
+
+ var expectedFactNptHours = factOperations
+ .Select(dto =>
+ {
+ var nptHours = factOperationsWithNpt
+ .Where(o => o.DateStart <= dto.DateStart)
+ .Sum(e => e.DurationHours);
+ return nptHours;
+ });
+
+ var actualFactDays = data
+ .Where(o => o.Fact != null)
+ .Select(o => o.Fact!.Day)
+ .ToArray();
+
+ var firstWellOperation = factOperations.MinBy(e => e.DateStart)!;
+
+ var expectedFactDays = factOperations
+ .Select(dto =>
+ {
+ var day = (dto.DateStart - firstWellOperation.DateStart).TotalDays;
+ return day;
+ });
+
+ //assert
+ Assert.Equal(expectedFactNptHours, actualFactNptHours);
+ Assert.Equal(expectedFactDays, actualFactDays);
+ }
+}