using AsbCloudApp.Data; using AsbCloudApp.Services; using AsbCloudDb.Model; using AsbCloudInfrastructure.Repository; using AsbSaubReport; using Mapster; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; 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 string connectionString; private readonly ITelemetryService telemetryService; private readonly IWellService wellService; private readonly IBackgroundWorkerService backgroundWorkerService; public ReportService(IAsbCloudDbContext db, IConfiguration configuration, ITelemetryService telemetryService, IWellService wellService, IBackgroundWorkerService backgroundWorkerService) { this.db = db; this.connectionString = configuration.GetConnectionString("DefaultConnection"); this.wellService = wellService; this.backgroundWorkerService = backgroundWorkerService; this.telemetryService = telemetryService; ReportCategoryId = db.FileCategories.AsNoTracking() .FirstOrDefault(c => c.Name.Equals("Рапорт")).Id; } public int ReportCategoryId { get; private set; } public string CreateReport(int idWell, int idUser, int stepSeconds, int format, DateTime begin, DateTime end, Action progressHandler) { var timezoneOffset = wellService.GetTimezone(idWell).Hours; var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset); var endUtc = end.ToUtcDateTimeOffset(timezoneOffset); var beginRemote = begin.ToTimeZoneOffsetHours(timezoneOffset); var endRemote = end.ToTimeZoneOffsetHours(timezoneOffset); var newReportId = backgroundWorkerService.Enqueue(async (id, token) => { var contextOptions = new DbContextOptionsBuilder() .UseNpgsql(connectionString) .Options; using var context = new AsbCloudDbContext(contextOptions); var tempDir = Path.Combine(Path.GetTempPath(), "report"); var generator = GetReportGenerator(idWell, beginRemote, endRemote, stepSeconds, format, context); var reportFileName = Path.Combine(tempDir, generator.GetReportDefaultFileName()); var totalPages = generator.GetPagesCount(); generator.OnProgress += (s, e) => { progressHandler.Invoke(e.Adapt(), id); }; generator.Make(reportFileName); var fileRepository = new FileRepository(context); var fileStorageRepository = new FileStorageRepository(); var fileService = new FileService(fileRepository, fileStorageRepository); var fileInfo = await fileService.MoveAsync(idWell, idUser, ReportCategoryId, reportFileName, reportFileName, token); progressHandler.Invoke(new { Operation = "done", Progress = 100f, TotalPages = totalPages, CurrentPage = totalPages, file = fileInfo, }, id); var newReportProperties = new ReportProperty { IdWell = idWell, IdFile = fileInfo.Id, Begin = beginUtc, End = endUtc, Step = stepSeconds, Format = format }; context.ReportProperties.Add(newReportProperties); context.SaveChanges(); }); progressHandler.Invoke(new ReportProgressDto { Operation = "Ожидает начала в очереди.", Progress = 0f, }, newReportId); return newReportId; } public int GetReportPagesCount(int idWell, DateTime begin, DateTime end, int stepSeconds, int format) { var timezoneOffset = wellService.GetTimezone(idWell).Hours; var beginRemote = begin.ToTimeZoneOffsetHours(timezoneOffset); var endRemote = end.ToTimeZoneOffsetHours(timezoneOffset); var generator = GetReportGenerator(idWell, beginRemote, endRemote, stepSeconds, format, (AsbCloudDbContext)db); var pagesCount = generator.GetPagesCount(); return pagesCount; } public DatesRangeDto GetDatesRangeOrDefault(int idWell) { var idTelemetry = telemetryService.GetIdTelemetryByIdWell(idWell); if (idTelemetry is null) return null; var range = telemetryService.GetDatesRange((int)idTelemetry); return range; } public async Task> GetAllReportsByWellAsync(int idWell, CancellationToken token) { var timezoneOffset = wellService.GetTimezone(idWell).Hours; var propertiesQuery = db.ReportProperties.Include(r => r.File) .Where(p => p.IdWell == idWell) .OrderBy(o => o.File.UploadDate) .AsNoTracking() .Take(1024); var properties = await propertiesQuery.ToListAsync(token); return properties.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.ToRemoteDateTime(timezoneOffset), }, IdWell = p.IdWell, Date = p.File.UploadDate.ToRemoteDateTime(timezoneOffset), Begin = p.Begin.ToRemoteDateTime(timezoneOffset), End = p.End.ToRemoteDateTime(timezoneOffset), Step = p.Step, Format = p.Format == 0 ? ".pdf" : ".las" }); } private static IReportGenerator GetReportGenerator(int idWell, DateTime begin, DateTime end, int stepSeconds, int format, AsbCloudDbContext context) { var dataSource = new ReportDataSourcePgCloud(context, idWell); IReportGenerator generator = format switch { //LAS 1 => new AsbSaubReportLas.ReprotGeneratorLas(dataSource), //PDF _ => new AsbSaubReportPdf.ReprotGeneratorPdf(dataSource), }; generator.Begin = begin; generator.End = end; generator.Step = TimeSpan.FromSeconds(stepSeconds); generator.WithCharts = true; generator.WithEvents = true; return generator; } } }