mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
CE-1068 - Initial checkin
This commit is contained in:
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.model.savedreports;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.AbstractWidgetRenderer;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
||||||
|
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.dashboard.widgets.DynamicFormWidgetData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.processes.implementations.savedreports.SavedReportToReportMetaDataAdapter;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Note - exists under 2 names, for the RenderSavedReport process, and for the
|
||||||
|
** ScheduledReport table
|
||||||
|
*******************************************************************************/
|
||||||
|
public class ReportValuesDynamicFormWidgetRenderer extends AbstractWidgetRenderer
|
||||||
|
{
|
||||||
|
private static final QLogger LOG = QLogger.getLogger(ReportValuesDynamicFormWidgetRenderer.class);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public RenderWidgetOutput render(RenderWidgetInput input) throws QException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
List<QFieldMetaData> fieldList = new ArrayList<>();
|
||||||
|
Map<String, String> defaultValues = new HashMap<>();
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// read params to ultimately find the query filter that has variables in it //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
SavedReport savedReport = null;
|
||||||
|
if(input.getQueryParams().containsKey("savedReportId"))
|
||||||
|
{
|
||||||
|
QRecord record = new GetAction().executeForRecord(new GetInput(SavedReport.TABLE_NAME).withPrimaryKey(ValueUtils.getValueAsInteger(input.getQueryParams().get("savedReportId"))));
|
||||||
|
savedReport = new SavedReport(record);
|
||||||
|
}
|
||||||
|
else if(input.getQueryParams().containsKey("id"))
|
||||||
|
{
|
||||||
|
QRecord scheduledReportRecord = new GetAction().executeForRecord(new GetInput(ScheduledReport.TABLE_NAME).withPrimaryKey(ValueUtils.getValueAsInteger(input.getQueryParams().get("id"))));
|
||||||
|
QRecord record = new GetAction().executeForRecord(new GetInput(SavedReport.TABLE_NAME).withPrimaryKey(ValueUtils.getValueAsInteger(scheduledReportRecord.getValueInteger("savedReportId"))));
|
||||||
|
savedReport = new SavedReport(record);
|
||||||
|
|
||||||
|
String inputValues = scheduledReportRecord.getValueString("inputValues");
|
||||||
|
if(StringUtils.hasContent(inputValues))
|
||||||
|
{
|
||||||
|
JSONObject jsonObject = JsonUtils.toJSONObject(inputValues);
|
||||||
|
for(String key : jsonObject.keySet())
|
||||||
|
{
|
||||||
|
defaultValues.put(key, jsonObject.optString(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//////////////////////////////////
|
||||||
|
// return quietly w/ nothing... //
|
||||||
|
//////////////////////////////////
|
||||||
|
DynamicFormWidgetData widgetData = new DynamicFormWidgetData();
|
||||||
|
return new RenderWidgetOutput(widgetData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(StringUtils.hasContent(savedReport.getQueryFilterJson()))
|
||||||
|
{
|
||||||
|
QQueryFilter queryFilter = SavedReportToReportMetaDataAdapter.getQQueryFilter(savedReport.getQueryFilterJson());
|
||||||
|
QTableMetaData table = QContext.getQInstance().getTable(savedReport.getTableName());
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// find variables in the query filter; convert them to a list of fields for the dynamic form //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
for(QFilterCriteria criteria : CollectionUtils.nonNullList(queryFilter.getCriteria()))
|
||||||
|
{
|
||||||
|
/////////////////////////////////
|
||||||
|
// todo - only variable fields //
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// todo - twice for "between" //
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
// todo - join fields!! //
|
||||||
|
//////////////////////////
|
||||||
|
QFieldMetaData fieldMetaData = table.getField(criteria.getFieldName()).clone();
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
// make name & label for field //
|
||||||
|
/////////////////////////////////
|
||||||
|
String operatorHumanish = StringUtils.allCapsToMixedCase(criteria.getOperator().name()); // todo match frontend..?
|
||||||
|
String fieldName = criteria.getFieldName() + operatorHumanish.replaceAll("_", "");
|
||||||
|
String label = fieldMetaData.getLabel() + " " + operatorHumanish.replaceAll("_", " ");
|
||||||
|
fieldMetaData.setName(fieldName);
|
||||||
|
fieldMetaData.setLabel(label);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// in this use case, every field is required and editable //
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
fieldMetaData.setIsRequired(true);
|
||||||
|
fieldMetaData.setIsEditable(true);
|
||||||
|
|
||||||
|
if(defaultValues.containsKey(fieldName))
|
||||||
|
{
|
||||||
|
fieldMetaData.setDefaultValue(defaultValues.get(fieldName));
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldList.add(fieldMetaData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////
|
||||||
|
// make output object and return //
|
||||||
|
///////////////////////////////////
|
||||||
|
DynamicFormWidgetData widgetData = new DynamicFormWidgetData();
|
||||||
|
widgetData.setFieldList(fieldList);
|
||||||
|
widgetData.setMergedDynamicFormValuesIntoFieldName("inputValues");
|
||||||
|
|
||||||
|
if(CollectionUtils.nullSafeIsEmpty(fieldList))
|
||||||
|
{
|
||||||
|
widgetData.setNoFieldsMessage("This Report does not use any Variable Values");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RenderWidgetOutput(widgetData);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
LOG.warn("Error rendering scheduled report values dynamic form widget", e, logPair("queryParams", String.valueOf(input.getQueryParams())));
|
||||||
|
throw (new QException("Error rendering scheduled report values dynamic form widget", e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.processes.implementations.savedreports;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.processes.QProcessCallbackFactory;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.processes.RunProcessAction;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
|
||||||
|
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.processes.RunProcessInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.savedreports.ScheduledReport;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||||
|
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public class RunScheduledReportExecuteStep implements BackendStep
|
||||||
|
{
|
||||||
|
private static final QLogger LOG = QLogger.getLogger(RunScheduledReportExecuteStep.class);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||||
|
{
|
||||||
|
Integer scheduledReportId = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
List<QRecord> records = runBackendStepInput.getRecords();
|
||||||
|
if(!CollectionUtils.nullSafeHasContents(records))
|
||||||
|
{
|
||||||
|
throw (new QUserFacingException("No scheduled report was selected or found."));
|
||||||
|
}
|
||||||
|
|
||||||
|
ScheduledReport scheduledReport = new ScheduledReport(records.get(0));
|
||||||
|
scheduledReportId = scheduledReport.getId();
|
||||||
|
|
||||||
|
/////////////////////////////////////////////
|
||||||
|
// run the process that renders the report //
|
||||||
|
/////////////////////////////////////////////
|
||||||
|
RunProcessAction runProcessAction = new RunProcessAction();
|
||||||
|
RunProcessInput renderProcessInput = new RunProcessInput();
|
||||||
|
renderProcessInput.setProcessName(RenderSavedReportMetaDataProducer.NAME);
|
||||||
|
renderProcessInput.setCallback(QProcessCallbackFactory.forPrimaryKey("id", scheduledReport.getSavedReportId()));
|
||||||
|
renderProcessInput.setFrontendStepBehavior(RunProcessInput.FrontendStepBehavior.SKIP);
|
||||||
|
renderProcessInput.setAsyncJobCallback(runBackendStepInput.getAsyncJobCallback());
|
||||||
|
|
||||||
|
renderProcessInput.addValue(RenderSavedReportMetaDataProducer.FIELD_NAME_REPORT_FORMAT, scheduledReport.getFormat());
|
||||||
|
renderProcessInput.addValue(RenderSavedReportMetaDataProducer.FIELD_NAME_EMAIL_ADDRESS, scheduledReport.getToAddresses());
|
||||||
|
renderProcessInput.addValue(RenderSavedReportMetaDataProducer.FIELD_NAME_EMAIL_SUBJECT, scheduledReport.getSubject());
|
||||||
|
|
||||||
|
if(StringUtils.hasContent(scheduledReport.getInputValues()))
|
||||||
|
{
|
||||||
|
//////////////////////////
|
||||||
|
// todo variable-values //
|
||||||
|
//////////////////////////
|
||||||
|
}
|
||||||
|
|
||||||
|
RunProcessOutput renderProcessOutput = runProcessAction.execute(renderProcessInput);
|
||||||
|
}
|
||||||
|
catch(QUserFacingException ufe)
|
||||||
|
{
|
||||||
|
LOG.info("Error running scheduled report", ufe, logPair("id", scheduledReportId));
|
||||||
|
throw (ufe);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
LOG.warn("Error running scheduled report", e, logPair("id", scheduledReportId));
|
||||||
|
throw (new QException("Error running scheduled report", e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.processes.implementations.savedreports;
|
||||||
|
|
||||||
|
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.MetaDataProducerInterface;
|
||||||
|
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.nocode.WidgetHtmlLine;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.layout.QIcon;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.NoCodeWidgetFrontendComponentMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendStepMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionInputMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QRecordListMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.savedreports.ScheduledReport;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** define process for rendering scheduled reports - that is - a thin layer on
|
||||||
|
** top of rendering a saved report.
|
||||||
|
*******************************************************************************/
|
||||||
|
public class RunScheduledReportMetaDataProducer implements MetaDataProducerInterface<QProcessMetaData>
|
||||||
|
{
|
||||||
|
public static final String NAME = "runScheduledReport";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public QProcessMetaData produce(QInstance qInstance) throws QException
|
||||||
|
{
|
||||||
|
QProcessMetaData process = new QProcessMetaData()
|
||||||
|
.withName(NAME)
|
||||||
|
.withLabel("Run Scheduled Report")
|
||||||
|
.withTableName(ScheduledReport.TABLE_NAME)
|
||||||
|
.withIcon(new QIcon().withName("print"))
|
||||||
|
|
||||||
|
.addStep(new QBackendStepMetaData()
|
||||||
|
.withName("execute")
|
||||||
|
.withInputData(new QFunctionInputMetaData().withRecordListMetaData(new QRecordListMetaData()
|
||||||
|
.withTableName(ScheduledReport.TABLE_NAME)))
|
||||||
|
.withCode(new QCodeReference(RunScheduledReportExecuteStep.class)))
|
||||||
|
|
||||||
|
.addStep(new QFrontendStepMetaData()
|
||||||
|
.withName("results")
|
||||||
|
.withComponent(new NoCodeWidgetFrontendComponentMetaData()
|
||||||
|
.withOutput(new WidgetHtmlLine().withVelocityTemplate("Success")))); // todo!!!
|
||||||
|
|
||||||
|
return (process);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user