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

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

View File

@ -32,10 +32,16 @@ public class DailyReportRepository : CrudRepositoryBase<DailyReportDto, DailyRep
var query = GetQuery().Where(d => d.IdWell == idWell); var query = GetQuery().Where(d => d.IdWell == idWell);
if (request.GeDate.HasValue) 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) 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) if (request.SortFields?.Any() == true)
{ {

View File

@ -28,7 +28,7 @@ public class DailyReportExportService : IDailyReportExportService
private const int columnTimeBalanceDurationFact = 4; private const int columnTimeBalanceDurationFact = 4;
private const int columnTimeBalanceReasonDeviation = 8; private const int columnTimeBalanceReasonDeviation = 8;
private const int columnTimeBalanceDrillingDeviationPerSection = 10; private const int columnTimeBalanceDrillingDeviationPerSection = 10;
private const int columnTimeBalanceDrillingDeviationPerDaily = 11; private const int columnTimeBalanceDrillingDeviationPerDay = 11;
private const int columnSheduleDriller = 3; private const int columnSheduleDriller = 3;
private const int columnSheduleShiftStart = 7; private const int columnSheduleShiftStart = 7;
@ -56,10 +56,9 @@ public class DailyReportExportService : IDailyReportExportService
private const string cellContractor = "C3"; private const string cellContractor = "C3";
private const string cellDeposit = "C5"; private const string cellDeposit = "C5";
private const string cellCluster = "C6"; private const string cellCluster = "C6";
private const string cellWellName = "C7"; private const string cellWellCaption = "C7";
private const string cellWellType = "C8"; private const string cellWellType = "C8";
private const string cellDateStart = "C12"; private const string cellDate = "C12";
private const string cellDateEnd = "D12";
private const string cellDepthStart = "C13"; private const string cellDepthStart = "C13";
private const string cellDepthEnd = "D13"; private const string cellDepthEnd = "D13";
@ -95,7 +94,7 @@ public class DailyReportExportService : IDailyReportExportService
var stream = await GenerateFileAsync(dailyReport, cancellationToken); 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); return (fileName, stream);
} }
@ -127,10 +126,9 @@ public class DailyReportExportService : IDailyReportExportService
sheet.Cell(cellContractor).Value = dailyReport.Contractor; sheet.Cell(cellContractor).Value = dailyReport.Contractor;
sheet.Cell(cellDeposit).Value = dailyReport.Deposit; sheet.Cell(cellDeposit).Value = dailyReport.Deposit;
sheet.Cell(cellCluster).Value = dailyReport.Cluster; 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(cellWellType).Value = dailyReport.WellType;
sheet.Cell(cellDateStart).Value = dailyReport.DateStart; sheet.Cell(cellDate).Value = dailyReport.Date;
sheet.Cell(cellDateEnd).Value = dailyReport.DateEnd;
sheet.Cell(cellDepthStart).Value = dailyReport.DepthStart; sheet.Cell(cellDepthStart).Value = dailyReport.DepthStart;
sheet.Cell(cellDepthEnd).Value = dailyReport.DepthEnd; sheet.Cell(cellDepthEnd).Value = dailyReport.DepthEnd;
@ -163,18 +161,18 @@ public class DailyReportExportService : IDailyReportExportService
foreach (var wellOperation in timeBalanceBlock.WellOperations.OrderBy(w => w.IdWellOperation)) foreach (var wellOperation in timeBalanceBlock.WellOperations.OrderBy(w => w.IdWellOperation))
{ {
sheet.Cell(rowCurrent, columnTimeBalanceDurationPlan).Value = wellOperation.DurationHours?.Plan; sheet.Cell(rowCurrent, columnTimeBalanceDurationPlan).Value = wellOperation.DurationHours.Plan;
sheet.Cell(rowCurrent, columnTimeBalanceDurationFact).Value = wellOperation.DurationHours?.Fact; sheet.Cell(rowCurrent, columnTimeBalanceDurationFact).Value = wellOperation.DurationHours.Fact;
sheet.Cell(rowCurrent, columnTimeBalanceReasonDeviation).Value = wellOperation.ReasonDeviation; sheet.Cell(rowCurrent, columnTimeBalanceReasonDeviation).Value = wellOperation.ReasonDeviation;
sheet.Cell(rowCurrent, columnTimeBalanceDrillingDeviationPerSection).Value = wellOperation.DrillingDeviationPerSection; sheet.Cell(rowCurrent, columnTimeBalanceDrillingDeviationPerSection).Value = wellOperation.DrillingDeviationPerSection;
sheet.Cell(rowCurrent, columnTimeBalanceDrillingDeviationPerDaily).Value = wellOperation.DrillingDeviationPerDaily; sheet.Cell(rowCurrent, columnTimeBalanceDrillingDeviationPerDay).Value = wellOperation.DrillingDeviationPerDay;
rowCurrent++; rowCurrent++;
} }
sheet.Cell(cellTimeBalanceBlockSection).Value = timeBalanceBlock.SectionName; sheet.Cell(cellTimeBalanceBlockSection).Value = timeBalanceBlock.SectionName;
sheet.Cell(cellTimeBalanceBlockWellDepthPlan).Value = timeBalanceBlock.WellDepthPlan; sheet.Cell(cellTimeBalanceBlockWellDepthPlan).Value = timeBalanceBlock.WellDepth.Plan;
sheet.Cell(cellTimeBalanceBlockWellDepthFact).Value = timeBalanceBlock.WellDepthFact; sheet.Cell(cellTimeBalanceBlockWellDepthFact).Value = timeBalanceBlock.WellDepth.Fact;
sheet.Cell(cellTimeBalanceBlockWellOperationSlipsTimeCount).Value = timeBalanceBlock.WellOperationSlipsTimeCount; sheet.Cell(cellTimeBalanceBlockWellOperationSlipsTimeCount).Value = timeBalanceBlock.WellOperationSlipsTimeCount;
} }

