Add RunReportForRecordProcess; 1st version of AbstractProcessMetaDataBuilder

This commit is contained in:
2022-11-03 10:24:59 -05:00
parent 3c04841f73
commit ab0b38dd82
16 changed files with 1154 additions and 26 deletions

View File

@ -54,6 +54,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleVal
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSourceType;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.queues.SQSQueueProviderMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportDataSource;
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;
@ -143,9 +144,8 @@ class QInstanceValidatorTest
qInstance.setTables(null);
qInstance.setProcesses(null);
},
"At least 1 table must be defined",
"Unrecognized table shape for possibleValueSource shape",
"Unrecognized processName for queue");
true,
"At least 1 table must be defined");
}
@ -162,9 +162,8 @@ class QInstanceValidatorTest
qInstance.setTables(new HashMap<>());
qInstance.setProcesses(new HashMap<>());
},
"At least 1 table must be defined",
"Unrecognized table shape for possibleValueSource shape",
"Unrecognized processName for queue");
true,
"At least 1 table must be defined");
}
@ -570,6 +569,40 @@ class QInstanceValidatorTest
/*******************************************************************************
**
*******************************************************************************/
@Test
void testFieldSectionDuplicateName()
{
QTableMetaData table = new QTableMetaData().withName("test")
.withBackendName(TestUtils.DEFAULT_BACKEND_NAME)
.withSection(new QFieldSection("section1", "Section 1", new QIcon("person"), Tier.T1, List.of("id")))
.withSection(new QFieldSection("section1", "Section 2", new QIcon("person"), Tier.T2, List.of("name")))
.withField(new QFieldMetaData("id", QFieldType.INTEGER))
.withField(new QFieldMetaData("name", QFieldType.INTEGER));
assertValidationFailureReasons((qInstance) -> qInstance.addTable(table), "more than 1 section named");
}
/*******************************************************************************
**
*******************************************************************************/
@Test
void testFieldSectionDuplicateLabel()
{
QTableMetaData table = new QTableMetaData().withName("test")
.withBackendName(TestUtils.DEFAULT_BACKEND_NAME)
.withSection(new QFieldSection("section1", "Section 1", new QIcon("person"), Tier.T1, List.of("id")))
.withSection(new QFieldSection("section2", "Section 1", new QIcon("person"), Tier.T2, List.of("name")))
.withField(new QFieldMetaData("id", QFieldType.INTEGER))
.withField(new QFieldMetaData("name", QFieldType.INTEGER));
assertValidationFailureReasons((qInstance) -> qInstance.addTable(table), "more than 1 section labeled");
}
/*******************************************************************************
**
*******************************************************************************/
@ -1258,6 +1291,138 @@ class QInstanceValidatorTest
/*******************************************************************************
**
*******************************************************************************/
@Test
void testReportName()
{
assertValidationFailureReasons((qInstance) -> qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).withName(null),
"Inconsistent naming for report");
assertValidationFailureReasons((qInstance) -> qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).withName(""),
"Inconsistent naming for report");
assertValidationFailureReasons((qInstance) -> qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).withName("wrongName"),
"Inconsistent naming for report");
}
/*******************************************************************************
**
*******************************************************************************/
@Test
void testReportNoDataSources()
{
assertValidationFailureReasons((qInstance) -> qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).withDataSources(null),
"At least 1 data source",
"unrecognized dataSourceName");
assertValidationFailureReasons((qInstance) -> qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).withDataSources(new ArrayList<>()),
"At least 1 data source",
"unrecognized dataSourceName");
}
/*******************************************************************************
**
*******************************************************************************/
@Test
void testReportDataSourceNames()
{
assertValidationFailureReasons((qInstance) -> qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).getDataSources().get(0).setName(null),
"Missing name for a dataSource",
"unrecognized dataSourceName");
assertValidationFailureReasons((qInstance) -> qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).getDataSources().get(0).setName(""),
"Missing name for a dataSource",
"unrecognized dataSourceName");
assertValidationFailureReasons((qInstance) ->
{
List<QReportDataSource> dataSources = new ArrayList<>(qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).getDataSources());
dataSources.add(dataSources.get(0));
qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).setDataSources(dataSources);
},
"More than one dataSource with name");
}
/*******************************************************************************
**
*******************************************************************************/
@Test
void testReportDataSourceTables()
{
assertValidationFailureReasons((qInstance) -> qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).getDataSources().get(0).setSourceTable("notATable"),
"is not a table in this instance");
assertValidationFailureReasons((qInstance) -> qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).getDataSources().get(0).setSourceTable(null),
"does not have a sourceTable");
assertValidationFailureReasons((qInstance) -> qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).getDataSources().get(0).setSourceTable(""),
"does not have a sourceTable");
}
/*******************************************************************************
**
*******************************************************************************/
@Test
void testReportDataSourceTablesFilter()
{
assertValidationFailureReasons((qInstance) -> qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).getDataSources().get(0).getQueryFilter().getCriteria().get(0).setFieldName(null),
"Missing fieldName for a criteria");
assertValidationFailureReasons((qInstance) -> qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).getDataSources().get(0).getQueryFilter().getCriteria().get(0).setFieldName("notAField"),
"is not a field in this table");
assertValidationFailureReasons((qInstance) -> qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).getDataSources().get(0).getQueryFilter().getCriteria().get(0).setOperator(null),
"Missing operator for a criteria");
assertValidationFailureReasons((qInstance) -> qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).getDataSources().get(0).getQueryFilter().withOrderBy(new QFilterOrderBy(null)),
"Missing fieldName for an orderBy");
assertValidationFailureReasons((qInstance) -> qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).getDataSources().get(0).getQueryFilter().withOrderBy(new QFilterOrderBy("notAField")),
"is not a field in this table");
}
/*******************************************************************************
**
*******************************************************************************/
@Test
void testReportDataSourceStaticDataSupplier()
{
assertValidationFailureReasons((qInstance) -> qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).getDataSources().get(0).withStaticDataSupplier(new QCodeReference()),
"has both a sourceTable and a staticDataSupplier");
assertValidationFailureReasons((qInstance) ->
{
QReportDataSource dataSource = qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).getDataSources().get(0);
dataSource.setSourceTable(null);
dataSource.setStaticDataSupplier(new QCodeReference(null, QCodeType.JAVA, null));
},
"missing a code reference name");
assertValidationFailureReasons((qInstance) ->
{
QReportDataSource dataSource = qInstance.getReport(TestUtils.REPORT_NAME_SHAPES_PERSON).getDataSources().get(0);
dataSource.setSourceTable(null);
dataSource.setStaticDataSupplier(new QCodeReference(ArrayList.class, null));
},
"is not of the expected type");
}
/*******************************************************************************
**
*******************************************************************************/

