Convert QRecord errors and warnings to new QStatusMessage type hierarchy.

This commit is contained in:
2023-05-09 08:49:46 -05:00
parent 647c5968d3
commit b2c7062709
28 changed files with 555 additions and 130 deletions

View File

@ -23,6 +23,7 @@ package com.kingsrook.qqq.backend.core.actions.customizers;
import java.util.List; import java.util.List;
import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput; import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
import com.kingsrook.qqq.backend.core.model.data.QRecord; import com.kingsrook.qqq.backend.core.model.data.QRecord;
@ -50,7 +51,7 @@ public abstract class AbstractPreInsertCustomizer
/******************************************************************************* /*******************************************************************************
** **
*******************************************************************************/ *******************************************************************************/
public abstract List<QRecord> apply(List<QRecord> records); public abstract List<QRecord> apply(List<QRecord> records) throws QException;

View File

@ -34,6 +34,8 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertOutput;
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput; 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.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.statusmessages.QStatusMessage;
import com.kingsrook.qqq.backend.core.model.statusmessages.QWarningMessage;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
@ -142,9 +144,9 @@ public abstract class ChildInserterPostInsertCustomizer extends AbstractPostInse
QRecord childRecord = insertedRecordIterator.next(); QRecord childRecord = insertedRecordIterator.next();
if(CollectionUtils.nullSafeHasContents(childRecord.getErrors())) if(CollectionUtils.nullSafeHasContents(childRecord.getErrors()))
{ {
for(String childWarning : childRecord.getErrors()) for(QStatusMessage error : childRecord.getErrors())
{ {
record.addWarning("Error creating child " + childTable.getLabel() + " (" + childWarning + ")"); record.addWarning(new QWarningMessage("Error creating child " + childTable.getLabel() + " (" + error.toString() + ")"));
} }
rs.add(record); rs.add(record);
continue; continue;

View File

@ -54,6 +54,8 @@ import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.joins.QJoinMetaData; import com.kingsrook.qqq.backend.core.model.metadata.joins.QJoinMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.tables.Association; import com.kingsrook.qqq.backend.core.model.metadata.tables.Association;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.statusmessages.NotFoundStatusMessage;
import com.kingsrook.qqq.backend.core.model.statusmessages.QWarningMessage;
import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleDispatcher; import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleDispatcher;
import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleInterface; import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleInterface;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
@ -68,8 +70,6 @@ public class DeleteAction
{ {
private static final QLogger LOG = QLogger.getLogger(DeleteAction.class); private static final QLogger LOG = QLogger.getLogger(DeleteAction.class);
public static final String NOT_FOUND_ERROR_PREFIX = "No record was found to delete";
/******************************************************************************* /*******************************************************************************
@ -238,7 +238,7 @@ public class DeleteAction
{ {
for(QRecord record : recordsForCustomizer) for(QRecord record : recordsForCustomizer)
{ {
record.addWarning("An error occurred after the delete: " + e.getMessage()); record.addWarning(new QWarningMessage("An error occurred after the delete: " + e.getMessage()));
outputRecordsWithWarnings.add(record); outputRecordsWithWarnings.add(record);
} }
} }
@ -400,7 +400,7 @@ public class DeleteAction
QRecord recordWithError = new QRecord(); QRecord recordWithError = new QRecord();
recordsWithErrors.add(recordWithError); recordsWithErrors.add(recordWithError);
recordWithError.setValue(primaryKeyField.getName(), primaryKeyValue); recordWithError.setValue(primaryKeyField.getName(), primaryKeyValue);
recordWithError.addError(NOT_FOUND_ERROR_PREFIX + " for " + primaryKeyField.getLabel() + " = " + primaryKeyValue); recordWithError.addError(new NotFoundStatusMessage("No record was found to delete for " + primaryKeyField.getLabel() + " = " + primaryKeyValue));
primaryKeysToRemoveFromInput.add(primaryKeyValue); primaryKeysToRemoveFromInput.add(primaryKeyValue);
} }
} }

View File

@ -58,6 +58,8 @@ import com.kingsrook.qqq.backend.core.model.metadata.joins.QJoinMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.tables.Association; import com.kingsrook.qqq.backend.core.model.metadata.tables.Association;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.tables.UniqueKey; import com.kingsrook.qqq.backend.core.model.metadata.tables.UniqueKey;
import com.kingsrook.qqq.backend.core.model.statusmessages.BadInputStatusMessage;
import com.kingsrook.qqq.backend.core.model.statusmessages.QWarningMessage;
import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleDispatcher; import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleDispatcher;
import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleInterface; import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleInterface;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
@ -122,7 +124,7 @@ public class InsertAction extends AbstractQActionFunction<InsertInput, InsertOut
////////////////////////////// //////////////////////////////
// log if there were errors // // log if there were errors //
////////////////////////////// //////////////////////////////
List<String> errors = insertOutput.getRecords().stream().flatMap(r -> r.getErrors().stream()).toList(); List<String> errors = insertOutput.getRecords().stream().flatMap(r -> r.getErrors().stream().map(Object::toString)).toList();
if(CollectionUtils.nullSafeHasContents(errors)) if(CollectionUtils.nullSafeHasContents(errors))
{ {
LOG.warn("Errors in insertAction", logPair("tableName", table.getName()), logPair("errorCount", errors.size()), errors.size() < 10 ? logPair("errors", errors) : logPair("first10Errors", errors.subList(0, 10))); LOG.warn("Errors in insertAction", logPair("tableName", table.getName()), logPair("errorCount", errors.size()), errors.size() < 10 ? logPair("errors", errors) : logPair("first10Errors", errors.subList(0, 10)));
@ -160,7 +162,7 @@ public class InsertAction extends AbstractQActionFunction<InsertInput, InsertOut
{ {
for(QRecord record : insertOutput.getRecords()) for(QRecord record : insertOutput.getRecords())
{ {
record.addWarning("An error occurred after the insert: " + e.getMessage()); record.addWarning(new QWarningMessage("An error occurred after the insert: " + e.getMessage()));
} }
} }
} }
@ -188,7 +190,7 @@ public class InsertAction extends AbstractQActionFunction<InsertInput, InsertOut
{ {
if(record.getValue(requiredField.getName()) == null || (requiredField.getType().isStringLike() && record.getValueString(requiredField.getName()).trim().equals(""))) if(record.getValue(requiredField.getName()) == null || (requiredField.getType().isStringLike() && record.getValueString(requiredField.getName()).trim().equals("")))
{ {
record.addError("Missing value in required field: " + requiredField.getLabel()); record.addError(new BadInputStatusMessage("Missing value in required field: " + requiredField.getLabel()));
} }
} }
} }
@ -274,7 +276,7 @@ public class InsertAction extends AbstractQActionFunction<InsertInput, InsertOut
Optional<List<Serializable>> keyValues = UniqueKeyHelper.getKeyValues(table, uniqueKey, record); Optional<List<Serializable>> keyValues = UniqueKeyHelper.getKeyValues(table, uniqueKey, record);
if(keyValues.isPresent() && (existingKeys.get(uniqueKey).contains(keyValues.get()) || keysInThisList.get(uniqueKey).contains(keyValues.get()))) if(keyValues.isPresent() && (existingKeys.get(uniqueKey).contains(keyValues.get()) || keysInThisList.get(uniqueKey).contains(keyValues.get())))
{ {
record.addError("Another record already exists with this " + uniqueKey.getDescription(table)); record.addError(new BadInputStatusMessage("Another record already exists with this " + uniqueKey.getDescription(table)));
foundDupe = true; foundDupe = true;
break; break;
} }

View File

@ -62,6 +62,9 @@ import com.kingsrook.qqq.backend.core.model.metadata.joins.JoinOn;
import com.kingsrook.qqq.backend.core.model.metadata.joins.QJoinMetaData; import com.kingsrook.qqq.backend.core.model.metadata.joins.QJoinMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.tables.Association; import com.kingsrook.qqq.backend.core.model.metadata.tables.Association;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.statusmessages.BadInputStatusMessage;
import com.kingsrook.qqq.backend.core.model.statusmessages.NotFoundStatusMessage;
import com.kingsrook.qqq.backend.core.model.statusmessages.QWarningMessage;
import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleDispatcher; import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleDispatcher;
import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleInterface; import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleInterface;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
@ -77,8 +80,6 @@ public class UpdateAction
{ {
private static final QLogger LOG = QLogger.getLogger(UpdateAction.class); private static final QLogger LOG = QLogger.getLogger(UpdateAction.class);
public static final String NOT_FOUND_ERROR_PREFIX = "No record was found to update";
/******************************************************************************* /*******************************************************************************
@ -137,7 +138,7 @@ public class UpdateAction
////////////////////////////// //////////////////////////////
// log if there were errors // // log if there were errors //
////////////////////////////// //////////////////////////////
List<String> errors = updateOutput.getRecords().stream().flatMap(r -> r.getErrors().stream()).toList(); List<String> errors = updateOutput.getRecords().stream().flatMap(r -> r.getErrors().stream().map(Object::toString)).toList();
if(CollectionUtils.nullSafeHasContents(errors)) if(CollectionUtils.nullSafeHasContents(errors))
{ {
LOG.warn("Errors in updateAction", logPair("tableName", updateInput.getTableName()), logPair("errorCount", errors.size()), errors.size() < 10 ? logPair("errors", errors) : logPair("first10Errors", errors.subList(0, 10))); LOG.warn("Errors in updateAction", logPair("tableName", updateInput.getTableName()), logPair("errorCount", errors.size()), errors.size() < 10 ? logPair("errors", errors) : logPair("first10Errors", errors.subList(0, 10)));
@ -180,7 +181,7 @@ public class UpdateAction
{ {
for(QRecord record : updateOutput.getRecords()) for(QRecord record : updateOutput.getRecords())
{ {
record.addWarning("An error occurred after the update: " + e.getMessage()); record.addWarning(new QWarningMessage("An error occurred after the update: " + e.getMessage()));
} }
} }
} }
@ -228,7 +229,7 @@ public class UpdateAction
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if(record.getValue(table.getPrimaryKeyField()) == null) if(record.getValue(table.getPrimaryKeyField()) == null)
{ {
record.addError("Missing value in primary key field"); record.addError(new BadInputStatusMessage("Missing value in primary key field"));
} }
} }
} }
@ -288,7 +289,7 @@ public class UpdateAction
if(!lookedUpRecords.containsKey(value)) if(!lookedUpRecords.containsKey(value))
{ {
record.addError(NOT_FOUND_ERROR_PREFIX + " for " + primaryKeyField.getLabel() + " = " + value); record.addError(new NotFoundStatusMessage("No record was found to update for " + primaryKeyField.getLabel() + " = " + value));
} }
} }
} }
@ -319,7 +320,7 @@ public class UpdateAction
{ {
if(record.getValue(requiredField.getName()) == null || (requiredField.getType().isStringLike() && record.getValueString(requiredField.getName()).trim().equals(""))) if(record.getValue(requiredField.getName()) == null || (requiredField.getType().isStringLike() && record.getValueString(requiredField.getName()).trim().equals("")))
{ {
record.addError("Missing value in required field: " + requiredField.getLabel()); record.addError(new BadInputStatusMessage("Missing value in required field: " + requiredField.getLabel()));
} }
} }
} }

View File

@ -45,6 +45,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.joins.QJoinMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.security.QSecurityKeyType; import com.kingsrook.qqq.backend.core.model.metadata.security.QSecurityKeyType;
import com.kingsrook.qqq.backend.core.model.metadata.security.RecordSecurityLock; import com.kingsrook.qqq.backend.core.model.metadata.security.RecordSecurityLock;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.statusmessages.PermissionDeniedMessage;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
import com.kingsrook.qqq.backend.core.utils.ListingHash; import com.kingsrook.qqq.backend.core.utils.ListingHash;
import com.kingsrook.qqq.backend.core.utils.StringUtils; import com.kingsrook.qqq.backend.core.utils.StringUtils;
@ -225,7 +226,7 @@ public class ValidateRecordSecurityLockHelper
{ {
if(RecordSecurityLock.NullValueBehavior.DENY.equals(recordSecurityLock.getNullValueBehavior())) if(RecordSecurityLock.NullValueBehavior.DENY.equals(recordSecurityLock.getNullValueBehavior()))
{ {
inputRecord.addError("You do not have permission to " + action.name().toLowerCase() + " this record - the referenced " + leftMostJoinTable.getLabel() + " was not found."); inputRecord.addError(new PermissionDeniedMessage("You do not have permission to " + action.name().toLowerCase() + " this record - the referenced " + leftMostJoinTable.getLabel() + " was not found."));
} }
} }
} }
@ -287,7 +288,7 @@ public class ValidateRecordSecurityLockHelper
if(RecordSecurityLock.NullValueBehavior.DENY.equals(recordSecurityLock.getNullValueBehavior())) if(RecordSecurityLock.NullValueBehavior.DENY.equals(recordSecurityLock.getNullValueBehavior()))
{ {
String lockLabel = CollectionUtils.nullSafeHasContents(recordSecurityLock.getJoinNameChain()) ? recordSecurityLock.getSecurityKeyType() : table.getField(recordSecurityLock.getFieldName()).getLabel(); String lockLabel = CollectionUtils.nullSafeHasContents(recordSecurityLock.getJoinNameChain()) ? recordSecurityLock.getSecurityKeyType() : table.getField(recordSecurityLock.getFieldName()).getLabel();
record.addError("You do not have permission to " + action.name().toLowerCase() + " a record without a value in the field: " + lockLabel); record.addError(new PermissionDeniedMessage("You do not have permission to " + action.name().toLowerCase() + " a record without a value in the field: " + lockLabel));
} }
} }
else else
@ -299,12 +300,12 @@ public class ValidateRecordSecurityLockHelper
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
// avoid telling the user a value from a foreign record that they didn't pass in themselves. // // avoid telling the user a value from a foreign record that they didn't pass in themselves. //
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
record.addError("You do not have permission to " + action.name().toLowerCase() + " this record."); record.addError(new PermissionDeniedMessage("You do not have permission to " + action.name().toLowerCase() + " this record."));
} }
else else
{ {
QFieldMetaData field = table.getField(recordSecurityLock.getFieldName()); QFieldMetaData field = table.getField(recordSecurityLock.getFieldName());
record.addError("You do not have permission to " + action.name().toLowerCase() + " a record with a value of " + recordSecurityValue + " in the field: " + field.getLabel()); record.addError(new PermissionDeniedMessage("You do not have permission to " + action.name().toLowerCase() + " a record with a value of " + recordSecurityValue + " in the field: " + field.getLabel()));
} }
} }
} }

View File

@ -29,6 +29,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType; import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
import com.kingsrook.qqq.backend.core.model.metadata.fields.ValueTooLongBehavior; import com.kingsrook.qqq.backend.core.model.metadata.fields.ValueTooLongBehavior;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.statusmessages.BadInputStatusMessage;
import com.kingsrook.qqq.backend.core.utils.StringUtils; import com.kingsrook.qqq.backend.core.utils.StringUtils;
@ -76,7 +77,7 @@ public class ValueBehaviorApplier
{ {
case TRUNCATE -> record.setValue(fieldName, StringUtils.safeTruncate(value, field.getMaxLength())); case TRUNCATE -> record.setValue(fieldName, StringUtils.safeTruncate(value, field.getMaxLength()));
case TRUNCATE_ELLIPSIS -> record.setValue(fieldName, StringUtils.safeTruncate(value, field.getMaxLength(), "...")); case TRUNCATE_ELLIPSIS -> record.setValue(fieldName, StringUtils.safeTruncate(value, field.getMaxLength(), "..."));
case ERROR -> record.addError("The value for " + field.getLabel() + " is too long (max allowed length=" + field.getMaxLength() + ")"); case ERROR -> record.addError(new BadInputStatusMessage("The value for " + field.getLabel() + " is too long (max allowed length=" + field.getMaxLength() + ")"));
case PASS_THROUGH -> case PASS_THROUGH ->
{ {
} }

View File

@ -35,6 +35,8 @@ import java.util.Map;
import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData; 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.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.statusmessages.QErrorMessage;
import com.kingsrook.qqq.backend.core.model.statusmessages.QWarningMessage;
import com.kingsrook.qqq.backend.core.utils.ValueUtils; import com.kingsrook.qqq.backend.core.utils.ValueUtils;
import org.apache.commons.lang.SerializationUtils; import org.apache.commons.lang.SerializationUtils;
@ -54,7 +56,8 @@ import org.apache.commons.lang.SerializationUtils;
** **
** Errors are meant to hold information about things that went wrong when ** Errors are meant to hold information about things that went wrong when
** processing a record - e.g., in a list of records that may be the output of an ** processing a record - e.g., in a list of records that may be the output of an
** action, like a bulk load. TODO - redo as some status object? ** action, like a bulk load. Warnings play a similar role, but are just advice
** - they don't mean that the action was failed, just something you may need to know.
*******************************************************************************/ *******************************************************************************/
public class QRecord implements Serializable public class QRecord implements Serializable
{ {
@ -64,8 +67,9 @@ public class QRecord implements Serializable
private Map<String, Serializable> values = new LinkedHashMap<>(); private Map<String, Serializable> values = new LinkedHashMap<>();
private Map<String, String> displayValues = new LinkedHashMap<>(); private Map<String, String> displayValues = new LinkedHashMap<>();
private Map<String, Serializable> backendDetails = new LinkedHashMap<>(); private Map<String, Serializable> backendDetails = new LinkedHashMap<>();
private List<String> errors = new ArrayList<>();
private List<String> warnings = new ArrayList<>(); private List<QErrorMessage> errors = new ArrayList<>();
private List<QWarningMessage> warnings = new ArrayList<>();
private Map<String, List<QRecord>> associatedRecords = new HashMap<>(); private Map<String, List<QRecord>> associatedRecords = new HashMap<>();
@ -106,6 +110,7 @@ public class QRecord implements Serializable
this.displayValues = doDeepCopy(record.displayValues); this.displayValues = doDeepCopy(record.displayValues);
this.backendDetails = doDeepCopy(record.backendDetails); this.backendDetails = doDeepCopy(record.backendDetails);
this.errors = doDeepCopy(record.errors); this.errors = doDeepCopy(record.errors);
this.warnings = doDeepCopy(record.warnings);
this.associatedRecords = doDeepCopy(record.associatedRecords); this.associatedRecords = doDeepCopy(record.associatedRecords);
} }
@ -123,7 +128,7 @@ public class QRecord implements Serializable
/******************************************************************************* /*******************************************************************************
** ** todo - move to a cloning utils maybe?
*******************************************************************************/ *******************************************************************************/
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
private <K, V> Map<K, V> doDeepCopy(Map<K, V> map) private <K, V> Map<K, V> doDeepCopy(Map<K, V> map)
@ -144,7 +149,7 @@ public class QRecord implements Serializable
/******************************************************************************* /*******************************************************************************
** ** todo - move to a cloning utils maybe?
*******************************************************************************/ *******************************************************************************/
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
private <T> List<T> doDeepCopy(List<T> list) private <T> List<T> doDeepCopy(List<T> list)
@ -542,7 +547,7 @@ public class QRecord implements Serializable
** Getter for errors ** Getter for errors
** **
*******************************************************************************/ *******************************************************************************/
public List<String> getErrors() public List<QErrorMessage> getErrors()
{ {
return (errors); return (errors);
} }
@ -553,7 +558,7 @@ public class QRecord implements Serializable
** Setter for errors ** Setter for errors
** **
*******************************************************************************/ *******************************************************************************/
public void setErrors(List<String> errors) public void setErrors(List<QErrorMessage> errors)
{ {
this.errors = errors; this.errors = errors;
} }
@ -564,7 +569,7 @@ public class QRecord implements Serializable
** Add one error to this record ** Add one error to this record
** **
*******************************************************************************/ *******************************************************************************/
public void addError(String error) public void addError(QErrorMessage error)
{ {
this.errors.add(error); this.errors.add(error);
} }
@ -575,7 +580,7 @@ public class QRecord implements Serializable
** Fluently Add one error to this record ** Fluently Add one error to this record
** **
*******************************************************************************/ *******************************************************************************/
public QRecord withError(String error) public QRecord withError(QErrorMessage error)
{ {
addError(error); addError(error);
return (this); return (this);
@ -658,7 +663,7 @@ public class QRecord implements Serializable
/******************************************************************************* /*******************************************************************************
** Getter for warnings ** Getter for warnings
*******************************************************************************/ *******************************************************************************/
public List<String> getWarnings() public List<QWarningMessage> getWarnings()
{ {
return (this.warnings); return (this.warnings);
} }
@ -668,7 +673,7 @@ public class QRecord implements Serializable
/******************************************************************************* /*******************************************************************************
** Setter for warnings ** Setter for warnings
*******************************************************************************/ *******************************************************************************/
public void setWarnings(List<String> warnings) public void setWarnings(List<QWarningMessage> warnings)
{ {
this.warnings = warnings; this.warnings = warnings;
} }
@ -678,7 +683,7 @@ public class QRecord implements Serializable
/******************************************************************************* /*******************************************************************************
** Fluent setter for warnings ** Fluent setter for warnings
*******************************************************************************/ *******************************************************************************/
public QRecord withWarnings(List<String> warnings) public QRecord withWarnings(List<QWarningMessage> warnings)
{ {
this.warnings = warnings; this.warnings = warnings;
return (this); return (this);
@ -690,7 +695,7 @@ public class QRecord implements Serializable
** Add one warning to this record ** Add one warning to this record
** **
*******************************************************************************/ *******************************************************************************/
public void addWarning(String warning) public void addWarning(QWarningMessage warning)
{ {
this.warnings.add(warning); this.warnings.add(warning);
} }

View File

@ -0,0 +1,41 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.kingsrook.qqq.backend.core.model.statusmessages;
/*******************************************************************************
** Record error message for when some bad input caused the issue (e.g., a missing
** value, or an illegal value). e.g., http 400 style.
*******************************************************************************/
public class BadInputStatusMessage extends QErrorMessage
{
/*******************************************************************************
** Constructor
**
*******************************************************************************/
public BadInputStatusMessage(String message)
{
super(message);
}
}

View File

@ -0,0 +1,41 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.kingsrook.qqq.backend.core.model.statusmessages;
/*******************************************************************************
** Record error message for when something couldn't be found (e.g., a request
** to update a record, but it isn't in the backend).
*******************************************************************************/
public class NotFoundStatusMessage extends QErrorMessage
{
/*******************************************************************************
** Constructor
**
*******************************************************************************/
public NotFoundStatusMessage(String message)
{
super(message);
}
}

View File

@ -0,0 +1,41 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.kingsrook.qqq.backend.core.model.statusmessages;
/*******************************************************************************
** Record error message for when the user didn't have permission to do what they
** were trying.
*******************************************************************************/
public class PermissionDeniedMessage extends QErrorMessage
{
/*******************************************************************************
** Constructor
**
******************************************************************************/
public PermissionDeniedMessage(String message)
{
super(message);
}
}

View File

@ -0,0 +1,46 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.kingsrook.qqq.backend.core.model.statusmessages;
/*******************************************************************************
** Abstract base class for all errors to be attached to QRecords.
**
** Framework is aware of a few specific sultypes here, that drive things like
** returning http 400 vs 500.
**
** Applications can define further subtypes (recommended to subclass this class's
** children, rather than this class), to help give (type-based) definition to errors.
*******************************************************************************/
public abstract class QErrorMessage extends QStatusMessage
{
/*******************************************************************************
** Constructor
**
*******************************************************************************/
public QErrorMessage(String message)
{
super(message);
}
}

View File

@ -0,0 +1,74 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.kingsrook.qqq.backend.core.model.statusmessages;
import java.io.Serializable;
/*******************************************************************************
** Abstract Base class for status messages (errors or warnings) that can be
** attached to QRecords.
**
** They look like exceptions, but they aren't throwable, and they are meant
** to just be put in a record's error or warning list. Those lists were originally
** just Strings, but we wanted to have some type information communicated with
** them, e.g., for marking an error as caused by bad-data (e.g., from a user, e.g.,
** for an HTTP 400) vs. a server-side error, etc.
*******************************************************************************/
public abstract class QStatusMessage implements Serializable
{
private String message;
/*******************************************************************************
** Constructor
**
*******************************************************************************/
public QStatusMessage(String message)
{
this.message = message;
}
/*******************************************************************************
** Getter for message
**
*******************************************************************************/
public String getMessage()
{
return message;
}
/*******************************************************************************
**
*******************************************************************************/
@Override
public String toString()
{
return (message);
}
}

View File

@ -0,0 +1,43 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.kingsrook.qqq.backend.core.model.statusmessages;
/*******************************************************************************
** Class to wrap warning messages to attach to QRecords.
**
** Applications can define subtypes as needed, to help give (type-based)
** definition to warnings.
*******************************************************************************/
public class QWarningMessage extends QStatusMessage
{
/*******************************************************************************
** Constructor
**
*******************************************************************************/
public QWarningMessage(String message)
{
super(message);
}
}

View File

@ -0,0 +1,41 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.kingsrook.qqq.backend.core.model.statusmessages;
/*******************************************************************************
** Record error message for when the system was at fault - not the user. e.g.,
** http 500 style.
*******************************************************************************/
public class SystemErrorStatusMessage extends QErrorMessage
{
/*******************************************************************************
** Constructor
**
*******************************************************************************/
public SystemErrorStatusMessage(String message)
{
super(message);
}
}

View File

@ -35,6 +35,7 @@ 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.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.statusmessages.QWarningMessage;
import com.kingsrook.qqq.backend.core.utils.TestUtils; import com.kingsrook.qqq.backend.core.utils.TestUtils;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
@ -74,7 +75,7 @@ class AbstractPostDeleteCustomizerTest extends BaseTest
assertEquals(1, deleteOutput.getRecordsWithWarnings().size()); assertEquals(1, deleteOutput.getRecordsWithWarnings().size());
assertEquals(1, deleteOutput.getRecordsWithWarnings().get(0).getValue("id")); assertEquals(1, deleteOutput.getRecordsWithWarnings().get(0).getValue("id"));
assertEquals(2, deleteOutput.getDeletedRecordCount()); assertEquals(2, deleteOutput.getDeletedRecordCount());
assertEquals("You shouldn't have deleted Homer...", deleteOutput.getRecordsWithWarnings().get(0).getWarnings().get(0)); assertEquals("You shouldn't have deleted Homer...", deleteOutput.getRecordsWithWarnings().get(0).getWarnings().get(0).getMessage());
GetInput getInput = new GetInput(); GetInput getInput = new GetInput();
getInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY); getInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
@ -107,7 +108,7 @@ class AbstractPostDeleteCustomizerTest extends BaseTest
{ {
if(record.getValue("firstName").equals("Homer")) if(record.getValue("firstName").equals("Homer"))
{ {
record.addWarning("You shouldn't have deleted Homer..."); record.addWarning(new QWarningMessage("You shouldn't have deleted Homer..."));
} }
} }

View File

@ -42,6 +42,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData; import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType; import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.statusmessages.QWarningMessage;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
import com.kingsrook.qqq.backend.core.utils.TestUtils; import com.kingsrook.qqq.backend.core.utils.TestUtils;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -110,7 +111,7 @@ class AbstractPostUpdateCustomizerTest extends BaseTest
updateInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("firstName", "Warning"))); updateInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("firstName", "Warning")));
UpdateOutput updateOutput = new UpdateAction().execute(updateInput); UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
assertTrue(CollectionUtils.nullSafeIsEmpty(updateOutput.getRecords().get(0).getErrors())); assertTrue(CollectionUtils.nullSafeIsEmpty(updateOutput.getRecords().get(0).getErrors()));
assertTrue(updateOutput.getRecords().get(0).getWarnings().stream().anyMatch(s -> s.contains("updated to a warning value"))); assertTrue(updateOutput.getRecords().get(0).getWarnings().stream().anyMatch(s -> s.getMessage().contains("updated to a warning value")));
GetInput getInput = new GetInput(); GetInput getInput = new GetInput();
getInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY); getInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
@ -128,7 +129,7 @@ class AbstractPostUpdateCustomizerTest extends BaseTest
updateInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("firstName", "throw"))); updateInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("firstName", "throw")));
UpdateOutput updateOutput = new UpdateAction().execute(updateInput); UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
assertTrue(CollectionUtils.nullSafeIsEmpty(updateOutput.getRecords().get(0).getErrors())); assertTrue(CollectionUtils.nullSafeIsEmpty(updateOutput.getRecords().get(0).getErrors()));
assertTrue(updateOutput.getRecords().get(0).getWarnings().stream().anyMatch(s -> s.contains("Forced Exception"))); assertTrue(updateOutput.getRecords().get(0).getWarnings().stream().anyMatch(s -> s.getMessage().contains("Forced Exception")));
GetInput getInput = new GetInput(); GetInput getInput = new GetInput();
getInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY); getInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
@ -178,7 +179,7 @@ class AbstractPostUpdateCustomizerTest extends BaseTest
if("warning".equalsIgnoreCase(record.getValueString("firstName"))) if("warning".equalsIgnoreCase(record.getValueString("firstName")))
{ {
record.addWarning("Record was updated to a warning value"); record.addWarning(new QWarningMessage("Record was updated to a warning value"));
} }
if("throw".equalsIgnoreCase(record.getValueString("firstName"))) if("throw".equalsIgnoreCase(record.getValueString("firstName")))

