Skip to content

Commit

Permalink
Merge pull request #10 from cortside/feature/SVC-1275
Browse files Browse the repository at this point in the history
Feature/svc 1275
  • Loading branch information
cYCL157 authored Apr 29, 2022
2 parents 03ea955 + 3b84ac4 commit 5bab3d6
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cortside.Common.DomainEvent;
using Cortside.SqlReportApi.Data;
Expand Down Expand Up @@ -199,5 +201,38 @@ public async Task ShouldExecuteReport() {
result.Should().NotBeNull();
}
}

[Fact]
public async Task ShouldExportReport() {
//arrange
var report = new ReportResult("my report") {
Columns = new List<ReportColumn> {
new ReportColumn {
Name = "column1"
},
new ReportColumn {
Name = "column2"
}
},
Rows = new List<object[]> {
new object[] {
"c1r1",
"c2,r1"},
new object[] {
"c1r2",
"c2r2"
},
}
};

//act
var result = service.ExportReport(report);

//assert
result.CanRead.Should().BeTrue();
var reader = new StreamReader(result);
var content = reader.ReadToEnd();
content.Should().ContainAll("column1,", "column2,", "c1r1,", "\"c2,r1\",", "c1r2,", "c2r2,");
}
}
}
Binary file not shown.
4 changes: 4 additions & 0 deletions src/Cortside.SqlReportApi.DomainService/ISqlReportService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using Cortside.SqlReportApi.Data;
using Cortside.SqlReportApi.Domain;
Expand All @@ -25,5 +27,7 @@ public interface ISqlReportService {
ReportArgumentQuery GetReportArgumentQuery(int id);

Task<ReportResult> ExecuteReport(string name, IQueryCollection query, List<string> permissions);

Stream ExportReport(ReportResult report);
}
}
28 changes: 28 additions & 0 deletions src/Cortside.SqlReportApi.DomainService/SqlReportService.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cortside.SqlReportApi.Data;
using Cortside.SqlReportApi.Domain;
Expand Down Expand Up @@ -184,5 +186,31 @@ public async Task<ReportResult> ExecuteReport(string name, IQueryCollection args
}
return result;
}

public Stream ExportReport(ReportResult report) {
var stream = new MemoryStream();
var writer = new StreamWriter(stream);

// write header
foreach (var column in report.Columns) {
writer.Write($"{column.Name},");
}

// write body
foreach (var row in report.Rows) {
writer.WriteLine();
foreach (var column in row) {
if (column.ToString().Contains(',')) {
// handle commas
writer.Write($"\"{column}\",");
} else {
writer.Write($"{column},");
}
}
};
writer.Flush();
stream.Position = 0;
return stream;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Cortside.SqlReportApi.Data;
Expand Down Expand Up @@ -212,5 +213,56 @@ public void GetReportGroupsShouldReturnObject() {
viewResult.Which.Value.Should().BeEquivalentTo(reportGroup);
serviceMock.Verify(s => s.GetReportGroups(), Times.Once);
}


[Fact]
public async void ExportReportShouldReturnObject() {
//arrange
var request = new Mock<HttpRequest>();
var context = new Mock<HttpContext>();
var dictionary = new Dictionary<string, StringValues>();
dictionary.Add("date", new StringValues("01/01/2000"));
var collection = new QueryCollection(dictionary);

request.SetupGet(x => x.Query).Returns(collection);
context.SetupGet(x => x.Request).Returns(request.Object);


var report = new ReportResult("my report") {
Columns = new List<ReportColumn> {
new ReportColumn {
Name = "column1"
},
new ReportColumn {
Name = "column2"
}
},
Rows = new List<object[]> {
new object[] {
"row1column1",
"row1column2"},
new object[] {
"row2column1",
"row2column2"
},
}
};

using MemoryStream stream = new MemoryStream();
using StreamWriter writer = new StreamWriter(stream);
writer.WriteLine("column1", "column2");
writer.WriteLine("row1column1", "row1column2");
writer.WriteLine("row2column1", "row2column2");

reportController.ControllerContext = new ControllerContext(new ActionContext(context.Object, new RouteData(), new ControllerActionDescriptor()));
serviceMock.Setup(s => s.ExecuteReport(It.IsAny<string>(), It.IsAny<QueryCollection>(), It.IsAny<List<string>>())).Returns(Task.FromResult(report));
serviceMock.Setup(s => s.ExportReport(It.IsAny<ReportResult>())).Returns(stream);

//act
var result = await reportController.Export("report");

//assert
var viewResult = result.Should().BeAssignableTo<FileStreamResult>();
}
}
}
28 changes: 28 additions & 0 deletions src/Cortside.SqlReportApi.WebApi/Controllers/ReportController.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Cortside.SqlReportApi.Data;
using Cortside.SqlReportApi.DomainService;
Expand Down Expand Up @@ -60,5 +63,30 @@ public async Task<IActionResult> Get(string name) {
return new UnauthorizedResult();
}
}

/// <summary>
/// Export report as csv
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
[HttpGet]
[Route("{name}/export")]
public async Task<IActionResult> Export(string name) {
var authProperties = await policyClient.EvaluateAsync(User);
AuthorizationModel responseModel = new AuthorizationModel() {
Permissions = authProperties.Permissions.ToList()
};
var permissionsPrefix = "Sql Report";
responseModel.Permissions = responseModel.Permissions.Select(p => $"{permissionsPrefix}.{p}").ToList();
try {
var report = await svc.ExecuteReport(name, Request.Query, authProperties.Permissions.ToList());
Stream result = svc.ExportReport(report);
return File(result, "application/octet-stream");
} catch (ResourceNotFoundMessage) {
return new NotFoundResult();
} catch (NotAuthorizedMessage) {
return new UnauthorizedResult();
}
}
}
}

0 comments on commit 5bab3d6

Please sign in to comment.