mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 05:01:07 +00:00
Merged feature/workflows-support into integration
This commit is contained in:
@ -21,7 +21,10 @@ public class CreateNewQBit
|
|||||||
|
|
||||||
private static ExecutorService executorService = null;
|
private static ExecutorService executorService = null;
|
||||||
|
|
||||||
private static String SED = "/opt/homebrew/bin/gsed";
|
private static String SED = "/opt/homebrew/bin/gsed"; // needs to be a version that supports -i (in-place edit)
|
||||||
|
private static String GIT = "/usr/bin/git";
|
||||||
|
private static String CP = "/bin/cp";
|
||||||
|
private static String MV = "/bin/mv";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -87,7 +90,7 @@ public class CreateNewQBit
|
|||||||
System.out.println();
|
System.out.println();
|
||||||
|
|
||||||
System.out.println("Copying template...");
|
System.out.println("Copying template...");
|
||||||
ProcessResult cpResult = run(new ProcessBuilder("cp", "-rv", template.getAbsolutePath(), dir.getAbsolutePath()));
|
ProcessResult cpResult = run(new ProcessBuilder(CP, "-rv", template.getAbsolutePath(), dir.getAbsolutePath()));
|
||||||
System.out.print(cpResult.stdout());
|
System.out.print(cpResult.stdout());
|
||||||
System.out.println();
|
System.out.println();
|
||||||
|
|
||||||
@ -100,7 +103,7 @@ public class CreateNewQBit
|
|||||||
System.out.println();
|
System.out.println();
|
||||||
|
|
||||||
System.out.println("Init'ing git repo...");
|
System.out.println("Init'ing git repo...");
|
||||||
run(new ProcessBuilder("git", "init").directory(dir));
|
run(new ProcessBuilder(GIT, "init").directory(dir));
|
||||||
System.out.println();
|
System.out.println();
|
||||||
|
|
||||||
// git remote add origin https://github.com/Kingsrook/${name}.git ?
|
// git remote add origin https://github.com/Kingsrook/${name}.git ?
|
||||||
@ -123,9 +126,9 @@ public class CreateNewQBit
|
|||||||
{
|
{
|
||||||
String srcPath = dir.getAbsolutePath() + "/src/main/java/com/kingsrook/qbits";
|
String srcPath = dir.getAbsolutePath() + "/src/main/java/com/kingsrook/qbits";
|
||||||
String packagePath = packageName.replace('.', '/');
|
String packagePath = packageName.replace('.', '/');
|
||||||
System.out.print(run(new ProcessBuilder("mv", "-v", srcPath + "/todo/TodoQBitConfig.java", srcPath + "/todo/" + className + "QBitConfig.java")).stdout());
|
System.out.print(run(new ProcessBuilder(MV, "-v", srcPath + "/todo/TodoQBitConfig.java", srcPath + "/todo/" + className + "QBitConfig.java")).stdout());
|
||||||
System.out.print(run(new ProcessBuilder("mv", "-v", srcPath + "/todo/TodoQBitProducer.java", srcPath + "/todo/" + className + "QBitProducer.java")).stdout());
|
System.out.print(run(new ProcessBuilder(MV, "-v", srcPath + "/todo/TodoQBitProducer.java", srcPath + "/todo/" + className + "QBitProducer.java")).stdout());
|
||||||
System.out.print(run(new ProcessBuilder("mv", "-v", srcPath + "/todo", srcPath + "/" + packagePath)).stdout());
|
System.out.print(run(new ProcessBuilder(MV, "-v", srcPath + "/todo", srcPath + "/" + packagePath)).stdout());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ public class ApiAwareTableCountExecutor extends TableCountExecutor implements Ap
|
|||||||
// take care of managing criteria, which may not be in this version, etc //
|
// take care of managing criteria, which may not be in this version, etc //
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
QQueryFilter filter = Objects.requireNonNullElseGet(input.getFilter(), () -> new QQueryFilter());
|
QQueryFilter filter = Objects.requireNonNullElseGet(input.getFilter(), () -> new QQueryFilter());
|
||||||
ApiQueryFilterUtils.manageCriteriaFields(filter, tableApiFields, badRequestMessages, apiName, countInput);
|
ApiQueryFilterUtils.manageCriteriaFields(filter, tableApiFields, badRequestMessages, apiName, apiVersion, countInput);
|
||||||
|
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
// no more badRequest checks below here //
|
// no more badRequest checks below here //
|
||||||
|
@ -106,7 +106,7 @@ public class ApiAwareTableQueryExecutor extends TableQueryExecutor implements Ap
|
|||||||
// take care of managing order-by fields and criteria, which may not be in this version, etc //
|
// take care of managing order-by fields and criteria, which may not be in this version, etc //
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
manageOrderByFields(filter, tableApiFields, badRequestMessages, apiName, queryInput);
|
manageOrderByFields(filter, tableApiFields, badRequestMessages, apiName, queryInput);
|
||||||
ApiQueryFilterUtils.manageCriteriaFields(filter, tableApiFields, badRequestMessages, apiName, queryInput);
|
ApiQueryFilterUtils.manageCriteriaFields(filter, tableApiFields, badRequestMessages, apiName, apiVersion, queryInput);
|
||||||
|
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
// no more badRequest checks below here //
|
// no more badRequest checks below here //
|
||||||
|
@ -24,11 +24,14 @@ package com.kingsrook.qqq.api.utils;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import com.kingsrook.qqq.api.actions.GetTableApiFieldsAction;
|
||||||
import com.kingsrook.qqq.api.model.actions.ApiFieldCustomValueMapper;
|
import com.kingsrook.qqq.api.model.actions.ApiFieldCustomValueMapper;
|
||||||
import com.kingsrook.qqq.api.model.metadata.fields.ApiFieldMetaData;
|
import com.kingsrook.qqq.api.model.metadata.fields.ApiFieldMetaData;
|
||||||
import com.kingsrook.qqq.api.model.metadata.fields.ApiFieldMetaDataContainer;
|
import com.kingsrook.qqq.api.model.metadata.fields.ApiFieldMetaDataContainer;
|
||||||
import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader;
|
import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QBadRequestException;
|
import com.kingsrook.qqq.backend.core.exceptions.QBadRequestException;
|
||||||
|
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.QueryOrCountInputInterface;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.QueryOrCountInputInterface;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
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.QQueryFilter;
|
||||||
@ -36,6 +39,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
|||||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
import com.kingsrook.qqq.backend.core.utils.ObjectUtils;
|
import com.kingsrook.qqq.backend.core.utils.ObjectUtils;
|
||||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||||
|
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -43,16 +47,57 @@ import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class ApiQueryFilterUtils
|
public class ApiQueryFilterUtils
|
||||||
{
|
{
|
||||||
|
private static final QLogger LOG = QLogger.getLogger(ApiQueryFilterUtils.class);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
**
|
**
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
public static void manageCriteriaFields(QQueryFilter filter, Map<String, QFieldMetaData> tableApiFields, List<String> badRequestMessages, String apiName, QueryOrCountInputInterface input)
|
@Deprecated(since = "version was added that took apiVerison")
|
||||||
|
public static void manageCriteriaFields(QQueryFilter filter, Map<String, QFieldMetaData> tableApiFields, List<String> badRequestMessages, String apiName, QueryOrCountInputInterface input) throws QException
|
||||||
|
{
|
||||||
|
manageCriteriaFields(filter, tableApiFields, badRequestMessages, apiName, null, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
**
|
||||||
|
***************************************************************************/
|
||||||
|
public static void manageCriteriaFields(QQueryFilter filter, Map<String, QFieldMetaData> tableApiFields, List<String> badRequestMessages, String apiName, String apiVersion, QueryOrCountInputInterface input) throws QException
|
||||||
{
|
{
|
||||||
for(QFilterCriteria criteria : CollectionUtils.nonNullList(filter.getCriteria()))
|
for(QFilterCriteria criteria : CollectionUtils.nonNullList(filter.getCriteria()))
|
||||||
{
|
{
|
||||||
String apiFieldName = criteria.getFieldName();
|
String apiFieldName = criteria.getFieldName();
|
||||||
QFieldMetaData field = tableApiFields.get(apiFieldName);
|
QFieldMetaData field = tableApiFields.get(apiFieldName);
|
||||||
|
|
||||||
|
String joinTableName = null;
|
||||||
|
if(apiFieldName.contains("."))
|
||||||
|
{
|
||||||
|
if(apiVersion == null)
|
||||||
|
{
|
||||||
|
LOG.warn("No apiVersion provided for manageCriteriaFields. Cannot process join criteria field", logPair("fieldName", apiFieldName));
|
||||||
|
badRequestMessages.add("Cannot process joined criteria field: " + apiFieldName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String[] split = apiFieldName.split("\\.", 2);
|
||||||
|
joinTableName = split[0];
|
||||||
|
String joinFieldName = split[1];
|
||||||
|
|
||||||
|
Map<String, QFieldMetaData> joinTableApiFields = GetTableApiFieldsAction.getTableApiFieldMap(new GetTableApiFieldsAction.ApiNameVersionAndTableName(apiName, apiVersion, joinTableName));
|
||||||
|
field = joinTableApiFields.get(joinFieldName);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
badRequestMessages.add("Error processing criteria field: " + apiFieldName + ": " + e.getMessage());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(field == null)
|
if(field == null)
|
||||||
{
|
{
|
||||||
badRequestMessages.add("Unrecognized criteria field name: " + apiFieldName + ".");
|
badRequestMessages.add("Unrecognized criteria field name: " + apiFieldName + ".");
|
||||||
@ -61,10 +106,12 @@ public class ApiQueryFilterUtils
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ApiFieldMetaData apiFieldMetaData = ObjectUtils.tryAndRequireNonNullElse(() -> ApiFieldMetaDataContainer.of(field).getApiFieldMetaData(apiName), new ApiFieldMetaData());
|
QFieldMetaData finalField = field;
|
||||||
|
ApiFieldMetaData apiFieldMetaData = ObjectUtils.tryAndRequireNonNullElse(() -> ApiFieldMetaDataContainer.of(finalField).getApiFieldMetaData(apiName), new ApiFieldMetaData());
|
||||||
if(StringUtils.hasContent(apiFieldMetaData.getReplacedByFieldName()))
|
if(StringUtils.hasContent(apiFieldMetaData.getReplacedByFieldName()))
|
||||||
{
|
{
|
||||||
criteria.setFieldName(apiFieldMetaData.getReplacedByFieldName());
|
String joinTablePrefix = joinTableName == null ? "" : (joinTableName + ".");
|
||||||
|
criteria.setFieldName(joinTablePrefix + apiFieldMetaData.getReplacedByFieldName());
|
||||||
}
|
}
|
||||||
else if(apiFieldMetaData.getCustomValueMapper() != null)
|
else if(apiFieldMetaData.getCustomValueMapper() != null)
|
||||||
{
|
{
|
||||||
|
@ -23,11 +23,15 @@ package com.kingsrook.qqq.api.middleware.specs.v1;
|
|||||||
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
import com.kingsrook.qqq.api.TestUtils;
|
import com.kingsrook.qqq.api.TestUtils;
|
||||||
import com.kingsrook.qqq.api.middleware.specs.ApiAwareSpecTestBase;
|
import com.kingsrook.qqq.api.middleware.specs.ApiAwareSpecTestBase;
|
||||||
|
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.query.QCriteriaOperator;
|
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.QFilterCriteria;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.session.QSystemUserSession;
|
||||||
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
||||||
import com.kingsrook.qqq.middleware.javalin.specs.AbstractEndpointSpec;
|
import com.kingsrook.qqq.middleware.javalin.specs.AbstractEndpointSpec;
|
||||||
import io.javalin.http.ContentType;
|
import io.javalin.http.ContentType;
|
||||||
@ -270,4 +274,88 @@ class ApiAwareTableQuerySpecV1Test extends ApiAwareSpecTestBase
|
|||||||
assertEquals("Could not find a table named no-such-table in this api.", jsonObject.getString("error"));
|
assertEquals("Could not find a table named no-such-table in this api.", jsonObject.getString("error"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testJoin() throws QException
|
||||||
|
{
|
||||||
|
/////////////////////////
|
||||||
|
// insert a test order //
|
||||||
|
/////////////////////////
|
||||||
|
QContext.init(TestUtils.defineInstance(), new QSystemUserSession());
|
||||||
|
TestUtils.insert1Order3Lines4LineExtrinsicsAnd1OrderExtrinsic();
|
||||||
|
|
||||||
|
/////////////////////////////
|
||||||
|
// assert success function //
|
||||||
|
/////////////////////////////
|
||||||
|
BiConsumer<HttpResponse<String>, Integer> assertOrderCount = (response, expectedCount) ->
|
||||||
|
{
|
||||||
|
assertEquals(200, response.getStatus());
|
||||||
|
JSONObject jsonObject = JsonUtils.toJSONObject(response.getBody());
|
||||||
|
JSONArray records = jsonObject.getJSONArray("records");
|
||||||
|
assertThat(records.length()).isEqualTo(expectedCount);
|
||||||
|
};
|
||||||
|
|
||||||
|
/////////////////////////
|
||||||
|
// assert 400 function //
|
||||||
|
/////////////////////////
|
||||||
|
BiConsumer<HttpResponse<String>, String> assert400 = (response, expectedMessage) ->
|
||||||
|
{
|
||||||
|
assertEquals(400, response.getStatus());
|
||||||
|
JSONObject jsonObject = JsonUtils.toJSONObject(response.getBody());
|
||||||
|
assertEquals(expectedMessage, jsonObject.getString("error"));
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// basic query (with no join filter) should find 1 record //
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
HttpResponse<String> response;
|
||||||
|
response = Unirest.post(getBaseUrlAndPath(TestUtils.API_PATH, TestUtils.V2023_Q1) + "/table/order/query")
|
||||||
|
.body(JsonUtils.toJson(Map.of("filter", new QQueryFilter(new QFilterCriteria("orderNo", QCriteriaOperator.EQUALS, "ORD123")))))
|
||||||
|
.contentType(ContentType.APPLICATION_JSON.getMimeType())
|
||||||
|
.asString();
|
||||||
|
assertOrderCount.accept(response, 1);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
// basic query (with no join filter) that should find 0 records //
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
response = Unirest.post(getBaseUrlAndPath(TestUtils.API_PATH, TestUtils.V2023_Q1) + "/table/order/query")
|
||||||
|
.body(JsonUtils.toJson(Map.of("filter", new QQueryFilter(new QFilterCriteria("orderNo", QCriteriaOperator.EQUALS, "not-found")))))
|
||||||
|
.contentType(ContentType.APPLICATION_JSON.getMimeType())
|
||||||
|
.asString();
|
||||||
|
assertOrderCount.accept(response, 0);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// try to filter by unknown join-table name - should 400 //
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
response = Unirest.post(getBaseUrlAndPath(TestUtils.API_PATH, TestUtils.V2023_Q1) + "/table/order/query")
|
||||||
|
.body(JsonUtils.toJson(Map.of("filter", new QQueryFilter(new QFilterCriteria("noSuchTable.sku", QCriteriaOperator.EQUALS, "BASIC1")))))
|
||||||
|
.contentType(ContentType.APPLICATION_JSON.getMimeType())
|
||||||
|
.asString();
|
||||||
|
assert400.accept(response, "Error processing criteria field: noSuchTable.sku: Unrecognized table name: noSuchTable");
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// try to filter by unknown join field name - should 400 //
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
response = Unirest.post(getBaseUrlAndPath(TestUtils.API_PATH, TestUtils.V2023_Q1) + "/table/order/query")
|
||||||
|
.body(JsonUtils.toJson(Map.of("filter", new QQueryFilter(new QFilterCriteria(TestUtils.TABLE_NAME_LINE_ITEM + ".noSuchField", QCriteriaOperator.EQUALS, "BASIC1")))))
|
||||||
|
.contentType(ContentType.APPLICATION_JSON.getMimeType())
|
||||||
|
.asString();
|
||||||
|
assert400.accept(response, "Unrecognized criteria field name: orderLine.noSuchField.");
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// join for sku - should find (but... memory backend isn't joining correctly at this time... //
|
||||||
|
// so we'll ensure at least http 200, and trust that other backends join correctly... //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
response = Unirest.post(getBaseUrlAndPath(TestUtils.API_PATH, TestUtils.V2023_Q1) + "/table/order/query")
|
||||||
|
.body(JsonUtils.toJson(Map.of("filter", new QQueryFilter(new QFilterCriteria(TestUtils.TABLE_NAME_LINE_ITEM + ".sku", QCriteriaOperator.EQUALS, "BASIC1")))))
|
||||||
|
.contentType(ContentType.APPLICATION_JSON.getMimeType())
|
||||||
|
.asString();
|
||||||
|
assertOrderCount.accept(response, 0); // todo - ideally 1, but memory backend joining...
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Reference in New Issue
Block a user