Salesforce Formula.recalculateFormulas Usage

Many Salesforce developers are not familiar with the method Formula.recalculateFormulas and possible was never needed to use it. Actually I'm developing in the Salesforce platform for years and was never needed it until recently.

The idea behind the method is that it recalculate all formula fields on the record for you without the need from you to query or changing the database.


Formula might be very complex, but to demonstrate the usage I created simple checkbox formula on account:

Consider the following code:

Account demoAcc = [	SELECT Id,Is_Account_Valid__c,Website FROM Account WHERE Website= null LIMIT 1];

//Website is empty, therefore the formula will be false
system.assertEquals(false, demoAcc.Is_Account_Valid__c); demoAcc.Website = 'www.testsite.com'; //assertion will fail, although website is now not empty. system.assertEquals(true, demoAcc.Is_Account_Valid__c);


The last assertion is failing, although the Website is populated which should change the formula to true. The formula is still false because this is the value when I query the record.

It will work if I will invoke Formula.recalculateFormulas after setting the site

Account demoAcc = [	SELECT Id,Is_Account_Valid__c,Website FROM Account WHERE Website= null LIMIT 1];

//Website is empty, therefore the formula will be false
system.assertEquals(false, demoAcc.Is_Account_Valid__c); demoAcc.Website = 'www.testsite.com'; Formula.recalculateFormulas(new List<Account>{demoAcc}); //assertion is fine as recalculateFormulas changed the formula system.assertEquals(true, demoAcc.Is_Account_Valid__c);


Important note that should take under consideration - the recalculate clear all reference fields.

Consider this code:

Account demoAcc = [	SELECT Id,Is_Account_Valid__c,Website,Owner.Name FROM Account WHERE Website= null LIMIT 1];

System.debug(demoAcc.Owner.Name);	//output: Liron Cohen

Formula.recalculateFormulas(new List<Account>{demoAcc});
System.debug(demoAcc.Owner.Name);	//output: null


The Owner.Name is null after the method invocation. This will happen for any field from reference and might be issue if you have logic based on that data.

To solve the issue, I can store the reference data and use it after the recalculate. 

For example:

Account demoAcc = [	SELECT Id,Is_Account_Valid__c,Website,Owner.Name FROM Account WHERE Website= null LIMIT 1];

User accOwner = demoAcc.Owner;

System.debug(demoAcc.Owner.Name);	//output: Liron Cohen

Formula.recalculateFormulas(new List<Account>{demoAcc});

demoAcc.Owner = accOwner;
System.debug(demoAcc.Owner.Name);	//output: Liron Cohen


Another important thing to note, is that the method actually does re-query the data, therefore it is counted as additional Soql query in the transaction limit and the records that processed are counted in the query rows limit.

If I will check the debug log from the last piece of code, I can see 2 Soql and 2 query rows. First for my query and second from the method recalculateFormulas.



No comments:

Post a Comment

Retire of Permission on Profiles

If you are working as a Salesforce admin/developer you've probably heard somewhere that Salesforce is planning to make a significant cha...