Фикс сервисов

1. Устранение багов выявленных при тестировании
2. Изменение имён методов в сервисе суточных отчётов
3. Фикс получения фиктивных суточных отчётов
4. Фикс шаблона
5. Правки в контроллере
6. Фикс в репозитории. Приведение к utc доа выполнения запроса
7. Покрытие сервиса тестами
This commit is contained in:
Степанов Дмитрий 2023-11-14 11:01:34 +05:00
parent 968596b4bf
commit 1bda2d5b77
7 changed files with 542 additions and 266 deletions

View File

@ -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;
/// <summary>
/// Суточные отчёты
/// </summary>
public interface IDailyReportService
{
/// <summary>
/// Создать отчёт
/// Обновить или создать суточный отчёт
/// </summary>
/// <param name="idWell"></param>
/// <param name="dateStart"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<int> InsertAsync(int idWell, DateTime dateStart, CancellationToken cancellationToken);
/// <summary>
/// Обновить блок
/// </summary>
/// <param name="idDailyReport"></param>
/// <param name="dateDailyReport"></param>
/// <param name="idUser"></param>
/// <param name="editableBlock"></param>
/// <param name="cancellationToken"></param>
/// <typeparam name="TBlock"></typeparam>
/// <param name="idWell"></param>
/// <returns></returns>
Task<int> UpdateBlockAsync<TBlock>(int idDailyReport, int idUser, TBlock editableBlock, CancellationToken cancellationToken)
where TBlock : EditableBlock;
Task<int> UpdateOrInsertAsync<TBlock>(int idWell, DateTime dateDailyReport, int idUser, TBlock editableBlock,
CancellationToken cancellationToken)
where TBlock : ItemInfoDto;
/// <summary>
/// Получить сформированный суточный отчёт
/// </summary>
/// <param name="idWell"></param>
/// <param name="dateStart"></param>
/// <param name="dateDailyReport"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<DailyReportDto> GetAsync(int idWell, DateTime dateStart, CancellationToken cancellationToken);
Task<DailyReportDto> GetAsync(int idWell, DateTime dateDailyReport, CancellationToken cancellationToken);
/// <summary>
/// Получить список суточных отчётов по скважине
@ -47,8 +41,7 @@ public interface IDailyReportService
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<PaginationContainer<DailyReportDto>> GetAsync(int idWell, FileReportRequest request,
CancellationToken cancellationToken);
Task<PaginationContainer<DailyReportDto>> GetAsync(int idWell, FileReportRequest request, CancellationToken cancellationToken);
/// <summary>
/// Получить диапазон дат по которым возможно сформировать суточный отчёты

View File

@ -32,10 +32,16 @@ public class DailyReportRepository : CrudRepositoryBase<DailyReportDto, DailyRep
var query = GetQuery().Where(d => 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)
{

View File

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

View File

@ -52,31 +52,16 @@ public class DailyReportService : IDailyReportService
this.detectedOperationService = detectedOperationService;
}
public async Task<int> 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<int> UpdateBlockAsync<TBlock>(int idDailyReport, int idUser, TBlock editableBlock,
public async Task<int> UpdateOrInsertAsync<TBlock>(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<DailyReportDto> GetAsync(int idWell, DateTime dateStart, CancellationToken cancellationToken)
public async Task<DailyReportDto> 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<DatesRangeDto?> 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<IEnumerable<SubsystemRecordDto>> GetSubsystemsAsync()
{
var modules = new List<SubsystemRecordDto>();
var subsystems = new List<SubsystemRecordDto>();
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<SubsystemRecordDto>();
@ -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<WellOperationDto> factWellOperations)
private static void AddFactWellOperationBlock(DailyReportDto dailyReport, IEnumerable<WellOperationDto> factWellOperations)
{
const int idWellOperationCategoryDrilling = 4001;
@ -373,13 +366,12 @@ public class DailyReportService : IDailyReportService
};
}
private Task<IEnumerable<WellOperationDto>> GetFactWellOperationsAsync(int idWell, DateTime? dailyReportDateStart,
DateTime? dailyReportDateEnd, CancellationToken cancellationToken) =>
private Task<IEnumerable<WellOperationDto>> 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);
}