View File

@ -0,0 +1,62 @@
/*
* QQQ - Low-code Application Framework for Engineers.
* Copyright (C) 2021-2022. 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.reports;
import com.kingsrook.qqq.backend.core.actions.processes.RunProcessAction;
import com.kingsrook.qqq.backend.core.exceptions.QException;
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.metadata.QInstance;
import com.kingsrook.qqq.backend.core.utils.TestUtils;
import org.junit.jupiter.api.Test;
/*******************************************************************************
** Unit test for BasicRunReportProcess
*******************************************************************************/
class RunReportForRecordProcessTest
{
/*******************************************************************************
**
*******************************************************************************/
@Test
void testRunReport() throws QException
{
QInstance instance = TestUtils.defineInstance();
TestUtils.insertDefaultShapes(instance);
RunProcessInput runProcessInput = new RunProcessInput(instance);
runProcessInput.setSession(TestUtils.getMockSession());
runProcessInput.setProcessName(TestUtils.PROCESS_NAME_RUN_SHAPES_PERSON_REPORT);
runProcessInput.addValue(BasicRunReportProcess.FIELD_REPORT_NAME, TestUtils.REPORT_NAME_SHAPES_PERSON);
runProcessInput.addValue("recordsParam", "recordIds");
runProcessInput.addValue("recordIds", "1");
RunProcessOutput runProcessOutput = new RunProcessAction().execute(runProcessInput);
// runProcessOutput = new RunProcessAction().execute(runProcessInput);
// assertThat(runProcessOutput.getProcessState().getNextStepName()).isPresent().get().isEqualTo(BasicRunReportProcess.STEP_NAME_ACCESS);
// assertThat(runProcessOutput.getValues()).containsKeys("downloadFileName", "serverFilePath");
}
}

View File