View File

@ -35,6 +35,8 @@ 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.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.statusmessages.BadInputStatusMessage;
import com.kingsrook.qqq.backend.core.model.statusmessages.QWarningMessage;
import com.kingsrook.qqq.backend.core.utils.TestUtils; import com.kingsrook.qqq.backend.core.utils.TestUtils;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
@ -74,7 +76,7 @@ class AbstractPreDeleteCustomizerTest extends BaseTest
assertEquals(0, deleteOutput.getRecordsWithWarnings().size()); assertEquals(0, deleteOutput.getRecordsWithWarnings().size());
assertEquals(1, deleteOutput.getRecordsWithErrors().get(0).getValue("id")); assertEquals(1, deleteOutput.getRecordsWithErrors().get(0).getValue("id"));
assertEquals(1, deleteOutput.getDeletedRecordCount()); assertEquals(1, deleteOutput.getDeletedRecordCount());
assertEquals("You may not delete a Homer.", deleteOutput.getRecordsWithErrors().get(0).getErrors().get(0)); assertEquals("You may not delete a Homer.", deleteOutput.getRecordsWithErrors().get(0).getErrors().get(0).getMessage());
GetInput getInput = new GetInput(); GetInput getInput = new GetInput();
getInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY); getInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
@ -99,7 +101,7 @@ class AbstractPreDeleteCustomizerTest extends BaseTest
assertEquals(1, deleteOutput.getRecordsWithWarnings().size()); assertEquals(1, deleteOutput.getRecordsWithWarnings().size());
assertEquals(3, deleteOutput.getRecordsWithWarnings().get(0).getValue("id")); assertEquals(3, deleteOutput.getRecordsWithWarnings().get(0).getValue("id"));
assertEquals(1, deleteOutput.getDeletedRecordCount()); assertEquals(1, deleteOutput.getDeletedRecordCount());
assertEquals("It was a bad idea to delete Bart", deleteOutput.getRecordsWithWarnings().get(0).getWarnings().get(0)); assertEquals("It was a bad idea to delete Bart", deleteOutput.getRecordsWithWarnings().get(0).getWarnings().get(0).getMessage());
GetInput getInput = new GetInput(); GetInput getInput = new GetInput();
getInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY); getInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
@ -127,11 +129,11 @@ class AbstractPreDeleteCustomizerTest extends BaseTest
{ {
if(record.getValue("firstName").equals("Homer")) if(record.getValue("firstName").equals("Homer"))
{ {
record.addError("You may not delete a Homer."); record.addError(new BadInputStatusMessage("You may not delete a Homer."));
} }
else if(record.getValue("firstName").equals("Bart")) else if(record.getValue("firstName").equals("Bart"))
{ {
record.addWarning("It was a bad idea to delete Bart"); record.addWarning(new QWarningMessage("It was a bad idea to delete Bart"));
} }
} }

