Skip to content

Commit

Permalink
update branch with main
Browse files Browse the repository at this point in the history
  • Loading branch information
wuall826 committed Apr 1, 2024
2 parents d9ecc00 + 8a58e76 commit 6dbc3af
Show file tree
Hide file tree
Showing 15 changed files with 387 additions and 317 deletions.
3 changes: 3 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
Jira ticket or GitHub issue:

- [ ] Includes a change file
- [ ] Updated tests (or n/a)
- [ ] Updated documentation (or n/a)
- [ ] Discussed with CGI (or n/a; see release procedure on wiki for applicability)
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,26 @@ This file is updated automatically as described in [Unreleased Changes](changes/

---------------------------------------------------------------------------------------------------

## [1.29.0] - 2024-03-28

### Added

* Format option for case downloads, allowing CSV and TSV formats in addition to Excel
* Full-Depth Summary Download from the Cases table
* DARE Input Sheet Download from the Cases table

### Changed

* Button text in first "Case QC" dialog from "Submit" to "Next" to clarify that there will be another step


## [1.28.1] - 2024-03-25

### Fixed

* Error when attempting to record sign offs


## [1.28.0] - 2024-03-14

### Added
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</parent>
<groupId>ca.on.oicr.gsi</groupId>
<artifactId>dimsum</artifactId>
<version>1.28.1-SNAPSHOT</version>
<version>1.29.1-SNAPSHOT</version>
<name>Dimsum</name>
<description>QC Tracking Dashboard</description>
<properties>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
package ca.on.oicr.gsi.dimsum.controller.rest;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -19,7 +16,9 @@
import ca.on.oicr.gsi.dimsum.controller.BadRequestException;
import ca.on.oicr.gsi.dimsum.service.CaseService;
import ca.on.oicr.gsi.dimsum.util.reporting.Report;
import ca.on.oicr.gsi.dimsum.util.reporting.reports.CaseReport;
import ca.on.oicr.gsi.dimsum.util.reporting.ReportFormat;
import ca.on.oicr.gsi.dimsum.util.reporting.reports.DareInputSheet;
import ca.on.oicr.gsi.dimsum.util.reporting.reports.FullDepthSummary;
import ca.on.oicr.gsi.dimsum.util.reporting.reports.TglTrackingReport;

@RestController
Expand All @@ -34,36 +33,31 @@ public HttpEntity<byte[]> generateReport(@PathVariable String reportName,
@RequestBody Map<String, String> parameters, HttpServletResponse response)
throws IOException {

ReportFormat format = Report.getFormat(parameters);
Report report = getReport(reportName);
XSSFWorkbook workbook = report.writeExcelFile(caseService, parameters);
byte[] bytes = report.writeFile(caseService, parameters);

HttpHeaders headers = new HttpHeaders();
headers.setContentType(new MediaType("application", "vnd.ms-excel"));
headers.setContentType(format.getMediaType());
response.setHeader("Content-Disposition",
"attachment; filename="
+ String.format("%s-%s.xlsx", reportName, DateTimeFormatter.ISO_LOCAL_DATE.format(
ZonedDateTime.now())));
+ String.format("%s-%s.%s", reportName, DateTimeFormatter.ISO_LOCAL_DATE.format(
ZonedDateTime.now()), format.getExtension()));

byte[] bytes = getReportBytes(workbook);
return new HttpEntity<byte[]>(bytes, headers);
}

private static Report getReport(String reportName) {
switch (reportName) {
case "tgl-tracking-sheet":
return TglTrackingReport.INSTANCE;
case "case-report":
return CaseReport.INSTANCE;
case "full-depth-summary":
return FullDepthSummary.INSTANCE;
case "dare-input-sheet":
return DareInputSheet.INSTANCE;
default:
throw new BadRequestException("Invalid report name");
}
}

private static byte[] getReportBytes(XSSFWorkbook workbook) throws IOException {
try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
workbook.write(output);
return output.toByteArray();
}
}

}
7 changes: 5 additions & 2 deletions src/main/java/ca/on/oicr/gsi/dimsum/service/CaseService.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -728,11 +729,13 @@ private void refreshCacheUpdatedCases() {

private void removeExpiredCachedSignoffs() {
ZonedDateTime cutoff = caseData.getTimestamp().minus(CACHE_OVERLAP_MINUTES, ChronoUnit.MINUTES);
for (String caseId : cachedSignoffsByCaseId.keySet()) {
Iterator<String> iterator = cachedSignoffsByCaseId.keySet().iterator();
while (iterator.hasNext()) {
String caseId = iterator.next();
List<NabuSavedSignoff> signoffs = cachedSignoffsByCaseId.get(caseId);
signoffs.removeIf(signoff -> signoff.getCreated().isBefore(cutoff));
if (signoffs.isEmpty()) {
cachedSignoffsByCaseId.remove(caseId);
iterator.remove();
}
}
}
Expand Down
30 changes: 19 additions & 11 deletions src/main/java/ca/on/oicr/gsi/dimsum/util/reporting/Column.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@ public void writeExcelCell(Cell cell, T object) {
cell.setCellValue(value);
}

@Override
public String getDelimitedColumnString(String delimiter, T object) {
String value = getter.apply(object);
if (value == null || value.isBlank()) {
return "";
}
// Quote string with double quotes if necessary; escape double quotes with double quotes
if (value.contains(delimiter) || value.contains("\"") || value.contains("'")) {
return "\"" + value.replace("\"", "\"\"") + "\"";
}
return value;
}

};
}

