mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 05:01:07 +00:00
Add static data provider capability to reports
This commit is contained in:
@ -73,7 +73,7 @@ public class CsvExportStreamer implements ExportStreamerInterface
|
||||
table = exportInput.getTable();
|
||||
outputStream = this.exportInput.getReportOutputStream();
|
||||
|
||||
writeReportHeaderRow();
|
||||
writeTitleAndHeader();
|
||||
}
|
||||
|
||||
|
||||
@ -81,7 +81,7 @@ public class CsvExportStreamer implements ExportStreamerInterface
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void writeReportHeaderRow() throws QReportingException
|
||||
private void writeTitleAndHeader() throws QReportingException
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -90,16 +90,20 @@ public class CsvExportStreamer implements ExportStreamerInterface
|
||||
outputStream.write((exportInput.getTitleRow() + "\n").getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
int col = 0;
|
||||
for(QFieldMetaData column : fields)
|
||||
if(exportInput.getIncludeHeaderRow())
|
||||
{
|
||||
if(col++ > 0)
|
||||
int col = 0;
|
||||
for(QFieldMetaData column : fields)
|
||||
{
|
||||
outputStream.write(',');
|
||||
if(col++ > 0)
|
||||
{
|
||||
outputStream.write(',');
|
||||
}
|
||||
outputStream.write(('"' + column.getLabel() + '"').getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
outputStream.write(('"' + column.getLabel() + '"').getBytes(StandardCharsets.UTF_8));
|
||||
outputStream.write('\n');
|
||||
}
|
||||
outputStream.write('\n');
|
||||
|
||||
outputStream.flush();
|
||||
}
|
||||
catch(Exception e)
|
||||
|
@ -130,7 +130,7 @@ public class ExcelExportStreamer implements ExportStreamerInterface
|
||||
|
||||
worksheet = workbook.newWorksheet(Objects.requireNonNullElse(label, "Sheet " + sheetCount));
|
||||
|
||||
writeReportHeaderRow();
|
||||
writeTitleAndHeader();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
@ -143,7 +143,7 @@ public class ExcelExportStreamer implements ExportStreamerInterface
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void writeReportHeaderRow() throws QReportingException
|
||||
private void writeTitleAndHeader() throws QReportingException
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -160,25 +160,28 @@ public class ExcelExportStreamer implements ExportStreamerInterface
|
||||
titleStyle.set();
|
||||
|
||||
row++;
|
||||
worksheet.flush();
|
||||
}
|
||||
|
||||
////////////////
|
||||
// header row //
|
||||
////////////////
|
||||
int col = 0;
|
||||
for(QFieldMetaData column : fields)
|
||||
if(exportInput.getIncludeHeaderRow())
|
||||
{
|
||||
worksheet.value(row, col, column.getLabel());
|
||||
col++;
|
||||
int col = 0;
|
||||
for(QFieldMetaData column : fields)
|
||||
{
|
||||
worksheet.value(row, col, column.getLabel());
|
||||
col++;
|
||||
}
|
||||
|
||||
StyleSetter headerStyle = worksheet.range(row, 0, row, fields.size() - 1).style();
|
||||
excelStylerInterface.styleHeaderRow(headerStyle);
|
||||
headerStyle.set();
|
||||
|
||||
row++;
|
||||
worksheet.flush();
|
||||
}
|
||||
|
||||
StyleSetter headerStyle = worksheet.range(row, 0, row, fields.size() - 1).style();
|
||||
excelStylerInterface.styleHeaderRow(headerStyle);
|
||||
headerStyle.set();
|
||||
|
||||
row++;
|
||||
|
||||
worksheet.flush();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
|
@ -30,6 +30,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import com.kingsrook.qqq.backend.core.actions.async.AsyncRecordPipeLoop;
|
||||
import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader;
|
||||
@ -180,10 +181,15 @@ public class GenerateReportAction
|
||||
{
|
||||
QTableMetaData table = reportInput.getInstance().getTable(dataSource.getSourceTable());
|
||||
|
||||
QMetaDataVariableInterpreter variableInterpreter = new QMetaDataVariableInterpreter();
|
||||
variableInterpreter.addValueMap("input", reportInput.getInputValues());
|
||||
|
||||
ExportInput exportInput = new ExportInput(reportInput.getInstance());
|
||||
exportInput.setSession(reportInput.getSession());
|
||||
exportInput.setReportFormat(reportFormat);
|
||||
exportInput.setFilename(reportInput.getFilename());
|
||||
exportInput.setTitleRow(getTitle(reportView, variableInterpreter));
|
||||
exportInput.setIncludeHeaderRow(reportView.getHeaderRow());
|
||||
exportInput.setReportOutputStream(reportInput.getReportOutputStream());
|
||||
|
||||
List<QFieldMetaData> fields;
|
||||
@ -222,9 +228,6 @@ public class GenerateReportAction
|
||||
*******************************************************************************/
|
||||
private void gatherData(ReportInput reportInput, QReportDataSource dataSource, QReportView tableView, List<QReportView> pivotViews, List<QReportView> variantViews) throws QException
|
||||
{
|
||||
QQueryFilter queryFilter = dataSource.getQueryFilter().clone();
|
||||
setInputValuesInQueryFilter(reportInput, queryFilter);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// check if this view has a transform step - if so, set it up now and run its pre-run //
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -257,13 +260,40 @@ public class GenerateReportAction
|
||||
RecordPipe recordPipe = new RecordPipe();
|
||||
new AsyncRecordPipeLoop().run("Report[" + reportInput.getReportName() + "]", null, recordPipe, (callback) ->
|
||||
{
|
||||
QueryInput queryInput = new QueryInput(reportInput.getInstance());
|
||||
queryInput.setSession(reportInput.getSession());
|
||||
queryInput.setRecordPipe(recordPipe);
|
||||
queryInput.setTableName(dataSource.getSourceTable());
|
||||
queryInput.setFilter(queryFilter);
|
||||
queryInput.setShouldTranslatePossibleValues(true); // todo - any limits or conditions on this?
|
||||
return (new QueryAction().execute(queryInput));
|
||||
if(dataSource.getSourceTable() != null)
|
||||
{
|
||||
QQueryFilter queryFilter = dataSource.getQueryFilter().clone();
|
||||
setInputValuesInQueryFilter(reportInput, queryFilter);
|
||||
|
||||
QueryInput queryInput = new QueryInput(reportInput.getInstance());
|
||||
queryInput.setSession(reportInput.getSession());
|
||||
queryInput.setRecordPipe(recordPipe);
|
||||
queryInput.setTableName(dataSource.getSourceTable());
|
||||
queryInput.setFilter(queryFilter);
|
||||
queryInput.setShouldTranslatePossibleValues(true); // todo - any limits or conditions on this?
|
||||
return (new QueryAction().execute(queryInput));
|
||||
}
|
||||
else if(dataSource.getStaticDataSupplier() != null)
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
Supplier<List<List<Serializable>>> supplier = QCodeLoader.getAdHoc(Supplier.class, dataSource.getStaticDataSupplier());
|
||||
List<List<Serializable>> lists = supplier.get();
|
||||
for(List<Serializable> list : lists)
|
||||
{
|
||||
QRecord record = new QRecord();
|
||||
int index = 0;
|
||||
for(Serializable value : list)
|
||||
{
|
||||
record.setValue("column" + (index++), value);
|
||||
}
|
||||
recordPipe.addRecord(record);
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw (new IllegalStateException("Misconfigured data source [" + dataSource.getName() + "]."));
|
||||
}
|
||||
}, () ->
|
||||
{
|
||||
List<QRecord> records = recordPipe.consumeAvailableRecords();
|
||||
@ -465,6 +495,7 @@ public class GenerateReportAction
|
||||
exportInput.setReportFormat(reportFormat);
|
||||
exportInput.setFilename(reportInput.getFilename());
|
||||
exportInput.setTitleRow(pivotOutput.titleRow);
|
||||
exportInput.setIncludeHeaderRow(view.getHeaderRow());
|
||||
exportInput.setReportOutputStream(reportInput.getReportOutputStream());
|
||||
|
||||
reportStreamer.setDisplayFormats(getDisplayFormatMap(view));
|
||||
@ -540,26 +571,7 @@ public class GenerateReportAction
|
||||
///////////
|
||||
// title //
|
||||
///////////
|
||||
String title = null;
|
||||
if(view.getTitleFields() != null && StringUtils.hasContent(view.getTitleFormat()))
|
||||
{
|
||||
List<String> titleValues = new ArrayList<>();
|
||||
for(String titleField : view.getTitleFields())
|
||||
{
|
||||
titleValues.add(variableInterpreter.interpret(titleField));
|
||||
}
|
||||
|
||||
title = valueFormatter.formatStringWithValues(view.getTitleFormat(), titleValues);
|
||||
}
|
||||
else if(StringUtils.hasContent(view.getTitleFormat()))
|
||||
{
|
||||
title = view.getTitleFormat();
|
||||
}
|
||||
|
||||
if(StringUtils.hasContent(title))
|
||||
{
|
||||
System.out.println(title);
|
||||
}
|
||||
String title = getTitle(view, variableInterpreter);
|
||||
|
||||
/////////////
|
||||
// headers //
|
||||
@ -701,6 +713,36 @@ public class GenerateReportAction
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private String getTitle(QReportView view, QMetaDataVariableInterpreter variableInterpreter)
|
||||
{
|
||||
String title = null;
|
||||
if(view.getTitleFields() != null && StringUtils.hasContent(view.getTitleFormat()))
|
||||
{
|
||||
List<String> titleValues = new ArrayList<>();
|
||||
for(String titleField : view.getTitleFields())
|
||||
{
|
||||
titleValues.add(variableInterpreter.interpret(titleField));
|
||||
}
|
||||
|
||||
title = new QValueFormatter().formatStringWithValues(view.getTitleFormat(), titleValues);
|
||||
}
|
||||
else if(StringUtils.hasContent(view.getTitleFormat()))
|
||||
{
|
||||
title = view.getTitleFormat();
|
||||
}
|
||||
|
||||
if(StringUtils.hasContent(title))
|
||||
{
|
||||
System.out.println(title);
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
@ -96,10 +96,14 @@ public class ListOfMapsExportStreamer implements ExportStreamerInterface
|
||||
currentSheetLabel = label;
|
||||
|
||||
rows.put(label, new ArrayList<>());
|
||||
headers.put(label, new ArrayList<>());
|
||||
for(QFieldMetaData field : fields)
|
||||
|
||||
if(exportInput.getIncludeHeaderRow())
|
||||
{
|
||||
headers.get(label).add(field.getLabel());
|
||||
headers.put(label, new ArrayList<>());
|
||||
for(QFieldMetaData field : fields)
|
||||
{
|
||||
headers.get(label).add(field.getLabel());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@ public class ExportInput extends AbstractTableActionInput
|
||||
private ReportFormat reportFormat;
|
||||
private OutputStream reportOutputStream;
|
||||
private String titleRow;
|
||||
private boolean includeHeaderRow = true;
|
||||
|
||||
|
||||
|
||||
@ -225,4 +226,27 @@ public class ExportInput extends AbstractTableActionInput
|
||||
{
|
||||
this.titleRow = titleRow;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for includeHeaderRow
|
||||
**
|
||||
*******************************************************************************/
|
||||
public boolean getIncludeHeaderRow()
|
||||
{
|
||||
return includeHeaderRow;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for includeHeaderRow
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setIncludeHeaderRow(boolean includeHeaderRow)
|
||||
{
|
||||
this.includeHeaderRow = includeHeaderRow;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,5 +31,6 @@ public enum QCodeUsage
|
||||
BACKEND_STEP, // a backend-step in a process
|
||||
CUSTOMIZER, // a function to customize part of a QQQ table's behavior
|
||||
POSSIBLE_VALUE_PROVIDER, // code that drives a custom possibleValueSource
|
||||
RECORD_AUTOMATION_HANDLER // code that executes record automations
|
||||
RECORD_AUTOMATION_HANDLER, // code that executes record automations
|
||||
REPORT_STATIC_DATA_SUPPLIER // code that supplies static data to a report
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ package com.kingsrook.qqq.backend.core.model.metadata.reporting;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -34,6 +35,8 @@ public class QReportDataSource
|
||||
private String sourceTable;
|
||||
private QQueryFilter queryFilter;
|
||||
|
||||
private QCodeReference staticDataSupplier;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -136,4 +139,38 @@ public class QReportDataSource
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for staticDataSupplier
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QCodeReference getStaticDataSupplier()
|
||||
{
|
||||
return staticDataSupplier;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for staticDataSupplier
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setStaticDataSupplier(QCodeReference staticDataSupplier)
|
||||
{
|
||||
this.staticDataSupplier = staticDataSupplier;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for staticDataSupplier
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QReportDataSource withStaticDataSupplier(QCodeReference staticDataSupplier)
|
||||
{
|
||||
this.staticDataSupplier = staticDataSupplier;
|
||||
return (this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ public class QReportView implements Cloneable
|
||||
private String titleFormat;
|
||||
private List<String> titleFields;
|
||||
private List<String> pivotFields;
|
||||
private boolean headerRow = true;
|
||||
private boolean totalRow = false;
|
||||
private boolean pivotSubTotals = false;
|
||||
private List<QReportField> columns;
|
||||
@ -327,6 +328,40 @@ public class QReportView implements Cloneable
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for headerRow
|
||||
**
|
||||
*******************************************************************************/
|
||||
public boolean getHeaderRow()
|
||||
{
|
||||
return headerRow;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for headerRow
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setHeaderRow(boolean headerRow)
|
||||
{
|
||||
this.headerRow = headerRow;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for headerRow
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QReportView withHeaderRow(boolean headerRow)
|
||||
{
|
||||
this.headerRow = headerRow;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for totalRow
|
||||
**
|
||||
|
Reference in New Issue
Block a user