View File

@ -35,6 +35,7 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateOutput;
import com.kingsrook.qqq.backend.core.model.data.QRecord; import com.kingsrook.qqq.backend.core.model.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.statusmessages.BadInputStatusMessage;
import com.kingsrook.qqq.backend.core.utils.TestUtils; import com.kingsrook.qqq.backend.core.utils.TestUtils;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
@ -70,7 +71,7 @@ class AbstractPreUpdateCustomizerTest extends BaseTest
updateInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY); updateInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
updateInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("firstName", "--"))); updateInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("firstName", "--")));
UpdateOutput updateOutput = new UpdateAction().execute(updateInput); UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
assertTrue(updateOutput.getRecords().get(0).getErrors().stream().anyMatch(s -> s.contains("must contain at least one letter"))); assertTrue(updateOutput.getRecords().get(0).getErrors().stream().anyMatch(s -> s.getMessage().contains("must contain at least one letter")));
GetInput getInput = new GetInput(); GetInput getInput = new GetInput();
getInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY); getInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
@ -146,7 +147,7 @@ class AbstractPreUpdateCustomizerTest extends BaseTest
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
if(!record.getValueString("firstName").matches(".*\\w.*")) if(!record.getValueString("firstName").matches(".*\\w.*"))
{ {
record.addError("First name must contain at least one letter."); record.addError(new BadInputStatusMessage("First name must contain at least one letter."));
} }
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////

