mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
CE-881 - Update RenderSavedReport process to stream results to a backend through new StorageAction.
This commit is contained in:
@ -24,13 +24,21 @@ package com.kingsrook.qqq.backend.core.model.savedreports;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.DefaultWidgetRenderer;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormatPossibleValueEnum;
|
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormatPossibleValueEnum;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.AdornmentType;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.AdornmentType;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.FieldAdornment;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.FieldAdornment;
|
||||||
|
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.layout.QIcon;
|
import com.kingsrook.qqq.backend.core.model.metadata.layout.QIcon;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QFieldSection;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QFieldSection;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.Tier;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.Tier;
|
||||||
@ -42,17 +50,66 @@ import com.kingsrook.qqq.backend.core.processes.implementations.savedreports.Ren
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class SavedReportsMetaDataProvider
|
public class SavedReportsMetaDataProvider
|
||||||
{
|
{
|
||||||
|
public static final String REPORT_STORAGE_TABLE_NAME = "reportStorage";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public void defineAll(QInstance instance, String backendName, Consumer<QTableMetaData> backendDetailEnricher) throws QException
|
public void defineAll(QInstance instance, String recordTablesBackendName, String reportStorageBackendName, Consumer<QTableMetaData> backendDetailEnricher) throws QException
|
||||||
{
|
{
|
||||||
instance.addTable(defineSavedReportTable(backendName, backendDetailEnricher));
|
instance.addTable(defineSavedReportTable(recordTablesBackendName, backendDetailEnricher));
|
||||||
instance.addPossibleValueSource(QPossibleValueSource.newForTable(SavedReport.TABLE_NAME));
|
instance.addPossibleValueSource(QPossibleValueSource.newForTable(SavedReport.TABLE_NAME));
|
||||||
instance.addPossibleValueSource(QPossibleValueSource.newForEnum(ReportFormatPossibleValueEnum.NAME, ReportFormatPossibleValueEnum.values()));
|
instance.addPossibleValueSource(QPossibleValueSource.newForEnum(ReportFormatPossibleValueEnum.NAME, ReportFormatPossibleValueEnum.values()));
|
||||||
instance.addProcess(new RenderSavedReportMetaDataProducer().produce(instance));
|
|
||||||
|
instance.addTable(defineReportStorageTable(reportStorageBackendName, backendDetailEnricher));
|
||||||
|
|
||||||
|
QProcessMetaData renderSavedReportProcess = new RenderSavedReportMetaDataProducer().produce(instance);
|
||||||
|
instance.addProcess(renderSavedReportProcess);
|
||||||
|
renderSavedReportProcess.getInputFields().stream()
|
||||||
|
.filter(f -> RenderSavedReportMetaDataProducer.FIELD_NAME_STORAGE_TABLE_NAME.equals(f.getName()))
|
||||||
|
.findFirst()
|
||||||
|
.ifPresent(f -> f.setDefaultValue(REPORT_STORAGE_TABLE_NAME));
|
||||||
|
|
||||||
|
instance.addWidget(defineReportSetupWidget());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private QTableMetaData defineReportStorageTable(String backendName, Consumer<QTableMetaData> backendDetailEnricher)
|
||||||
|
{
|
||||||
|
QTableMetaData table = new QTableMetaData()
|
||||||
|
.withName(REPORT_STORAGE_TABLE_NAME)
|
||||||
|
.withBackendName(backendName)
|
||||||
|
.withPrimaryKeyField("reference")
|
||||||
|
.withField(new QFieldMetaData("reference", QFieldType.STRING))
|
||||||
|
.withField(new QFieldMetaData("contents", QFieldType.BLOB));
|
||||||
|
|
||||||
|
if(backendDetailEnricher != null)
|
||||||
|
{
|
||||||
|
backendDetailEnricher.accept(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (table);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private QWidgetMetaDataInterface defineReportSetupWidget()
|
||||||
|
{
|
||||||
|
return new QWidgetMetaData()
|
||||||
|
.withName("reportSetupWidget")
|
||||||
|
.withLabel("Report Setup")
|
||||||
|
.withIsCard(true)
|
||||||
|
.withType(WidgetType.REPORT_SETUP.getType())
|
||||||
|
.withCodeReference(new QCodeReference(DefaultWidgetRenderer.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -73,6 +130,7 @@ public class SavedReportsMetaDataProvider
|
|||||||
.withFieldsFromEntity(SavedReport.class)
|
.withFieldsFromEntity(SavedReport.class)
|
||||||
.withSection(new QFieldSection("identity", new QIcon().withName("badge"), Tier.T1, List.of("id", "label")))
|
.withSection(new QFieldSection("identity", new QIcon().withName("badge"), Tier.T1, List.of("id", "label")))
|
||||||
.withSection(new QFieldSection("settings", new QIcon().withName("settings"), Tier.T2, List.of("tableName")))
|
.withSection(new QFieldSection("settings", new QIcon().withName("settings"), Tier.T2, List.of("tableName")))
|
||||||
|
.withSection(new QFieldSection("reportSetup", new QIcon().withName("table_chart"), Tier.T2).withWidgetName("reportSetupWidget"))
|
||||||
.withSection(new QFieldSection("data", new QIcon().withName("text_snippet"), Tier.T2, List.of("queryFilterJson", "columnsJson", "pivotTableJson")))
|
.withSection(new QFieldSection("data", new QIcon().withName("text_snippet"), Tier.T2, List.of("queryFilterJson", "columnsJson", "pivotTableJson")))
|
||||||
.withSection(new QFieldSection("hidden", new QIcon().withName("text_snippet"), Tier.T2, List.of("inputFieldsJson", "userId")).withIsHidden(true))
|
.withSection(new QFieldSection("hidden", new QIcon().withName("text_snippet"), Tier.T2, List.of("inputFieldsJson", "userId")).withIsHidden(true))
|
||||||
.withSection(new QFieldSection("dates", new QIcon().withName("calendar_month"), Tier.T3, List.of("createDate", "modifyDate")));
|
.withSection(new QFieldSection("dates", new QIcon().withName("calendar_month"), Tier.T3, List.of("createDate", "modifyDate")));
|
||||||
|
@ -22,15 +22,16 @@
|
|||||||
package com.kingsrook.qqq.backend.core.processes.implementations.savedreports;
|
package com.kingsrook.qqq.backend.core.processes.implementations.savedreports;
|
||||||
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.OutputStream;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||||
import com.kingsrook.qqq.backend.core.actions.reporting.GenerateReportAction;
|
import com.kingsrook.qqq.backend.core.actions.reporting.GenerateReportAction;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.tables.StorageAction;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||||
@ -38,6 +39,7 @@ import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutp
|
|||||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportDestination;
|
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.ReportFormat;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportInput;
|
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.storage.StorageInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.savedreports.SavedReport;
|
import com.kingsrook.qqq.backend.core.model.savedreports.SavedReport;
|
||||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||||
@ -60,32 +62,33 @@ public class RenderSavedReportExecuteStep implements BackendStep
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ReportFormat reportFormat = ReportFormat.fromString(runBackendStepInput.getValueString("reportFormat"));
|
String storageTableName = runBackendStepInput.getValueString(RenderSavedReportMetaDataProducer.FIELD_NAME_STORAGE_TABLE_NAME);
|
||||||
|
ReportFormat reportFormat = ReportFormat.fromString(runBackendStepInput.getValueString(RenderSavedReportMetaDataProducer.FIELD_NAME_REPORT_FORMAT));
|
||||||
|
|
||||||
SavedReport savedReport = new SavedReport(runBackendStepInput.getRecords().get(0));
|
SavedReport savedReport = new SavedReport(runBackendStepInput.getRecords().get(0));
|
||||||
File tmpFile = File.createTempFile("SavedReport" + savedReport.getId(), "." + reportFormat.getExtension(), new File("/tmp/"));
|
String downloadFileBaseName = getDownloadFileBaseName(runBackendStepInput, savedReport);
|
||||||
|
String storageReference = UUID.randomUUID() + "/" + downloadFileBaseName + "." + reportFormat.getExtension();
|
||||||
|
|
||||||
|
OutputStream outputStream = new StorageAction().createOutputStream(new StorageInput(storageTableName).withReference(storageReference));
|
||||||
|
|
||||||
runBackendStepInput.getAsyncJobCallback().updateStatus("Generating Report");
|
runBackendStepInput.getAsyncJobCallback().updateStatus("Generating Report");
|
||||||
|
|
||||||
QReportMetaData reportMetaData = new SavedReportToReportMetaDataAdapter().adapt(savedReport, reportFormat);
|
QReportMetaData reportMetaData = new SavedReportToReportMetaDataAdapter().adapt(savedReport, reportFormat);
|
||||||
|
|
||||||
try(FileOutputStream reportOutputStream = new FileOutputStream(tmpFile))
|
|
||||||
{
|
|
||||||
ReportInput reportInput = new ReportInput();
|
ReportInput reportInput = new ReportInput();
|
||||||
reportInput.setReportMetaData(reportMetaData);
|
reportInput.setReportMetaData(reportMetaData);
|
||||||
reportInput.setReportDestination(new ReportDestination()
|
reportInput.setReportDestination(new ReportDestination()
|
||||||
.withReportFormat(reportFormat)
|
.withReportFormat(reportFormat)
|
||||||
.withReportOutputStream(reportOutputStream));
|
.withReportOutputStream(outputStream));
|
||||||
|
|
||||||
Map<String, Serializable> values = runBackendStepInput.getValues();
|
Map<String, Serializable> values = runBackendStepInput.getValues();
|
||||||
reportInput.setInputValues(values);
|
reportInput.setInputValues(values);
|
||||||
|
|
||||||
new GenerateReportAction().execute(reportInput);
|
new GenerateReportAction().execute(reportInput);
|
||||||
}
|
|
||||||
|
|
||||||
String downloadFileBaseName = getDownloadFileBaseName(runBackendStepInput, savedReport);
|
|
||||||
runBackendStepOutput.addValue("downloadFileName", downloadFileBaseName + "." + reportFormat.getExtension());
|
runBackendStepOutput.addValue("downloadFileName", downloadFileBaseName + "." + reportFormat.getExtension());
|
||||||
runBackendStepOutput.addValue("serverFilePath", tmpFile.getCanonicalPath());
|
runBackendStepOutput.addValue("storageTableName", storageTableName);
|
||||||
|
runBackendStepOutput.addValue("storageReference", storageReference);
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
|
@ -47,6 +47,9 @@ public class RenderSavedReportMetaDataProducer implements MetaDataProducerInterf
|
|||||||
{
|
{
|
||||||
public static final String NAME = "renderSavedReport";
|
public static final String NAME = "renderSavedReport";
|
||||||
|
|
||||||
|
public static final String FIELD_NAME_STORAGE_TABLE_NAME = "storageTableName";
|
||||||
|
public static final String FIELD_NAME_REPORT_FORMAT = "reportFormat";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -61,13 +64,14 @@ public class RenderSavedReportMetaDataProducer implements MetaDataProducerInterf
|
|||||||
.withIcon(new QIcon().withName("print"))
|
.withIcon(new QIcon().withName("print"))
|
||||||
.addStep(new QBackendStepMetaData()
|
.addStep(new QBackendStepMetaData()
|
||||||
.withName("pre")
|
.withName("pre")
|
||||||
.withInputData(new QFunctionInputMetaData().withRecordListMetaData(new QRecordListMetaData()
|
.withInputData(new QFunctionInputMetaData()
|
||||||
.withTableName(SavedReport.TABLE_NAME)))
|
.withField(new QFieldMetaData(FIELD_NAME_STORAGE_TABLE_NAME, QFieldType.STRING))
|
||||||
|
.withRecordListMetaData(new QRecordListMetaData().withTableName(SavedReport.TABLE_NAME)))
|
||||||
.withCode(new QCodeReference(RenderSavedReportPreStep.class)))
|
.withCode(new QCodeReference(RenderSavedReportPreStep.class)))
|
||||||
.addStep(new QFrontendStepMetaData()
|
.addStep(new QFrontendStepMetaData()
|
||||||
.withName("input")
|
.withName("input")
|
||||||
.withComponent(new QFrontendComponentMetaData().withType(QComponentType.EDIT_FORM))
|
.withComponent(new QFrontendComponentMetaData().withType(QComponentType.EDIT_FORM))
|
||||||
.withFormField(new QFieldMetaData("reportFormat", QFieldType.STRING)
|
.withFormField(new QFieldMetaData(FIELD_NAME_REPORT_FORMAT, QFieldType.STRING)
|
||||||
.withPossibleValueSourceName(ReportFormatPossibleValueEnum.NAME)
|
.withPossibleValueSourceName(ReportFormatPossibleValueEnum.NAME)
|
||||||
.withIsRequired(true)))
|
.withIsRequired(true)))
|
||||||
.addStep(new QBackendStepMetaData()
|
.addStep(new QBackendStepMetaData()
|
||||||
|
@ -22,10 +22,17 @@
|
|||||||
package com.kingsrook.qqq.backend.core.processes.implementations.savedreports;
|
package com.kingsrook.qqq.backend.core.processes.implementations.savedreports;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||||
|
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
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.processes.RunBackendStepOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.savedreports.SavedReport;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -40,8 +47,30 @@ public class RenderSavedReportPreStep implements BackendStep
|
|||||||
@Override
|
@Override
|
||||||
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||||
{
|
{
|
||||||
// todo - verify ran on 1
|
String storageTableName = runBackendStepInput.getValueString(RenderSavedReportMetaDataProducer.FIELD_NAME_STORAGE_TABLE_NAME);
|
||||||
// todo - load the SavedReport
|
if(!StringUtils.hasContent(storageTableName))
|
||||||
|
{
|
||||||
|
throw (new QUserFacingException("Process configuration error: Missing value for storageTableName."));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(QContext.getQInstance().getTable(storageTableName) == null)
|
||||||
|
{
|
||||||
|
throw (new QUserFacingException("Process configuration error: Unrecognized value for storageTableName - no table named [" + storageTableName + "] was found in the instance."));
|
||||||
|
}
|
||||||
|
|
||||||
|
List<QRecord> records = runBackendStepInput.getRecords();
|
||||||
|
if(!CollectionUtils.nullSafeHasContents(records))
|
||||||
|
{
|
||||||
|
throw (new QUserFacingException("No report was selected or found to be rendered."));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(records.size() > 1)
|
||||||
|
{
|
||||||
|
throw (new QUserFacingException("You may only render 1 report at a time."));
|
||||||
|
}
|
||||||
|
|
||||||
|
SavedReport savedReport = new SavedReport(records.get(0));
|
||||||
|
|
||||||
// todo - check for inputs - set up the input screen...
|
// todo - check for inputs - set up the input screen...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,9 @@ package com.kingsrook.qqq.backend.core.processes.implementations.savedreports;
|
|||||||
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -42,14 +45,17 @@ import com.kingsrook.qqq.backend.core.model.actions.reporting.pivottable.PivotTa
|
|||||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.pivottable.PivotTableValue;
|
import com.kingsrook.qqq.backend.core.model.actions.reporting.pivottable.PivotTableValue;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.storage.StorageInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
import com.kingsrook.qqq.backend.core.model.savedreports.ReportColumns;
|
import com.kingsrook.qqq.backend.core.model.savedreports.ReportColumns;
|
||||||
import com.kingsrook.qqq.backend.core.model.savedreports.SavedReport;
|
import com.kingsrook.qqq.backend.core.model.savedreports.SavedReport;
|
||||||
import com.kingsrook.qqq.backend.core.model.savedreports.SavedReportsMetaDataProvider;
|
import com.kingsrook.qqq.backend.core.model.savedreports.SavedReportsMetaDataProvider;
|
||||||
|
import com.kingsrook.qqq.backend.core.modules.backend.implementations.memory.MemoryStorageAction;
|
||||||
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
||||||
import com.kingsrook.qqq.backend.core.utils.LocalMacDevUtils;
|
import com.kingsrook.qqq.backend.core.utils.LocalMacDevUtils;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
@ -57,7 +63,6 @@ import org.junit.jupiter.api.Disabled;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -71,7 +76,7 @@ class RenderSavedReportProcessTest extends BaseTest
|
|||||||
@BeforeEach
|
@BeforeEach
|
||||||
void beforeEach() throws Exception
|
void beforeEach() throws Exception
|
||||||
{
|
{
|
||||||
new SavedReportsMetaDataProvider().defineAll(QContext.getQInstance(), TestUtils.MEMORY_BACKEND_NAME, null);
|
new SavedReportsMetaDataProvider().defineAll(QContext.getQInstance(), TestUtils.MEMORY_BACKEND_NAME, TestUtils.MEMORY_BACKEND_NAME, null);
|
||||||
GenerateReportActionTest.insertPersonRecords(QContext.getQInstance());
|
GenerateReportActionTest.insertPersonRecords(QContext.getQInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,17 +136,14 @@ class RenderSavedReportProcessTest extends BaseTest
|
|||||||
RunProcessOutput runProcessOutput = runRenderReportProcess(savedReport, ReportFormatPossibleValueEnum.CSV);
|
RunProcessOutput runProcessOutput = runRenderReportProcess(savedReport, ReportFormatPossibleValueEnum.CSV);
|
||||||
|
|
||||||
String downloadFileName = runProcessOutput.getValueString("downloadFileName");
|
String downloadFileName = runProcessOutput.getValueString("downloadFileName");
|
||||||
String serverFilePath = runProcessOutput.getValueString("serverFilePath");
|
|
||||||
|
|
||||||
assertThat(downloadFileName)
|
assertThat(downloadFileName)
|
||||||
.startsWith(label + " - ")
|
.startsWith(label + " - ")
|
||||||
.matches(".*\\d\\d\\d\\d-\\d\\d-\\d\\d-\\d\\d\\d\\d.*")
|
.matches(".*\\d\\d\\d\\d-\\d\\d-\\d\\d-\\d\\d\\d\\d.*")
|
||||||
.endsWith(".csv");
|
.endsWith(".csv");
|
||||||
|
|
||||||
File serverFile = new File(serverFilePath);
|
InputStream inputStream = getInputStream(runProcessOutput);
|
||||||
assertTrue(serverFile.exists());
|
List<String> lines = IOUtils.readLines(inputStream, StandardCharsets.UTF_8);
|
||||||
|
|
||||||
List<String> lines = FileUtils.readLines(serverFile);
|
|
||||||
assertEquals("""
|
assertEquals("""
|
||||||
"Id","First Name","Last Name"
|
"Id","First Name","Last Name"
|
||||||
""".trim(), lines.get(0));
|
""".trim(), lines.get(0));
|
||||||
@ -149,7 +151,41 @@ class RenderSavedReportProcessTest extends BaseTest
|
|||||||
"1","Darin","Jonson"
|
"1","Darin","Jonson"
|
||||||
""".trim(), lines.get(1));
|
""".trim(), lines.get(1));
|
||||||
|
|
||||||
LocalMacDevUtils.openFile(serverFilePath);
|
writeTmpFileAndOpen(inputStream, ".csv");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private static InputStream getInputStream(RunProcessOutput runProcessOutput) throws QException
|
||||||
|
{
|
||||||
|
String storageTableName = runProcessOutput.getValueString("storageTableName");
|
||||||
|
String storageReference = runProcessOutput.getValueString("storageReference");
|
||||||
|
InputStream inputStream = new MemoryStorageAction().getInputStream(new StorageInput(storageTableName).withReference(storageReference));
|
||||||
|
return inputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private void writeTmpFileAndOpen(InputStream inputStream, String suffix) throws IOException
|
||||||
|
{
|
||||||
|
// LocalMacDevUtils.mayOpenFiles = true;
|
||||||
|
if(LocalMacDevUtils.mayOpenFiles)
|
||||||
|
{
|
||||||
|
inputStream.reset();
|
||||||
|
|
||||||
|
File tmpFile = File.createTempFile(getClass().getName(), suffix, new File("/tmp/"));
|
||||||
|
FileOutputStream fileOutputStream = new FileOutputStream(tmpFile);
|
||||||
|
inputStream.transferTo(fileOutputStream);
|
||||||
|
fileOutputStream.close();
|
||||||
|
|
||||||
|
LocalMacDevUtils.openFile(tmpFile.getAbsolutePath());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -203,14 +239,8 @@ class RenderSavedReportProcessTest extends BaseTest
|
|||||||
QRecord savedReport = insertBasicSavedPivotReport(label);
|
QRecord savedReport = insertBasicSavedPivotReport(label);
|
||||||
RunProcessOutput runProcessOutput = runRenderReportProcess(savedReport, ReportFormatPossibleValueEnum.XLSX);
|
RunProcessOutput runProcessOutput = runRenderReportProcess(savedReport, ReportFormatPossibleValueEnum.XLSX);
|
||||||
|
|
||||||
String serverFilePath = runProcessOutput.getValueString("serverFilePath");
|
InputStream inputStream = getInputStream(runProcessOutput);
|
||||||
System.out.println(serverFilePath);
|
writeTmpFileAndOpen(inputStream, ".xlsx");
|
||||||
|
|
||||||
File serverFile = new File(serverFilePath);
|
|
||||||
assertTrue(serverFile.exists());
|
|
||||||
|
|
||||||
LocalMacDevUtils.mayOpenFiles = true;
|
|
||||||
LocalMacDevUtils.openFile(serverFilePath, "/Applications/Numbers.app");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -225,14 +255,9 @@ class RenderSavedReportProcessTest extends BaseTest
|
|||||||
QRecord savedReport = insertBasicSavedPivotReport(label);
|
QRecord savedReport = insertBasicSavedPivotReport(label);
|
||||||
RunProcessOutput runProcessOutput = runRenderReportProcess(savedReport, ReportFormatPossibleValueEnum.JSON);
|
RunProcessOutput runProcessOutput = runRenderReportProcess(savedReport, ReportFormatPossibleValueEnum.JSON);
|
||||||
|
|
||||||
String serverFilePath = runProcessOutput.getValueString("serverFilePath");
|
InputStream inputStream = getInputStream(runProcessOutput);
|
||||||
System.out.println(serverFilePath);
|
String json = StringUtils.join("\n", IOUtils.readLines(inputStream, StandardCharsets.UTF_8));
|
||||||
|
printReport(json);
|
||||||
File serverFile = new File(serverFilePath);
|
|
||||||
assertTrue(serverFile.exists());
|
|
||||||
|
|
||||||
String json = FileUtils.readFileToString(serverFile, StandardCharsets.UTF_8);
|
|
||||||
System.out.println(json);
|
|
||||||
|
|
||||||
JSONArray jsonArray = new JSONArray(json);
|
JSONArray jsonArray = new JSONArray(json);
|
||||||
assertEquals(2, jsonArray.length());
|
assertEquals(2, jsonArray.length());
|
||||||
@ -262,6 +287,16 @@ class RenderSavedReportProcessTest extends BaseTest
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private void printReport(String report)
|
||||||
|
{
|
||||||
|
// System.out.println(report);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -272,13 +307,8 @@ class RenderSavedReportProcessTest extends BaseTest
|
|||||||
QRecord savedReport = insertBasicSavedPivotReport(label);
|
QRecord savedReport = insertBasicSavedPivotReport(label);
|
||||||
RunProcessOutput runProcessOutput = runRenderReportProcess(savedReport, ReportFormatPossibleValueEnum.CSV);
|
RunProcessOutput runProcessOutput = runRenderReportProcess(savedReport, ReportFormatPossibleValueEnum.CSV);
|
||||||
|
|
||||||
String serverFilePath = runProcessOutput.getValueString("serverFilePath");
|
InputStream inputStream = getInputStream(runProcessOutput);
|
||||||
System.out.println(serverFilePath);
|
List<String> csv = IOUtils.readLines(inputStream, StandardCharsets.UTF_8);
|
||||||
|
|
||||||
File serverFile = new File(serverFilePath);
|
|
||||||
assertTrue(serverFile.exists());
|
|
||||||
|
|
||||||
List<String> csv = FileUtils.readLines(serverFile, StandardCharsets.UTF_8);
|
|
||||||
System.out.println(csv);
|
System.out.println(csv);
|
||||||
|
|
||||||
assertEquals("""
|
assertEquals("""
|
||||||
@ -316,6 +346,7 @@ class RenderSavedReportProcessTest extends BaseTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -329,12 +360,8 @@ class RenderSavedReportProcessTest extends BaseTest
|
|||||||
String serverFilePath = runProcessOutput.getValueString("serverFilePath");
|
String serverFilePath = runProcessOutput.getValueString("serverFilePath");
|
||||||
System.out.println(serverFilePath);
|
System.out.println(serverFilePath);
|
||||||
|
|
||||||
File serverFile = new File(serverFilePath);
|
InputStream inputStream = getInputStream(runProcessOutput);
|
||||||
assertTrue(serverFile.exists());
|
writeTmpFileAndOpen(inputStream, ".xlsx");
|
||||||
|
|
||||||
// LocalMacDevUtils.mayOpenFiles = true;
|
|
||||||
LocalMacDevUtils.openFile(serverFilePath, "/Applications/Numbers.app");
|
|
||||||
LocalMacDevUtils.openFile(serverFilePath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -349,13 +376,8 @@ class RenderSavedReportProcessTest extends BaseTest
|
|||||||
QRecord savedReport = insertSavedPivotReportWithAllFunctions(label);
|
QRecord savedReport = insertSavedPivotReportWithAllFunctions(label);
|
||||||
RunProcessOutput runProcessOutput = runRenderReportProcess(savedReport, ReportFormatPossibleValueEnum.CSV);
|
RunProcessOutput runProcessOutput = runRenderReportProcess(savedReport, ReportFormatPossibleValueEnum.CSV);
|
||||||
|
|
||||||
String serverFilePath = runProcessOutput.getValueString("serverFilePath");
|
InputStream inputStream = getInputStream(runProcessOutput);
|
||||||
System.out.println(serverFilePath);
|
List<String> csv = IOUtils.readLines(inputStream, StandardCharsets.UTF_8);
|
||||||
|
|
||||||
File serverFile = new File(serverFilePath);
|
|
||||||
assertTrue(serverFile.exists());
|
|
||||||
|
|
||||||
List<String> csv = FileUtils.readLines(serverFile, StandardCharsets.UTF_8);
|
|
||||||
System.out.println(csv);
|
System.out.println(csv);
|
||||||
|
|
||||||
assertEquals("""
|
assertEquals("""
|
||||||
|
@ -23,7 +23,7 @@ package com.kingsrook.qqq.backend.module.rdbms.reporting;
|
|||||||
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.InputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import com.kingsrook.qqq.backend.core.actions.processes.QProcessCallbackFactory;
|
import com.kingsrook.qqq.backend.core.actions.processes.QProcessCallbackFactory;
|
||||||
@ -44,6 +44,7 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria
|
|||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterOrderBy;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterOrderBy;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.storage.StorageInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportDataSource;
|
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportDataSource;
|
||||||
@ -55,11 +56,12 @@ import com.kingsrook.qqq.backend.core.model.savedreports.ReportColumns;
|
|||||||
import com.kingsrook.qqq.backend.core.model.savedreports.SavedReport;
|
import com.kingsrook.qqq.backend.core.model.savedreports.SavedReport;
|
||||||
import com.kingsrook.qqq.backend.core.model.savedreports.SavedReportsMetaDataProvider;
|
import com.kingsrook.qqq.backend.core.model.savedreports.SavedReportsMetaDataProvider;
|
||||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||||
|
import com.kingsrook.qqq.backend.core.modules.backend.implementations.memory.MemoryStorageAction;
|
||||||
import com.kingsrook.qqq.backend.core.processes.implementations.savedreports.RenderSavedReportMetaDataProducer;
|
import com.kingsrook.qqq.backend.core.processes.implementations.savedreports.RenderSavedReportMetaDataProducer;
|
||||||
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
||||||
import com.kingsrook.qqq.backend.module.rdbms.TestUtils;
|
import com.kingsrook.qqq.backend.module.rdbms.TestUtils;
|
||||||
import com.kingsrook.qqq.backend.module.rdbms.actions.RDBMSActionTest;
|
import com.kingsrook.qqq.backend.module.rdbms.actions.RDBMSActionTest;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
@ -220,7 +222,7 @@ public class GenerateReportActionRDBMSTest extends RDBMSActionTest
|
|||||||
{
|
{
|
||||||
newSavedReport.setLabel("Test Report");
|
newSavedReport.setLabel("Test Report");
|
||||||
QContext.setQSession(new QSession().withSecurityKeyValue(TestUtils.SECURITY_KEY_STORE_ALL_ACCESS, true));
|
QContext.setQSession(new QSession().withSecurityKeyValue(TestUtils.SECURITY_KEY_STORE_ALL_ACCESS, true));
|
||||||
new SavedReportsMetaDataProvider().defineAll(QContext.getQInstance(), TestUtils.MEMORY_BACKEND_NAME, null);
|
new SavedReportsMetaDataProvider().defineAll(QContext.getQInstance(), TestUtils.MEMORY_BACKEND_NAME, TestUtils.MEMORY_BACKEND_NAME, null);
|
||||||
|
|
||||||
QRecord savedReport = new InsertAction().execute(new InsertInput(SavedReport.TABLE_NAME).withRecordEntity(newSavedReport)).getRecords().get(0);
|
QRecord savedReport = new InsertAction().execute(new InsertInput(SavedReport.TABLE_NAME).withRecordEntity(newSavedReport)).getRecords().get(0);
|
||||||
|
|
||||||
@ -231,7 +233,11 @@ public class GenerateReportActionRDBMSTest extends RDBMSActionTest
|
|||||||
input.addValue("reportFormat", ReportFormatPossibleValueEnum.CSV.getPossibleValueId());
|
input.addValue("reportFormat", ReportFormatPossibleValueEnum.CSV.getPossibleValueId());
|
||||||
RunProcessOutput runProcessOutput = new RunProcessAction().execute(input);
|
RunProcessOutput runProcessOutput = new RunProcessAction().execute(input);
|
||||||
|
|
||||||
return (FileUtils.readLines(new File(runProcessOutput.getValueString("serverFilePath")), StandardCharsets.UTF_8));
|
String storageTableName = runProcessOutput.getValueString("storageTableName");
|
||||||
|
String storageReference = runProcessOutput.getValueString("storageReference");
|
||||||
|
InputStream inputStream = new MemoryStorageAction().getInputStream(new StorageInput(storageTableName).withReference(storageReference));
|
||||||
|
|
||||||
|
return (IOUtils.readLines(inputStream, StandardCharsets.UTF_8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user