public async void IReport_ReportMultiple_Tests() { PdfReport report = new PdfReport("a/b/c/file.pdf"); Assert.True(await report.Configure(PdfApiMock.Object, BarcodeMock.Object), "Configure should succeed"); var result = await report.Report(new Report.Model.Document() { DefaultFont = new Font { Name = "name1", Size = 10, Style = "italic" }, Content = new List <ContentObject>() { new ContentObject { Page = new List <PageContentItem>() { new PageContentItem() { Text = "mock text", Location = new Location() { Left = 10, Top = 20, Right = 300, Bottom = 400 } }, new PageContentItem() { Url = "file://issue-link-qr?link=123", Location = new Location() { Left = 50, Top = 60, Right = 700, Bottom = 800 } }, new PageContentItem() { Rows = new List <TableRow>() { new TableRow() { Cells = new List <TableCell>() { new TableCell() { Text = "cell 11" }, new TableCell() { Text = "cell 12" } } } } } } }, new ContentObject { Page = new List <PageContentItem>() { new PageContentItem() { Text = "mock text2", Location = new Location() { Left = 10, Top = 20, Right = 300, Bottom = 400 } }, new PageContentItem() { Url = "file://issue-link-qr?link=123", Location = new Location() { Left = 50, Top = 60, Right = 700, Bottom = 800 } }, new PageContentItem() { Rows = new List <TableRow>() { new TableRow() { Cells = new List <TableCell>() { new TableCell() { Text = "cell 11-1" }, new TableCell() { Text = "cell 12-1" } } } } } } } } }); Assert.True(result, "Invalid Report result"); Assert.Equal("name1", report._defaultFont.Name); Assert.Equal(10, report._defaultFont.Size); Assert.Equal("italic", report._defaultFont.Style); PdfApiMock.Verify(e => e.PutCreateDocumentAsync(It.IsRegex("[-0-9A-Fa-f]*\\.pdf"), null, "a/b/c/tmp_file.pdf"), Times.Exactly(2)); PdfApiMock.Verify(e => e.PostDocumentTextHeaderAsync(It.IsRegex("[-0-9A-Fa-f]*\\.pdf"), It.Is <TextHeader>(h => Regex.IsMatch(h.Value, "Generated.*by Aspose.PDF Exporter")) , It.IsAny <int?>(), It.IsAny <int?>(), null, "a/b/c/tmp_file.pdf"), Times.Exactly(2)); PdfApiMock.Verify(e => e.PostDocumentTextHeaderAsync(It.IsRegex("[-0-9A-Fa-f]*\\.pdf"), It.Is <TextHeader>(h => Regex.IsMatch(h.Value, "Generated.*by Aspose.PDF Exporter")) , It.IsAny <int?>(), It.IsAny <int?>(), null, "a/b/c/tmp_file.pdf"), Times.Exactly(2)); PdfApiMock.Verify(e => e.PostDocumentTextFooterAsync(It.IsRegex("[-0-9A-Fa-f]*\\.pdf"), It.Is <TextFooter>(h => Regex.IsMatch(h.Value, "Powered by Aspose.PDF for Cloud, Aspose.Barcode for Cloud")) , It.IsAny <int?>(), It.IsAny <int?>(), null, "a/b/c/tmp_file.pdf"), Times.Exactly(2)); PdfApiMock.Verify(e => e.PutAddTextAsync(It.IsRegex("[-0-9A-Fa-f]*\\.pdf"), 1, It.Is <Paragraph>(p => p.Lines.Exists(l => l.Segments.Exists(s => s.Value == "mock text")) && IsEqual(p.Rectangle.LLX, 10) && IsEqual(p.Rectangle.LLY, 440) && IsEqual(p.Rectangle.URX, 300) && IsEqual(p.Rectangle.URY, 820) ), "a/b/c/tmp_file.pdf", null), Times.Once); PdfApiMock.Verify(e => e.PutAddTextAsync(It.IsRegex("[-0-9A-Fa-f]*\\.pdf"), 1, It.Is <Paragraph>(p => p.Lines.Exists(l => l.Segments.Exists(s => s.Value == "mock text2")) && IsEqual(p.Rectangle.LLX, 10) && IsEqual(p.Rectangle.LLY, 440) && IsEqual(p.Rectangle.URX, 300) && IsEqual(p.Rectangle.URY, 820) ), "a/b/c/tmp_file.pdf", null), Times.Once); PdfApiMock.Verify(e => e.PostInsertImageAsync(It.IsRegex("[-0-9A-Fa-f]*\\.pdf"), 1 , It.Is <double>(m => IsEqual(m, 50)) , It.Is <double>(m => IsEqual(m, 40)) , It.Is <double>(m => IsEqual(m, 700)) , It.Is <double>(m => IsEqual(m, 780)) , It.IsRegex("[-0-9A-Fa-f]*\\.pdf"), null, "a/b/c/tmp_file.pdf", It.IsAny <Stream>()), Times.Exactly(2)); PdfApiMock.Verify(e => e.PostPageTablesAsync(It.IsRegex("[-0-9A-Fa-f]*\\.pdf"), 1, It.Is <List <Table> >(ts => ts.Count == 1 && ts[0].Rows.Count == 1 && ts[0].Rows[0].Cells[0].Paragraphs.Count == 1 && ts[0].Rows[0].Cells[0].Paragraphs[0].Text == "cell 11" && ts[0].Rows[0].Cells[1].Paragraphs.Count == 1 && ts[0].Rows[0].Cells[1].Paragraphs[0].Text == "cell 12" ), null, "a/b/c/tmp_file.pdf"), Times.Once); PdfApiMock.Verify(e => e.PostPageTablesAsync(It.IsRegex("[-0-9A-Fa-f]*\\.pdf"), 1, It.Is <List <Table> >(ts => ts.Count == 1 && ts[0].Rows.Count == 1 && ts[0].Rows[0].Cells[0].Paragraphs.Count == 1 && ts[0].Rows[0].Cells[0].Paragraphs[0].Text == "cell 11-1" && ts[0].Rows[0].Cells[1].Paragraphs.Count == 1 && ts[0].Rows[0].Cells[1].Paragraphs[0].Text == "cell 12-1" ), null, "a/b/c/tmp_file.pdf"), Times.Once); PdfApiMock.Verify(e => e.PutMergeDocumentsAsync("file.pdf", It.Is <MergeDocuments>(f => f.List.Count == 2), null, "a/b/c"), Times.Once); }
public async Task <IActionResult> ExportIssues([FromForm(Name = "issues")] List <string> issuesList, [FromForm(Name = "includeqr")] bool includeQRCode , [FromHeader(Name = "Referer")] string referer, [FromHeader(Name = "x-real-ip")] string realIp, [FromHeader(Name = "User-Agent")] string userAgent , [FromHeader(Name = "x-forwarded-for")] string forwardedFor) { IActionResult result = null; DateTime requestDateTime = DateTime.Now; TaskMeasurer taskMeasurer = new TaskMeasurer(); string extension = "pdf"; Model.ClientRegistration registrationData = _client.RegistrationData; string fileId = Guid.NewGuid().ToString(); string reportFileName = $"{_configuration.GetValue<string>("Settings:StorageRoot", "clients_jiracloud")}/{registrationData.ClientKey}/{fileId}.{extension}"; JArray fields = null; JObject issues = null; Dictionary <string, JArray> epicStories = new Dictionary <string, JArray>(); Report.Model.Document document = null; Model.ReportFile reportFile = null; ReportJiraCloudModel reportJiraCloudModel = null; List <StatisticalDocument> statItems = new List <StatisticalDocument>(); try { _logger.LogInformation($"{requestDateTime} New job ClientKey {registrationData.ClientKey}, issues {String.Join(", ", issuesList)}"); HttpClient httpCli = _clientFactory.CreateClient("jira_client"); httpCli.BaseAddress = new Uri(registrationData.BaseUrl); RestApiClient cli = new RestApiClient(registrationData.Key, registrationData.SharedSecret, registrationData.ClientKey, httpCli); fields = (JArray)JsonConvert.DeserializeObject(await taskMeasurer.Run(() => cli.Get($"/rest/api/3/field"), "000_FetchFields")); var EpicNameField = getField(fields, "com.pyxis.greenhopper.jira:gh-epic-label"); string[] responses = await taskMeasurer.Run(() => Task.WhenAll(issuesList.Select(i => cli.Get($"/rest/api/3/issue/{i}"))), "111_FetchIssuesData"); PdfReport pdfReport = new PdfReport(filePath: reportFileName, storageName: _configuration.GetValue <string>("Settings:StorageName"), debug: _hostEnvironment.IsDevelopment()); await pdfReport.Configure(_client.PdfApi, _client.BarcodeApi); issues = JToken.FromObject(new { issues = responses.Select(JsonConvert.DeserializeObject).ToList() }) as JObject; // get stories for epics epicStories = new Dictionary <string, JArray>(); if (!string.IsNullOrEmpty(EpicNameField)) { var issuesArr = await Task.WhenAll(issues["issues"] .Where(i => !string.IsNullOrEmpty(i.SelectToken($"$.fields.{EpicNameField}")?.ToString())) .Select(async i => KeyValuePair.Create(i.SelectToken($"$.key")?.ToString(), await getSubtasksForEpic(cli, i.SelectToken($"$.key")?.ToString())) )); epicStories = issuesArr.ToDictionary(t => t.Key, t => t.Value); } document = taskMeasurer.RunSync(() => { reportJiraCloudModel = new ReportJiraCloudModel(System.IO.File.ReadAllText( _configuration.GetValue("Templates:ReportIssuesModel", "template/Report-Issues.Mustache"))) { EpicLinkField = getField(fields, "com.pyxis.greenhopper.jira:gh-epic-link"), EpicNameField = EpicNameField, GenerateQRCode = includeQRCode }; return(reportJiraCloudModel.CreateReportModel(reportJiraCloudModel.issuesModel(issues, epicStories))); }, "112_PrepareReportModel"); if (null == document.Options) { document.Options = new Report.Model.DocumentOptions(); } await pdfReport.Report(document); DateTime current = DateTime.Now; reportFile = new Model.ReportFile { UniqueId = $"{Guid.NewGuid()}", ReportType = extension, ContentType = "application/pdf", FileName = issuesList.Count == 1 ? $"{issuesList.First()}.{extension}" : $"Issues.{extension}", StorageFileName = reportFileName, ClientId = registrationData.Id, Created = current, Expired = current.AddHours(_configuration.GetValue("Settings:FileExpirationHours", 24)), }; _dbContext.ReportFile.Add(reportFile); statItems = taskMeasurer.Stat.Concat(pdfReport.Stat).ToList(); await _dbContext.SaveChangesAsync(); _logger.LogInformation($"{current} Finished {registrationData.ClientKey} in {DateTime.Now - requestDateTime}"); return(result = new OkObjectResult(new { fileid = reportFile.UniqueId , downloadlink = _basePathReplacement.ReplaceBaseUrl(Url.Link("GetDownload", new { id = reportFile.UniqueId })) , expText = TimeSpan.FromHours(_configuration.GetValue("Settings:FileExpirationHours", 24)).ToReadableString() , exp = reportFile.Expired })); } catch (Exception ex) { ZipFileArchive archive = new ZipFileArchive().AddFile("010_request_params.json", new { RequestId = _client.RequestId, FileId = fileId, FileName = reportFileName, includeQRCode, referer, realIp, userAgent, forwardedFor, issues = issuesList }); foreach (var f in new Dictionary <string, object> { { "020_registration.json", registrationData }, { "030_fields.json", fields }, { "040_issues.json", issues }, { "050_epic_stories.json", epicStories }, { "051_RenderedDocument.yaml", reportJiraCloudModel?.RenderedYamlDocument }, { "052_RenderedJsonDocument.yaml", reportJiraCloudModel?.RenderedJsonDocument }, { "060_document.json", document }, { "070_report_file.json", reportFile }, { "080_result.json", result }, }.ToArray()) { archive.AddFile(f.Key, f.Value); } throw new ControllerException($"Error generating {reportFileName}", innerException: ex, customData: await archive.Archive()); } finally { _client.Stat = statItems; } }