View File

@ -76,7 +76,7 @@ class DeleteActionTest extends BaseTest
assertEquals(1, result.getDeletedRecordCount()); assertEquals(1, result.getDeletedRecordCount());
assertEquals(1, result.getRecordsWithErrors().size()); assertEquals(1, result.getRecordsWithErrors().size());
assertEquals(2, result.getRecordsWithErrors().get(0).getValueInteger("id")); assertEquals(2, result.getRecordsWithErrors().get(0).getValueInteger("id"));
assertEquals("No record was found to delete for Id = 2", result.getRecordsWithErrors().get(0).getErrors().get(0)); assertEquals("No record was found to delete for Id = 2", result.getRecordsWithErrors().get(0).getErrors().get(0).getMessage());
} }
@ -331,28 +331,28 @@ class DeleteActionTest extends BaseTest
DeleteOutput deleteOutput = new DeleteAction().execute(deleteInput); DeleteOutput deleteOutput = new DeleteAction().execute(deleteInput);
assertEquals(0, deleteOutput.getDeletedRecordCount()); assertEquals(0, deleteOutput.getDeletedRecordCount());
assertEquals(1, deleteOutput.getRecordsWithErrors().size()); assertEquals(1, deleteOutput.getRecordsWithErrors().size());
assertEquals("No record was found to delete for Id = 1", deleteOutput.getRecordsWithErrors().get(0).getErrors().get(0)); assertEquals("No record was found to delete for Id = 1", deleteOutput.getRecordsWithErrors().get(0).getErrors().get(0).getMessage());
deleteInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM); deleteInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM);
deleteInput.setPrimaryKeys(List.of(1)); deleteInput.setPrimaryKeys(List.of(1));
deleteOutput = new DeleteAction().execute(deleteInput); deleteOutput = new DeleteAction().execute(deleteInput);
assertEquals(0, deleteOutput.getDeletedRecordCount()); assertEquals(0, deleteOutput.getDeletedRecordCount());
assertEquals(1, deleteOutput.getRecordsWithErrors().size()); assertEquals(1, deleteOutput.getRecordsWithErrors().size());
assertEquals("No record was found to delete for Id = 1", deleteOutput.getRecordsWithErrors().get(0).getErrors().get(0)); assertEquals("No record was found to delete for Id = 1", deleteOutput.getRecordsWithErrors().get(0).getErrors().get(0).getMessage());
deleteInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC); deleteInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC);
deleteInput.setPrimaryKeys(List.of(1)); deleteInput.setPrimaryKeys(List.of(1));
deleteOutput = new DeleteAction().execute(deleteInput); deleteOutput = new DeleteAction().execute(deleteInput);
assertEquals(0, deleteOutput.getDeletedRecordCount()); assertEquals(0, deleteOutput.getDeletedRecordCount());
assertEquals(1, deleteOutput.getRecordsWithErrors().size()); assertEquals(1, deleteOutput.getRecordsWithErrors().size());
assertEquals("No record was found to delete for Id = 1", deleteOutput.getRecordsWithErrors().get(0).getErrors().get(0)); assertEquals("No record was found to delete for Id = 1", deleteOutput.getRecordsWithErrors().get(0).getErrors().get(0).getMessage());
deleteInput.setTableName(TestUtils.TABLE_NAME_ORDER_EXTRINSIC); deleteInput.setTableName(TestUtils.TABLE_NAME_ORDER_EXTRINSIC);
deleteInput.setPrimaryKeys(List.of(1)); deleteInput.setPrimaryKeys(List.of(1));
deleteOutput = new DeleteAction().execute(deleteInput); deleteOutput = new DeleteAction().execute(deleteInput);
assertEquals(0, deleteOutput.getDeletedRecordCount()); assertEquals(0, deleteOutput.getDeletedRecordCount());
assertEquals(1, deleteOutput.getRecordsWithErrors().size()); assertEquals(1, deleteOutput.getRecordsWithErrors().size());
assertEquals("No record was found to delete for Id = 1", deleteOutput.getRecordsWithErrors().get(0).getErrors().get(0)); assertEquals("No record was found to delete for Id = 1", deleteOutput.getRecordsWithErrors().get(0).getErrors().get(0).getMessage());
} }

View File

