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

261 lines
9.3 KiB
C#
Raw Normal View History

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.Subsystems;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudApp.Services.AutoGeneratedDailyReports;
using AsbCloudApp.Services.Subsystems;
using AsbCloudDb.Model;
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 ISubsystemOperationTimeService subsystemOperationTimeService;
private readonly ICrudRepository<SubsystemDto> subsystemRepository;
private readonly ILimitingParameterService limitingParameterService;
private readonly IAutoGeneratedDailyReportMakerService autoGeneratedDailyReportMakerService;
public AutoGeneratedDailyReportService(IWellService wellService,
IWellOperationRepository wellOperationRepository,
ISubsystemOperationTimeService subsystemOperationTimeService,
ICrudRepository<SubsystemDto> subsystemRepository,
ILimitingParameterService limitingParameterService,
IAutoGeneratedDailyReportMakerService autoGeneratedDailyReportMakerService)
{
this.wellOperationRepository = wellOperationRepository;
this.wellService = wellService;
this.subsystemOperationTimeService = subsystemOperationTimeService;
this.subsystemRepository = subsystemRepository;
this.limitingParameterService = limitingParameterService;
this.autoGeneratedDailyReportMakerService = autoGeneratedDailyReportMakerService;
}
2023-07-25 17:07:50 +05:00
public async Task<PaginationContainer<AutoGeneratedDailyReportInfoDto>> GetListAsync(int idWell,
AutoGeneratedDailyReportRequest request,
CancellationToken cancellationToken)
{
2023-07-25 17:07:50 +05:00
var result = new PaginationContainer<AutoGeneratedDailyReportInfoDto>
{
Skip = request.Skip ?? 0,
Take = request.Take ?? 10,
2023-07-25 17:07:50 +05:00
Items = Enumerable.Empty<AutoGeneratedDailyReportInfoDto>()
};
2023-07-25 17:07:50 +05:00
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 = await GetDatesRangeAsync(idWell, cancellationToken);
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);
2023-07-25 17:07:50 +05:00
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);
2023-07-25 17:07:50 +05:00
if (finishDate.Date <= datesRange.To.Date)
datesRange.To = finishDate;
}
2023-07-25 17:07:50 +05:00
for (int day = result.Skip; (day - result.Skip) < result.Take && (datesRange.From.AddDays(day)) <= datesRange.To; day++)
{
var reportDate = DateOnly.FromDateTime(datesRange.From.AddDays(day));
2023-07-25 17:07:50 +05:00
reports.Add(new AutoGeneratedDailyReportInfoDto
{
FileName = string.Format(fileNameTemplate, well.Caption, well.Cluster, reportDate),
ReportDate = reportDate,
FileSize = GetFileSize(reportDate, idWell),
});
}
2023-07-25 17:07:50 +05:00
result.Items = reports;
return result;
}
public async Task<(string fileName, Stream stream)> GenerateAsync(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);
var report = new AutoGeneratedDailyReportDto
{
FileName = string.Format(fileNameTemplate, well.Caption, well.Cluster, reportDate),
FileSize = GetFileSize(reportDate, idWell),
ReportDate = reportDate,
Head = CreateHeadBlock(well, 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);
}
public async Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, CancellationToken cancellationToken)
{
var factOperations = await GetFactOperationsAsync(idWell, null, null,
cancellationToken);
if (!factOperations.Any())
return null;
return new DatesRangeDto
{
2023-08-15 13:39:04 +05:00
From = factOperations.Min(o => o.DateStart),
To = factOperations.Max(o => o.DateStart)
};
}
private HeadBlockDto CreateHeadBlock(WellDto well, IEnumerable<WellOperationDto> factOperations)
{
var customer = well.Companies.FirstOrDefault(company => company.IdCompanyType == 1);
var sortedFactOperations = factOperations.OrderBy(o => o.DateStart);
return new HeadBlockDto
{
Customer = customer?.Caption ?? string.Empty,
Deposit = well.Deposit ?? string.Empty,
2023-07-25 17:07:50 +05:00
Cluster = well.Cluster ?? string.Empty,
Well = well.Caption,
DepthFrom = sortedFactOperations.FirstOrDefault()?.DepthStart ?? 0.00,
DepthTo = sortedFactOperations.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,
2023-07-25 17:07:50 +05:00
Hours = l.TotalMinutes,
PercentDepth = sumDepths != 0 ? l.Depth / sumDepths : 0,
Depth = l.Depth,
});
}
2023-08-15 13:39:04 +05:00
private async Task<IOrderedEnumerable<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" },
};
2023-08-15 13:39:04 +05:00
return (await wellOperationRepository.GetAsync(request, cancellationToken))
.OrderBy(w => w.DateStart);
}
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(DateOnly reportDate, int idWell)
{
2023-07-25 17:07:50 +05:00
const int fileSizeTemplate = 10240;
long ticks = 1L * reportDate.Year * reportDate.Month * reportDate.Day * idWell;
int remainder = (int)(ticks % (fileSizeTemplate / 10));
return fileSizeTemplate + remainder;
}
}