The proposed solution works well with automated processes that run under the profile name Automated Process
but doesn't work with Apex code that runs under the same profile name of the user that launched it.
A complete solution to my problem would be to create a dummy checkbox field (e.g. Status_Change_Enabled__c
). Then use the following validation rule that takes into account both the case of automated process and Apex code.
AND(
NOT(ISNEW()),
ISCHANGED(Status),
AND(
$Profile.Name != "System Administrator",
$Profile.Name != "Automated Process",
Status_Change_Enabled__c != true
)
)
In order to make it works, one way is to:
- Set the default value of the checkbox to
false
.
- At each update of
Status
field through Apex, update also the value of the checkbox to true
.
- Use a trigger with
after update
that update the value of the checkbox to false
again.
Since the trigger will be called after the validation rule, the status will be update successfully. The trigger will update only the checkbox, so there will be no problems with the validation rule. Be sure to not generate an infinite recursive loop of triggers call. A working example could be the following:
trigger CaseTrigger on Case (after update) {
if (trigger.isAfter && trigger.isUpdate) {
List<Id> case_ids = New List<Id>();
for (Case c: Trigger.New) {
if (c.Status_Change_Enabled__c) {
case_ids.add(c.Id);
}
}
List<Case> cases = [SELECT Status_Change_Enabled__c FROM Case WHERE Id IN : case_ids];
for (Case c: cases) {
c.Status_Change_Enabled__c = false;
}
update cases;
}
}
Of course, the best practice would be to put it in a trigger handler.
Anyway, this implementation doesn't completely satisfy me because it's prone to errors since one should remember to update the checkbox each time an update of the status should be made. I encourage any of you that has a better way to handle this to post an answer.