@ -113,7 +113,7 @@ class InsertActionTest extends BaseTest
assertEquals(1, TestUtils.queryTable(qInstance, TestUtils.TABLE_NAME_PERSON_MEMORY).size()); assertEquals(1, TestUtils.queryTable(qInstance, TestUtils.TABLE_NAME_PERSON_MEMORY).size());
assertNull(insertOutput.getRecords().get(0).getValueInteger("id")); assertNull(insertOutput.getRecords().get(0).getValueInteger("id"));
assertEquals(1, insertOutput.getRecords().get(0).getErrors().size()); assertEquals(1, insertOutput.getRecords().get(0).getErrors().size());
assertThat(insertOutput.getRecords().get(0).getErrors().get(0)).contains("Another record already exists with this First Name and Last Name"); assertThat(insertOutput.getRecords().get(0).getErrors().get(0).getMessage()).contains("Another record already exists with this First Name and Last Name");
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// try to insert that person again, with 2 others - the 2 should work, but the one fail // // try to insert that person again, with 2 others - the 2 should work, but the one fail //
@ -156,7 +156,7 @@ class InsertActionTest extends BaseTest
assertEquals(1, insertOutput.getRecords().get(0).getValueInteger("id")); assertEquals(1, insertOutput.getRecords().get(0).getValueInteger("id"));
assertNull(insertOutput.getRecords().get(1).getValueInteger("id")); assertNull(insertOutput.getRecords().get(1).getValueInteger("id"));
assertEquals(1, insertOutput.getRecords().get(1).getErrors().size()); assertEquals(1, insertOutput.getRecords().get(1).getErrors().size());
assertThat(insertOutput.getRecords().get(1).getErrors().get(0)).contains("Another record already exists with this First Name and Last Name"); assertThat(insertOutput.getRecords().get(1).getErrors().get(0).getMessage()).contains("Another record already exists with this First Name and Last Name");
} }
@ -183,7 +183,7 @@ class InsertActionTest extends BaseTest
assertEquals(1, insertOutput.getRecords().get(0).getValueInteger("id")); assertEquals(1, insertOutput.getRecords().get(0).getValueInteger("id"));
assertNull(insertOutput.getRecords().get(1).getValueInteger("id")); assertNull(insertOutput.getRecords().get(1).getValueInteger("id"));
assertEquals(1, insertOutput.getRecords().get(1).getErrors().size()); assertEquals(1, insertOutput.getRecords().get(1).getErrors().size());
assertThat(insertOutput.getRecords().get(1).getErrors().get(0)).contains("Another record already exists with this Name"); assertThat(insertOutput.getRecords().get(1).getErrors().get(0).getMessage()).contains("Another record already exists with this Name");
} }
@ -303,7 +303,7 @@ class InsertActionTest extends BaseTest
insertInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC); insertInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC);
insertInput.setRecords(List.of(new QRecord().withValue("lineItemId", null).withValue("key", "kidsCanCallYou").withValue("value", "HoJu"))); insertInput.setRecords(List.of(new QRecord().withValue("lineItemId", null).withValue("key", "kidsCanCallYou").withValue("value", "HoJu")));
InsertOutput insertOutput = new InsertAction().execute(insertInput); InsertOutput insertOutput = new InsertAction().execute(insertInput);
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0).getMessage());
} }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -314,7 +314,7 @@ class InsertActionTest extends BaseTest
insertInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC); insertInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC);
insertInput.setRecords(List.of(new QRecord().withValue("lineItemId", 1701).withValue("key", "kidsCanCallYou").withValue("value", "HoJu"))); insertInput.setRecords(List.of(new QRecord().withValue("lineItemId", 1701).withValue("key", "kidsCanCallYou").withValue("value", "HoJu")));
InsertOutput insertOutput = new InsertAction().execute(insertInput); InsertOutput insertOutput = new InsertAction().execute(insertInput);
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0).getMessage());
} }
{ {
@ -341,7 +341,7 @@ class InsertActionTest extends BaseTest
insertLineItemExtrinsicInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC); insertLineItemExtrinsicInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC);
insertLineItemExtrinsicInput.setRecords(List.of(new QRecord().withValue("lineItemId", 4200).withValue("key", "kidsCanCallYou").withValue("value", "HoJu"))); insertLineItemExtrinsicInput.setRecords(List.of(new QRecord().withValue("lineItemId", 4200).withValue("key", "kidsCanCallYou").withValue("value", "HoJu")));
InsertOutput insertLineItemExtrinsicOutput = new InsertAction().execute(insertLineItemExtrinsicInput); InsertOutput insertLineItemExtrinsicOutput = new InsertAction().execute(insertLineItemExtrinsicInput);
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertLineItemExtrinsicOutput.getRecords().get(0).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertLineItemExtrinsicOutput.getRecords().get(0).getErrors().get(0).getMessage());
} }
{ {
@ -371,9 +371,9 @@ class InsertActionTest extends BaseTest
new QRecord().withValue("lineItemId", 4700).withValue("key", "theKidsCanCallYou").withValue("value", "HoJu") new QRecord().withValue("lineItemId", 4700).withValue("key", "theKidsCanCallYou").withValue("value", "HoJu")
)); ));
InsertOutput insertOutput = new InsertAction().execute(insertInput); InsertOutput insertOutput = new InsertAction().execute(insertInput);
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0).getMessage());
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(1).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(1).getErrors().get(0).getMessage());
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(2).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(2).getErrors().get(0).getMessage());
assertEquals(0, insertOutput.getRecords().get(3).getErrors().size()); assertEquals(0, insertOutput.getRecords().get(3).getErrors().size());
assertNotNull(insertOutput.getRecords().get(3).getValueInteger("id")); assertNotNull(insertOutput.getRecords().get(3).getValueInteger("id"));
} }
@ -395,14 +395,14 @@ class InsertActionTest extends BaseTest
new QRecord().withValue("lineItemId", 4700).withValue("key", "theKidsCanCallYou").withValue("value", "HoJu") new QRecord().withValue("lineItemId", 4700).withValue("key", "theKidsCanCallYou").withValue("value", "HoJu")
)); ));
InsertOutput insertOutput = new InsertAction().execute(insertInput); InsertOutput insertOutput = new InsertAction().execute(insertInput);
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0).getMessage());
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(1).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(1).getErrors().get(0).getMessage());
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(2).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(2).getErrors().get(0).getMessage());
assertEquals(0, insertOutput.getRecords().get(3).getErrors().size()); assertEquals(0, insertOutput.getRecords().get(3).getErrors().size());
assertNotNull(insertOutput.getRecords().get(3).getValueInteger("id")); assertNotNull(insertOutput.getRecords().get(3).getValueInteger("id"));
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(4).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(4).getErrors().get(0).getMessage());
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(5).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(5).getErrors().get(0).getMessage());
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(6).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(6).getErrors().get(0).getMessage());
assertEquals(0, insertOutput.getRecords().get(7).getErrors().size()); assertEquals(0, insertOutput.getRecords().get(7).getErrors().size());
assertNotNull(insertOutput.getRecords().get(7).getValueInteger("id")); assertNotNull(insertOutput.getRecords().get(7).getValueInteger("id"));
} }
@ -426,7 +426,7 @@ class InsertActionTest extends BaseTest
insertInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM); insertInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM);
insertInput.setRecords(List.of(new QRecord().withValue("orderId", null).withValue("sku", "BASIC1").withValue("quantity", 1))); insertInput.setRecords(List.of(new QRecord().withValue("orderId", null).withValue("sku", "BASIC1").withValue("quantity", 1)));
InsertOutput insertOutput = new InsertAction().execute(insertInput); InsertOutput insertOutput = new InsertAction().execute(insertInput);
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0).getMessage());
} }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -437,7 +437,7 @@ class InsertActionTest extends BaseTest
insertInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM); insertInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM);
insertInput.setRecords(List.of(new QRecord().withValue("orderId", 1701).withValue("sku", "BASIC1").withValue("quantity", 1))); insertInput.setRecords(List.of(new QRecord().withValue("orderId", 1701).withValue("sku", "BASIC1").withValue("quantity", 1)));
InsertOutput insertOutput = new InsertAction().execute(insertInput); InsertOutput insertOutput = new InsertAction().execute(insertInput);
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0).getMessage());
} }
{ {
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -457,7 +457,7 @@ class InsertActionTest extends BaseTest
insertLineItemInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM); insertLineItemInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM);
insertLineItemInput.setRecords(List.of(new QRecord().withValue("orderId", 42).withValue("sku", "BASIC1").withValue("quantity", 1))); insertLineItemInput.setRecords(List.of(new QRecord().withValue("orderId", 42).withValue("sku", "BASIC1").withValue("quantity", 1)));
InsertOutput insertLineItemOutput = new InsertAction().execute(insertLineItemInput); InsertOutput insertLineItemOutput = new InsertAction().execute(insertLineItemInput);
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertLineItemOutput.getRecords().get(0).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertLineItemOutput.getRecords().get(0).getErrors().get(0).getMessage());
} }
{ {
@ -480,9 +480,9 @@ class InsertActionTest extends BaseTest
new QRecord().withValue("orderId", 47).withValue("sku", "BASIC1").withValue("quantity", 1) new QRecord().withValue("orderId", 47).withValue("sku", "BASIC1").withValue("quantity", 1)
)); ));
InsertOutput insertOutput = new InsertAction().execute(insertInput); InsertOutput insertOutput = new InsertAction().execute(insertInput);
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0).getMessage());
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(1).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(1).getErrors().get(0).getMessage());
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(2).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(2).getErrors().get(0).getMessage());
assertEquals(0, insertOutput.getRecords().get(3).getErrors().size()); assertEquals(0, insertOutput.getRecords().get(3).getErrors().size());
assertNotNull(insertOutput.getRecords().get(3).getValueInteger("id")); assertNotNull(insertOutput.getRecords().get(3).getValueInteger("id"));
} }
@ -504,14 +504,14 @@ class InsertActionTest extends BaseTest
new QRecord().withValue("orderId", 47).withValue("sku", "BASIC1").withValue("quantity", 1) new QRecord().withValue("orderId", 47).withValue("sku", "BASIC1").withValue("quantity", 1)
)); ));
InsertOutput insertOutput = new InsertAction().execute(insertInput); InsertOutput insertOutput = new InsertAction().execute(insertInput);
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(0).getErrors().get(0).getMessage());
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(1).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(1).getErrors().get(0).getMessage());
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(2).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(2).getErrors().get(0).getMessage());
assertEquals(0, insertOutput.getRecords().get(3).getErrors().size()); assertEquals(0, insertOutput.getRecords().get(3).getErrors().size());
assertNotNull(insertOutput.getRecords().get(3).getValueInteger("id")); assertNotNull(insertOutput.getRecords().get(3).getValueInteger("id"));
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(4).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(4).getErrors().get(0).getMessage());
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(5).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(5).getErrors().get(0).getMessage());
assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(6).getErrors().get(0)); assertEquals("You do not have permission to insert this record - the referenced Order was not found.", insertOutput.getRecords().get(6).getErrors().get(0).getMessage());
assertEquals(0, insertOutput.getRecords().get(7).getErrors().size()); assertEquals(0, insertOutput.getRecords().get(7).getErrors().size());
assertNotNull(insertOutput.getRecords().get(7).getValueInteger("id")); assertNotNull(insertOutput.getRecords().get(7).getValueInteger("id"));
} }
@ -531,7 +531,7 @@ class InsertActionTest extends BaseTest
insertInput.setTableName(TestUtils.TABLE_NAME_ORDER); insertInput.setTableName(TestUtils.TABLE_NAME_ORDER);
insertInput.setRecords(List.of(new QRecord().withValue("storeId", 2))); insertInput.setRecords(List.of(new QRecord().withValue("storeId", 2)));
InsertOutput insertOutput = new InsertAction().execute(insertInput); InsertOutput insertOutput = new InsertAction().execute(insertInput);
assertEquals("You do not have permission to insert a record with a value of 2 in the field: Store Id", insertOutput.getRecords().get(0).getErrors().get(0)); assertEquals("You do not have permission to insert a record with a value of 2 in the field: Store Id", insertOutput.getRecords().get(0).getErrors().get(0).getMessage());
assertEquals(0, TestUtils.queryTable(qInstance, TestUtils.TABLE_NAME_ORDER).size()); assertEquals(0, TestUtils.queryTable(qInstance, TestUtils.TABLE_NAME_ORDER).size());
} }
@ -549,7 +549,7 @@ class InsertActionTest extends BaseTest
insertInput.setTableName(TestUtils.TABLE_NAME_ORDER); insertInput.setTableName(TestUtils.TABLE_NAME_ORDER);
insertInput.setRecords(List.of(new QRecord())); insertInput.setRecords(List.of(new QRecord()));
InsertOutput insertOutput = new InsertAction().execute(insertInput); InsertOutput insertOutput = new InsertAction().execute(insertInput);
assertEquals("You do not have permission to insert a record without a value in the field: Store Id", insertOutput.getRecords().get(0).getErrors().get(0)); assertEquals("You do not have permission to insert a record without a value in the field: Store Id", insertOutput.getRecords().get(0).getErrors().get(0).getMessage());
assertEquals(0, TestUtils.queryTable(qInstance, TestUtils.TABLE_NAME_ORDER).size()); assertEquals(0, TestUtils.queryTable(qInstance, TestUtils.TABLE_NAME_ORDER).size());
} }
@ -617,7 +617,7 @@ class InsertActionTest extends BaseTest
// 1st record had no value in orderNo - assert it errored // // 1st record had no value in orderNo - assert it errored //
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
assertEquals(1, insertOutput.getRecords().get(0).getErrors().size()); assertEquals(1, insertOutput.getRecords().get(0).getErrors().size());
assertEquals("Missing value in required field: Order No", insertOutput.getRecords().get(0).getErrors().get(0)); assertEquals("Missing value in required field: Order No", insertOutput.getRecords().get(0).getErrors().get(0).getMessage());
/////////////////////////////////////////////// ///////////////////////////////////////////////
// 2nd record had a value - it should insert // // 2nd record had a value - it should insert //
@ -629,7 +629,7 @@ class InsertActionTest extends BaseTest
// 3rd record had spaces-only in orderNo - make sure that fails // // 3rd record had spaces-only in orderNo - make sure that fails //
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
assertEquals(1, insertOutput.getRecords().get(2).getErrors().size()); assertEquals(1, insertOutput.getRecords().get(2).getErrors().size());
assertEquals("Missing value in required field: Order No", insertOutput.getRecords().get(2).getErrors().get(0)); assertEquals("Missing value in required field: Order No", insertOutput.getRecords().get(2).getErrors().get(0).getMessage());
} }
} }

