forked from ddrilling/AsbCloudServer
232 lines
7.9 KiB
C#
232 lines
7.9 KiB
C#
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);
|
||
}
|
||
}
|