View File

@ -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<double?>
{
Plan = 2000
},
WellOperations = new[]
{
new TimeBalanceRecordDto
{
IdWellOperation = 1,
DurationHours = new PlanFactDto<double?>
{
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<double?>
{
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<IWellService>();
private readonly ITrajectoryFactRepository trajectoryFactRepositoryMock = Substitute.For<ITrajectoryFactRepository>();
@ -33,18 +198,30 @@ public class DailyReportServiceTest
private readonly ISubsystemOperationTimeService subsystemOperationTimeServiceMock = Substitute.For<ISubsystemOperationTimeService>();
private readonly IProcessMapReportWellDrillingService processMapReportWellDrillingServiceMock = Substitute.For<IProcessMapReportWellDrillingService>();
private readonly IDetectedOperationService detectedOperationServiceMock = Substitute.For<IDetectedOperationService>();
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<DailyReportDto>(), Arg.Any<CancellationToken>())
.ReturnsForAnyArgs(idDailyReport);
dailyReportRepositoryMock.GetOrDefaultAsync(idDailyReport, Arg.Any<CancellationToken>())
.Returns(fakeDailyReport);
dailyReportRepositoryMock.GetOrDefaultAsync(Arg.Any<int>(), Arg.Any<DateTime>(), Arg.Any<CancellationToken>())
.ReturnsForAnyArgs(fakeDailyReport);
dailyReportRepositoryMock.UpdateAsync(Arg.Any<DailyReportDto>(), Arg.Any<CancellationToken>())
.ReturnsForAnyArgs(idDailyReport);
wellServiceMock.GetOrDefaultAsync(Arg.Any<int>(), Arg.Any<CancellationToken>())
.ReturnsForAnyArgs(fakeWell);
trajectoryFactRepositoryMock.GetAsync(Arg.Any<TrajectoryGeoFactRequest>(), Arg.Any<CancellationToken>())
.ReturnsForAnyArgs(new[] { fakeLastFactTrajectory });
wellOperationRepositoryMock.GetAsync(Arg.Any<WellOperationRequest>(), Arg.Any<CancellationToken>())
.ReturnsForAnyArgs(new[] { fakeFirstFactWellOperation, fakeLastFactWellOperation });
wellOperationRepositoryMock.GetSectionTypes()
.ReturnsForAnyArgs(new[] { fakeSectionType });
detectedOperationServiceMock.GetAsync(Arg.Any<DetectedOperationRequest>(), Arg.Any<CancellationToken>())
.ReturnsForAnyArgs(fakeWellOperationSlipsTime);
subsystemOperationTimeServiceMock.GetStatAsync(Arg.Any<SubsystemOperationTimeRequest>(), Arg.Any<CancellationToken>())
.ReturnsForAnyArgs(new[] { fakeStatSubsystemOperationTimePerDay });
scheduleRepositoryMock.GetAsync(idWell, dateDailyReport, Arg.Any<CancellationToken>())
.ReturnsForAnyArgs(new[] { fakeShedule });
processMapReportWellDrillingServiceMock.GetAsync(idWell, Arg.Any<CancellationToken>())
.ReturnsForAnyArgs(new[] { fakeProcessMapReportWellDrilling });
}
[Fact]
public async Task InsertAsync_ShouldReturn_ExceptionAboutDuplicate()
public async Task UpdateOrInsertAsync_ShouldReturn_UpdatedSubsystemBlock()
{
//arrange
dailyReportRepositoryMock.AnyAsync(Arg.Any<int>(), Arg.Any<DateTime>(), Arg.Any<CancellationToken>())
.ReturnsForAnyArgs(true);
//act
Task Result() => dailyReportService.InsertAsync(idWell, dateStart, CancellationToken.None);
//assert
var exception = await Assert.ThrowsAsync<ArgumentInvalidException>(Result);
Assert.Equal("Суточный отчёт уже существует", exception.Message);
}
[Fact]
public async Task InsertAsync_ShouldReturn_PositiveId()
{
//arrange
dailyReportRepositoryMock.AnyAsync(Arg.Any<int>(), Arg.Any<DateTime>(), Arg.Any<CancellationToken>())
.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<double>()
{
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<DateTime> factWellOperationDates)
{
//arrange
wellOperationRepositoryMock.GetAsync(Arg.Any<WellOperationRequest>(), 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<object[]> FactWellOperationDates()
{
yield return new object[]
{
new[]
{
new DateTime(2023, 11, 1),
new DateTime(2023, 11, 9),
DateTime.UtcNow
}
};
yield return new object[]
{
new[]
{
new DateTime(2023, 11, 1),
new DateTime(2023, 11, 1)
}
};
yield return new object[]
{
new[]
{
DateTime.UtcNow,
DateTime.UtcNow
}
};
yield return new object[]
{
new[]
{
new DateTime(2023, 11, 1),
new DateTime(2023, 11, 9),
new DateTime(2023, 11, 11)
}
};
}
}

View File

@ -5,7 +5,6 @@ using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Data.DailyReport;
using AsbCloudApp.Data.DailyReport.Blocks;
using AsbCloudApp.Data.DailyReport.Blocks.Sign;
using AsbCloudApp.Data.DailyReport.Blocks.Subsystems;
using AsbCloudApp.Data.DailyReport.Blocks.TimeBalance;
@ -57,39 +56,11 @@ public class DailyReportController : ControllerBase
}
}
/// <summary>
/// Создать суточный отчёт
/// </summary>
/// <param name="idWell">Id скважины</param>
/// <param name="dateStart">Дата формирования суточного отчёта</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost]
[Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> InsertAsync(int idWell, DateOnly dateStart, CancellationToken cancellationToken)
{
var dateStartToDateTime = dateStart.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc);
var datesRange = await dailyReportService.GetDatesRangeAsync(idWell, cancellationToken);
if (dateStartToDateTime < datesRange?.From || dateStartToDateTime > datesRange?.To)
throw new ArgumentInvalidException("Невозможно сформировать суточный отчёт", nameof(dateStart));
await AssertUserAccessToWell(idWell, cancellationToken);
var id = await dailyReportService.InsertAsync(idWell, dateStart.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc),
cancellationToken);
return Ok(id);
}
/// <summary>
/// Обновить подпись
/// </summary>
/// <param name="idWell">Id скважины</param>
/// <param name="idDailyReport">Id суточного отчёта</param>
/// <param name="dateDailyReport">Дата суточного отчёта</param>
/// <param name="signBlock">Обновляемый блок</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
@ -97,14 +68,15 @@ public class DailyReportController : ControllerBase
[Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public Task<IActionResult> UpdateSignBlockAsync(int idWell, int idDailyReport, SignBlockDto signBlock, CancellationToken cancellationToken) =>
UpdateBlockAsync(idWell, idDailyReport, signBlock, cancellationToken);
public Task<IActionResult> UpdateSignBlockAsync(int idWell, DateOnly dateDailyReport, SignBlockDto signBlock,
CancellationToken cancellationToken) =>
UpdateOrInsertAsync(idWell, dateDailyReport, signBlock, cancellationToken);
/// <summary>
/// Обновить наработку подсистем
/// </summary>
/// <param name="idWell">Id скважины</param>
/// <param name="idDailyReport">Id суточного отчёта</param>
/// <param name="dateDailyReport">Дата суточного отчёта</param>
/// <param name="subsystemBlock">Обновляемый блок</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
@ -112,7 +84,7 @@ public class DailyReportController : ControllerBase
[Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public Task<IActionResult> UpdateSubsystemBlockAsync(int idWell, int idDailyReport, SubsystemBlockDto subsystemBlock,
public Task<IActionResult> UpdateSubsystemBlockAsync(int idWell, DateOnly dateDailyReport, SubsystemBlockDto subsystemBlock,
CancellationToken cancellationToken)
{
var validSubsystemNames = new[] { "АвтоСПО", "Автопроработка" };
@ -121,14 +93,14 @@ public class DailyReportController : ControllerBase
throw new ArgumentInvalidException($"Возможно добавить подсистемы с именами {string.Join(", ", validSubsystemNames)}",
nameof(subsystemBlock.Subsystems));
return UpdateBlockAsync(idWell, idDailyReport, subsystemBlock, cancellationToken);
return UpdateOrInsertAsync(idWell, dateDailyReport, subsystemBlock, cancellationToken);
}
/// <summary>
/// Обновить баланс времени
/// </summary>
/// <param name="idWell">Id скважины</param>
/// <param name="idDailyReport">Id суточного отчёта</param>
/// <param name="dateDailyReport">Дата суточного отчёта</param>
/// <param name="timeBalanceBlock">Обновляемый блок</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
@ -136,7 +108,7 @@ public class DailyReportController : ControllerBase
[Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public Task<IActionResult> UpdateTimeBalanceBlockAsync(int idWell, int idDailyReport, TimeBalanceBlockDto timeBalanceBlock,
public Task<IActionResult> UpdateTimeBalanceBlockAsync(int idWell, DateOnly dateDailyReport, TimeBalanceBlockDto timeBalanceBlock,
CancellationToken cancellationToken)
{
var validWellOperationsIds = new[] { 1, 2, 3, 4 };
@ -144,13 +116,13 @@ public class DailyReportController : ControllerBase
if (timeBalanceBlock.WellOperations.Any(o => !validWellOperationsIds.Contains(o.IdWellOperation)))
throw new ArgumentInvalidException($"Возможно добавить операции только с Id: {string.Join(", ", validWellOperationsIds)}",
nameof(timeBalanceBlock.WellOperations));
var wellSections = wellOperationRepository.GetSectionTypes();
if (wellSections.All(s => s.Id != timeBalanceBlock.IdSection))
throw new ArgumentInvalidException($"Секция с Id: {timeBalanceBlock.IdSection} не найдена", nameof(timeBalanceBlock.IdSection));
return UpdateBlockAsync(idWell, idDailyReport, timeBalanceBlock, cancellationToken);
return UpdateOrInsertAsync(idWell, dateDailyReport, timeBalanceBlock, cancellationToken);
}
/// <summary>
@ -193,36 +165,37 @@ public class DailyReportController : ControllerBase
/// Экспорт суточного рапорта
/// </summary>
/// <param name="idWell">Id скважины</param>
/// <param name="dateStart">Дата формирования суточного отчёта</param>
/// <param name="dateDailyReport">Дата формирования суточного отчёта</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet("{dateStart}")]
[HttpGet("{dateDailyReport}")]
[ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> ExportAsync(int idWell, DateOnly dateStart, CancellationToken cancellationToken)
public async Task<IActionResult> ExportAsync(int idWell, DateOnly dateDailyReport, CancellationToken cancellationToken)
{
var dateStartToDateTime = dateStart.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc);
var dateStartToDateTime = dateDailyReport.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc);
var datesRange = await dailyReportService.GetDatesRangeAsync(idWell, cancellationToken);
if (dateStartToDateTime < datesRange?.From || dateStartToDateTime > datesRange?.To)
throw new ArgumentInvalidException("Невозможно получить суточный отчёт", nameof(dateStart));
throw new ArgumentInvalidException("Невозможно получить суточный отчёт", nameof(dateDailyReport));
await AssertUserAccessToWell(idWell, cancellationToken);
var dailyReport = await dailyReportExportService.ExportAsync(idWell,
dateStart.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc), cancellationToken);
dateDailyReport.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc), cancellationToken);
return File(dailyReport.File, "application/octet-stream", dailyReport.FileName);
}
private async Task<IActionResult> UpdateBlockAsync<TBlock>(int idWell, int idDailyReport, TBlock block,
private async Task<IActionResult> UpdateOrInsertAsync<TBlock>(int idWell, DateOnly dateDailyReport, TBlock block,
CancellationToken cancellationToken)
where TBlock : EditableBlock
where TBlock : ItemInfoDto
{
await AssertUserAccessToWell(idWell, cancellationToken);
var id = await dailyReportService.UpdateBlockAsync(idDailyReport, IdUser, block, cancellationToken);
var id = await dailyReportService.UpdateOrInsertAsync(idWell, dateDailyReport.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc), IdUser,
block, cancellationToken);
return Ok(id);
}