View File

@ -376,7 +376,7 @@ class UpdateActionTest extends BaseTest
// 1st record tried to set a null orderNo - assert it errored // // 1st record tried to set a null orderNo - assert it errored //
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
assertEquals(1, updateOutput.getRecords().get(0).getErrors().size()); assertEquals(1, updateOutput.getRecords().get(0).getErrors().size());
assertEquals("Missing value in required field: Order No", updateOutput.getRecords().get(0).getErrors().get(0)); assertEquals("Missing value in required field: Order No", updateOutput.getRecords().get(0).getErrors().get(0).getMessage());
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// 2nd record didn't try to change orderNo, so should be fine // // 2nd record didn't try to change orderNo, so should be fine //
@ -392,7 +392,7 @@ class UpdateActionTest extends BaseTest
// 4th record tried to set orderNo to all spaces - assert it errored // // 4th record tried to set orderNo to all spaces - assert it errored //
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
assertEquals(1, updateOutput.getRecords().get(3).getErrors().size()); assertEquals(1, updateOutput.getRecords().get(3).getErrors().size());
assertEquals("Missing value in required field: Order No", updateOutput.getRecords().get(3).getErrors().get(0)); assertEquals("Missing value in required field: Order No", updateOutput.getRecords().get(3).getErrors().get(0).getMessage());
} }
@ -439,7 +439,7 @@ class UpdateActionTest extends BaseTest
updateInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM); updateInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM);
updateInput.setRecords(List.of(new QRecord().withValue("id", 10).withValue("orderId", null).withValue("sku", "BASIC2"))); updateInput.setRecords(List.of(new QRecord().withValue("id", 10).withValue("orderId", null).withValue("sku", "BASIC2")));
UpdateOutput updateOutput = new UpdateAction().execute(updateInput); UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
assertEquals("You do not have permission to update this record - the referenced Order was not found.", updateOutput.getRecords().get(0).getErrors().get(0)); assertEquals("You do not have permission to update this record - the referenced Order was not found.", updateOutput.getRecords().get(0).getErrors().get(0).getMessage());
} }
//////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////
@ -452,7 +452,7 @@ class UpdateActionTest extends BaseTest
updateInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM); updateInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM);
updateInput.setRecords(List.of(new QRecord().withValue("id", 20).withValue("sku", "BASIC3"))); updateInput.setRecords(List.of(new QRecord().withValue("id", 20).withValue("sku", "BASIC3")));
UpdateOutput updateOutput = new UpdateAction().execute(updateInput); UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
assertEquals("No record was found to update for Id = 20", updateOutput.getRecords().get(0).getErrors().get(0)); assertEquals("No record was found to update for Id = 20", updateOutput.getRecords().get(0).getErrors().get(0).getMessage());
} }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -464,7 +464,7 @@ class UpdateActionTest extends BaseTest
updateInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM); updateInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM);
updateInput.setRecords(List.of(new QRecord().withValue("id", 10).withValue("orderId", 2).withValue("sku", "BASIC3"))); updateInput.setRecords(List.of(new QRecord().withValue("id", 10).withValue("orderId", 2).withValue("sku", "BASIC3")));
UpdateOutput updateOutput = new UpdateAction().execute(updateInput); UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
assertEquals("You do not have permission to update this record - the referenced Order was not found.", updateOutput.getRecords().get(0).getErrors().get(0)); assertEquals("You do not have permission to update this record - the referenced Order was not found.", updateOutput.getRecords().get(0).getErrors().get(0).getMessage());
} }
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
@ -475,7 +475,7 @@ class UpdateActionTest extends BaseTest
updateInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC); updateInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC);
updateInput.setRecords(List.of(new QRecord().withValue("id", 100).withValue("lineItemId", null).withValue("key", "updatedKey"))); updateInput.setRecords(List.of(new QRecord().withValue("id", 100).withValue("lineItemId", null).withValue("key", "updatedKey")));
UpdateOutput updateOutput = new UpdateAction().execute(updateInput); UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
assertEquals("You do not have permission to update this record - the referenced Order was not found.", updateOutput.getRecords().get(0).getErrors().get(0)); assertEquals("You do not have permission to update this record - the referenced Order was not found.", updateOutput.getRecords().get(0).getErrors().get(0).getMessage());
} }
////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////
@ -488,7 +488,7 @@ class UpdateActionTest extends BaseTest
updateInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC); updateInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC);
updateInput.setRecords(List.of(new QRecord().withValue("id", 200).withValue("key", "updatedKey"))); updateInput.setRecords(List.of(new QRecord().withValue("id", 200).withValue("key", "updatedKey")));
UpdateOutput updateOutput = new UpdateAction().execute(updateInput); UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
assertEquals("No record was found to update for Id = 200", updateOutput.getRecords().get(0).getErrors().get(0)); assertEquals("No record was found to update for Id = 200", updateOutput.getRecords().get(0).getErrors().get(0).getMessage());
} }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -500,7 +500,7 @@ class UpdateActionTest extends BaseTest
updateInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC); updateInput.setTableName(TestUtils.TABLE_NAME_LINE_ITEM_EXTRINSIC);
updateInput.setRecords(List.of(new QRecord().withValue("id", 100).withValue("lineItemId", 20).withValue("key", "updatedKey"))); updateInput.setRecords(List.of(new QRecord().withValue("id", 100).withValue("lineItemId", 20).withValue("key", "updatedKey")));
UpdateOutput updateOutput = new UpdateAction().execute(updateInput); UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
assertEquals("You do not have permission to update this record - the referenced Order was not found.", updateOutput.getRecords().get(0).getErrors().get(0)); assertEquals("You do not have permission to update this record - the referenced Order was not found.", updateOutput.getRecords().get(0).getErrors().get(0).getMessage());
} }
} }
@ -518,7 +518,7 @@ class UpdateActionTest extends BaseTest
updateInput.setTableName(TestUtils.TABLE_NAME_ORDER); updateInput.setTableName(TestUtils.TABLE_NAME_ORDER);
updateInput.setRecords(List.of(new QRecord().withValue("id", 999).withValue("orderNo", "updated"))); updateInput.setRecords(List.of(new QRecord().withValue("id", 999).withValue("orderNo", "updated")));
UpdateOutput updateOutput = new UpdateAction().execute(updateInput); UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
assertEquals("No record was found to update for Id = 999", updateOutput.getRecords().get(0).getErrors().get(0)); assertEquals("No record was found to update for Id = 999", updateOutput.getRecords().get(0).getErrors().get(0).getMessage());
} }
@ -548,7 +548,7 @@ class UpdateActionTest extends BaseTest
updateInput.setTableName(TestUtils.TABLE_NAME_ORDER); updateInput.setTableName(TestUtils.TABLE_NAME_ORDER);
updateInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("orderNo", "updated"))); updateInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("orderNo", "updated")));
UpdateOutput updateOutput = new UpdateAction().execute(updateInput); UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
assertEquals("No record was found to update for Id = 1", updateOutput.getRecords().get(0).getErrors().get(0)); assertEquals("No record was found to update for Id = 1", updateOutput.getRecords().get(0).getErrors().get(0).getMessage());
QContext.getQSession().withSecurityKeyValues(MapBuilder.of(TestUtils.SECURITY_KEY_TYPE_STORE_ALL_ACCESS, ListBuilder.of(true))); QContext.getQSession().withSecurityKeyValues(MapBuilder.of(TestUtils.SECURITY_KEY_TYPE_STORE_ALL_ACCESS, ListBuilder.of(true)));
assertThat(TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER)).noneMatch(r -> r.getValueString("orderNo").equals("updated")); assertThat(TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER)).noneMatch(r -> r.getValueString("orderNo").equals("updated"));
@ -562,7 +562,7 @@ class UpdateActionTest extends BaseTest
updateInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("orderNo", "updated").withValue("storeId", 2))); updateInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("orderNo", "updated").withValue("storeId", 2)));
updateOutput = new UpdateAction().execute(updateInput); updateOutput = new UpdateAction().execute(updateInput);
assertEquals("You do not have permission to update a record with a value of 2 in the field: Store Id", updateOutput.getRecords().get(0).getErrors().get(0)); assertEquals("You do not have permission to update a record with a value of 2 in the field: Store Id", updateOutput.getRecords().get(0).getErrors().get(0).getMessage());
QContext.getQSession().withSecurityKeyValues(MapBuilder.of(TestUtils.SECURITY_KEY_TYPE_STORE_ALL_ACCESS, ListBuilder.of(true))); QContext.getQSession().withSecurityKeyValues(MapBuilder.of(TestUtils.SECURITY_KEY_TYPE_STORE_ALL_ACCESS, ListBuilder.of(true)));
assertThat(TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER)).noneMatch(r -> r.getValueString("orderNo").equals("updated")); assertThat(TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER)).noneMatch(r -> r.getValueString("orderNo").equals("updated"));
@ -593,7 +593,7 @@ class UpdateActionTest extends BaseTest
updateInput.setTableName(TestUtils.TABLE_NAME_ORDER); updateInput.setTableName(TestUtils.TABLE_NAME_ORDER);
updateInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("storeId", null))); updateInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("storeId", null)));
UpdateOutput updateOutput = new UpdateAction().execute(updateInput); UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
assertEquals("You do not have permission to update a record without a value in the field: Store Id", updateOutput.getRecords().get(0).getErrors().get(0)); assertEquals("You do not have permission to update a record without a value in the field: Store Id", updateOutput.getRecords().get(0).getErrors().get(0).getMessage());
assertEquals(0, TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER).stream().filter(r -> r.getValue("storeId") == null).count()); assertEquals(0, TestUtils.queryTable(TestUtils.TABLE_NAME_ORDER).stream().filter(r -> r.getValue("storeId") == null).count());
} }

View File

