Skip to content

Instantly share code, notes, and snippets.

@vncasolns
Created February 15, 2024 06:42
Show Gist options
  • Save vncasolns/9b6b0399b92777f6fdf62f8b71b727b5 to your computer and use it in GitHub Desktop.
Save vncasolns/9b6b0399b92777f6fdf62f8b71b727b5 to your computer and use it in GitHub Desktop.
UniqueConstraintValidator
/**
* Validate unique constraints on Salesforce objects. It accepts a list of records and checks if there are
* any duplicate records based on the fields specified in the constructor.
* The SObjectType represents the type of Salesforce object that the class will work with, and the list of
* fields represents the fields that should be unique.
*/
public with sharing class UniqueConstraintValidator {
private SObjectType objectAPIName;
private List<String> fields;
private Map<String, SObjectField> sObjectFieldMap;
public UniqueConstraintValidator(String sObjectName, List<String> fields) {
this.objectAPIName = Schema.getGlobalDescribe().get(sObjectName);
this.fields = fields;
this.sObjectFieldMap = objectAPIName.getDescribe().fields.getMap();
}
public void validateUniqueConstraint(List<SObject> records) {
Map<String, Set<String>> fieldValuesMap = new Map<String, Set<String>>();
List<String> fieldLabels = new List<String>();
for (String field : fields) {
fieldValuesMap.put(field, new Set<String>());
fieldLabels.add(sObjectFieldMap.get(field).getDescribe().getLabel());
}
Map<String, SObject> constraintMap = new Map<String, SObject>();
List<SObject> recordsWithDuplicateCombinations = new List<SObject>();
for (SObject record : records) {
String combination = getCombinationString(record);
if (constraintMap.containsKey(combination)) {
recordsWithDuplicateCombinations.add(record);
} else {
for (String field : fields) {
fieldValuesMap.get(field).add(String.valueOf(record.get(field)));
}
constraintMap.put(combination, record);
}
}
List<SObject> existingRecords = executeQuery(fieldValuesMap);
for (SObject existingRecord : existingRecords) {
String combination = getCombinationString(existingRecord);
if (constraintMap.containsKey(combination)) {
recordsWithDuplicateCombinations.add(constraintMap.get(combination));
}
}
for (SObject record : recordsWithDuplicateCombinations) {
record.addError(
String.format(
'Duplicate record detected with the same constraint of fields: {0}.',
new List<String>{ String.join(fieldLabels, ', ') }
)
);
}
}
private String getCombinationString(SObject record) {
String combination = '';
for (String field : fields) {
String fieldValue = String.valueOf(record.get(field));
combination += fieldValue + '-';
}
return combination.substring(0, combination.length() - 1);
}
private List<SObject> executeQuery(Map<String, Object> fieldValuesMap) {
String query = 'SELECT Id, ' + String.join(fields, ', ') + ' FROM ' + objectAPIName + ' WHERE ';
for (String field : fields) {
query += field + ' IN :' + field + ' AND ';
}
query = query.substring(0, query.length() - 5);
Map<String, Object> queryBinds = new Map<String, Object>();
for (String field : fields) {
queryBinds.put(field, fieldValuesMap.get(field));
}
return Database.queryWithBinds(query, queryBinds, AccessLevel.USER_MODE);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment