Refactor report generation logic and enhance Excel/PDF output formatting

- Updated the ReportService to improve the structure of Excel and PDF report generation, including the addition of fiscal period parameters.
- Refactored methods to build summary and detail sheets in Excel, enhancing readability and styling.
- Improved PDF document layout and added titles for better presentation of report data.
- Enhanced integration tests to verify the correctness of generated reports and ensure the presence of expected artifacts.
This commit is contained in:
DongHeon Jang 2026-04-17 11:27:29 +09:00
parent 114c58737f
commit 661d78a225
2 changed files with 395 additions and 32 deletions

View File

@ -8,15 +8,36 @@ import com.hanwha.nexacrodemo.consolidation.ConsolidationPayload;
import com.hanwha.nexacrodemo.minio.ObjectStorageService; import com.hanwha.nexacrodemo.minio.ObjectStorageService;
import com.hanwha.nexacrodemo.minio.StoredObject; import com.hanwha.nexacrodemo.minio.StoredObject;
import com.lowagie.text.Document; import com.lowagie.text.Document;
import com.lowagie.text.Element;
import com.lowagie.text.Font;
import com.lowagie.text.FontFactory;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph; import com.lowagie.text.Paragraph;
import com.lowagie.text.Phrase;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter; import com.lowagie.text.pdf.PdfWriter;
import java.awt.Color;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.FontUnderline;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
@ -27,6 +48,10 @@ import org.springframework.stereotype.Service;
@Service @Service
public class ReportService { public class ReportService {
private static final DateTimeFormatter REPORT_TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
private static final DecimalFormat AMOUNT_FORMAT = new DecimalFormat("#,##0.00");
private static final Map<String, String> LABELS = buildLabels();
private final ReportMapper reportMapper; private final ReportMapper reportMapper;
private final ConsolidationMapper consolidationMapper; private final ConsolidationMapper consolidationMapper;
private final ObjectStorageService objectStorageService; private final ObjectStorageService objectStorageService;
@ -53,7 +78,7 @@ public class ReportService {
public void generateReports(Long runId, String fiscalPeriod, ConsolidationPayload payload) { public void generateReports(Long runId, String fiscalPeriod, ConsolidationPayload payload) {
try { try {
byte[] excelBytes = buildExcel(payload); byte[] excelBytes = buildExcel(fiscalPeriod, payload);
byte[] pdfBytes = buildPdf(fiscalPeriod, payload); byte[] pdfBytes = buildPdf(fiscalPeriod, payload);
ReportArtifactCommand excelArtifact = new ReportArtifactCommand(); ReportArtifactCommand excelArtifact = new ReportArtifactCommand();
@ -93,19 +118,13 @@ public class ReportService {
.body(new ByteArrayResource(storedObject.getBytes())); .body(new ByteArrayResource(storedObject.getBytes()));
} }
private byte[] buildExcel(ConsolidationPayload payload) throws IOException { private byte[] buildExcel(String fiscalPeriod, ConsolidationPayload payload) throws IOException {
try (XSSFWorkbook workbook = new XSSFWorkbook()) { try (XSSFWorkbook workbook = new XSSFWorkbook()) {
Sheet summarySheet = workbook.createSheet("Summary"); Map<String, CellStyle> styles = createExcelStyles(workbook);
int rowIndex = 0; buildSummarySheet(workbook, fiscalPeriod, payload, styles);
for (Map.Entry<String, BigDecimal> metric : payload.getMetrics().entrySet()) { buildDetailSheet(workbook, "Contributions", fiscalPeriod, payload.getContributionRows(), styles);
Row row = summarySheet.createRow(rowIndex++); buildDetailSheet(workbook, "Eliminations", fiscalPeriod, payload.getEliminationRows(), styles);
row.createCell(0).setCellValue(metric.getKey()); buildDetailSheet(workbook, "Forecast", fiscalPeriod, payload.getForecastRows(), styles);
row.createCell(1).setCellValue(metric.getValue().doubleValue());
}
writeRows(workbook.createSheet("Contributions"), payload.getContributionRows());
writeRows(workbook.createSheet("Eliminations"), payload.getEliminationRows());
writeRows(workbook.createSheet("Forecast"), payload.getForecastRows());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
workbook.write(outputStream); workbook.write(outputStream);
@ -115,39 +134,352 @@ public class ReportService {
private byte[] buildPdf(String fiscalPeriod, ConsolidationPayload payload) throws IOException { private byte[] buildPdf(String fiscalPeriod, ConsolidationPayload payload) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Document document = new Document(); Document document = new Document(PageSize.A4.rotate(), 36, 36, 36, 36);
PdfWriter.getInstance(document, outputStream); PdfWriter.getInstance(document, outputStream);
document.open(); document.open();
document.add(new Paragraph("Hanwha Consolidation Demo")); addPdfTitle(document, "Hanwha Consolidation Summary", 18, new Color(24, 54, 93));
document.add(new Paragraph("Fiscal period: " + fiscalPeriod)); addPdfTitle(document, "Fiscal period " + fiscalPeriod + " | Generated " + generatedAt(), 10, new Color(90, 96, 106));
document.add(new Paragraph(" ")); document.add(new Paragraph(" "));
for (Map.Entry<String, BigDecimal> metric : payload.getMetrics().entrySet()) { addSummaryTable(document, payload.getMetrics());
document.add(new Paragraph(metric.getKey() + ": " + metric.getValue())); addDetailTable(document, "Contributions", payload.getContributionRows(), 8);
} addDetailTable(document, "Eliminations", payload.getEliminationRows(), 8);
addDetailTable(document, "Forecast", payload.getForecastRows(), 8);
document.close(); document.close();
return outputStream.toByteArray(); return outputStream.toByteArray();
} }
private void writeRows(Sheet sheet, List<Map<String, Object>> rows) { private void buildSummarySheet(
XSSFWorkbook workbook,
String fiscalPeriod,
ConsolidationPayload payload,
Map<String, CellStyle> styles
) {
Sheet sheet = workbook.createSheet("Summary");
sheet.setDisplayGridlines(false);
Row titleRow = sheet.createRow(0);
titleRow.setHeightInPoints(28);
createCell(titleRow, 0, "Hanwha Consolidation Summary", styles.get("title"));
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 3));
Row subtitleRow = sheet.createRow(1);
createCell(subtitleRow, 0, "Fiscal period " + fiscalPeriod + " | Generated " + generatedAt(), styles.get("subtitle"));
sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 3));
Row sectionRow = sheet.createRow(3);
createCell(sectionRow, 0, "Performance Snapshot", styles.get("section"));
Row headerRow = sheet.createRow(4);
createCell(headerRow, 0, "Metric", styles.get("header"));
createCell(headerRow, 1, "Value", styles.get("header"));
int rowIndex = 5;
for (Map.Entry<String, BigDecimal> metric : payload.getMetrics().entrySet()) {
Row row = sheet.createRow(rowIndex++);
createCell(row, 0, label(metric.getKey()), styles.get("text"));
createNumericCell(row, 1, metric.getValue(), styleForKey(styles, metric.getKey()));
}
sheet.createFreezePane(0, 5);
sheet.setColumnWidth(0, 26 * 256);
sheet.setColumnWidth(1, 18 * 256);
sheet.setColumnWidth(2, 18 * 256);
sheet.setColumnWidth(3, 18 * 256);
}
private void buildDetailSheet(
XSSFWorkbook workbook,
String sheetName,
String fiscalPeriod,
List<Map<String, Object>> rows,
Map<String, CellStyle> styles
) {
Sheet sheet = workbook.createSheet(sheetName);
sheet.setDisplayGridlines(false);
int columnCount = rows.isEmpty() ? 1 : rows.get(0).size();
Row titleRow = sheet.createRow(0);
titleRow.setHeightInPoints(24);
createCell(titleRow, 0, sheetName + " Detail", styles.get("title"));
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, Math.max(0, columnCount - 1)));
Row subtitleRow = sheet.createRow(1);
createCell(subtitleRow, 0, "Fiscal period " + fiscalPeriod + " | Rows " + rows.size(), styles.get("subtitle"));
sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, Math.max(0, columnCount - 1)));
if (rows.isEmpty()) { if (rows.isEmpty()) {
Row row = sheet.createRow(0); Row emptyRow = sheet.createRow(3);
row.createCell(0).setCellValue("No data"); createCell(emptyRow, 0, "No data available", styles.get("empty"));
sheet.setColumnWidth(0, 24 * 256);
return; return;
} }
Row header = sheet.createRow(0); List<String> keys = List.copyOf(rows.get(0).keySet());
int cellIndex = 0; Row headerRow = sheet.createRow(3);
for (String key : rows.get(0).keySet()) { for (int index = 0; index < keys.size(); index++) {
header.createCell(cellIndex++).setCellValue(key); createCell(headerRow, index, label(keys.get(index)), styles.get("header"));
} }
int rowIndex = 1; int rowIndex = 4;
for (Map<String, Object> item : rows) { for (Map<String, Object> item : rows) {
Row row = sheet.createRow(rowIndex++); Row row = sheet.createRow(rowIndex++);
int valueIndex = 0; for (int cellIndex = 0; cellIndex < keys.size(); cellIndex++) {
for (Object value : item.values()) { String key = keys.get(cellIndex);
row.createCell(valueIndex++).setCellValue(value == null ? "" : String.valueOf(value)); writeValueCell(row, cellIndex, key, item.get(key), styles);
} }
} }
sheet.createFreezePane(0, 4);
sheet.setAutoFilter(new CellRangeAddress(3, rowIndex - 1, 0, keys.size() - 1));
for (int index = 0; index < keys.size(); index++) {
sheet.autoSizeColumn(index);
int currentWidth = sheet.getColumnWidth(index);
sheet.setColumnWidth(index, Math.min(currentWidth + 1024, 28 * 256));
}
}
private Map<String, CellStyle> createExcelStyles(XSSFWorkbook workbook) {
Map<String, CellStyle> styles = new LinkedHashMap<>();
short amountFormat = workbook.createDataFormat().getFormat("#,##0.00");
short percentFormat = workbook.createDataFormat().getFormat("0.00%");
var titleFont = workbook.createFont();
titleFont.setBold(true);
titleFont.setColor(org.apache.poi.ss.usermodel.IndexedColors.WHITE.getIndex());
titleFont.setFontHeightInPoints((short) 14);
var subtitleFont = workbook.createFont();
subtitleFont.setColor(org.apache.poi.ss.usermodel.IndexedColors.GREY_80_PERCENT.getIndex());
var sectionFont = workbook.createFont();
sectionFont.setBold(true);
sectionFont.setColor(org.apache.poi.ss.usermodel.IndexedColors.DARK_BLUE.getIndex());
var headerFont = workbook.createFont();
headerFont.setBold(true);
headerFont.setColor(org.apache.poi.ss.usermodel.IndexedColors.WHITE.getIndex());
var emptyFont = workbook.createFont();
emptyFont.setItalic(true);
emptyFont.setUnderline(FontUnderline.SINGLE);
emptyFont.setColor(org.apache.poi.ss.usermodel.IndexedColors.GREY_50_PERCENT.getIndex());
CellStyle title = workbook.createCellStyle();
title.setFont(titleFont);
title.setFillForegroundColor(org.apache.poi.ss.usermodel.IndexedColors.DARK_BLUE.getIndex());
title.setFillPattern(FillPatternType.SOLID_FOREGROUND);
title.setAlignment(HorizontalAlignment.LEFT);
title.setVerticalAlignment(VerticalAlignment.CENTER);
title.setBorderBottom(BorderStyle.THIN);
styles.put("title", title);
CellStyle subtitle = workbook.createCellStyle();
subtitle.setFont(subtitleFont);
subtitle.setAlignment(HorizontalAlignment.LEFT);
styles.put("subtitle", subtitle);
CellStyle section = workbook.createCellStyle();
section.setFont(sectionFont);
section.setAlignment(HorizontalAlignment.LEFT);
styles.put("section", section);
CellStyle header = workbook.createCellStyle();
header.setFont(headerFont);
header.setFillForegroundColor(org.apache.poi.ss.usermodel.IndexedColors.ORANGE.getIndex());
header.setFillPattern(FillPatternType.SOLID_FOREGROUND);
header.setAlignment(HorizontalAlignment.CENTER);
header.setVerticalAlignment(VerticalAlignment.CENTER);
applyBorder(header);
styles.put("header", header);
CellStyle text = workbook.createCellStyle();
text.setAlignment(HorizontalAlignment.LEFT);
text.setVerticalAlignment(VerticalAlignment.CENTER);
applyBorder(text);
styles.put("text", text);
CellStyle number = workbook.createCellStyle();
number.cloneStyleFrom(text);
number.setAlignment(HorizontalAlignment.RIGHT);
number.setDataFormat(amountFormat);
styles.put("number", number);
CellStyle ratio = workbook.createCellStyle();
ratio.cloneStyleFrom(number);
ratio.setDataFormat(percentFormat);
styles.put("ratio", ratio);
CellStyle empty = workbook.createCellStyle();
empty.setFont(emptyFont);
styles.put("empty", empty);
return styles;
}
private void applyBorder(CellStyle style) {
style.setBorderTop(BorderStyle.THIN);
style.setBorderRight(BorderStyle.THIN);
style.setBorderBottom(BorderStyle.THIN);
style.setBorderLeft(BorderStyle.THIN);
}
private void writeValueCell(Row row, int cellIndex, String key, Object value, Map<String, CellStyle> styles) {
if (value instanceof BigDecimal decimal) {
createNumericCell(row, cellIndex, decimal, styleForKey(styles, key));
return;
}
if (value instanceof Number number) {
createNumericCell(row, cellIndex, BigDecimal.valueOf(number.doubleValue()), styleForKey(styles, key));
return;
}
createCell(row, cellIndex, value == null ? "" : String.valueOf(value), styles.get("text"));
}
private void createCell(Row row, int index, String value, CellStyle style) {
var cell = row.createCell(index);
cell.setCellValue(value);
cell.setCellStyle(style);
}
private void createNumericCell(Row row, int index, BigDecimal value, CellStyle style) {
var cell = row.createCell(index);
cell.setCellValue(value.doubleValue());
cell.setCellStyle(style);
}
private CellStyle styleForKey(Map<String, CellStyle> styles, String key) {
return key.toLowerCase().contains("ratio") ? styles.get("ratio") : styles.get("number");
}
private void addPdfTitle(Document document, String text, int size, Color color) {
Font font = FontFactory.getFont(FontFactory.HELVETICA_BOLD, size, color);
Paragraph paragraph = new Paragraph(text, font);
paragraph.setAlignment(Element.ALIGN_LEFT);
paragraph.setSpacingAfter(4f);
document.add(paragraph);
}
private void addSummaryTable(Document document, Map<String, BigDecimal> metrics) {
PdfPTable table = new PdfPTable(new float[] {3f, 1.3f});
table.setWidthPercentage(100f);
table.setSpacingBefore(6f);
table.setSpacingAfter(12f);
table.addCell(pdfHeaderCell("Metric"));
table.addCell(pdfHeaderCell("Value"));
for (Map.Entry<String, BigDecimal> metric : metrics.entrySet()) {
table.addCell(pdfBodyCell(label(metric.getKey()), Element.ALIGN_LEFT));
table.addCell(pdfBodyCell(format(metric.getValue(), metric.getKey()), Element.ALIGN_RIGHT));
}
document.add(table);
}
private void addDetailTable(Document document, String title, List<Map<String, Object>> rows, int maxRows) {
Font sectionFont = FontFactory.getFont(FontFactory.HELVETICA_BOLD, 12, new Color(24, 54, 93));
Paragraph section = new Paragraph(title, sectionFont);
section.setSpacingBefore(8f);
section.setSpacingAfter(6f);
document.add(section);
if (rows.isEmpty()) {
document.add(new Paragraph("No data available", FontFactory.getFont(FontFactory.HELVETICA_OBLIQUE, 10, new Color(120, 120, 120))));
return;
}
List<String> keys = List.copyOf(rows.get(0).keySet());
PdfPTable table = new PdfPTable(keys.size());
table.setWidthPercentage(100f);
table.setSpacingAfter(8f);
for (String key : keys) {
table.addCell(pdfHeaderCell(label(key)));
}
int visibleRows = Math.min(maxRows, rows.size());
for (int rowIndex = 0; rowIndex < visibleRows; rowIndex++) {
Map<String, Object> row = rows.get(rowIndex);
for (String key : keys) {
int alignment = isNumericValue(row.get(key)) ? Element.ALIGN_RIGHT : Element.ALIGN_LEFT;
table.addCell(pdfBodyCell(format(row.get(key), key), alignment));
}
}
document.add(table);
if (rows.size() > maxRows) {
document.add(new Paragraph(
"Showing first " + maxRows + " of " + rows.size() + " rows.",
FontFactory.getFont(FontFactory.HELVETICA_OBLIQUE, 9, new Color(120, 120, 120))
));
}
}
private PdfPCell pdfHeaderCell(String text) {
PdfPCell cell = new PdfPCell(new Phrase(text, FontFactory.getFont(FontFactory.HELVETICA_BOLD, 9, Color.WHITE)));
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setBackgroundColor(new Color(243, 127, 32));
cell.setBorderColor(new Color(220, 220, 220));
cell.setPadding(6f);
return cell;
}
private PdfPCell pdfBodyCell(String text, int alignment) {
PdfPCell cell = new PdfPCell(new Phrase(text, FontFactory.getFont(FontFactory.HELVETICA, 9, Color.DARK_GRAY)));
cell.setHorizontalAlignment(alignment);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setBorderColor(new Color(226, 229, 233));
cell.setPadding(5f);
return cell;
}
private boolean isNumericValue(Object value) {
return value instanceof Number || value instanceof BigDecimal;
}
private String format(Object value, String key) {
if (value == null) {
return "";
}
if (value instanceof BigDecimal decimal) {
return format(decimal, key);
}
if (value instanceof Number number) {
return format(BigDecimal.valueOf(number.doubleValue()), key);
}
return String.valueOf(value);
}
private String format(BigDecimal value, String key) {
if (key.toLowerCase().contains("ratio")) {
return AMOUNT_FORMAT.format(value.multiply(BigDecimal.valueOf(100))) + "%";
}
return AMOUNT_FORMAT.format(value);
}
private String label(String key) {
return LABELS.getOrDefault(key, key);
}
private String generatedAt() {
return ZonedDateTime.now(ZoneId.of("Asia/Seoul")).format(REPORT_TIME_FORMAT);
}
private static Map<String, String> buildLabels() {
Map<String, String> labels = new LinkedHashMap<>();
labels.put("acceptedTrialRows", "Accepted Trial Rows");
labels.put("acceptedForecastRows", "Accepted Forecast Rows");
labels.put("grossContributionKrw", "Gross Contribution (KRW)");
labels.put("eliminationKrw", "Elimination (KRW)");
labels.put("forecastKrw", "Forecast (KRW)");
labels.put("netContributionKrw", "Net Contribution (KRW)");
labels.put("entityCode", "Entity Code");
labels.put("accountCode", "Account Code");
labels.put("partnerEntityCode", "Partner Entity");
labels.put("translatedAmount", "Translated Amount");
labels.put("ownershipRatio", "Ownership Ratio");
labels.put("finalAmount", "Final Amount");
labels.put("internalTrade", "Internal Trade");
labels.put("eliminationAmount", "Elimination Amount");
labels.put("note", "Note");
labels.put("scenarioCode", "Scenario");
return labels;
} }
} }