@ -55,6 +55,7 @@ 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.fields.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.session.QSession; import com.kingsrook.qqq.backend.core.model.session.QSession;
import com.kingsrook.qqq.backend.core.model.statusmessages.SystemErrorStatusMessage;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
import com.kingsrook.qqq.backend.core.utils.JsonUtils; import com.kingsrook.qqq.backend.core.utils.JsonUtils;
import com.kingsrook.qqq.backend.core.utils.SleepUtils; import com.kingsrook.qqq.backend.core.utils.SleepUtils;
@ -202,7 +203,7 @@ public class BaseAPIActionUtil
} }
catch(Exception e) catch(Exception e)
{ {
record.addError("Error: " + e.getMessage()); record.addError(new SystemErrorStatusMessage("Error: " + e.getMessage()));
insertOutput.addRecord(record); insertOutput.addRecord(record);
} }
@ -421,13 +422,13 @@ public class BaseAPIActionUtil
JSONObject errorObject = jsonObject.getJSONObject("error"); JSONObject errorObject = jsonObject.getJSONObject("error");
if(errorObject.has("message")) if(errorObject.has("message"))
{ {
record.addError("Error: " + errorObject.getString("message")); record.addError(new SystemErrorStatusMessage("Error: " + errorObject.getString("message")));
} }
} }
if(CollectionUtils.nullSafeIsEmpty(record.getErrors())) if(CollectionUtils.nullSafeIsEmpty(record.getErrors()))
{ {
record.addError("Unspecified error executing insert."); record.addError(new SystemErrorStatusMessage("Unspecified error executing insert."));
} }
} }

View File

@ -37,6 +37,7 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.query.JoinsContext;
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.data.QRecord; import com.kingsrook.qqq.backend.core.model.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.statusmessages.SystemErrorStatusMessage;
import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager; import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager;
@ -217,7 +218,7 @@ public class RDBMSDeleteAction extends AbstractRDBMSAction implements DeleteInte
catch(Exception e) catch(Exception e)
{ {
LOG.debug("Exception trying to delete [" + tableName + "][" + primaryKey + "]", e); LOG.debug("Exception trying to delete [" + tableName + "][" + primaryKey + "]", e);
deleteOutput.addRecordWithError(new QRecord(table, primaryKey).withError("Record was not deleted: " + e.getMessage())); deleteOutput.addRecordWithError(new QRecord(table, primaryKey).withError(new SystemErrorStatusMessage("Record was not deleted: " + e.getMessage())));
} }
} }

View File

