Created
August 27, 2018 23:08
-
-
Save brianmfear/cbfc5dd068bf78ba571ae56864dcc69e to your computer and use it in GitHub Desktop.
Example of mapping related records to report errors on (Apex Code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Help report errors to parent/child object on failed DML update | |
// For use in Trigger contexts only. | |
// This version is for demonstration purposes only, and should not | |
// be considered production ready without additional modifications. | |
// | |
// Example trigger: | |
// | |
// trigger updateContactPhone on Account(after update) { | |
// Id[] updates = new Id[0]; | |
// for(Account record: Trigger.new) { | |
// if(record.Phone != Trigger.oldMap.get(record.Id).Phone) { | |
// updates.add(record.Id); | |
// } | |
// } | |
// if(!updates.isEmpty()) { | |
// TriggerDmlHelper helper = new TriggerDmlHelper(List<Account>.class, List<Contact>.class); | |
// for(Contact record: [SELECT AccountId FROM Contact WHERE AccountId = :updates]) { | |
// Account triggerAccount = Trigger.newMap.get(record.AccountId); | |
// record.Phone = triggerAccount.Phone; | |
// helper.addMapping(triggerAccount, record); | |
// } | |
// helper.updateRecords('Failed to update {1}. First error was: {2}'); | |
// } | |
// } | |
public class TriggerDmlHelper { | |
// Class to normalize various database.*result types. | |
class DmlResult { | |
Id recordId; | |
Integer rowIndex; | |
Boolean success; | |
Database.Error[] errors; | |
DmlResult(Boolean success, Id recordId, Database.Error[] errors, Integer rowIndex) { | |
this.success = success; | |
this.recordId = recordId; | |
this.errors = errors; | |
this.rowIndex = rowIndex; | |
} | |
} | |
// normalizes the various database.*result types for reportErrors | |
class DmlResultList implements Iterable<DmlResult> { | |
DmlResult[] genResults; | |
DmlResultList(Database.SaveResult[] results) { | |
genResults = new DmlResult[0]; | |
for(Database.SaveResult result: results) { | |
genResults.add(new DmlResult(result.isSuccess(), result.getId(), result.getErrors(), genResults.size())); | |
} | |
} | |
DmlResultList(Database.DeleteResult[] results) { | |
genResults = new DmlResult[0]; | |
for(Database.DeleteResult result: results) { | |
genResults.add(new DmlResult(result.isSuccess(), result.getId(), result.getErrors(), genResults.size())); | |
} | |
} | |
DmlResultList(Database.UndeleteResult[] results) { | |
genResults = new DmlResult[0]; | |
for(Database.UndeleteResult result: results) { | |
genResults.add(new DmlResult(result.isSuccess(), result.getId(), result.getErrors(), genResults.size())); | |
} | |
} | |
public Iterator<DmlResult> iterator() { | |
return genResults.iterator(); | |
} | |
} | |
// 1:1 mapping of which record is trying to update another record | |
SObject[] source, dest; | |
// Recommend using concrete types like List<Account> instead of List<SObject> | |
public TriggerDmlHelper(Type sourceType, Type destType) { | |
source = (SObject[])sourceType.newInstance(); | |
dest = (SObject[])destType.newInstance(); | |
} | |
// Adds another 1:1 mapping | |
public void addMapping(SObject src, SObject dst) { | |
source.add(src); | |
dest.add(dst); | |
} | |
// DML operations | |
public void insertRecords(String msg) { | |
reportErrors(new DmlResultList(Database.insert(dest, false)), msg); | |
} | |
public void updateRecords(String msg) { | |
reportErrors(new DmlResultList(Database.update(dest, false)), msg); | |
} | |
public void deleteRecords(String msg) { | |
reportErrors(new DmlResultList(Database.delete(dest, false)), msg); | |
} | |
public void undeleteRecords(String msg) { | |
reportErrors(new DmlResultList(Database.undelete(dest, false)), msg); | |
} | |
// For each failure, add an error to the source record | |
void reportErrors(DmlResultList results, String msg) { | |
Iterator<DmlResult> iter = results.iterator(); | |
while(iter.hasNext()) { | |
DmlResult result = iter.next(); | |
if(!result.success) { | |
source[result.rowIndex].addError( | |
String.format( | |
msg, | |
new String[] { | |
source[result.rowIndex].Id, | |
dest[result.rowIndex].Id, | |
result.errors[0].getMessage() | |
} | |
) | |
); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Great example. I bookmarked it for future use.
I think the below line is missing 0 argument:
helper.updateRecords('Failed to update {1}. First error was: {2}');