diff --git a/AsbCloudApp/Services/DailyReport/IDailyReportService.cs b/AsbCloudApp/Services/DailyReport/IDailyReportService.cs
index c07a5c06..44283a44 100644
--- a/AsbCloudApp/Services/DailyReport/IDailyReportService.cs
+++ b/AsbCloudApp/Services/DailyReport/IDailyReportService.cs
@@ -3,42 +3,36 @@ using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Data.DailyReport;
-using AsbCloudApp.Data.DailyReport.Blocks;
using AsbCloudApp.Requests;
namespace AsbCloudApp.Services.DailyReport;
+///
+/// Суточные отчёты
+///
public interface IDailyReportService
{
///
- /// Создать отчёт
+ /// Обновить или создать суточный отчёт
///
- ///
- ///
- ///
- ///
- Task InsertAsync(int idWell, DateTime dateStart, CancellationToken cancellationToken);
-
- ///
- /// Обновить блок
- ///
- ///
+ ///
///
///
///
- ///
+ ///
///
- Task UpdateBlockAsync(int idDailyReport, int idUser, TBlock editableBlock, CancellationToken cancellationToken)
- where TBlock : EditableBlock;
+ Task UpdateOrInsertAsync(int idWell, DateTime dateDailyReport, int idUser, TBlock editableBlock,
+ CancellationToken cancellationToken)
+ where TBlock : ItemInfoDto;
///
/// Получить сформированный суточный отчёт
///
///
- ///
+ ///
///
///
- Task GetAsync(int idWell, DateTime dateStart, CancellationToken cancellationToken);
+ Task GetAsync(int idWell, DateTime dateDailyReport, CancellationToken cancellationToken);
///
/// Получить список суточных отчётов по скважине
@@ -47,8 +41,7 @@ public interface IDailyReportService
///
///
///
- Task> GetAsync(int idWell, FileReportRequest request,
- CancellationToken cancellationToken);
+ Task> GetAsync(int idWell, FileReportRequest request, CancellationToken cancellationToken);
///
/// Получить диапазон дат по которым возможно сформировать суточный отчёты
diff --git a/AsbCloudInfrastructure/Repository/DailyReportRepository.cs b/AsbCloudInfrastructure/Repository/DailyReportRepository.cs
index 147cae3e..add98668 100644
--- a/AsbCloudInfrastructure/Repository/DailyReportRepository.cs
+++ b/AsbCloudInfrastructure/Repository/DailyReportRepository.cs
@@ -32,10 +32,16 @@ public class DailyReportRepository : CrudRepositoryBase d.IdWell == idWell);
if (request.GeDate.HasValue)
- query = query.Where(d => d.Date >= request.GeDate.Value.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc));
+ {
+ var geDate = request.GeDate.Value.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc);
+ query = query.Where(d => d.Date >= geDate);
+ }
if (request.LeDate.HasValue)
- query = query.Where(d => d.Date <= request.LeDate.Value.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc));
+ {
+ var leDate = request.LeDate.Value.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc);
+ query = query.Where(d => d.Date <= leDate);
+ }
if (request.SortFields?.Any() == true)
{
diff --git a/AsbCloudInfrastructure/Services/DailyReport/DailyReportExportService.cs b/AsbCloudInfrastructure/Services/DailyReport/DailyReportExportService.cs
index 6fbc0c12..53bb24f3 100644
--- a/AsbCloudInfrastructure/Services/DailyReport/DailyReportExportService.cs
+++ b/AsbCloudInfrastructure/Services/DailyReport/DailyReportExportService.cs
@@ -28,7 +28,7 @@ public class DailyReportExportService : IDailyReportExportService
private const int columnTimeBalanceDurationFact = 4;
private const int columnTimeBalanceReasonDeviation = 8;
private const int columnTimeBalanceDrillingDeviationPerSection = 10;
- private const int columnTimeBalanceDrillingDeviationPerDaily = 11;
+ private const int columnTimeBalanceDrillingDeviationPerDay = 11;
private const int columnSheduleDriller = 3;
private const int columnSheduleShiftStart = 7;
@@ -56,10 +56,9 @@ public class DailyReportExportService : IDailyReportExportService
private const string cellContractor = "C3";
private const string cellDeposit = "C5";
private const string cellCluster = "C6";
- private const string cellWellName = "C7";
+ private const string cellWellCaption = "C7";
private const string cellWellType = "C8";
- private const string cellDateStart = "C12";
- private const string cellDateEnd = "D12";
+ private const string cellDate = "C12";
private const string cellDepthStart = "C13";
private const string cellDepthEnd = "D13";
@@ -95,7 +94,7 @@ public class DailyReportExportService : IDailyReportExportService
var stream = await GenerateFileAsync(dailyReport, cancellationToken);
- var fileName = $"Суточный_рапорт_по_скважине_{dailyReport.WellName}_куст_{dailyReport.Cluster}_от_{dailyReport.DateStart:yy-MM-dd}.xlsx";
+ var fileName = $"Суточный_рапорт_по_скважине_{dailyReport.WellCaption}_куст_{dailyReport.Cluster}_от_{dailyReport.Date:yy-MM-dd}.xlsx";
return (fileName, stream);
}
@@ -127,10 +126,9 @@ public class DailyReportExportService : IDailyReportExportService
sheet.Cell(cellContractor).Value = dailyReport.Contractor;
sheet.Cell(cellDeposit).Value = dailyReport.Deposit;
sheet.Cell(cellCluster).Value = dailyReport.Cluster;
- sheet.Cell(cellWellName).Value = dailyReport.WellName;
+ sheet.Cell(cellWellCaption).Value = dailyReport.WellCaption;
sheet.Cell(cellWellType).Value = dailyReport.WellType;
- sheet.Cell(cellDateStart).Value = dailyReport.DateStart;
- sheet.Cell(cellDateEnd).Value = dailyReport.DateEnd;
+ sheet.Cell(cellDate).Value = dailyReport.Date;
sheet.Cell(cellDepthStart).Value = dailyReport.DepthStart;
sheet.Cell(cellDepthEnd).Value = dailyReport.DepthEnd;
@@ -163,18 +161,18 @@ public class DailyReportExportService : IDailyReportExportService
foreach (var wellOperation in timeBalanceBlock.WellOperations.OrderBy(w => w.IdWellOperation))
{
- sheet.Cell(rowCurrent, columnTimeBalanceDurationPlan).Value = wellOperation.DurationHours?.Plan;
- sheet.Cell(rowCurrent, columnTimeBalanceDurationFact).Value = wellOperation.DurationHours?.Fact;
+ sheet.Cell(rowCurrent, columnTimeBalanceDurationPlan).Value = wellOperation.DurationHours.Plan;
+ sheet.Cell(rowCurrent, columnTimeBalanceDurationFact).Value = wellOperation.DurationHours.Fact;
sheet.Cell(rowCurrent, columnTimeBalanceReasonDeviation).Value = wellOperation.ReasonDeviation;
sheet.Cell(rowCurrent, columnTimeBalanceDrillingDeviationPerSection).Value = wellOperation.DrillingDeviationPerSection;
- sheet.Cell(rowCurrent, columnTimeBalanceDrillingDeviationPerDaily).Value = wellOperation.DrillingDeviationPerDaily;
+ sheet.Cell(rowCurrent, columnTimeBalanceDrillingDeviationPerDay).Value = wellOperation.DrillingDeviationPerDay;
rowCurrent++;
}
sheet.Cell(cellTimeBalanceBlockSection).Value = timeBalanceBlock.SectionName;
- sheet.Cell(cellTimeBalanceBlockWellDepthPlan).Value = timeBalanceBlock.WellDepthPlan;
- sheet.Cell(cellTimeBalanceBlockWellDepthFact).Value = timeBalanceBlock.WellDepthFact;
+ sheet.Cell(cellTimeBalanceBlockWellDepthPlan).Value = timeBalanceBlock.WellDepth.Plan;
+ sheet.Cell(cellTimeBalanceBlockWellDepthFact).Value = timeBalanceBlock.WellDepth.Fact;
sheet.Cell(cellTimeBalanceBlockWellOperationSlipsTimeCount).Value = timeBalanceBlock.WellOperationSlipsTimeCount;
}
diff --git a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs
index 95d42411..97cc4e85 100644
--- a/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs
+++ b/AsbCloudInfrastructure/Services/DailyReport/DailyReportService.cs
@@ -52,31 +52,16 @@ public class DailyReportService : IDailyReportService
this.detectedOperationService = detectedOperationService;
}
- public async Task InsertAsync(int idWell, DateTime dateStart, CancellationToken cancellationToken)
- {
- if (await dailyReportRepository.AnyAsync(idWell, dateStart, cancellationToken))
- throw new ArgumentInvalidException(nameof(dateStart), "Суточный отчёт уже существует");
-
- var dailyReport = new DailyReportDto
- {
- IdWell = idWell,
- DateStart = dateStart,
- };
-
- return await dailyReportRepository.InsertAsync(dailyReport, cancellationToken);
- }
-
- public async Task UpdateBlockAsync(int idDailyReport, int idUser, TBlock editableBlock,
+ public async Task UpdateOrInsertAsync(int idWell, DateTime dateDailyReport, int idUser, TBlock editableBlock,
CancellationToken cancellationToken)
- where TBlock : EditableBlock
+ where TBlock : ItemInfoDto
{
- var dailyReport = await dailyReportRepository.GetOrDefaultAsync(idDailyReport, cancellationToken)
- ?? throw new ArgumentInvalidException(nameof(idDailyReport), $"Суточный отчёт с Id: {idDailyReport} не найден");
-
- editableBlock.IdUser = idUser;
-
- editableBlock.DateLastUpdate = DateTime.UtcNow;
- dailyReport.DateLastUpdate = DateTime.UtcNow;
+ var dailyReport = await dailyReportRepository.GetOrDefaultAsync(idWell, dateDailyReport, cancellationToken) ??
+ new DailyReportDto
+ {
+ IdWell = idWell,
+ Date = dateDailyReport
+ };
switch (editableBlock)
{
@@ -89,39 +74,46 @@ public class DailyReportService : IDailyReportService
case SignBlockDto signBlock:
dailyReport.SignBlock = signBlock;
break;
+ default:
+ throw new InvalidOperationException("Unexpected type of editableBlock");
}
+ editableBlock.IdUser = idUser;
+ editableBlock.LastUpdateDate = DateTime.UtcNow;
+
+ dailyReport.DateLastUpdate = DateTime.UtcNow;
+
+ if (dailyReport.Id == 0)
+ return await dailyReportRepository.InsertAsync(dailyReport, cancellationToken);
+
return await dailyReportRepository.UpdateAsync(dailyReport, cancellationToken);
}
- public async Task GetAsync(int idWell, DateTime dateStart, CancellationToken cancellationToken)
+ public async Task GetAsync(int idWell, DateTime dateDailyReport, CancellationToken cancellationToken)
{
var well = await wellService.GetOrDefaultAsync(idWell, cancellationToken);
if (well is null)
throw new ArgumentInvalidException($"Скважина с Id: {idWell} не найдена", nameof(idWell));
- var dailyReport = await dailyReportRepository.GetOrDefaultAsync(idWell, dateStart, cancellationToken) ?? new DailyReportDto
+ var dailyReport = await dailyReportRepository.GetOrDefaultAsync(idWell, dateDailyReport, cancellationToken) ?? new DailyReportDto
{
- DateStart = dateStart.Date,
+ Date = dateDailyReport.Date,
IdWell = well.Id
};
- var factWellOperations = await GetFactWellOperationsAsync(idWell, dailyReport.DateStart, dailyReport.DateEnd,
- cancellationToken);
+ var factWellOperations = (await GetFactWellOperationsAsync(idWell, dailyReport.Date, cancellationToken))
+ .OrderBy(o => o.DateStart)
+ .ThenBy(o => o.DepthStart);
- dailyReport.WellName = well.Caption;
+ dailyReport.WellCaption = well.Caption;
dailyReport.WellType = well.WellType;
dailyReport.Cluster = well.Cluster;
dailyReport.Deposit = well.Deposit;
dailyReport.Customer = well.Companies.FirstOrDefault(c => c.IdCompanyType == 1)?.Caption;
dailyReport.Contractor = well.Companies.FirstOrDefault(c => c.IdCompanyType == 2)?.Caption;
-
- if (factWellOperations.Any())
- {
- dailyReport.DepthStart = factWellOperations.Min(o => o.DepthStart);
- dailyReport.DepthEnd = factWellOperations.Max(o => o.DepthEnd);
- }
+ dailyReport.DepthStart = factWellOperations.FirstOrDefault()?.DepthStart;
+ dailyReport.DepthEnd = factWellOperations.LastOrDefault()?.DepthEnd;
await UpdateTimeBalanceBlockAsync(dailyReport, factWellOperations, cancellationToken);
await UpdateSubsystemBlockAsync(dailyReport, cancellationToken);
@@ -184,18 +176,18 @@ public class DailyReportService : IDailyReportService
{
for (var day = result.Skip; day - result.Skip < result.Take && datesRange.To.AddDays(-day) >= datesRange.From; day++)
{
- var dateStart = datesRange.To.AddDays(-day);
+ var dateDailyReport = datesRange.To.AddDays(-day).Date;
- AddDailyReport(dateStart);
+ AddDailyReport(dateDailyReport);
}
}
else
{
for (var day = result.Skip; day - result.Skip < result.Take && datesRange.From.AddDays(day) <= datesRange.To; day++)
{
- var dateStart = datesRange.From.AddDays(day);
+ var dateDailyReport = datesRange.From.AddDays(day).Date;
- AddDailyReport(dateStart);
+ AddDailyReport(dateDailyReport);
}
}
@@ -203,10 +195,9 @@ public class DailyReportService : IDailyReportService
return result;
- void AddDailyReport(DateTime dateStart)
+ void AddDailyReport(DateTime date)
{
- var existingDailyReport = existingDailyReports.FirstOrDefault(d => d.IdWell == idWell &&
- d.DateStart == dateStart);
+ var existingDailyReport = existingDailyReports.FirstOrDefault(d => d.IdWell == idWell && d.Date == date);
if (existingDailyReport is not null)
{
@@ -216,7 +207,7 @@ public class DailyReportService : IDailyReportService
dailyReports.Add(new DailyReportDto
{
- DateStart = dateStart,
+ Date = date,
IdWell = well.Id
});
}
@@ -224,16 +215,18 @@ public class DailyReportService : IDailyReportService
public async Task GetDatesRangeAsync(int idWell, CancellationToken cancellationToken)
{
- var factOperations = await GetFactWellOperationsAsync(idWell, null, null,
- cancellationToken);
+ var factOperations = await GetFactWellOperationsAsync(idWell, null, cancellationToken);
if (!factOperations.Any())
return null;
+ var minDateStart = factOperations.Min(o => o.DateStart);
+ var maxDateStart = factOperations.Max(o => o.DateStart);
+
return new DatesRangeDto
{
- From = factOperations.Min(o => o.DateStart).Date,
- To = factOperations.Max(o => o.DateStart).Date
+ From = minDateStart.Date.AddDays(1) <= DateTime.UtcNow ? minDateStart : DateTime.UtcNow.Date.AddDays(-1),
+ To = maxDateStart.AddDays(1) <= DateTime.UtcNow ? maxDateStart : DateTime.UtcNow.Date.AddDays(-1)
};
}
@@ -241,24 +234,24 @@ public class DailyReportService : IDailyReportService
CancellationToken cancellationToken)
{
const int idWellOperationSlipsTime = 5011;
-
+
if (dailyReport.TimeBalanceBlock is not null)
{
dailyReport.TimeBalanceBlock.SectionName = wellOperationRepository.GetSectionTypes()
.FirstOrDefault(s => s.Id == dailyReport.TimeBalanceBlock.IdSection)?.Caption;
-
+
dailyReport.TimeBalanceBlock.WellOperationSlipsTimeCount = (await detectedOperationService.GetAsync(
new DetectedOperationRequest
{
IdsCategories = new[] { idWellOperationSlipsTime },
IdWell = dailyReport.IdWell,
- GtDate = dailyReport.DateStart,
- LtDate = dailyReport.DateEnd
+ GtDate = dailyReport.Date,
+ LtDate = dailyReport.Date.AddHours(24)
}, cancellationToken))?.Stats.Sum(s => s.Count);
- dailyReport.TimeBalanceBlock.WellDepthFact = factWellOperations
+ dailyReport.TimeBalanceBlock.WellDepth.Fact = factWellOperations
.Where(o => o.IdWellSectionType == dailyReport.TimeBalanceBlock.IdSection)
- .Sum(o => o.DepthEnd = o.DepthStart);
+ .Sum(o => o.DepthEnd - o.DepthStart);
}
}
@@ -267,9 +260,9 @@ public class DailyReportService : IDailyReportService
var trajectory = (await trajectoryFactRepository.GetAsync(new TrajectoryGeoFactRequest
{
IdWell = dailyReport.IdWell,
- GeDate = dailyReport.DateStart,
- LeDate = dailyReport.DateEnd
- }, cancellationToken)).LastOrDefault();
+ GeDate = dailyReport.Date,
+ LeDate = dailyReport.Date.AddHours(24)
+ }, cancellationToken)).MaxBy(t => t.WellboreDepth);
dailyReport.TrajectoryBlock = new TrajectoryBlockDto
{
@@ -281,7 +274,7 @@ public class DailyReportService : IDailyReportService
}
private async Task AddScheduleBlockAsync(DailyReportDto dailyReport, CancellationToken cancellationToken) =>
- dailyReport.ScheduleBlock = (await scheduleRepository.GetAsync(dailyReport.IdWell, dailyReport.DateStart, cancellationToken))
+ dailyReport.ScheduleBlock = (await scheduleRepository.GetAsync(dailyReport.IdWell, dailyReport.Date, cancellationToken))
.Select(s => new ScheduleRecordDto
{
ShiftStart = s.ShiftStart,
@@ -299,13 +292,13 @@ public class DailyReportService : IDailyReportService
async Task> GetSubsystemsAsync()
{
- var modules = new List();
+ var subsystems = new List();
- var statSubsystemOperationTimePerDaily = (await subsystemOperationTimeService.GetStatAsync(new SubsystemOperationTimeRequest
+ var statSubsystemOperationTimePerDay = (await subsystemOperationTimeService.GetStatAsync(new SubsystemOperationTimeRequest
{
IdWell = dailyReport.IdWell,
- GtDate = dailyReport.DateStart,
- LtDate = dailyReport.DateEnd
+ GtDate = dailyReport.Date,
+ LtDate = dailyReport.Date.AddHours(24)
}, cancellationToken)).Select(s =>
{
var subsystemRecord = s.Adapt();
@@ -325,21 +318,21 @@ public class DailyReportService : IDailyReportService
return subsystemRecord;
});
- modules.AddRange(statSubsystemOperationTimePerDaily);
- modules.AddRange(statSubsystemOperationTimePerWell);
+ subsystems.AddRange(statSubsystemOperationTimePerDay);
+ subsystems.AddRange(statSubsystemOperationTimePerWell);
if (dailyReport.SubsystemBlock?.Subsystems != null && dailyReport.SubsystemBlock.Subsystems.Any())
- modules.AddRange(dailyReport.SubsystemBlock.Subsystems);
+ subsystems.AddRange(dailyReport.SubsystemBlock.Subsystems);
- return modules;
+ return subsystems.OrderBy(s => s.SubsystemName);
}
}
private async Task AddProcessMapWellDrillingBlockAsync(DailyReportDto dailyReport, CancellationToken cancellationToken)
{
dailyReport.ProcessMapWellDrillingBlock = (await processMapReportWellDrillingService.GetAsync(dailyReport.IdWell,
- cancellationToken)).Where(p => p.DateStart >= dailyReport.DateStart &&
- p.DateStart <= dailyReport.DateEnd)
+ cancellationToken)).Where(p => p.DateStart >= dailyReport.Date &&
+ p.DateStart <= dailyReport.Date.AddHours(24))
.GroupBy(p => p.DrillingMode)
.Select(g => new ProcessMapWellDrillingRecordDto
{
@@ -354,7 +347,7 @@ public class DailyReportService : IDailyReportService
});
}
- private void AddFactWellOperationBlock(DailyReportDto dailyReport, IEnumerable factWellOperations)
+ private static void AddFactWellOperationBlock(DailyReportDto dailyReport, IEnumerable factWellOperations)
{
const int idWellOperationCategoryDrilling = 4001;
@@ -373,13 +366,12 @@ public class DailyReportService : IDailyReportService
};
}
- private Task> GetFactWellOperationsAsync(int idWell, DateTime? dailyReportDateStart,
- DateTime? dailyReportDateEnd, CancellationToken cancellationToken) =>
+ private Task> GetFactWellOperationsAsync(int idWell, DateTime? dateDailyReport, CancellationToken cancellationToken) =>
wellOperationRepository.GetAsync(new WellOperationRequest
{
IdWell = idWell,
OperationType = WellOperation.IdOperationTypeFact,
- GeDate = dailyReportDateStart,
- LtDate = dailyReportDateEnd
+ GeDate = dateDailyReport,
+ LtDate = dateDailyReport?.AddHours(24)
}, cancellationToken);
}
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/Services/DailyReport/DailyReportTemplate.xlsx b/AsbCloudInfrastructure/Services/DailyReport/DailyReportTemplate.xlsx
index 6bf8da35..7594507c 100644
Binary files a/AsbCloudInfrastructure/Services/DailyReport/DailyReportTemplate.xlsx and b/AsbCloudInfrastructure/Services/DailyReport/DailyReportTemplate.xlsx differ
diff --git a/AsbCloudWebApi.Tests/Services/DailyReportServiceTest.cs b/AsbCloudWebApi.Tests/Services/DailyReportServiceTest.cs
index 7e7046a8..a8447fa2 100644
--- a/AsbCloudWebApi.Tests/Services/DailyReportServiceTest.cs
+++ b/AsbCloudWebApi.Tests/Services/DailyReportServiceTest.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections.Generic;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
@@ -6,11 +8,15 @@ using AsbCloudApp.Data.DailyReport;
using AsbCloudApp.Data.DailyReport.Blocks.Sign;
using AsbCloudApp.Data.DailyReport.Blocks.Subsystems;
using AsbCloudApp.Data.DailyReport.Blocks.TimeBalance;
-using AsbCloudApp.Exceptions;
+using AsbCloudApp.Data.DetectedOperation;
+using AsbCloudApp.Data.ProcessMaps.Report;
+using AsbCloudApp.Data.Subsystems;
using AsbCloudApp.Repositories;
+using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudApp.Services.ProcessMaps.WellDrilling;
using AsbCloudApp.Services.Subsystems;
+using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.DailyReport;
using NSubstitute;
using Xunit;
@@ -20,10 +26,169 @@ namespace AsbCloudWebApi.Tests.Services;
public class DailyReportServiceTest
{
private const int idDailyReport = 1;
- private const int idWell = 2;
private const int idUser = 3;
+ private const int idWell = 2;
- private readonly DateTime dateStart = new DateOnly(2023, 10, 26).ToDateTime(TimeOnly.MinValue);
+ private readonly DateTime dateDailyReport = new DateOnly(2023, 10, 26).ToDateTime(TimeOnly.MinValue);
+
+ private readonly SubsystemBlockDto fakeSubsystemBlock = new()
+ {
+ IdUser = idUser,
+ WellBore = 999,
+ MeasurementsPerDay = 999,
+ TotalRopPlan = 999,
+ Comment = "Увеличить обороты",
+ Subsystems = new[]
+ {
+ new SubsystemRecordDto
+ {
+ SubsystemName = "АвтоСПО",
+ IdTimeInterval = 2,
+ UsedTimeHours = 24,
+ SumDepthInterval = 1500,
+ KUsage = 100
+ }
+ }
+ };
+
+ private readonly SignBlockDto fakeSignBlock = new()
+ {
+ IdUser = idUser,
+ DrillingMaster = new SignRecordDto
+ {
+ Name = "Иван",
+ Patronymic = "Иванович",
+ Surname = "Иванов"
+ },
+ Supervisor = new SignRecordDto()
+ {
+ Name = "Илья",
+ Patronymic = "Ильич",
+ Surname = "Бурилов"
+ }
+ };
+
+ private readonly TimeBalanceBlockDto fakeTimeBalanceBlock = new()
+ {
+ IdUser = idUser,
+ IdSection = 1,
+ WellDepth = new PlanFactDto
+ {
+ Plan = 2000
+ },
+ WellOperations = new[]
+ {
+ new TimeBalanceRecordDto
+ {
+ IdWellOperation = 1,
+ DurationHours = new PlanFactDto
+ {
+ Fact = 100,
+ Plan = 150,
+ },
+ DrillingDeviationPerSection = 90,
+ DrillingDeviationPerDay = 100,
+ ReasonDeviation = "Отклонение"
+ }
+ }
+ };
+
+ private readonly DetectedOperationListDto fakeWellOperationSlipsTime = new()
+ {
+ Stats = new[]
+ {
+ new DetectedOperationDrillersStatDto
+ {
+ Count = 40
+ }
+ }
+ };
+
+ private readonly ProcessMapReportWellDrillingDto fakeProcessMapReportWellDrilling = new()
+ {
+ DrillingMode = "Ротор",
+ DateStart = new DateTime(2023, 10, 26),
+ DeltaDepth = 500,
+ Rop = new PlanFactDto
+ {
+ Plan = 300,
+ Fact = 500
+ },
+ MechDrillingHours = 100
+ };
+
+ private readonly WellSectionTypeDto fakeSectionType = new()
+ {
+ Id = 1,
+ Caption = "Пилотный ствол",
+ };
+
+ private readonly TrajectoryGeoFactDto fakeLastFactTrajectory = new()
+ {
+ WellboreDepth = 100,
+ VerticalDepth = 150,
+ ZenithAngle = 3,
+ AzimuthGeo = 5
+ };
+
+ private readonly CompanyDto fakeCustomer = new()
+ {
+ Caption = "Тестовый заказчик",
+ IdCompanyType = 1
+ };
+
+ private readonly CompanyDto fakeContractor = new()
+ {
+ Caption = "Тестовый подрядчик",
+ IdCompanyType = 2
+ };
+
+ private readonly WellOperationDto fakeFirstFactWellOperation = new()
+ {
+ IdWell = idWell,
+ IdParentCategory = 4001,
+ IdWellSectionType = 1,
+ CategoryName = "Механическое. бурение",
+ DateStart = new DateTime(2023, 10, 26),
+ DepthStart = 80,
+ DepthEnd = 150,
+ DurationHours = 8,
+ };
+
+ private readonly WellOperationDto fakeLastFactWellOperation = new()
+ {
+ IdWell = idWell,
+ CategoryName = "Механическое. бурение",
+ IdWellSectionType = 1,
+ IdParentCategory = 4001,
+ DateStart = new DateTime(2023, 10, 26),
+ DepthStart = 150,
+ DepthEnd = 200,
+ DurationHours = 8,
+ };
+
+ private readonly ScheduleDto fakeShedule = new()
+ {
+ IdWell = idWell,
+ ShiftStart = new TimeDto(1),
+ ShiftEnd = new TimeDto(5),
+ DrillStart = new DateTime(2023, 01, 26),
+ DrillEnd = new DateTime(2023, 12, 26),
+ Driller = new()
+ {
+ Name = "Иван",
+ Surname = "Иванов",
+ Patronymic = "Бурила"
+ }
+ };
+
+ private readonly SubsystemStatDto fakeStatSubsystemOperationTimePerDay = new()
+ {
+ SubsystemName = "АПД",
+ SumDepthInterval = 250,
+ UsedTimeHours = 200,
+ KUsage = 30
+ };
private readonly IWellService wellServiceMock = Substitute.For();
private readonly ITrajectoryFactRepository trajectoryFactRepositoryMock = Substitute.For();
@@ -33,18 +198,30 @@ public class DailyReportServiceTest
private readonly ISubsystemOperationTimeService subsystemOperationTimeServiceMock = Substitute.For();
private readonly IProcessMapReportWellDrillingService processMapReportWellDrillingServiceMock = Substitute.For();
private readonly IDetectedOperationService detectedOperationServiceMock = Substitute.For();
-
+
private readonly DailyReportService dailyReportService;
private readonly DailyReportDto fakeDailyReport;
+ private readonly WellDto fakeWell;
public DailyReportServiceTest()
{
- fakeDailyReport = new()
+ fakeDailyReport = new DailyReportDto
{
Id = idDailyReport,
IdWell = idWell,
- DateStart = dateStart
+ Date = dateDailyReport,
+ DateLastUpdate = null
+ };
+
+ fakeWell = new WellDto
+ {
+ Id = idWell,
+ Caption = "Тестовое название",
+ WellType = "Горизонтальная",
+ Cluster = "Тестовый куст",
+ Deposit = "Тестовое месторождение",
+ Companies = new[] { fakeCustomer, fakeContractor }
};
dailyReportService = new DailyReportService(wellServiceMock,
@@ -59,139 +236,276 @@ public class DailyReportServiceTest
dailyReportRepositoryMock.InsertAsync(Arg.Any(), Arg.Any())
.ReturnsForAnyArgs(idDailyReport);
- dailyReportRepositoryMock.GetOrDefaultAsync(idDailyReport, Arg.Any())
- .Returns(fakeDailyReport);
+ dailyReportRepositoryMock.GetOrDefaultAsync(Arg.Any(), Arg.Any(), Arg.Any())
+ .ReturnsForAnyArgs(fakeDailyReport);
dailyReportRepositoryMock.UpdateAsync(Arg.Any(), Arg.Any())
.ReturnsForAnyArgs(idDailyReport);
+
+ wellServiceMock.GetOrDefaultAsync(Arg.Any(), Arg.Any())
+ .ReturnsForAnyArgs(fakeWell);
+
+ trajectoryFactRepositoryMock.GetAsync(Arg.Any(), Arg.Any())
+ .ReturnsForAnyArgs(new[] { fakeLastFactTrajectory });
+
+ wellOperationRepositoryMock.GetAsync(Arg.Any(), Arg.Any())
+ .ReturnsForAnyArgs(new[] { fakeFirstFactWellOperation, fakeLastFactWellOperation });
+
+ wellOperationRepositoryMock.GetSectionTypes()
+ .ReturnsForAnyArgs(new[] { fakeSectionType });
+
+ detectedOperationServiceMock.GetAsync(Arg.Any(), Arg.Any())
+ .ReturnsForAnyArgs(fakeWellOperationSlipsTime);
+
+ subsystemOperationTimeServiceMock.GetStatAsync(Arg.Any(), Arg.Any())
+ .ReturnsForAnyArgs(new[] { fakeStatSubsystemOperationTimePerDay });
+
+ scheduleRepositoryMock.GetAsync(idWell, dateDailyReport, Arg.Any())
+ .ReturnsForAnyArgs(new[] { fakeShedule });
+
+ processMapReportWellDrillingServiceMock.GetAsync(idWell, Arg.Any())
+ .ReturnsForAnyArgs(new[] { fakeProcessMapReportWellDrilling });
}
[Fact]
- public async Task InsertAsync_ShouldReturn_ExceptionAboutDuplicate()
+ public async Task UpdateOrInsertAsync_ShouldReturn_UpdatedSubsystemBlock()
{
- //arrange
- dailyReportRepositoryMock.AnyAsync(Arg.Any(), Arg.Any(), Arg.Any())
- .ReturnsForAnyArgs(true);
-
//act
- Task Result() => dailyReportService.InsertAsync(idWell, dateStart, CancellationToken.None);
-
- //assert
- var exception = await Assert.ThrowsAsync(Result);
- Assert.Equal("Суточный отчёт уже существует", exception.Message);
- }
-
- [Fact]
- public async Task InsertAsync_ShouldReturn_PositiveId()
- {
- //arrange
- dailyReportRepositoryMock.AnyAsync(Arg.Any(), Arg.Any(), Arg.Any())
- .ReturnsForAnyArgs(false);
-
- //act
- var result = await dailyReportService.InsertAsync(idWell, dateStart, CancellationToken.None);
+ var result = await dailyReportService.UpdateOrInsertAsync(idWell, dateDailyReport, idUser, fakeSubsystemBlock, CancellationToken.None);
//assert
+ Assert.NotNull(fakeSubsystemBlock.LastUpdateDate);
+ Assert.NotNull(fakeDailyReport.DateLastUpdate);
+ Assert.Equal(fakeSubsystemBlock.IdUser, idUser);
+ Assert.Equal(fakeDailyReport.SubsystemBlock, fakeSubsystemBlock);
Assert.Equal(idDailyReport, result);
}
[Fact]
- public async Task UpdateSubsystemBlock_ShouldReturn_Success()
+ public async Task UpdateOrInsertAsync_ShouldReturn_UpdatedSignBlock()
{
- //arrange
- var fakeSubsystemBlock = new SubsystemBlockDto
- {
- IdUser = idUser,
- WellBore = 999,
- MeasurementsPerDay = 999,
- TotalRopPlan = 999,
- Comment = "Увеличить обороты",
- Subsystems = new[]
- {
- new SubsystemRecordDto
- {
- SubsystemName = "АвтоСПО",
- IdTimeInterval = 1,
- UsedTimeHours = 24,
- SumDepthInterval = 1500,
- KUsage = 100
- }
- }
- };
-
//act
- var result = await dailyReportService.UpdateBlockAsync(idDailyReport, idUser, fakeSubsystemBlock, CancellationToken.None);
-
- //assert
- Assert.NotNull(fakeSubsystemBlock.DateLastUpdate);
- Assert.NotNull(fakeDailyReport.DateLastUpdate);
- Assert.Equal(fakeDailyReport.SubsystemBlock, fakeSubsystemBlock);
- Assert.Equal(idDailyReport, result);
- }
-
- [Fact]
- public async Task UpdateSignBlock_ShouldReturn_Success()
- {
- //arrange
- var fakeSignBlock = new SignBlockDto
- {
- IdUser = idUser,
- DrillingMaster = new SignRecordDto()
- {
- Name = "Иван",
- Patronymic = "Иванович",
- Surname = "Иванов"
- },
- Supervisor = new SignRecordDto()
- {
- Name = "Илья",
- Patronymic = "Ильич",
- Surname = "Бурилов"
- }
- };
-
- //act
- var result = await dailyReportService.UpdateBlockAsync(idDailyReport, idUser, fakeSignBlock, CancellationToken.None);
+ var result = await dailyReportService.UpdateOrInsertAsync(idWell, dateDailyReport, idUser, fakeSignBlock, CancellationToken.None);
//assert
- Assert.NotNull(fakeSignBlock.DateLastUpdate);
+ Assert.NotNull(fakeSignBlock.LastUpdateDate);
Assert.NotNull(fakeDailyReport.DateLastUpdate);
+ Assert.Equal(fakeSignBlock.IdUser, idUser);
Assert.Equal(fakeDailyReport.SignBlock, fakeSignBlock);
Assert.Equal(idDailyReport, result);
}
[Fact]
- public async Task UpdateTimeBalance_ShouldReturn_Success()
+ public async Task UpdateOrInsertAsync_ShouldReturn_UpdatedTimeBalanceBlock()
{
- //arrange
- var fakeTimeBalanceBlock = new TimeBalanceBlockDto
- {
- IdUser = idUser,
- IdSection = 1,
- WellDepthPlan = 2000,
- WellOperations = new[]
- {
- new TimeBalanceRecordDto()
- {
- DurationHours = new PlanFactDto()
- {
- Fact = 100,
- Plan = 150,
- },
- DrillingDeviationPerSection = 90,
- DrillingDeviationPerDaily = 100,
- ReasonDeviation = "Отклонение"
- }
- }
- };
-
//act
- var result = await dailyReportService.UpdateBlockAsync(idDailyReport, idUser, fakeTimeBalanceBlock, CancellationToken.None);
+ var result = await dailyReportService.UpdateOrInsertAsync(idWell, dateDailyReport, idUser, fakeTimeBalanceBlock,
+ CancellationToken.None);
//assert
- Assert.NotNull(fakeTimeBalanceBlock.DateLastUpdate);
+ Assert.NotNull(fakeTimeBalanceBlock.LastUpdateDate);
Assert.NotNull(fakeDailyReport.DateLastUpdate);
+ Assert.Equal(fakeTimeBalanceBlock.IdUser, idUser);
Assert.Equal(fakeDailyReport.TimeBalanceBlock, fakeTimeBalanceBlock);
Assert.Equal(idDailyReport, result);
}
+
+ [Fact]
+ public async Task GetAsync_ShouldReturn_AddedWellInfo()
+ {
+ //act
+ var result = await dailyReportService.GetAsync(idWell, dateDailyReport, CancellationToken.None);
+
+ //assert
+ Assert.Equal(result.IdWell, fakeWell.Id);
+ Assert.Equal(result.WellCaption, fakeWell.Caption);
+ Assert.Equal(result.WellType, fakeWell.WellType);
+ Assert.Equal(result.Cluster, fakeWell.Cluster);
+ Assert.Equal(result.Deposit, fakeWell.Deposit);
+ Assert.Equal(result.Customer, fakeCustomer.Caption);
+ Assert.Equal(result.Contractor, fakeContractor.Caption);
+ Assert.Equal(result.DepthStart, fakeFirstFactWellOperation.DepthStart);
+ Assert.Equal(result.DepthEnd, fakeLastFactWellOperation.DepthEnd);
+ }
+
+ [Fact]
+ public async Task GetAsync_ShouldReturn_AddedTrajectoryBlock()
+ {
+ //act
+ var result = await dailyReportService.GetAsync(idWell, dateDailyReport, CancellationToken.None);
+
+ //assert
+ Assert.Equal(fakeLastFactTrajectory.WellboreDepth, result.TrajectoryBlock.WellboreDepth);
+ Assert.Equal(fakeLastFactTrajectory.VerticalDepth, result.TrajectoryBlock.VerticalDepth);
+ Assert.Equal(fakeLastFactTrajectory.ZenithAngle, result.TrajectoryBlock.ZenithAngle);
+ Assert.Equal(fakeLastFactTrajectory.AzimuthGeo, result.TrajectoryBlock.AzimuthGeo);
+ }
+
+ [Fact]
+ public async Task GetAsync_ShouldReturn_AddedFactWellOperationBlock()
+ {
+ //act
+ var result = await dailyReportService.GetAsync(idWell, dateDailyReport, CancellationToken.None);
+
+ //assert
+ Assert.Equal(16, result.FactWellOperationBlock.SectionDrillingHours);
+ Assert.Single(result.FactWellOperationBlock.WellOperations);
+
+ var wellOperation = result.FactWellOperationBlock.WellOperations.Single();
+
+ Assert.Equal("Механическое. бурение", wellOperation.CategoryName);
+ Assert.Equal(16, wellOperation.DurationHours);
+ }
+
+ [Fact]
+ public async Task GetAsync_ShouldReturn_AddedScheduleBlock()
+ {
+ //act
+ var result = await dailyReportService.GetAsync(idWell, dateDailyReport, CancellationToken.None);
+
+ //assert
+ Assert.Single(result.ScheduleBlock);
+
+ var sheduleRecord = result.ScheduleBlock.Single();
+
+ Assert.Equal(fakeShedule.ShiftStart, sheduleRecord.ShiftStart);
+ Assert.Equal(fakeShedule.ShiftEnd, sheduleRecord.ShiftEnd);
+ Assert.Equal(fakeShedule.Driller?.Name, sheduleRecord.Name);
+ Assert.Equal(fakeShedule.Driller?.Surname, sheduleRecord.Surname);
+ Assert.Equal(fakeShedule.Driller?.Patronymic, sheduleRecord.Patronymic);
+ }
+
+ [Fact]
+ public async Task GetAsync_ShouldReturn_UpdatedTimeBalanceBlock()
+ {
+ //arrange
+ fakeDailyReport.TimeBalanceBlock = fakeTimeBalanceBlock;
+
+ //act
+ var result = await dailyReportService.GetAsync(idWell, dateDailyReport, CancellationToken.None);
+
+ //assert
+ Assert.NotNull(result.TimeBalanceBlock);
+ Assert.Equal(fakeSectionType.Id, result.TimeBalanceBlock.IdSection);
+ Assert.Equal(fakeSectionType.Caption, result.TimeBalanceBlock.SectionName);
+ Assert.Equal(2000, result.TimeBalanceBlock?.WellDepth.Plan);
+ Assert.Equal(120, result.TimeBalanceBlock?.WellDepth.Fact);
+ Assert.Equal(40, result.TimeBalanceBlock?.WellOperationSlipsTimeCount);
+ }
+
+ [Fact]
+ public async Task GetAsync_ShouldReturn_AddedProcessMapWellDrillingBlock()
+ {
+ //act
+ var result = await dailyReportService.GetAsync(idWell, dateDailyReport, CancellationToken.None);
+
+ //assert
+ Assert.Single(result.ProcessMapWellDrillingBlock);
+
+ var processMapWellDrillingRecord = result.ProcessMapWellDrillingBlock.Single();
+
+ Assert.Equal(fakeProcessMapReportWellDrilling.DrillingMode, processMapWellDrillingRecord.DrillingMode);
+ Assert.Equal(fakeProcessMapReportWellDrilling.Rop.Plan, processMapWellDrillingRecord.Rop.Plan);
+ Assert.Equal(fakeProcessMapReportWellDrilling.Rop.Fact, processMapWellDrillingRecord.Rop.Fact);
+ Assert.Equal(fakeProcessMapReportWellDrilling.DeltaDepth, processMapWellDrillingRecord.WellBoreDepth);
+ Assert.Equal(fakeProcessMapReportWellDrilling.MechDrillingHours, processMapWellDrillingRecord.MechDrillingHours);
+ }
+
+ [Fact]
+ public async Task GetAsync_ShouldReturn_UpdatedSubsystemBlock()
+ {
+ //arrange
+ fakeDailyReport.SubsystemBlock = fakeSubsystemBlock;
+
+ //act
+ var result = await dailyReportService.GetAsync(idDailyReport, dateDailyReport, CancellationToken.None);
+
+ //assert
+ Assert.NotNull(result.SubsystemBlock);
+ Assert.Equal(3, result.SubsystemBlock?.Subsystems.Count());
+
+ var subsystemRecord0 = result.SubsystemBlock?.Subsystems.ElementAt(0);
+
+ Assert.Equal("АвтоСПО", subsystemRecord0?.SubsystemName);
+ Assert.Equal(2, subsystemRecord0?.IdTimeInterval);
+ Assert.Equal(24, subsystemRecord0?.UsedTimeHours);
+ Assert.Equal(1500, subsystemRecord0?.SumDepthInterval);
+ Assert.Equal(100, subsystemRecord0?.KUsage);
+
+ var subsystemRecord1 = result.SubsystemBlock?.Subsystems.ElementAt(1);
+
+ Assert.Equal(fakeStatSubsystemOperationTimePerDay.SubsystemName, subsystemRecord1?.SubsystemName);
+ Assert.Equal(1, subsystemRecord1?.IdTimeInterval);
+ Assert.Equal(fakeStatSubsystemOperationTimePerDay.UsedTimeHours, subsystemRecord1?.UsedTimeHours);
+ Assert.Equal(fakeStatSubsystemOperationTimePerDay.SumDepthInterval, subsystemRecord1?.SumDepthInterval);
+ Assert.Equal(fakeStatSubsystemOperationTimePerDay.KUsage, subsystemRecord1?.KUsage);
+ }
+
+ [Fact]
+ public async Task GetAsync_ShouldReturn_FictiveDailyReport()
+ {
+ //act
+ var result = await dailyReportService.GetAsync(idWell, new FileReportRequest(), CancellationToken.None);
+
+ //assert
+ Assert.True((fakeLastFactWellOperation.DateStart - fakeFirstFactWellOperation.DateStart).Days == result.Count);
+ }
+
+ [Theory]
+ [MemberData(nameof(FactWellOperationDates))]
+ public async Task GetDatesRangeAsync_ShouldReturn_DateRangeByFactWellOperations(IEnumerable factWellOperationDates)
+ {
+ //arrange
+ wellOperationRepositoryMock.GetAsync(Arg.Any(), CancellationToken.None)
+ .ReturnsForAnyArgs(factWellOperationDates.Select(dateStart => new WellOperationDto { DateStart = dateStart }));
+
+ //act
+ var result = await dailyReportService.GetDatesRangeAsync(idWell, CancellationToken.None);
+
+ //assert
+ Assert.NotNull(result);
+ Assert.True(result.From <= result.To);
+ Assert.True(result.To < DateTime.UtcNow.Date);
+ }
+
+ public static IEnumerable