@ -76,6 +76,11 @@ import com.kingsrook.qqq.backend.core.model.metadata.processes.QRecordListMetaDa
import com.kingsrook.qqq.backend.core.model.metadata.queues.QQueueMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.queues.QQueueProviderMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.queues.SQSQueueProviderMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportDataSource;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportField;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportView;
import com.kingsrook.qqq.backend.core.model.metadata.reporting.ReportType;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.tables.automation.AutomationStatusTracking;
import com.kingsrook.qqq.backend.core.model.metadata.tables.automation.AutomationStatusTrackingType;
@ -91,6 +96,7 @@ import com.kingsrook.qqq.backend.core.processes.implementations.basepull.Basepul
import com.kingsrook.qqq.backend.core.processes.implementations.etl.basic.BasicETLProcess;
import com.kingsrook.qqq.backend.core.processes.implementations.etl.streamed.StreamedETLProcess;
import com.kingsrook.qqq.backend.core.processes.implementations.mock.MockBackendStep;
import com.kingsrook.qqq.backend.core.processes.implementations.reports.RunReportForRecordProcess;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -118,10 +124,12 @@ public class TestUtils
public static final String PROCESS_NAME_INCREASE_BIRTHDATE = "increaseBirthdate";
public static final String PROCESS_NAME_ADD_TO_PEOPLES_AGE = "addToPeoplesAge";
public static final String PROCESS_NAME_BASEPULL = "basepullTest";
public static final String PROCESS_NAME_RUN_SHAPES_PERSON_REPORT = "runShapesPersonReport";
public static final String TABLE_NAME_PERSON_FILE = "personFile";
public static final String TABLE_NAME_PERSON_MEMORY = "personMemory";
public static final String TABLE_NAME_ID_AND_NAME_ONLY = "idAndNameOnly";
public static final String TABLE_NAME_BASEPULL = "basepullTest";
public static final String REPORT_NAME_SHAPES_PERSON = "shapesPersonReport";
public static final String POSSIBLE_VALUE_SOURCE_STATE = "state"; // enum-type
public static final String POSSIBLE_VALUE_SOURCE_SHAPE = "shape"; // table-type
@ -167,6 +175,9 @@ public class TestUtils
qInstance.addProcess(defineProcessIncreasePersonBirthdate());
qInstance.addProcess(defineProcessBasepull());
qInstance.addReport(defineShapesPersonsReport());
qInstance.addProcess(defineShapesPersonReportProcess());
qInstance.addAutomationProvider(definePollingAutomationProvider());
qInstance.addQueueProvider(defineSqsProvider());
@ -951,4 +962,52 @@ public class TestUtils
.withProcessName(PROCESS_NAME_INCREASE_BIRTHDATE));
}
/*******************************************************************************
**
*******************************************************************************/
public static QReportMetaData defineShapesPersonsReport()
{
return new QReportMetaData()
.withName(REPORT_NAME_SHAPES_PERSON)
.withProcessName(PROCESS_NAME_RUN_SHAPES_PERSON_REPORT)
.withInputFields(List.of(
new QFieldMetaData(RunReportForRecordProcess.FIELD_RECORD_ID, QFieldType.INTEGER).withIsRequired(true)
))
.withDataSources(List.of(
new QReportDataSource()
.withName("persons")
.withSourceTable(TestUtils.TABLE_NAME_PERSON_MEMORY)
.withQueryFilter(new QQueryFilter()
.withCriteria(new QFilterCriteria("favoriteShapeId", QCriteriaOperator.EQUALS, List.of("${input." + RunReportForRecordProcess.FIELD_RECORD_ID + "}")))
)
))
.withViews(List.of(
new QReportView()
.withName("person")
.withDataSourceName("persons")
.withType(ReportType.TABLE)
.withColumns(List.of(
new QReportField().withName("id"),
new QReportField().withName("firstName"),
new QReportField().withName("lastName")
))
));
}
/*******************************************************************************
**
*******************************************************************************/
public static QProcessMetaData defineShapesPersonReportProcess()
{
return RunReportForRecordProcess.processMetaDataBuilder()
.withProcessName(PROCESS_NAME_RUN_SHAPES_PERSON_REPORT)
.withReportName(REPORT_NAME_SHAPES_PERSON)
.withTableName(TestUtils.TABLE_NAME_SHAPE)
.getProcessMetaData();
}
}