View File

@ -6,7 +6,12 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hanwha.nexacrodemo.upload.TestWorkbookFactory; import com.hanwha.nexacrodemo.upload.TestWorkbookFactory;
import java.io.ByteArrayInputStream;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
@ -29,6 +34,9 @@ class ConsolidationIntegrationTest {
@Autowired @Autowired
private ConsolidationService consolidationService; private ConsolidationService consolidationService;
@Autowired
private ObjectMapper objectMapper;
@Test @Test
void validUploadsCanBeConsolidatedAndReported() throws Exception { void validUploadsCanBeConsolidatedAndReported() throws Exception {
MockHttpSession session = login("operator", "demo1234"); MockHttpSession session = login("operator", "demo1234");
@ -55,10 +63,33 @@ class ConsolidationIntegrationTest {
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$.datasets.runs[0].statusCode").value("SUCCESS")); .andExpect(jsonPath("$.datasets.runs[0].statusCode").value("SUCCESS"));
mockMvc.perform(get("/api/tx/reports/overview").session(session)) MvcResult overviewResult = mockMvc.perform(get("/api/tx/reports/overview").session(session))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$.datasets.artifacts.length()").value(2)) .andExpect(jsonPath("$.datasets.artifacts.length()").value(2))
.andExpect(jsonPath("$.datasets.jobLogs[0].logLevel").exists()); .andExpect(jsonPath("$.datasets.jobLogs[0].logLevel").exists())
.andReturn();
JsonNode artifacts = objectMapper.readTree(overviewResult.getResponse().getContentAsByteArray())
.path("datasets")
.path("artifacts");
long excelArtifactId = -1L;
for (JsonNode artifact : artifacts) {
if ("EXCEL".equals(artifact.path("artifactType").asText())) {
excelArtifactId = artifact.path("id").asLong();
break;
}
}
Assertions.assertTrue(excelArtifactId > 0, "EXCEL artifact should exist");
MvcResult excelDownload = mockMvc.perform(get("/api/reports/{artifactId}/download", excelArtifactId).session(session))
.andExpect(status().isOk())
.andReturn();
try (var workbook = WorkbookFactory.create(new ByteArrayInputStream(excelDownload.getResponse().getContentAsByteArray()))) {
Assertions.assertEquals("Hanwha Consolidation Summary", workbook.getSheet("Summary").getRow(0).getCell(0).getStringCellValue());
Assertions.assertEquals("Entity Code", workbook.getSheet("Contributions").getRow(3).getCell(0).getStringCellValue());
Assertions.assertNotNull(workbook.getSheet("Forecast"));
}
} }
private void upload(MockHttpSession session, String templateCode, String fileName, byte[] content) throws Exception { private void upload(MockHttpSession session, String templateCode, String fileName, byte[] content) throws Exception {