DD.WellWorkover.Cloud/AsbCloudInfrastructure/Services/AutoGeneratedDailyReports/AutoGeneratedDailyReportService.cs

248 lines
8.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<AutoGeneratedDailyReportInfoDto>> GetListAsync(int idWell,
AutoGeneratedDailyReportRequest request,
CancellationToken cancellationToken)
{
var result = new PaginationContainer<AutoGeneratedDailyReportInfoDto>
{
Skip = request.Skip ?? 0,
Take = request.Take ?? 10,
Items = Enumerable.Empty<AutoGeneratedDailyReportInfoDto>()
};
var reports = new List<AutoGeneratedDailyReportInfoDto>();
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;
result.Count = (int)(Math.Ceiling((datesRange.To - DateTime.UnixEpoch).TotalDays) - Math.Floor((datesRange.From - DateTime.UnixEpoch).TotalDays));
if (request.StartDate.HasValue)
{
var startDate = new DateTime(request.StartDate.Value.Year, request.StartDate.Value.Month,
request.StartDate.Value.Day);
if(startDate.Date >= datesRange.From.Date)
datesRange.From = startDate;
}
if (request.FinishDate.HasValue)
{
var finishDate = new DateTime(request.FinishDate.Value.Year, request.FinishDate.Value.Month,
request.FinishDate.Value.Day);
if (finishDate.Date <= datesRange.To.Date)
datesRange.To = finishDate;
}
for (int day = result.Skip; (day - result.Skip) < result.Take && (datesRange.From.AddDays(day)) <= datesRange.To; day++)
{
var dateFrom = datesRange.From.AddDays(day);
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;
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
{
Customer = customer?.Caption ?? string.Empty,
Deposit = well.Deposit ?? string.Empty,
Cluster = well.Cluster ?? string.Empty,
Well = well.Caption,
DepthFrom = factOperations.FirstOrDefault()?.DepthStart ?? 0.00,
DepthTo = 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,
Hours = 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 = 10240;
return new Random().Next(1, 8193) + fileSizeTemplate;
}
}