mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-17 20:50:44 +00:00
Merge branch 'dev' into feature/CTLE-434-oms-update-business-logic
# Conflicts: # qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/MemoryBackendModuleTest.java # qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/backend/javalin/QJavalinImplementation.java
This commit is contained in:
@ -615,34 +615,19 @@ public class QJavalinImplementation
|
||||
updateInput.setTableName(tableName);
|
||||
|
||||
PermissionsHelper.checkTablePermissionThrowing(updateInput, TablePermissionSubType.EDIT);
|
||||
QTableMetaData tableMetaData = qInstance.getTable(table);
|
||||
|
||||
QJavalinAccessLogger.logStart("update", logPair("table", table), logPair("primaryKey", primaryKey));
|
||||
|
||||
List<QRecord> recordList = new ArrayList<>();
|
||||
QRecord record = new QRecord();
|
||||
record.setTableName(tableName);
|
||||
recordList.add(record);
|
||||
|
||||
Map<?, ?> map = context.bodyAsClass(Map.class);
|
||||
for(Map.Entry<?, ?> entry : map.entrySet())
|
||||
{
|
||||
String fieldName = ValueUtils.getValueAsString(entry.getKey());
|
||||
Object value = entry.getValue();
|
||||
record.setValue(tableMetaData.getPrimaryKeyField(), primaryKey);
|
||||
setRecordValuesForInsertOrUpdate(context, tableMetaData, record);
|
||||
updateInput.setRecords(recordList);
|
||||
|
||||
if(StringUtils.hasContent(String.valueOf(value)))
|
||||
{
|
||||
record.setValue(fieldName, (Serializable) value);
|
||||
}
|
||||
else if("".equals(value))
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if frontend sent us an empty string - put a null in the record's value map. //
|
||||
// this could potentially be changed to be type-specific (e.g., store an empty-string for STRING //
|
||||
// fields, but null for INTEGER, etc) - but, who really wants empty-string in database anyway? //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
record.setValue(fieldName, null);
|
||||
}
|
||||
}
|
||||
|
||||
QTableMetaData tableMetaData = qInstance.getTable(tableName);
|
||||
record.setValue(tableMetaData.getPrimaryKeyField(), primaryKey);
|
||||
|
||||
QJavalinAccessLogger.logStart("update", logPair("table", tableName), logPair("primaryKey", primaryKey));
|
||||
@ -674,6 +659,80 @@ public class QJavalinImplementation
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static void setRecordValuesForInsertOrUpdate(Context context, QTableMetaData tableMetaData, QRecord record) throws IOException
|
||||
{
|
||||
String contentType = Objects.requireNonNullElse(context.header("content-type"), "");
|
||||
boolean isContentTypeJson = contentType.toLowerCase().contains("json");
|
||||
|
||||
try
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if the caller said they've sent JSON, or if they didn't supply a content-type, then try to read the body //
|
||||
// as JSON. if it throws, we'll continue by trying to read form params, but if it succeeds, we'll return. //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if(isContentTypeJson || !StringUtils.hasContent(contentType))
|
||||
{
|
||||
Map<?, ?> map = context.bodyAsClass(Map.class);
|
||||
for(Map.Entry<?, ?> entry : map.entrySet())
|
||||
{
|
||||
String fieldName = ValueUtils.getValueAsString(entry.getKey());
|
||||
Object value = entry.getValue();
|
||||
|
||||
if(StringUtils.hasContent(String.valueOf(value)))
|
||||
{
|
||||
record.setValue(fieldName, (Serializable) value);
|
||||
}
|
||||
else if("".equals(value))
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if frontend sent us an empty string - put a null in the record's value map. //
|
||||
// this could potentially be changed to be type-specific (e.g., store an empty-string for STRING //
|
||||
// fields, but null for INTEGER, etc) - but, who really wants empty-string in database anyway? //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
record.setValue(fieldName, null);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
LOG.info("Error trying to read body as map", e, logPair("contentType", contentType));
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
// process form params //
|
||||
/////////////////////////
|
||||
for(Map.Entry<String, List<String>> formParam : context.formParamMap().entrySet())
|
||||
{
|
||||
String fieldName = formParam.getKey();
|
||||
List<String> values = formParam.getValue();
|
||||
if(CollectionUtils.nullSafeHasContents(values))
|
||||
{
|
||||
String value = values.get(0);
|
||||
if(StringUtils.hasContent(value))
|
||||
{
|
||||
record.setValue(fieldName, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
record.setValue(fieldName, null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// is this ever hit?
|
||||
record.setValue(fieldName, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@ -689,20 +748,13 @@ public class QJavalinImplementation
|
||||
QJavalinAccessLogger.logStart("insert", logPair("table", tableName));
|
||||
|
||||
PermissionsHelper.checkTablePermissionThrowing(insertInput, TablePermissionSubType.INSERT);
|
||||
QTableMetaData tableMetaData = qInstance.getTable(tableName);
|
||||
|
||||
List<QRecord> recordList = new ArrayList<>();
|
||||
QRecord record = new QRecord();
|
||||
record.setTableName(tableName);
|
||||
recordList.add(record);
|
||||
|
||||
Map<?, ?> map = context.bodyAsClass(Map.class);
|
||||
for(Map.Entry<?, ?> entry : map.entrySet())
|
||||
{
|
||||
if(StringUtils.hasContent(String.valueOf(entry.getValue())))
|
||||
{
|
||||
record.setValue(String.valueOf(entry.getKey()), (Serializable) entry.getValue());
|
||||
}
|
||||
}
|
||||
setRecordValuesForInsertOrUpdate(context, tableMetaData, record);
|
||||
insertInput.setRecords(recordList);
|
||||
|
||||
InsertAction insertAction = new InsertAction();
|
||||
|
@ -391,11 +391,13 @@ class QJavalinImplementationTest extends QJavalinTestBase
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** test an insert
|
||||
** test an insert - posting the data as a JSON object.
|
||||
**
|
||||
** This was the original supported version, but multipart form was added in May 2023
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_dataInsert()
|
||||
public void test_dataInsertJson()
|
||||
{
|
||||
Map<String, Serializable> body = new HashMap<>();
|
||||
body.put("firstName", "Bobby");
|
||||
@ -425,11 +427,45 @@ class QJavalinImplementationTest extends QJavalinTestBase
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** test an update
|
||||
** test an insert - posting a multipart form.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_dataUpdate()
|
||||
public void test_dataInsertMultipartForm()
|
||||
{
|
||||
HttpResponse<String> response = Unirest.post(BASE_URL + "/data/person")
|
||||
.header("Content-Type", "application/json")
|
||||
.multiPartContent()
|
||||
.field("firstName", "Bobby")
|
||||
.field("lastName", "Hull")
|
||||
.field("email", "bobby@hull.com")
|
||||
.asString();
|
||||
|
||||
assertEquals(200, response.getStatus());
|
||||
JSONObject jsonObject = JsonUtils.toJSONObject(response.getBody());
|
||||
assertTrue(jsonObject.has("records"));
|
||||
JSONArray records = jsonObject.getJSONArray("records");
|
||||
assertEquals(1, records.length());
|
||||
JSONObject record0 = records.getJSONObject(0);
|
||||
assertTrue(record0.has("values"));
|
||||
assertEquals("person", record0.getString("tableName"));
|
||||
JSONObject values0 = record0.getJSONObject("values");
|
||||
assertTrue(values0.has("firstName"));
|
||||
assertEquals("Bobby", values0.getString("firstName"));
|
||||
assertTrue(values0.has("id"));
|
||||
assertEquals(7, values0.getInt("id"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** test an update - posting the data as a JSON object.
|
||||
**
|
||||
** This was the original supported version, but multipart form was added in May 2023
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_dataUpdateJson()
|
||||
{
|
||||
Map<String, Serializable> body = new HashMap<>();
|
||||
body.put("firstName", "Free");
|
||||
@ -465,6 +501,44 @@ class QJavalinImplementationTest extends QJavalinTestBase
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** test an update - posting the data as a multipart form
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void test_dataUpdateMultipartForm()
|
||||
{
|
||||
HttpResponse<String> response = Unirest.patch(BASE_URL + "/data/person/4")
|
||||
.multiPartContent()
|
||||
.field("firstName", "Free")
|
||||
.field("birthDate", "")
|
||||
.asString();
|
||||
|
||||
assertEquals(200, response.getStatus());
|
||||
JSONObject jsonObject = JsonUtils.toJSONObject(response.getBody());
|
||||
assertTrue(jsonObject.has("records"));
|
||||
JSONArray records = jsonObject.getJSONArray("records");
|
||||
assertEquals(1, records.length());
|
||||
JSONObject record0 = records.getJSONObject(0);
|
||||
assertTrue(record0.has("values"));
|
||||
assertEquals("person", record0.getString("tableName"));
|
||||
JSONObject values0 = record0.getJSONObject("values");
|
||||
assertEquals(4, values0.getInt("id"));
|
||||
assertEquals("Free", values0.getString("firstName"));
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// re-GET the record, and validate that birthDate was nulled out //
|
||||
///////////////////////////////////////////////////////////////////
|
||||
response = Unirest.get(BASE_URL + "/data/person/4").asString();
|
||||
assertEquals(200, response.getStatus());
|
||||
jsonObject = JsonUtils.toJSONObject(response.getBody());
|
||||
assertTrue(jsonObject.has("values"));
|
||||
JSONObject values = jsonObject.getJSONObject("values");
|
||||
assertFalse(values.has("birthDate"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** test a delete
|
||||
**
|
||||
|
Reference in New Issue
Block a user