mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 05:01:07 +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