diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/automation/RunRecordScriptsAutomationHandler.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/automation/RunRecordScriptsAutomationHandler.java
new file mode 100644
index 00000000..dfb75ca6
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/automation/RunRecordScriptsAutomationHandler.java
@@ -0,0 +1,89 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2023. 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.actions.automation;
+
+
+import com.kingsrook.qqq.backend.core.actions.scripts.RunAdHocRecordScriptAction;
+import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
+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.scripts.RunAdHocRecordScriptInput;
+import com.kingsrook.qqq.backend.core.model.actions.scripts.RunAdHocRecordScriptOutput;
+import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
+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.tables.query.QueryInput;
+import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin;
+import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
+import com.kingsrook.qqq.backend.core.model.automation.RecordAutomationInput;
+import com.kingsrook.qqq.backend.core.model.data.QRecord;
+import com.kingsrook.qqq.backend.core.model.metadata.code.AdHocScriptCodeReference;
+import com.kingsrook.qqq.backend.core.model.scripts.Script;
+import com.kingsrook.qqq.backend.core.model.scripts.ScriptRevision;
+import com.kingsrook.qqq.backend.core.model.scripts.ScriptType;
+import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
+import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public class RunRecordScriptsAutomationHandler extends RecordAutomationHandler
+{
+ private static final QLogger LOG = QLogger.getLogger(RunRecordScriptsAutomationHandler.class);
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public void execute(RecordAutomationInput recordAutomationInput) throws QException
+ {
+ String tableName = recordAutomationInput.getTableName();
+ QueryInput queryInput = new QueryInput();
+ queryInput.setTableName(ScriptRevision.TABLE_NAME);
+ queryInput.setFilter(new QQueryFilter(
+ new QFilterCriteria("script.tableName", QCriteriaOperator.EQUALS, tableName),
+ new QFilterCriteria("scriptType.name", QCriteriaOperator.EQUALS, "Record Script") // todo... no. something about post-insert/update?
+ ));
+ queryInput.withQueryJoin(new QueryJoin(Script.TABLE_NAME).withBaseTableOrAlias(ScriptRevision.TABLE_NAME).withJoinMetaData(QContext.getQInstance().getJoin("currentScriptRevision")));
+ queryInput.withQueryJoin(new QueryJoin(ScriptType.TABLE_NAME).withBaseTableOrAlias(Script.TABLE_NAME));
+
+ QueryOutput queryOutput = new QueryAction().execute(queryInput);
+ for(QRecord scriptRevision : CollectionUtils.nonNullList(queryOutput.getRecords()))
+ {
+ // todo - refresh the records if more than 1 script
+
+ LOG.info("Running script against records", logPair("scriptRevisionId", scriptRevision.getValue("id")), logPair("scriptId", scriptRevision.getValue("scriptIdd")));
+ RunAdHocRecordScriptInput input = new RunAdHocRecordScriptInput();
+ input.setCodeReference(new AdHocScriptCodeReference().withScriptRevisionRecord(scriptRevision));
+ input.setTableName(tableName);
+ input.setRecordList(recordAutomationInput.getRecordList());
+ RunAdHocRecordScriptOutput output = new RunAdHocRecordScriptOutput();
+ new RunAdHocRecordScriptAction().run(input, output);
+ }
+
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/RunAdHocRecordScriptAction.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/RunAdHocRecordScriptAction.java
index 4ec61c9a..5c00eae3 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/RunAdHocRecordScriptAction.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/RunAdHocRecordScriptAction.java
@@ -23,25 +23,38 @@ package com.kingsrook.qqq.backend.core.actions.scripts;
import java.io.Serializable;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Map;
import java.util.Objects;
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
import com.kingsrook.qqq.backend.core.actions.scripts.logging.QCodeExecutionLoggerInterface;
import com.kingsrook.qqq.backend.core.actions.scripts.logging.ScriptExecutionLoggerInterface;
import com.kingsrook.qqq.backend.core.actions.scripts.logging.StoreScriptLogAndScriptLogLineExecutionLogger;
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
+import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
+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.scripts.ExecuteCodeInput;
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeOutput;
import com.kingsrook.qqq.backend.core.model.actions.scripts.RunAdHocRecordScriptInput;
import com.kingsrook.qqq.backend.core.model.actions.scripts.RunAdHocRecordScriptOutput;
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput;
-import com.kingsrook.qqq.backend.core.model.data.QRecord;
+import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
+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.tables.query.QueryInput;
+import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin;
+import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
+import com.kingsrook.qqq.backend.core.model.metadata.code.AdHocScriptCodeReference;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeType;
+import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.scripts.Script;
import com.kingsrook.qqq.backend.core.model.scripts.ScriptRevision;
+import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
/*******************************************************************************
@@ -49,7 +62,10 @@ import com.kingsrook.qqq.backend.core.model.scripts.ScriptRevision;
*******************************************************************************/
public class RunAdHocRecordScriptAction
{
- // todo! private Map scriptRevisionCache = new HashMap<>();
+ private static final QLogger LOG = QLogger.getLogger(RunAdHocRecordScriptAction.class);
+
+ private Map scriptRevisionCacheByScriptRevisionId = new HashMap<>();
+ private Map scriptRevisionCacheByScriptId = new HashMap<>();
@@ -60,18 +76,43 @@ public class RunAdHocRecordScriptAction
{
ActionHelper.validateSession(input);
+ /////////////////////////
+ // figure out the code //
+ /////////////////////////
ScriptRevision scriptRevision = getScriptRevision(input);
+ if(scriptRevision == null)
+ {
+ throw (new QException("Script revision was not found."));
+ }
- GetInput getInput = new GetInput();
- getInput.setTableName(input.getTableName());
- getInput.setPrimaryKey(input.getRecordPrimaryKey());
- GetOutput getOutput = new GetAction().execute(getInput);
- QRecord record = getOutput.getRecord();
- // todo err if not found
+ ////////////////////////////
+ // figure out the records //
+ ////////////////////////////
+ QTableMetaData table = QContext.getQInstance().getTable(input.getTableName());
+ if(CollectionUtils.nullSafeIsEmpty(input.getRecordList()))
+ {
+ QueryInput queryInput = new QueryInput();
+ queryInput.setTableName(input.getTableName());
+ queryInput.setFilter(new QQueryFilter(new QFilterCriteria(table.getPrimaryKeyField(), QCriteriaOperator.IN, input.getRecordPrimaryKeyList())));
+ QueryOutput queryOutput = new QueryAction().execute(queryInput);
+ input.setRecordList(queryOutput.getRecords());
+ }
+ if(CollectionUtils.nullSafeIsEmpty(input.getRecordList()))
+ {
+ ////////////////////////////////////////
+ // just return if nothing found? idk //
+ ////////////////////////////////////////
+ LOG.info("No records supplied as input (or found via primary keys); exiting with noop");
+ return;
+ }
+
+ /////////////
+ // run it! //
+ /////////////
ExecuteCodeInput executeCodeInput = new ExecuteCodeInput();
executeCodeInput.setInput(new HashMap<>(Objects.requireNonNullElseGet(input.getInputValues(), HashMap::new)));
- executeCodeInput.getInput().put("record", record);
+ executeCodeInput.getInput().put("records", new ArrayList<>(input.getRecordList()));
executeCodeInput.setContext(new HashMap<>());
if(input.getOutputObject() != null)
{
@@ -82,10 +123,8 @@ public class RunAdHocRecordScriptAction
{
executeCodeInput.getContext().put("scriptUtils", input.getScriptUtils());
}
- else
- {
- executeCodeInput.getContext().put("scriptUtils", new ScriptApiUtils());
- }
+
+ executeCodeInput.getContext().put("api", new ScriptApi());
executeCodeInput.setCodeReference(new QCodeReference().withInlineCode(scriptRevision.getContents()).withCodeType(QCodeType.JAVA_SCRIPT)); // todo - code type as attribute of script!!
@@ -116,34 +155,57 @@ public class RunAdHocRecordScriptAction
*******************************************************************************/
private ScriptRevision getScriptRevision(RunAdHocRecordScriptInput input) throws QException
{
- // todo if(!scriptRevisionCache.containsKey(input.getCodeReference()))
+ AdHocScriptCodeReference codeReference = input.getCodeReference();
+ if(codeReference.getScriptRevisionRecord() != null)
{
- Serializable scriptId = input.getCodeReference().getScriptId();
- /*
- if(scriptId == null)
- {
- throw (new QNotFoundException("The input record [" + input.getCodeReference().getScriptId() + "][" + input.getCodeReference().getRecordPrimaryKey()
- + "] does not have a script specified for [" + input.getCodeReference().getFieldName() + "]"));
- }
-
- */
-
- Script script = getScript(input, scriptId);
- /* todo
- if(script.getCurrentScriptRevisionId() == null)
- {
- throw (new QNotFoundException("The script for record [" + input.getCodeReference().getRecordTable() + "][" + input.getCodeReference().getRecordPrimaryKey()
- + "] (scriptId=" + scriptId + ") does not have a current version."));
- }
-
- */
-
- ScriptRevision scriptRevision = getCurrentScriptRevision(input, script.getCurrentScriptRevisionId());
- // scriptRevisionCache.put(input.getCodeReference(), scriptRevision);
- return scriptRevision;
+ return (new ScriptRevision(codeReference.getScriptRevisionRecord()));
}
- // return scriptRevisionCache.get(input.getCodeReference());
+ if(codeReference.getScriptRevisionId() != null)
+ {
+ if(!scriptRevisionCacheByScriptRevisionId.containsKey(codeReference.getScriptRevisionId()))
+ {
+ GetInput getInput = new GetInput();
+ getInput.setTableName(ScriptRevision.TABLE_NAME);
+ getInput.setPrimaryKey(codeReference.getScriptRevisionId());
+ GetOutput getOutput = new GetAction().execute(getInput);
+ if(getOutput.getRecord() != null)
+ {
+ scriptRevisionCacheByScriptRevisionId.put(codeReference.getScriptRevisionId(), new ScriptRevision(getOutput.getRecord()));
+ }
+ else
+ {
+ scriptRevisionCacheByScriptRevisionId.put(codeReference.getScriptRevisionId(), null);
+ }
+ }
+
+ return (scriptRevisionCacheByScriptRevisionId.get(codeReference.getScriptRevisionId()));
+ }
+
+ if(codeReference.getScriptId() != null)
+ {
+ if(!scriptRevisionCacheByScriptId.containsKey(codeReference.getScriptId()))
+ {
+ QueryInput queryInput = new QueryInput();
+ queryInput.setTableName(ScriptRevision.TABLE_NAME);
+ queryInput.setFilter(new QQueryFilter(new QFilterCriteria("script.id", QCriteriaOperator.EQUALS, codeReference.getScriptId())));
+ queryInput.withQueryJoin(new QueryJoin(Script.TABLE_NAME).withBaseTableOrAlias(ScriptRevision.TABLE_NAME).withJoinMetaData(QContext.getQInstance().getJoin("currentScriptRevision")));
+ QueryOutput queryOutput = new QueryAction().execute(queryInput);
+
+ if(CollectionUtils.nullSafeHasContents(queryOutput.getRecords()))
+ {
+ scriptRevisionCacheByScriptId.put(codeReference.getScriptId(), new ScriptRevision(queryOutput.getRecords().get(0)));
+ }
+ else
+ {
+ scriptRevisionCacheByScriptId.put(codeReference.getScriptId(), null);
+ }
+ }
+
+ return (scriptRevisionCacheByScriptId.get(codeReference.getScriptId()));
+ }
+
+ throw (new QException("Code reference did not contain a scriptRevision, scriptRevisionId, or scriptId"));
}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/ScriptApi.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/ScriptApi.java
new file mode 100644
index 00000000..ad560f1f
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/ScriptApi.java
@@ -0,0 +1,237 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2023. 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.actions.scripts;
+
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import com.kingsrook.qqq.backend.core.actions.permissions.PermissionsHelper;
+import com.kingsrook.qqq.backend.core.actions.permissions.TablePermissionSubType;
+import com.kingsrook.qqq.backend.core.actions.tables.DeleteAction;
+import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
+import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
+import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
+import com.kingsrook.qqq.backend.core.context.QContext;
+import com.kingsrook.qqq.backend.core.exceptions.QException;
+import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteInput;
+import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
+import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
+import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterOrderBy;
+import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
+import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
+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.tables.QTableMetaData;
+
+
+/*******************************************************************************
+
+ $api.query("order", null);
+ $api.query($utils.newQueryInput().withTable("order").withLimit(1).withShouldGenerateDisplayValues())
+ *******************************************************************************/
+public class ScriptApi implements Serializable
+{
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public QueryInput newQueryInput()
+ {
+ return (new QueryInput());
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public QQueryFilter newQueryFilter()
+ {
+ return (new QQueryFilter());
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public QFilterCriteria newFilterCriteria()
+ {
+ return (new QFilterCriteria());
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public QFilterOrderBy newFilterOrderBy()
+ {
+ return (new QFilterOrderBy());
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public QRecord newRecord()
+ {
+ return (new QRecord());
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public List query(String tableName, QQueryFilter filter) throws QException
+ {
+ QueryInput queryInput = new QueryInput();
+ queryInput.setTableName(tableName);
+ queryInput.setFilter(filter);
+ PermissionsHelper.checkTablePermissionThrowing(queryInput, TablePermissionSubType.READ);
+ return (new QueryAction().execute(queryInput).getRecords());
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public List query(QueryInput queryInput) throws QException
+ {
+ PermissionsHelper.checkTablePermissionThrowing(queryInput, TablePermissionSubType.READ);
+ return (new QueryAction().execute(queryInput).getRecords());
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public void insert(String tableName, QRecord record) throws QException
+ {
+ insert(tableName, List.of(record));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public void insert(String tableName, List recordList) throws QException
+ {
+ InsertInput insertInput = new InsertInput();
+ insertInput.setTableName(tableName);
+ insertInput.setRecords(recordList);
+ PermissionsHelper.checkTablePermissionThrowing(insertInput, TablePermissionSubType.INSERT);
+ new InsertAction().execute(insertInput);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public void update(String tableName, QRecord record) throws QException
+ {
+ update(tableName, List.of(record));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public void update(String tableName, List recordList) throws QException
+ {
+ UpdateInput updateInput = new UpdateInput();
+ updateInput.setTableName(tableName);
+ updateInput.setRecords(recordList);
+ PermissionsHelper.checkTablePermissionThrowing(updateInput, TablePermissionSubType.EDIT);
+ new UpdateAction().execute(updateInput);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public void delete(String tableName, Serializable primaryKey) throws QException
+ {
+ delete(tableName, List.of(primaryKey));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public void delete(String tableName, QRecord record) throws QException
+ {
+ delete(tableName, List.of(record));
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public void delete(String tableName, List> recordOrPrimaryKeyList) throws QException
+ {
+ QTableMetaData table = QContext.getQInstance().getTable(tableName);
+ DeleteInput deleteInput = new DeleteInput();
+ deleteInput.setTableName(tableName);
+ List primaryKeyList = new ArrayList<>();
+ for(Object o : recordOrPrimaryKeyList)
+ {
+ if(o instanceof QRecord qRecord)
+ {
+ primaryKeyList.add(qRecord.getValue(table.getPrimaryKeyField()));
+ }
+ else
+ {
+ primaryKeyList.add((Serializable) o);
+ }
+ }
+ deleteInput.setPrimaryKeys(primaryKeyList);
+ PermissionsHelper.checkTablePermissionThrowing(deleteInput, TablePermissionSubType.DELETE);
+ new DeleteAction().execute(deleteInput);
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public void delete(String tableName, QQueryFilter filter) throws QException
+ {
+ DeleteInput deleteInput = new DeleteInput();
+ deleteInput.setTableName(tableName);
+ deleteInput.setQueryFilter(filter);
+ PermissionsHelper.checkTablePermissionThrowing(deleteInput, TablePermissionSubType.DELETE);
+ new DeleteAction().execute(deleteInput);
+ }
+
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/ScriptApiUtils.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/ScriptApiUtils.java
deleted file mode 100644
index d4b5631e..00000000
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/ScriptApiUtils.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * QQQ - Low-code Application Framework for Engineers.
- * Copyright (C) 2021-2023. 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.actions.scripts;
-
-
-import java.io.Serializable;
-import java.util.List;
-import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
-import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
-import com.kingsrook.qqq.backend.core.exceptions.QException;
-import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
-import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
-import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput;
-import com.kingsrook.qqq.backend.core.model.data.QRecord;
-
-
-/*******************************************************************************
-
- $utils.query("order", null);
- $utils.query($utils.newQueryInput().withTable("order").withLimit(1).withShouldGenerateDisplayValues())
- *******************************************************************************/
-public class ScriptApiUtils implements Serializable
-{
-
- /*******************************************************************************
- **
- *******************************************************************************/
- public QueryInput newQueryInput()
- {
- return (new QueryInput());
- }
-
-
-
- /*******************************************************************************
- **
- *******************************************************************************/
- public QRecord newQRecord()
- {
- return (new QRecord());
- }
-
-
-
- /*******************************************************************************
- **
- *******************************************************************************/
- public List query(String table, QQueryFilter filter) throws QException
- {
- QueryInput queryInput = new QueryInput();
- queryInput.setTableName(table);
- queryInput.setFilter(filter);
- return (new QueryAction().execute(queryInput).getRecords());
- }
-
-
-
- /*******************************************************************************
- **
- *******************************************************************************/
- public List query(QueryInput queryInput) throws QException
- {
- return (new QueryAction().execute(queryInput).getRecords());
- }
-
-
-
- /*******************************************************************************
- **
- *******************************************************************************/
- public void update(String table, List recordList) throws QException
- {
- UpdateInput updateInput = new UpdateInput();
- updateInput.setTableName(table);
- updateInput.setRecords(recordList);
- new UpdateAction().execute(updateInput);
- }
-
-
-
- /*******************************************************************************
- **
- *******************************************************************************/
- public void update(String table, QRecord record) throws QException
- {
- UpdateInput updateInput = new UpdateInput();
- updateInput.setTableName(table);
- updateInput.setRecords(List.of(record));
- new UpdateAction().execute(updateInput);
- }
-
-}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/scripts/RunAdHocRecordScriptInput.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/scripts/RunAdHocRecordScriptInput.java
index 971ff4c0..cf097f4f 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/scripts/RunAdHocRecordScriptInput.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/scripts/RunAdHocRecordScriptInput.java
@@ -23,9 +23,11 @@ package com.kingsrook.qqq.backend.core.model.actions.scripts;
import java.io.Serializable;
+import java.util.List;
import java.util.Map;
import com.kingsrook.qqq.backend.core.actions.scripts.logging.QCodeExecutionLoggerInterface;
import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput;
+import com.kingsrook.qqq.backend.core.model.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.code.AdHocScriptCodeReference;
@@ -36,7 +38,8 @@ public class RunAdHocRecordScriptInput extends AbstractTableActionInput
{
private AdHocScriptCodeReference codeReference;
private Map inputValues;
- private Serializable recordPrimaryKey;
+ private List recordPrimaryKeyList; // can either supply recordList, or recordPrimaryKeyList
+ private List recordList;
private String tableName;
private QCodeExecutionLoggerInterface logger;
@@ -207,37 +210,6 @@ public class RunAdHocRecordScriptInput extends AbstractTableActionInput
- /*******************************************************************************
- ** Getter for recordPrimaryKey
- *******************************************************************************/
- public Serializable getRecordPrimaryKey()
- {
- return (this.recordPrimaryKey);
- }
-
-
-
- /*******************************************************************************
- ** Setter for recordPrimaryKey
- *******************************************************************************/
- public void setRecordPrimaryKey(Serializable recordPrimaryKey)
- {
- this.recordPrimaryKey = recordPrimaryKey;
- }
-
-
-
- /*******************************************************************************
- ** Fluent setter for recordPrimaryKey
- *******************************************************************************/
- public RunAdHocRecordScriptInput withRecordPrimaryKey(Serializable recordPrimaryKey)
- {
- this.recordPrimaryKey = recordPrimaryKey;
- return (this);
- }
-
-
-
/*******************************************************************************
** Getter for tableName
*******************************************************************************/
@@ -267,4 +239,66 @@ public class RunAdHocRecordScriptInput extends AbstractTableActionInput
return (this);
}
+
+
+ /*******************************************************************************
+ ** Getter for recordList
+ *******************************************************************************/
+ public List getRecordList()
+ {
+ return (this.recordList);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for recordList
+ *******************************************************************************/
+ public void setRecordList(List recordList)
+ {
+ this.recordList = recordList;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for recordList
+ *******************************************************************************/
+ public RunAdHocRecordScriptInput withRecordList(List recordList)
+ {
+ this.recordList = recordList;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for recordPrimaryKeyList
+ *******************************************************************************/
+ public List getRecordPrimaryKeyList()
+ {
+ return (this.recordPrimaryKeyList);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for recordPrimaryKeyList
+ *******************************************************************************/
+ public void setRecordPrimaryKeyList(List recordPrimaryKeyList)
+ {
+ this.recordPrimaryKeyList = recordPrimaryKeyList;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for recordPrimaryKeyList
+ *******************************************************************************/
+ public RunAdHocRecordScriptInput withRecordPrimaryKeyList(List recordPrimaryKeyList)
+ {
+ this.recordPrimaryKeyList = recordPrimaryKeyList;
+ return (this);
+ }
+
}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/code/AdHocScriptCodeReference.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/code/AdHocScriptCodeReference.java
index bab3cc69..02441950 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/code/AdHocScriptCodeReference.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/code/AdHocScriptCodeReference.java
@@ -22,12 +22,22 @@
package com.kingsrook.qqq.backend.core.model.metadata.code;
+import com.kingsrook.qqq.backend.core.model.data.QRecord;
+
+
/*******************************************************************************
**
*******************************************************************************/
public class AdHocScriptCodeReference extends QCodeReference
{
+ ////////////////////////////////////////////////////////////////////////////////
+ // can supply scriptId (in which case, current revisionId will be looked up), //
+ // or revisionId (in which case, record will be looked up) //
+ // or, the record. //
+ ////////////////////////////////////////////////////////////////////////////////
private Integer scriptId;
+ private Integer scriptRevisionId;
+ private QRecord scriptRevisionRecord;
@@ -60,4 +70,66 @@ public class AdHocScriptCodeReference extends QCodeReference
return (this);
}
+
+
+ /*******************************************************************************
+ ** Getter for scriptRevisionId
+ *******************************************************************************/
+ public Integer getScriptRevisionId()
+ {
+ return (this.scriptRevisionId);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for scriptRevisionId
+ *******************************************************************************/
+ public void setScriptRevisionId(Integer scriptRevisionId)
+ {
+ this.scriptRevisionId = scriptRevisionId;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for scriptRevisionId
+ *******************************************************************************/
+ public AdHocScriptCodeReference withScriptRevisionId(Integer scriptRevisionId)
+ {
+ this.scriptRevisionId = scriptRevisionId;
+ return (this);
+ }
+
+
+
+ /*******************************************************************************
+ ** Getter for scriptRevisionRecord
+ *******************************************************************************/
+ public QRecord getScriptRevisionRecord()
+ {
+ return (this.scriptRevisionRecord);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for scriptRevisionRecord
+ *******************************************************************************/
+ public void setScriptRevisionRecord(QRecord scriptRevisionRecord)
+ {
+ this.scriptRevisionRecord = scriptRevisionRecord;
+ }
+
+
+
+ /*******************************************************************************
+ ** Fluent setter for scriptRevisionRecord
+ *******************************************************************************/
+ public AdHocScriptCodeReference withScriptRevisionRecord(QRecord scriptRevisionRecord)
+ {
+ this.scriptRevisionRecord = scriptRevisionRecord;
+ return (this);
+ }
+
}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/tables/TablesPossibleValueSourceMetaDataProvider.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/tables/TablesPossibleValueSourceMetaDataProvider.java
index bb8f6a26..27cce6df 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/tables/TablesPossibleValueSourceMetaDataProvider.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/tables/TablesPossibleValueSourceMetaDataProvider.java
@@ -23,12 +23,16 @@ package com.kingsrook.qqq.backend.core.model.metadata.tables;
import java.util.ArrayList;
+import java.util.Comparator;
import java.util.List;
+import com.kingsrook.qqq.backend.core.instances.QInstanceEnricher;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.PVSValueFormatAndFields;
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValue;
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSourceType;
+import com.kingsrook.qqq.backend.core.utils.StringUtils;
+import org.apache.commons.lang.BooleanUtils;
/*******************************************************************************
@@ -53,9 +57,15 @@ public class TablesPossibleValueSourceMetaDataProvider
List> enumValues = new ArrayList<>();
for(QTableMetaData table : qInstance.getTables().values())
{
- enumValues.add(new QPossibleValue<>(table.getName(), table.getLabel()));
+ if(BooleanUtils.isNotTrue(table.getIsHidden()))
+ {
+ String label = StringUtils.hasContent(table.getLabel()) ? table.getLabel() : QInstanceEnricher.nameToLabel(table.getName());
+ enumValues.add(new QPossibleValue<>(table.getName(), label));
+ }
}
+ enumValues.sort(Comparator.comparing(QPossibleValue::getLabel));
+
possibleValueSource.withEnumValues(enumValues);
return (possibleValueSource);
}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/scripts/ScriptsMetaDataProvider.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/scripts/ScriptsMetaDataProvider.java
index 7029df3c..356230c4 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/scripts/ScriptsMetaDataProvider.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/scripts/ScriptsMetaDataProvider.java
@@ -81,6 +81,7 @@ public class ScriptsMetaDataProvider
.withName("storeScriptRevision")
.withStepList(List.of(
new QBackendStepMetaData()
+ .withName("main")
.withCode(new QCodeReference(StoreScriptRevisionProcessStep.class))
)));
}
@@ -118,6 +119,30 @@ public class ScriptsMetaDataProvider
.withJoinOn(new JoinOn("id", "scriptLogId"))
.withOrderBy(new QFilterOrderBy("id"))
.withInferredName());
+
+ instance.addJoin(new QJoinMetaData()
+ .withType(JoinType.ONE_TO_MANY)
+ .withLeftTable(Script.TABLE_NAME)
+ .withRightTable(ScriptRevision.TABLE_NAME)
+ .withJoinOn(new JoinOn("id", "scriptId"))
+ .withOrderBy(new QFilterOrderBy("id"))
+ .withInferredName());
+
+ instance.addJoin(new QJoinMetaData()
+ .withType(JoinType.ONE_TO_ONE)
+ .withLeftTable(Script.TABLE_NAME)
+ .withRightTable(ScriptRevision.TABLE_NAME)
+ .withJoinOn(new JoinOn("currentScriptRevisionId", "id"))
+ .withName("currentScriptRevision"));
+
+ instance.addJoin(new QJoinMetaData()
+ .withType(JoinType.ONE_TO_MANY)
+ .withLeftTable(ScriptType.TABLE_NAME)
+ .withRightTable(Script.TABLE_NAME)
+ .withJoinOn(new JoinOn("id", "scriptTypeId"))
+ .withOrderBy(new QFilterOrderBy("id"))
+ .withInferredName());
+
}
diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/scripts/RunAdHocRecordScriptActionTest.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/scripts/RunAdHocRecordScriptActionTest.java
index b8edad0f..2dbf8eb9 100644
--- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/scripts/RunAdHocRecordScriptActionTest.java
+++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/scripts/RunAdHocRecordScriptActionTest.java
@@ -67,7 +67,7 @@ class RunAdHocRecordScriptActionTest extends BaseTest
""");
RunAdHocRecordScriptInput runAdHocRecordScriptInput = new RunAdHocRecordScriptInput();
- runAdHocRecordScriptInput.setRecordPrimaryKey(1);
+ runAdHocRecordScriptInput.setRecordPrimaryKeyList(List.of(1));
runAdHocRecordScriptInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
runAdHocRecordScriptInput.setCodeReference(new AdHocScriptCodeReference().withScriptId(scriptId));
runAdHocRecordScriptInput.setLogger(new Log4jCodeExecutionLogger());