From 3a1125f66842b675f9820973e0b5580d595e5ea2 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Tue, 2 Apr 2024 15:44:50 -0500 Subject: [PATCH] CE-881 Add RenderedReport records --- .../model/savedreports/RenderedReport.java | 506 ++++++++++++++++++ .../savedreports/RenderedReportStatus.java | 96 ++++ .../SavedReportsMetaDataProvider.java | 40 +- .../RenderSavedReportExecuteStep.java | 73 ++- 4 files changed, 702 insertions(+), 13 deletions(-) create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/RenderedReport.java create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/savedreports/RenderedReportStatus.java 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); } }