View File

@ -52,31 +52,16 @@ public class DailyReportService : IDailyReportService
this.detectedOperationService = detectedOperationService; this.detectedOperationService = detectedOperationService;
} }
public async Task<int> InsertAsync(int idWell, DateTime dateStart, CancellationToken cancellationToken) public async Task<int> UpdateOrInsertAsync<TBlock>(int idWell, DateTime dateDailyReport, int idUser, TBlock editableBlock,
{
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,
CancellationToken cancellationToken) CancellationToken cancellationToken)
where TBlock : EditableBlock where TBlock : ItemInfoDto
{ {
var dailyReport = await dailyReportRepository.GetOrDefaultAsync(idDailyReport, cancellationToken) var dailyReport = await dailyReportRepository.GetOrDefaultAsync(idWell, dateDailyReport, cancellationToken) ??
?? throw new ArgumentInvalidException(nameof(idDailyReport), $"Суточный отчёт с Id: {idDailyReport} не найден"); new DailyReportDto
{
editableBlock.IdUser = idUser; IdWell = idWell,
Date = dateDailyReport
editableBlock.DateLastUpdate = DateTime.UtcNow; };
dailyReport.DateLastUpdate = DateTime.UtcNow;
switch (editableBlock) switch (editableBlock)
{ {
@ -89,39 +74,46 @@ public class DailyReportService : IDailyReportService
case SignBlockDto signBlock: case SignBlockDto signBlock:
dailyReport.SignBlock = signBlock; dailyReport.SignBlock = signBlock;
break; 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); 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); var well = await wellService.GetOrDefaultAsync(idWell, cancellationToken);
if (well is null) if (well is null)
throw new ArgumentInvalidException($"Скважина с Id: {idWell} не найдена", nameof(idWell)); 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 IdWell = well.Id
}; };
var factWellOperations = await GetFactWellOperationsAsync(idWell, dailyReport.DateStart, dailyReport.DateEnd, var factWellOperations = (await GetFactWellOperationsAsync(idWell, dailyReport.Date, cancellationToken))
cancellationToken); .OrderBy(o => o.DateStart)
.ThenBy(o => o.DepthStart);
dailyReport.WellName = well.Caption; dailyReport.WellCaption = well.Caption;
dailyReport.WellType = well.WellType; dailyReport.WellType = well.WellType;
dailyReport.Cluster = well.Cluster; dailyReport.Cluster = well.Cluster;
dailyReport.Deposit = well.Deposit; dailyReport.Deposit = well.Deposit;
dailyReport.Customer = well.Companies.FirstOrDefault(c => c.IdCompanyType == 1)?.Caption; dailyReport.Customer = well.Companies.FirstOrDefault(c => c.IdCompanyType == 1)?.Caption;
dailyReport.Contractor = well.Companies.FirstOrDefault(c => c.IdCompanyType == 2)?.Caption; dailyReport.Contractor = well.Companies.FirstOrDefault(c => c.IdCompanyType == 2)?.Caption;
dailyReport.DepthStart = factWellOperations.FirstOrDefault()?.DepthStart;
if (factWellOperations.Any()) dailyReport.DepthEnd = factWellOperations.LastOrDefault()?.DepthEnd;
{
dailyReport.DepthStart = factWellOperations.Min(o => o.DepthStart);
dailyReport.DepthEnd = factWellOperations.Max(o => o.DepthEnd);
}
await UpdateTimeBalanceBlockAsync(dailyReport, factWellOperations, cancellationToken); await UpdateTimeBalanceBlockAsync(dailyReport, factWellOperations, cancellationToken);
await UpdateSubsystemBlockAsync(dailyReport, 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++) 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 else
{ {
for (var day = result.Skip; day - result.Skip < result.Take && datesRange.From.AddDays(day) <= datesRange.To; day++) 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; return result;
void AddDailyReport(DateTime dateStart) void AddDailyReport(DateTime date)
{ {
var existingDailyReport = existingDailyReports.FirstOrDefault(d => d.IdWell == idWell && var existingDailyReport = existingDailyReports.FirstOrDefault(d => d.IdWell == idWell && d.Date == date);
d.DateStart == dateStart);
if (existingDailyReport is not null) if (existingDailyReport is not null)
{ {
@ -216,7 +207,7 @@ public class DailyReportService : IDailyReportService
dailyReports.Add(new DailyReportDto dailyReports.Add(new DailyReportDto
{ {
DateStart = dateStart, Date = date,
IdWell = well.Id IdWell = well.Id
}); });
} }
@ -224,16 +215,18 @@ public class DailyReportService : IDailyReportService
public async Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, CancellationToken cancellationToken) public async Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, CancellationToken cancellationToken)
{ {
var factOperations = await GetFactWellOperationsAsync(idWell, null, null, var factOperations = await GetFactWellOperationsAsync(idWell, null, cancellationToken);
cancellationToken);
if (!factOperations.Any()) if (!factOperations.Any())
return null; return null;
var minDateStart = factOperations.Min(o => o.DateStart);
var maxDateStart = factOperations.Max(o => o.DateStart);
return new DatesRangeDto return new DatesRangeDto
{ {
From = factOperations.Min(o => o.DateStart).Date, From = minDateStart.Date.AddDays(1) <= DateTime.UtcNow ? minDateStart : DateTime.UtcNow.Date.AddDays(-1),
To = factOperations.Max(o => o.DateStart).Date To = maxDateStart.AddDays(1) <= DateTime.UtcNow ? maxDateStart : DateTime.UtcNow.Date.AddDays(-1)
}; };
} }
@ -252,13 +245,13 @@ public class DailyReportService : IDailyReportService
{ {
IdsCategories = new[] { idWellOperationSlipsTime }, IdsCategories = new[] { idWellOperationSlipsTime },
IdWell = dailyReport.IdWell, IdWell = dailyReport.IdWell,
GtDate = dailyReport.DateStart, GtDate = dailyReport.Date,
LtDate = dailyReport.DateEnd LtDate = dailyReport.Date.AddHours(24)
}, cancellationToken))?.Stats.Sum(s => s.Count); }, cancellationToken))?.Stats.Sum(s => s.Count);
dailyReport.TimeBalanceBlock.WellDepthFact = factWellOperations dailyReport.TimeBalanceBlock.WellDepth.Fact = factWellOperations
.Where(o => o.IdWellSectionType == dailyReport.TimeBalanceBlock.IdSection) .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 var trajectory = (await trajectoryFactRepository.GetAsync(new TrajectoryGeoFactRequest
{ {
IdWell = dailyReport.IdWell, IdWell = dailyReport.IdWell,
GeDate = dailyReport.DateStart, GeDate = dailyReport.Date,
LeDate = dailyReport.DateEnd LeDate = dailyReport.Date.AddHours(24)
}, cancellationToken)).LastOrDefault(); }, cancellationToken)).MaxBy(t => t.WellboreDepth);
dailyReport.TrajectoryBlock = new TrajectoryBlockDto dailyReport.TrajectoryBlock = new TrajectoryBlockDto
{ {
@ -281,7 +274,7 @@ public class DailyReportService : IDailyReportService
} }
private async Task AddScheduleBlockAsync(DailyReportDto dailyReport, CancellationToken cancellationToken) => 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 .Select(s => new ScheduleRecordDto
{ {
ShiftStart = s.ShiftStart, ShiftStart = s.ShiftStart,
@ -299,13 +292,13 @@ public class DailyReportService : IDailyReportService
async Task<IEnumerable<SubsystemRecordDto>> GetSubsystemsAsync() 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, IdWell = dailyReport.IdWell,
GtDate = dailyReport.DateStart, GtDate = dailyReport.Date,
LtDate = dailyReport.DateEnd LtDate = dailyReport.Date.AddHours(24)
}, cancellationToken)).Select(s => }, cancellationToken)).Select(s =>
{ {
var subsystemRecord = s.Adapt<SubsystemRecordDto>(); var subsystemRecord = s.Adapt<SubsystemRecordDto>();
@ -325,21 +318,21 @@ public class DailyReportService : IDailyReportService
return subsystemRecord; return subsystemRecord;
}); });
modules.AddRange(statSubsystemOperationTimePerDaily); subsystems.AddRange(statSubsystemOperationTimePerDay);
modules.AddRange(statSubsystemOperationTimePerWell); subsystems.AddRange(statSubsystemOperationTimePerWell);
if (dailyReport.SubsystemBlock?.Subsystems != null && dailyReport.SubsystemBlock.Subsystems.Any()) 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) private async Task AddProcessMapWellDrillingBlockAsync(DailyReportDto dailyReport, CancellationToken cancellationToken)
{ {
dailyReport.ProcessMapWellDrillingBlock = (await processMapReportWellDrillingService.GetAsync(dailyReport.IdWell, dailyReport.ProcessMapWellDrillingBlock = (await processMapReportWellDrillingService.GetAsync(dailyReport.IdWell,
cancellationToken)).Where(p => p.DateStart >= dailyReport.DateStart && cancellationToken)).Where(p => p.DateStart >= dailyReport.Date &&
p.DateStart <= dailyReport.DateEnd) p.DateStart <= dailyReport.Date.AddHours(24))
.GroupBy(p => p.DrillingMode) .GroupBy(p => p.DrillingMode)
.Select(g => new ProcessMapWellDrillingRecordDto .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; const int idWellOperationCategoryDrilling = 4001;
@ -373,13 +366,12 @@ public class DailyReportService : IDailyReportService
}; };
} }
private Task<IEnumerable<WellOperationDto>> GetFactWellOperationsAsync(int idWell, DateTime? dailyReportDateStart, private Task<IEnumerable<WellOperationDto>> GetFactWellOperationsAsync(int idWell, DateTime? dateDailyReport, CancellationToken cancellationToken) =>
DateTime? dailyReportDateEnd, CancellationToken cancellationToken) =>
wellOperationRepository.GetAsync(new WellOperationRequest wellOperationRepository.GetAsync(new WellOperationRequest
{ {
IdWell = idWell, IdWell = idWell,
OperationType = WellOperation.IdOperationTypeFact, OperationType = WellOperation.IdOperationTypeFact,
GeDate = dailyReportDateStart, GeDate = dateDailyReport,
LtDate = dailyReportDateEnd LtDate = dateDailyReport?.AddHours(24)
}, cancellationToken); }, cancellationToken);
} }

