CE-881 - Refactoring exports & reports

- add some fields together into ReportDestination class
- pass more data into export streamers (views) and add preRun method
- Add queryHint POTENTIALLY_LARGE_NUMBER_OF_RESULTS
- add pivot views
- optionally take in full ReportMetaData object instead of a name (e.g., for a user-defined/saved report)
This commit is contained in:
2024-03-27 19:50:06 -05:00
parent 05f31d0722
commit e078015732
17 changed files with 421 additions and 165 deletions

View File

@ -31,6 +31,7 @@ import com.kingsrook.qqq.backend.core.logging.QLogger;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput;
import com.kingsrook.qqq.backend.core.model.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportView;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.utils.StringUtils;
@ -65,12 +66,12 @@ public class CsvExportStreamer implements ExportStreamerInterface
**
*******************************************************************************/
@Override
public void start(ExportInput exportInput, List<QFieldMetaData> fields, String label) throws QReportingException
public void start(ExportInput exportInput, List<QFieldMetaData> fields, String label, QReportView view) throws QReportingException
{
this.exportInput = exportInput;
this.fields = fields;
table = exportInput.getTable();
outputStream = this.exportInput.getReportOutputStream();
outputStream = this.exportInput.getReportDestination().getReportOutputStream();
writeTitleAndHeader();
}

View File

