Before Insert/Update/Undelete/Delete handling

As a good practice to keep best quality and code performance, before steps should be used to modify Trigger Context only. We should not modify any other records and we should not use asynchronous calls in before triggers.


Basic example of Before Insert/Update/Undelete step

The below step will set up the default Account.Rating value in case the value was not set already. Step could be registered in the Before Insert, Update and Undelete triggers to implement self-fixing functionality.

1public with sharing class SetAccountRatingStep extends forvendi.Step {
2
3
4   public SetAccountRatingStep() {
5       super(SetAccountRatingStep.class.getName());
6   }
 1public override Boolean initRecordProcessing(Object record, Object optionalOldRecord) {
 2    // populate value of Rating if none was set
 3       Account acc = (Account)record;
 4       if (String.isBlank(acc.Rating)) {
 5           acc.Rating = 'Warm';
 6       }
 7    // we return false because everything we need is finished
 8       return false;
 9   }
10}

Example of Before Delete step

The below step will block deletion of Salesforce Record. Step is enough generic to be registered on Before Delete trigger on for any Salesforce Object.

 1public with sharing class BlockRecordDeletionStep extends forvendi.Step {
 2
 3
 4    public BlockRecordDeletionStep() {
 5        super(BlockRecordDeletionStep.class.getName());
 6    }
 7 
 8    public override Boolean initRecordProcessing(Object record, Object optionalOldRecord) {
 9         SObject sfRecord = (SObject)record;
10     // block record action with addError method to trigger an exception
11         sfRecord.addError('You cannot remove ' + sfRecord.get('Name')  +
12         '  ' + sfRecord.getSObjectType() + ' record!');
13       
14         return false;
15    }
16 }

Simple as that you can provide any logic suited to your needs for before triggers.

Removing account record Removing account record


Modify Trigger Context base on the Parent record data (Store with generic Loader usage)

The below step will be class using in step which will be used in the Account trigger before update.

 1public with sharing class SetAccountHierarchyInNameStep extends forvendi.Step {
 2
 3
 4    public SetAccountHierarchyInNameStep() {
 5        super(SetAccountHierarchyInNameStep.class.getName());
 6    }
 7
 8
 9    public override Boolean initRecordProcessing(Object record, Object optionalOldRecord) {
10        // cast incoming record to account
11        // if value of Parent.Id is not equal null and is new or changed compared
12        //  to the optionalOldRecord value
13        // use default DataStore, load our parent record and pass it to another method
14        Account acc = (Account) record;
15        if (isNewOrChanged(acc, (SObject) optionalOldRecord, Account.ParentId) && acc.ParentId != null) {
16            getStore().requestToLoad(acc.ParentId);
17            return true;
18        }
19        return false;
20    }
21
22
23    public override void finishRecordProcessing(Object record, Object optionalOldRecord) {
24        // inside initRecordProcessing requetsToLoad() method stored parent account records
25        // to build hierarchy name we pull parent record from store based on incoming record ParentId
26        // and combine two names in order
27        Account acc = (Account) record;
28        Account parentAcc = (Account) getStore().getFromStore(acc.ParentId);
29        if (parentAcc != null) {
30            String[] accName = acc.Name.split('->');
31            acc.Name = parentAcc.Name + '->' + accName[accName.size() - 1];
32        }
33    }
34}

Most important methods of our class are both methods used on getStore() which returns DataStore generated by default. First we use requestToLoad and pass the value of ParentId, from the record that we want to save. Here in this example as we pass just the Id, the record associated with it will be pulled and saved within our generated Datastore and finally passed to finishRecordProcessing.

Second method which is getFromStore we use here again we Id parameter to simply pull value from DataStore associated with this key.

With this implementation after updating Parent field on any Account : Removing account record Removing account record

Now feature perform below code:

1if (parentAcc != null) {
2    String[] accName = acc.Name.split('->');
3    acc.Name = parentAcc.Name + '->' + accName[accName.size() - 1];
4}

And builds a Name of Account like this. Removing account record Removing account record