@ -365,7 +365,7 @@ public class RDBMSUpdateActionTest extends RDBMSActionTest
updateInput.setRecords(records); updateInput.setRecords(records);
UpdateOutput updateOutput = new UpdateAction().execute(updateInput); UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
assertFalse(updateOutput.getRecords().get(0).getErrors().isEmpty()); assertFalse(updateOutput.getRecords().get(0).getErrors().isEmpty());
assertEquals("Missing value in primary key field", updateOutput.getRecords().get(0).getErrors().get(0)); assertEquals("Missing value in primary key field", updateOutput.getRecords().get(0).getErrors().get(0).getMessage());
} }
{ {
@ -377,7 +377,7 @@ public class RDBMSUpdateActionTest extends RDBMSActionTest
updateInput.setRecords(records); updateInput.setRecords(records);
UpdateOutput updateOutput = new UpdateAction().execute(updateInput); UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
assertFalse(updateOutput.getRecords().get(0).getErrors().isEmpty()); assertFalse(updateOutput.getRecords().get(0).getErrors().isEmpty());
assertEquals("Missing value in primary key field", updateOutput.getRecords().get(0).getErrors().get(0)); assertEquals("Missing value in primary key field", updateOutput.getRecords().get(0).getErrors().get(0).getMessage());
} }
{ {
@ -393,7 +393,7 @@ public class RDBMSUpdateActionTest extends RDBMSActionTest
UpdateOutput updateOutput = new UpdateAction().execute(updateInput); UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
assertFalse(updateOutput.getRecords().get(0).getErrors().isEmpty()); assertFalse(updateOutput.getRecords().get(0).getErrors().isEmpty());
assertEquals("Missing value in primary key field", updateOutput.getRecords().get(0).getErrors().get(0)); assertEquals("Missing value in primary key field", updateOutput.getRecords().get(0).getErrors().get(0).getMessage());
assertTrue(updateOutput.getRecords().get(1).getErrors().isEmpty()); assertTrue(updateOutput.getRecords().get(1).getErrors().isEmpty());

View File

@ -68,6 +68,12 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateOutput;
import com.kingsrook.qqq.backend.core.model.data.QRecord; 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.fields.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.statusmessages.BadInputStatusMessage;
import com.kingsrook.qqq.backend.core.model.statusmessages.NotFoundStatusMessage;
import com.kingsrook.qqq.backend.core.model.statusmessages.PermissionDeniedMessage;
import com.kingsrook.qqq.backend.core.model.statusmessages.QErrorMessage;
import com.kingsrook.qqq.backend.core.model.statusmessages.QStatusMessage;
import com.kingsrook.qqq.backend.core.model.statusmessages.QWarningMessage;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
import com.kingsrook.qqq.backend.core.utils.Pair; import com.kingsrook.qqq.backend.core.utils.Pair;
import com.kingsrook.qqq.backend.core.utils.StringUtils; import com.kingsrook.qqq.backend.core.utils.StringUtils;
@ -364,12 +370,12 @@ public class ApiImplementation
InsertAction insertAction = new InsertAction(); InsertAction insertAction = new InsertAction();
InsertOutput insertOutput = insertAction.execute(insertInput); InsertOutput insertOutput = insertAction.execute(insertInput);
List<String> errors = insertOutput.getRecords().get(0).getErrors(); List<QErrorMessage> errors = insertOutput.getRecords().get(0).getErrors();
if(CollectionUtils.nullSafeHasContents(errors)) if(CollectionUtils.nullSafeHasContents(errors))
{ {
boolean isBadRequest = areAnyErrorsBadRequest(errors); boolean isBadRequest = areAnyErrorsBadRequest(errors);
String message = "Error inserting " + table.getLabel() + ": " + StringUtils.joinWithCommasAndAnd(errors); String message = "Error inserting " + table.getLabel() + ": " + joinErrorsWithCommasAndAnd(errors);
if(isBadRequest) if(isBadRequest)
{ {
throw (new QBadRequestException(message)); throw (new QBadRequestException(message));
@ -383,10 +389,10 @@ public class ApiImplementation
LinkedHashMap<String, Serializable> outputRecord = new LinkedHashMap<>(); LinkedHashMap<String, Serializable> outputRecord = new LinkedHashMap<>();
outputRecord.put(table.getPrimaryKeyField(), insertOutput.getRecords().get(0).getValue(table.getPrimaryKeyField())); outputRecord.put(table.getPrimaryKeyField(), insertOutput.getRecords().get(0).getValue(table.getPrimaryKeyField()));
List<String> warnings = insertOutput.getRecords().get(0).getWarnings(); List<QWarningMessage> warnings = insertOutput.getRecords().get(0).getWarnings();
if(CollectionUtils.nullSafeHasContents(warnings)) if(CollectionUtils.nullSafeHasContents(warnings))
{ {
outputRecord.put("warning", "Warning inserting " + table.getLabel() + ", some data may have been inserted: " + StringUtils.joinWithCommasAndAnd(warnings)); outputRecord.put("warning", "Warning inserting " + table.getLabel() + ", some data may have been inserted: " + joinErrorsWithCommasAndAnd(warnings));
} }
return (outputRecord); return (outputRecord);
@ -463,19 +469,19 @@ public class ApiImplementation
LinkedHashMap<String, Serializable> outputRecord = new LinkedHashMap<>(); LinkedHashMap<String, Serializable> outputRecord = new LinkedHashMap<>();
response.add(outputRecord); response.add(outputRecord);
List<String> errors = record.getErrors(); List<QErrorMessage> errors = record.getErrors();
List<String> warnings = record.getWarnings(); List<QWarningMessage> warnings = record.getWarnings();
if(CollectionUtils.nullSafeHasContents(errors)) if(CollectionUtils.nullSafeHasContents(errors))
{ {
outputRecord.put("statusCode", HttpStatus.Code.BAD_REQUEST.getCode()); outputRecord.put("statusCode", HttpStatus.Code.BAD_REQUEST.getCode());
outputRecord.put("statusText", HttpStatus.Code.BAD_REQUEST.getMessage()); outputRecord.put("statusText", HttpStatus.Code.BAD_REQUEST.getMessage());
outputRecord.put("error", "Error inserting " + table.getLabel() + ": " + StringUtils.joinWithCommasAndAnd(errors)); outputRecord.put("error", "Error inserting " + table.getLabel() + ": " + joinErrorsWithCommasAndAnd(errors));
} }
else if(CollectionUtils.nullSafeHasContents(warnings)) else if(CollectionUtils.nullSafeHasContents(warnings))
{ {
outputRecord.put("statusCode", HttpStatus.Code.CREATED.getCode()); outputRecord.put("statusCode", HttpStatus.Code.CREATED.getCode());
outputRecord.put("statusText", HttpStatus.Code.CREATED.getMessage()); outputRecord.put("statusText", HttpStatus.Code.CREATED.getMessage());
outputRecord.put("warning", "Warning inserting " + table.getLabel() + ", some data may have been inserted: " + StringUtils.joinWithCommasAndAnd(warnings)); outputRecord.put("warning", "Warning inserting " + table.getLabel() + ", some data may have been inserted: " + joinErrorsWithCommasAndAnd(warnings));
outputRecord.put(table.getPrimaryKeyField(), record.getValue(table.getPrimaryKeyField())); outputRecord.put(table.getPrimaryKeyField(), record.getValue(table.getPrimaryKeyField()));
} }
else else
@ -570,7 +576,7 @@ public class ApiImplementation
UpdateAction updateAction = new UpdateAction(); UpdateAction updateAction = new UpdateAction();
UpdateOutput updateOutput = updateAction.execute(updateInput); UpdateOutput updateOutput = updateAction.execute(updateInput);
List<String> errors = updateOutput.getRecords().get(0).getErrors(); List<QErrorMessage> errors = updateOutput.getRecords().get(0).getErrors();
if(CollectionUtils.nullSafeHasContents(errors)) if(CollectionUtils.nullSafeHasContents(errors))
{ {
if(areAnyErrorsNotFound(errors)) if(areAnyErrorsNotFound(errors))
@ -581,7 +587,7 @@ public class ApiImplementation
{ {
boolean isBadRequest = areAnyErrorsBadRequest(errors); boolean isBadRequest = areAnyErrorsBadRequest(errors);
String message = "Error updating " + table.getLabel() + ": " + StringUtils.joinWithCommasAndAnd(errors); String message = "Error updating " + table.getLabel() + ": " + joinErrorsWithCommasAndAnd(errors);
if(isBadRequest) if(isBadRequest)
{ {
throw (new QBadRequestException(message)); throw (new QBadRequestException(message));
@ -679,10 +685,10 @@ public class ApiImplementation
////////// //////////
} }
List<String> errors = record.getErrors(); List<QErrorMessage> errors = record.getErrors();
if(CollectionUtils.nullSafeHasContents(errors)) if(CollectionUtils.nullSafeHasContents(errors))
{ {
outputRecord.put("error", "Error updating " + table.getLabel() + ": " + StringUtils.joinWithCommasAndAnd(errors)); outputRecord.put("error", "Error updating " + table.getLabel() + ": " + joinErrorsWithCommasAndAnd(errors));
if(areAnyErrorsNotFound(errors)) if(areAnyErrorsNotFound(errors))
{ {
outputRecord.put("statusCode", HttpStatus.Code.NOT_FOUND.getCode()); outputRecord.put("statusCode", HttpStatus.Code.NOT_FOUND.getCode());
@ -729,13 +735,14 @@ public class ApiImplementation
DeleteOutput deleteOutput = deleteAction.execute(deleteInput); DeleteOutput deleteOutput = deleteAction.execute(deleteInput);
if(CollectionUtils.nullSafeHasContents(deleteOutput.getRecordsWithErrors())) if(CollectionUtils.nullSafeHasContents(deleteOutput.getRecordsWithErrors()))
{ {
if(areAnyErrorsNotFound(deleteOutput.getRecordsWithErrors().get(0).getErrors())) List<QErrorMessage> errors = deleteOutput.getRecordsWithErrors().get(0).getErrors();
if(areAnyErrorsNotFound(errors))
{ {
throw (new QNotFoundException("Could not find " + table.getLabel() + " with " + table.getFields().get(table.getPrimaryKeyField()).getLabel() + " of " + primaryKey)); throw (new QNotFoundException("Could not find " + table.getLabel() + " with " + table.getFields().get(table.getPrimaryKeyField()).getLabel() + " of " + primaryKey));
} }
else else
{ {
throw (new QException("Error deleting " + table.getLabel() + ": " + StringUtils.joinWithCommasAndAnd(deleteOutput.getRecordsWithErrors().get(0).getErrors()))); throw (new QException("Error deleting " + table.getLabel() + ": " + joinErrorsWithCommasAndAnd(errors)));
} }
} }
} }
@ -811,8 +818,8 @@ public class ApiImplementation
/////////////////////////////////////// ///////////////////////////////////////
List<Map<String, Serializable>> response = new ArrayList<>(); List<Map<String, Serializable>> response = new ArrayList<>();
List<QRecord> recordsWithErrors = deleteOutput.getRecordsWithErrors(); List<QRecord> recordsWithErrors = deleteOutput.getRecordsWithErrors();
Map<String, List<String>> primaryKeyToErrorsMap = new HashMap<>(); Map<String, List<QErrorMessage>> primaryKeyToErrorsMap = new HashMap<>();
for(QRecord recordWithError : CollectionUtils.nonNullList(recordsWithErrors)) for(QRecord recordWithError : CollectionUtils.nonNullList(recordsWithErrors))
{ {
String primaryKey = recordWithError.getValueString(table.getPrimaryKeyField()); String primaryKey = recordWithError.getValueString(table.getPrimaryKeyField());
@ -825,11 +832,11 @@ public class ApiImplementation
response.add(outputRecord); response.add(outputRecord);
outputRecord.put(table.getPrimaryKeyField(), primaryKey); outputRecord.put(table.getPrimaryKeyField(), primaryKey);
String primaryKeyString = ValueUtils.getValueAsString(primaryKey); String primaryKeyString = ValueUtils.getValueAsString(primaryKey);
List<String> errors = primaryKeyToErrorsMap.get(primaryKeyString); List<QErrorMessage> errors = primaryKeyToErrorsMap.get(primaryKeyString);
if(CollectionUtils.nullSafeHasContents(errors)) if(CollectionUtils.nullSafeHasContents(errors))
{ {
outputRecord.put("error", "Error deleting " + table.getLabel() + ": " + StringUtils.joinWithCommasAndAnd(errors)); outputRecord.put("error", "Error deleting " + table.getLabel() + ": " + joinErrorsWithCommasAndAnd(errors));
if(areAnyErrorsNotFound(errors)) if(areAnyErrorsNotFound(errors))
{ {
outputRecord.put("statusCode", HttpStatus.Code.NOT_FOUND.getCode()); outputRecord.put("statusCode", HttpStatus.Code.NOT_FOUND.getCode());
@ -853,6 +860,16 @@ public class ApiImplementation
/*******************************************************************************
**
*******************************************************************************/
private static String joinErrorsWithCommasAndAnd(List<? extends QStatusMessage> errors)
{
return StringUtils.joinWithCommasAndAnd(errors.stream().map(QStatusMessage::getMessage).toList());
}
/******************************************************************************* /*******************************************************************************
** **
*******************************************************************************/ *******************************************************************************/
@ -1109,13 +1126,9 @@ public class ApiImplementation
/******************************************************************************* /*******************************************************************************
** **
*******************************************************************************/ *******************************************************************************/
private static boolean areAnyErrorsBadRequest(List<String> errors) private static boolean areAnyErrorsBadRequest(List<QErrorMessage> errors)
{ {
boolean isBadRequest = errors.stream().anyMatch(e -> return errors.stream().anyMatch(e -> (e instanceof BadInputStatusMessage) || (e instanceof PermissionDeniedMessage));
e.contains("Missing value in required field")
|| e.contains("You do not have permission")
);
return isBadRequest;
} }
@ -1123,9 +1136,9 @@ public class ApiImplementation
/******************************************************************************* /*******************************************************************************
** **
*******************************************************************************/ *******************************************************************************/
private static boolean areAnyErrorsNotFound(List<String> errors) private static boolean areAnyErrorsNotFound(List<QErrorMessage> errors)
{ {
return errors.stream().anyMatch(e -> e.startsWith(UpdateAction.NOT_FOUND_ERROR_PREFIX) || e.startsWith(DeleteAction.NOT_FOUND_ERROR_PREFIX)); return errors.stream().anyMatch(e -> (e instanceof NotFoundStatusMessage));
} }
} }

View File

@ -52,6 +52,8 @@ import com.kingsrook.qqq.backend.core.model.metadata.joins.QJoinMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.tables.Association; import com.kingsrook.qqq.backend.core.model.metadata.tables.Association;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.tables.UniqueKey; import com.kingsrook.qqq.backend.core.model.metadata.tables.UniqueKey;
import com.kingsrook.qqq.backend.core.model.statusmessages.BadInputStatusMessage;
import com.kingsrook.qqq.backend.core.model.statusmessages.QWarningMessage;
import com.kingsrook.qqq.backend.core.modules.backend.implementations.memory.MemoryBackendModule; import com.kingsrook.qqq.backend.core.modules.backend.implementations.memory.MemoryBackendModule;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
@ -156,7 +158,7 @@ public class TestUtils
{ {
if(!record.getValueString("firstName").matches(".*[a-z].*")) if(!record.getValueString("firstName").matches(".*[a-z].*"))
{ {
record.addWarning("First name does not contain any letters..."); record.addWarning(new QWarningMessage("First name does not contain any letters..."));
} }
} }
@ -238,6 +240,7 @@ public class TestUtils
{ {
return new QTableMetaData() return new QTableMetaData()
.withName(TABLE_NAME_ORDER) .withName(TABLE_NAME_ORDER)
.withCustomizer(TableCustomizers.PRE_INSERT_RECORD.getRole(), new QCodeReference(OrderPreInsertCustomizer.class))
.withBackendName(MEMORY_BACKEND_NAME) .withBackendName(MEMORY_BACKEND_NAME)
.withMiddlewareMetaData(new ApiTableMetaDataContainer().withApiTableMetaData(TestUtils.API_NAME, new ApiTableMetaData().withInitialVersion(V2022_Q4))) .withMiddlewareMetaData(new ApiTableMetaDataContainer().withApiTableMetaData(TestUtils.API_NAME, new ApiTableMetaData().withInitialVersion(V2022_Q4)))
.withPrimaryKeyField("id") .withPrimaryKeyField("id")
@ -398,4 +401,37 @@ public class TestUtils
insertPersonRecord(4, "Lisa", "Simpson"); insertPersonRecord(4, "Lisa", "Simpson");
insertPersonRecord(5, "Maggie", "Simpson"); insertPersonRecord(5, "Maggie", "Simpson");
} }
/*******************************************************************************
**
*******************************************************************************/
public static class OrderPreInsertCustomizer extends AbstractPreInsertCustomizer
{
/*******************************************************************************
**
*******************************************************************************/
@Override
public List<QRecord> apply(List<QRecord> records) throws QException
{
for(QRecord record : records)
{
for(QRecord orderLine : CollectionUtils.nonNullList(record.getAssociatedRecords().get("orderLines")))
{
if(orderLine.getValueInteger("quantity") != null && orderLine.getValueInteger("quantity") <= 0)
{
record.addError(new BadInputStatusMessage("Quantity may not be less than 0. See SKU " + orderLine.getValueString("sku")));
}
}
if("throw".equals(record.getValueString("orderNo")))
{
throw (new QException("Throwing error, as requested..."));
}
}
return (records);
}
}
} }

View File

@ -684,6 +684,35 @@ class QJavalinApiHandlerTest extends BaseTest
/*******************************************************************************
**
*******************************************************************************/
@Test
void testInsertErrorsFromCustomizer() throws QException
{
HttpResponse<String> response = Unirest.post(BASE_URL + "/api/" + VERSION + "/order/")
.body("""
{"orderNo": "ORD123", "storeId": 47, "orderLines":
[
{"lineNumber": 1, "sku": "BASIC1", "quantity": 0},
]
}
""")
.asString();
System.out.println(response.getBody());
assertErrorResponse(HttpStatus.BAD_REQUEST_400, "Quantity may not be less than 0", response);
response = Unirest.post(BASE_URL + "/api/" + VERSION + "/order/")
.body("""
{"orderNo": "throw", "storeId": 47}
""")
.asString();
System.out.println(response.getBody());
assertErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR_500, "Throwing error, as requested", response);
}
/******************************************************************************* /*******************************************************************************
** **
*******************************************************************************/ *******************************************************************************/