diff --git a/AsbCloudApp/Data/ReportProgressDto.cs b/AsbCloudApp/Data/ReportProgressDto.cs new file mode 100644 index 00000000..f3380d56 --- /dev/null +++ b/AsbCloudApp/Data/ReportProgressDto.cs @@ -0,0 +1,10 @@ +namespace AsbCloudApp.Data +{ + public class ReportProgressDto + { + public float Progress { get; set; } + public string Operation { get; set; } + public int CurrentPage { get; set; } + public int TotalPages { get; set; } + } +} diff --git a/AsbCloudApp/Data/ReportPropertiesDto.cs b/AsbCloudApp/Data/ReportPropertiesDto.cs index 09674a62..a1e3e6e9 100644 --- a/AsbCloudApp/Data/ReportPropertiesDto.cs +++ b/AsbCloudApp/Data/ReportPropertiesDto.cs @@ -6,7 +6,7 @@ namespace AsbCloudApp.Data { public int Id { get; set; } public string Name { get; set; } - public string FullName { get; set; } + public string Url { get; set; } public int IdWell { get; set; } public DateTime Date { get; set; } public DateTimeOffset Begin { get; set; } diff --git a/AsbCloudApp/Services/IFileService.cs b/AsbCloudApp/Services/IFileService.cs index 34a0f3fc..6b1eb37c 100644 --- a/AsbCloudApp/Services/IFileService.cs +++ b/AsbCloudApp/Services/IFileService.cs @@ -24,6 +24,8 @@ namespace AsbCloudApp.Services CancellationToken token = default); Task> GetInfosByCategoryAsync(int idWell, int idCategory, CancellationToken token = default); Task DeletedAsync(int id, CancellationToken token); - string GetFileName(FileInfoDto fileInfo); + string GetUrl(FileInfoDto fileInfo); + string GetUrl(int idFile); + string GetUrl(int idWell, int idCategory, int idFile, string dotExtention); } } diff --git a/AsbCloudApp/Services/IReportService.cs b/AsbCloudApp/Services/IReportService.cs index 939f6083..0d7d80b4 100644 --- a/AsbCloudApp/Services/IReportService.cs +++ b/AsbCloudApp/Services/IReportService.cs @@ -11,14 +11,15 @@ namespace AsbCloudApp.Services int ReportCategoryId { get; } int CreateReport(int idWell, int idUser, int stepSeconds, int format, DateTime begin, DateTime end, - Action handleReportProgress, - Action handleReportName); + Action handleReportProgress); int GetReportPagesCount(int idWell, DateTime begin, DateTime end, int stepSeconds, int format); - Task> GetSuitableReportsAsync(int idWell, + + Task> GetSuitableReportsAsync(int idWell, DateTime begin, DateTime end, int stepSeconds, int format, CancellationToken token); Task GetReportsDatesRangeAsync(int idWell, CancellationToken token); + Task> GetAllReportsByWellAsync(int idWell, CancellationToken token); } } diff --git a/AsbCloudInfrastructure/CommonLibs/AsbSaubReport.dll b/AsbCloudInfrastructure/CommonLibs/AsbSaubReport.dll index 19620af6..9366757e 100644 Binary files a/AsbCloudInfrastructure/CommonLibs/AsbSaubReport.dll and b/AsbCloudInfrastructure/CommonLibs/AsbSaubReport.dll differ diff --git a/AsbCloudInfrastructure/CommonLibs/AsbSaubReportLas.dll b/AsbCloudInfrastructure/CommonLibs/AsbSaubReportLas.dll index 1e5c8d32..56a22028 100644 Binary files a/AsbCloudInfrastructure/CommonLibs/AsbSaubReportLas.dll and b/AsbCloudInfrastructure/CommonLibs/AsbSaubReportLas.dll differ diff --git a/AsbCloudInfrastructure/CommonLibs/AsbSaubReportPdf.dll b/AsbCloudInfrastructure/CommonLibs/AsbSaubReportPdf.dll index 5c23bfdd..51b612f0 100644 Binary files a/AsbCloudInfrastructure/CommonLibs/AsbSaubReportPdf.dll and b/AsbCloudInfrastructure/CommonLibs/AsbSaubReportPdf.dll differ diff --git a/AsbCloudInfrastructure/CommonLibs/ref/AsbSaubReportLas.dll b/AsbCloudInfrastructure/CommonLibs/ref/AsbSaubReportLas.dll index f1c38b78..5f40dc30 100644 Binary files a/AsbCloudInfrastructure/CommonLibs/ref/AsbSaubReportLas.dll and b/AsbCloudInfrastructure/CommonLibs/ref/AsbSaubReportLas.dll differ diff --git a/AsbCloudInfrastructure/CommonLibs/ref/AsbSaubReportPdf.dll b/AsbCloudInfrastructure/CommonLibs/ref/AsbSaubReportPdf.dll index 2f6b1677..ac44aab6 100644 Binary files a/AsbCloudInfrastructure/CommonLibs/ref/AsbSaubReportPdf.dll and b/AsbCloudInfrastructure/CommonLibs/ref/AsbSaubReportPdf.dll differ diff --git a/AsbCloudInfrastructure/ReportDataSourcePgCloud.cs b/AsbCloudInfrastructure/ReportDataSourcePgCloud.cs index 446dec51..3429dd85 100644 --- a/AsbCloudInfrastructure/ReportDataSourcePgCloud.cs +++ b/AsbCloudInfrastructure/ReportDataSourcePgCloud.cs @@ -54,6 +54,7 @@ namespace AsbSaubReport Customer = well.RelationCompaniesWells.FirstOrDefault(c => c.Company.IdCompanyType == 1)?.Company.Caption, DrillingStartDate = well.Telemetry?.Info?.DrillingStartDate ?? default, TimeZoneId = well.Telemetry?.Info?.TimeZoneId ?? default, + TimeZoneOffsetTotalHours = well.Telemetry?.Info?.TimeZoneOffsetTotalHours ?? default, }; } @@ -62,19 +63,19 @@ namespace AsbSaubReport var messagesStat = (from item in context.TelemetryMessages where item.IdTelemetry == idTelemetry group item.Date by item.IdTelemetry into g - select new { min = g.Min(), max = g.Max(), count = g.Count()}) + select new { min = g.Min(), max = g.Max(), count = g.Count() }) .FirstOrDefault(); var dataStat = (from item in context.TelemetryDataSaub - where item.IdTelemetry == idTelemetry + where item.IdTelemetry == idTelemetry group item.Date by item.IdTelemetry into g select new { min = g.Min(), max = g.Max(), count = g.Count() }) .FirstOrDefault(); var result = new AnalyzeResult { - MinDate = dataStat?.max ?? messagesStat?.min ?? default, - MaxDate = dataStat?.max ?? messagesStat?.min ?? default, + MinDate = dataStat?.min ?? messagesStat?.min ?? default, + MaxDate = dataStat?.max ?? messagesStat?.max ?? default, MessagesCount = messagesStat?.count ?? 0, }; @@ -86,6 +87,7 @@ namespace AsbSaubReport where item.IdTelemetry == idTelemetry && item.Date >= begin && item.Date <= end + orderby item.Date select new DataSaubReport { Id = item.Id, @@ -115,6 +117,7 @@ namespace AsbSaubReport where item.IdTelemetry == idTelemetry && item.Date >= begin && item.Date <= end + orderby item.Date select new MessageReport { Id = item.Id, diff --git a/AsbCloudInfrastructure/Services/ReportService.cs b/AsbCloudInfrastructure/Services/ReportService.cs index 4f3f8875..6236f8d2 100644 --- a/AsbCloudInfrastructure/Services/ReportService.cs +++ b/AsbCloudInfrastructure/Services/ReportService.cs @@ -2,7 +2,7 @@ using AsbCloudApp.Services; using AsbCloudDb.Model; using AsbSaubReport; -using AsbSaubReportPdf; +using Mapster; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using System; @@ -39,90 +39,66 @@ namespace AsbCloudInfrastructure.Services public int ReportCategoryId { get; private set; } public int CreateReport(int idWell, int idUser, int stepSeconds, int format, DateTime begin, - DateTime end, Action progressHandler, Action reportNameHandler) + 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)) + 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) => { - var generator = GetReportGenerator(idWell, begin, end, stepSeconds, format, context); - generator.OnProgress += (s, e) => progressHandler.Invoke(e.progress, e.operation, id); + progressHandler.Invoke(e.Adapt(), id); + }; + generator.Make(reportFileName); - var reportFileName = GetReportFileName(context, idWell); + var fileService = new FileService(context); + using var filestream = File.OpenRead(reportFileName); + var fileInfo = fileService.SaveAsync(idWell, idUser, ReportCategoryId, reportFileName, filestream).Result; + filestream.Close(); - generator.Make(reportFileName); - if (reportFileName is not null) - { - var shorReportName = Path.GetFileName(reportFileName); - reportNameHandler.Invoke(shorReportName, id); + progressHandler.Invoke(new + { + Operation = "done", + Progress = 100f, + TotalPages = totalPages, + CurrentPage = totalPages, + file = fileInfo, + }, id); - var newReportFile = new AsbCloudDb.Model.FileInfo - { - IdWell = idWell, - IdAuthor = idUser, - IdCategory = ReportCategoryId, - Name = reportFileName, - UploadDate = DateTime.Now, - }; - - context.Files.Add(newReportFile); - - var newReportProperties = new ReportProperty - { - IdWell = idWell, - IdFile = newReportFile.Id, - Begin = begin, - End = end, - Step = stepSeconds, - Format = format - }; - context.ReportProperties.Add(newReportProperties); - context.SaveChanges(); - } - } + 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; } - private string GetReportFileName(AsbCloudDbContext context, int idWell) - { - var well = context.Wells.Include(w => w.Cluster).FirstOrDefault(w => w.Id == idWell); - var fileName = Path.Combine(fileService.RootPath, $"{idWell}", $"{ReportCategoryId}", $"Рапорт куст{well?.Cluster?.Caption} скв{well.Caption}.pdf") ; - return fileName; - } - 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> GetSuitableReportsAsync(int idWell, - DateTime begin, DateTime end, int stepSeconds, int format, CancellationToken token = default) - { - var suitableReportsFromDb = await GetSuitableReportsFromDbAsync(idWell, - begin, end, stepSeconds, format, token).ConfigureAwait(false); - - var suitableReportsProperties = suitableReportsFromDb.Select(r => new ReportPropertiesDto - { - Id = r.Id, - Name = Path.GetFileName(r.File.Name), - FullName = r.File.Name, - IdWell = r.IdWell, - Date = r.File.UploadDate, - Begin = r.Begin, - End = r.End, - Step = r.Step, - Format = r.Format == 0 ? ".pdf" : ".las" - }); - - return suitableReportsProperties; - } - public async Task GetReportsDatesRangeAsync(int idWell, CancellationToken token = default) { @@ -154,25 +130,53 @@ namespace AsbCloudInfrastructure.Services }; } - private async Task> GetSuitableReportsFromDbAsync(int idWell, - DateTime begin, DateTime end, int stepSeconds, int format, - CancellationToken token = default) - { - var suitableReportsNames = await (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 r).OrderBy(o => o.File.UploadDate) - .AsNoTracking() - .Take(512).ToListAsync(token) - .ConfigureAwait(false); - return suitableReportsNames; - } + [Obsolete] + Task> IReportService.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, + Url = fileService.GetUrl(r.IdFile), + 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); - private IReportGenerator GetReportGenerator(int idWell, DateTime begin, + 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, +#pragma warning disable IDE0057 // Use range operator + Url = fileService.GetUrl(r.IdWell, ReportCategoryId, r.File.Id, r.File.Name.Substring(r.File.Name.LastIndexOf(".") > 0 ? r.File.Name.LastIndexOf(".") : r.File.Name.Length)), +#pragma warning restore IDE0057 // Use range operator + 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); @@ -181,11 +185,11 @@ namespace AsbCloudInfrastructure.Services switch (format) { case 1: //LAS - generator = new AsbSaubReportLas.LasReprotGenerator(dataSource); + generator = new AsbSaubReportLas.ReprotGeneratorLas(dataSource); break; case 0: //PDF default: - generator = new PdfReprotGenerator(dataSource); + generator = new AsbSaubReportPdf.ReprotGeneratorPdf(dataSource); break; } diff --git a/AsbCloudWebApi/Controllers/ReportController.cs b/AsbCloudWebApi/Controllers/ReportController.cs index 67e05734..180fb908 100644 --- a/AsbCloudWebApi/Controllers/ReportController.cs +++ b/AsbCloudWebApi/Controllers/ReportController.cs @@ -5,8 +5,6 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; using System; using System.Collections.Generic; -using System.IO; -using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -33,25 +31,6 @@ namespace AsbCloudWebApi.Controllers this.reportsHubContext = reportsHubContext; } - private void HandleReportProgressAsync(float progress, string operation, int id) => - Task.Run(() => - { - reportsHubContext.Clients.Group($"Report_{id}").SendAsync( - nameof(IReportHubClient.GetReportProgress), - new { Progress = progress, Operation = operation, ReportName = "" } - ).ConfigureAwait(false); - }); - - private void HandleReportNameAsync(string reportName, int groupId) => - Task.Run(() => - { - reportsHubContext.Clients.All.SendAsync( - nameof(IReportHubClient.GetReportProgress), - new { Progress = 100, Operation = "Отчет успешно создан", ReportName = reportName } - ).ConfigureAwait(false); - }); - - /// /// Создает отчет по скважине с указанными параметрами /// @@ -65,9 +44,44 @@ namespace AsbCloudWebApi.Controllers /// id фоновой задачи формирования отчета [HttpPost] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task CreateReportAsync(int idWell, int idUser, int stepSeconds, int format, + public async Task CreateReportAsync(int idWell, int stepSeconds, int format, DateTime begin = default, DateTime end = default, CancellationToken token = default) + { + var idCompany = User.GetCompanyId(); + var idUser = User.GetUserId(); + + if ((idCompany is null) || (idUser is null)) + return Forbid(); + + if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false)) + return Forbid(); + + void HandleReportProgressAsync(object progress, int id) => + Task.Run(() => + { + reportsHubContext.Clients.Group($"Report_{id}").SendAsync( + nameof(IReportHubClient.GetReportProgress), + progress + ).ConfigureAwait(false); + }); + + var id = reportService.CreateReport(idWell, (int)idUser, + stepSeconds, format, begin, end, HandleReportProgressAsync); + + return Ok(id); + } + + /// + /// Возвращает имена всех отчетов по скважине + /// + /// id скважины + /// Токен для отмены задачи + /// Список имен существующих отчетов (отчетов) + [HttpGet] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + public async Task GetAllReportsNamesByWellAsync(int idWell, CancellationToken token = default) { int? idCompany = User.GetCompanyId(); @@ -78,45 +92,9 @@ namespace AsbCloudWebApi.Controllers idWell, token).ConfigureAwait(false)) return Forbid(); - var id = reportService.CreateReport(idWell, idUser, - stepSeconds, format, begin, end, HandleReportProgressAsync, HandleReportNameAsync); + var reports = await reportService.GetAllReportsByWellAsync(idWell, token).ConfigureAwait(false); - return Ok(id); - } - - /// - /// Возвращает файл-отчет с диска на сервере - /// - /// id скважины - /// имя запрашиваемого файла (отчета) - /// Токен для отмены задачи - /// файл с отчетом - [HttpGet] - [Route("{reportName}")] - [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] - public async Task GetReportAsync([FromRoute] int idWell, - string reportName, CancellationToken token = default) - { - try - { - int? idCompany = User.GetCompanyId(); - - if (idCompany is null) - return Forbid(); - - if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, - idWell, token).ConfigureAwait(false)) - return Forbid(); - - // TODO: словарь content typoв - var relativePath = Path.Combine(fileService.RootPath, $"{idWell}", - $"{reportService.ReportCategoryId}", reportName); - return PhysicalFile(Path.GetFullPath(relativePath), "application/pdf", reportName); - } - catch (FileNotFoundException ex) - { - return NotFound($"Файл не найден. Текст ошибки: {ex.Message}"); - } + return Ok(reports); } /// @@ -130,6 +108,7 @@ namespace AsbCloudWebApi.Controllers /// дата окончания интервала /// Токен для отмены задачи /// Список имен существующих отчетов (отчетов) + [Obsolete] [HttpGet] [Route("suitableReports")] [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] @@ -137,12 +116,18 @@ namespace AsbCloudWebApi.Controllers DateTime begin = default, DateTime end = default, CancellationToken token = default) { + int? idCompany = User.GetCompanyId(); + + if (idCompany is null) + return Forbid(); + + if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, + idWell, token).ConfigureAwait(false)) + return Forbid(); + var suitableReportsNames = await reportService.GetSuitableReportsAsync(idWell, begin, end, stepSeconds, format, token).ConfigureAwait(false); - if (suitableReportsNames is null || !suitableReportsNames.Any()) - return NoContent(); - return Ok(suitableReportsNames); }