View File

@ -1,4 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using AsbCloudApp.Data; using AsbCloudApp.Data;
@ -6,11 +8,15 @@ using AsbCloudApp.Data.DailyReport;
using AsbCloudApp.Data.DailyReport.Blocks.Sign; using AsbCloudApp.Data.DailyReport.Blocks.Sign;
using AsbCloudApp.Data.DailyReport.Blocks.Subsystems; using AsbCloudApp.Data.DailyReport.Blocks.Subsystems;
using AsbCloudApp.Data.DailyReport.Blocks.TimeBalance; 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.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services; using AsbCloudApp.Services;
using AsbCloudApp.Services.ProcessMaps.WellDrilling; using AsbCloudApp.Services.ProcessMaps.WellDrilling;
using AsbCloudApp.Services.Subsystems; using AsbCloudApp.Services.Subsystems;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.DailyReport; using AsbCloudInfrastructure.Services.DailyReport;
using NSubstitute; using NSubstitute;
using Xunit; using Xunit;
@ -20,10 +26,169 @@ namespace AsbCloudWebApi.Tests.Services;
public class DailyReportServiceTest public class DailyReportServiceTest
{ {
private const int idDailyReport = 1; private const int idDailyReport = 1;
private const int idWell = 2;
private const int idUser = 3; 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 IWellService wellServiceMock = Substitute.For<IWellService>();
private readonly ITrajectoryFactRepository trajectoryFactRepositoryMock = Substitute.For<ITrajectoryFactRepository>(); private readonly ITrajectoryFactRepository trajectoryFactRepositoryMock = Substitute.For<ITrajectoryFactRepository>();
@ -37,14 +202,26 @@ public class DailyReportServiceTest
private readonly DailyReportService dailyReportService; private readonly DailyReportService dailyReportService;
private readonly DailyReportDto fakeDailyReport; private readonly DailyReportDto fakeDailyReport;
private readonly WellDto fakeWell;
public DailyReportServiceTest() public DailyReportServiceTest()
{ {
fakeDailyReport = new() fakeDailyReport = new DailyReportDto
{ {
Id = idDailyReport, Id = idDailyReport,
IdWell = idWell, 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, dailyReportService = new DailyReportService(wellServiceMock,
@ -59,139 +236,276 @@ public class DailyReportServiceTest
dailyReportRepositoryMock.InsertAsync(Arg.Any<DailyReportDto>(), Arg.Any<CancellationToken>()) dailyReportRepositoryMock.InsertAsync(Arg.Any<DailyReportDto>(), Arg.Any<CancellationToken>())
.ReturnsForAnyArgs(idDailyReport); .ReturnsForAnyArgs(idDailyReport);
dailyReportRepositoryMock.GetOrDefaultAsync(idDailyReport, Arg.Any<CancellationToken>()) dailyReportRepositoryMock.GetOrDefaultAsync(Arg.Any<int>(), Arg.Any<DateTime>(), Arg.Any<CancellationToken>())
.Returns(fakeDailyReport); .ReturnsForAnyArgs(fakeDailyReport);
dailyReportRepositoryMock.UpdateAsync(Arg.Any<DailyReportDto>(), Arg.Any<CancellationToken>()) dailyReportRepositoryMock.UpdateAsync(Arg.Any<DailyReportDto>(), Arg.Any<CancellationToken>())
.ReturnsForAnyArgs(idDailyReport); .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] [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 //act
Task Result() => dailyReportService.InsertAsync(idWell, dateStart, CancellationToken.None); var result = await dailyReportService.UpdateOrInsertAsync(idWell, dateDailyReport, idUser, fakeSubsystemBlock, 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);
//assert //assert
Assert.NotNull(fakeSubsystemBlock.LastUpdateDate);
Assert.NotNull(fakeDailyReport.DateLastUpdate);
Assert.Equal(fakeSubsystemBlock.IdUser, idUser);
Assert.Equal(fakeDailyReport.SubsystemBlock, fakeSubsystemBlock);
Assert.Equal(idDailyReport, result); Assert.Equal(idDailyReport, result);
} }
[Fact] [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 //act
var result = await dailyReportService.UpdateBlockAsync(idDailyReport, idUser, fakeSubsystemBlock, CancellationToken.None); var result = await dailyReportService.UpdateOrInsertAsync(idWell, dateDailyReport, idUser, fakeSignBlock, 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);
//assert //assert
Assert.NotNull(fakeSignBlock.DateLastUpdate); Assert.NotNull(fakeSignBlock.LastUpdateDate);
Assert.NotNull(fakeDailyReport.DateLastUpdate); Assert.NotNull(fakeDailyReport.DateLastUpdate);
Assert.Equal(fakeSignBlock.IdUser, idUser);
Assert.Equal(fakeDailyReport.SignBlock, fakeSignBlock); Assert.Equal(fakeDailyReport.SignBlock, fakeSignBlock);
Assert.Equal(idDailyReport, result); Assert.Equal(idDailyReport, result);
} }
[Fact] [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 //act
var result = await dailyReportService.UpdateBlockAsync(idDailyReport, idUser, fakeTimeBalanceBlock, CancellationToken.None); var result = await dailyReportService.UpdateOrInsertAsync(idWell, dateDailyReport, idUser, fakeTimeBalanceBlock,
CancellationToken.None);
//assert //assert
Assert.NotNull(fakeTimeBalanceBlock.DateLastUpdate); Assert.NotNull(fakeTimeBalanceBlock.LastUpdateDate);
Assert.NotNull(fakeDailyReport.DateLastUpdate); Assert.NotNull(fakeDailyReport.DateLastUpdate);
Assert.Equal(fakeTimeBalanceBlock.IdUser, idUser);
Assert.Equal(fakeDailyReport.TimeBalanceBlock, fakeTimeBalanceBlock); Assert.Equal(fakeDailyReport.TimeBalanceBlock, fakeTimeBalanceBlock);
Assert.Equal(idDailyReport, result); 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 System.Threading.Tasks;
using AsbCloudApp.Data; using AsbCloudApp.Data;
using AsbCloudApp.Data.DailyReport; using AsbCloudApp.Data.DailyReport;
using AsbCloudApp.Data.DailyReport.Blocks;
using AsbCloudApp.Data.DailyReport.Blocks.Sign; using AsbCloudApp.Data.DailyReport.Blocks.Sign;
using AsbCloudApp.Data.DailyReport.Blocks.Subsystems; using AsbCloudApp.Data.DailyReport.Blocks.Subsystems;
using AsbCloudApp.Data.DailyReport.Blocks.TimeBalance; 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>
/// Обновить подпись /// Обновить подпись
/// </summary> /// </summary>
/// <param name="idWell">Id скважины</param> /// <param name="idWell">Id скважины</param>
/// <param name="idDailyReport">Id суточного отчёта</param> /// <param name="dateDailyReport">Дата суточного отчёта</param>
/// <param name="signBlock">Обновляемый блок</param> /// <param name="signBlock">Обновляемый блок</param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
@ -97,14 +68,15 @@ public class DailyReportController : ControllerBase
[Permission] [Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)] [ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public Task<IActionResult> UpdateSignBlockAsync(int idWell, int idDailyReport, SignBlockDto signBlock, CancellationToken cancellationToken) => public Task<IActionResult> UpdateSignBlockAsync(int idWell, DateOnly dateDailyReport, SignBlockDto signBlock,
UpdateBlockAsync(idWell, idDailyReport, signBlock, cancellationToken); CancellationToken cancellationToken) =>
UpdateOrInsertAsync(idWell, dateDailyReport, signBlock, cancellationToken);
/// <summary> /// <summary>
/// Обновить наработку подсистем /// Обновить наработку подсистем
/// </summary> /// </summary>
/// <param name="idWell">Id скважины</param> /// <param name="idWell">Id скважины</param>
/// <param name="idDailyReport">Id суточного отчёта</param> /// <param name="dateDailyReport">Дата суточного отчёта</param>
/// <param name="subsystemBlock">Обновляемый блок</param> /// <param name="subsystemBlock">Обновляемый блок</param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
@ -112,7 +84,7 @@ public class DailyReportController : ControllerBase
[Permission] [Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)] [ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] [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) CancellationToken cancellationToken)
{ {
var validSubsystemNames = new[] { "АвтоСПО", "Автопроработка" }; var validSubsystemNames = new[] { "АвтоСПО", "Автопроработка" };
@ -121,14 +93,14 @@ public class DailyReportController : ControllerBase
throw new ArgumentInvalidException($"Возможно добавить подсистемы с именами {string.Join(", ", validSubsystemNames)}", throw new ArgumentInvalidException($"Возможно добавить подсистемы с именами {string.Join(", ", validSubsystemNames)}",
nameof(subsystemBlock.Subsystems)); nameof(subsystemBlock.Subsystems));
return UpdateBlockAsync(idWell, idDailyReport, subsystemBlock, cancellationToken); return UpdateOrInsertAsync(idWell, dateDailyReport, subsystemBlock, cancellationToken);
} }
/// <summary> /// <summary>
/// Обновить баланс времени /// Обновить баланс времени
/// </summary> /// </summary>
/// <param name="idWell">Id скважины</param> /// <param name="idWell">Id скважины</param>
/// <param name="idDailyReport">Id суточного отчёта</param> /// <param name="dateDailyReport">Дата суточного отчёта</param>
/// <param name="timeBalanceBlock">Обновляемый блок</param> /// <param name="timeBalanceBlock">Обновляемый блок</param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
@ -136,7 +108,7 @@ public class DailyReportController : ControllerBase
[Permission] [Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)] [ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] [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) CancellationToken cancellationToken)
{ {
var validWellOperationsIds = new[] { 1, 2, 3, 4 }; var validWellOperationsIds = new[] { 1, 2, 3, 4 };
@ -150,7 +122,7 @@ public class DailyReportController : ControllerBase
if (wellSections.All(s => s.Id != timeBalanceBlock.IdSection)) if (wellSections.All(s => s.Id != timeBalanceBlock.IdSection))
throw new ArgumentInvalidException($"Секция с Id: {timeBalanceBlock.IdSection} не найдена", nameof(timeBalanceBlock.IdSection)); throw new ArgumentInvalidException($"Секция с Id: {timeBalanceBlock.IdSection} не найдена", nameof(timeBalanceBlock.IdSection));
return UpdateBlockAsync(idWell, idDailyReport, timeBalanceBlock, cancellationToken); return UpdateOrInsertAsync(idWell, dateDailyReport, timeBalanceBlock, cancellationToken);
} }
/// <summary> /// <summary>
@ -193,36 +165,37 @@ public class DailyReportController : ControllerBase
/// Экспорт суточного рапорта /// Экспорт суточного рапорта
/// </summary> /// </summary>
/// <param name="idWell">Id скважины</param> /// <param name="idWell">Id скважины</param>
/// <param name="dateStart">Дата формирования суточного отчёта</param> /// <param name="dateDailyReport">Дата формирования суточного отчёта</param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet("{dateStart}")] [HttpGet("{dateDailyReport}")]
[ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK)] [ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] [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); var datesRange = await dailyReportService.GetDatesRangeAsync(idWell, cancellationToken);
if (dateStartToDateTime < datesRange?.From || dateStartToDateTime > datesRange?.To) if (dateStartToDateTime < datesRange?.From || dateStartToDateTime > datesRange?.To)
throw new ArgumentInvalidException("Невозможно получить суточный отчёт", nameof(dateStart)); throw new ArgumentInvalidException("Невозможно получить суточный отчёт", nameof(dateDailyReport));
await AssertUserAccessToWell(idWell, cancellationToken); await AssertUserAccessToWell(idWell, cancellationToken);
var dailyReport = await dailyReportExportService.ExportAsync(idWell, 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); 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) CancellationToken cancellationToken)
where TBlock : EditableBlock where TBlock : ItemInfoDto
{ {
await AssertUserAccessToWell(idWell, cancellationToken); 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); return Ok(id);
} }