using AsbCloudApp.Data; using AsbCloudApp.Services; using AsbCloudDb.Model; 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 IConfiguration configuration; private readonly ITelemetryService telemetryService; private readonly IFileService fileService; private readonly IReportsBackgroundQueue queue; public ReportService(IAsbCloudDbContext db, IConfiguration configuration, ITelemetryService telemetryService, IFileService fileService, IReportsBackgroundQueue queue) { this.db = db; this.configuration = configuration; this.telemetryService = telemetryService; this.fileService = fileService; this.queue = queue; ReportCategoryId = db.FileCategories.AsNoTracking() .FirstOrDefault(c => c.Name.Equals("Рапорт")).Id; } public int ReportCategoryId { get; private set; } public int CreateReport(int idWell, int idUser, int stepSeconds, int format, DateTime begin, DateTime end, Action progressHandler) { var newReportId = queue.EnqueueTask((id) => { var optionsBuilder = new DbContextOptionsBuilder(); optionsBuilder.UseNpgsql(configuration.GetConnectionString("DefaultConnection")); var tempDir = Path.Combine(Path.GetTempPath(), "report"); using var context = new AsbCloudDbContext(optionsBuilder.Options); var generator = GetReportGenerator(idWell, begin, end, 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 fileService = new FileService(context, new GoogleDriveService()); var fileInfo = fileService.MoveAsync(idWell, idUser, ReportCategoryId, reportFileName, reportFileName).Result; progressHandler.Invoke(new { Operation = "done", Progress = 100f, TotalPages = totalPages, CurrentPage = totalPages, file = fileInfo, }, id); var newReportProperties = new ReportProperty { IdWell = idWell, IdFile = fileInfo.Id, Begin = begin, End = end, 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 generator = GetReportGenerator(idWell, begin, end, stepSeconds, format, (AsbCloudDbContext)db); return generator.GetPagesCount(); } public async Task GetReportsDatesRangeAsync(int idWell, CancellationToken token = default) { var telemetryId = telemetryService.GetIdTelemetryByIdWell(idWell); if (telemetryId is null) return null; var datesRange = await (from d in db.TelemetryDataSaub where d.IdTelemetry == telemetryId select d.Date).Union( from m in db.TelemetryMessages where m.IdTelemetry == telemetryId select m.Date).DefaultIfEmpty() .GroupBy(g => true) .AsNoTracking() .Select(g => new { From = g.Min(), To = g.Max() }).OrderBy(gr => gr.From) .FirstOrDefaultAsync(token) .ConfigureAwait(false); return new DatesRangeDto { From = datesRange.From, To = datesRange.To.Year == 1 ? DateTime.MaxValue : datesRange.To }; } public Task> GetSuitableReportsAsync(int idWell, DateTime begin, DateTime end, int stepSeconds, int format, CancellationToken token) => (from r in db.ReportProperties.Include(r => r.File) where r.IdWell == idWell && r.Begin >= begin && r.End <= end && r.Step <= stepSeconds && r.Format == format select new ReportPropertiesDto { Id = r.Id, Name = r.File.Name, File = new FileInfoDto{ Id = r.File.Id, Author = null, IdAuthor = r.File.IdAuthor??0, IdCategory = r.File.IdCategory, IdWell = r.File.IdWell, Name = r.File.Name, Size = r.File.Size, UploadDate = r.File.UploadDate, }, IdWell = r.IdWell, Date = r.File.UploadDate, Begin = r.Begin, End = r.End, Step = r.Step, Format = r.Format == 0 ? ".pdf" : ".las" }) .OrderBy(o => o.Date) .AsNoTracking() .Take(512).ToListAsync(token); public Task> GetAllReportsByWellAsync(int idWell, CancellationToken token) => (from r in db.ReportProperties.Include(r => r.File) where r.IdWell == idWell select new ReportPropertiesDto { Id = r.Id, Name = r.File.Name, File = new FileInfoDto { Id = r.File.Id, Author = null, IdAuthor = r.File.IdAuthor ?? 0, IdCategory = r.File.IdCategory, IdWell = r.File.IdWell, Name = r.File.Name, Size = r.File.Size, UploadDate = r.File.UploadDate, }, IdWell = r.IdWell, Date = r.File.UploadDate, Begin = r.Begin, End = r.End, Step = r.Step, Format = r.Format == 0 ? ".pdf" : ".las" }) .OrderBy(o => o.Date) .AsNoTracking() .Take(1024).ToListAsync(token); 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; } } }