@ -52,6 +52,7 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin;
import com.kingsrook.qqq.backend.core.model.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportView;
import com.kingsrook.qqq.backend.core.model.metadata.tables.ExposedJoin;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleDispatcher;
@ -138,7 +139,7 @@ public class ExportAction
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// check if this report format has a max-rows limit -- if so, do a count to verify we're under the limit //
///////////////////////////////////////////////////////////////////////////////////////////////////////////
ReportFormat reportFormat = exportInput.getReportFormat();
ReportFormat reportFormat = exportInput.getReportDestination().getReportFormat();
verifyCountUnderMax(exportInput, backendModule, reportFormat);
preExecuteRan = true;
@ -232,6 +233,7 @@ public class ExportAction
}
queryInput.getFilter().setLimit(exportInput.getLimit());
queryInput.setShouldTranslatePossibleValues(true);
queryInput.withQueryHint(QueryInput.QueryHint.POTENTIALLY_LARGE_NUMBER_OF_RESULTS);
/////////////////////////////////////////////////////////////////
// tell this query that it needs to put its output into a pipe //
@ -242,10 +244,19 @@ public class ExportAction
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// set up a report streamer, which will read rows from the pipe, and write formatted report rows to the output stream //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ReportFormat reportFormat = exportInput.getReportFormat();
ReportFormat reportFormat = exportInput.getReportDestination().getReportFormat();
ExportStreamerInterface reportStreamer = reportFormat.newReportStreamer();
List<QFieldMetaData> fields = getFields(exportInput);
reportStreamer.start(exportInput, fields, "Sheet 1");
//////////////////////////////////////////////////////////
// it seems we can pass a view with just a name in here //
//////////////////////////////////////////////////////////
List<QReportView> views = new ArrayList<>();
views.add(new QReportView()
.withName("export"));
reportStreamer.preRun(exportInput.getReportDestination(), views);
reportStreamer.start(exportInput, fields, "Sheet 1", views.get(0));
//////////////////////////////////////////
// run the query action as an async job //
@ -334,7 +345,7 @@ public class ExportAction
try
{
exportInput.getReportOutputStream().close();
exportInput.getReportDestination().getReportOutputStream().close();
}
catch(Exception e)
{

View File

@ -26,8 +26,10 @@ import java.util.List;
import java.util.Map;
import com.kingsrook.qqq.backend.core.exceptions.QReportingException;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportDestination;
import com.kingsrook.qqq.backend.core.model.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportView;
/*******************************************************************************
@ -35,20 +37,14 @@ import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
*******************************************************************************/
public interface ExportStreamerInterface
{
/*******************************************************************************
** Called once, before any rows are available. Meant to write a header, for example.
*******************************************************************************/
void start(ExportInput exportInput, List<QFieldMetaData> fields, String label) throws QReportingException;
/*******************************************************************************
** Called as records flow into the pipe.
******************************************************************************/
void addRecords(List<QRecord> recordList) throws QReportingException;
/*******************************************************************************
** Called once, after all rows are available. Meant to write a footer, or close resources, for example.
** Called once, before any sheets are actually being produced.
*******************************************************************************/
void finish() throws QReportingException;
default void preRun(ReportDestination reportDestination, List<QReportView> views) throws QReportingException
{
// noop in base class
}
/*******************************************************************************
**
@ -58,6 +54,20 @@ public interface ExportStreamerInterface
// noop in base class
}
/*******************************************************************************
** Called once per sheet, before any rows are available. Meant to write a
** header, for example.
**
** If multiple sheets are being created, there is no separate end-sheet call.
** Rather, a new one will just get started...
*******************************************************************************/
void start(ExportInput exportInput, List<QFieldMetaData> fields, String label, QReportView view) throws QReportingException;
/*******************************************************************************
** Called as records flow into the pipe.
******************************************************************************/
void addRecords(List<QRecord> recordList) throws QReportingException;
/*******************************************************************************
**
*******************************************************************************/
@ -65,4 +75,11 @@ public interface ExportStreamerInterface
{
addRecords(List.of(record));
}
/*******************************************************************************
** Called after all sheets are complete. Meant to do a final write, or close
** resources, for example.
*******************************************************************************/
void finish() throws QReportingException;
}

View File

@ -41,6 +41,7 @@ import com.kingsrook.qqq.backend.core.actions.reporting.customizers.DataSourceQu
import com.kingsrook.qqq.backend.core.actions.reporting.customizers.ReportViewCustomizer;
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
import com.kingsrook.qqq.backend.core.actions.values.QValueFormatter;
import com.kingsrook.qqq.backend.core.context.QContext;
import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.exceptions.QFormulaException;
import com.kingsrook.qqq.backend.core.exceptions.QReportingException;
@ -108,9 +109,9 @@ public class GenerateReportAction
Map<String, AggregatesInterface<?>> totalAggregates = new HashMap<>();
Map<String, AggregatesInterface<?>> varianceTotalAggregates = new HashMap<>();
private QReportMetaData report;
private ReportFormat reportFormat;
private ExportStreamerInterface reportStreamer;
private List<QReportDataSource> dataSources;
private List<QReportView> views;
@ -119,33 +120,39 @@ public class GenerateReportAction
*******************************************************************************/
public void execute(ReportInput reportInput) throws QException
{
report = reportInput.getInstance().getReport(reportInput.getReportName());
reportFormat = reportInput.getReportFormat();
QReportMetaData report = getReportMetaData(reportInput);
this.views = report.getViews();
this.dataSources = report.getDataSources();
ReportFormat reportFormat = reportInput.getReportDestination().getReportFormat();
if(reportFormat == null)
{
throw new QException("Report format was not specified.");
}
reportStreamer = reportFormat.newReportStreamer();
reportStreamer.preRun(reportInput.getReportDestination(), views);
////////////////////////////////////////////////////////////////////////////////////////////////
// foreach data source, do a query (possibly more than 1, if it goes to multiple table views) //
////////////////////////////////////////////////////////////////////////////////////////////////
for(QReportDataSource dataSource : report.getDataSources())
for(QReportDataSource dataSource : dataSources)
{
//////////////////////////////////////////////////////////////////////////////
// make a list of the views that use this data source for various purposes. //
//////////////////////////////////////////////////////////////////////////////
List<QReportView> dataSourceTableViews = report.getViews().stream()
List<QReportView> dataSourceTableViews = views.stream()
.filter(v -> v.getType().equals(ReportType.TABLE))
.filter(v -> v.getDataSourceName().equals(dataSource.getName()))
.toList();
List<QReportView> dataSourceSummaryViews = report.getViews().stream()
List<QReportView> dataSourceSummaryViews = views.stream()
.filter(v -> v.getType().equals(ReportType.SUMMARY))
.filter(v -> v.getDataSourceName().equals(dataSource.getName()))
.toList();
List<QReportView> dataSourceVariantViews = report.getViews().stream()
List<QReportView> dataSourceVariantViews = views.stream()
.filter(v -> v.getType().equals(ReportType.SUMMARY))
.filter(v -> v.getVarianceDataSourceName() != null && v.getVarianceDataSourceName().equals(dataSource.getName()))
.toList();
@ -190,13 +197,29 @@ public class GenerateReportAction
}
}
////////////////////////////////////////
// add pivot sheets //
// todo - but, only for Excel, right? //
////////////////////////////////////////
for(QReportView view : views)
{
if(view.getType().equals(ReportType.PIVOT))
{
startTableView(reportInput, null, view);
//////////////////////////////////////////////////////////////////////////
// there's no data to add to a pivot table, so nothing else to do here. //
//////////////////////////////////////////////////////////////////////////
}
}
outputSummaries(reportInput);
reportStreamer.finish();
try
{
reportInput.getReportOutputStream().close();
reportInput.getReportDestination().getReportOutputStream().close();
}
catch(Exception e)
{
@ -206,31 +229,50 @@ public class GenerateReportAction
/*******************************************************************************
**
*******************************************************************************/
private QReportMetaData getReportMetaData(ReportInput reportInput) throws QException
{
if(reportInput.getReportMetaData() != null)
{
return reportInput.getReportMetaData();
}
if(StringUtils.hasContent(reportInput.getReportName()))
{
return QContext.getQInstance().getReport(reportInput.getReportName());
}
throw (new QReportingException("ReportInput did not contain required parameters to identify the report being generated"));
}
/*******************************************************************************
**
*******************************************************************************/
private void startTableView(ReportInput reportInput, QReportDataSource dataSource, QReportView reportView) throws QException
{
QTableMetaData table = reportInput.getInstance().getTable(dataSource.getSourceTable());
QMetaDataVariableInterpreter variableInterpreter = new QMetaDataVariableInterpreter();
variableInterpreter.addValueMap("input", reportInput.getInputValues());
ExportInput exportInput = new ExportInput();
exportInput.setReportFormat(reportFormat);
exportInput.setFilename(reportInput.getFilename());
exportInput.setReportDestination(reportInput.getReportDestination());
exportInput.setTitleRow(getTitle(reportView, variableInterpreter));
exportInput.setIncludeHeaderRow(reportView.getIncludeHeaderRow());
exportInput.setReportOutputStream(reportInput.getReportOutputStream());
JoinsContext joinsContext = null;
if(StringUtils.hasContent(dataSource.getSourceTable()))
if(dataSource != null)
{
joinsContext = new JoinsContext(exportInput.getInstance(), dataSource.getSourceTable(), dataSource.getQueryJoins(), dataSource.getQueryFilter());
if(StringUtils.hasContent(dataSource.getSourceTable()))
{
joinsContext = new JoinsContext(exportInput.getInstance(), dataSource.getSourceTable(), dataSource.getQueryJoins(), dataSource.getQueryFilter());
}
}
List<QFieldMetaData> fields = new ArrayList<>();
for(QReportField column : reportView.getColumns())
for(QReportField column : CollectionUtils.nonNullList(reportView.getColumns()))
{
if(column.getIsVirtual())
{
@ -256,7 +298,7 @@ public class GenerateReportAction
}
reportStreamer.setDisplayFormats(getDisplayFormatMap(fields));
reportStreamer.start(exportInput, fields, reportView.getLabel());
reportStreamer.start(exportInput, fields, reportView.getLabel(), reportView);
}
@ -307,6 +349,7 @@ public class GenerateReportAction
queryInput.setTableName(dataSource.getSourceTable());
queryInput.setFilter(queryFilter);
queryInput.setQueryJoins(dataSource.getQueryJoins());
queryInput.withQueryHint(QueryInput.QueryHint.POTENTIALLY_LARGE_NUMBER_OF_RESULTS);
queryInput.setShouldTranslatePossibleValues(true);
queryInput.setFieldsToTranslatePossibleValues(setupFieldsToTranslatePossibleValues(reportInput, dataSource, new JoinsContext(reportInput.getInstance(), dataSource.getSourceTable(), dataSource.getQueryJoins(), queryInput.getFilter())));
@ -371,7 +414,7 @@ public class GenerateReportAction
{
Set<String> fieldsToTranslatePossibleValues = new HashSet<>();
for(QReportView view : report.getViews())
for(QReportView view : views)
{
for(QReportField column : CollectionUtils.nonNullList(view.getColumns()))
{
@ -577,22 +620,20 @@ public class GenerateReportAction
*******************************************************************************/
private void outputSummaries(ReportInput reportInput) throws QReportingException, QFormulaException
{
List<QReportView> reportViews = report.getViews().stream().filter(v -> v.getType().equals(ReportType.SUMMARY)).toList();
List<QReportView> reportViews = views.stream().filter(v -> v.getType().equals(ReportType.SUMMARY)).toList();
for(QReportView view : reportViews)
{
QReportDataSource dataSource = report.getDataSource(view.getDataSourceName());
QReportDataSource dataSource = getDataSource(view.getDataSourceName());
QTableMetaData table = reportInput.getInstance().getTable(dataSource.getSourceTable());
SummaryOutput summaryOutput = computeSummaryRowsForView(reportInput, view, table);
ExportInput exportInput = new ExportInput();
exportInput.setReportFormat(reportFormat);
exportInput.setFilename(reportInput.getFilename());
exportInput.setReportDestination(reportInput.getReportDestination());
exportInput.setTitleRow(summaryOutput.titleRow);
exportInput.setIncludeHeaderRow(view.getIncludeHeaderRow());
exportInput.setReportOutputStream(reportInput.getReportOutputStream());
reportStreamer.setDisplayFormats(getDisplayFormatMap(view));
reportStreamer.start(exportInput, getFields(table, view), view.getLabel());
reportStreamer.start(exportInput, getFields(table, view), view.getLabel(), view);
reportStreamer.addRecords(summaryOutput.summaryRows); // todo - what if this set is huge?
@ -605,6 +646,24 @@ public class GenerateReportAction
/*******************************************************************************
**
*******************************************************************************/
private QReportDataSource getDataSource(String dataSourceName)
{
for(QReportDataSource dataSource : CollectionUtils.nonNullList(dataSources))
{
if(dataSource.getName().equals(dataSourceName))
{
return (dataSource);
}
}
return (null);
}
/*******************************************************************************
**
*******************************************************************************/

View File

@ -34,6 +34,7 @@ import com.kingsrook.qqq.backend.core.logging.QLogger;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput;
import com.kingsrook.qqq.backend.core.model.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportView;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
import com.kingsrook.qqq.backend.core.utils.StringUtils;
@ -69,12 +70,12 @@ public class JsonExportStreamer implements ExportStreamerInterface
**
*******************************************************************************/
@Override
public void start(ExportInput exportInput, List<QFieldMetaData> fields, String label) throws QReportingException
public void start(ExportInput exportInput, List<QFieldMetaData> fields, String label, QReportView view) throws QReportingException
{
this.exportInput = exportInput;
this.fields = fields;
table = exportInput.getTable();
outputStream = this.exportInput.getReportOutputStream();
outputStream = this.exportInput.getReportDestination().getReportOutputStream();
try
{

View File

@ -31,6 +31,7 @@ import com.kingsrook.qqq.backend.core.logging.QLogger;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ExportInput;
import com.kingsrook.qqq.backend.core.model.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportView;
/*******************************************************************************
@ -87,7 +88,7 @@ public class ListOfMapsExportStreamer implements ExportStreamerInterface
**
*******************************************************************************/
@Override
public void start(ExportInput exportInput, List<QFieldMetaData> fields, String label) throws QReportingException
public void start(ExportInput exportInput, List<QFieldMetaData> fields, String label, QReportView view) throws QReportingException
{
this.exportInput = exportInput;
this.fields = fields;

View File

@ -0,0 +1,51 @@
/*
* QQQ - Low-code Application Framework for Engineers.
* Copyright (C) 2021-2024. Kingsrook, LLC
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
* contact@kingsrook.com
* https://github.com/Kingsrook/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.kingsrook.qqq.backend.core.actions.reporting;
import java.util.List;
import java.util.Optional;
import com.kingsrook.qqq.backend.core.exceptions.QReportingException;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportView;
/*******************************************************************************
**
*******************************************************************************/
public class ReportUtils
{
/*******************************************************************************
**
*******************************************************************************/
public static QReportView getSourceViewForPivotTableView(List<QReportView> views, QReportView pivotTableView) throws QReportingException
{
Optional<QReportView> sourceView = views.stream().filter(v -> v.getName().equals(pivotTableView.getPivotTableSourceViewName())).findFirst();
if(sourceView.isEmpty())
{
throw (new QReportingException("Could not find data view [" + pivotTableView.getPivotTableSourceViewName() + "] for pivot table view [" + pivotTableView.getName() + "]"));
}
return sourceView.get();
}
}

View File

@ -22,7 +22,6 @@
package com.kingsrook.qqq.backend.core.model.actions.reporting;
import java.io.OutputStream;
import java.util.List;
import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
@ -37,9 +36,8 @@ public class ExportInput extends AbstractTableActionInput
private Integer limit;
private List<String> fieldNames;
private String filename;
private ReportFormat reportFormat;
private OutputStream reportOutputStream;
private ReportDestination reportDestination;
private String titleRow;
private boolean includeHeaderRow = true;
@ -120,71 +118,6 @@ public class ExportInput extends AbstractTableActionInput
/*******************************************************************************
** Getter for filename
**
*******************************************************************************/
public String getFilename()
{
return filename;
}
/*******************************************************************************
** Setter for filename
**
*******************************************************************************/
public void setFilename(String filename)
{
this.filename = filename;
}
/*******************************************************************************
** Getter for reportFormat
**
*******************************************************************************/
public ReportFormat getReportFormat()
{
return reportFormat;
}
/*******************************************************************************
** Setter for reportFormat
**
*******************************************************************************/
public void setReportFormat(ReportFormat reportFormat)
{
this.reportFormat = reportFormat;
}
/*******************************************************************************
** Getter for reportOutputStream
**
*******************************************************************************/
public OutputStream getReportOutputStream()
{
return reportOutputStream;
}
/*******************************************************************************
** Setter for reportOutputStream
**
*******************************************************************************/
public void setReportOutputStream(OutputStream reportOutputStream)
{
this.reportOutputStream = reportOutputStream;
}
/*******************************************************************************
**
@ -226,4 +159,36 @@ public class ExportInput extends AbstractTableActionInput
this.includeHeaderRow = includeHeaderRow;
}
/*******************************************************************************
** Getter for reportDestination
*******************************************************************************/
public ReportDestination getReportDestination()
{
return (this.reportDestination);
}
/*******************************************************************************
** Setter for reportDestination
*******************************************************************************/
public void setReportDestination(ReportDestination reportDestination)
{
this.reportDestination = reportDestination;
}
/*******************************************************************************
** Fluent setter for reportDestination
*******************************************************************************/
public ExportInput withReportDestination(ReportDestination reportDestination)
{
this.reportDestination = reportDestination;
return (this);
}
}

View File

@ -0,0 +1,130 @@
/*
* QQQ - Low-code Application Framework for Engineers.
* Copyright (C) 2021-2024. Kingsrook, LLC
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
* contact@kingsrook.com
* https://github.com/Kingsrook/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.kingsrook.qqq.backend.core.model.actions.reporting;
import java.io.OutputStream;
/*******************************************************************************
**
*******************************************************************************/
public class ReportDestination
{
private String filename;
private ReportFormat reportFormat;
private OutputStream reportOutputStream;
/*******************************************************************************
** Getter for filename
*******************************************************************************/
public String getFilename()
{
return (this.filename);
}
/*******************************************************************************
** Setter for filename
*******************************************************************************/
public void setFilename(String filename)
{
this.filename = filename;
}
/*******************************************************************************
** Fluent setter for filename
*******************************************************************************/
public ReportDestination withFilename(String filename)
{
this.filename = filename;
return (this);
}
/*******************************************************************************
** Getter for reportFormat
*******************************************************************************/
public ReportFormat getReportFormat()
{
return (this.reportFormat);
}
/*******************************************************************************
** Setter for reportFormat
*******************************************************************************/
public void setReportFormat(ReportFormat reportFormat)
{
this.reportFormat = reportFormat;
}
/*******************************************************************************
** Fluent setter for reportFormat
*******************************************************************************/
public ReportDestination withReportFormat(ReportFormat reportFormat)
{
this.reportFormat = reportFormat;
return (this);
}
/*******************************************************************************
** Getter for reportOutputStream
*******************************************************************************/
public OutputStream getReportOutputStream()
{
return (this.reportOutputStream);
}
/*******************************************************************************
** Setter for reportOutputStream
*******************************************************************************/
public void setReportOutputStream(OutputStream reportOutputStream)
{
this.reportOutputStream = reportOutputStream;
}
/*******************************************************************************
** Fluent setter for reportOutputStream
*******************************************************************************/
public ReportDestination withReportOutputStream(OutputStream reportOutputStream)
{
this.reportOutputStream = reportOutputStream;
return (this);
}
}

View File

@ -25,10 +25,10 @@ package com.kingsrook.qqq.backend.core.model.actions.reporting;
import java.util.Locale;
import java.util.function.Supplier;
import com.kingsrook.qqq.backend.core.actions.reporting.CsvExportStreamer;
import com.kingsrook.qqq.backend.core.actions.reporting.ExcelExportStreamer;
import com.kingsrook.qqq.backend.core.actions.reporting.ExportStreamerInterface;
import com.kingsrook.qqq.backend.core.actions.reporting.JsonExportStreamer;
import com.kingsrook.qqq.backend.core.actions.reporting.ListOfMapsExportStreamer;
import com.kingsrook.qqq.backend.core.actions.reporting.excel.poi.ExcelPoiBasedStreamingExportStreamer;
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
import com.kingsrook.qqq.backend.core.utils.StringUtils;
import org.dhatim.fastexcel.Worksheet;
@ -39,7 +39,13 @@ import org.dhatim.fastexcel.Worksheet;
*******************************************************************************/
public enum ReportFormat
{
XLSX(Worksheet.MAX_ROWS, Worksheet.MAX_COLS, ExcelExportStreamer::new, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
XLSX(Worksheet.MAX_ROWS, Worksheet.MAX_COLS, ExcelPoiBasedStreamingExportStreamer::new, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
/////////////////////////////////////////////////////////////////////////
// if we need to fall back to Fastexcel, this was its version of this. //
/////////////////////////////////////////////////////////////////////////
// XLSX(Worksheet.MAX_ROWS, Worksheet.MAX_COLS, ExcelFastexcelExportStreamer::new, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
JSON(null, null, JsonExportStreamer::new, "application/json"),
CSV(null, null, CsvExportStreamer::new, "text/csv"),
LIST_OF_MAPS(null, null, ListOfMapsExportStreamer::new, null);

View File

@ -22,11 +22,11 @@
package com.kingsrook.qqq.backend.core.model.actions.reporting;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportMetaData;
/*******************************************************************************
@ -34,12 +34,12 @@ import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput;
*******************************************************************************/
public class ReportInput extends AbstractTableActionInput
{
private String reportName;
private String reportName;
private QReportMetaData reportMetaData;
private Map<String, Serializable> inputValues;
private String filename;
private ReportFormat reportFormat;
private OutputStream reportOutputStream;
private ReportDestination reportDestination;
@ -111,66 +111,63 @@ public class ReportInput extends AbstractTableActionInput
/*******************************************************************************
** Getter for filename
**
** Getter for reportDestination
*******************************************************************************/
public String getFilename()
public ReportDestination getReportDestination()
{
return filename;
return (this.reportDestination);
}
/*******************************************************************************
** Setter for filename
**
** Setter for reportDestination
*******************************************************************************/
public void setFilename(String filename)
public void setReportDestination(ReportDestination reportDestination)
{
this.filename = filename;
this.reportDestination = reportDestination;
}
/*******************************************************************************
** Getter for reportFormat
**
** Fluent setter for reportDestination
*******************************************************************************/
public ReportFormat getReportFormat()
public ReportInput withReportDestination(ReportDestination reportDestination)
{
return reportFormat;
this.reportDestination = reportDestination;
return (this);
}
/*******************************************************************************
** Getter for reportMetaData
*******************************************************************************/
public QReportMetaData getReportMetaData()
{
return (this.reportMetaData);
}
/*******************************************************************************
** Setter for reportFormat
**
** Setter for reportMetaData
*******************************************************************************/
public void setReportFormat(ReportFormat reportFormat)
public void setReportMetaData(QReportMetaData reportMetaData)
{
this.reportFormat = reportFormat;
this.reportMetaData = reportMetaData;
}
/*******************************************************************************
** Getter for reportOutputStream
**
** Fluent setter for reportMetaData
*******************************************************************************/
public OutputStream getReportOutputStream()
public ReportInput withReportMetaData(QReportMetaData reportMetaData)
{
return reportOutputStream;
this.reportMetaData = reportMetaData;
return (this);
}
/*******************************************************************************
** Setter for reportOutputStream
**
*******************************************************************************/
public void setReportOutputStream(OutputStream reportOutputStream)
{
this.reportOutputStream = reportOutputStream;
}
}

View File

@ -34,6 +34,7 @@ import com.kingsrook.qqq.backend.core.actions.reporting.GenerateReportAction;
import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportDestination;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportInput;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportMetaData;
@ -66,8 +67,9 @@ public class ExecuteReportStep implements BackendStep
{
ReportInput reportInput = new ReportInput();
reportInput.setReportName(reportName);
reportInput.setReportFormat(ReportFormat.XLSX); // todo - variable
reportInput.setReportOutputStream(reportOutputStream);
reportInput.setReportDestination(new ReportDestination()
.withReportFormat(ReportFormat.XLSX) // todo - variable
.withReportOutputStream(reportOutputStream));
Map<String, Serializable> values = runBackendStepInput.getValues();
reportInput.setInputValues(values);