Expand All @@ -29,19 +42,12 @@ public void writeExcelCell(Cell cell, T object) {
}
}

};
}

public static <T> Column<T> forInteger(String title, Function<T, Integer> getter) {
return new Column<T>(title) {

@Override
public void writeExcelCell(Cell cell, T object) {
Integer value = getter.apply(object);
if (value != null) {
cell.setCellValue(value.doubleValue());
}
public String getDelimitedColumnString(String delimiter, T object) {
BigDecimal value = getter.apply(object);
return value.toPlainString();
}

};
}

Expand All @@ -57,4 +63,6 @@ public String getTitle() {

public abstract void writeExcelCell(Cell cell, T object);

public abstract String getDelimitedColumnString(String delimiter, T object);

}
57 changes: 55 additions & 2 deletions src/main/java/ca/on/oicr/gsi/dimsum/util/reporting/Report.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
package ca.on.oicr.gsi.dimsum.util.reporting;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import ca.on.oicr.gsi.dimsum.controller.BadRequestException;
import ca.on.oicr.gsi.dimsum.service.CaseService;

public abstract class Report {

private static final String PARAM_FORMAT = "format";
private static final String PARAM_HEADINGS = "includeHeadings";

private final String title;
private final List<ReportSection<?>> sections;

Expand All @@ -21,12 +28,58 @@ public String getTitle() {
return title;
}

public XSSFWorkbook writeExcelFile(CaseService caseService, Map<String, String> parameters) {
public static ReportFormat getFormat(Map<String, String> parameters) {
String format = parameters.get(PARAM_FORMAT);
if (format == null) {
return ReportFormat.EXCEL;
}
switch (format) {
case "excel":
return ReportFormat.EXCEL;
case "csv":
return ReportFormat.CSV;
case "tsv":
return ReportFormat.TSV;
default:
throw new BadRequestException("Invalid report format: " + format);
}
}

public byte[] writeFile(CaseService caseService, Map<String, String> parameters)
throws IOException {
ReportFormat format = getFormat(parameters);

switch (format) {
case EXCEL:
return writeExcelFile(caseService, parameters);
case CSV:
return writeDelimitedFile(caseService, ",", parameters);
case TSV:
return writeDelimitedFile(caseService, "\t", parameters);
default:
throw new BadRequestException("Invalid download format: " + format);
}
}

private byte[] writeExcelFile(CaseService caseService, Map<String, String> parameters)
throws IOException {
XSSFWorkbook workbook = new XSSFWorkbook();
for (ReportSection<?> section : sections) {
section.createExcelSheet(workbook, caseService, parameters);
}
return workbook;
try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
workbook.write(output);
return output.toByteArray();
}
}

private byte[] writeDelimitedFile(CaseService caseService, String delimiter,
Map<String, String> parameters) {
StringBuilder sb = new StringBuilder();
boolean includeHeadings = Objects.equals("true", parameters.get(PARAM_HEADINGS));
// This does not support multiple sections
sections.get(0).createDelimitedText(sb, caseService, delimiter, includeHeadings, parameters);
return sb.toString().getBytes();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package ca.on.oicr.gsi.dimsum.util.reporting;

import org.springframework.http.MediaType;

public enum ReportFormat {
// @formatter:off
EXCEL(new MediaType("application", "vnd.ms-excel"), "xlsx"),
CSV(new MediaType("text", "csv"), "csv"),
TSV(new MediaType("text", "tab-separated-values"), "tsv");
// @formatter:on

private final MediaType mediaType;
private final String extension;

private ReportFormat(MediaType mediaType, String extension) {
this.mediaType = mediaType;
this.extension = extension;
}

public MediaType getMediaType() {
return mediaType;
}

public String getExtension() {
return extension;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import ca.on.oicr.gsi.dimsum.controller.BadRequestException;
import ca.on.oicr.gsi.dimsum.service.CaseService;

public abstract class ReportSection<T> {
Expand Down Expand Up @@ -41,6 +42,29 @@ public void writeExcelSheet(XSSFSheet worksheet, List<T> objects) {
}
}

@Override
public void writeDelimitedText(StringBuilder sb, List<T> objects, String delimiter,
boolean includeHeaders) {
List<Column<T>> columns = getColumns();
if (includeHeaders) {
for (int i = 0; i < columns.size(); i++) {
if (i > 0) {
sb.append(delimiter);
}
sb.append(columns.get(i).getTitle());
}
}
for (T object : objects) {
for (int i = 0; i < columns.size(); i++) {
if (i > 0) {
sb.append(delimiter);
}
sb.append(columns.get(i).getDelimitedColumnString(delimiter, object));
}
sb.append("\r\n");
}
}

}

private final String title;
Expand Down Expand Up @@ -68,6 +92,15 @@ public void createExcelSheet(XSSFWorkbook workbook, CaseService caseService,

protected abstract void writeExcelSheet(XSSFSheet worksheet, List<T> objects);

public void createDelimitedText(StringBuilder sb, CaseService caseService,
String delimiter, boolean includeHeadings, Map<String, String> parameters) {
List<T> objects = getData(caseService, parameters);
writeDelimitedText(sb, objects, delimiter, includeHeadings);
}

protected abstract void writeDelimitedText(StringBuilder sb, List<T> objects, String delimiter,
boolean includeHeaders);

/**
* Fetches data from the CaseService based on parameters provided
*
Expand Down
Loading

0 comments on commit 6dbc3af

Please sign in to comment.