diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/RenderedReport.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/RenderedReport.java
new file mode 100644
index 00000000..19ef870d
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/RenderedReport.java
@@ -0,0 +1,506 @@
+/*
+ * 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 .
+ */
+
+package com.kingsrook.qqq.backend.core.model.savedreports;
+
+
+import java.time.Instant;
+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.data.QField;
+import com.kingsrook.qqq.backend.core.model.data.QRecord;
+import com.kingsrook.qqq.backend.core.model.data.QRecordEntity;
+import com.kingsrook.qqq.backend.core.model.metadata.fields.DisplayFormat;
+import com.kingsrook.qqq.backend.core.model.metadata.fields.DynamicDefaultValueBehavior;
+import com.kingsrook.qqq.backend.core.model.metadata.fields.ValueTooLongBehavior;
+
+
+/*******************************************************************************
+ ** Entity bean for the rendered report table
+ *******************************************************************************/
+public class RenderedReport extends QRecordEntity
+{
+ public static final String TABLE_NAME = "renderedReport";
+
+ @QField(isEditable = false)
+ private Integer id;
+
+ @QField(isEditable = false)
+ private Instant createDate;
+
+ @QField(isEditable = false)
+ private Instant modifyDate;
+
+ @QField(maxLength = 250, valueTooLongBehavior = ValueTooLongBehavior.ERROR, dynamicDefaultValueBehavior = DynamicDefaultValueBehavior.USER_ID)
+ private String userId;
+
+ @QField(possibleValueSourceName = SavedReport.TABLE_NAME)
+ private Integer savedReportId;
+
+ @QField(possibleValueSourceName = RenderedReportStatus.NAME, label = "Status")
+ private Integer renderedReportStatusId;
+
+ @QField(maxLength = 40, valueTooLongBehavior = ValueTooLongBehavior.ERROR)
+ private String jobUuid;
+
+ @QField(maxLength = 250, valueTooLongBehavior = ValueTooLongBehavior.ERROR)
+ private String resultPath;
+
+ @QField(maxLength = 10, valueTooLongBehavior = ValueTooLongBehavior.ERROR, possibleValueSourceName = ReportFormatPossibleValueEnum.NAME)
+ private String reportFormat;
+
+ @QField()
+ private Instant startTime;
+
+ @QField()
+ private Instant endTime;
+
+ @QField(displayFormat = DisplayFormat.COMMAS)
+ private Integer rowCount;
+
+ @QField(maxLength = 250, valueTooLongBehavior = ValueTooLongBehavior.TRUNCATE_ELLIPSIS)
+ private String errorMessage;
+
+
+
+ /*******************************************************************************
+ ** Constructor
+ **
+ *******************************************************************************/
+ public RenderedReport()
+ {
+ }
+
+
+
+ /*******************************************************************************
+ ** Constructor
+ **
+ *******************************************************************************/
+ public RenderedReport(QRecord qRecord) throws QException
+ {
+ populateFromQRecord(qRecord);
+ }
+
+
+ /*******************************************************************************
+ ** Getter for id
+ *******************************************************************************/
+ public Integer getId()
+ {
+ return (this.id);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for id
+ *******************************************************************************/
+ public void setId(Integer id)
+ {
+ this.id = id;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for id
+ *******************************************************************************/
+ public RenderedReport withId(Integer id)
+ {
+ this.id = id;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for createDate
+ *******************************************************************************/
+ public Instant getCreateDate()
+ {
+ return (this.createDate);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for createDate
+ *******************************************************************************/
+ public void setCreateDate(Instant createDate)
+ {
+ this.createDate = createDate;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for createDate
+ *******************************************************************************/
+ public RenderedReport withCreateDate(Instant createDate)
+ {
+ this.createDate = createDate;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for modifyDate
+ *******************************************************************************/
+ public Instant getModifyDate()
+ {
+ return (this.modifyDate);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for modifyDate
+ *******************************************************************************/
+ public void setModifyDate(Instant modifyDate)
+ {
+ this.modifyDate = modifyDate;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for modifyDate
+ *******************************************************************************/
+ public RenderedReport withModifyDate(Instant modifyDate)
+ {
+ this.modifyDate = modifyDate;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for userId
+ *******************************************************************************/
+ public String getUserId()
+ {
+ return (this.userId);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for userId
+ *******************************************************************************/
+ public void setUserId(String userId)
+ {
+ this.userId = userId;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for userId
+ *******************************************************************************/
+ public RenderedReport withUserId(String userId)
+ {
+ this.userId = userId;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for savedReportId
+ *******************************************************************************/
+ public Integer getSavedReportId()
+ {
+ return (this.savedReportId);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for savedReportId
+ *******************************************************************************/
+ public void setSavedReportId(Integer savedReportId)
+ {
+ this.savedReportId = savedReportId;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for savedReportId
+ *******************************************************************************/
+ public RenderedReport withSavedReportId(Integer savedReportId)
+ {
+ this.savedReportId = savedReportId;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for renderedReportStatusId
+ *******************************************************************************/
+ public Integer getRenderedReportStatusId()
+ {
+ return (this.renderedReportStatusId);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for renderedReportStatusId
+ *******************************************************************************/
+ public void setRenderedReportStatusId(Integer renderedReportStatusId)
+ {
+ this.renderedReportStatusId = renderedReportStatusId;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for renderedReportStatusId
+ *******************************************************************************/
+ public RenderedReport withRenderedReportStatusId(Integer renderedReportStatusId)
+ {
+ this.renderedReportStatusId = renderedReportStatusId;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for jobUuid
+ *******************************************************************************/
+ public String getJobUuid()
+ {
+ return (this.jobUuid);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for jobUuid
+ *******************************************************************************/
+ public void setJobUuid(String jobUuid)
+ {
+ this.jobUuid = jobUuid;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for jobUuid
+ *******************************************************************************/
+ public RenderedReport withJobUuid(String jobUuid)
+ {
+ this.jobUuid = jobUuid;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for resultPath
+ *******************************************************************************/
+ public String getResultPath()
+ {
+ return (this.resultPath);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for resultPath
+ *******************************************************************************/
+ public void setResultPath(String resultPath)
+ {
+ this.resultPath = resultPath;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for resultPath
+ *******************************************************************************/
+ public RenderedReport withResultPath(String resultPath)
+ {
+ this.resultPath = resultPath;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for reportFormat
+ *******************************************************************************/
+ public String getReportFormat()
+ {
+ return (this.reportFormat);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for reportFormat
+ *******************************************************************************/
+ public void setReportFormat(String reportFormat)
+ {
+ this.reportFormat = reportFormat;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for reportFormat
+ *******************************************************************************/
+ public RenderedReport withReportFormat(String reportFormat)
+ {
+ this.reportFormat = reportFormat;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for startTime
+ *******************************************************************************/
+ public Instant getStartTime()
+ {
+ return (this.startTime);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for startTime
+ *******************************************************************************/
+ public void setStartTime(Instant startTime)
+ {
+ this.startTime = startTime;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for startTime
+ *******************************************************************************/
+ public RenderedReport withStartTime(Instant startTime)
+ {
+ this.startTime = startTime;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for endTime
+ *******************************************************************************/
+ public Instant getEndTime()
+ {
+ return (this.endTime);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for endTime
+ *******************************************************************************/
+ public void setEndTime(Instant endTime)
+ {
+ this.endTime = endTime;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for endTime
+ *******************************************************************************/
+ public RenderedReport withEndTime(Instant endTime)
+ {
+ this.endTime = endTime;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for rowCount
+ *******************************************************************************/
+ public Integer getRowCount()
+ {
+ return (this.rowCount);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for rowCount
+ *******************************************************************************/
+ public void setRowCount(Integer rowCount)
+ {
+ this.rowCount = rowCount;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for rowCount
+ *******************************************************************************/
+ public RenderedReport withRowCount(Integer rowCount)
+ {
+ this.rowCount = rowCount;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for errorMessage
+ *******************************************************************************/
+ public String getErrorMessage()
+ {
+ return (this.errorMessage);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for errorMessage
+ *******************************************************************************/
+ public void setErrorMessage(String errorMessage)
+ {
+ this.errorMessage = errorMessage;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for errorMessage
+ *******************************************************************************/
+ public RenderedReport withErrorMessage(String errorMessage)
+ {
+ this.errorMessage = errorMessage;
+ return (this);
+ }
+
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/RenderedReportStatus.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/RenderedReportStatus.java
new file mode 100644
index 00000000..b407fc07
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/RenderedReportStatus.java
@@ -0,0 +1,96 @@
+/*
+ * 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 .
+ */
+
+package com.kingsrook.qqq.backend.core.model.savedreports;
+
+
+import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.PossibleValueEnum;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public enum RenderedReportStatus implements PossibleValueEnum
+{
+ RUNNING(1, "Running"),
+ COMPLETE(2, "Complete"),
+ FAILED(3, "Failed");
+
+ public static final String NAME = "renderedReportStatus";
+
+ private final Integer id;
+ private final String label;
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ RenderedReportStatus(int id, String label)
+ {
+ this.id = id;
+ this.label = label;
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for id
+ **
+ *******************************************************************************/
+ public Integer getId()
+ {
+ return id;
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for label
+ **
+ *******************************************************************************/
+ public String getLabel()
+ {
+ return label;
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public Integer getPossibleValueId()
+ {
+ return id;
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public String getPossibleValueLabel()
+ {
+ return label;
+ }
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/SavedReportsMetaDataProvider.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/SavedReportsMetaDataProvider.java
index 8549c9a9..9ffbcab0 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/SavedReportsMetaDataProvider.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/SavedReportsMetaDataProvider.java
@@ -34,6 +34,7 @@ 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.possiblevalues.QPossibleValueSource;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
+import com.kingsrook.qqq.backend.core.model.metadata.tables.Capability;
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.Tier;
@@ -55,8 +56,10 @@ public class SavedReportsMetaDataProvider
public void defineAll(QInstance instance, String recordTablesBackendName, String reportStorageBackendName, Consumer backendDetailEnricher) throws QException
{
instance.addTable(defineSavedReportTable(recordTablesBackendName, backendDetailEnricher));
+ instance.addTable(defineRenderedReportTable(recordTablesBackendName, backendDetailEnricher));
instance.addPossibleValueSource(QPossibleValueSource.newForTable(SavedReport.TABLE_NAME));
instance.addPossibleValueSource(QPossibleValueSource.newForEnum(ReportFormatPossibleValueEnum.NAME, ReportFormatPossibleValueEnum.values()));
+ instance.addPossibleValueSource(QPossibleValueSource.newForEnum(RenderedReportStatus.NAME, RenderedReportStatus.values()));
instance.addTable(defineReportStorageTable(reportStorageBackendName, backendDetailEnricher));
@@ -92,8 +95,6 @@ public class SavedReportsMetaDataProvider
return (table);
}
-
-
/*******************************************************************************
**
*******************************************************************************/
@@ -118,7 +119,6 @@ public class SavedReportsMetaDataProvider
{
QTableMetaData table = new QTableMetaData()
.withName(SavedReport.TABLE_NAME)
- .withLabel("Saved Report")
.withIcon(new QIcon().withName("article"))
.withRecordLabelFormat("%s")
.withRecordLabelFields("label")
@@ -145,4 +145,38 @@ public class SavedReportsMetaDataProvider
return (table);
}
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ private QTableMetaData defineRenderedReportTable(String backendName, Consumer backendDetailEnricher) throws QException
+ {
+ QTableMetaData table = new QTableMetaData()
+ .withName(RenderedReport.TABLE_NAME)
+ .withIcon(new QIcon().withName("print"))
+ .withRecordLabelFormat("%s - %s")
+ .withRecordLabelFields("savedReportId", "startTime")
+ .withBackendName(backendName)
+ .withPrimaryKeyField("id")
+ .withFieldsFromEntity(RenderedReport.class)
+ .withSection(new QFieldSection("identity", new QIcon().withName("badge"), Tier.T1, List.of("id", "savedReportId", "renderedReportStatusId")))
+ .withSection(new QFieldSection("input", new QIcon().withName("input"), Tier.T2, List.of("userId", "reportFormat")))
+ .withSection(new QFieldSection("output", new QIcon().withName("output"), Tier.T2, List.of("jobUuid", "resultPath", "rowCount", "errorMessage", "startTime", "endTime")))
+ .withSection(new QFieldSection("dates", new QIcon().withName("calendar_month"), Tier.T3, List.of("createDate", "modifyDate")))
+ .withoutCapabilities(Capability.allWriteCapabilities());
+
+ table.getField("renderedReportStatusId").setAdornments(List.of(new FieldAdornment(AdornmentType.CHIP)
+ .withValues(AdornmentType.ChipValues.iconAndColorValues(RenderedReportStatus.RUNNING.getId(), "pending", AdornmentType.ChipValues.COLOR_SECONDARY))
+ .withValues(AdornmentType.ChipValues.iconAndColorValues(RenderedReportStatus.COMPLETE.getId(), "check", AdornmentType.ChipValues.COLOR_SUCCESS))
+ .withValues(AdornmentType.ChipValues.iconAndColorValues(RenderedReportStatus.FAILED.getId(), "error", AdornmentType.ChipValues.COLOR_ERROR))));
+
+ if(backendDetailEnricher != null)
+ {
+ backendDetailEnricher.accept(table);
+ }
+
+ return (table);
+ }
+
}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedreports/RenderSavedReportExecuteStep.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedreports/RenderSavedReportExecuteStep.java
index a6d99954..028e512e 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedreports/RenderSavedReportExecuteStep.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/savedreports/RenderSavedReportExecuteStep.java
@@ -25,23 +25,35 @@ package com.kingsrook.qqq.backend.core.processes.implementations.savedreports;
import java.io.OutputStream;
import java.io.Serializable;
import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.UUID;
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.tables.InsertAction;
import com.kingsrook.qqq.backend.core.actions.tables.StorageAction;
+import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
import com.kingsrook.qqq.backend.core.exceptions.QException;
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.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.ReportFormatPossibleValueEnum;
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportInput;
+import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportOutput;
+import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.storage.StorageInput;
+import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput;
+import com.kingsrook.qqq.backend.core.model.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportMetaData;
+import com.kingsrook.qqq.backend.core.model.savedreports.RenderedReport;
+import com.kingsrook.qqq.backend.core.model.savedreports.RenderedReportStatus;
import com.kingsrook.qqq.backend.core.model.savedreports.SavedReport;
+import com.kingsrook.qqq.backend.core.utils.ExceptionUtils;
import com.kingsrook.qqq.backend.core.utils.StringUtils;
@@ -60,22 +72,43 @@ public class RenderSavedReportExecuteStep implements BackendStep
@Override
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
{
+ QRecord renderedReportRecord = null;
+
try
{
- 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));
- String downloadFileBaseName = getDownloadFileBaseName(runBackendStepInput, savedReport);
- String storageReference = UUID.randomUUID() + "/" + downloadFileBaseName + "." + reportFormat.getExtension();
-
- OutputStream outputStream = new StorageAction().createOutputStream(new StorageInput(storageTableName).withReference(storageReference));
+ ////////////////////////////////
+ // read inputs, set up params //
+ ////////////////////////////////
+ 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));
+ String downloadFileBaseName = getDownloadFileBaseName(runBackendStepInput, savedReport);
+ String storageReference = LocalDate.now() + "/" + LocalTime.now().toString().replaceAll(":", "").replaceFirst("\\..*", "") + "/" + UUID.randomUUID() + "/" + downloadFileBaseName + "." + reportFormat.getExtension();
+ OutputStream outputStream = new StorageAction().createOutputStream(new StorageInput(storageTableName).withReference(storageReference));
runBackendStepInput.getAsyncJobCallback().updateStatus("Generating Report");
+ //////////////////////////////////////////////////////////////////
+ // insert a rendered-report record indicating that it's running //
+ //////////////////////////////////////////////////////////////////
+ renderedReportRecord = new InsertAction().execute(new InsertInput(RenderedReport.TABLE_NAME).withRecordEntity(new RenderedReport()
+ .withSavedReportId(savedReport.getId())
+ .withStartTime(Instant.now())
+ // todo .withJobUuid(runBackendStepInput.get)
+ .withRenderedReportStatusId(RenderedReportStatus.RUNNING.getId())
+ .withReportFormat(ReportFormatPossibleValueEnum.valueOf(reportFormat.name()).getPossibleValueId())
+ )).getRecords().get(0);
+
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ // convert the report record to report meta-data, which the GenerateReportAction works on //
+ ////////////////////////////////////////////////////////////////////////////////////////////
QReportMetaData reportMetaData = new SavedReportToReportMetaDataAdapter().adapt(savedReport, reportFormat);
+ /////////////////////////////////////
+ // setup & run the generate action //
+ /////////////////////////////////////
ReportInput reportInput = new ReportInput();
+ reportInput.setAsyncJobCallback(runBackendStepInput.getAsyncJobCallback());
reportInput.setReportMetaData(reportMetaData);
reportInput.setReportDestination(new ReportDestination()
.withReportFormat(reportFormat)
@@ -84,7 +117,18 @@ public class RenderSavedReportExecuteStep implements BackendStep
Map values = runBackendStepInput.getValues();
reportInput.setInputValues(values);
- new GenerateReportAction().execute(reportInput);
+ ReportOutput reportOutput = new GenerateReportAction().execute(reportInput);
+
+ ///////////////////////////////////
+ // update record to show success //
+ ///////////////////////////////////
+ new UpdateAction().execute(new UpdateInput(RenderedReport.TABLE_NAME).withRecord(new QRecord()
+ .withValue("id", renderedReportRecord.getValue("id"))
+ .withValue("resultPath", storageReference)
+ .withValue("renderedReportStatusId", RenderedReportStatus.COMPLETE.getPossibleValueId())
+ .withValue("endTime", Instant.now())
+ .withValue("rowCount", reportOutput.getTotalRecordCount())
+ ));
runBackendStepOutput.addValue("downloadFileName", downloadFileBaseName + "." + reportFormat.getExtension());
runBackendStepOutput.addValue("storageTableName", storageTableName);
@@ -92,9 +136,18 @@ public class RenderSavedReportExecuteStep implements BackendStep
}
catch(Exception e)
{
- // todo - render error screen?
+ if(renderedReportRecord != null)
+ {
+ new UpdateAction().execute(new UpdateInput(RenderedReport.TABLE_NAME).withRecord(new QRecord()
+ .withValue("id", renderedReportRecord.getValue("id"))
+ .withValue("renderedReportStatusId", RenderedReportStatus.FAILED.getPossibleValueId())
+ .withValue("endTime", Instant.now())
+ .withValue("errorMessage", ExceptionUtils.concatenateMessagesFromChain(e))
+ ));
+ }
LOG.warn("Error rendering saved report", e);
+ throw (e);
}
}