forked from ddrilling/AsbCloudServer
Формирование суточных отчётов
1. Добавил сервис для работы с суточными отчётами. 2. Сделал формирование отчёта в Excel файле по заготовленному шаблону. 3. Поправил Dto. 4. Реализация методов в контроллере + небольшое исправление. В методе получения списка добавил запрос, который позволяет получать данные по параметрам.
This commit is contained in:
parent
d0d8d48c4e
commit
1413e80f09
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace AsbCloudApp.Data.AutogeneratedDailyReport;
|
namespace AsbCloudApp.Data.AutogeneratedDailyReport;
|
||||||
|
|
||||||
@ -31,15 +30,15 @@ public class AutoGeneratedDailyReportDto
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Блок подсистем
|
/// Блок подсистем
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<SubsystemRecordDto> Subsystems { get; set; } = null!;
|
public SubsystemRecordDto[] Subsystems { get; set; } = null!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Блок ограничивающих параметров
|
/// Блок ограничивающих параметров
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<LimitingParameterRecordDto> LimitingParameters { get; set; } = null!;
|
public LimitingParameterRecordDto[] LimitingParameters { get; set; } = null!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Баланс времени
|
/// Баланс времени
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<TimeBalanceRecordDto> TimeBalance { get; set; } = null!;
|
public TimeBalanceRecordDto[] TimeBalance { get; set; } = null!;
|
||||||
}
|
}
|
@ -10,6 +10,11 @@ public class LimitingParameterRecordDto
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public double TotalHours { get; set; }
|
public double TotalHours { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Проходка
|
||||||
|
/// </summary>
|
||||||
|
public double Depth { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Название ограничивающего параметра
|
/// Название ограничивающего параметра
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
19
AsbCloudApp/Requests/AutoGeneratedDailyReportRequest.cs
Normal file
19
AsbCloudApp/Requests/AutoGeneratedDailyReportRequest.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Requests;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Параметры запроса для получения авто-генерируемых суточных отчётов
|
||||||
|
/// </summary>
|
||||||
|
public class AutoGeneratedDailyReportRequest : RequestBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Дата начала периода
|
||||||
|
/// </summary>
|
||||||
|
public DateOnly? StartDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Дата конца периода
|
||||||
|
/// </summary>
|
||||||
|
public DateOnly? FinishDate { get; set; }
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AsbCloudApp.Data.AutogeneratedDailyReport;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Services.AutoGeneratedDailyReports;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Сервис для генерации файлов авто-генерируемых суточный отчётов
|
||||||
|
/// </summary>
|
||||||
|
public interface IAutoGeneratedDailyReportMakerService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Генерация файла
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="report"></param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<Stream> MakeReportAsync(AutoGeneratedDailyReportDto report, CancellationToken cancellationToken);
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.AutogeneratedDailyReport;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Services.AutoGeneratedDailyReports;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Сервис для работы с авто-генерируемыми суточными отчётами
|
||||||
|
/// </summary>
|
||||||
|
public interface IAutoGeneratedDailyReportService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Список файлов суточных отчётов
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idWell"></param>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<PaginationContainer<AutoGeneratedDailyReportDto>> GetListAsync(int idWell,
|
||||||
|
AutoGeneratedDailyReportRequest request,
|
||||||
|
CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Генерация файла с отчётом
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idWell"></param>
|
||||||
|
/// <param name="reportDate"></param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<(string fileName, Stream stream)> GenerateReportAsync(int idWell, DateOnly reportDate,
|
||||||
|
CancellationToken cancellationToken);
|
||||||
|
}
|
@ -36,6 +36,7 @@
|
|||||||
<EmbeddedResource Include="Services\WellOperationService\ScheduleReportTemplate.xlsx" />
|
<EmbeddedResource Include="Services\WellOperationService\ScheduleReportTemplate.xlsx" />
|
||||||
<EmbeddedResource Include="Services\WellOperationService\WellOperationImportTemplate.xlsx" />
|
<EmbeddedResource Include="Services\WellOperationService\WellOperationImportTemplate.xlsx" />
|
||||||
<EmbeddedResource Include="Services\ProcessMap\ProcessMapPlanTemplate.xlsx" />
|
<EmbeddedResource Include="Services\ProcessMap\ProcessMapPlanTemplate.xlsx" />
|
||||||
|
<EmbeddedResource Include="Services\AutoGeneratedDailyReports\AutogeneratedDailyReportTemplate.xlsx" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -23,7 +23,9 @@ using Microsoft.Extensions.Caching.Memory;
|
|||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System;
|
using System;
|
||||||
|
using AsbCloudApp.Services.AutoGeneratedDailyReports;
|
||||||
using AsbCloudApp.Services.Notifications;
|
using AsbCloudApp.Services.Notifications;
|
||||||
|
using AsbCloudInfrastructure.Services.AutoGeneratedDailyReports;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure
|
namespace AsbCloudInfrastructure
|
||||||
{
|
{
|
||||||
@ -217,6 +219,9 @@ namespace AsbCloudInfrastructure
|
|||||||
services.AddTransient<IWitsRecordRepository<AsbCloudApp.Data.WITS.Record60Dto>, WitsRecordRepository<AsbCloudApp.Data.WITS.Record60Dto, AsbCloudDb.Model.WITS.Record60>>();
|
services.AddTransient<IWitsRecordRepository<AsbCloudApp.Data.WITS.Record60Dto>, WitsRecordRepository<AsbCloudApp.Data.WITS.Record60Dto, AsbCloudDb.Model.WITS.Record60>>();
|
||||||
services.AddTransient<IWitsRecordRepository<AsbCloudApp.Data.WITS.Record61Dto>, WitsRecordRepository<AsbCloudApp.Data.WITS.Record61Dto, AsbCloudDb.Model.WITS.Record61>>();
|
services.AddTransient<IWitsRecordRepository<AsbCloudApp.Data.WITS.Record61Dto>, WitsRecordRepository<AsbCloudApp.Data.WITS.Record61Dto, AsbCloudDb.Model.WITS.Record61>>();
|
||||||
|
|
||||||
|
services.AddTransient<IAutoGeneratedDailyReportService, AutoGeneratedDailyReportService>();
|
||||||
|
services.AddTransient<IAutoGeneratedDailyReportMakerService, AutoGeneratedDailyReportMakerService>();
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AsbCloudApp.Data.AutogeneratedDailyReport;
|
||||||
|
using AsbCloudApp.Services.AutoGeneratedDailyReports;
|
||||||
|
using AsbCloudInfrastructure.Services.AutoGeneratedDailyReports.AutogeneratedDailyReportBlocks;
|
||||||
|
using ClosedXML.Excel;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.AutoGeneratedDailyReports;
|
||||||
|
|
||||||
|
public class AutoGeneratedDailyReportMakerService : IAutoGeneratedDailyReportMakerService
|
||||||
|
{
|
||||||
|
private readonly IEnumerable<IExcelBlockWriter> blockWriters = new List<IExcelBlockWriter>()
|
||||||
|
{
|
||||||
|
new HeadExcelBlockWriter(),
|
||||||
|
new SubsystemExcelBlockWriter(),
|
||||||
|
new LimitingParameterExcelBlockWriter(),
|
||||||
|
new TimeBalanceExcelBlockWriter()
|
||||||
|
};
|
||||||
|
|
||||||
|
public async Task<Stream> MakeReportAsync(AutoGeneratedDailyReportDto report, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
using var excelTemplateStream = await GetExcelTemplateStreamAsync(cancellationToken);
|
||||||
|
|
||||||
|
using var workbook = new XLWorkbook(excelTemplateStream, XLEventTracking.Disabled);
|
||||||
|
|
||||||
|
AddToWorkbook(workbook, report);
|
||||||
|
|
||||||
|
MemoryStream memoryStream = new MemoryStream();
|
||||||
|
workbook.SaveAs(memoryStream, new SaveOptions { });
|
||||||
|
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
return memoryStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<Stream> GetExcelTemplateStreamAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var resourceName = Assembly.GetExecutingAssembly()
|
||||||
|
.GetManifestResourceNames()
|
||||||
|
.FirstOrDefault(n => n.EndsWith("AutogeneratedDailyReportTemplate.xlsx"))!;
|
||||||
|
|
||||||
|
using var stream = Assembly.GetExecutingAssembly()
|
||||||
|
.GetManifestResourceStream(resourceName)!;
|
||||||
|
|
||||||
|
var memoryStream = new MemoryStream();
|
||||||
|
await stream.CopyToAsync(memoryStream, cancellationToken);
|
||||||
|
memoryStream.Position = 0;
|
||||||
|
|
||||||
|
return memoryStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddToWorkbook(XLWorkbook workbook, AutoGeneratedDailyReportDto report)
|
||||||
|
{
|
||||||
|
const string sheetName = "Рапорт";
|
||||||
|
|
||||||
|
var sheet = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetName)
|
||||||
|
?? throw new FileFormatException($"Книга excel не содержит листа {sheetName}.");
|
||||||
|
|
||||||
|
foreach (var blockBuilder in blockWriters)
|
||||||
|
{
|
||||||
|
blockBuilder.Write(sheet, report);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,242 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.AutogeneratedDailyReport;
|
||||||
|
using AsbCloudApp.Data.SAUB;
|
||||||
|
using AsbCloudApp.Data.Subsystems;
|
||||||
|
using AsbCloudApp.Exceptions;
|
||||||
|
using AsbCloudApp.Repositories;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
using AsbCloudApp.Services.AutoGeneratedDailyReports;
|
||||||
|
using AsbCloudApp.Services.Subsystems;
|
||||||
|
using AsbCloudDb.Model;
|
||||||
|
using AsbCloudInfrastructure.Services.SAUB;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.AutoGeneratedDailyReports;
|
||||||
|
|
||||||
|
public class AutoGeneratedDailyReportService : IAutoGeneratedDailyReportService
|
||||||
|
{
|
||||||
|
private const string fileNameTemplate = "Суточный_отчёт_по_скважине_{0}_куст_{1}_от_{2}.xlsx";
|
||||||
|
|
||||||
|
private readonly IWellService wellService;
|
||||||
|
private readonly IWellOperationRepository wellOperationRepository;
|
||||||
|
private readonly TelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache;
|
||||||
|
private readonly ISubsystemOperationTimeService subsystemOperationTimeService;
|
||||||
|
private readonly ICrudRepository<SubsystemDto> subsystemRepository;
|
||||||
|
private readonly ILimitingParameterService limitingParameterService;
|
||||||
|
private readonly IAutoGeneratedDailyReportMakerService autoGeneratedDailyReportMakerService;
|
||||||
|
|
||||||
|
public AutoGeneratedDailyReportService(IWellService wellService,
|
||||||
|
IWellOperationRepository wellOperationRepository,
|
||||||
|
TelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache,
|
||||||
|
ISubsystemOperationTimeService subsystemOperationTimeService,
|
||||||
|
ICrudRepository<SubsystemDto> subsystemRepository,
|
||||||
|
ILimitingParameterService limitingParameterService,
|
||||||
|
IAutoGeneratedDailyReportMakerService autoGeneratedDailyReportMakerService)
|
||||||
|
{
|
||||||
|
this.wellOperationRepository = wellOperationRepository;
|
||||||
|
this.wellService = wellService;
|
||||||
|
this.telemetryDataCache = telemetryDataCache;
|
||||||
|
this.subsystemOperationTimeService = subsystemOperationTimeService;
|
||||||
|
this.subsystemRepository = subsystemRepository;
|
||||||
|
this.limitingParameterService = limitingParameterService;
|
||||||
|
this.autoGeneratedDailyReportMakerService = autoGeneratedDailyReportMakerService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PaginationContainer<AutoGeneratedDailyReportDto>> GetListAsync(int idWell,
|
||||||
|
AutoGeneratedDailyReportRequest request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = new PaginationContainer<AutoGeneratedDailyReportDto>
|
||||||
|
{
|
||||||
|
Skip = request.Skip ?? 0,
|
||||||
|
Take = request.Take ?? 10,
|
||||||
|
};
|
||||||
|
|
||||||
|
var reports = new List<AutoGeneratedDailyReportDto>();
|
||||||
|
|
||||||
|
var well = await wellService.GetOrDefaultAsync(idWell, cancellationToken)
|
||||||
|
?? throw new ArgumentInvalidException("Скважина не найдена", nameof(idWell));
|
||||||
|
|
||||||
|
if (!well.IdTelemetry.HasValue)
|
||||||
|
throw new ArgumentInvalidException("Телеметрия для скважины отсутствует", nameof(idWell));
|
||||||
|
|
||||||
|
var datesRange = telemetryDataCache.GetOrDefaultDataDateRange(well.IdTelemetry.Value);
|
||||||
|
|
||||||
|
if (datesRange is null)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (request.StartDate.HasValue)
|
||||||
|
{
|
||||||
|
var startDate = new DateTime(request.StartDate.Value.Year, request.StartDate.Value.Month,
|
||||||
|
request.StartDate.Value.Day);
|
||||||
|
|
||||||
|
datesRange.From = startDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.FinishDate.HasValue)
|
||||||
|
{
|
||||||
|
var finishDate = new DateTime(request.FinishDate.Value.Year, request.FinishDate.Value.Month,
|
||||||
|
request.FinishDate.Value.Day);
|
||||||
|
|
||||||
|
datesRange.To = finishDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var dateFrom = datesRange.From; dateFrom <= datesRange.To; dateFrom = dateFrom.AddDays(1))
|
||||||
|
{
|
||||||
|
reports.Add(new AutoGeneratedDailyReportDto
|
||||||
|
{
|
||||||
|
FileName = string.Format(fileNameTemplate, well.Caption, well.Cluster, DateOnly.FromDateTime(dateFrom)),
|
||||||
|
ReportDate = DateOnly.FromDateTime(dateFrom),
|
||||||
|
FileSize = GetFileSize() / 1024,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Items = reports.Skip(result.Skip).Take(result.Take);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<(string fileName, Stream stream)> GenerateReportAsync(int idWell, DateOnly reportDate,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var startDate = new DateTime(reportDate.Year, reportDate.Month, reportDate.Day);
|
||||||
|
var finishDate = startDate.AddDays(1);
|
||||||
|
|
||||||
|
var well = await wellService.GetOrDefaultAsync(idWell, cancellationToken)
|
||||||
|
?? throw new ArgumentInvalidException("Скважина не найдена", nameof(idWell));
|
||||||
|
|
||||||
|
if (!well.IdTelemetry.HasValue)
|
||||||
|
throw new ArgumentInvalidException("Телеметрия для скважины отсутствует", nameof(idWell));
|
||||||
|
|
||||||
|
var factOperations = (await GetFactOperationsAsync(well.Id, startDate, finishDate,
|
||||||
|
cancellationToken)).ToArray();
|
||||||
|
|
||||||
|
var report = new AutoGeneratedDailyReportDto
|
||||||
|
{
|
||||||
|
FileName = string.Format(fileNameTemplate, well.Caption, well.Cluster, reportDate),
|
||||||
|
FileSize = GetFileSize() / 1024,
|
||||||
|
ReportDate = reportDate,
|
||||||
|
Head = CreateHeadBlock(well, reportDate, factOperations),
|
||||||
|
Subsystems = (await CreateSubsystemBlockAsync(idWell, startDate, finishDate, cancellationToken)).ToArray(),
|
||||||
|
LimitingParameters = (await CreateLimitingParameterBlockAsync(idWell, startDate, finishDate, cancellationToken)).ToArray(),
|
||||||
|
TimeBalance = factOperations.GroupBy(w => w.CategoryName).Select(x => new TimeBalanceRecordDto
|
||||||
|
{
|
||||||
|
Name = x.Key ?? "Название операции отсутствует",
|
||||||
|
DurationHours = x.Sum(o => o.DurationHours)
|
||||||
|
}).ToArray(),
|
||||||
|
};
|
||||||
|
|
||||||
|
var stream = await autoGeneratedDailyReportMakerService.MakeReportAsync(report, cancellationToken);
|
||||||
|
|
||||||
|
return (report.FileName, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HeadBlockDto CreateHeadBlock(WellDto well, DateOnly reportDate, WellOperationDto[] factOperations)
|
||||||
|
{
|
||||||
|
var customer = well.Companies.FirstOrDefault(company => company.IdCompanyType == 1);
|
||||||
|
|
||||||
|
return new HeadBlockDto
|
||||||
|
{
|
||||||
|
From = reportDate,
|
||||||
|
Customer = customer?.Caption ?? string.Empty,
|
||||||
|
Deposit = well.Deposit ?? string.Empty,
|
||||||
|
ClusterName = well.Cluster ?? string.Empty,
|
||||||
|
WellName = well.Caption,
|
||||||
|
WellDepthIntervalStartDate = factOperations.FirstOrDefault()?.DepthStart ?? 0.00,
|
||||||
|
WellDepthIntervalFinishDate = factOperations.LastOrDefault()?.DepthEnd ?? 0.00
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IEnumerable<SubsystemRecordDto>> CreateSubsystemBlockAsync(int idWell, DateTime startDate,
|
||||||
|
DateTime finishDate,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var subsystems = await subsystemRepository.GetAllAsync(cancellationToken);
|
||||||
|
var subsystemStats = await GetSubsystemStatsAsync(idWell, startDate, finishDate,
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
|
return subsystems.Select(subsystem =>
|
||||||
|
{
|
||||||
|
var subsytemStat = subsystemStats?.FirstOrDefault(s => s.IdSubsystem == subsystem.Id);
|
||||||
|
|
||||||
|
return new SubsystemRecordDto
|
||||||
|
{
|
||||||
|
Name = subsystem.Name,
|
||||||
|
KUsage = subsytemStat?.KUsage ?? 0.00,
|
||||||
|
UsedTimeHours = subsytemStat?.UsedTimeHours ?? 0.00,
|
||||||
|
Depth = subsytemStat?.SumDepthInterval ?? 0.00,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IEnumerable<LimitingParameterRecordDto>> CreateLimitingParameterBlockAsync(int idWell,
|
||||||
|
DateTime startDate, DateTime finishDate, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var limitingParameterStats = (await GetLimitingParameterStatsAsync(idWell,
|
||||||
|
startDate, finishDate, cancellationToken)).ToArray();
|
||||||
|
|
||||||
|
var sumDepths = limitingParameterStats.Sum(x => x.Depth);
|
||||||
|
|
||||||
|
return limitingParameterStats.Select(l => new LimitingParameterRecordDto
|
||||||
|
{
|
||||||
|
NameFeedRegulator = l.NameFeedRegulator,
|
||||||
|
TotalHours = l.TotalMinutes,
|
||||||
|
PercentDepth = l.Depth / sumDepths,
|
||||||
|
Depth = l.Depth,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task<IEnumerable<WellOperationDto>> GetFactOperationsAsync(int idWell, DateTime startDate,
|
||||||
|
DateTime finishDate, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var request = new WellOperationRequest
|
||||||
|
{
|
||||||
|
IdWell = idWell,
|
||||||
|
OperationType = WellOperation.IdOperationTypeFact,
|
||||||
|
GeDate = startDate,
|
||||||
|
LtDate = finishDate,
|
||||||
|
SortFields = new[] { "DateStart asc" },
|
||||||
|
};
|
||||||
|
|
||||||
|
return wellOperationRepository.GetAsync(request, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task<IEnumerable<SubsystemStatDto>?> GetSubsystemStatsAsync(int idWell, DateTime startDate,
|
||||||
|
DateTime finishDate, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var request = new SubsystemOperationTimeRequest
|
||||||
|
{
|
||||||
|
IdWell = idWell,
|
||||||
|
GtDate = startDate,
|
||||||
|
LtDate = finishDate,
|
||||||
|
};
|
||||||
|
|
||||||
|
return subsystemOperationTimeService.GetStatAsync(request, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task<IEnumerable<LimitingParameterDto>> GetLimitingParameterStatsAsync(int idWell,
|
||||||
|
DateTime startDate, DateTime finishDate, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var request = new LimitingParameterRequest
|
||||||
|
{
|
||||||
|
IdWell = idWell,
|
||||||
|
GtDate = startDate,
|
||||||
|
LtDate = finishDate,
|
||||||
|
};
|
||||||
|
|
||||||
|
return limitingParameterService.GetStatAsync(request, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetFileSize()
|
||||||
|
{
|
||||||
|
const int fileSizeTemplate = 8192;
|
||||||
|
|
||||||
|
return new Random().Next(1, 8193) + fileSizeTemplate;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
using AsbCloudApp.Data.AutogeneratedDailyReport;
|
||||||
|
using ClosedXML.Excel;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.AutoGeneratedDailyReports.AutogeneratedDailyReportBlocks;
|
||||||
|
|
||||||
|
public class HeadExcelBlockWriter : IExcelBlockWriter
|
||||||
|
{
|
||||||
|
private const int columnCustomer = 1;
|
||||||
|
private const int columnDeposit = 2;
|
||||||
|
private const int columnCluster = 3;
|
||||||
|
private const int columnWell = 4;
|
||||||
|
|
||||||
|
private const int columnFrom = 1;
|
||||||
|
private const int columnTo = 2;
|
||||||
|
private const int columnWellDepthIntervalStartDate = 3;
|
||||||
|
private const int columnWellDepthIntervalFinishDate = 4;
|
||||||
|
|
||||||
|
public void Write(IXLWorksheet sheet, AutoGeneratedDailyReportDto report)
|
||||||
|
{
|
||||||
|
const int rowHeaderBlockSectionOne = 2;
|
||||||
|
const int rowHeaderBlockSectionTwo = 5;
|
||||||
|
|
||||||
|
var rowSectionOne = sheet.Row(1 + rowHeaderBlockSectionOne);
|
||||||
|
|
||||||
|
rowSectionOne.Cell(columnCustomer).Value = report.Head.Customer;
|
||||||
|
rowSectionOne.Cell(columnDeposit).Value = report.Head.Deposit;
|
||||||
|
rowSectionOne.Cell(columnCluster).Value = report.Head.ClusterName;
|
||||||
|
rowSectionOne.Cell(columnWell).Value = report.Head.WellName;
|
||||||
|
|
||||||
|
var rowSectionTwo = sheet.Row(1 + rowHeaderBlockSectionTwo);
|
||||||
|
|
||||||
|
rowSectionTwo.Cell(columnFrom).Value = report.Head.From;
|
||||||
|
rowSectionTwo.Cell(columnTo).Value = report.Head.To;
|
||||||
|
rowSectionTwo.Cell(columnWellDepthIntervalStartDate).Value = report.Head.WellDepthIntervalStartDate;
|
||||||
|
rowSectionTwo.Cell(columnWellDepthIntervalFinishDate).Value = report.Head.WellDepthIntervalFinishDate;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
using AsbCloudApp.Data.AutogeneratedDailyReport;
|
||||||
|
using ClosedXML.Excel;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.AutoGeneratedDailyReports.AutogeneratedDailyReportBlocks;
|
||||||
|
|
||||||
|
public interface IExcelBlockWriter
|
||||||
|
{
|
||||||
|
void Write(IXLWorksheet sheet, AutoGeneratedDailyReportDto report);
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using AsbCloudApp.Data.AutogeneratedDailyReport;
|
||||||
|
using ClosedXML.Excel;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.AutoGeneratedDailyReports.AutogeneratedDailyReportBlocks;
|
||||||
|
|
||||||
|
public class LimitingParameterExcelBlockWriter : IExcelBlockWriter
|
||||||
|
{
|
||||||
|
private const int rowHeaderBlock = 18;
|
||||||
|
|
||||||
|
private const int columnNameFeedRegulator = 1;
|
||||||
|
private const int columnDepth = 2;
|
||||||
|
private const int columnTotalHours = 3;
|
||||||
|
private const int columnPercentDepth = 4;
|
||||||
|
|
||||||
|
public void Write(IXLWorksheet sheet, AutoGeneratedDailyReportDto report)
|
||||||
|
{
|
||||||
|
if(!report.LimitingParameters.Any())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < report.LimitingParameters.Length; i++)
|
||||||
|
{
|
||||||
|
var row = sheet.Row(1 + i + rowHeaderBlock);
|
||||||
|
|
||||||
|
row.Cell(columnNameFeedRegulator).Value = report.LimitingParameters[i].NameFeedRegulator;
|
||||||
|
row.Cell(columnDepth).Value = report.LimitingParameters[i].Depth;
|
||||||
|
row.Cell(columnTotalHours).Value = report.LimitingParameters[i].TotalHours;
|
||||||
|
row.Cell(columnPercentDepth).Value = report.LimitingParameters[i].PercentDepth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using AsbCloudApp.Data.AutogeneratedDailyReport;
|
||||||
|
using ClosedXML.Excel;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.AutoGeneratedDailyReports.AutogeneratedDailyReportBlocks;
|
||||||
|
|
||||||
|
public class SubsystemExcelBlockWriter : IExcelBlockWriter
|
||||||
|
{
|
||||||
|
private const int rowHeaderBlock = 10;
|
||||||
|
|
||||||
|
private const int columnName = 1;
|
||||||
|
private const int columnKUsage = 2;
|
||||||
|
private const int columnDepth = 3;
|
||||||
|
private const int columnUsedTimeHours = 4;
|
||||||
|
|
||||||
|
public void Write(IXLWorksheet sheet, AutoGeneratedDailyReportDto report)
|
||||||
|
{
|
||||||
|
if(!report.Subsystems.Any())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < report.Subsystems.Length; i++)
|
||||||
|
{
|
||||||
|
var row = sheet.Row(1 + i + rowHeaderBlock);
|
||||||
|
|
||||||
|
row.Cell(columnName).Value = report.Subsystems[i].Name;
|
||||||
|
row.Cell(columnKUsage).Value = report.Subsystems[i].KUsage;
|
||||||
|
row.Cell(columnDepth).Value = report.Subsystems[i].Depth;
|
||||||
|
row.Cell(columnUsedTimeHours).Value = report.Subsystems[i].UsedTimeHours;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using AsbCloudApp.Data.AutogeneratedDailyReport;
|
||||||
|
using ClosedXML.Excel;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.AutoGeneratedDailyReports.AutogeneratedDailyReportBlocks;
|
||||||
|
|
||||||
|
public class TimeBalanceExcelBlockWriter : IExcelBlockWriter
|
||||||
|
{
|
||||||
|
private const int rowHeaderBlock = 27;
|
||||||
|
|
||||||
|
private const int columnName = 1;
|
||||||
|
private const int columnDurationHours = 2;
|
||||||
|
|
||||||
|
public void Write(IXLWorksheet sheet, AutoGeneratedDailyReportDto report)
|
||||||
|
{
|
||||||
|
if(!report.TimeBalance.Any())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < report.TimeBalance.Length; i++)
|
||||||
|
{
|
||||||
|
var row = sheet.Row(1 + i + rowHeaderBlock);
|
||||||
|
|
||||||
|
row.Cell(columnName).Value = report.TimeBalance[i].Name;
|
||||||
|
row.Cell(columnDurationHours).Value = report.TimeBalance[i].DurationHours;
|
||||||
|
|
||||||
|
AddBorderToCell(row.Cell(columnName));
|
||||||
|
AddBorderToCell(row.Cell(columnDurationHours));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddBorderToCell(IXLCell cell)
|
||||||
|
{
|
||||||
|
cell.Style.Border.TopBorder = XLBorderStyleValues.Thin;
|
||||||
|
cell.Style.Border.BottomBorder = XLBorderStyleValues.Thin;
|
||||||
|
cell.Style.Border.LeftBorder = XLBorderStyleValues.Thin;
|
||||||
|
cell.Style.Border.RightBorder = XLBorderStyleValues.Thin;
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
@ -1,9 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AsbCloudApp.Data.AutogeneratedDailyReport;
|
using AsbCloudApp.Data.AutogeneratedDailyReport;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
using AsbCloudApp.Services.AutoGeneratedDailyReports;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
@ -11,42 +15,75 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
namespace AsbCloudWebApi.Controllers;
|
namespace AsbCloudWebApi.Controllers;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Контроллер для автоматически сгенерированных отчётов
|
/// Контроллер для авто-генерируемых суточных отчётов
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/well/{idWell}/[controller]")]
|
[Route("api/well/{idWell}/[controller]")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class AutoGeneratedDailyReportController : ControllerBase
|
public class AutoGeneratedDailyReportController : ControllerBase
|
||||||
{
|
{
|
||||||
|
private readonly IAutoGeneratedDailyReportService autoGeneratedDailyReportService;
|
||||||
|
private readonly IWellService wellService;
|
||||||
|
|
||||||
|
public AutoGeneratedDailyReportController(IAutoGeneratedDailyReportService autoGeneratedDailyReportService,
|
||||||
|
IWellService wellService)
|
||||||
|
{
|
||||||
|
this.autoGeneratedDailyReportService = autoGeneratedDailyReportService;
|
||||||
|
this.wellService = wellService;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Метод генерации отчёта
|
/// Формирование отчёта
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idWell">Id скважины</param>
|
/// <param name="idWell">Id скважины</param>
|
||||||
/// <param name="date">Дата работы системы</param>
|
/// <param name="reportDate">Дата отчёта</param>
|
||||||
/// <param name="cancellationToken"></param>
|
/// <param name="cancellationToken"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("generate")]
|
[Route("generate")]
|
||||||
[ProducesResponseType(typeof(PhysicalFileResult), (int)HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(PhysicalFileResult), (int)HttpStatusCode.OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
public Task<IActionResult> GenerateAsync([FromRoute] int idWell, DateOnly date, CancellationToken cancellationToken)
|
public async Task<IActionResult> GenerateAsync([FromRoute] int idWell,
|
||||||
|
[Required] DateOnly reportDate,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
if (!await CanUserAccessToWellAsync(idWell, cancellationToken))
|
||||||
|
return Forbid();
|
||||||
|
|
||||||
|
var reportFile = await autoGeneratedDailyReportService.GenerateReportAsync(idWell,
|
||||||
|
reportDate,
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
|
return File(reportFile.stream, "application/octet-stream", reportFile.fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получение списка файлов отчёта
|
/// Список файлов суточных отчётов
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idWell">Id скважины</param>
|
/// <param name="idWell">Id скважины</param>
|
||||||
/// <param name="begin">Дата начала работ на скважине</param>
|
/// <param name="request">Параметры запроса</param>
|
||||||
/// <param name="end">Дата окончания работ на скважине</param>
|
|
||||||
/// <param name="cancellationToken"></param>
|
/// <param name="cancellationToken"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[ProducesResponseType(typeof(IEnumerable<AutoGeneratedDailyReportDto>), (int)HttpStatusCode.OK)]
|
[ProducesResponseType(typeof(IEnumerable<AutoGeneratedDailyReportDto>), (int)HttpStatusCode.OK)]
|
||||||
public Task<IActionResult> GetListAsync([FromRoute] int idWell, DateOnly? begin, DateOnly? end,
|
public async Task<IActionResult> GetListAsync([FromRoute][Required] int idWell,
|
||||||
|
[FromQuery] AutoGeneratedDailyReportRequest request,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
if (!await CanUserAccessToWellAsync(idWell, cancellationToken))
|
||||||
|
return Forbid();
|
||||||
|
|
||||||
|
var reports = await autoGeneratedDailyReportService.GetListAsync(idWell,
|
||||||
|
request,
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
|
return Ok(reports);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<bool> CanUserAccessToWellAsync(int idWell, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
int? idCompany = User.GetCompanyId();
|
||||||
|
return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
|
||||||
|
idWell, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user