Доработки

1. Добавлен шаблон суточного отчёта
2. Рефакторинг DTO для суточного отчёта
3. Обновлена валидация входных данных в методах контроллера
4. Небольшой рефакторинг сервисов
This commit is contained in:
Степанов Дмитрий 2023-11-07 15:57:15 +05:00
parent af5d713fc7
commit dcaec8b4a2
10 changed files with 62 additions and 45 deletions

View File

@ -6,11 +6,9 @@ namespace AsbCloudApp.Data.DailyReport.Blocks;
public class ProcessMapWellDrillingRecordDto
{
/// <summary>
/// Id режима бурения
/// 1 - ротор
/// 2 - слайд
/// Режим бурения
/// </summary>
public int IdMode { get; set; }
public string DrillingMode { get; set; } = null!;
/// <summary>
/// Мех. скорость

View File

@ -8,15 +8,9 @@ namespace AsbCloudApp.Data.DailyReport.Blocks.Subsystems;
public class SubsystemRecordDto
{
/// <summary>
/// 1 - АПД, ч/м
/// 11 - АПД ротор
/// 12 - АПД слайд
/// 65536 - Осцилляция
/// 65537 - Демпфер
/// 100000 - Автопроработка
/// 100001 - АвтоСПО
/// Название подсистемы
/// </summary>
public int IdSubsystem { get; set; }
public string SubsystemName { get; set; } = null!;
/// <summary>
/// Идентификатор временного интервала

View File

@ -15,6 +15,11 @@ public class TimeBalanceBlockDto : EditableBlock
[Range(1, int.MaxValue)]
public int IdSection { get; set; }
/// <summary>
/// Название секции
/// </summary>
public string? SectionName { get; set; }
/// <summary>
/// Плановая проходка скважины
/// </summary>

View File

@ -6,10 +6,10 @@ namespace AsbCloudApp.Data.DailyReport.Blocks.TimeBalance;
public class TimeBalanceRecordDto
{
/// <summary>
/// Мех. бурение - 4001
/// Статический замер - 4002
/// Наращивание - 4004
/// Промывка, ОБР - 4012
/// Мех. бурение - 1
/// Снятие замера, ориентирование - 2
/// Наращивание, выход на режим - 3
/// Промывка, проработка - 4
/// </summary>
public int IdWellOperation { get; set; }

View File

@ -6,9 +6,9 @@ namespace AsbCloudApp.Data.DailyReport.Blocks.WellOperation;
public class WellOperationRecordDto
{
/// <summary>
/// Id категории операции
/// Название категории
/// </summary>
public int? IdWellCategory { get; set; }
public string? CategoryName { get; set; }
/// <summary>
/// Продолжительность операции

View File

@ -43,7 +43,7 @@ public class DailyReportExportService : IDailyReportExportService
private const int columnUseSubsystemPerWellSumDepthInterval = 7;
private const int columnUseSubsystemPerWellKUsage = 8;
private const int columnProcessMapWellDrillingBlockMode = 2;
private const int columnProcessMapWellDrillingBlockDrillingMode = 2;
private const int columnProcessMapWellDrillingBlockWellBoreDepth = 3;
private const int columnProcessMapWellDrillingBlockMechDrillingHours = 4;
private const int columnProcessMapWellDrillingBlockRopPlan = 5;
@ -95,12 +95,12 @@ 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.WellName}_куст_{dailyReport.Cluster}_от_{dailyReport.DateStart:yy-MM-dd}.xlsx";
return (fileName, stream);
}
private async Task<Stream> GenerateFileAsync(DailyReportDto dailyReport, CancellationToken cancellationToken)
private static async Task<Stream> GenerateFileAsync(DailyReportDto dailyReport, CancellationToken cancellationToken)
{
using var excelTemplateStream = await Assembly
.GetExecutingAssembly()
@ -172,7 +172,7 @@ public class DailyReportExportService : IDailyReportExportService
rowCurrent++;
}
sheet.Cell(cellTimeBalanceBlockSection).Value = timeBalanceBlock.IdSection;
sheet.Cell(cellTimeBalanceBlockSection).Value = timeBalanceBlock.SectionName;
sheet.Cell(cellTimeBalanceBlockWellDepthPlan).Value = timeBalanceBlock.WellDepthPlan;
sheet.Cell(cellTimeBalanceBlockWellDepthFact).Value = timeBalanceBlock.WellDepthFact;
sheet.Cell(cellTimeBalanceBlockCountWellOperationSlipsTime).Value = timeBalanceBlock.CountWellOperationSlipsTime;
@ -180,8 +180,8 @@ public class DailyReportExportService : IDailyReportExportService
private static void AddSubsystemBlockToSheet(IXLWorksheet sheet, SubsystemBlockDto subsystemBlock)
{
var groupedModules = subsystemBlock.Modules.OrderBy(m => m.IdSubsystem)
.GroupBy(m => m.IdSubsystem);
var groupedModules = subsystemBlock.Modules.OrderBy(m => m.SubsystemName)
.GroupBy(m => m.SubsystemName);
var rowСurrent = rowStartSubsystemBlock;
@ -228,9 +228,9 @@ public class DailyReportExportService : IDailyReportExportService
{
var rowCurrent = rowStartProcessMapWellDrillingBlock;
foreach (var processMapWellDrilling in processMapWellDrillingBlock.OrderBy(p => p.IdMode))
foreach (var processMapWellDrilling in processMapWellDrillingBlock.OrderBy(p => p.DrillingMode))
{
sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockMode).Value = processMapWellDrilling.IdMode;
sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockDrillingMode).Value = processMapWellDrilling.DrillingMode;
sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockWellBoreDepth).Value = processMapWellDrilling.WellBoreDepth;
sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockMechDrillingHours).Value = processMapWellDrilling.MechDrillingHours;
sheet.Cell(rowCurrent, columnProcessMapWellDrillingBlockRopPlan).Value = processMapWellDrilling.Rop.Plan;
@ -244,9 +244,9 @@ public class DailyReportExportService : IDailyReportExportService
{
sheet.Cell(cellDurationHoursDrillingPerSection).Value = factWellOperationBlock.DurationHoursDrillingPerSection;
foreach (var factOperation in factWellOperationBlock.WellOperations.OrderBy(w => w.IdWellCategory))
foreach (var factOperation in factWellOperationBlock.WellOperations.OrderBy(w => w.CategoryName))
{
sheet.Cell(rowStartFactWellOperationBlock, columnWellOperationCategory).Value = factOperation.IdWellCategory;
sheet.Cell(rowStartFactWellOperationBlock, columnWellOperationCategory).Value = factOperation.CategoryName;
sheet.Cell(rowStartFactWellOperationBlock, columnWellOperationDurationHours).Value = factOperation.DurationHours;
}
}

View File

@ -115,8 +115,12 @@ public class DailyReportService : IDailyReportService
dailyReport.Deposit = well.Deposit;
dailyReport.Customer = well.Companies.FirstOrDefault(c => c.IdCompanyType == 1)?.Caption;
dailyReport.Contractor = well.Companies.FirstOrDefault(c => c.IdCompanyType == 2)?.Caption;
dailyReport.DepthStart = factWellOperations.Min(o => o.DepthStart);
dailyReport.DepthEnd = factWellOperations.Max(o => o.DepthEnd);
if (factWellOperations.Any())
{
dailyReport.DepthStart = factWellOperations.Min(o => o.DepthStart);
dailyReport.DepthEnd = factWellOperations.Max(o => o.DepthEnd);
}
await UpdateTimeBalanceBlockAsync(dailyReport, factWellOperations, cancellationToken);
await UpdateSubsystemBlockAsync(dailyReport, cancellationToken);
@ -239,6 +243,9 @@ public class DailyReportService : IDailyReportService
if (dailyReport.TimeBalanceBlock is not null)
{
dailyReport.TimeBalanceBlock.SectionName = wellOperationRepository.GetSectionTypes()
.FirstOrDefault(s => s.Id == dailyReport.TimeBalanceBlock.IdSection)?.Caption;
dailyReport.TimeBalanceBlock.CountWellOperationSlipsTime = (await detectedOperationService.GetAsync(
new DetectedOperationRequest
{
@ -333,10 +340,10 @@ public class DailyReportService : IDailyReportService
cancellationToken)).Where(p => p.DateStart >= dailyReport.DateStart &&
p.DateStart <= dailyReport.DateEnd &&
p.IdMode.HasValue)
.GroupBy(p => p.IdMode)
.GroupBy(p => p.DrillingMode)
.Select(g => new ProcessMapWellDrillingRecordDto
{
IdMode = g.Key!.Value,
DrillingMode = g.Key,
WellBoreDepth = g.Sum(p => p.DeltaDepth),
Rop = new PlanFactDto<double?>
{
@ -356,7 +363,7 @@ public class DailyReportService : IDailyReportService
WellOperations = factWellOperations.GroupBy(o => o.IdParentCategory)
.Select(g => new WellOperationRecordDto
{
IdWellCategory = g.Key,
CategoryName = g.First().CategoryName,
DurationHours = g.Sum(o => o.DurationHours)
}),

View File

@ -110,7 +110,7 @@ public class DailyReportServiceTest
{
new SubsystemRecordDto
{
IdSubsystem = 10000,
SubsystemName = "АвтоСПО",
IdTimeInterval = 1,
UsedTimeHours = 24,
SumDepthInterval = 1500,

View File

@ -70,6 +70,13 @@ public class DailyReportController : ControllerBase
[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),
@ -90,8 +97,7 @@ 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) =>
public Task<IActionResult> UpdateSignBlockAsync(int idWell, int idDailyReport, SignBlockDto signBlock, CancellationToken cancellationToken) =>
UpdateBlockAsync(idWell, idDailyReport, signBlock, cancellationToken);
/// <summary>
@ -109,10 +115,10 @@ public class DailyReportController : ControllerBase
public Task<IActionResult> UpdateSubsystemBlockAsync(int idWell, int idDailyReport, SubsystemBlockDto subsystemBlock,
CancellationToken cancellationToken)
{
var validSubsystemIds = new[] { 100000, 100001 };
var validSubsystemNames = new[] { "АвтоСПО", "Автопроработка" };
if (subsystemBlock.Modules.Any(m => !validSubsystemIds.Contains(m.IdSubsystem)))
throw new ArgumentInvalidException($"Возможно добавить модули только с Id: {string.Join(", ", validSubsystemIds)}",
if (subsystemBlock.Modules.Any(m => !validSubsystemNames.Contains(m.SubsystemName)))
throw new ArgumentInvalidException($"Возможно добавить модули только с именами {string.Join(", ", validSubsystemNames)}",
nameof(subsystemBlock.Modules));
return UpdateBlockAsync(idWell, idDailyReport, subsystemBlock, cancellationToken);
@ -133,10 +139,10 @@ public class DailyReportController : ControllerBase
public Task<IActionResult> UpdateTimeBalanceBlockAsync(int idWell, int idDailyReport, TimeBalanceBlockDto timeBalanceBlock,
CancellationToken cancellationToken)
{
var validWellOperationsIds = new[] { 4001, 4002, 4004, 4012 };
var validWellOperationsIds = new[] { 1, 2, 3, 4 };
if (timeBalanceBlock.WellOperations.Any(o => !validWellOperationsIds.Contains(o.IdWellOperation)))
throw new ArgumentInvalidException($"Возможно добавить операции только с Id: {string.Join(",", validWellOperationsIds)}",
throw new ArgumentInvalidException($"Возможно добавить операции только с Id: {string.Join(", ", validWellOperationsIds)}",
nameof(timeBalanceBlock.WellOperations));
var wellSections = wellOperationRepository.GetSectionTypes();
@ -187,18 +193,25 @@ public class DailyReportController : ControllerBase
/// Экспорт суточного рапорта
/// </summary>
/// <param name="idWell">Id скважины</param>
/// <param name="dailyReportDateStart">Дата формирования суточного отчёта</param>
/// <param name="dateStart">Дата формирования суточного отчёта</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet("{dailyReportDateStart}")]
[HttpGet("{dateStart}")]
[ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> ExportAsync(int idWell, DateOnly dailyReportDateStart, CancellationToken cancellationToken)
public async Task<IActionResult> ExportAsync(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 dailyReport = await dailyReportExportService.ExportAsync(idWell,
dailyReportDateStart.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc), cancellationToken);
dateStart.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc), cancellationToken);
return File(dailyReport.File, "application/octet-stream", dailyReport.FileName);
}