0

Background

An Apex Trigger has been set up on a parent object to automatically create a child object record when the parent object record is created.

However, another Apex Trigger has been set up on the child object which prevents the creation of child object records (by displaying an error, much like a validation rule) unless:

a) The user is a System Administrator OR

b) The user meets another condition (I won't go into too much detail for the sake of brevity)

Issue

The Apex Trigger on the child object prevents the Apex Trigger on the parent object from creating a child object record.

This is not desired.

Question

Is there a way to create an exception in the child object trigger for records that are being created by the parent object trigger?

Perhaps this can be achieved detecting if the child object record is being created by Apex (as opposed to a user), or by making the parent object trigger imperonate a system administrator user when creating the record.

Any help would be much appreciated.

1

The approach we have taken is to have a Boolean (Checkbox) field on certain objects that marks it as created directly by our code - the code explicitly sets this as TRUE. Clearly this relies on not exposing that field in any of the UI layouts, for example, which is something the admins have to understand. The default value for this field indicates that the object was NOT created by our code. The child creation is disallowed if this flag is not set TRUE.

An alternative might be to push all the code creation of these objects into a trigger-based Platform Event consumer. In this case the contextual user is no longer the user that initiated the creation of the parent object, but rather is the "Automated Process" user. You can then always allow the "Automated Process" user to create these child instances. There are some downsides here -

  1. The Owner for the child won't be right (unless the child is actually a Master Detail child, where it inherits the parent owner anyway).
  2. You have to create a Platform Event type to hold the detail of the Parent the children are to be created for, instantiate it and dispatch it on the event bus from where the Parent object code would previously have created the children.
  3. You have to write the trigger-based Platform Event consumer.
  4. The children are created asynchronously when the Platform Event is consumed.
  • Thanks, this is a good suggestion. I'm trying to make a decision between your approach and IllusiveBrian's static variable approach. – M H Oct 13 at 3:03
  • We have some select cases where we also use a static boolean. As cropredy said there can be issues with this in some edge cases. One of the nice things about the field-based approach is that you can also treat the records differently after initial creation - obviously this is only relevant in certain use cases. – Phil W Oct 13 at 7:49
  • 1
    Thanks Phil, we ended up going with this approach. – M H Oct 16 at 21:44
0

If you want to detect the record creation is through trigger at parent object then do the following things and record at child will be created: - Create a checkbox field at child and mark it as default false. - Add a condition in child object trigger to bypass the restriction of record creation if the checkbox is set to true. - While creating records of child object in parent object trigger, ensure that the child object records which you are going to create must have checkbox checked. In this way you can get your child object records created through parent object trigger.

  • 1
    Um, that's what I said in my answer...? – Phil W Oct 11 at 11:34
0

You can put a static boolean on your child object's trigger handler and set it before calling insert in the parent's trigger handler. They are part of the same transaction, so static variables persist. Keep in mind that this will mean the variable is set after the parent trigger runs, you could add a line in the child trigger to unset the variable after you've checked it if this is an issue.

public class ChildTriggerHandler
{
    public static boolean skipUserValidation = false;

    public static onBeforeInsert()
    {
        if(!skipUserValidation && User.getProfileId() != ADMINPROFILE || !complicatedValidationLogic())
        {
           throw new Exception('Child cannot be created');
        }
        //optional
        skipUserValidation = false;
    }
}

public class ParentTriggerHandler
{
    public static createChildren()
    {
        Child__c child = new Child__c();
        ChildTriggerHandler.skipUserValidation = true;
        insert child;
    }
}
  • there's an edge case downside to this approach. If the DML done upon the parent is using AllOrNothing=false and some recs fail; SFDC will retry the batch (successes only) but the static variables won't be reverted and hence the expected child processing will not occur for the retried recs – cropredy Oct 11 at 17:17
  • @cropredy I'm not sure exactly how that would work, you're saying if it's not AllOrNothing it will try to insert child records again, but not run the rest of the Parent trigger? – IllusiveBrian Oct 11 at 20:05
  • not exactly - see Trigger Order of Execution Additional Considerations - second bullet. See also this post that gives an analogous use case – cropredy Oct 11 at 21:06
  • @cropredy From my understanding, assuming we have modified the triggers to insert all the children at once (or whatever logic is needed to do the fewest insert statements to insert them in a bulk trigger), if there are some failed and some successful records all the commits will be rolled back, the Parent trigger will run again with only successful records, execute ChildTriggerHandler.skipUserValidation = true; and then try to insert the child records again. However, your case probably comes up if allOrNothing is false on the child insert, I'm thinking about how to handle that. – IllusiveBrian Oct 11 at 22:04
  • This is also assuming that there aren't any roll-up summaries or other reasons that inserting a child record would call the Parent trigger again, or that the recursion has been dealt with in the Parent trigger. – IllusiveBrian Oct 11 at 22:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.