DD.WellWorkover.Cloud/AsbCloudInfrastructure/Services/ReportService.cs

232 lines
7.9 KiB
C#
Raw Permalink 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 AsbCloudApp.Data;
using AsbCloudApp.Data.Progress;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Background;
using AsbSaubReport;
using Mapster;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services;
public class ReportService : IReportService
{
private readonly IAsbCloudDbContext db;
private readonly ITelemetryService telemetryService;
private readonly FileService fileService;
private readonly IWellService wellService;
private readonly BackgroundWorker backgroundWorkerService;
public ReportService(IAsbCloudDbContext db,
ITelemetryService telemetryService,
IWellService wellService,
FileService fileService,
BackgroundWorker backgroundWorkerService)
{
this.db = db;
this.wellService = wellService;
this.backgroundWorkerService = backgroundWorkerService;
this.telemetryService = telemetryService;
this.fileService = fileService;
}
public string EnqueueCreateReportWork(int idWell, int idUser, ReportParametersRequest request, Action<object, string> progressHandler)
{
var work = new WorkToCreateReport(idWell, idUser, request, progressHandler);
work.OnErrorAsync = (message, exception, token) => Task.Run(() => {
var state = new ProgressExceptionDto
{
Operation = "error",
Progress = 100f,
Message = string.IsNullOrEmpty(message)
? exception.Message
: message,
Exception = exception,
};
progressHandler.Invoke(state, work.Id);
}, token);
progressHandler.Invoke(new ReportProgressDto
{
Operation = "Ожидает начала в очереди.",
Progress = 0f,
}, work.Id);
backgroundWorkerService.Enqueue(work);
return work.Id;
}
public int GetReportPagesCount(int idWell, DateTimeOffset begin, DateTimeOffset end, int stepSeconds, int format)
{
var timezoneOffset = wellService.GetTimezone(idWell).Hours;
var beginRemote = begin.DateTime.ToTimeZoneOffsetHours(timezoneOffset);
var endRemote = end.DateTime.ToTimeZoneOffsetHours(timezoneOffset);
var generator = GetReportGenerator(idWell, beginRemote, endRemote, stepSeconds, format, db);
var pagesCount = generator.GetPagesCount();
return pagesCount;
}
public DatesRangeDto? GetDatesRangeOrDefault(int idWell)
{
var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell);
if (telemetry is null)
return null;
var range = telemetryService.GetDatesRange(telemetry.Id);
return range;
}
public async Task<IEnumerable<ReportPropertiesDto>> GetAllReportsByWellAsync(int idWell, CancellationToken token)
{
var timezoneOffset = wellService.GetTimezone(idWell).Hours;
var timeSpan = TimeSpan.FromHours(timezoneOffset);
var propertiesQuery = db.ReportProperties.Include(r => r.File)
.Where(p => p.IdWell == idWell)
.OrderBy(o => o.File.UploadDate)
.AsNoTracking()
.Take(1024);
var entities = await propertiesQuery.ToListAsync(token);
var dtos = entities.Select(p => new ReportPropertiesDto
{
Id = p.Id,
Name = p.File.Name,
File = new FileInfoDto
{
Id = p.File.Id,
Author = null,
IdAuthor = p.File.IdAuthor ?? 0,
IdCategory = p.File.IdCategory,
IdWell = p.File.IdWell,
Name = p.File.Name,
Size = p.File.Size,
UploadDate = p.File.UploadDate.ToOffset(timeSpan),
},
IdWell = p.IdWell,
Date = p.File.UploadDate.ToOffset(timeSpan),
Begin = p.Begin.ToOffset(timeSpan),
End = p.End.ToOffset(timeSpan),
Step = p.Step,
Format = p.Format == 0 ? ".pdf" : ".las"
});
return dtos;
}
public async Task CreateReportAsync(
string workId,
int idWell,
int idUser,
ReportParametersRequest request,
Action<ProgressDto, string> progressHandler,
CancellationToken token)
{
var timezoneOffset = wellService.GetTimezone(idWell).Hours;
var beginRemote = request.Begin.DateTime;
var endRemote = request.End.DateTime;
var beginUtc = request.Begin.ToUniversalTime();
var endUtc = request.End.ToUniversalTime();
var tempDir = Path.Combine(Path.GetTempPath(), "report");
var generator = GetReportGenerator(idWell, beginRemote, endRemote, request.StepSeconds, request.Format, db);
var reportFileName = Path.Combine(tempDir, generator.GetReportDefaultFileName());
var totalPages = generator.GetPagesCount();
generator.OnProgress += (s, e) =>
{
var arg = e.Adapt<ReportProgressDto>();
progressHandler(arg, workId);
};
generator.Make(reportFileName);
var ReportCategoryId = db.FileCategories
.AsNoTracking()
.First(c => c.Name.Equals("Рапорт"))
.Id;
var fileInfo = (await fileService.MoveAsync(idWell, idUser, ReportCategoryId, reportFileName, reportFileName, token))!;
if (fileInfo == null)
{
var state = new ProgressExceptionDto
{
Operation = "error",
Progress = 100f,
Message = "Не удалось сгенерировать файл отчёта",
Exception = new FileNotFoundException(),
};
progressHandler(state, workId);
return;
}
progressHandler(new ReportProgressFinalDto()
{
Operation = "done",
Progress = 100f,
TotalPages = totalPages,
CurrentPage = totalPages,
file = fileInfo,
}, workId);
var newReportProperties = new ReportProperty
{
IdWell = idWell,
IdFile = fileInfo.Id,
Begin = beginUtc,
End = endUtc,
Step = request.StepSeconds,
Format = request.Format
};
db.ReportProperties.Add(newReportProperties);
db.SaveChanges();
}
private static IReportGenerator GetReportGenerator(int idWell, DateTime begin,
DateTime end, int stepSeconds, int format, IAsbCloudDbContext context)
{
var dataSource = new ReportDataSourcePgCloud(context, idWell);
IReportGenerator generator = format switch
{
//LAS
1 => new AsbSaubReportLas.ReprotGeneratorLas(dataSource),
//PDF
_ => new AsbSaubReportPdf.ReprotGeneratorPdf(dataSource),
};
if (begin == default || end == default)
{
var analyzeResult = dataSource.Analyze();
begin = begin == default ? analyzeResult.MinDate : begin;
end = end == default ? begin.AddDays(1) : end;
}
generator.Begin = begin;
generator.End = end;
generator.Step = TimeSpan.FromSeconds(stepSeconds);
generator.WithCharts = true;
generator.WithEvents = true;
return generator;
}
public async Task<int> DeleteAllOldReportsAsync(TimeSpan lifetime, CancellationToken token)
{
var lifeTimeStartDate = DateTimeOffset.UtcNow.Date - lifetime;
var fileIds = await db.ReportProperties
.Where(r => r.File.UploadDate.Date < lifeTimeStartDate)
.Select(r => r.IdFile)
.ToArrayAsync(token);
return await fileService.DeleteAsync(fileIds, token);
}
}