Recalcul des champs de formule Salesforce en Apex
10 Sep 2019
Table de matières
L’édition hiver ‘20 de Salesforce inclue une nouvelle classe Apex Formule
– regardez ici un exemple de ses capacités.
Quoi de neuf
James Hou a annoncé, dans l’excellent résumé de l’édition hiver ‘20 de Salesforce sur Reddit, traduit par Windyo :
Recalcul des formules en Apex : c’est ENORME.
Cette release permet de calculer les formules, en batch, sans opération DML.
De fait, ça permet donc de laisser les champs formules gérer les calculs un peu complexes, et d’en utiliser les résultats en Apex sans sauvegarder.
Et c’est vrai !
Voyons un petit exemple :
@isTest
public class UnTest {
static testMethod void executerTest() {
ObjetParent__c parent = new ObjetParent__c(
Name = 'Un parent',
Code__c = 'ABAB'
);
INSERT parent;
ObjetEnfant__c enfant = new ObjetEnfant__c(
Name = 'Un enfant',
Code__c = 'XYXY',
Parent__c = parent.Id
);
System.assertEquals(NULL, enfant.Formule_Code_Concatene__c);
Test.startTest();
Formula.recalculateFormulas(new List<ObjetEnfant__c>{enfant});
Test.stopTest();
System.assertEquals('ABAB|XYXY', enfant.Formule_Code_Concatene__c);
}
}
Notez que l’objet dit « enfant
» n’existe pas dans la base de données.
Je ne l’ai pas encore enregistré avec une commande INSERT
.
Et quand même, après la commande Formula.recalculateFormulas()
, le valeur de son champ Formule_Code_Concatene__c
est ABAB|XYXY
.
Notez: Dans ce cas, la formule est:
Parent__r.Code__c
& "|" &
Code__c
Erreur connu
Si vous essayez dans un contexte de déclencheur BEFORE
, vous verrez peut-être une erreur System.DmlException
qui annonce UNKNOWN_EXCEPTION
et Cannot set the value of a calculated field
.
Jusqu’ici, il me paraî qu’il faut éviter d’exécuter Formula.recalculateFormulas()
avec les objets SObject
que vous désirez mettre à jour.
S’il faut lire les contenus du champ de formule Contact.Formule_1__c
pour décider s’il faut mettre à jour le champs Contact.Champs_Personnalise__c
, faîtes ainsi :
private void xyzzy(List<Contact> contacts) {
Map<Contact, Contact> contactsEtLeursCopies = new Map<Contact, Contact>();
for ( Contact c : contacts ) { contactsEtLeursCopies.put(c, c.clone()); }
Formula.recalculateFormulas(contactsEtLeursCopies.values());
for ( Contact c : contacts ) {
Contact cCopie = contactsEtLeursCopies.get(c);
if ( cCopie.Formule_1__c == 'Bonjour' ) {
c.Champs_Personnalise__c = 'le monde';
}
}
}
Je ne sais pas lequel est plus performant : une petite requête SOQL ou cet approche-ci de faire des copies des SObject
. Qu’en pensez-vous ?